Development Process
Deployment Overviewโ
| Actions โ โ Consequences | merge/push on main branch | tag X.Y.Z (from main) |
|---|---|---|
| Artifactory | โ
snapshot deployed | โ
release deployed |
| Discord | โ
Beta-tester announcement posted to #beta-test (changelog diff since last release, pings the beta-tester role) | โ
Changelog diff posted |
| Deployed on LE Play | โ Or manually using pterodactyl panel | โ
deployed on play.lasers-enigma.eu server โ ๏ธif breaking changes, update & deploy le-play-server-utils |
| Deployed on LE Beta test server | โ
in-development plugin jar deployed & server restarted ( update-beta-server) | โ beta runs the in-development builds |
| Notify admins joining their server to update the plugin | โ
if "check_for_new_beta_versions: true" in config (default: false). lasers-enigma-commit-hash.txt updated | โ
if "check_for_new_version: true" in config (default: true) lasers-enigma-version.txt and lasers-enigma-commit-hash.txt updated |
| Download link on LE website | Lastest unstable release | Latest stable release |
| download.php script update | โ
deployed via sftp | โ |
| Publish plugin to marketplaces | โ | โ
Modrinth and Hangar published automatically โ ๏ธ SpigotMC must be updated manually (see 13. Publication on the Markets) |
โน๏ธ Independently of merge/tag, the beta test server is also rebuilt as a sanitized mirror of play whenever a server pack is generated (manual or scheduled), while keeping its in-development plugin builds. See CI/CD ยง Beta server mirror.
Branch Model and Tag Naming Conventionโ
The project uses a single main branch supporting all targeted Minecraft versions (1.19.4 โ 1.21.x).
Version and Tag Naming Conventionโ
The version in gradle.properties must ALWAYS include the -SNAPSHOT suffix:
| Context | Branch | Tag Format | Version in gradle.properties | Example |
|---|---|---|---|---|
| Development | main | X.Y.Z | X.Y.Z-SNAPSHOT | 8.27.0-SNAPSHOT |
Important notes:
- The
-SNAPSHOTsuffix is automatically removed by the CI during the build when creating a release tag - Never remove
-SNAPSHOTmanually fromgradle.properties - The CI/CD pipeline verifies that:
- Tags are created from the
mainbranch - The version in
gradle.propertiesmatches the tag name +-SNAPSHOT
- Tags are created from the
Development and deployment stepsโ
1. Find or Create an Issueโ
Before starting any work, consult the issue board ( see Issues Board) to verify if an issue corresponding to your task or bug already exists.
If no suitable issue is found, create one by detailing the problem or desired feature, including reproduction steps, impact and useful footage.
2. Create a Branchโ
Before creating your branch, run a git pull on main to fetch the latest changes, then create your branch from main.
Create your branch following the Conventional Commits naming convention (adopted 2026-05-18; older branches stay as-is): <type>/<issue_id>-<short-kebab-desc>. Examples: feat/123-component-color-command, fix/599-duplicate-title, refactor/612-cube-manager-cleanup.
Allowed types: feat (new user-facing capability), fix (user-visible bug), refactor (internal, no user effect), perf (observable optimisation), chore (deps, build config, tooling), docs, ci, build, test. Append ! to the type for a breaking change (e.g. feat/700-drop-legacy-save-format).
A clear and descriptive branch name facilitates tracking and review.
๐ก Tip: The
validate-branch-and-commit-namingskill verifies the format and blocks GitLab auto-close keywords before commit.
3. Developโ
If your development environment is not set-up yet, follow the Setup Development Environment documentation.
๐ก Tip: The
dev-issueAI prompt can guide you through the full implementation workflow: branch creation, version bump, plan validation, code generation, translation staging, build and CHANGELOG update โ all in one guided session.
Run Gradle to compile and deploy the shadow jar on your local server (the wrapper is included in the project, no need to install Gradle):
./gradlew clean build
Key Points:
- Backward Compatibility: Ensure that your changes do not negatively impact existing functionalities. This includes potential database migration.
- Internal Documentation (Javadoc): Comment your code and update Javadoc for any new functions or classes.
- Static Analysis (SonarQube): Run the IntelliJ plugin that is an analysis tool to check code quality and address any flagged issues.
4. Testโ
Analyze your changes to identify the relevant test scenarios (feature and non-regression tests). You can either test yourself or write a test plan then give it to a Skytale's Puzzle Game Designer along with a running server that runs your branch.
โน๏ธ Automated architecture tests run as part of the build (
./gradlew clean buildlocally, and on every CI pipeline): ArchUnit rules freeze each plugin's layered/feature architecture, so a layer violation fails the build. There are still no behavioural unit tests โ gameplay is validated manually. See CI/CD ยง Build & automated tests.
See the Testing documentation for more information.
5. Update the Wikiโ
If your changes affect the documentation, update the corresponding wiki pages.
โ ๏ธ Warning : Remember to update the sidebar to include new pages or sections.
There is two ways to update the Wiki:
- Use GitLab's web UI
- Use a local clone: clone the wiki into the project's gitignored "wiki" folder (see Set-up development environment) and edit it there.
cd wikigit switch maingit pull- Edit your files (don't forget to update the sidebar!).
git add .git commitgit push
6. Increment the Version in gradle.propertiesโ
Adjust the version number in the root gradle.properties file according to the type of change.
This project follows Semantic Versioning (SemVer): X.Y.Z. The segment to bump is driven by the Conventional Commits type chosen for your branch in step 2:
| Conventional type | Bump | Notes |
|---|---|---|
fix, refactor, perf (non-breaking), chore, docs, ci, build, test | Z (patch) | Backwards-compatible โ no new feature per SemVer. |
feat (non-breaking) | Y (minor) | Reset Z to 0. |
<type>! (breaking) | X (major) | Reset Y and Z to 0. Confirm with reviewers explicitly. |
For more details on SemVer, see semver.org.
๐ก Tip: The
bump-versionskill automates the increment, with a pre-flight viacheck-version-publishedโ no bump is performed if the current version isn't already tagged.
Important: The version MUST include the -SNAPSHOT suffix: use X.Y.Z-SNAPSHOT (e.g., 7.1.0-SNAPSHOT).
The -SNAPSHOT suffix is removed automatically by the CI when creating a release tag. Never remove it manually from gradle.properties.
The CI will verify the version format when you create your merge request or push directly.
7. Update the CHANGELOG.mdโ
Append your changes made, including issue numbers, bug fixes, and new features at the top of the file, just after the table of content.
Be aware that your changes will be used to post release notes on our Discord server.
โ ๏ธ Warning : Don't reformat the entire file.
๐ก Tip: The
add-changelog-entryskill picks the right subsection (## Fixes/## Features/## Technical changes) based on the Conventional type, formats the bullet, and refuses to edit a published version's entries.
8. Commit and Pushโ
Write clear and concise commit messages following Conventional Commits (adopted 2026-05-18; older commits stay frozen as-is):
- One feature = one commit (same for bugfixes).
- Commit subject:
<type>(<scope>)?!?: <description> (#<issue_id>)โ one line, โค ~72 chars when possible. The(#<issue_id>)reference at the end is mandatory. - Examples:
feat(race): add continue command for skeleton (#510)fix(area): prevent duplicate title on resize (#599)refactor(cube-manager): drop obsolete listener (#612)chore(deps): bump paper API to 1.21.11 (#620)feat(area)!: drop legacy save format (#700)โ!marks breaking.
- Scope is optional but encouraged:
area,race,component,lasers,inventory,command,db,i18n,wiki,deps, โฆ
โ ๏ธ Never use GitLab auto-close keywords in commit messages (subject or body):
Close,Closes,Closed,Closing,Fix,Fixes,Fixed,Fixing,Resolve,Resolves,Resolved,Resolving,Implement,Implements,Implemented,Implementingfollowed by#<issue>. They close the issue automatically on merge. Issues are closed manually at release time, never on merge โ see step 12. The bare(#<issue>)reference is fine โ it just renders as a link.
Push your commits to the remote repository and verify that your changes are present in your working branch.
๐ก Tip: The
validate-branch-and-commit-namingskill checks the format and blocks the forbidden auto-close keywords before commit.
๐ Deterministic enforcement: beyond that explanatory pre-check, a versioned
commit-msghook (.githooks/) enforces these invariants at commit time for everyone โ Claude and manual commits alike. It strips AI-credit trailers, validates the Conventional Commits subject +(#<issue>), and blocks the auto-close keywords. Activate it once per clone withgit config core.hooksPath .githooks(see Setup Development Environment). In a genuine emergency, bypass it withgit commit --no-verify.
9. Create the Merge Requestโ
Create a merge request from your branch to main and include a detailed description of the changes.
๐ก Tip: Before opening the MR, use the
reviewAI prompt to run a self-review. It checks branch naming, commit messages, version bump, CHANGELOG format, and architecture compliance โ and produces a structuredโ / โ ๏ธ / โreport.
What your merge request should contain:
- Title should contain
#<issue_id> - Description of what should be tested and what have been tested already.
- Any additional information that you think is relevant to understand the code.
- The build must pass. If it doesn't pass, read the pipeline's logs.
- If you did multiple commits for the same feature, check "Squash commits" checkbox.
Optional: Update other projectsโ
Other plugin may be impacted by your modifications:
If your changes creates a breaking change that needs to be handled in those projects repositories, you should:
Publish lasers-enigma in your local maven repository:โ
- Use
git statusto check that you have no uncommited or unpushed changes. - Run
./gradlew publishToMavenLocalto deploy the jar in your local maven repository.
Create a merge request in those other repositories and put a link to those merge request in this lasers enigma merge request.โ
- Clone the repositories
- In those project's build file (
build.gradle.ktsorpom.xml), update the version of the lasers enigma dependency. - Sync/Reload the project.
- Run a build to check compilation
- Fix the found issues.
- commit push and create a merge request (see those projects documentation for further details).
- Add the link to those other projects merge request in the lasers enigma merge request.
When your lasers enigma merge request will be merged / taggedโ
Update the version of lasers enigma dependency in those other projects accordingly.
10. Merge Request Review Processโ
The merge request should be reviewed by a developer other than the one who made the changes. If your merge request takes too long to be reviewed, ping a developer on our Discord server.
๐ก Tip: Once you receive review comments, the
fix-mr-commentsAI prompt can automatically fetch all GitLab MR comments and apply the requested fixes one by one, validating the build after each one.
11. Post-Merge: CI/CDโ
Once the merge request is merged, the CI/CD pipeline automatically triggers on main.
This pipeline includes:
- Compilation and building the project (NMS dependencies are resolved automatically by paperweight).
- Updating the lasers-enigma-commit-hash.txt file on the website through sftp. It will allow the plugin to notify server operators that this new beta version is available.
- Deploying the download.php script.
- Packaging and publishing the SNAPSHOT release on Skytale's artifactory.
- Deploying the plugin jar on the
beta.lasers-enigma.euMinecraft server and triggering a server restart. - Posting a beta-version announcement to the
#beta-testDiscord channel, pinging the beta-tester role with the in-progress changelog diff since the last release.
โ ๏ธ Warning : Keep an eye on the CI/CD notifications to quickly address any failures.
12. Publish a Version: Tag Creationโ
โน๏ธInformation : You must be a maintainer in order to create a tag. You can request the permission to do so on our Discord server.
๐ก Tip: The
releaseAI prompt orchestrates the whole release: it inventories the workspace clones, asks the breaking-changes question, presents a recap and โ only after your explicit validation โ executes the tags/pushes itself in the proven order, monitors the pipelines via the GitLab MCP, closes the released issues and checks the deployed servers.
Multi-repo release setโ
A release may involve up to five repos present in the workspace, each with its own publication mode:
| Repo | Publication | Release action |
|---|---|---|
lasersenigma | tag-based | tag X.Y.Z (process below) |
le-play-server-utils/ (LEPSU) | tag-based | same tag process on its own repo |
le-agent/ | main auto-deploys | verify everything is committed and pushed |
le-mcp/ | main auto-deploys | verify everything is committed and pushed |
wiki/ | published by the build-and-deploy-docs job of the lasersenigma pipeline | verify committed and pushed; see the special case below |
An absent clone is reported, never silently skipped. SME and particleanimlib are out of this checklist โ SME is only covered by the manual breaking-changes question.
Joint LE + LEPSU release (proven order): tag LE first โ wait for its publish-to-artifactory job to succeed โ in LEPSU, pin the LE dependency in pom.xml to the released LE version (the pom's own version stays -SNAPSHOT), commit update LE, push โ tag LEPSU โ push the tag โ monitor its pipeline. Never tag LEPSU before the LE artifact is published.
Wiki republication special case: the public docs are only rebuilt when the lasersenigma pipeline runs build-and-deploy-docs. If wiki/ received commits since the last pipeline that ran that job and no LE tag ships in the batch (e.g. a LEPSU-only or docs-only release), trigger a manual pipeline on lasersenigma (ref: main) with the variable DEPLOY_DOCS=true to publish the documentation.
LasersEnigma tag processโ
In order to publish a release, after the build on main is validated, create a tag corresponding to the new version. This tag officially marks the release.
Before creating the tag, ensure the version in gradle.properties matches the tag you're about to create with the -SNAPSHOT suffix:
- For tag
7.0.0frommain: version must be7.0.0-SNAPSHOT
โ ๏ธ Important: Never remove the
-SNAPSHOTsuffix manually. The CI will remove it automatically during the build.
Tag Naming Convention:
- Releases use the format
X.Y.Z(e.g.,7.0.0)
The CI/CD pipeline will verify that:
- The tag is created from the
mainbranch - The version in
gradle.propertiesequals the tag name +-SNAPSHOT - The CHANGELOG has been updated
Example for main branch:
## Ensure version in gradle.properties is 7.0.0-SNAPSHOT
git switch main
git pull
git tag 7.0.0
git push --tags
The pipeline is triggered on tag push:
- Compilation and building the project (NMS dependencies are resolved automatically by paperweight).
- Removing
-SNAPSHOTsuffix from the version. Then packaging and publishing the release on Skytale's artifactory. - Updating the lasers-enigma-version.txt and lasers-enigma-commit-hash.txt files on the website through sftp. It will allow the plugin to notify server operators that this new version is available.
- Deploying the plugin jar on
play.lasers-enigma.euMinecraft server and triggering a server restart. - Publishing the plugin to Modrinth and Hangar marketplaces.
- Publishing an official release announcement on our Discord server.
When the tag is pushed, close every released issue (the (#NNN) references of the released commits, plus any open issue labelled Status: To release), removing the Status: label on close โ a closed issue carries no Status label (see Issue management). The release workflow performs this via the GitLab MCP after showing you the list for validation. This is the only step where issues are closed โ never via GitLab auto-close keywords in commit messages or MR descriptions (which would close the issue at merge time, before the tag exists). Then check the deployed servers (the workflow runs the read-only check-server-status skill on play, and on beta / le-mcp / le-agent when they shipped) and verify the Discord changelog.
13. Publication on the Marketsโ
Modrinth and Hangar are published automatically by the CI/CD pipeline when a tag is created.
The following marketplace must be updated manually:
โ ๏ธ Warning : You may need 2FA. For this, mails sent to [email protected] should be redirected to your own email address. To edit email redirection, follow this link.
| URL | Login | Publication |
|---|---|---|
| Modrinth | bZx | Automatic |
| HangarMC | bZx | Automatic |
| SpigotMC | [email protected] | Manual |