Skip to content

feat(release): prepare ASF npm candidates - #3335

Merged
M4n5ter merged 7 commits into
apache:mainfrom
M4n5ter:feat/asf-npm-candidate
Aug 22, 2026
Merged

feat(release): prepare ASF npm candidates#3335
M4n5ter merged 7 commits into
apache:mainfrom
M4n5ter:feat/asf-npm-candidate

Conversation

@M4n5ter

@M4n5ter M4n5ter commented Aug 20, 2026

Copy link
Copy Markdown
Member
English

Summary

  • add a credential-free, upstream-only workflow that prepares one unsigned npm convenience candidate from the exact ASF source RC reference;
  • reuse the immutable CLI validation matrix and carry the same tarball through Linux, macOS, Windows, and Eval checks;
  • generate the ASF-specific SHA-512 sidecar only at handoff, then write a closed record binding the tarball bytes to the source reference, commit, repository, workflow run, and attempt;
  • reject fork provenance and partial job re-runs, and revalidate the live tag target and main ancestry immediately before upload;
  • document the Release Manager handoff and the boundary around tag-signature authentication, voting, credentials, and publication.

Trust boundary

The Release Manager and source-release process remain the sole authority for deciding that a source RC tag is signed by a key in the trusted ASF KEYS material. This workflow pins the selected annotated tag, commit, and validated npm bytes; it does not authenticate the tag signature or establish source-release approval.

A partial job re-run is intentionally rejected because it could combine authorization and artifact facts from different workflow attempts. Use Re-run all jobs instead.

Scope and dependency

This is the first, non-publishing slice of G8. It depends on #3222 for unified product identity, npm package construction, and the reusable validation workflow.

The workflow does not sign artifacts, call npm staging or publication, modify dist-tags, or claim that the source release has passed either required vote. Those requirements remain tracked in #3275.

Refs #3275.

Verification

  • node --test scripts/asf-npm-candidate.test.mjs scripts/asf-npm-workflow-policy.test.mjs
  • mise exec go -- go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7 .github/workflows/asf-npm-candidate.yml .github/workflows/cli-package-validation.yml
  • npm run build
  • npm run format:check
  • npm run lint
  • npm run check:release
  • real npm tarball creation, confirmation that the generic pack emits no SHA-512, ASF record creation, and independent verification
  • npm run release:cli:smoke
简体中文

概述

  • 新增无凭据、仅允许上游仓库运行的工作流,从精确的 ASF 源码 RC reference 准备唯一的未签名 npm convenience candidate;
  • 复用不可变 CLI 验证矩阵,让同一份 tarball 通过 Linux、macOS、Windows 和 Eval 检查;
  • 只在 ASF handoff 边界生成 SHA-512,并写入闭合记录,将 tarball 字节绑定到源码 reference、commit、仓库、workflow run 和 attempt;
  • 拒绝 fork provenance 和部分 job 重跑,并在上传前重新验证 live tag target 与 main ancestry;
  • 记录 Release Manager 交接流程,明确 tag 签名认证、投票、凭据和发布的职责边界。

信任边界

只有 Release Manager 和 source-release 流程有权判断 source RC tag 是否由可信 ASF KEYS 中的密钥签名。该工作流只固定所选 annotated tag、commit 和已经验证的 npm 字节;它不会认证 tag 签名,也不会建立源码 release 已获批准的事实。

部分 job 重跑会混合不同 workflow attempt 的 authority 与 artifact 事实,因此被刻意拒绝;应使用 Re-run all jobs

范围与依赖

这是 G8 的第一个非发布阶段。它依赖 #3222 提供统一产品身份、npm 包构建和可复用验证工作流。

该工作流不签名、不调用 npm staging 或发布、不修改 dist-tag,也不声称源码 release 已通过任一必要投票。其余要求继续由 #3275 跟踪。

Refs #3275

验证

  • node --test scripts/asf-npm-candidate.test.mjs scripts/asf-npm-workflow-policy.test.mjs
  • mise exec go -- go run github.com/rhysd/actionlint/cmd/actionlint@v1.7.7 .github/workflows/asf-npm-candidate.yml .github/workflows/cli-package-validation.yml
  • npm run build
  • npm run format:check
  • npm run lint
  • npm run check:release
  • 实际 npm tarball 构建、确认通用 pack 不生成 SHA-512、ASF record 生成以及独立验证
  • npm run release:cli:smoke

@M4n5ter
M4n5ter force-pushed the feat/1510-unify-product-release branch from 929f2a1 to 8875c17 Compare August 21, 2026 07:13
@M4n5ter
M4n5ter force-pushed the feat/asf-npm-candidate branch from b8b8f52 to f43376a Compare August 21, 2026 07:16
@M4n5ter
M4n5ter force-pushed the feat/1510-unify-product-release branch from 2a867aa to 38ef63e Compare August 21, 2026 09:05
@M4n5ter
M4n5ter force-pushed the feat/1510-unify-product-release branch 2 times, most recently from 0404d02 to 5d77994 Compare August 21, 2026 13:51
@M4n5ter
M4n5ter deleted the branch apache:main August 21, 2026 14:35
@M4n5ter M4n5ter closed this Aug 21, 2026
@M4n5ter M4n5ter reopened this Aug 21, 2026
@M4n5ter
M4n5ter changed the base branch from feat/1510-unify-product-release to main August 21, 2026 14:44
@M4n5ter
M4n5ter force-pushed the feat/asf-npm-candidate branch from f43376a to 08c449a Compare August 21, 2026 14:45
@M4n5ter
M4n5ter marked this pull request as ready for review August 22, 2026 01:41
@M4n5ter
M4n5ter requested review from Astro-Han and jackwener August 22, 2026 01:48
@M4n5ter
M4n5ter force-pushed the feat/asf-npm-candidate branch from fe27354 to cd0bca6 Compare August 22, 2026 05:53
Add a credential-free handoff that builds and validates one immutable npm tarball from the exact ASF source release candidate. The recorded provenance and SHA-512 checksum support release review while deliberately keeping signing, approval, and npm publication outside this workflow.
Reject fork identities and partial workflow reruns so every handoff record describes one upstream run attempt and its exact validated bytes. Keep source-tag authentication with the Release Manager, and generate ASF-specific SHA-512 metadata only at the handoff boundary.
Give ASF npm candidate mechanics a dedicated CI selection lane so changes to their scripts and workflows cannot bypass the contract tests. Shared CLI validation remains owned by both release surfaces.\n\nDerive release identity from one exact source tag and keep rerun authority with the validation artifact while the handoff independently revalidates the live tag.
Make the source candidate tag the sole version authority at the handoff boundary. This removes an unreachable tag/version mismatch state and the mirror contracts that existed only to keep both representations aligned, while preserving independent verification of external candidate records.
Derive the ASF npm candidate tag and commit directly from the selected workflow ref. This removes duplicated operator input and cross-job state while retaining tag identity, ancestry, attempt, and live-reference validation.
The lightweight ASF npm contract suite does not need its own affected-path authority. Running it with the existing dependency-free core checks removes planner state and routing tests while preserving all candidate validation coverage.
@M4n5ter
M4n5ter force-pushed the feat/asf-npm-candidate branch from 1221466 to d268ed7 Compare August 22, 2026 07:55

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for making the npm candidate handoff reproducible and for simplifying the CI planner so the contract actually runs on this head. The hosted test, audit, and package checks are all green. I found one non-blocking product-identity seam that should be consolidated before this release path becomes authority, noted inline.

AI-assisted review disclosure: OpenAI Codex coordinated independent release-contract and packaging reviews, including an adversarial exact-head recheck. I verified the retained finding, rejected the unsupported provenance concern, and checked the live CI and review state before making the final decision.

Comment thread scripts/asf-npm-candidate.mjs Outdated
Validate ASF npm candidates through the shared root, Desktop, and CLI manifest authority before binding them to a source RC. This prevents candidate records from accepting additional public commands or a divergent product version.
@M4n5ter
M4n5ter requested a review from Astro-Han August 22, 2026 09:19

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks @M4n5ter — reviewed at exact head efe48ad65a966058a9a2fb40aa0c7917137564f1. No P0–P2 findings; approving.

What was checked

The release contract chain is closed end to end: tag ref → annotated tag object → tag commit equals GITHUB_SHA → that commit is an ancestor of main → the reusable workflow builds one tarball from that same commit → all four platform jobs and Eval consume that single artifact → the handoff record binds SHA-256/SHA-512, source tag and commit, run ID and attempt, and re-validates the live tag before upload.

  • Version authority is single-sourced. Root, Desktop and CLI manifests resolve through one path; the CLI surface is restricted to the public maka command. Tarball naming, version and record consistency are all validated rather than assumed.
  • No publish capability is introduced. asf-npm-candidate.yml declares permissions: contents: read at both workflow and job level, with no id-token, no registry auth, no npm publish and no dist-tag mutation. Signing and the release vote stay outside candidate preparation and are documented as human gates in the runbook — the right boundary for an ASF release candidate.
  • Failure, rerun and concurrency paths hold. Runs serialize on the same ref; the handoff requires the validation run attempt to match the current attempt; the job fails closed if the tag is moved, is no longer an annotated tag, or no longer resolves to a commit reachable from main.
  • No parallel CI authority. check:asf-npm runs unconditionally, and the CLI validation workflow keeps using the existing tarball builder rather than introducing a second build path. The ci-test-plan changes only assign ownership for the new files.
  • Existing pack tooling continues to own staging, third-party notices, production-dependency audit, file manifest and artifact metrics; the candidate script recomputes SHA-256/SHA-512 and refuses to overwrite an existing sidecar or record.

Verification

34 focused tests green in a read-only worktree at the exact head (ASF npm candidate, workflow policy, CI test plan); actionlint clean; git diff --check clean. Required checks at this head: audit, package and test all SUCCESS.

mergeStateStatus=BLOCKED / reviewDecision=REVIEW_REQUIRED at the time of writing reflects the independent-approval gate, not a code finding.


This review was AI-assisted. It is not a substitute for independent human review by a committer.

@M4n5ter
M4n5ter merged commit 2e8cd03 into apache:main Aug 22, 2026
3 checks passed
@M4n5ter
M4n5ter deleted the feat/asf-npm-candidate branch August 22, 2026 09:42
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