Skip to content

ci(promote): replace push-based promotion with PR gate#1195

Merged
castrojo merged 1 commit intoublue-os:mainfrom
castrojo:main
Mar 17, 2026
Merged

ci(promote): replace push-based promotion with PR gate#1195
castrojo merged 1 commit intoublue-os:mainfrom
castrojo:main

Conversation

@castrojo
Copy link
Collaborator

Ok I think I got it this time, I can confirm this works via testing in my personal repo. I am likely going to force this because we need the action in the LTS branch anyway.

Agent Notes follow:

Solution

Replace with create-lts-pr.yml, a PR-gate workflow:

  • Fires on every push to main (and workflow_dispatch)
  • Uses git diff --quiet (content diff, not commit graph) to detect new content — survives squash-merges without false positives
  • Passes the commit list as a COMMIT_LIST env var and uses printf to build the PR body, safely handling commit messages containing double quotes (e.g. Revert "...")
  • Auto-creates a draft PR from mainlts, or updates the existing one
  • Maintainer squash-merges the PR as the human approval gate
  • No pre-flight check: branch protection is the guard against direct lts commits

Also fixes AGENTS.md: corrects the release schedule (cron 0 6 * * 2 = Tuesday 6am UTC, not Sunday 2am UTC) and updates all references to the old workflow.

Testing

Tested on the castrojo/bluefin-lts fork:

  • ✅ Workflow fires on push and creates draft PR correctly
  • ✅ PR body auto-updates on subsequent pushes without creating duplicate PRs
  • ✅ Commit messages with double quotes handled safely (the Revert "..." case)
  • ✅ Force-push after squash: workflow correctly updates existing PR

Assisted-by: Claude Sonnet 4.6 via GitHub Copilot

The existing promote-to-lts.yml has a fatal self-deadlock bug: after the
first successful squash-push, commit S lives on lts but not in main's graph.
Every subsequent pre-flight check (rev-list origin/lts ^origin/main) sees S
and permanently fails. Manual git surgery required after every promotion.

Replace with create-lts-pr.yml, a PR-gate workflow:
- Fires on every push to main (and on workflow_dispatch)
- Uses git diff --quiet (content diff, not commit graph) to detect new content
  and survive squash-merges without false positives
- Passes the commit list as a COMMIT_LIST env var and uses printf to build
  the PR body, safely handling commit messages that contain double quotes
- Auto-creates a draft PR from main → lts, or updates the existing one
- Maintainer squash-merges the PR as the human approval gate
- No pre-flight check needed: branch protection is the guard

Also update AGENTS.md to reflect the new workflow and correct the release
schedule (cron 0 6 * * 2 = Tuesday 6am UTC, not Sunday 2am UTC).

Tested on castrojo/bluefin-lts fork:
- Workflow fires on push and creates draft PR correctly
- PR body auto-updates on subsequent pushes without creating duplicate PRs
- Commit messages with double quotes (e.g. Revert "...") handled safely

Assisted-by: Claude Sonnet 4.6 via GitHub Copilot
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@castrojo castrojo requested a review from tulilirockz as a code owner March 17, 2026 22:12
Copilot AI review requested due to automatic review settings March 17, 2026 22:12
@castrojo castrojo merged commit 6462f99 into ublue-os:main Mar 17, 2026
16 of 18 checks passed
@github-actions github-actions bot mentioned this pull request Mar 17, 2026
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR changes the mainlts promotion mechanism from a manual squash-push workflow to an always-on PR gate, and updates the CI/CD documentation accordingly.

Changes:

  • Remove the manual promote-to-lts.yml workflow that squash-pushed directly to lts.
  • Add create-lts-pr.yml to automatically create/update a draft PR from mainlts when branch content differs.
  • Update AGENTS.md to reflect the new PR-gated promotion flow and correct the weekly release schedule wording.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 4 comments.

File Description
AGENTS.md Updates documentation to reflect PR-gated promotion and Tuesday release schedule.
.github/workflows/promote-to-lts.yml Removes the previous manual squash-push promotion workflow.
.github/workflows/create-lts-pr.yml Adds automation that opens/updates a draft mainlts promotion PR based on content diff.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +43 to +48
LIST=$(git log origin/lts..origin/main --oneline)
{
echo "list<<EOF"
echo "$LIST"
echo "EOF"
} >> "$GITHUB_OUTPUT"

if [ -n "$EXISTING" ]; then
echo "Updating existing promote PR #${EXISTING}"
printf '%s\n' "${BODY}" | gh pr edit "$EXISTING" --body-file - || true
**Phase 1 — Promotion (human-gated via PR):**
1. Every push to `main` triggers `create-lts-pr.yml`
2. The workflow checks `git diff --quiet origin/lts origin/main` (content diff, not commit graph — survives squash-merges)
3. If content differs: a draft PR from `main` → `lts` is created (or the existing one is updated with the latest commit list)
echo "No content difference between lts and main. Nothing to promote."
echo "has_diff=false" >> "$GITHUB_OUTPUT"
else
echo "has_diff=true" >> "$GITHUB_OUTPUT"
castrojo added a commit that referenced this pull request Mar 17, 2026
... and of course I messed it up, one more. :)

## Solution

Find the most-recent commit on `main` whose tree hash matches the
current `lts` tree. Since squash-merges preserve content exactly, this
is always the `main` commit that was squash-merged into `lts`. `git log`
is anchored from that point, showing only genuinely new commits
regardless of squash-merge history.

If no match is found within 500 commits (first-ever promotion), falls
back to `git diff --name-status`.

## Also fixed

- Removed `|| true` from `gh pr edit` — failures now surface visibly
instead of silently leaving the PR body stale
- Added guard: if `git diff` detects a difference but
`origin/lts..origin/main` is empty (lts is ahead/diverged), skip rather
than open a misleading empty PR

Addresses Copilot review comments from #1195.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assisted-by: Claude Sonnet 4.6 via GitHub Copilot

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
castrojo added a commit that referenced this pull request Mar 17, 2026
## Commits pending promotion to `lts`

a764cfc fix(ci): use tree-hash anchor for accurate promotion commit list
(#1197)
6462f99 ci(promote): replace push-based promotion with PR gate (#1195)
dd4152f chore(deps): update quay.io/centos-bootc/centos-bootc:c10s
docker digest to 7b1e3d1 (#1194)
1658526 chore(deps): update
system_files/usr/share/gnome-shell/extensions/search-light@icedman.github.com
digest to 4e93e0e (#1193)
aa14da4 chore(deps): update quay.io/centos-bootc/centos-bootc:c10s
docker digest to b10c380 (#1191)
1ff0c7e Revert "feat(GNOME) : gnome 49 backport" (#1192)
18bb989 chore(deps): update quay.io/centos-bootc/centos-bootc:c10s
docker digest to ff6f31c (#1185)
24765e4 feat(GNOME) : gnome 49 backport (#1187)
bc65f2a chore(deps): update
system_files/usr/share/gnome-shell/extensions/search-light@icedman.github.com
digest to e4ad180 (#1190)
914432d chore(deps): update ghcr.io/ublue-os/brew:latest docker digest
to fef8b47 (#1189)
1339bc4 chore(deps): update cgr.dev/chainguard/wolfi-base:latest docker
digest to 2a43204 (#1188)
4e13431 chore(deps): update ghcr.io/projectbluefin/common:latest docker
digest to 9409d0c (#1186)
6a0ad87 chore(deps): update cgr.dev/chainguard/wolfi-base:latest docker
digest to a9a3a0c (#1184)
8e1c75f chore(deps): update ghcr.io/projectbluefin/common:latest docker
digest to 69e0d5c (#1174)
90132e8 chore(deps): update cgr.dev/chainguard/wolfi-base:latest docker
digest to 08420c1 (#1181)
b23f809 chore(deps): update actions/download-artifact digest to 3e5f45b
(#1183)
13f9b46 chore(deps): update quay.io/centos-bootc/centos-bootc:c10s
docker digest to c2dba5f (#1182)
7316e19 chore(deps): update cgr.dev/chainguard/wolfi-base:latest docker
digest to 00f9662 (#1156)

---
_Squash-merge this PR to promote. The PR body updates automatically as
`main` advances._

---------

Co-authored-by: ubot-7274[bot] <217212047+ubot-7274[bot]@users.noreply.github.com>
Co-authored-by: James Reilly <jreilly1821@gmail.com>
Co-authored-by: Jorge O. Castro <jorge.castro@gmail.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
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.

2 participants