Releasing¶
Overview¶
The HAProxy Template Ingress Controller uses a dual-release model where the controller and Helm chart have independent version numbers. This allows chart-only releases (e.g., documentation fixes) without requiring a new controller version.
Both use Semantic Versioning with support for pre-release suffixes.
Version Numbering¶
Format: MAJOR.MINOR.PATCH[-PRERELEASE]
| Type | Example | Description |
|---|---|---|
| Stable release | 0.1.0, 1.0.0 |
Production-ready version |
| Alpha | 0.1.0-alpha.1 |
Early testing, APIs may change |
| Beta | 0.1.0-beta.1 |
Feature complete, needs testing |
| Release candidate | 0.1.0-rc.1 |
Final testing before release |
CHANGELOG Conventions¶
A single CHANGELOG.md tracks changes for both controller and chart. Use prefixes to indicate scope:
| Prefix | When to Use |
|---|---|
[Controller] |
Changes to controller code only |
[Chart] |
Changes to Helm chart only (values, templates) |
| (no prefix) | Changes affecting both controller and chart |
Example:
## [0.1.0] - 2025-01-15
### Added
- [Chart] Default SSL certificate support via Helm values
- [Controller] Leader election for high availability
- New CRD field for custom annotations <!-- affects both -->
### Changed
- [Chart] Default replica count changed from 1 to 2
Prerequisites¶
Before releasing:
- Clean working directory - All changes committed
- CHANGELOG.md updated - Release notes documented
- All tests passing - CI pipeline green on main branch
- Documentation updated - Any new features documented
Controller Release Process¶
1. Update CHANGELOG.md¶
Prepare the changelog for release:
# Current structure
## [Unreleased]
### Added
- New feature X
# Change to
## [0.1.0-alpha.1] - 2025-01-15
### Added
- New feature X
## [Unreleased]
2. Run the Release Script¶
Example:
The script will:
- Validate version format (SemVer)
- Check CHANGELOG.md has the version entry
- Update the
VERSIONfile - Update
Chart.yamlappVersion and image annotation - Create a commit and annotated tag
3. Push to Trigger CI¶
Example:
What CI Does Automatically¶
When a controller-v* tag is pushed, CI will:
- Build binaries for linux/amd64, linux/arm64, linux/arm/v7
- Create GitLab release with:
- Signed binaries
- SHA256 checksums
- Release notes from CHANGELOG.md
- Pre-release flag (for alpha/beta/rc versions)
- Build Docker images for HAProxy 3.0, 3.1, 3.2
- Sign all artifacts with Cosign (keyless OIDC)
- Generate SBOM (Software Bill of Materials) for each image
- Attach SBOM attestation to images via Cosign
- Trigger documentation build with version tag
Chart Release Process¶
When to Release Chart Separately
Only release the chart separately when:
- Chart-only changes (values, templates, docs)
- Breaking Helm value changes
- Chart bug fixes independent of controller
Controller releases automatically update the chart's appVersion.
1. Update CHANGELOG.md¶
Add a ## [<version>] section with chart changes prefixed by [Chart]:
2. Run the Release Script¶
The script will:
- Validate version format (SemVer)
- Check CHANGELOG.md has the version entry
- Update
Chart.yamlversion - Create a commit and annotated tag
3. Push to Trigger CI¶
What CI Does Automatically¶
When a chart-v* tag is pushed, CI will:
- Package Helm chart as OCI artifact
- Push to GitLab registry at
registry.gitlab.com/haproxy-template-ic/haproxy-template-ingress-controller/charts - Sign with Cosign (keyless)
- Create GitLab release with release notes from CHANGELOG.md
- Trigger documentation build with version tag
Documentation Versioning¶
Each release creates a versioned documentation snapshot:
| Release Type | Docs Behavior |
|---|---|
Stable (0.1.0) |
Creates version, gets latest alias |
Pre-release (0.1.0-alpha.1) |
Creates version, no latest alias |
| Final after pre-release | Removes matching pre-release versions |
Example lifecycle:
0.1.0-alpha.1released -> Docs at/v0.1.0-alpha.1/0.1.0-alpha.2released -> Docs at/v0.1.0-alpha.2/0.1.0released -> Docs at/v0.1.0/withlatestalias, alpha versions removed
Pre-release vs Final Release¶
Pre-releases¶
Pre-releases (alpha, beta, rc) have these differences:
- Docker images built but don't get
latesttag - Documentation created but not marked as
latest - GitLab release marked as pre-release
- Not recommended for production use
Final Releases¶
Final releases (no suffix):
- Docker images get
latesttags - Documentation gets
latestalias - Pre-release documentation versions are removed
- Recommended for production use
Troubleshooting¶
Release Script Fails¶
| Error | Solution |
|---|---|
| "Working directory is not clean" | Commit or stash changes |
| "CHANGELOG.md has no entry" | Add ## [version] section |
| "Invalid version format" | Use X.Y.Z or X.Y.Z-suffix.N |
CI Pipeline Fails¶
- Check GitLab CI logs for specific error
- Verify tests pass locally with
make test - Check Docker builds work locally
Docker Image Missing¶
If images don't appear after release:
- Check
release-controller-imagesjob completed - Verify registry authentication succeeded
- Check for build errors in job logs
Supply Chain Security¶
All release artifacts are signed and include security metadata:
Artifact Signing¶
All artifacts are signed with Cosign using keyless OIDC:
- Binaries: Checksums file signed with detached signature
- Docker images: Each image tag signed
- Helm chart: OCI artifact signed
Verify image signature:
cosign verify \
--certificate-identity-regexp='https://gitlab.com/haproxy-template-ic/.*' \
--certificate-oidc-issuer='https://gitlab.com' \
registry.gitlab.com/haproxy-template-ic/haproxy-template-ingress-controller:v0.1.0
SBOM (Software Bill of Materials)¶
Each Docker image includes an SBOM attestation in SPDX format:
View SBOM:
cosign verify-attestation \
--type spdxjson \
--certificate-identity-regexp='https://gitlab.com/haproxy-template-ic/.*' \
--certificate-oidc-issuer='https://gitlab.com' \
registry.gitlab.com/haproxy-template-ic/haproxy-template-ingress-controller:v0.1.0 \
| jq -r '.payload' | base64 -d | jq '.predicate'
The SBOM lists all packages, libraries, and dependencies in the container image.
Version Files Reference¶
| File | Content | Updated By |
|---|---|---|
VERSION |
Controller version | Release script |
Chart.yaml:version |
Chart version | Chart release script |
Chart.yaml:appVersion |
Controller version | Controller release script |
Chart.yaml annotation |
Image version | Controller release script |