Skip to content
Closed
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
137 changes: 125 additions & 12 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,11 @@ jobs:

publish-crates:
name: publish to crates.io
needs: [validate, quality-recheck]
# Gate the first irreversible publish on the CLI binaries building
# successfully (RFC-0110 / Codex #519 P1): if any platform build fails we
# must NOT publish to a registry, or the release is partial (crates live but
# binaries missing). npm/pypi are gated on publish-crates.
needs: [validate, quality-recheck, build-cli-binaries]
runs-on: ubuntu-latest
timeout-minutes: 60
environment: crates-io
Expand Down Expand Up @@ -145,28 +149,62 @@ jobs:

publish-npm:
name: publish to npm
needs: [validate, quality-recheck, publish-crates]
# RFC-0110: assemble the per-platform + launcher packages from the prebuilt
# binaries and publish them. needs build-cli-binaries for the artifacts.
needs: [validate, quality-recheck, publish-crates, build-cli-binaries]
runs-on: ubuntu-latest
timeout-minutes: 30
environment: npm
permissions:
id-token: write # for provenance
env:
VERSION: ${{ needs.validate.outputs.version }}
steps:
- uses: actions/checkout@v6
- uses: actions/setup-node@v6
with:
node-version: '20'
registry-url: 'https://registry.npmjs.org'
- run: |
if [ -d "bindings/node" ]; then
cd bindings/node
npm ci
npm publish --access public --provenance
else
echo "no bindings/node yet — skipping"
fi
- name: Download CLI binaries
uses: actions/download-artifact@v7
with:
pattern: cli-*
path: dl
- name: Reshape artifacts into a platform-keyed bin dir
run: |
mkdir -p dist-bin
for d in dl/cli-*; do
key="${d#dl/cli-}"
mkdir -p "dist-bin/$key"
cp "$d"/* "dist-bin/$key/"
done
ls -R dist-bin
- name: Assemble npm packages
run: node npm/scripts/build-npm.mjs --version "$VERSION" --bin-dir dist-bin --out dist-npm

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Check NPM_TOKEN before running npm assembly

In the missing-NPM_TOKEN release path this patch is meant to tolerate, this step still runs before the token guard in Publish packages. I searched the repo for npm/scripts/build-npm.mjs, npm/, and package manifests and found no matching file/tree, so node will fail with MODULE_NOT_FOUND at this line and the publish-npm job will fail instead of warning and skipping. Move the token guard ahead of the download/assembly steps or add the npm package builder in the same change.

Useful? React with 👍 / 👎.

- name: Publish packages (idempotent — platform packages first)
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
if [ -z "${NODE_AUTH_TOKEN:-}" ]; then
echo "::warning::NPM_TOKEN is not set — skipping npm publish. Configure it in repo Settings → Environments → npm."
exit 0
fi
publish_one() {
dir="$1"
name=$(node -p "require('./$dir/package.json').name")
ver=$(node -p "require('./$dir/package.json').version")
if npm view "$name@$ver" version >/dev/null 2>&1; then
echo "$name@$ver already on npm; skipping"
return 0
fi
( cd "$dir" && npm publish --access public --provenance )
}
# Platform packages must exist before the main package (whose
# optionalDependencies reference them).
for dir in dist-npm/mycelium-*; do
[ -d "$dir" ] && publish_one "$dir"
done
publish_one "dist-npm/mycelium"

publish-pypi:
name: publish to PyPI
Expand All @@ -190,6 +228,56 @@ jobs:
echo "no bindings/python yet — skipping"
fi

build-cli-binaries:
# RFC-0110: cross-compile the `mycelium` CLI for each distributed platform,
# upload each as a workflow artifact (consumed by publish-npm in a follow-up
# and attached to the GitHub Release below). Native builds for 4 targets;
# `cross` handles the linux-arm64 C toolchain (tree-sitter grammars are C).
name: build CLI binary (${{ matrix.key }})
needs: [validate, quality-recheck]
runs-on: ${{ matrix.os }}
timeout-minutes: 30
strategy:
fail-fast: false
matrix:
include:
- { key: darwin-arm64, os: macos-14, target: aarch64-apple-darwin, exe: mycelium, cross: false }
- { key: darwin-x64, os: macos-13, target: x86_64-apple-darwin, exe: mycelium, cross: false }
- { key: linux-x64, os: ubuntu-latest, target: x86_64-unknown-linux-gnu, exe: mycelium, cross: false }
- { key: linux-arm64, os: ubuntu-latest, target: aarch64-unknown-linux-gnu, exe: mycelium, cross: true }
- { key: win32-x64, os: windows-latest, target: x86_64-pc-windows-msvc, exe: mycelium.exe, cross: false }
steps:
- uses: actions/checkout@v6
- uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: release-${{ matrix.target }}
- name: Install cross (linux-arm64)
if: ${{ matrix.cross }}
uses: taiki-e/install-action@v2
with:
tool: cross
- name: Build release binary
shell: bash
run: |
if [ "${{ matrix.cross }}" = "true" ]; then
cross build --release -p mycelium-rcig-cli --target ${{ matrix.target }}
else
cargo build --release -p mycelium-rcig-cli --target ${{ matrix.target }}
fi
- name: Stage binary under its platform key
shell: bash
run: |
mkdir -p "dist-bin/${{ matrix.key }}"
cp "target/${{ matrix.target }}/release/${{ matrix.exe }}" "dist-bin/${{ matrix.key }}/${{ matrix.exe }}"
- uses: actions/upload-artifact@v7
with:
name: cli-${{ matrix.key }}
path: dist-bin/${{ matrix.key }}/${{ matrix.exe }}
if-no-files-found: error

finalize:
name: merge to main, tag, GitHub Release
# Charter §5.12: touching main requires founder authorization.
Expand All @@ -198,7 +286,7 @@ jobs:
# (scripts/release-ceremony.sh) or a manual workflow_dispatch serves as
# the explicit human authorization step.
if: github.event_name == 'workflow_dispatch'
needs: [validate, publish-crates, publish-npm, publish-pypi]
needs: [validate, publish-crates, publish-npm, publish-pypi, build-cli-binaries]
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
Expand Down Expand Up @@ -263,13 +351,38 @@ jobs:
git tag -a "v$VERSION" -m "Release v$VERSION"
git push origin "v$VERSION"

# Step D — Create the GitHub Release on the tag reachable from main.
# Step D — Download the per-platform CLI binaries and rename them with a
# platform suffix (the raw artifacts are all named `mycelium`/`.exe`, which
# would collide as release assets). RFC-0110.
- name: Download CLI binaries
uses: actions/download-artifact@v7
with:
pattern: cli-*
path: dist-release
- name: Collect release assets
shell: bash
run: |
mkdir -p release-assets
for d in dist-release/cli-*; do
key="${d#dist-release/cli-}"
if [ -f "$d/mycelium.exe" ]; then
cp "$d/mycelium.exe" "release-assets/mycelium-$key.exe"
elif [ -f "$d/mycelium" ]; then
cp "$d/mycelium" "release-assets/mycelium-$key"
fi
done
ls -la release-assets

# Step E — Create the GitHub Release on the tag reachable from main,
# attaching the per-platform binaries (a download path for users who do
# not use npm/bun/cargo).
- name: Create GitHub Release
uses: softprops/action-gh-release@v3
with:
tag_name: v${{ env.VERSION }}
generate_release_notes: true
target_commitish: main
files: release-assets/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Expand Down
Loading