Skip to content

Commit 964c63a

Browse files
authored
Merge branch 'main' into renovate/ghcr.io-projectbluefin-common-latest
2 parents 52d3087 + ff85922 commit 964c63a

File tree

4 files changed

+65
-29
lines changed

4 files changed

+65
-29
lines changed

.github/workflows/promote-to-lts.yml

Lines changed: 56 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,35 +3,69 @@ name: Promote Main to LTS
33
on:
44
workflow_dispatch:
55
inputs:
6-
pr_title:
7-
description: 'Pull request title'
6+
commit_title:
7+
description: 'Commit title for the squash promotion commit'
88
required: false
9-
default: 'Promote main to lts'
10-
pr_body:
11-
description: 'Pull request body'
9+
default: 'promote: main to lts'
10+
commit_body:
11+
description: 'Commit body (optional)'
1212
required: false
1313
default: |
14-
## Summary
15-
Promotion of tested changes from `main` to `lts` production branch.
16-
17-
**IMPORTANT**: This PR should ONLY contain commits from `main` → `lts`. Never merge in the opposite direction.
14+
Squash promotion of tested changes from `main` to `lts`.
1815
1916
permissions:
20-
pull-requests: write
21-
issues: write
17+
contents: write
2218

2319
jobs:
24-
create-promotion-pr:
20+
promote:
2521
runs-on: ubuntu-latest
2622
steps:
27-
- name: Create Pull Request
28-
env:
29-
GH_TOKEN: ${{ github.token }}
23+
- name: Checkout lts
24+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6
25+
with:
26+
ref: lts
27+
fetch-depth: 0
28+
token: ${{ github.token }}
29+
30+
- name: Fetch main
31+
run: git fetch origin main
32+
33+
- name: Pre-flight check
3034
run: |
31-
gh pr create \
32-
--repo ${{ github.repository }} \
33-
--base lts \
34-
--head main \
35-
--title "${{ inputs.pr_title }}" \
36-
--body "${{ inputs.pr_body }}" \
37-
--label "promotion"
35+
UNIQUE=$(git rev-list origin/lts ^origin/main --count)
36+
if [ "$UNIQUE" -gt 0 ]; then
37+
echo "ERROR: lts has $UNIQUE commit(s) that are not in main:"
38+
git log --oneline origin/lts ^origin/main
39+
echo ""
40+
echo "All changes must land in main before promoting to lts."
41+
echo "Land the above commits in main first, then re-run this workflow."
42+
exit 1
43+
fi
44+
echo "Pre-flight passed: lts has no commits outside of main."
45+
46+
- name: Configure Git
47+
run: |
48+
git config user.name "github-actions[bot]"
49+
git config user.email "github-actions[bot]@users.noreply.github.com"
50+
51+
- name: Squash merge main into lts
52+
id: squash
53+
run: |
54+
git merge --squash origin/main
55+
if git diff --cached --quiet; then
56+
echo "No changes to promote: origin/main is already fully merged into lts."
57+
echo "has_changes=false" >> "$GITHUB_OUTPUT"
58+
else
59+
echo "has_changes=true" >> "$GITHUB_OUTPUT"
60+
fi
61+
62+
- name: Commit promotion
63+
if: steps.squash.outputs.has_changes == 'true'
64+
run: |
65+
git commit \
66+
-m "${{ inputs.commit_title }}" \
67+
-m "${{ inputs.commit_body }}"
68+
69+
- name: Push to lts
70+
if: steps.squash.outputs.has_changes == 'true'
71+
run: git push origin lts

.github/workflows/reusable-build-image.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ jobs:
173173
id: setup-syft
174174
if: ${{ github.ref == 'refs/heads/lts' && inputs.publish }}
175175
continue-on-error: true
176-
uses: anchore/sbom-action/download-syft@17ae1740179002c89186b61233e0f892c3118b11 # v0
176+
uses: anchore/sbom-action/download-syft@57aae528053a48a3f6235f2d9461b05fbcb7366d # v0
177177

178178
- name: Generate SBOM
179179
id: generate-sbom

AGENTS.md

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ This section is the authoritative reference for all CI/CD behavior. Read it comp
121121
| `build-dx-hwe.yml` | Caller — builds `bluefin-dx` with HWE kernel |
122122
| `reusable-build-image.yml` | Reusable workflow — all 5 callers invoke this |
123123
| `scheduled-lts-release.yml` | Dispatcher — owns the weekly Sunday production release |
124-
| `promote-to-lts.yml` | Creates a PR to merge `main``lts` (see below) |
124+
| `promote-to-lts.yml` | Squash-pushes `main``lts` with pre-flight divergence check (see below) |
125125
| `generate-release.yml` | Creates a GitHub Release when `build-gdx.yml` completes on `lts` |
126126

127127
### Two Branches, Two Tag Namespaces
@@ -139,9 +139,9 @@ Promotion and production release are **intentionally decoupled**. There are two
139139

140140
**Phase 1 — Promotion (manual, no publishing):**
141141
1. A maintainer triggers `promote-to-lts.yml` via `workflow_dispatch`
142-
2. The workflow opens a PR from `main` targeting `lts` directly (no intermediate branch)
143-
3. A maintainer reviews and merges the PR
144-
4. The merge triggers a `push` event on `lts` — all 5 build workflows run as **validation builds** (`publish=false`). No images are published. This is intentional: it confirms that the merged code builds cleanly on `lts` before the next production release.
142+
2. The workflow runs a **pre-flight check**: fails immediately if `lts` has any commits not reachable from `main`, printing those commits with instructions to land them in `main` first.
143+
3. The workflow performs a **squash merge** (`git merge --squash origin/main`) and pushes one clean commit to `lts`. There is no PR. Triggering `workflow_dispatch` is the human approval step.
144+
4. The push triggers a `push` event on `lts` — all 5 build workflows run as **validation builds** (`publish=false`). No images are published. This confirms the promoted code builds cleanly on `lts` before the next production release.
145145

146146
**Phase 2 — Production release (automated or manual publishing):**
147147
1. `scheduled-lts-release.yml` fires at `0 2 * * 0` (Sunday 2am UTC), OR a maintainer manually triggers it
@@ -153,6 +153,8 @@ Promotion and production release are **intentionally decoupled**. There are two
153153

154154
**NEVER merge `lts` into `main`.** The flow is always one-way: `main``lts`.
155155

156+
**NEVER commit directly to `lts`.** All changes — including CI hotfixes — must land in `main` first. Direct commits to `lts` create divergence that causes the pre-flight check to fail and blocks future promotions.
157+
156158
### `publish` Input — How It Is Evaluated
157159

158160
All 5 caller workflows pass the same `publish:` expression:
@@ -263,7 +265,7 @@ If you see `schedule:` in any of the 5 build callers, remove it entirely. Do not
263265
- `build-regular-hwe.yml` — HWE kernel variant of `bluefin`
264266
- `build-dx-hwe.yml` — HWE kernel variant of `bluefin-dx`
265267
- `scheduled-lts-release.yml` — Weekly production release dispatcher (sole owner of Sunday builds)
266-
- `promote-to-lts.yml`Opens a one-way `main` `lts` promotion PR
268+
- `promote-to-lts.yml`Squash-pushes `main` into `lts` (with pre-flight divergence check)
267269
- `generate-release.yml` — Creates GitHub Release after successful GDX build on `lts`
268270

269271
## Validation Scenarios

image-versions.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ images:
22
- name: centos-bootc
33
image: quay.io/centos-bootc/centos-bootc
44
tag: c10s
5-
digest: sha256:d1a9fbd49da12d2834106a4f0707c72d18081610f525f37ed0c3e802a4fdbe11
5+
digest: sha256:226b06fa4104bed3547897f41d2a934bcc1ba8a5c587eab5c39d4a758c2d1c61
66
- name: common
77
image: ghcr.io/projectbluefin/common
88
tag: latest

0 commit comments

Comments
 (0)