From 4eb194cbc65b26fb40be808ea499e5fe2ec9bd60 Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 30 Sep 2026 08:13:46 +0000 Subject: [PATCH] Prefix release binary zips with the release version Assets are now named corgea--.zip (e.g. corgea-v1.16.0-aarch64-apple-darwin.zip). The npm bundler takes the tag and still accepts the legacy unversioned names so older releases can be republished. Co-authored-by: ibrahim --- .github/workflows/npm-publish.yml | 2 +- .github/workflows/release-binaries.yml | 33 ++++++++++++++++++++++---- RELEASING.md | 8 +++---- build_release.sh | 8 ++++++- scripts/npm/bundle-binaries.js | 29 +++++++++++++++------- 5 files changed, 61 insertions(+), 19 deletions(-) diff --git a/.github/workflows/npm-publish.yml b/.github/workflows/npm-publish.yml index 629c8e7..2669088 100644 --- a/.github/workflows/npm-publish.yml +++ b/.github/workflows/npm-publish.yml @@ -76,7 +76,7 @@ jobs: run: npm install --include=dev - name: Bundle binaries into vendor/ - run: node scripts/npm/bundle-binaries.js release-assets + run: node scripts/npm/bundle-binaries.js release-assets "${{ needs.prepare.outputs.tag_name }}" - name: Publish corgea-cli env: diff --git a/.github/workflows/release-binaries.yml b/.github/workflows/release-binaries.yml index 74a02b0..12ac6d5 100644 --- a/.github/workflows/release-binaries.yml +++ b/.github/workflows/release-binaries.yml @@ -116,11 +116,36 @@ jobs: ;; esac + # Release builds are named after the tag so they match the release they are + # attached to (npm-publish.yml looks them up by tag). Branch builds have no + # tag, so they fall back to the Cargo.toml version. + - name: Resolve Asset Name + id: asset + shell: bash + env: + INPUT_TAG: ${{ inputs.tag }} + run: | + if [[ -n "$INPUT_TAG" ]]; then + version="$INPUT_TAG" + elif [[ "$GITHUB_REF" == refs/tags/* ]]; then + version="$GITHUB_REF_NAME" + else + version="v$(cargo metadata --no-deps --format-version 1 \ + | jq -r '.packages[] | select(.name == "corgea") | .version')" + fi + + if [[ -z "$version" || "$version" == "v" ]]; then + echo "Could not resolve the release version" >&2 + exit 1 + fi + + echo "zip=corgea-${version}-${{ matrix.target }}.zip" >> "$GITHUB_OUTPUT" + - name: Archive Binary (Unix) if: runner.os != 'Windows' shell: bash run: | - zip -j "corgea-${{ matrix.target }}.zip" \ + zip -j "${{ steps.asset.outputs.zip }}" \ "target/${{ matrix.target }}/release/${{ matrix.binary_name }}" - name: Archive Binary (Windows) @@ -129,7 +154,7 @@ jobs: run: | Compress-Archive ` -Path "target\${{ matrix.target }}\release\${{ matrix.binary_name }}" ` - -DestinationPath "corgea-${{ matrix.target }}.zip" ` + -DestinationPath "${{ steps.asset.outputs.zip }}" ` -Force - name: Upload to GitHub Release (tags) @@ -137,7 +162,7 @@ jobs: uses: softprops/action-gh-release@v2 with: tag_name: ${{ inputs.tag || github.ref_name }} - files: "corgea-${{ matrix.target }}.zip" + files: ${{ steps.asset.outputs.zip }} env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} @@ -146,4 +171,4 @@ jobs: uses: actions/upload-artifact@v4 with: name: binaries-${{ matrix.target }} - path: "corgea-${{ matrix.target }}.zip" + path: ${{ steps.asset.outputs.zip }} diff --git a/RELEASING.md b/RELEASING.md index 7bdc917..8ef2758 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -6,7 +6,7 @@ The `corgea` CLI ships to three channels, all driven by **one git tag**: |---|---|---| | npm | `@corgea/cli` (scoped, bundles native binaries) | `npm install -g @corgea/cli` | | PyPI | `corgea-cli` (maturin-built wheels) | `pip install corgea-cli` | -| GitHub Release | `corgea-.zip` (raw binaries) | download from the [Releases page](https://github.com/Corgea/cli/releases) | +| GitHub Release | `corgea-vX.Y.Z-.zip` (raw binaries) | download from the [Releases page](https://github.com/Corgea/cli/releases) | Pushing an annotated `vX.Y.Z` tag to `main` fans out to three GitHub Actions workflows that build and publish all three. **Publishing is automated; the changelog is not** (see [Release notes](#release-notes)). @@ -58,7 +58,7 @@ Pushing an annotated `vX.Y.Z` tag to `main` fans out to three GitHub Actions wor | # | Workflow | File | Publishes | |---|---|---|---| | 1 | **CI** | `release.yml` | wheels → **PyPI** (`corgea-cli`), on tag | - | 2 | **Native Binary Release** | `release-binaries.yml` | 6 target zips → **GitHub Release** | + | 2 | **Native Binary Release** | `release-binaries.yml` | 7 target zips → **GitHub Release** | | 3 | **Publish npm Package** | `npm-publish.yml` | bundles binaries → **npm** (`@corgea/cli`) | Workflow 3 is triggered by workflow 2 completing successfully (and only when the tag is `v`-prefixed). If it does not auto-start, dispatch it manually: @@ -69,8 +69,8 @@ Pushing an annotated `vX.Y.Z` tag to `main` fans out to three GitHub Actions wor ## What gets built - **PyPI wheels** (`release.yml`): Linux (x86_64, x86), Windows (x64, x86), macOS (x86_64, aarch64), plus an sdist. Asserts `manylinux2014` tags for broad Linux compatibility. -- **Native binaries** (`release-binaries.yml`): `x86_64-unknown-linux-gnu`, `x86_64-unknown-linux-musl`, `aarch64-unknown-linux-gnu`, `aarch64-unknown-linux-musl`, `x86_64-apple-darwin`, `aarch64-apple-darwin`, `x86_64-pc-windows-msvc`. -- **npm binary bundling** (`npm-publish.yml` → `scripts/npm/bundle-binaries.js`): downloads the GitHub Release zips and lays them out as `vendor//corgea/corgea`. At runtime `bin/corgea.js` selects the binary for the host OS/arch. npm ships 5 of the 7 targets (both Linux arches use the musl build). +- **Native binaries** (`release-binaries.yml`): `x86_64-unknown-linux-gnu`, `x86_64-unknown-linux-musl`, `aarch64-unknown-linux-gnu`, `aarch64-unknown-linux-musl`, `x86_64-apple-darwin`, `aarch64-apple-darwin`, `x86_64-pc-windows-msvc`. Each is zipped as `corgea--.zip` (e.g. `corgea-v1.16.0-aarch64-apple-darwin.zip`); branch builds use `v` + the `Cargo.toml` version in place of the tag. Releases before this naming shipped `corgea-.zip`. +- **npm binary bundling** (`npm-publish.yml` → `scripts/npm/bundle-binaries.js `): downloads the GitHub Release zips (versioned name, falling back to the legacy unversioned name) and lays them out as `vendor//corgea/corgea`. At runtime `bin/corgea.js` selects the binary for the host OS/arch. npm ships 5 of the 7 targets (both Linux arches use the musl build). ### Linux glibc floor diff --git a/build_release.sh b/build_release.sh index 8f92a03..139efc8 100755 --- a/build_release.sh +++ b/build_release.sh @@ -22,6 +22,12 @@ else exit 1 fi +VERSION="v$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name == "corgea") | .version')" +if [ "$VERSION" == "v" ]; then + echo "Could not read the corgea version from Cargo.toml (is jq installed?)" + exit 1 +fi + for target in "${TARGETS[@]}" do if [ $BUILD_OS == "Darwin" ]; then @@ -37,7 +43,7 @@ do ./scripts/check-linux-binary.sh "target/$target/release/corgea" "$target" || exit 1 fi - zip_file_name="corgea-$target.zip" + zip_file_name="corgea-$VERSION-$target.zip" # if zip_file_name exists, remove it if [ -f $zip_file_name ]; then diff --git a/scripts/npm/bundle-binaries.js b/scripts/npm/bundle-binaries.js index c6a13d6..84f7e0d 100644 --- a/scripts/npm/bundle-binaries.js +++ b/scripts/npm/bundle-binaries.js @@ -18,9 +18,25 @@ function fail(message) { process.exit(1); } -const [assetsDirArg] = process.argv.slice(2); -if (!assetsDirArg) { - fail("usage: bundle-binaries "); +const [assetsDirArg, releaseTag] = process.argv.slice(2); +if (!assetsDirArg || !releaseTag) { + fail("usage: bundle-binaries "); +} + +// Releases before versioned asset names shipped `corgea-.zip`; keep +// accepting it so older tags can still be republished. +function findArchive(triple) { + const candidates = [ + `corgea-${releaseTag}-${triple}.zip`, + `corgea-${triple}.zip`, + ]; + for (const name of candidates) { + const archivePath = path.join(assetsDir, name); + if (fs.existsSync(archivePath)) { + return { archiveName: name, archivePath }; + } + } + fail(`missing release asset for ${triple}: tried ${candidates.join(", ")}`); } const repoRoot = path.resolve(__dirname, "..", ".."); @@ -30,12 +46,7 @@ const vendorRoot = path.join(repoRoot, "vendor"); fs.rmSync(vendorRoot, { recursive: true, force: true }); for (const { triple, binary } of TARGETS) { - const archiveName = `corgea-${triple}.zip`; - const archivePath = path.join(assetsDir, archiveName); - - if (!fs.existsSync(archivePath)) { - fail(`missing release asset: ${archivePath}`); - } + const { archiveName, archivePath } = findArchive(triple); const destDir = path.join(vendorRoot, triple, "corgea"); fs.mkdirSync(destDir, { recursive: true });