Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .github/workflows/back-merge.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ name: Back-merge
# After a release on main, sync main back into next so its changelog, manifest,
# and version bumps do not drift. No conflict -> push next directly (the App is
# an "always" bypass actor on next). Conflict -> open a PR for a human.
# Any other failure -> open a tracking issue so the drift is never silent.

on:
release:
Expand Down Expand Up @@ -50,3 +51,17 @@ jobs:
--body "Automated back-merge hit conflicts (CHANGELOG / manifest / version files). Resolve manually, then merge into next." \
--repo "${{ github.repository }}"
fi

# Never let a back-merge fail silently: a rejected push or any other error
# opens a tracking issue so a human resyncs main into next.
- name: Open tracking issue on failure
if: failure()
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: |
gh issue create \
--repo "${{ github.repository }}" \
--title "Back-merge main into next failed (run ${{ github.run_id }})" \
--label "back-merge-failed" \

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Create the back-merge failure label before using it

In repos synced from the canonical .github/labels.yml, back-merge-failed is not defined, and gh issue create resolves label IDs before creating the issue; when this failure path runs with the missing label, the command aborts and the trailing || echo masks 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 👍 / 👎.

--body "The automated back-merge of \`main\` into \`next\` failed, so \`next\` is drifting from the latest release. Resync manually by opening a PR from \`main\` into \`next\`. Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" \
|| echo "issue creation failed; check the run logs"
49 changes: 49 additions & 0 deletions .github/workflows/promote.yml
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)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Treat an empty promote lookup as missing

When no next -> main PR is already open, the jq expression over an empty list yields null, which is non-empty to [ -z "$PR" ]; the workflow then skips gh pr create and tries to merge PR null. That makes the first/manual promote run fail before it can open the PR, so coerce the query to an empty string (for example with .[0].number // "") or test for null explicitly.

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Use the ruleset bypass when merging promote PRs

With the checked main ruleset, main still requires one CODEOWNERS approval, and this repo's existing release-PR path documents that plain gh pr merge is refused by the branch policy even for the bot App (.github/workflows/ci.yml:77-89). gh pr merge --auto only merges after required reviews/checks are satisfied, so a PR created by this workflow will remain blocked waiting for approval instead of self-merging after CI; add an approval path or use the same admin/bypass merge mechanism intentionally.

Useful? React with 👍 / 👎.

2 changes: 1 addition & 1 deletion .release-please-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@
"plugins/aidd-pm": "2.1.0",
"plugins/aidd-orchestrator": "2.1.0",
"plugins/aidd-refine": "2.1.0",
"plugins/aidd-ui": "4.0.0"
"plugins/aidd-ui": "0.1.0-alpha.0"
}
58 changes: 58 additions & 0 deletions docs/RELEASE.md
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.
2 changes: 1 addition & 1 deletion plugins/aidd-ui/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
"name": "aidd-ui",
"version": "4.0.0",
"version": "0.1.0-alpha.0",
"description": "ALPHA, not ready for use. UI and UX concern for the AI-Driven Development framework. Use when the user wants to design, review, or improve a frontend interface. Do NOT use for backend-only or non-UI tasks.",
"author": {
"name": "AI-Driven Dev",
Expand Down
18 changes: 0 additions & 18 deletions plugins/aidd-ui/CHANGELOG.md
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))
1 change: 1 addition & 0 deletions release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
},
"plugins/aidd-ui": {
"package-name": "aidd-ui",
"release-as": "0.1.0-alpha.0",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Include aidd-ui in the release artifact matrix

This pin forces plugins/aidd-ui into the next release, but the only per-plugin artifact job still iterates the six older plugins in .github/workflows/ci.yml:176-184 and omits aidd-ui. When release-please publishes an aidd-ui tag, no matrix cell uploads /tmp/aidd-ui-v...zip, so that GitHub release is created without its installable bundle; add aidd-ui to the matrix before forcing the release.

Useful? React with 👍 / 👎.

"extra-files": [
{
"type": "json",
Expand Down