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
99 changes: 77 additions & 22 deletions .github/workflows/images-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,7 @@ jobs:
brew tap-new mesh-llm/packaging-validation
tap_formula="$(brew --repository)/Library/Taps/mesh-llm/homebrew-packaging-validation/Formula/mesh-llm.rb"
cp artifacts/homebrew/Formula/mesh-llm.rb "$tap_formula"
brew trust --formula mesh-llm/packaging-validation/mesh-llm
brew audit --strict --online mesh-llm/packaging-validation/mesh-llm
brew install --formula mesh-llm/packaging-validation/mesh-llm
brew test mesh-llm/packaging-validation/mesh-llm
Expand Down Expand Up @@ -484,8 +485,8 @@ jobs:
if-no-files-found: error
retention-days: 14

node-sdk-preflight:
name: Assemble and install-test Node SDK npm package
node-sdk-package:
name: Assemble and dry-run publish Node SDK npm package
if: always() && needs.plan.outputs.npm_enabled == 'true' && needs.node-sdk-addon.result == 'success'
needs: [plan, node-sdk-addon]
runs-on: ubuntu-24.04
Expand Down Expand Up @@ -526,16 +527,15 @@ jobs:
--output-dir artifacts/node-sdk-package \
--expected-version "$MESH_VERSION" \
--targets "$targets"
- name: Test, pack, install, and dry-run publish
- name: Test, pack, and dry-run publish
timeout-minutes: 5
env:
NPM_PLAN: ${{ needs.plan.outputs.npm_plan }}
MESH_VERSION: ${{ needs.plan.outputs.mesh_version }}
shell: bash
run: |
set -euo pipefail
npm test --prefix artifacts/node-sdk-package
mkdir -p artifacts/npm consumer
mkdir -p artifacts/npm
(
cd artifacts/node-sdk-package
npm pack --pack-destination "$GITHUB_WORKSPACE/artifacts/npm"
Expand All @@ -549,28 +549,82 @@ jobs:
if [[ "$MESH_VERSION" == *-* ]]; then dist_tag=next; fi
npm publish "./$tarball" --dry-run --access public --tag "$dist_tag" --provenance=false
fi
(
cd consumer
npm init --yes >/dev/null
npm install "../$tarball"
if jq -e '.targets | index("linux-x64")' <<<"$NPM_PLAN" >/dev/null; then
node "$GITHUB_WORKSPACE/scripts/node-sdk-runtime-smoke.cjs" \
--package-root "$PWD" \
--expected-version "$MESH_VERSION" \
--target linux-x64-assembled-package
fi
)
- uses: actions/upload-artifact@v7
with:
name: mesh-llm-node-sdk-npm-${{ needs.plan.outputs.mesh_version }}
path: artifacts/npm/*.tgz
if-no-files-found: error
retention-days: 14

node-sdk-preflight:
name: Install and start Node SDK ${{ matrix.name }}
if: always() && needs.plan.outputs.npm_enabled == 'true' && needs.node-sdk-package.result == 'success'
needs: [plan, node-sdk-package]
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.plan.outputs.npm_matrix) }}
runs-on: ${{ fromJSON(matrix.runner_labels) }}
timeout-minutes: 10
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
- uses: actions/setup-node@v7
with:
node-version: '24'
package-manager-cache: false
- uses: actions/download-artifact@v8
with:
name: mesh-llm-node-sdk-npm-${{ needs.plan.outputs.mesh_version }}
path: artifacts/npm
- name: Install and exercise the assembled package on Unix
if: runner.os != 'Windows'
timeout-minutes: 5
env:
MESH_VERSION: ${{ needs.plan.outputs.mesh_version }}
NODE_SDK_TARGET: ${{ matrix.target }}
shell: bash
run: |
set -euo pipefail
tarballs=(artifacts/npm/*.tgz)
[[ ${#tarballs[@]} -eq 1 && -f "${tarballs[0]}" ]] || { echo "expected one assembled npm tarball" >&2; exit 1; }
tarball="$GITHUB_WORKSPACE/${tarballs[0]}"
mkdir consumer
cd consumer
npm init --yes >/dev/null
npm install "$tarball"
node "$GITHUB_WORKSPACE/scripts/node-sdk-runtime-smoke.cjs" \
--package-root "$PWD" --expected-version "$MESH_VERSION" \
--target "$NODE_SDK_TARGET"
- name: Install and exercise the assembled package on Windows
if: runner.os == 'Windows'
timeout-minutes: 5
env:
MESH_VERSION: ${{ needs.plan.outputs.mesh_version }}
NODE_SDK_TARGET: ${{ matrix.target }}
shell: pwsh
run: |
$ErrorActionPreference = 'Stop'
$PSNativeCommandUseErrorActionPreference = $true
$tarballs = @(Get-ChildItem -LiteralPath artifacts/npm -Filter '*.tgz' -File)
if ($tarballs.Count -ne 1) { throw 'expected one assembled npm tarball' }
$tarball = $tarballs[0].FullName
New-Item -ItemType Directory -Path consumer | Out-Null
Push-Location consumer
try {
npm init --yes | Out-Null
npm install $tarball
node "$env:GITHUB_WORKSPACE/scripts/node-sdk-runtime-smoke.cjs" `
--package-root (Get-Location).Path --expected-version $env:MESH_VERSION `
--target $env:NODE_SDK_TARGET
} finally {
Pop-Location
}

publish-node-sdk:
name: Publish Node SDK to npm
if: always() && needs.plan.outputs.publish_npm == 'true' && needs.node-sdk-preflight.result == 'success'
needs: [plan, node-sdk-preflight]
if: always() && needs.plan.outputs.publish_npm == 'true' && needs.node-sdk-package.result == 'success' && needs.node-sdk-preflight.result == 'success'
needs: [plan, node-sdk-package, node-sdk-preflight]
runs-on: ubuntu-24.04
environment: npm
permissions:
Expand Down Expand Up @@ -958,7 +1012,7 @@ jobs:
readiness:
name: Packaging readiness manifest
if: always()
needs: [plan, upstream, package-image, homebrew, release-assembly, node-sdk-addon, node-sdk-preflight, publish-node-sdk, image-index, promote-images, publish-release-assets]
needs: [plan, upstream, package-image, homebrew, release-assembly, node-sdk-addon, node-sdk-package, node-sdk-preflight, publish-node-sdk, image-index, promote-images, publish-release-assets]
runs-on: ubuntu-24.04
steps:
- name: Record and enforce required results
Expand All @@ -975,6 +1029,7 @@ jobs:
RELEASE_ASSEMBLY: ${{ needs.release-assembly.result }}
NPM_ENABLED: ${{ needs.plan.outputs.npm_enabled }}
NPM_ADDONS: ${{ needs.node-sdk-addon.result }}
NPM_PACKAGE: ${{ needs.node-sdk-package.result }}
NPM_PREFLIGHT: ${{ needs.node-sdk-preflight.result }}
PUBLISH_NPM_REQUESTED: ${{ needs.plan.outputs.publish_npm }}
PUBLISH_NPM: ${{ needs.publish-node-sdk.result }}
Expand All @@ -1000,7 +1055,7 @@ jobs:
if [[ "$HOMEBREW_ENABLED" == true ]]; then [[ "$HOMEBREW" == success ]] || return 1; fi
if [[ "$ASSEMBLY_ENABLED" == true ]]; then [[ "$RELEASE_ASSEMBLY" == success ]] || return 1; fi
if [[ "$NPM_ENABLED" == true ]]; then
[[ "$NPM_ADDONS" == success && "$NPM_PREFLIGHT" == success ]] || return 1
[[ "$NPM_ADDONS" == success && "$NPM_PACKAGE" == success && "$NPM_PREFLIGHT" == success ]] || return 1
fi
if [[ "$PUBLISH_NPM_REQUESTED" == true ]]; then [[ "$PUBLISH_NPM" == success ]] || return 1; fi
if [[ "$PUBLISH_IMAGES_REQUESTED" == true ]]; then
Expand All @@ -1016,12 +1071,12 @@ jobs:
--argjson run_id "$GITHUB_RUN_ID" --argjson run_attempt "$GITHUB_RUN_ATTEMPT" \
--arg plan "$PLAN" --arg upstream "$UPSTREAM" --arg package_images "$PACKAGE_IMAGES" \
--arg homebrew "$HOMEBREW" --arg release_assembly "$RELEASE_ASSEMBLY" \
--arg npm_addons "$NPM_ADDONS" --arg npm_preflight "$NPM_PREFLIGHT" --arg publish_npm "$PUBLISH_NPM" \
--arg npm_addons "$NPM_ADDONS" --arg npm_package "$NPM_PACKAGE" --arg npm_preflight "$NPM_PREFLIGHT" --arg publish_npm "$PUBLISH_NPM" \
--arg image_index "$IMAGE_INDEX" --arg promote_images "$PROMOTE_IMAGES" --arg publish_assets "$PUBLISH_ASSETS" \
--arg publish_images_requested "$PUBLISH_IMAGES_REQUESTED" \
--arg publish_assets_requested "$PUBLISH_ASSETS_REQUESTED" \
--arg publish_npm_requested "$PUBLISH_NPM_REQUESTED" \
'{schema:"mesh-packaging-readiness-v1",status:$status,correlation_id:$correlation_id,packaging_run_id:$run_id,packaging_run_attempt:$run_attempt,upstream:{repository:$repository,ref:$ref,sha:$sha,manifest_sha256:$manifest_sha256},requested:{publish_images:$publish_images_requested,publish_release_assets:$publish_assets_requested,publish_npm:$publish_npm_requested},results:{plan:$plan,upstream:$upstream,package_images:$package_images,homebrew:$homebrew,release_assembly:$release_assembly,npm_addons:$npm_addons,npm_preflight:$npm_preflight,publish_npm:$publish_npm,image_index:$image_index,promote_images:$promote_images,publish_release_assets:$publish_assets}}' \
'{schema:"mesh-packaging-readiness-v1",status:$status,correlation_id:$correlation_id,packaging_run_id:$run_id,packaging_run_attempt:$run_attempt,upstream:{repository:$repository,ref:$ref,sha:$sha,manifest_sha256:$manifest_sha256},requested:{publish_images:$publish_images_requested,publish_release_assets:$publish_assets_requested,publish_npm:$publish_npm_requested},results:{plan:$plan,upstream:$upstream,package_images:$package_images,homebrew:$homebrew,release_assembly:$release_assembly,npm_addons:$npm_addons,npm_package:$npm_package,npm_preflight:$npm_preflight,publish_npm:$publish_npm,image_index:$image_index,promote_images:$promote_images,publish_release_assets:$publish_assets}}' \
| tee packaging-readiness.json
[[ "$status" == success ]]
- uses: actions/upload-artifact@v7
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ This repository is the packaging and distribution control plane for published [`
```text
published upstream tag + immutable tag SHA
-> verified host/runtime product bundles -> native packages -> OCI images
-> npm addon lanes -> per-lane fresh install/start -> assembled @mesh-llm/sdk
-> verified npm addon lanes -> assembled @mesh-llm/sdk -> per-platform fresh install/start
tarball -> clean install/start
```

Expand Down
25 changes: 22 additions & 3 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Production Readiness TODO

- [ ] Verify Homebrew host integrity and bound forced test-process cleanup.
QA: compare the installed host with its product-manifest digest, prove a
TERM-ignoring child is killed and reaped with bounded waits, pass the formula
tests and full suite, and complete the updated Homebrew release rehearsal.

- [x] Admit the generated Homebrew validation formula under tap-trust policy.
QA: trust only that formula after generation and before audit, verify the
isolated Homebrew trust record, pass the workflow regression, and complete a
Homebrew audit/install/runtime dry run without disabling tap trust.
Validation: run `41341832014` passed audit, installation, automatic client
readiness, bounded shutdown, and terminal readiness with publication disabled.

- [ ] Require installed npm lifecycle QA on every selected native platform.
QA: execute one assembled tarball on macOS ARM64, Linux ARM64/x64, and
Windows x64; verify each runner target; reject failed, cancelled, or skipped
required consumers in readiness and publication gates; pass focused workflow
and smoke fixtures, the full TypeScript suite, and a current-artifact dry run.

- [ ] Align packaging with the 0.79.0 producer after the workspace and CI
migrations. QA: verify the exact current product schema, runtime ABI/release
identity, bundled plugins, and Node SDK source/console/lifecycle contracts;
Expand Down Expand Up @@ -183,10 +201,11 @@

- [x] Assemble, preflight, and publish the canonical `@mesh-llm/sdk` tarball.
QA: local fixture dry runs produce the expected cross-platform tarball,
every addon lane packs and installs into a clean consumer project, and its
every selected native platform installs it into a clean consumer project, and its
public `Node` API completes bounded start/status/finally-stop with normal
process exit. The assembled host package repeats the lifecycle proof before
`npm publish --dry-run`; workflow lint proves CI can schedule every lane.
process exit. Assembly performs `npm publish --dry-run`; workflow lint proves
CI can schedule every lane. The later per-platform lifecycle regression and
its current-artifact acceptance are tracked in the active item above.

- [x] Document npm packaging and hand ownership off from `mesh-llm`.
QA: documentation scans find the canonical repository and workflow, the
Expand Down
2 changes: 1 addition & 1 deletion docs/packaging-readiness-scorecard.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Readiness is evidence-based, not a static percentage. A release is ready only wh
| Package correctness | Native metadata, checksum, host/runtime ownership, version/runtime-list checks, and no-device client readiness with bounded shutdown | Full dry-run evidence |
| OCI correctness | Image installs the exact package, labels both input digests, checks the final entrypoint, and reaches client readiness without a device | Full dry-run evidence plus separate hardware qualification |
| Homebrew | Direct upstream arm64 product, formula-owned runtime, strict audit/install/test, and no-device client readiness | Validate each release before tap update |
| npm SDK | Every addon lane is packed into a fresh project and must complete public `Node` start/status/finally-stop with normal process exit; the assembled package repeats the host-lane proof | Validate the exact public package separately during distribution certification |
| npm SDK | Every selected native platform installs the same assembled tarball into a fresh project, verifies its runner target, and completes public `Node.fromConfig` start/status/finally-stop with normal process exit | Validate the exact public package separately during distribution certification |
| Efficiency | One host per OS/architecture is composed with 8 verified runtimes and fans out to 11 package rows; no source builds | Record duration, artifact sizes, and cache behavior |
| Publish safety | Dry-run override, job-local write permissions, release environment | Configure/approve environment and observe first publish rehearsal |
| Automation | Repository dispatch receiver | Provision upstream fine-grained dispatch credential/App |
Expand Down
9 changes: 9 additions & 0 deletions docs/publishing.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ unknown IDs fail before scheduling. Publication requires the complete matching
producer set: images require all native rows, package release assets require all
native rows plus Homebrew, and npm requires all addon lanes.

For npm, one assembly job packs the verified addons and tagged JavaScript into
the release tarball. Each selected target then downloads that same artifact,
installs it in a clean project on its native runner, checks the runner's OS and
architecture, and executes bounded `Node.fromConfig` start/status/stop. npm
publication waits for every selected consumer. Readiness records archive
verification as `npm_addons`, assembly as `npm_package`, and the complete native
consumer matrix as `npm_preflight`; required failures, cancellations, and skips
fail the gate. These consumers do not compile upstream sources.

Every enabled native package row preserves its BuildKit statement under an
artifact-specific filename, scans the exact package file into SPDX, and verifies
that the SPDX file subject names and hashes that same package. The current
Expand Down
Loading