-
Notifications
You must be signed in to change notification settings - Fork 14
ci: harden release flow, pin and reset aidd-ui #368
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,49 @@ | ||
| name: Promote next to main | ||
|
|
||
| # One intuitive button to ship `next` to `main` the RIGHT way: a rebase-merge | ||
| # that preserves every conventional commit, so commitlint passes per commit and | ||
| # release-please reads the scopes to bump each plugin. A squash here collapses | ||
| # the commits into one (often non-conventional) message and breaks both, which | ||
| # is exactly the failure this workflow prevents. | ||
| # | ||
| # Run it from the Actions tab (Run workflow). It opens the next -> main PR and | ||
| # enables rebase auto-merge; CI gates it, then it merges itself. | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
|
|
||
| concurrency: | ||
| group: promote | ||
| cancel-in-progress: false | ||
|
|
||
| permissions: {} | ||
|
|
||
| jobs: | ||
| promote: | ||
| name: Open and rebase-merge next into main | ||
| runs-on: ubuntu-latest | ||
| steps: | ||
| - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 | ||
| id: app-token | ||
| with: | ||
| app-id: ${{ secrets.AIDD_BOT_APP_ID }} | ||
| private-key: ${{ secrets.AIDD_BOT_PRIVATE_KEY }} | ||
|
|
||
| - name: Open or reuse the promote PR, enable rebase auto-merge | ||
| env: | ||
| GH_TOKEN: ${{ steps.app-token.outputs.token }} | ||
| REPO: ${{ github.repository }} | ||
| run: | | ||
| set -euo pipefail | ||
| # Reuse an open next -> main PR if one exists, else open one with a | ||
| # conventional, squash-safe title. | ||
| PR=$(gh pr list --repo "$REPO" --base main --head next --state open --json number --jq '.[0].number' || true) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
When no Useful? React with 👍 / 👎. |
||
| if [ -z "$PR" ]; then | ||
| PR=$(gh pr create --repo "$REPO" --base main --head next \ | ||
| --title "chore: promote next to main" \ | ||
| --body "Automated promotion of \`next\` to \`main\`. Merged by **rebase** to preserve conventional commits for release-please. Do not squash." \ | ||
| | grep -oE '[0-9]+$') | ||
| fi | ||
| echo "Promote PR: #$PR" | ||
| # Rebase auto-merge: GitHub merges it once CI is green. Never squash. | ||
| gh pr merge "$PR" --repo "$REPO" --rebase --auto | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
With the checked Useful? React with 👍 / 👎. |
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| # Releasing | ||
|
|
||
| The release pipeline is automated. A human (or an AI agent) only triggers the | ||
| promotion; everything after that runs itself. | ||
|
|
||
| ## The flow | ||
|
|
||
| ``` | ||
| next --(promote)--> main --(release-please)--> version PR --(auto-merge)--> tags + GitHub releases | ||
| | | ||
| '--(back-merge)--> next (keeps next in sync) | ||
| ``` | ||
|
|
||
| 1. **Work lands on `next`** via normal PRs (rebase or squash into `next`, your choice). | ||
| 2. **Promote `next` to `main`.** Run the **Promote next to main** workflow (Actions tab -> Run workflow). It opens a `next -> main` PR and **rebase-merges** it. | ||
| 3. **release-please** runs on the push to `main`, opens a version PR (bumps + changelogs), and the CI **auto-merges that version PR** (`--squash --admin`). No human needed. | ||
| 4. **Tags and GitHub releases** are published per package and for the root. | ||
| 5. **Back-merge** fires on `release: published` and syncs `main` back into `next` so the changelog and version files do not drift. | ||
|
|
||
| ## The one rule: promote with REBASE, never squash | ||
|
|
||
| `next -> main` carries many conventional commits (`feat(scope):`, `fix(scope):`). | ||
| Two things depend on them: | ||
|
|
||
| - **commitlint** checks every commit message. A squash collapses them into one | ||
| subject taken from the PR title; if that title is not a valid conventional | ||
| type (e.g. `release:`), commitlint fails on `main` and **release-please is | ||
| skipped** -- no release happens. | ||
| - **release-please** reads each commit's type and scope to bump the right plugin | ||
| by the right amount. A squash hides them, so it cannot compute the versions. | ||
|
|
||
| So always use the **Promote** workflow (it rebase-merges). If you merge by hand, | ||
| use **Rebase and merge**, never **Squash**. The version PR that release-please | ||
| opens is its own single commit and is fine to squash -- that one is automated. | ||
|
|
||
| ## If a release breaks (recovery) | ||
|
|
||
| Symptom: after a promote, `main` CI is red on **Commitlint** and **Release | ||
| Please** is skipped -- usually a squashed, non-conventional promote commit. | ||
|
|
||
| 1. An admin temporarily disables the `main protection` ruleset (Settings -> | ||
| Rules), force-pushes `main` back to the commit before the bad merge, then | ||
| re-enables the ruleset. | ||
| 2. Re-run the **Promote** workflow (rebase). release-please then cuts the | ||
| release normally. | ||
|
|
||
| ## Pinning a specific version | ||
|
|
||
| To force a package to a chosen version on the next cut, set `release-as` for it | ||
| in `release-please-config.json` (deterministic, overrides any `Release-As:` | ||
| commit footer). Remove the pin afterwards so automatic bumps resume. | ||
|
|
||
| ## Back-merge failures | ||
|
|
||
| If the back-merge cannot push `next`, it opens an issue labelled | ||
| `back-merge-failed`. Resync by opening a `main -> next` PR. The root cause is the | ||
| bot app needing an `always` bypass on the `next` ruleset; align that and the | ||
| back-merge runs unattended. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1 @@ | ||
| # Changelog | ||
|
|
||
| ## [4.0.0](https://github.com/ai-driven-dev/framework/compare/aidd-ui-v0.1.0-alpha.0...aidd-ui-v4.0.0) (2026-06-30) | ||
|
|
||
|
|
||
| ### Features | ||
|
|
||
| * **aidd-ui:** scaffold alpha plugin (0.1.0-alpha.0) ([#319](https://github.com/ai-driven-dev/framework/issues/319)) ([a56792a](https://github.com/ai-driven-dev/framework/commit/a56792afb6584ba17115011721823a2439fb7759)) | ||
|
|
||
|
|
||
| ### Miscellaneous | ||
|
|
||
| * **framework:** release as 4.0.0 ([5b0fc9d](https://github.com/ai-driven-dev/framework/commit/5b0fc9d9116e37abe7ef5dbb5d06438f607475e8)) | ||
| * **framework:** trigger ci recheck after history rewrite ([391760e](https://github.com/ai-driven-dev/framework/commit/391760e19eb69fe80e098c3aefc3c527cda2169a)) | ||
|
|
||
|
|
||
| ### Refactoring | ||
|
|
||
| * conform remaining skills to the authoring contract ([#334](https://github.com/ai-driven-dev/framework/issues/334)) ([dcc232a](https://github.com/ai-driven-dev/framework/commit/dcc232a5a7a7bcdf0c477b36399fd4d412685022)) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -85,6 +85,7 @@ | |
| }, | ||
| "plugins/aidd-ui": { | ||
| "package-name": "aidd-ui", | ||
| "release-as": "0.1.0-alpha.0", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
This pin forces Useful? React with 👍 / 👎. |
||
| "extra-files": [ | ||
| { | ||
| "type": "json", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In repos synced from the canonical
.github/labels.yml,back-merge-failedis not defined, andgh issue createresolves label IDs before creating the issue; when this failure path runs with the missing label, the command aborts and the trailing|| echomasks it, leaving no tracking issue for the drift. Add the label to the canonical label list or create the issue first and label it only if the label exists.Useful? React with 👍 / 👎.