Skip to content

ci(cli): validate npm tarball across platforms - #3185

Merged
M4n5ter merged 2 commits into
mainfrom
feat/cli-cross-platform-validation
Aug 18, 2026
Merged

ci(cli): validate npm tarball across platforms#3185
M4n5ter merged 2 commits into
mainfrom
feat/cli-cross-platform-validation

Conversation

@M4n5ter

@M4n5ter M4n5ter commented Aug 18, 2026

Copy link
Copy Markdown
Member
English

Summary

Adds a read-only release gate for the npm CLI artifact introduced by #3173. The workflow builds one tarball, then tests that exact artifact on Linux (minimum and current Node), macOS arm64, and Windows x64.

The installed-product smoke runs outside the repository with an empty offline npm cache and covers both bins, Eval assets, PTY and native locks, TUI setup, Runtime Host lifecycle, and a filesystem-backed model turn. It also fails packaging when the artifact exceeds reviewed size or file-count limits.

Refs #3166

Verification

  • Release tarball pack and full installed-product smoke passed locally.
  • Release policy tests, lint, format, CLI typecheck, notice checks, and actionlint passed.
  • The aggregate check:release stopped on a local pre-existing @maka/ui stale-build timestamp; its affected checks were run individually.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: OpenAI Codex implemented the workflow, artifact policy, installed-product smoke, and tests under human direction and review.

Checklist

  • Tests cover the change and fail without it
  • Lint, format, typecheck and the affected suites pass locally

Does this PR entail a change in behavior?

  • Yes — described under Summary above
  • No
中文

概要

#3173 引入的 npm CLI 产物增加只读发布门禁。工作流只构建一次 tarball,并在 Linux(最低及当前 Node)、macOS arm64 和 Windows x64 上验证同一个产物。

安装态冒烟测试在仓库外、空离线 npm 缓存中运行,覆盖两个 bin、Eval 资源、PTY 和原生文件锁、TUI 配置、Runtime Host 生命周期,以及通过文件系统 worker 完成的受控模型回合。打包产物超过已审定的体积或文件数上限时也会失败。

Refs #3166

验证

  • 本地通过 release tarball 打包及完整安装态冒烟测试。
  • release policy 测试、lint、format、CLI typecheck、notice 检查及 actionlint 均通过。
  • 聚合命令 check:release 因本地已有的 @maka/ui 构建时间戳陈旧而停止;其受影响检查已分别通过。

AI 使用

请且仅选择一项:

  • 没有生成式工具作出实质性贡献
  • 生成式工具作出了实质性贡献

工具及范围:OpenAI Codex 在人工指导与审核下实现了工作流、产物策略、安装态冒烟测试及相关测试。

检查清单

  • 测试覆盖此变更,且在缺少该变更时会失败
  • lint、format、typecheck 和受影响测试套件已在本地通过

本 PR 是否包含行为变更?

  • 是——已在上方概要中说明

@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary

This PR adds a read-only release gate for the npm CLI artifact.

It builds one immutable tarball and tests that exact artifact on Linux, macOS arm64, and Windows x64 with Node.js 22.19 and 24. Offline smoke tests run outside the repository with an empty npm cache. They cover both CLI bins, Eval assets, PTY and native locks, TUI startup, Runtime Host lifecycle, and a filesystem-backed model turn.

The release path also enforces limits for compressed size, unpacked size, and file count. check:release now includes the artifact policy test.

Source of truth

The PR extends the existing release packaging and validation path. It does not create a parallel packaging path. The workflow reuses one packaged artifact for all platform and runtime checks.

Scope and complexity

The solution is coherent with the release-gate objective. The smoke-test complexity supports cross-platform process control, cleanup, timeouts, isolated environments, bounded output, and installed-product validation. The artifact policy tests provide focused regression coverage for release growth.

No safe deletion or simplification is evident from the supplied changes. Removing the added controls or checks would weaken artifact, runtime, or cross-platform coverage.

Complexity delta

The PR adds one read-only workflow, one immutable-artifact handoff, a platform and Node.js version matrix, artifact metric limits, and extensive installed-product test states. It adds exported policy constants and validation functions, but it does not add a new packaging authority or user-facing runtime API.

The PR adds workflow branches for platform-specific process termination and cleanup. It also adds test-maintenance burden through PTY, TUI, Runtime Host, mock-provider, timeout, and filesystem-worker scenarios.

The single-artifact design removes the risk of validating separately rebuilt packages across jobs. The focused policy test centralizes artifact ceilings. Total maintenance complexity increases, but the increase is justified by the cross-platform release coverage and the absence of a parallel packaging path.

Risks and validation

The workflow can block releases when artifact metrics exceed the configured ceilings. Cross-platform process and TUI tests can be sensitive to timing, environment differences, and cleanup failures. The offline mock-provider test can fail if the installed artifact omits required runtime assets.

Reported local validation passed tarball packaging, installed-product smoke tests, release policy tests, lint, format, CLI typecheck, notice checks, and actionlint. The aggregate check:release result was affected by a pre-existing @maka/ui stale-build timestamp. Required check status remains unverified without direct CI evidence.

Review-relevant risks

The PR changes release governance by adding a read-only cross-platform artifact gate. Material governance or release changes require independent human review under repository policy.

The PR changes packaged-artifact validation and can prevent releases that exceed reviewed size or file-count limits. Material release behavior changes require independent human review under repository policy.

The workflow downloads and executes the packaged CLI in isolated environments. This affects release and security review surfaces. Material security or release changes require independent human review under repository policy.

The packaging path validates third-party notices. Material licensing or attribution effects require independent human review under repository policy.

No direct user-facing API or runtime behavior change was identified in the current diff.

The person performing the merge must review the final diff. A maintainer makes the final determination.

Walkthrough

The PR adds CLI release artifact limits, package validation, comprehensive installed-package smoke tests, and a GitHub Actions workflow that tests immutable artifacts across Linux, macOS, and Windows.

Changes

CLI Release Validation

Layer / File(s) Summary
Artifact policy and packaging
scripts/release-cli-artifact-policy.mjs, scripts/release-cli-artifact-policy.test.mjs, scripts/release-cli-package.mjs, package.json
The release process validates compressed size, unpacked size, and entry count against safe-integer and ceiling rules before it writes checksums and metadata. The release check includes the new policy tests.
Package integrity and process validation
scripts/smoke-release-cli-package.mjs
The smoke verifier checks checksums, inventory, artifact metrics, installed runtime files, CLI behavior, PTY operation, native file locking, bounded output, timeouts, cleanup, and process termination.
Runtime and provider scenarios
scripts/smoke-release-cli-package.mjs
The verifier tests interactive TUI startup, Runtime Host lifecycle, filesystem-worker execution, and a local mock provider with streaming and non-streaming responses.
Cross-platform CI execution
.github/workflows/cli-package-validation.yml
The workflow builds and uploads one immutable CLI artifact, then runs smoke tests on Linux, macOS, and Windows with Node.js 22.19 and 24.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: 🔵 Low · up to 268a0

This PR adds cross-platform validation of the packaged CLI, but the validation path still has bounded risks from unpinned npm transitive dependencies, Windows cleanup and path handling, and a brittle TUI assertion that could cause nondeterministic failures or long CI timeouts. It is mergeable with explicit owner awareness and follow-up on these reliability and reproducibility issues.

Sequence Diagram(s)

sequenceDiagram
  participant GitHubActions
  participant ReleasePackager
  participant ArtifactStore
  participant SmokeVerifier
  participant RuntimeHost
  participant MockProvider
  GitHubActions->>ReleasePackager: create and validate CLI tarball
  ReleasePackager->>ArtifactStore: upload package and metadata
  GitHubActions->>ArtifactStore: download immutable artifact
  GitHubActions->>SmokeVerifier: run platform smoke test
  SmokeVerifier->>RuntimeHost: install and execute CLI
  RuntimeHost->>MockProvider: discover model and process requests
  RuntimeHost-->>SmokeVerifier: return runtime and filesystem results
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the cross-platform npm CLI tarball validation added by the pull request.
Description check ✅ Passed The description follows the template, explains the release gate, documents verification results and the known aggregate-check issue, and completes the AI-use and checklist sections.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Ai Use Disclosure ✅ Passed The PR selects only generative tooling, names OpenAI Codex and its scope, and both introduced commits contain matching standalone Generated-by trailers.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cli-cross-platform-validation

Comment @coderabbitai help to get the list of available commands.

@M4n5ter
M4n5ter force-pushed the feat/cli-cross-platform-validation branch from 440d137 to 74d4d39 Compare August 18, 2026 03:29

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
scripts/smoke-release-cli-package.mjs (1)

316-324: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Check provider.error before the sentinel assertion.

A provider-side failure returns HTTP 500, so the CLI output lacks RESPONSE_SENTINEL. Line 319 then throws the generic Expected output to contain "MAKA_RELEASE_SMOKE_OK" error, and the precise provider error at line 323 never surfaces. Report the root cause first.

♻️ Proposed reordering
     if (result.exitCode !== 0) {
       throw new Error(`Controlled maka run exited with ${result.exitCode}: ${result.stderr}`);
     }
+    if (provider.error) throw provider.error;
     assertOutput(result.stdout, RESPONSE_SENTINEL);
     if (!provider.sawReadTool || !provider.sawFileSentinel) {
       throw new Error('Controlled maka run did not execute the installed filesystem worker');
     }
-    if (provider.error) throw provider.error;
     behaviorCompleted = true;

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 665d1b16-c876-4def-be02-fa26bac39752

📥 Commits

Reviewing files that changed from the base of the PR and between 38bd18f and 74d4d39.

📒 Files selected for processing (6)
  • .github/workflows/cli-package-validation.yml
  • package.json
  • scripts/release-cli-artifact-policy.mjs
  • scripts/release-cli-artifact-policy.test.mjs
  • scripts/release-cli-package.mjs
  • scripts/smoke-release-cli-package.mjs

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Comment thread scripts/smoke-release-cli-package.mjs Outdated
Comment thread scripts/smoke-release-cli-package.mjs Outdated
Comment thread scripts/smoke-release-cli-package.mjs
@M4n5ter
M4n5ter force-pushed the feat/cli-cross-platform-validation branch from 36c48fc to c57337f Compare August 18, 2026 04:02
Build the CLI package once and exercise that immutable artifact on the minimum Node runtime plus Linux, macOS arm64, and Windows. The installed smoke uses production configuration and protocol paths so native modules, TUI setup, Runtime Host teardown, and a filesystem-backed model turn are validated without repository dependencies.

Keep publishing authority out of this workflow and fail release builds on reviewed artifact growth.

Generated-by: OpenAI Codex
Run the installed CLI checks in a child process so Windows unloads native addons and ConPTY before the parent removes the temporary installation. Preserve validation and cleanup failures independently, and always settle an exact Runtime Host before reporting lifecycle regressions.

Use the installed cross-spawn implementation for Windows command shims, rely on stable TUI command tokens, and parse JSON records independently of ConPTY control sequences.

Generated-by: OpenAI Codex
@M4n5ter
M4n5ter force-pushed the feat/cli-cross-platform-validation branch from c57337f to 268a026 Compare August 18, 2026 04:03
@M4n5ter
M4n5ter marked this pull request as ready for review August 18, 2026 04:16
@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Validate immutable npm CLI tarball across supported platforms

✨ Enhancement 🧪 Tests ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Builds one immutable CLI tarball and validates it across Linux, macOS, and Windows.
• Exercises installed bins, native modules, TUI, Runtime Host, and filesystem-backed model turns.
• Blocks release candidates exceeding reviewed size, unpacked-size, or file-count ceilings.
Diagram

graph TD
  Pack["Pack CLI"] --> Policy{"Policy pass?"} --> Artifact["Immutable tarball"] --> Matrix["Platform matrix"] --> Install["Offline install"] --> Smoke["Product smoke"] --> Gate["Release gate"]
  Policy -- "No" --> Fail["Fail build"]
Loading
High-Level Assessment

The selected approach is appropriate: building once proves every runner validates the same publishable artifact, while native runners exercise platform-specific PTY, locking, command-shim, and cleanup behavior. Building separately per platform would weaken artifact immutability, repository-based tests would miss packaging defects, and coupling this workflow to publishing would unnecessarily expand its authority.

Files changed (6) +1123 / -82

Enhancement (2) +28 / -0
release-cli-artifact-policy.mjsDefine reviewed CLI artifact growth ceilings +22/-0

Define reviewed CLI artifact growth ceilings

• Introduces shared limits for compressed bytes, unpacked bytes, and entry count. Validation rejects malformed metrics and release artifacts exceeding any reviewed ceiling.

scripts/release-cli-artifact-policy.mjs

release-cli-package.mjsEnforce artifact limits while packaging the CLI +6/-0

Enforce artifact limits while packaging the CLI

• Validates npm pack's compressed size, unpacked size, and entry count before accepting the release tarball and generating its checksum.

scripts/release-cli-package.mjs

Tests (2) +948 / -81
release-cli-artifact-policy.test.mjsTest CLI artifact metric enforcement +40/-0

Test CLI artifact metric enforcement

• Verifies the established baseline remains accepted, each ceiling is enforced independently, and malformed numeric metrics are rejected without coercion.

scripts/release-cli-artifact-policy.test.mjs

smoke-release-cli-package.mjsExpand installed-product smoke coverage and isolation +908/-81

Expand installed-product smoke coverage and isolation

• Validates checksum, inventory, artifact limits, bins, packaged assets, patched dependencies, PTY support, and native file locks from an offline installation. Adds isolated child-process verification, interactive TUI and Runtime Host lifecycle checks, a filesystem-backed model turn using a local mock provider, bounded output, timeouts, and cross-platform cleanup handling.

scripts/smoke-release-cli-package.mjs

Other (2) +147 / -1
cli-package-validation.ymlAdd cross-platform validation for one immutable CLI tarball +146/-0

Add cross-platform validation for one immutable CLI tarball

• Adds a read-only GitHub Actions workflow that packages the CLI once and uploads the tarball with its checksum and inventory. A matrix validates that artifact on minimum and current Node versions across Linux x64, macOS arm64, and Windows x64.

.github/workflows/cli-package-validation.yml

package.jsonInclude artifact policy tests in release checks +1/-1

Include artifact policy tests in release checks

• Extends the aggregate release check to execute the CLI artifact policy tests alongside existing file-policy and notice validations.

package.json

@M4n5ter

M4n5ter commented Aug 18, 2026

Copy link
Copy Markdown
Member Author

I have manually reviewed this PR, confirmed that it has no major impact and is easy to roll back, and I take responsibility for this result.

@M4n5ter
M4n5ter merged commit 32e3cbb into main Aug 18, 2026
18 of 19 checks passed
@M4n5ter
M4n5ter deleted the feat/cli-cross-platform-validation branch August 18, 2026 04:19
@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider

Great, no issues found!

Qodo reviewed your code and found no material issues that require review

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: c64c1cdf-774a-47fa-b820-b392c62c5d42

📥 Commits

Reviewing files that changed from the base of the PR and between 74d4d39 and 268a026.

📒 Files selected for processing (2)
  • .github/workflows/cli-package-validation.yml
  • scripts/smoke-release-cli-package.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • scripts/smoke-release-cli-package.mjs

Included review availability: Your plan includes up to 3 reviews per rolling hour; 0 remain after this review.

node-version: '22.19.0'
cache: npm
- name: Select the release npm toolchain
run: npm install --global --no-audit --no-fund npm@11.12.1

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -eu

printf '%s\n' '--- workflow references ---'
rg -n -C 4 'npm install --global|npm@11\.12\.1|package-lock|corepack|pnpm|yarn|npm ci|npm install' .github/workflows/cli-package-validation.yml

printf '%s\n' '--- repository package-manager files ---'
git ls-files | rg '(^|/)(package\.json|package-lock\.json|npm-shrinkwrap\.json|pnpm-lock\.yaml|yarn\.lock|\.npmrc|\.nvmrc|\.node-version|packageManager)$' || true

printf '%s\n' '--- package-manager declarations ---'
for f in package.json .npmrc .nvmrc .node-version; do
  if [ -f "$f" ]; then
    echo "### $f"
    cat -n "$f"
  fi
done

Repository: maka-agent/maka-agent

Length of output: 8024


🏁 Script executed:

#!/bin/bash
set -eu

python3 - <<'PY'
import io
import json
import tarfile
import urllib.request

version = "11.12.1"
url = f"https://registry.npmjs.org/npm/{version}"
with urllib.request.urlopen(url, timeout=20) as response:
    metadata = json.load(response)

print("--- registry metadata ---")
print("name:", metadata.get("name"))
print("version:", metadata.get("version"))
dist = metadata.get("dist", {})
print("tarball:", dist.get("tarball"))
print("integrity:", dist.get("integrity"))
print("shasum:", dist.get("shasum"))

tarball_url = dist["tarball"]
with urllib.request.urlopen(tarball_url, timeout=30) as response:
    data = response.read()

print("--- published package files ---")
with tarfile.open(fileobj=io.BytesIO(data), mode="r:gz") as archive:
    names = archive.getnames()
    for name in names:
        if name in {
            "package/package.json",
            "package/package-lock.json",
            "package/npm-shrinkwrap.json",
        } or name.endswith(("/package-lock.json", "/npm-shrinkwrap.json")):
            print(name)

    package_json = json.load(archive.extractfile("package/package.json"))
    print("--- npm package manifest ---")
    print("packageManager:", package_json.get("packageManager"))
    print("dependencies:", len(package_json.get("dependencies", {})))
    print("optionalDependencies:", len(package_json.get("optionalDependencies", {})))
    print("bundledDependencies:", package_json.get("bundledDependencies"))
PY

Repository: maka-agent/maka-agent

Length of output: 2445


🏁 Script executed:

#!/bin/bash
set -eu

tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT

curl -fsSLk 'https://registry.npmjs.org/npm/11.12.1' > "$tmpdir/metadata.json"

python3 - "$tmpdir/metadata.json" <<'PY'
import json, sys
metadata = json.load(open(sys.argv[1]))
dist = metadata["dist"]
print("--- registry metadata ---")
print("name:", metadata["name"])
print("version:", metadata["version"])
print("tarball:", dist["tarball"])
print("integrity:", dist.get("integrity"))
print("shasum:", dist.get("shasum"))
PY

tarball="$(python3 - "$tmpdir/metadata.json" <<'PY'
import json, sys
print(json.load(open(sys.argv[1]))["dist"]["tarball"])
PY
)"
curl -fsSLk "$tarball" > "$tmpdir/npm.tgz"

printf '%s\n' '--- published lockfile names ---'
tar -tzf "$tmpdir/npm.tgz" | grep -E '(^|/)(package-lock\.json|npm-shrinkwrap\.json)$' || true

printf '%s\n' '--- published npm manifest dependency fields ---'
tar -xOf "$tmpdir/npm.tgz" package/package.json |
  python3 -c 'import json,sys; p=json.load(sys.stdin); print("packageManager:",p.get("packageManager")); print("dependencies:",len(p.get("dependencies",{}))); print("optionalDependencies:",len(p.get("optionalDependencies",{}))); print("bundledDependencies:",p.get("bundledDependencies"))'

Repository: maka-agent/maka-agent

Length of output: 591


Pin npm’s dependency tree, not only its version.

The root package.json pins npm@11.12.1, but the published package has no lockfile or shrinkwrap and declares 65 dependencies. Both global installs can therefore resolve transitive dependencies outside the repository lockfile. Add a reviewed mechanism that pins the complete npm toolchain.

🧰 Tools
🪛 zizmor (1.29.0)

[warning] 82-82: ad-hoc installation of packages (adhoc-packages): installs a package outside of a lockfile

(adhoc-packages)

Sources: Path instructions, Linters/SAST tools

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.

1 participant