Skip to content

ci: align workflow structure with hriv reference implementation - #15

Merged
kphunter merged 3 commits into
mainfrom
devin/1777133166-align-workflows-with-hriv
Apr 25, 2026
Merged

ci: align workflow structure with hriv reference implementation#15
kphunter merged 3 commits into
mainfrom
devin/1777133166-align-workflows-with-hriv

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Apr 25, 2026

Copy link
Copy Markdown
Contributor

Summary

Rewrites all CI/CD workflows to match the authoritative hriv monorepo pattern, adapted for a single-component repo. This brings haproxy-operator's release pipeline, image tag contract, and permission model into alignment with the org's reference implementation.

What changed

ci.yaml — complete rewrite

  • Triggers: push + PR to main only (removed tags: ["v*"] and workflow_dispatch)
  • Version computation: inline from git tags + conventional-commit analysis (same algorithm as hriv, plus bump-minor-pre-major support for MAJOR==0)
  • Image tag contract: sha-<fullsha> + <ver>-rc.<ts>.<short> (hriv format) instead of <ver>-head.<sha> + moving :head pointer
  • Trivy scanning split: table-to-log on PRs (with ignore-unfixed), SARIF-to-Security on main
  • PR builds: load: true (local scan) instead of skipping entirely
  • Attestations: provenance: false, sbom: false to keep exactly 2 image artifacts per push
  • Permissions: least-privilege workflow default (contents: read) with job-level elevations; includes actions: read for SARIF upload on private repos
  • Change detection: always builds on main pushes (needed for release-retag); git-diff gating only on PRs for Dockerfile go.mod go.sum main.go internal/
  • Removed inline helm-publish (moved to dedicated workflow)
  • Job renamed: imagebuild (⚠️ update branch protection if image is a required check)

release-please.yaml — rewrite

  • Standard manifest mode instead of prerelease mode (removed versioning, prerelease, prerelease-type from config)
  • Stale release-as guard from hriv (fails loudly if one-shot overrides linger)
  • Dispatch pattern: fires helm-publish.yaml + release-retag.yaml via workflow_dispatch (same GITHUB_TOKEN dispatch pattern as hriv)
  • Least-privilege permissions with job-level elevations

New workflows (matching hriv)

Workflow Purpose
helm-publish.yaml Release-only Helm chart OCI publishing (parses vX.Y.Z from tag)
release-retag.yaml sha-<commit> → semver + latest image retagging with Cosign signing
pr-title-lint.yaml Conventional-commit PR title enforcement with sticky failure comments

release-please-config.json

  • Removed "versioning": "prerelease", "prerelease": true, "prerelease-type": "rc"

Image tag contract (after merge)

Event Tags pushed to ghcr.io/<repo>/haproxy-operator
Main push sha-<fullsha> (immutable) + <ver>-rc.<ts>.<short>
Release (vX.Y.Z) <version> + latest (via release-retag, iff highest stable)
PR build Built + scanned locally, NOT pushed

Review & Testing Checklist for Human

  • Update branch protection — CI job renamed from image to build; update required status checks if image is listed
  • Verify image tag contract matches expectations — the new tags (sha-<sha> + <ver>-rc.<ts>.<short>) replace the old <ver>-head.<sha> + moving :head format. Confirm flux-fleet ImagePolicy for haproxy-operator is updated (or will be updated) to match the new -rc.<ts> pattern
  • Confirm prerelease→standard mode transition is safe — manifest currently shows 0.3.0; next release-please run will compute from conventional commits since v0.3.0. Verify no in-flight rc release PRs will be disrupted
  • Test PR title lint — after merge, open a test PR with a non-conventional title to verify the sticky comment workflow fires correctly

Notes

  • The inline helm-publish job that previously ran on every main push has been removed. Charts are now only published on release, matching hriv. If flux-fleet currently tracks a :head chart OCI tag for haproxy-operator, that routing will need to be updated.
  • Chart Cosign signing was removed to match hriv's helm-publish.yaml (only images are signed, via release-retag.yaml). If chart signature verification is required downstream, it can be added back.
  • Change detection always builds on main pushes to ensure release-please merge commits still produce a sha-<commit> image for release-retag.yaml to find.
  • Version computation respects bump-minor-pre-major: true (improvement over hriv's reference implementation).

Link to Devin session: https://app.devin.ai/sessions/616a3e66529e458fbcfc0b6cca2703a7
Requested by: @kphunter


Open in Devin Review

Rewrite all CI/CD workflows to match the authoritative hriv monorepo
pattern, adapted for a single-component repo. Key changes:

ci.yaml:
- Remove tag and workflow_dispatch triggers; fire on push/PR to main only
- Remove monolithic 'versions' job; compute version inline from git tags
  + conventional commit analysis (same algorithm as hriv)
- Replace docker/metadata-action with explicit sha-<fullsha> +
  <ver>-rc.<ts>.<short> tag format matching hriv's image tag contract
- Split Trivy scanning: table-to-log on PRs, SARIF-to-Security on main
- Load (don't push) PR builds for local Trivy scanning
- Disable provenance/SBOM attestations to keep exactly 2 image artifacts
- Add per-component change detection (Dockerfile, Go source)
- Adopt least-privilege permissions (workflow-level contents:read,
  job-level elevations)
- Remove inline helm-publish job (moved to dedicated workflow)

release-please.yaml:
- Switch from prerelease mode to standard manifest mode
- Add stale release-as guard (prevents stuck version overrides)
- Dispatch helm-publish.yaml + release-retag.yaml on release (same
  GITHUB_TOKEN dispatch pattern as hriv)
- Adopt least-privilege permissions with job-level elevations
- Remove graduated-release promotion (not needed in standard mode)

New workflows:
- helm-publish.yaml: release-only Helm chart OCI publishing
- release-retag.yaml: sha→semver+latest image retagging with Cosign
- pr-title-lint.yaml: conventional-commit PR title enforcement with
  sticky failure comments

release-please-config.json:
- Remove versioning/prerelease/prerelease-type fields

Co-Authored-By: kyle_hunter@bcit.ca <kyle_hunter@bcit.ca>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

⚙️ Control Options:

  • Disable automatic comment and CI monitoring

devin-ai-integration[bot]

This comment was marked as resolved.

Address Devin Review findings:

1. Always build on main pushes so release-please merge commits
   (which only touch CHANGELOG/manifest/Chart.yaml, not Go source)
   still produce a sha-<commit> image that release-retag.yaml can
   find. Change detection is now only used to skip unnecessary PR
   builds.

2. Add actions:read permission to the build job, required by
   codeql-action/upload-sarif on private repos.

Co-Authored-By: kyle_hunter@bcit.ca <kyle_hunter@bcit.ca>
devin-ai-integration[bot]

This comment was marked as resolved.

1. Version computation now mirrors release-please's
   bump-minor-pre-major setting: while MAJOR==0, breaking changes
   bump minor instead of major, keeping CI rc tags in sync with
   actual releases.

2. OCI image.version label now includes the timestamp component
   (<ver>-rc.<ts>.<short>) matching the published tag exactly.

Co-Authored-By: kyle_hunter@bcit.ca <kyle_hunter@bcit.ca>
devin-ai-integration[bot]

This comment was marked as resolved.

Comment thread .github/workflows/ci.yaml
Comment on lines +187 to +204
SUBJECTS=$(git log "${RANGE}" --pretty=format:"%s" -- Dockerfile go.mod go.sum main.go internal/)
BODIES=$(git log "${RANGE}" --pretty=format:"%b" -- Dockerfile go.mod go.sum main.go internal/)

if echo "$SUBJECTS" | grep -qE "^[a-zA-Z]+(\([^)]+\))?!:" \
|| echo "$BODIES" | grep -qE "^BREAKING[ -]CHANGE:"; then
# Mirror release-please's bump-minor-pre-major: while the
# project is still on major 0, breaking changes bump minor
# instead of major so CI tags stay in sync with releases.
if ((MAJOR == 0)); then
((MINOR+=1)); PATCH=0
else
((MAJOR+=1)); MINOR=0; PATCH=0
fi
elif echo "$SUBJECTS" | grep -qE "^feat(\(.+\))?:"; then
((MINOR+=1)); PATCH=0
else
((PATCH+=1))
fi

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: CI version computation path-filters git log, diverging from release-please's full-history analysis

The Compute next version step (.github/workflows/ci.yaml:187-188) filters git log to only commits touching Dockerfile go.mod go.sum main.go internal/. This means a feat!: commit that only changes charts/ or docs/ would be missed by the CI version bump but picked up by release-please, causing CI pre-release tags (e.g., 0.3.1-rc.*) to diverge from the actual release version (e.g., 0.4.0). This is functionally harmless — CI tags are ephemeral artifacts and release-retag produces the authoritative stable tag — but could confuse operators inspecting image tags between a merge and a release.

Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Acknowledged. This matches hriv's pattern — CI version computation is path-filtered to the component's build context while release-please analyzes full history. As noted, CI rc tags are ephemeral; release-retag.yaml produces the authoritative semver tags from release-please's version.

@kphunter
kphunter merged commit 4ca3dc4 into main Apr 25, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant