Branch Strategy & Release Flow
This repository follows GitHub Flow: main is the only long-lived branch. There is no develop branch.
Develop and Production are GitHub Environments, not branches. "Deploying" to them means pushing the app and devcontainer container images to GHCR (ghcr.io/a5chin/python-uv/{app,devcontainer}).
gitGraph
commit id: "initial commit"
branch feature/xxx
commit id: "add feature"
checkout main
merge feature/xxx id: "merge feature [Develop + Draft]"
branch fix/xxx
commit id: "fix bug"
checkout main
merge fix/xxx id: "merge fix [Develop + Draft]" tag: "v1.0.0"
branch hotfix/xxx
commit id: "urgent fix"
checkout main
merge hotfix/xxx id: "merge hotfix [Develop + Draft]" tag: "v1.0.1"
- [Develop + Draft]: every merge into
mainpushes the images to Develop and, if the builds succeed, updates the Draft Release. - Tags (
v1.0.0,v1.0.1): publishing the Draft adds the tag to the commit it points to and deploys that tag to Production. No commit is made for the tag; check the Develop images before publishing.
Branches
Create every branch from main and merge it back into main with a pull request. Never push directly to main.
| Prefix | Use | Label added automatically |
|---|---|---|
feature/ |
New features | feature |
fix/ |
Bug fixes | fix |
hotfix/ |
Urgent fix for a problem in Production | hotfix |
refactor/ |
Refactoring | refactor |
Labels are added by labeler.yml from the branch prefix; PRs that change *.md files also get documentation. These labels decide the section of the release notes.
1. Merge into main → Develop
Every merge into main runs release.yml:
- The
publishjob builds theappanddevcontainerimages and pushes them to GHCR with the tagsmainandsha-<full commit SHA>(environment: Develop). - Only if both builds succeed, the
draftjob updates the Draft Release with release-drafter. The Draft points to the exact commit that was just built.
If several PRs are merged in quick succession, older runs are cancelled and only the latest commit is built and drafted.
2. Review the Draft Release → Publish → Production
Publishing is done by a maintainer with write access to the repository. Contributors only need to get their PR merged into main.
- Open Releases on GitHub and edit the existing Draft. Do not create a new release or push a tag yourself.
- Check the tag. release-drafter proposes it from the version labels on the merged PRs (
major/minor/patch; the highest wins, defaultpatch). Maintainers add version labels manually. You may change the tag; change it right before publishing, because any merge intomainin between makes release-drafter overwrite it with its proposed value. - Edit the release notes if needed, then click Publish release. Publishing from the GitHub UI or with
gh release edit <tag> --draft=false(your own credentials) is fine. Only releases published from inside a GitHub Actions workflow withGITHUB_TOKENfail to trigger the deployment. - The
publishjob runs again (environment: Production), rebuilds the images from the tag, and pushes them with the tags<release tag>(e.g.v1.3.0) andlatest. Theorg.opencontainers.image.versionlabel is set to the release tag.
Warning
The tag must start with v (e.g. v1.3.0). The Production environment only allows deployments from tags matching v* (a tag policy; no v* branch is created), so any other tag is rejected.
Pre-releases are not deployed: only a full release (or converting a pre-release to a full release) triggers Production.
Hotfixes
Hotfixes follow the same flow: create hotfix/* from main, open a PR to main, merge, then publish the Draft.
Note that everything already merged into main but not yet released ships together with the hotfix. Check the Draft's change list before publishing.
- If some of those changes must not ship yet, revert them with a PR to
mainfirst, then publish. - The proposed tag follows the PR labels (the highest of
major/minor/patchwins), so it may be a minor version even for a hotfix. Change it if it does not match what you are releasing (e.g.v1.2.4for a patch); it must still start withv.
When Something Fails
| Symptom | Cause | Action |
|---|---|---|
| The Draft Release was not updated after a merge | The publish job (image build) failed, so draft was skipped |
Open the Release workflow run in the Actions tab, fix the failure, then re-run the failed jobs or merge the fix into main |
| Production succeeded for only one image | Image builds run independently (fail-fast: false) |
Re-run the failed job in the same workflow run |
| Production deployment was rejected | The tag does not start with v |
Edit the release, set it back to a draft, change the tag to start with v, and publish again |