Release CI/CD
User story
As a maintainer, merging a release-worthy Gitmoji commit to main should produce a GitHub release and matching backend/frontend images on GHCR after all existing CI checks pass.
Requirements
- Reuse
juftin/actions/semantic-release@v1and the Gitmoji configuration fromjuftin/cookiecutter-python. - Release only trusted pushes to
juftin/camply-webonmain, after the complete CI workflow succeeds. Pull requests must never publish. - Publish
ghcr.io/juftin/camply-backendandghcr.io/juftin/camply-frontendwith matching full semantic versions and moving major aliases such asv1. Updatelatestafter every successfulmainbuild, including commits that do not warrant a semantic release. - Stamp all backend workspace packages, the backend lockfile, and frontend package metadata in the release workspace before building. Leave version changes uncommitted; Git tags identify releases.
- Attach version-stamped sdists for all four installable backend workspace packages to each GitHub release. Build the distributions before creating the release; do not publish packages to PyPI.
- Enable
semantic-release-major-tagto advance matching Git major aliases such asv1after release success, in addition to the existing Docker aliases. - Separate release creation from image publishing:
release.yamlcreates the GitHub release with the existing Renovate GitHub App;publish.yamlhandles nativerelease: publishedevents using the exact full-version tag. Use the repository'sAPP_IDandAPP_PRIVATE_KEYsecrets directly. UseGITHUB_TOKENonly for GHCR publishing. - Preserve the frontend's same-origin
/apiconfiguration and existing Docker build contexts. - Document setup, version rules, initial release behavior, verification, and failure recovery. Application hosting and PyPI publishing are outside this feature.
Acceptance scenarios
- A successful
mainbuild containing✨publishes a minor release (the initial release is1.0.0when no release tags exist). - Failed or cancelled CI, pull requests, and forks cannot publish artifacts. Successful
mainbuilds without release-worthy changes publish onlylatest. - Both image tags and installed application metadata match the selected release version.
- A failed image publication leaves the GitHub release intact; rerunning its publish workflow retries the same tagged version without another semantic release.
- A
1.2.3release updates the1.2.3,v1, andlatestimage tags; a subsequent2.0.0release updates2.0.0,v2, andlatestwhile preservingv1. - Each GitHub release includes
backend,db,providers, andworkersdists with matching metadata versions and required source/configuration files; a failed source build prevents publication. - After a successful
1.2.3release, Git tagv1points to the released commit; later releases advance their own major alias without changing other majors. - A release-producing main build publishes images once via the release event; a successful main build without a release calls the same publisher for
latestonly. Missing App credentials fail release creation rather than silently suppressing the publish event.