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
277 changes: 94 additions & 183 deletions plugins/magpie-release-management/skills/announce-draft/SKILL.md

Large diffs are not rendered by default.

204 changes: 76 additions & 128 deletions plugins/magpie-release-management/skills/archive-sweep/SKILL.md

Large diffs are not rendered by default.

257 changes: 96 additions & 161 deletions plugins/magpie-release-management/skills/audit-report/SKILL.md

Large diffs are not rendered by default.

213 changes: 79 additions & 134 deletions plugins/magpie-release-management/skills/keys-sync/SKILL.md

Large diffs are not rendered by default.

234 changes: 86 additions & 148 deletions plugins/magpie-release-management/skills/prepare/SKILL.md

Large diffs are not rendered by default.

106 changes: 41 additions & 65 deletions plugins/magpie-release-management/skills/prepare/automated-signing.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,79 +3,58 @@

# Step A — Automated release signing setup (sub-command: `automated-signing`, 🪶 ASF-specific)

> **Scope.** Only for a project whose organization offers it: the
> organization manifest key `release_process.automated_signing`,
> resolved `project.md` → organization manifest → framework default
> (not offered). The option is an ASF Infra offering
> ([Infra § Automated release signing](https://infra.apache.org/release-signing.html#automated-release-signing))
> and only [`organizations/ASF/organization.md`](../../../../organizations/ASF/organization.md)
> sets the key; where it resolves to `null` or unset, Step 0 blocks and
> the flow is not described. Those adopters keep the RM-key flow.

A one-time, version-less **drafting** step. Under the policy an ASF
project may let CI sign the artefacts it builds with an
Infra-provisioned key **provided that** every signed artefact is built
reproducibly, CI deploys to staging only, and a committer re-validates
every artefact **bit-by-bit identical on trusted hardware** before
publication; the Apache Security Team approves the workflow before use.
> **Scope.** Only for a project whose organization offers it: the organization manifest key `release_process.automated_signing`,
> resolved `project.md` → organization manifest → framework default (not offered).
> The option is an ASF Infra offering ([Infra § Automated release signing](https://infra.apache.org/release-signing.html#automated-release-signing))
> and only [`organizations/ASF/organization.md`](../../../../organizations/ASF/organization.md) sets the key;
> where it resolves to `null` or unset, Step 0 blocks and the flow is not described.
> Those adopters keep the RM-key flow.

A one-time, version-less **drafting** step.
Under the policy an ASF project may let CI sign the artefacts it builds with an Infra-provisioned key **provided that**:
every signed artefact is built reproducibly, CI deploys to staging only,
and a committer re-validates every artefact **bit-by-bit identical on trusted hardware** before publication;
the Apache Security Team approves the workflow before use.
Background:
[`docs/release-management/reproducibility.md` § Automated release signing](../../../../docs/release-management/reproducibility.md#automated-release-signing--asf-specific-optional).

## A1 — Eligibility gate

All of the following, else stop and list what is missing:

- `release_process.automated_signing` is set (`project.md` →
organization manifest → framework default; Step 0 checked it).
- `release-build.md` → `source_archive_method: git-archive`,
`reproducibility_source: on`, and `reproducibility_binaries:
byte-identical` for every convenience binary in `expected_artefacts`
(or none).
- The most recent RC's `release-verify-rc` report on its planning issue
shows Step 9 `PASS` with every artefact `identical`. If no such report
exists the build is not *demonstrably* reproducible yet: tell the RM
to cut and verify one RC with the checks on first.
- `release_vote_backend: atr` or `release_dist_backend: atr` — ATR
trusted publishing is the staging target the workflow template uses.
- `release_process.automated_signing` is set (`project.md` → organization manifest → framework default; Step 0 checked it).
- `release-build.md` → `source_archive_method: git-archive`, `reproducibility_source: on`,
and `reproducibility_binaries: byte-identical` for every convenience binary in `expected_artefacts` (or none).
- The most recent RC's `release-verify-rc` report on its planning issue shows Step 9 `PASS` with every artefact `identical`.
If no such report exists the build is not *demonstrably* reproducible yet: tell the RM to cut and verify one RC with the checks on first.
- `release_vote_backend: atr` or `release_dist_backend: atr` — ATR trusted publishing is the staging target the workflow template uses.

## A2 — Draft the Infra Jira ticket

Draft (never file) an `INFRA` ticket titled *"CI release signing key
for Apache <PROJECT>"* that: requests the key per the policy (4096-bit
RSA, signing-only, private half held by infra-root, public block to
`KEYS`, encrypted revocation certificate to the project's private
repo); names the workflow (`ci_release_workflow`) and the staging
target (ATR via `apache/tooling-actions/upload-to-atr`, pinned by
commit SHA); **highlights the trusted-hardware validation step** —
`release-verify-rc` Step 9 with `--trusted-hardware`, `repro-archive
compare --require-identical` for every artefact, recorded on the
planning issue, gating `release-promote`; and references the
background ticket in
`release_process.automated_signing.key_request_background`.
Draft (never file) an `INFRA` ticket titled *"CI release signing key for Apache <PROJECT>"* that:
- requests the key per the policy (4096-bit RSA, signing-only, private half held by infra-root, public block to `KEYS`, encrypted revocation certificate to the project's private repo);
- names the workflow (`ci_release_workflow`) and the staging target (ATR via `apache/tooling-actions/upload-to-atr`, pinned by commit SHA);
- **highlights the trusted-hardware validation step** — `release-verify-rc` Step 9 with `--trusted-hardware`,
`repro-archive compare --require-identical` for every artefact, recorded on the planning issue, gating `release-promote`;
- references the background ticket in `release_process.automated_signing.key_request_background`.

## A3 — Draft the Security Team notification

Draft (never send — [spec § Boundary 3](../../../../docs/release-management/spec.md#boundary-3-agent-never-sends-mail-to-dev-users-announce))
a mail to `release_process.automated_signing.approval_body`
(`security@apache.org`) from the RM, pointing at the ticket, the
workflow PR and the validation step, asking for the approval the
policy requires before the workflow is used. Plain text, real links,
per the repository's email rules.
a mail to `release_process.automated_signing.approval_body` (`security@apache.org`) from the RM,
pointing at the ticket, the workflow PR and the validation step, asking for the approval the policy requires before the workflow is used.
Plain text, real links, per the repository's email rules.

## A4 — Propose the workflow PR

From
[`projects/_template/workflows/release-candidate.yml`](../../../magpie-setup/templates/workflows/release-candidate.yml),
rendered with the project's slug, artefact prefix, source format and
`build_command`, placed at `ci_release_workflow`. The template builds
the source archive with the embedded `repro-archive` script (copy
`tools/reproducible-archive/src/reproducible_archive/__init__.py` to
`release/reproducible_archive.py` in the upstream repo), builds
binaries under `SOURCE_DATE_EPOCH`, builds twice and compares,
checksums with sha512 only, and uploads to ATR with OIDC. It contains
**no key material and no signing step**; the signing mechanism is what
Infra agrees on the ticket. Pin every action to a commit SHA. Open as a
draft PR via `gh pr create --web` after RM confirmation.
From [`projects/_template/workflows/release-candidate.yml`](../../../magpie-setup/templates/workflows/release-candidate.yml),
rendered with the project's slug, artefact prefix, source format and `build_command`, placed at `ci_release_workflow`.
The template builds the source archive with the embedded `repro-archive` script
(copy `tools/reproducible-archive/src/reproducible_archive/__init__.py` to `release/reproducible_archive.py` in the upstream repo),
builds binaries under `SOURCE_DATE_EPOCH`, builds twice and compares, checksums with sha512 only, and uploads to ATR with OIDC.
It contains **no key material and no signing step**; the signing mechanism is what Infra agrees on the ticket.
Pin every action to a commit SHA.
Open as a draft PR via `gh pr create --web` after RM confirmation.

<!-- BEGIN MAGPIE BLOCK: pre-pr-adversarial-review — generated from tools/dev/blocks/pre-pr-adversarial-review.md -->

Expand Down Expand Up @@ -152,13 +131,10 @@ reviewers reported each, and every entry in `warnings` verbatim.

## A5 — Propose the config diff

`release-management-config.md § Signing`: `automated_release_signing:
requested`, `ci_release_workflow`, `ci_signing_infra_ticket` (once the
ticket exists). Tell the RM that `enabled` is set only after Infra has
provisioned the key, its public block is in `KEYS`
(`release-keys-sync`), the Security Team has approved, and the workflow
PR is merged — and that from then on `release-rc-cut` emits the tag
push instead of local signing, `release-verify-rc` Step 9 is mandatory,
`release-management-config.md § Signing`: `automated_release_signing: requested`, `ci_release_workflow`, `ci_signing_infra_ticket` (once the ticket exists).
Tell the RM that `enabled` is set only after Infra has provisioned the key, its public block is in `KEYS` (`release-keys-sync`),
the Security Team has approved, and the workflow PR is merged.
From then on `release-rc-cut` emits the tag push instead of local signing, `release-verify-rc` Step 9 is mandatory,
and `release-promote` blocks without the attestation.

Return ONLY valid JSON with this structure:
Expand All @@ -177,5 +153,5 @@ Return ONLY valid JSON with this structure:
}
```

`filed_or_sent` is always `false`: the skill drafts the ticket and the
mail and proposes the PR; the RM files, sends and marks ready.
`filed_or_sent` is always `false`: the skill drafts the ticket and the mail and proposes the PR;
the RM files, sends and marks ready.
40 changes: 14 additions & 26 deletions plugins/magpie-release-management/skills/prepare/plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,11 @@ git ls-remote --tags https://github.com/<upstream>.git > <tags.txt>
python3 <skill-dir>/scripts/prev_tag.py --tags <tags.txt> --version <version> --train <train-pattern>
```

`<train-pattern>` comes from `release-trains.md` (e.g. `2.x`); add
`--tag-prefix <ns>/` for namespaced tags. `previous_tag` is the highest
final release tag below `<version>` in the train (the same major when no
train is given), skipping release candidates and other pre-releases;
when `null`, ask the RM.
`<train-pattern>` comes from `release-trains.md` (e.g. `2.x`); add `--tag-prefix <ns>/` for namespaced tags.
`previous_tag` is the highest final release tag below `<version>` in the train (the same major when no train is given),
skipping release candidates and other pre-releases; when `null`, ask the RM.

**Empty-set hand-off.** If the merged-PR set is empty and
`--skip-empty-check` was not passed, return:
**Empty-set hand-off.** If the merged-PR set is empty and `--skip-empty-check` was not passed, return:

```json
{
Expand All @@ -40,18 +37,14 @@ when `null`, ask the RM.
}
```

Do not proceed to the planning issue draft when `empty_pr_set` is
`true`.
Do not proceed to the planning issue draft when `empty_pr_set` is `true`.

## 1b — Draft the planning issue body

Compose the planning issue body using:

- `release_planning_issue_template` from config (path under
`<project-config>/`), if present; otherwise use the default template
below.
- The version, release train, release branch, previous tag, and the
merged-PR set.
- `release_planning_issue_template` from config (path under `<project-config>/`), if present; otherwise the default template below.
- The version, release train, release branch, previous tag, and the merged-PR set.

Default planning issue template:

Expand Down Expand Up @@ -103,23 +96,19 @@ Default planning issue template:
- [ANNOUNCE] sent: (TBD)
```

Present the draft issue title and body to the RM. Ask for
confirmation before creating the issue.
Present the draft issue title and body to the RM.
Ask for confirmation before creating the issue.

Proposed issue title: `Release <Product Name> <version>`

If the RM confirms, write the body to a temp file (the planning issue body
is internally-generated content, not attacker-controlled, but using
`--body-file` avoids shell-quoting edge cases with multi-line bodies):
If the RM confirms, write the approved body to `<scratch>/planning-issue-body-<version>.md` with the Write tool
(`<scratch>` is the session scratch directory as an absolute path) and create the issue with a plain `gh` call:

```bash
cat > /tmp/planning-issue-body-<version>.md <<'EOF'
<body>
EOF
gh issue create \
--repo <upstream> \
--title "Release <Product Name> <version>" \
--body-file /tmp/planning-issue-body-<version>.md \
--body-file <scratch>/planning-issue-body-<version>.md \
--label "release-planning"
```

Expand All @@ -136,6 +125,5 @@ Return ONLY valid JSON with this structure:
}
```

`proposed` is always `true` at the point this JSON is returned — the
issue has not yet been created. Creation happens only after the RM's
explicit confirmation in the conversation.
`proposed` is always `true` at the point this JSON is returned — the issue has not yet been created.
Creation happens only after the RM's explicit confirmation in the conversation.
31 changes: 13 additions & 18 deletions plugins/magpie-release-management/skills/prepare/post.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,28 +9,23 @@
python3 <skill-dir>/scripts/next_dev_version.py --version <version> --config <project-config>/release-management-config.md
```

The script reads `version_manifest_files` from the resolved config and
reports on those files. Python packaging files (`pyproject.toml`,
`setup.cfg`, `setup.py`, and a `*.py` file only because it is a
configured version file) get `2.12.0.dev0` and Maven `pom.xml`
`2.12.0-SNAPSHOT` (minor bump from `2.11.0`). For `Cargo.toml`, unknown
formats, and any file passed that is not in `version_manifest_files`
(listed under `not_configured`), `next_dev_version` is `null` with
`needs_rm_confirmation`: surface the current string and ask the RM to
confirm the replacement before substituting.

If the project uses a different next-version convention (e.g. patch
bump rather than minor bump), the RM supplies the correct next version
via the conversation before the PR is opened.
The script reads `version_manifest_files` from the resolved config and reports on those files.
Python packaging files (`pyproject.toml`, `setup.cfg`, `setup.py`, and a `*.py` file only because it is a configured version file) get `2.12.0.dev0`,
and Maven `pom.xml` gets `2.12.0-SNAPSHOT` (minor bump from `2.11.0`).
For `Cargo.toml`, unknown formats, and any file passed that is not in `version_manifest_files` (listed under `not_configured`),
`next_dev_version` is `null` with `needs_rm_confirmation`:
surface the current string and ask the RM to confirm the replacement before substituting.

If the project uses a different next-version convention (e.g. patch bump rather than minor bump),
the RM supplies the correct next version via the conversation before the PR is opened.

## 14b — Compose the post-release bump PR

The bump PR touches only the files listed in `version_manifest_files`.
It does not touch changelogs, `NOTICE`, or `LICENSE`.

**Scope enforcement.** If a proposed file path falls outside
`version_manifest_files`, flag it as a scope violation and ask the RM
to confirm before including it.
**Scope enforcement.** If a proposed file path falls outside `version_manifest_files`,
flag it as a scope violation and ask the RM to confirm before including it.

<!-- BEGIN MAGPIE BLOCK: pre-pr-adversarial-review — generated from tools/dev/blocks/pre-pr-adversarial-review.md -->

Expand Down Expand Up @@ -121,8 +116,8 @@ Files updated: <version_manifest_files as bullet list>
Generated by `release-prepare` (magpie-release-prepare).
```

Present the PR title, body, and file scope to the RM. Ask for
confirmation before opening the PR.
Present the PR title, body, and file scope to the RM.
Ask for confirmation before opening the PR.

Return ONLY valid JSON with this structure:

Expand Down
Loading