Development Workflow
1. Introduction
This guide describes the development workflow for Event and Membership Management projects. We follow the GitFlow branching model, automated through the GitFlow Maven Plugin.
1.1. GitFlow Origins
|
GitFlow was originally conceived by Vincent Driessen in his influential 2010 blog post "A successful Git branching model". For an excellent introduction to GitFlow concepts with visual diagrams, see the Atlassian GitFlow Tutorial. |
1.2. Core Principles
| Stable develop |
The |
| Production-ready main |
The |
| Feature isolation |
New features are developed in isolated branches |
| Release preparation |
Releases are prepared in dedicated branches for stabilization |
2. Branch Strategy
main ─────●───────────────────●──────────────────────●────►
│ ↑ ↑
│ release/1.2.0 │
│ ↑ │
│ │ release/1.3.0
│ │ ↑
develop ─────●───●───●───●───●───●───●───●───●───●───●──●───►
↑ ↑ ↑
feature/ feature/ feature/
ADO-101 ADO-102 ADO-103
2.1. Branch Types
| Branch Type | Purpose | Naming Convention |
|---|---|---|
|
Production-ready releases |
|
|
Integration branch for features |
|
Feature |
New functionality |
|
Bugfix |
Bug fixes for develop |
|
Release |
Release preparation |
|
Hotfix |
Emergency production fixes |
|
3. Feature Development
3.1. Creating a Feature Branch
# Ensure develop is up to date
git checkout develop
git pull origin develop
# Create feature branch
git checkout -b feature/ADO-123-add-user-authentication
3.2. Branch Naming Convention
feature/ADO-{work-item-id}-{brief-description}
-
Always reference the Azure DevOps work item ID
-
Use lowercase with hyphens
-
Keep the description brief but descriptive
feature/ADO-123-add-user-authentication
feature/ADO-456-refactor-payment-service
bugfix/ADO-789-fix-login-redirect
3.3. Commit Messages
ADO-{id}: Brief description (max 72 chars)
Optional longer explanation of:
- What changed
- Why it changed
- Notable implementation details
ADO-123: Add JWT authentication to login endpoint
Implement JWT-based authentication using Spring Security.
- Added JwtTokenProvider service
- Configured SecurityFilterChain
- Added login and refresh token endpoints
3.4. Formatting and the Pre-commit Hook
The Angular repositories — membership-ui, event-registration-ui and event-admin-ui — format staged files on commit, using husky, lint-staged and Prettier. The Java-only repositories have no hook.
The hook is a convenience, not the gate. It runs only when the checkout has its tooling, and otherwise skips with a notice instead of blocking the commit:
-
In a git worktree it does not run at all in
membership-uiandevent-registration-ui. Husky 9 pointscore.hooksPathat.husky/_, whichnpm installgenerates per checkout, and a worktree does not have one. -
event-admin-uistays on husky 7, because its build toolchain is Node 16 and husky 9 requires Node 18. Husky 7 pointscore.hooksPathat the tracked.huskydirectory, so git runs the hook in a worktree too — where it finds nonode_modulesand skips. -
In a fresh clone before
npm install, or from a client without node on PATH, it prints a notice and exits. -
It never installs, builds or downloads anything.
Git hooks do not load ~/.bashrc, so for nvm’s node to be found by IDEs, GUI clients and non-interactive shells, put this in ~/.config/husky/init.sh, which husky 9 sources before every hook. Husky 7 does not read it, so in event-admin-ui such a client skips the hook instead:
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
The gate is the Format job in the pull-request pipeline, from the shared check-format.yml workflow. It stages the pull request’s changes as one commit, runs the repository’s own lint-staged over them, and fails if anything would be rewritten. It therefore applies exactly the hook’s rules — the same glob, .prettierignore and commands.
Two consequences to expect:
-
Only changed files are checked. Formatting drift in untouched files is left alone.
-
Touching a file formats all of it. lint-staged formats whole files, so editing a file with pre-existing drift produces a whitespace-only diff across it — expected, and reviewable with
git diff -w. Where the hook did not run, format the file yourself withnpx prettier --write <file>before pushing.
After pulling a change that upgrades husky, run npm install once so the checkout’s hooks path is updated.
4. Release Process
4.1. Overview
A release takes three steps, and only the middle one is hand work:
-
Start — the
manual-release-start.ymlworkflow cutsrelease/X.Y.Zfromdevelopand opens a pull request intomain. -
Prepare — release notes in
RELEASE.md, and any fix the release needs, are committed to the release branch. -
Merge — merging the pull request triggers
push-main.yml, which publishes and deploys the release, then finishes GitFlow: tagsmain, merges the tag back intodevelop, and bumpsdevelopto the next SNAPSHOT.
4.2. Starting a Release
Confirm first that the develop pipeline is green on the commit you intend to release, and that no other release/ or hotfix/ branch is open — release-finish expects exactly one.
Run the GitFlow Release Start workflow from the Actions tab, or:
gh workflow run manual-release-start.yml --repo christhonie/<repo> --ref develop -f version=X.Y.Z
Use the version develop is already on, without -SNAPSHOT. The input is free text, and cutting a higher number strands the one consumers have been pinning against — see CI and Release Pipeline Traps.
The workflow:
-
Creates
release/X.Y.Zfromdevelopand pushes it -
Sets
<revision>toX.Y.Zon the release branch only -
Opens a pull request
Release X.Y.Zfrom the release branch intomain
develop is not changed when a release starts. Its version moves when the release finishes.
4.3. Release Branch Activities
During the release phase:
-
Release notes in
RELEASE.md, appended as a new## X.Y.Zsection -
Fixes the release needs before it ships
-
Configuration adjustments
What runs on the release branch is deliberately little:
-
The push that creates the branch is made with
GITHUB_TOKEN, which triggers no workflows. -
Repositories with a
push-release.ymlrun the back-end tests on later pushes — but it ignores*.md, so a notes-only commit runs nothing. -
The SPA and plugin repositories have no release-branch workflow at all.
-
pr-non-main.ymlignores pull requests intomain, andmainhas no required checks.
A release pull request that reports no checks is therefore normal. The code was tested by the develop pipeline before the release was cut.
4.4. Completing a Release
When the release is ready, merge the pull request into main. push-main.yml then runs:
-
Production build with the
prodMaven profile -
Docker image build and push
-
Helm chart package and push
-
Stage deploy — the stage ArgoCD manifest is bumped to the new chart version
-
GitFlow release-finish, which:
-
Tags
mainwithX.Y.Z -
Merges the tag into
develop, resolving a conflict confined to<revision>automatically -
Bumps
developto the next SNAPSHOT (see Version Bumping) -
Deletes the release branch
-
Verify the finish: the tag exists, develop carries Merge tag 'X.Y.Z' into develop followed by the Release now finished bump, and the release branch is gone.
If the Gitflow job fails, the artefact has usually already shipped from the jobs ahead of it. Do not re-run the job — finish the remaining steps by hand, as described in CI and Release Pipeline Traps.
5. GitFlow Maven Plugin
5.1. Overview
The GitFlow Maven Plugin automates GitFlow operations, ensuring consistent version management and branch handling.
Best Practice: Configure the plugin in the parent POM to ensure consistency across all projects in the organization.
5.2. Plugin Configuration
Reference implementation from event/pom.xml:
<plugin>
<groupId>com.amashchenko.maven.plugin</groupId>
<artifactId>gitflow-maven-plugin</artifactId>
<version>${gitflow-maven-plugin.version}</version>
<configuration>
<!-- Whether to print commands output into the console -->
<verbose>false</verbose>
<!-- Whether to fetch remote branch and compare it with the local one -->
<fetchRemote>true</fetchRemote>
<!-- Whether to call Maven install goal during the mojo execution -->
<installProject>false</installProject>
<!-- Whether to push to the remote for release/feature/hotfix start -->
<pushRemote>true</pushRemote>
<!-- Whether to skip changing project version on feature branches -->
<skipFeatureVersion>true</skipFeatureVersion>
<!-- CI-friendly versioning support -->
<versionProperty>revision</versionProperty>
<skipUpdateVersion>true</skipUpdateVersion>
<!-- Git flow configuration -->
<gitFlowConfig>
<productionBranch>main</productionBranch>
<developmentBranch>develop</developmentBranch>
<featureBranchPrefix>feature/</featureBranchPrefix>
<releaseBranchPrefix>release/</releaseBranchPrefix>
<hotfixBranchPrefix>hotfix/</hotfixBranchPrefix>
<supportBranchPrefix>support/</supportBranchPrefix>
<versionTagPrefix />
<origin>origin</origin>
</gitFlowConfig>
<!-- Git commit messages -->
<commitMessages>
<featureStartMessage>Feature start. Set feature version to @{version}.</featureStartMessage>
<featureFinishMessage>Feature finished. Development version updated to @{version}.</featureFinishMessage>
<hotfixStartMessage>Hotfix start. Set hotfix version to @{version}.</hotfixStartMessage>
<hotfixFinishMessage>Hotfix now finished. Development version updated to @{version}.</hotfixFinishMessage>
<releaseStartMessage>Release start. Set release version to @{version}.</releaseStartMessage>
<releaseFinishMessage>Release now finished. Development version incremented to @{version}.</releaseFinishMessage>
<releaseFinishMergeMessage>Released v@{version}</releaseFinishMergeMessage>
<tagHotfixMessage>Tag hotfix @{version}</tagHotfixMessage>
<tagReleaseMessage>Tag release @{version}</tagReleaseMessage>
</commitMessages>
</configuration>
</plugin>
5.3. Key Configuration Options
| Option | Description |
|---|---|
|
Uses CI-friendly |
|
Don’t modify version when creating feature branches |
|
Automatically push branches and tags to remote |
|
Works with flatten-maven-plugin for CI-friendly builds |
5.4. Plugin Goals
| Goal | Description |
|---|---|
|
Create a new feature branch from develop |
|
Merge feature branch back to develop |
|
Create release branch, update versions |
|
Merge to main, tag, merge back to develop |
|
Create hotfix branch from main |
|
Merge hotfix to main and develop |
5.5. CI-Friendly Versioning
The plugin works with Maven’s CI-friendly versioning and the flatten-maven-plugin:
<properties>
<revision>1.3.2-SNAPSHOT</revision>
</properties>
<version>${revision}</version>
This allows the version to be set dynamically during CI builds while the POM remains unchanged.
6. Hotfix Process
Hotfixes are emergency fixes applied directly to production.
6.1. Creating a Hotfix
mvn gitflow:hotfix-start -DhotfixVersion=1.2.1
This:
-
Creates
hotfix/1.2.1branch frommain -
Updates version to
1.2.1
6.2. Completing a Hotfix
mvn gitflow:hotfix-finish
This:
-
Merges hotfix to
main -
Creates version tag
-
Merges hotfix to
develop -
Deletes hotfix branch
|
TODO: GitHub Actions automation for the hotfix workflow has not yet been implemented. Currently, hotfixes are performed manually using the GitFlow Maven Plugin. |
7. Version Management
7.1. Version Lifecycle
| Branch | Version Format | Example |
|---|---|---|
develop |
|
|
release/X.Y.Z |
|
|
main (after release) |
|
|
develop (after release) |
|
|
7.2. Version Bumping
When a release starts, only the release branch changes:
-
Release branch:
1.2.0-SNAPSHOT→1.2.0 -
Develop branch: unchanged at
1.2.0-SNAPSHOT
When the release finishes, develop moves to the next patch SNAPSHOT — 1.2.0 → 1.2.1-SNAPSHOT. If develop has already been moved past that while the release was open, it keeps its own version; the finish never moves it backwards.
A minor or major increment is made on develop by hand, by editing <revision>.
7.3. Semantic Versioning
Follow Semantic Versioning:
| MAJOR |
Breaking changes to public API |
| MINOR |
New functionality, backwards compatible |
| PATCH |
Bug fixes, backwards compatible |
8. CI/CD Integration
For detailed information on how the development workflow integrates with CI/CD pipelines, see GitHub Actions CI/CD Architecture.
8.1. PR Pipelines
-
PRs to
developtrigger the test pipeline -
All tests must pass before merge (unless overridden)
-
Path filtering ensures only relevant tests run
-
In the Angular repositories, a
Formatjob checks every PR’s changes regardless of paths — see Formatting and the Pre-commit Hook
9. Best Practices
10. Related Documentation
-
GitHub Actions CI/CD Architecture - CI/CD pipeline configuration
-
GitHub Repository Rules - Branch protection and code owner setup
-
Helm Chart Patterns - Helm chart structure
-
ArgoCD Deployment - GitOps deployment
11. External References
-
Atlassian GitFlow Tutorial - Excellent visual introduction
-
GitFlow Maven Plugin - Documentation and configuration options
-
Semantic Versioning - Version numbering guidelines