fix(ci): pass deployment body as raw JSON for empty required_contexts… #13
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release | |
| # Triggered on a git tag push (v*). Builds AOT-published binaries for four | |
| # platforms (linux-x64, linux-arm64, osx-arm64, win-x64), stages each full | |
| # publish tree into binaries/<rid>/, then publishes the npm tarball from | |
| # the ubuntu publish job. | |
| # | |
| # Intel Mac (osx-x64) is NOT shipped — all modern Apple hardware is arm64. | |
| # If Intel Mac support is re-added later, either use a macos-14-large | |
| # Intel runner or cross-compile osx-x64 from macos-14 arm64. | |
| # | |
| # IMPORTANT: the AOT binary depends on sibling native libs (libe_sqlite3, | |
| # libonnxruntime, vec0, models/). The matrix job stages the ENTIRE publish | |
| # tree into binaries/<rid>/ — copying just the executable would yield a | |
| # DllNotFoundException at runtime. | |
| # | |
| # .NET SDK version is pinned by /global.json at the repo root so every | |
| # matrix leg uses the same SDK regardless of what's pre-installed on the | |
| # runner. Currently pinned to .NET 10 (see global.json). | |
| # | |
| # No untrusted github.event.* fields are interpolated into run: blocks; | |
| # only the static matrix values and secrets.NPM_TOKEN (via env:) are used. | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| permissions: | |
| contents: write | |
| deployments: write | |
| jobs: | |
| build: | |
| name: Build ${{ matrix.rid }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - rid: linux-x64 | |
| os: ubuntu-latest | |
| artifact: total-recall-linux-x64 | |
| exe: total-recall | |
| - rid: linux-arm64 | |
| os: ubuntu-24.04-arm | |
| artifact: total-recall-linux-arm64 | |
| exe: total-recall | |
| - rid: osx-arm64 | |
| os: macos-14 | |
| artifact: total-recall-osx-arm64 | |
| exe: total-recall | |
| - rid: win-x64 | |
| os: windows-latest | |
| artifact: total-recall-win-x64 | |
| exe: total-recall.exe | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - name: Checkout (with LFS for ONNX model files) | |
| uses: actions/checkout@v4 | |
| with: | |
| lfs: true | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Install npm dependencies (provides sqlite-vec native lib) | |
| run: npm ci | |
| - name: Setup .NET | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| global-json-file: global.json | |
| - name: Install clang for NativeAOT (Linux) | |
| if: runner.os == 'Linux' | |
| run: sudo apt-get update && sudo apt-get install -y clang zlib1g-dev | |
| # The tag name drives -p:Version so the AOT binary reports the right | |
| # string from `total-recall --version` (CliApp.ResolveAppVersion reads | |
| # AssemblyInformationalVersionAttribute at runtime). Stripping the | |
| # leading "v" matches the SemVer convention embedded in package.json. | |
| # Pre-release suffixes (e.g. "0.8.0-beta.5") flow through unchanged | |
| # because InformationalVersion accepts SemVer 2.0 strings. | |
| # | |
| # REF_NAME is passed via env: (never interpolated directly into run:) | |
| # per GitHub Actions script-injection guidance. | |
| - name: Publish (Unix) | |
| if: runner.os != 'Windows' | |
| shell: bash | |
| env: | |
| RID: ${{ matrix.rid }} | |
| REF_NAME: ${{ github.ref_name }} | |
| run: | | |
| set -euo pipefail | |
| VERSION="${REF_NAME#v}" | |
| dotnet publish src/TotalRecall.Host/TotalRecall.Host.csproj \ | |
| -c Release \ | |
| -r "$RID" \ | |
| -p:PublishAot=true \ | |
| -p:Version="$VERSION" \ | |
| -p:InformationalVersion="$VERSION" | |
| - name: Publish (Windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| env: | |
| RID: ${{ matrix.rid }} | |
| REF_NAME: ${{ github.ref_name }} | |
| run: | | |
| $version = $env:REF_NAME -replace '^v','' | |
| dotnet publish src/TotalRecall.Host/TotalRecall.Host.csproj ` | |
| -c Release ` | |
| -r "$env:RID" ` | |
| -p:PublishAot=true ` | |
| -p:Version="$version" ` | |
| -p:InformationalVersion="$version" | |
| - name: Stage publish tree into binaries (Unix) | |
| if: runner.os != 'Windows' | |
| shell: bash | |
| env: | |
| RID: ${{ matrix.rid }} | |
| EXE: ${{ matrix.exe }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "binaries/$RID" | |
| cp -a "src/TotalRecall.Host/bin/Release/net8.0/$RID/publish/." "binaries/$RID/" | |
| echo "--- staged tree ---" | |
| ls -la "binaries/$RID" | |
| test -f "binaries/$RID/$EXE" | |
| - name: Stage publish tree into binaries (Windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| env: | |
| RID: ${{ matrix.rid }} | |
| EXE: ${{ matrix.exe }} | |
| run: | | |
| $dest = "binaries/$env:RID" | |
| New-Item -ItemType Directory -Force -Path $dest | Out-Null | |
| Copy-Item -Recurse -Force "src/TotalRecall.Host/bin/Release/net8.0/$env:RID/publish/*" $dest | |
| Write-Host "--- staged tree ---" | |
| Get-ChildItem $dest | |
| if (-not (Test-Path "$dest/$env:EXE")) { | |
| throw "Expected executable $dest/$env:EXE missing after staging" | |
| } | |
| - name: Upload artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.artifact }} | |
| path: binaries/${{ matrix.rid }} | |
| if-no-files-found: error | |
| retention-days: 7 | |
| publish: | |
| name: Publish npm package | |
| needs: build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@v4 | |
| - name: Setup Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| registry-url: 'https://registry.npmjs.org' | |
| - name: Download linux-x64 artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: total-recall-linux-x64 | |
| path: binaries/linux-x64 | |
| - name: Download linux-arm64 artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: total-recall-linux-arm64 | |
| path: binaries/linux-arm64 | |
| - name: Download osx-arm64 artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: total-recall-osx-arm64 | |
| path: binaries/osx-arm64 | |
| - name: Download win-x64 artifact | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: total-recall-win-x64 | |
| path: binaries/win-x64 | |
| - name: Verify all four RIDs staged | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| missing=0 | |
| for f in \ | |
| binaries/linux-x64/total-recall \ | |
| binaries/linux-arm64/total-recall \ | |
| binaries/osx-arm64/total-recall \ | |
| binaries/win-x64/total-recall.exe; do | |
| if [ ! -f "$f" ]; then | |
| echo "MISSING: $f" >&2 | |
| missing=1 | |
| else | |
| echo "OK: $f ($(stat -c%s "$f") bytes)" | |
| fi | |
| done | |
| if [ "$missing" -ne 0 ]; then | |
| echo "One or more RIDs missing from staged binaries/ tree" >&2 | |
| exit 1 | |
| fi | |
| echo "--- full binaries/ tree ---" | |
| find binaries -maxdepth 2 -type f | sort | |
| - name: Restore executable bit on Unix binaries | |
| shell: bash | |
| run: | | |
| chmod +x binaries/linux-x64/total-recall | |
| chmod +x binaries/linux-arm64/total-recall | |
| chmod +x binaries/osx-arm64/total-recall | |
| - name: npm publish | |
| env: | |
| NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} | |
| # Prerelease-aware dist-tag routing. If package.json version contains | |
| # a dash (e.g. 0.8.0-beta.1), publish under the matching dist-tag | |
| # (beta, rc, alpha) so "latest" is NOT clobbered. Only stable versions | |
| # publish to latest. No untrusted github.event.* input is read here; | |
| # the version string comes from the committed package.json at the | |
| # tagged SHA. | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| case "$VERSION" in | |
| *-*) | |
| PRERELEASE_TAG="${VERSION##*-}" | |
| PRERELEASE_TAG="${PRERELEASE_TAG%%.*}" | |
| echo "Publishing $VERSION under dist-tag $PRERELEASE_TAG" | |
| npm publish --tag "$PRERELEASE_TAG" | |
| ;; | |
| *) | |
| echo "Publishing $VERSION under dist-tag latest" | |
| npm publish | |
| ;; | |
| esac | |
| - name: Create GitHub deployment | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| VERSION=$(node -p "require('./package.json').version") | |
| DEPLOY_ID=$(gh api repos/${{ github.repository }}/deployments \ | |
| --input - \ | |
| --jq '.id' <<PAYLOAD | |
| {"ref":"${{ github.sha }}","environment":"npm-publish","description":"v${VERSION} published to npm","auto_merge":false,"required_contexts":[]} | |
| PAYLOAD | |
| ) | |
| gh api "repos/${{ github.repository }}/deployments/${DEPLOY_ID}/statuses" \ | |
| -f state="success" \ | |
| -f description="v${VERSION} published to npm" \ | |
| -f environment_url="https://www.npmjs.com/package/@strvmarv/total-recall/v/${VERSION}" | |
| - name: Stage per-RID release assets | |
| shell: bash | |
| # The AOT binary alone is NOT runnable — it depends on sibling | |
| # libonnxruntime.dylib, vec0.dylib (via sqlite-vec), the models/ | |
| # subtree, and any other native runtime assets staged into | |
| # binaries/<rid>/ by the matrix publish step. Uploading just the | |
| # executable (as 0.8.0-beta.4 did) produces a TypeInitializationException | |
| # at first DB open because Microsoft.ML.OnnxRuntime cannot P/Invoke | |
| # into the missing libonnxruntime.dylib. | |
| # | |
| # Ship the entire publish tree per RID as a compressed archive: | |
| # - Unix RIDs -> .tar.gz (preserves executable bit + symlinks) | |
| # - Windows -> .zip (native Windows tooling) | |
| # | |
| # scripts/fetch-binary.js downloads the matching archive, extracts | |
| # it into binaries/<rid>/, and re-asserts the executable bit. | |
| run: | | |
| set -euo pipefail | |
| mkdir -p release-assets | |
| # tar -C <dir> -czf <out> . packs the contents of <dir> at the | |
| # archive root so extraction with `tar -xzf archive -C dest` | |
| # drops them straight into dest/ without a leading <rid>/ dir. | |
| # | |
| # All RIDs (including win-x64) use .tar.gz. The publish runner is | |
| # ubuntu-latest where `tar` is GNU tar, NOT bsdtar — GNU tar's -a | |
| # selects a compression program from the suffix and falls through | |
| # to uncompressed for .zip, producing a tar file with a misleading | |
| # extension. v0.8.0-beta.6's win-x64.zip was actually a POSIX tar | |
| # archive that broke any Windows extraction tool requiring real | |
| # PKZIP format. Switching the Windows leg to .tar.gz too keeps | |
| # one archive format and one extraction code path. Windows 10+ | |
| # ships tar.exe (bsdtar/libarchive) which handles .tar.gz natively | |
| # since 1803, and scripts/fetch-binary.js calls it directly on | |
| # Windows installs. | |
| tar -C binaries/linux-x64 -czf release-assets/total-recall-linux-x64.tar.gz . | |
| tar -C binaries/linux-arm64 -czf release-assets/total-recall-linux-arm64.tar.gz . | |
| tar -C binaries/osx-arm64 -czf release-assets/total-recall-osx-arm64.tar.gz . | |
| tar -C binaries/win-x64 -czf release-assets/total-recall-win-x64.tar.gz . | |
| ls -la release-assets/ | |
| echo "--- archive contents preview ---" | |
| tar -tzf release-assets/total-recall-osx-arm64.tar.gz | head -20 | |
| - name: Attach archives to GitHub release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: | | |
| release-assets/total-recall-linux-x64.tar.gz | |
| release-assets/total-recall-linux-arm64.tar.gz | |
| release-assets/total-recall-osx-arm64.tar.gz | |
| release-assets/total-recall-win-x64.tar.gz | |
| prerelease: ${{ contains(github.ref_name, '-') }} | |
| fail_on_unmatched_files: true |