Skip to content

Add release-mageos orchestration skill - #351

Draft
marcelmtz wants to merge 1 commit into
mage-os:mainfrom
marcelmtz:feat/release-orchestration-skill
Draft

Add release-mageos orchestration skill#351
marcelmtz wants to merge 1 commit into
mage-os:mainfrom
marcelmtz:feat/release-orchestration-skill

Conversation

@marcelmtz

Copy link
Copy Markdown
Contributor

Draft — opening for feedback on shape and scope before polishing.

Adds a release-mageos skill that sequences the existing release skills (analyze-release-preview, add-release-history, audit-release-branches, prep-release-prs, summarize-release-status) behind preflight gates and artifact-level verification.

The motivation is the 3.4.0 release: most of the elapsed time went into re-deriving things that are mechanically checkable, and a few of the ordering rules only existed in people's heads.

What it adds

scripts/preflight.sh — blocking gates

Gate Blocks when
1 The previous release's history files are not merged. Building without them makes the previous release's packages drift on rebuild.
2 The target tag already exists (re-release guard).
3 The target version is already published.
4 The supported-version matrix lacks the target, or dist/index.js was not rebuilt to contain it.
5 The active gh account has no write access.

Plus a bundled-repo survey, explicitly labelled a hint rather than evidence — see below.

scripts/verify-packages.php — what actually shipped

Downloads both releases' package archives, hashes both trees, and diffs ignoring composer.json.

This exists because git compare <tag>...main is unreliable here. push-release-tag.yml creates a Release X.Y.Z commit that is not on main, so tags sit on a diverged lineage and already-shipped commits report as "ahead". During 3.4.0 this made mageos-magento-zend-db (5 ahead) and mageos-magento-zend-pdf (3 ahead) look like they carried unshipped fixes; diffing the published zips showed only a workflow file and a version bump.

SKILL.md

Phases, the three human gates (go/no-go, copy review, publish ordering), and the traps: per-repo fork remote layout, dual gh accounts, composer audit.block-insecure, the installation-check matrix never covering the version being released, and isolated patches not moving the upstream version.

Verification

Both scripts were tested against 3.4.0 as a known-answer fixture.

verify-packages.php 3.3.0 3.4.0 reproduces the manual analysis exactly — the 6 module-cms files, module-review/Controller/Adminhtml/Product/Save.php, module-customer/Controller/Account/Edit.php, and the 2 module-catalog files from #318 — with an unrelated package returning identical as a control.

Testing preflight.sh against the same fixture found three bugs, all fixed in this branch:

  • Gate 3 grepped "version":"3.4.0" against the p2 payload and silently passed on an already-published version. Now parses the JSON.
  • The repo survey joined all commit subjects into one string before filtering, so a single Sansec commit masked everything else — it labelled mageos-magento2 "infra only" while it contained both Add new packages from repo.magento.com #318 and Mage-OS 3.0 prep: merge release/3.x into main #320. Now filters per commit.
  • Gate 5 interpolated a raw 403 body into the failure message.

Deliberately not automated

Porting Adobe isolated patches, publishing anything, and severity/urgency framing. During 3.4.0 the draft notes claimed all three fixes required an authenticated admin session, which was wrong — one is a storefront controller, and Adobe rates the top issue PR:N. @rhoerr caught it in review. A generator would have produced the same sentence just as confidently, so the skill documents the check (look at the controller namespace) rather than pretending to make the judgement.

Open questions

  1. Scope — this encodes knowledge about mage-os/github-actions and mage-os/mage-os-org too. Reasonable here, or should it live somewhere shared?
  2. Build dispatch — Phases 2 and 5 are documented procedure, not scripted. Worth scripting the dispatch-and-wait, or is a human watching the build the right call?
  3. Repo listpreflight.sh hardcodes the bundled repos. Could derive them from packages-config.js instead; happy to do that if preferred.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AxvB8dNevCJK39SxnVWrNK

Sequences the existing release skills behind preflight gates and
artifact-level verification, so the ordering rules and known traps are
checked rather than remembered.

scripts/preflight.sh blocks a build when:
  - the previous release's history files are not merged (they gate the
    build; without them the previous release's packages drift on rebuild)
  - the target tag already exists, or the version is already published
  - the supported-version matrix lacks the target, or dist/index.js was
    not rebuilt to contain it
  - the active gh account has no write access

scripts/verify-packages.php diffs the built archives of two releases,
ignoring composer.json. Release tags sit on a diverged lineage, so
`git compare <tag>...main` reports already-shipped commits as ahead;
comparing published zips is the only reliable signal. Verified against
3.3.0 -> 3.4.0: reproduces the 9 files from mage-os#320 and mage-os#318, and confirms
zend-db/zend-pdf carried no PHP changes despite showing as ahead.

SKILL.md documents the phases, the three human gates (go/no-go, copy
review, publish ordering), and the traps: fork remote layout differing
per repo, the dual gh accounts, composer audit.block-insecure, the
installation-check matrix never covering the version being released,
and isolated patches not moving the upstream version.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AxvB8dNevCJK39SxnVWrNK

`publish_tag: true` triggers `push-release-tag.yml`, which creates and pushes the version tag in every source repo. **There is no manual tagging step.**

The deploy job is gated to `["vinai", "rhoerr", "marcelmtz", "mage-os-ci"]`.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This will get stale over time, should be left out

**This repo is forked.** Verify remotes before branching:

- `origin` → the user's fork (`marcelmtz/mage-os-org`)
- `source` → upstream (`mage-os/mage-os-org`) — note it is **not** called `upstream`

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

These won't be true for everyone -- but probably works for this purpose. Maybe we can make the remote aliases more generic.

echo "Survey — repos with commits since $PREV (HINT ONLY, not evidence)"

if [[ -n "$PREV" ]]; then
REPOS=(mageos-magento2 mageos-inventory mageos-magento2-page-builder mageos-security-package

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is there a simple/realistic way we can derive the list?

@melindash

melindash commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

@marcelmtz
I’ve been working in adjacent territory and hit several of the same things — mostly wanted to flag the overlap before I go further.

On open question 3 (deriving the bundled repos rather than hardcoding). I have this working. Reading packageDirs / packageIndividual out of packages-config.js and each package’s own composer.json at a given ref gives 380 packages across the build repos, and it can’t drift from what the build produces because it’s the same config. Happy to hand that over or extract it, whichever is more useful.

On the tag lineage. You found this when 3.4.0 went sideways; I ran into it separately, and it’s structural rather than a one-off. Every release from 2.2.2 to 3.4.0 is a one-off Release X.Y.Z commit sitting on top of main rather than on a branch — tag 3.4.0’s parent is main’s current head. So those “ahead” counts on the Zend forks were never going to be right, and comparing the published archives instead is the correct way round. I ended up at the same approach for something unrelated: hash both trees, ignore composer.json.

Question: You list porting Adobe isolated patches under, "deliberately not automated," and the reasoning (the severity framing in the 3.4.0 notes) is fair. I’ve been treating the path rewriting as separable from the judgement: vendor/magento/module-cms/… → app/code/Magento/Cms/… is a table lookup against packages-config.js, and it holds for 98.4% of the 1138 Open Source patches in quality-patches.

Where I’ve drawn the line is that the tooling refuses to decide two things and reports them instead: a hunk that won’t apply because we already fixed it another way (underscore.js in APSB26–92, which #320 also skipped), and a composer.json dependency an isolated patch structurally can’t express. Does that match where you’d put it, or would you keep the whole port manual?

Context: I’m looking at whether we could support two release lines rather than one, and your gates are a big part of what would make that affordable — halving the manual re-derivation per release matters a lot more when there are twice as many releases. Writing that up separately; will link here.

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.

3 participants