Releases follow the pattern v{SEMVER}-{CLUB} (e.g., v1.0.0-arsenal). Codenames are drawn alphabetically from the historic club list of famous football clubs.
Branch protection prevents direct pushes to master, so all release prep goes through a PR:
git checkout master && git pull
git checkout -b release/v1.0.0-arsenalMove items from [Unreleased] to a new release section in CHANGELOG.md, then commit and push the branch:
# Move items from [Unreleased] to new release section
# Example: [1.0.0 - Arsenal] - 2026-XX-XX
git add CHANGELOG.md
git commit -m "docs(changelog): prepare release notes for v1.0.0-arsenal"
git push origin release/v1.0.0-arsenalOpen a pull request from release/v1.0.0-arsenal into master and merge it. The tag must be created after the merge so it points to the correct commit on master.
Before creating the tag, verify all of the following:
-
CHANGELOG.md[Unreleased]section is moved to a new versioned release entry - Release PR is merged into
master -
./mvnw clean installpasses - Club name is valid and follows alphabetical order (see historic club list)
- All CI checks on
masterare green
After the PR is merged, pull master and create the annotated tag:
git checkout master && git pull
git tag -a v1.0.0-arsenal -m "Release 1.0.0 - Arsenal"
git push origin v1.0.0-arsenalPushing the tag triggers the CD workflow which automatically:
- Validates tag format (semver and club name)
- Builds and tests the project with Maven
- Publishes Docker images to GitHub Container Registry with three tags
- Creates a GitHub Release with auto-generated changelog from commits
Each release publishes multiple tags for flexibility:
# By semantic version (recommended for production)
docker pull ghcr.io/nanotaboada/java-samples-spring-boot:1.0.0
# By club name (memorable alternative)
docker pull ghcr.io/nanotaboada/java-samples-spring-boot:arsenal
# Latest release
docker pull ghcr.io/nanotaboada/java-samples-spring-boot:latest