Complete guide to GitOps Reverser's automated release system with semantic versioning.
Required: Enable GitHub Actions to create pull requests.
Your organization has disabled this at the org level. Enable it in this order:
-
Organization Settings (requires admin/owner permissions):
- Go to:
https://github.com/organizations/YOUR_ORG/settings/actions - Under "Workflow permissions": ✅ "Allow GitHub Actions to create and approve pull requests"
- Click Save
- Go to:
-
Repository Settings (should now be available):
- Go to:
https://github.com/YOUR_ORG/gitops-reverser/settings/actions - Under "Workflow permissions": ✅ "Allow GitHub Actions to create and approve pull requests"
- Click Save
- Go to:
# Create a test commit
git commit --allow-empty -m "feat: test automated releases"
git push origin mainExpected outcome:
- CI runs (lint, unit tests, e2e)
- If tests pass → Release PR created for v0.2.0
- Merge PR → GitHub Release + Docker images published
Push to main
↓
[CI: Build & Test + E2E]
↓ (tests pass)
[release-please analyzes commits]
↓ (version bump needed)
[Create/Update Release PR]
↓ (human reviews & merges)
[Create GitHub Release + Tag (draft)]
↓
[Retag CI-built images to semver + latest, sign, attest → publish the release]
The next Release PR is opened/refreshed by a second release-please pass that runs after a release is published, so it never sees the still-draft release. See What Happens When You Push.
On every push to main:
-
CI Tests Run (
.github/workflows/release.ymlcalls the reusable.github/workflows/ci.yml— the same jobs every PR runs):- Lint:
task lint(golangci-lint, hadolint, actionlint, helm lint) - Unit tests:
task test(with the coverage ratchet) - E2E tests: the Ginkgo suite in a k3d cluster, plus the project image scan
- Lint:
-
Release handling (if tests pass) — release-please runs as two separate passes:
- Cut pass (
release-pleasejob): if the previous Release PR was merged, cut its GitHub Release (created as a draft — see step 4). This pass usesskip-github-pull-request, so it does not open the next PR. - PR pass (
release-please-prjob): analyze commits since the last release, determine the version bump, and create/update the next Release PR (skip-github-release). It runs after the release is published, so it sees the just-published release instead of the draft. Without this split, the run that cut a draft would open a PR computed against the whole history and propose a bogus "release everything" version.
- Cut pass (
-
Release PR Contents:
- Auto-generated CHANGELOG.md updates
- Updated
charts/gitops-reverser/Chart.yamlversions - Summary of all changes
-
When Release PR is Merged:
- GitHub Release created with tag (e.g.,
v0.2.0) — first as a draft, so every signed asset (install.yaml, SBOM,.sigstore.jsonsignatures,.intoto.jsonlattestations) can be attached before it goes public; immutable releases reject post-publish uploads, sopublish-releaseflips the draft to published only after every asset is in place. - The linux/amd64 + linux/arm64 image digests already built and scanned by that
commit's CI run are retagged (not rebuilt) as
0.2.0,0.2,0,latestonghcr.io, then cosign-signed with SLSA provenance + SPDX SBOM attestations
- GitHub Release created with tag (e.g.,
<type>(<optional scope>): <description>
[optional body]
[optional footer(s)]
| Type | Version Bump | Example |
|---|---|---|
feat |
Minor (0.1.0 → 0.2.0) | feat(controller): add multi-repo support |
fix |
Patch (0.1.0 → 0.1.1) | fix(webhook): handle timeout |
feat! or BREAKING CHANGE: |
Major (0.1.0 → 1.0.0) | feat!: redesign API |
docs |
No bump | docs: update README |
style |
No bump | style: format code |
refactor |
No bump | refactor: simplify logic |
perf |
Patch (0.1.0 → 0.1.1) | perf: optimize loop |
test |
No bump | test: add unit tests |
build |
No bump | build: update deps |
ci |
No bump | ci: improve workflow |
chore |
No bump | chore: update .gitignore |
revert |
Patch (0.1.0 → 0.1.1) | revert: undo feature X |
Feature (Minor Bump):
git commit -m "feat(controller): add multi-repository support
Allows configuring different Git repos for different namespaces,
improving flexibility in audit trail organization.
Closes #42"Bug Fix (Patch Bump):
git commit -m "fix(webhook): prevent race condition in event queue
The event queue could process events out of order. This adds proper locking.
Fixes #123"Breaking Change (Major Bump):
git commit -m "feat!: redesign GitRepoConfig API
BREAKING CHANGE: The GitRepoConfig CRD uses a different schema.
Users must migrate using the provided script.
Migration guide: docs/migration-v1.md"Solution: Enable at org level first (if greyed out), then repo level. See Prerequisites Setup above.
Check:
- ✅ CI tests passed (green checkmark in Actions tab)
- ✅ Commit used conventional format (
feat:,fix:, etc.) - ✅ Pushed to
mainbranch - ✅ GitHub Actions has PR creation permissions
Retry:
# Check workflow status
gh run list --branch main --limit 5
# Re-run failed workflow
gh run rerun <run-id>
# Or push new commit
git commit --allow-empty -m "feat: trigger release"
git push origin mainRelease process won't proceed if tests fail. Fix tests first:
# Run tests locally
make lint
make test
make test-e2e
# Fix issues, then push
git add .
git commit -m "fix: resolve test failures"
git push origin mainCauses:
- Multiple commit types (most significant wins)
!orBREAKING CHANGE:triggers major bump.release-please-manifest.jsonout of sync
Solution: Edit Release PR version or close it and retrigger.
Check:
- Build logs in Actions tab
- Multi-arch build issues (amd64/arm64)
- Registry authentication (GITHUB_TOKEN permissions)
# View logs
gh run view --log
# Manually retrigger
gh run rerun <run-id>✅ Good:
feat(controller): add support for custom branch names
Users can now specify different branch names for different GitRepoConfigs,
allowing more flexible repository organization.
❌ Bad:
add stuff
fix bug
wip
Indicate which component is affected:
feat(controller): ...fix(webhook): ...docs(readme): ...test(integration): ...
git commit -m "feat(controller): add multi-repo support"
git commit -m "docs: document multi-repo config"
git commit -m "test: add multi-repo tests"Before merging:
- ✅ Verify changelog accuracy
- ✅ Check version bump is appropriate
- ✅ Ensure all commits are included
- ✅ Confirm breaking changes are documented
For major version bumps:
- Discuss in an issue first
- Add migration guide to
docs/ - Update relevant documentation
- Announce in discussions/Slack
These are automatically updated by release-please:
.release-please-manifest.json- Current versioncharts/gitops-reverser/Chart.yaml- Helm chart versionsCHANGELOG.md- Auto-generated changelog
Don't modify these without understanding the impact:
release-please-config.json- Semantic versioning rules.github/workflows/ci.yml- Validation pipeline (PRs + reused on main).github/workflows/release.yml- Release/publish pipeline (push to main)
See docs/ci-overview.md for the full CI/CD design.
If automation fails completely:
# 1. Tag the commit
git tag -a v0.2.1 -m "Release v0.2.1"
git push origin v0.2.1
# 2. CI will build and push Docker images
# 3. Create GitHub Release
gh release create v0.2.1 \
--title "v0.2.1" \
--notes "Emergency release: fix critical bug"Note: Manual releases should be rare. Fix the automation instead.
- Conventional Commits Specification
- Semantic Versioning
- Release Please Documentation
CONTRIBUTING.md- Full commit guidelinesREADME.md- Quick reference
- Check this document first
- Review existing Release PRs for examples
- Check GitHub Actions logs for errors
- Open an issue or discussion if stuck