v0.0.22 #31
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 | |
| on: | |
| release: | |
| types: [published] | |
| workflow_dispatch: | |
| inputs: | |
| release_tag: | |
| description: "Existing release tag to rebuild and publish, for example v0.0.17" | |
| required: false | |
| type: string | |
| # Skip beta/prerelease tags — handled by release-beta.yml | |
| permissions: | |
| contents: write | |
| id-token: write | |
| attestations: write | |
| env: | |
| CARGO_TERM_COLOR: always | |
| concurrency: | |
| group: release-${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build: | |
| name: Build ${{ matrix.name }} | |
| if: github.event_name == 'workflow_dispatch' || !github.event.release.prerelease | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - name: aarch64-macos | |
| runner: macos-14 | |
| target: aarch64-apple-darwin | |
| bottle_tag: arm64_sonoma | |
| archive: tar.gz | |
| - name: x86_64-linux | |
| runner: ubuntu-22.04 | |
| target: x86_64-unknown-linux-gnu | |
| bottle_tag: x86_64_linux | |
| archive: tar.gz | |
| - name: aarch64-linux | |
| runner: ubuntu-22.04-arm | |
| target: aarch64-unknown-linux-gnu | |
| archive: tar.gz | |
| - name: x86_64-windows | |
| runner: windows-latest | |
| target: x86_64-pc-windows-msvc | |
| archive: zip | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ github.event_name == 'workflow_dispatch' && inputs.release_tag || github.ref }} | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: "22" | |
| cache: npm | |
| cache-dependency-path: dashboard/package-lock.json | |
| - name: Build dashboard assets | |
| working-directory: dashboard | |
| run: | | |
| npm ci | |
| npm run build | |
| - uses: dtolnay/rust-toolchain@stable | |
| with: | |
| targets: ${{ matrix.target }} | |
| - name: Use lld-link | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| where.exe lld-link | |
| lld-link --version | |
| "RUSTFLAGS=-C linker=lld-link.exe" >> $env:GITHUB_ENV | |
| - name: Cache Rust build | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| shared-key: release-${{ matrix.target }} | |
| cache-on-failure: true | |
| - name: Build release binary | |
| run: cargo build --release --target ${{ matrix.target }} | |
| - name: Get version | |
| id: version | |
| shell: bash | |
| run: | | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ] && [ -n "${{ inputs.release_tag }}" ]; then | |
| TAG="${{ inputs.release_tag }}" | |
| VERSION="${TAG#v}" | |
| elif [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then | |
| TAG="dry-run-${GITHUB_SHA::7}" | |
| VERSION="${TAG#v}" | |
| else | |
| TAG="${GITHUB_REF_NAME}" | |
| VERSION="${GITHUB_REF_NAME#v}" | |
| fi | |
| echo "tag=${TAG}" >> "$GITHUB_OUTPUT" | |
| echo "version=${VERSION}" >> "$GITHUB_OUTPUT" | |
| # --- Binary archive (all platforms) --- | |
| - name: Package binary (unix) | |
| if: matrix.archive == 'tar.gz' | |
| run: | | |
| cd target/${{ matrix.target }}/release | |
| tar czf ../../../tracedecay-${{ steps.version.outputs.tag }}-${{ matrix.name }}.tar.gz tracedecay | |
| cd ../../.. | |
| - name: Generate archive attestation (unix) | |
| if: matrix.archive == 'tar.gz' && github.event_name == 'release' | |
| uses: actions/attest@v4 | |
| with: | |
| subject-path: tracedecay-${{ steps.version.outputs.tag }}-${{ matrix.name }}.${{ matrix.archive }} | |
| - name: Upload binary archive artifact (unix) | |
| if: matrix.archive == 'tar.gz' | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: binary-${{ matrix.name }} | |
| path: tracedecay-${{ steps.version.outputs.tag }}-${{ matrix.name }}.${{ matrix.archive }} | |
| - name: Package binary (windows) | |
| if: matrix.archive == 'zip' | |
| shell: pwsh | |
| run: | | |
| Compress-Archive -Path target/${{ matrix.target }}/release/tracedecay.exe -DestinationPath tracedecay-${{ steps.version.outputs.tag }}-${{ matrix.name }}.zip -Force | |
| - name: Generate archive attestation (windows) | |
| if: matrix.archive == 'zip' && github.event_name == 'release' | |
| uses: actions/attest@v4 | |
| with: | |
| subject-path: tracedecay-${{ steps.version.outputs.tag }}-${{ matrix.name }}.${{ matrix.archive }} | |
| - name: Upload binary archive artifact (windows) | |
| if: matrix.archive == 'zip' | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: binary-${{ matrix.name }} | |
| path: tracedecay-${{ steps.version.outputs.tag }}-${{ matrix.name }}.${{ matrix.archive }} | |
| # --- Homebrew bottle (only for platforms with bottle_tag) --- | |
| - name: Package Homebrew bottle | |
| if: matrix.bottle_tag | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| BOTTLE_TAG="${{ matrix.bottle_tag }}" | |
| mkdir -p tracedecay/${VERSION}/bin | |
| cp target/${{ matrix.target }}/release/tracedecay tracedecay/${VERSION}/bin/tracedecay | |
| chmod +x tracedecay/${VERSION}/bin/tracedecay | |
| tar czf "tracedecay-${VERSION}.${BOTTLE_TAG}.bottle.tar.gz" tracedecay/ | |
| - name: Generate bottle attestation | |
| if: matrix.bottle_tag && github.event_name == 'release' | |
| uses: actions/attest@v4 | |
| with: | |
| subject-path: tracedecay-${{ steps.version.outputs.version }}.${{ matrix.bottle_tag }}.bottle.tar.gz | |
| - name: Upload bottle artifact | |
| if: matrix.bottle_tag | |
| uses: actions/upload-artifact@v6 | |
| with: | |
| name: bottle-${{ matrix.bottle_tag }} | |
| path: "tracedecay-*.bottle.tar.gz" | |
| publish-assets: | |
| name: Publish release assets | |
| if: | | |
| needs.build.result == 'success' && | |
| ( | |
| (github.event_name == 'release' && !github.event.release.prerelease) || | |
| (github.event_name == 'workflow_dispatch' && inputs.release_tag != '') | |
| ) | |
| needs: build | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Get release tag | |
| id: release | |
| run: | | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then | |
| TAG="${{ inputs.release_tag }}" | |
| else | |
| TAG="${GITHUB_REF_NAME}" | |
| fi | |
| echo "tag=${TAG}" >> "$GITHUB_OUTPUT" | |
| - name: Download binary artifacts | |
| uses: actions/download-artifact@v7 | |
| with: | |
| pattern: binary-* | |
| path: binaries | |
| merge-multiple: true | |
| - name: Upload binaries to release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| find binaries -type f -name 'tracedecay-*' -print -exec \ | |
| gh release upload "${{ steps.release.outputs.tag }}" {} --repo "${{ github.repository }}" --clobber \; | |
| update-homebrew: | |
| name: Update Homebrew tap | |
| if: | | |
| needs.build.result == 'success' && | |
| ( | |
| (github.event_name == 'release' && !github.event.release.prerelease) || | |
| (github.event_name == 'workflow_dispatch' && inputs.release_tag != '') | |
| ) | |
| needs: [build, publish-assets] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then | |
| TAG="${{ inputs.release_tag }}" | |
| else | |
| TAG="${GITHUB_REF_NAME}" | |
| fi | |
| VERSION="${TAG#v}" | |
| echo "tag=$TAG" >> "$GITHUB_OUTPUT" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Download bottle artifacts | |
| uses: actions/download-artifact@v7 | |
| with: | |
| pattern: bottle-* | |
| path: bottles | |
| merge-multiple: true | |
| - name: Upload bottles to release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| for f in bottles/tracedecay-*.bottle.tar.gz; do | |
| gh release upload "${{ steps.version.outputs.tag }}" "$f" --clobber | |
| done | |
| - name: Download source tarball | |
| run: | | |
| curl -sL "https://github.com/${{ github.repository }}/archive/refs/tags/${{ steps.version.outputs.tag }}.tar.gz" -o "source.tar.gz" | |
| - name: Compute SHA256 hashes | |
| id: hashes | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| SOURCE_SHA=$(sha256sum source.tar.gz | awk '{print $1}') | |
| echo "source_sha=${SOURCE_SHA}" >> "$GITHUB_OUTPUT" | |
| for f in bottles/tracedecay-*.bottle.tar.gz; do | |
| tag=$(basename "$f" | sed "s/tracedecay-${VERSION}\.\(.*\)\.bottle\.tar\.gz/\1/") | |
| sha=$(sha256sum "$f" | awk '{print $1}') | |
| echo "${tag}_sha=${sha}" >> "$GITHUB_OUTPUT" | |
| done | |
| # NOTE: the Homebrew tap (ScriptedAlchemy/homebrew-tap) is an external | |
| # repo — the previous formula there must be removed/renamed | |
| # separately; this step only writes the new Formula/tracedecay.rb. | |
| - name: Update formula | |
| env: | |
| TAP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ steps.version.outputs.version }}" | |
| SOURCE_SHA="${{ steps.hashes.outputs.source_sha }}" | |
| ARM64_SONOMA_SHA="${{ steps.hashes.outputs.arm64_sonoma_sha }}" | |
| X86_64_LINUX_SHA="${{ steps.hashes.outputs.x86_64_linux_sha }}" | |
| git clone "https://x-access-token:${TAP_GITHUB_TOKEN}@github.com/ScriptedAlchemy/homebrew-tap.git" tap | |
| mkdir -p tap/Formula | |
| cat > tap/Formula/tracedecay.rb << EOF | |
| class Tracedecay < Formula | |
| desc "Code intelligence tool that builds semantic knowledge graphs from source code" | |
| homepage "https://github.com/ScriptedAlchemy/tracedecay" | |
| url "https://github.com/ScriptedAlchemy/tracedecay/archive/refs/tags/v${VERSION}.tar.gz" | |
| sha256 "${SOURCE_SHA}" | |
| license "MIT" | |
| bottle do | |
| root_url "https://github.com/ScriptedAlchemy/tracedecay/releases/download/v${VERSION}" | |
| sha256 cellar: :any_skip_relocation, arm64_sonoma: "${ARM64_SONOMA_SHA}" | |
| sha256 cellar: :any_skip_relocation, x86_64_linux: "${X86_64_LINUX_SHA}" | |
| end | |
| depends_on "rust" => :build | |
| def install | |
| system "cargo", "install", *std_cargo_args | |
| end | |
| test do | |
| system "#{bin}/tracedecay", "--help" | |
| end | |
| end | |
| EOF | |
| cd tap | |
| # Clean up the legacy pre-rebrand formula if it still exists. | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add Formula/tracedecay.rb | |
| git diff --cached --quiet || git commit -m "tracedecay ${VERSION}" | |
| git push | |
| update-scoop: | |
| name: Update Scoop bucket | |
| if: | | |
| needs.build.result == 'success' && | |
| ( | |
| (github.event_name == 'release' && !github.event.release.prerelease) || | |
| (github.event_name == 'workflow_dispatch' && inputs.release_tag != '') | |
| ) | |
| needs: [build, publish-assets] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Get release info | |
| id: release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then | |
| TAG="${{ inputs.release_tag }}" | |
| else | |
| TAG="${GITHUB_REF_NAME}" | |
| fi | |
| VERSION="${TAG#v}" | |
| echo "version=${VERSION}" >> "$GITHUB_OUTPUT" | |
| echo "tag=${TAG}" >> "$GITHUB_OUTPUT" | |
| gh release download "${TAG}" \ | |
| --repo "${{ github.repository }}" \ | |
| --pattern "tracedecay-${TAG}-x86_64-windows.zip" \ | |
| --dir . | |
| SHA256=$(sha256sum "tracedecay-${TAG}-x86_64-windows.zip" | cut -d' ' -f1) | |
| echo "sha256_win64=${SHA256}" >> "$GITHUB_OUTPUT" | |
| # NOTE: the Scoop bucket (ScriptedAlchemy/scoop-bucket) is an external | |
| # repo — the previous bucket manifest there must be removed separately; | |
| # this step only writes the new bucket/tracedecay.json. | |
| - name: Update Scoop manifest | |
| env: | |
| SCOOP_GITHUB_TOKEN: ${{ secrets.TAP_GITHUB_TOKEN }} | |
| run: | | |
| VERSION="${{ steps.release.outputs.version }}" | |
| TAG="${{ steps.release.outputs.tag }}" | |
| SHA256="${{ steps.release.outputs.sha256_win64 }}" | |
| cat > tracedecay.json << EOF | |
| { | |
| "version": "${VERSION}", | |
| "description": "Code intelligence tool that builds semantic knowledge graphs from source code", | |
| "homepage": "https://github.com/ScriptedAlchemy/tracedecay", | |
| "license": "MIT", | |
| "architecture": { | |
| "64bit": { | |
| "url": "https://github.com/ScriptedAlchemy/tracedecay/releases/download/${TAG}/tracedecay-${TAG}-x86_64-windows.zip", | |
| "hash": "${SHA256}" | |
| } | |
| }, | |
| "bin": "tracedecay.exe", | |
| "checkver": { | |
| "github": "https://github.com/ScriptedAlchemy/tracedecay" | |
| }, | |
| "autoupdate": { | |
| "architecture": { | |
| "64bit": { | |
| "url": "https://github.com/ScriptedAlchemy/tracedecay/releases/download/v\$version/tracedecay-v\$version-x86_64-windows.zip" | |
| } | |
| } | |
| } | |
| } | |
| EOF | |
| git clone "https://x-access-token:${SCOOP_GITHUB_TOKEN}@github.com/ScriptedAlchemy/scoop-bucket.git" scoop-repo | |
| cd scoop-repo | |
| mkdir -p bucket | |
| cp ../tracedecay.json bucket/tracedecay.json | |
| # Clean up legacy pre-rebrand manifests (root-level and bucket/). | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add bucket/tracedecay.json | |
| git diff --cached --quiet || git commit -m "tracedecay ${VERSION}" | |
| git push | |
| # Rewrites the MCP registry manifest (server.json) from the actual release | |
| # artifacts so the version, download URLs, and fileSha256 digests always | |
| # describe real uploaded assets. Skips (with a warning) when the release has | |
| # no MCPB packages, since those are not yet produced by the build matrix. | |
| update-server-json: | |
| name: Update server.json manifest | |
| if: | | |
| needs.build.result == 'success' && | |
| ( | |
| (github.event_name == 'release' && !github.event.release.prerelease) || | |
| (github.event_name == 'workflow_dispatch' && inputs.release_tag != '') | |
| ) | |
| needs: [build, publish-assets] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| with: | |
| ref: master | |
| - name: Rewrite server.json from release artifacts | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| set -euo pipefail | |
| if [ "${GITHUB_EVENT_NAME}" = "workflow_dispatch" ]; then | |
| TAG="${{ inputs.release_tag }}" | |
| else | |
| TAG="${GITHUB_REF_NAME}" | |
| fi | |
| VERSION="${TAG#v}" | |
| REPO="${{ github.repository }}" | |
| PLATFORMS="aarch64-macos:mcp.tar.gz x86_64-linux:mcp.tar.gz aarch64-linux:mcp.tar.gz x86_64-windows:mcp.zip" | |
| mkdir -p assets | |
| missing=0 | |
| for entry in $PLATFORMS; do | |
| platform="${entry%%:*}" | |
| ext="${entry#*:}" | |
| asset="tracedecay-${TAG}-${platform}.${ext}" | |
| if ! gh release download "$TAG" --repo "$REPO" --pattern "$asset" --dir assets; then | |
| echo "::warning::release asset ${asset} not found" | |
| missing=1 | |
| fi | |
| done | |
| if [ "$missing" -ne 0 ]; then | |
| echo "::warning::server.json not updated — this release has no complete MCPB package set" | |
| exit 0 | |
| fi | |
| printf '[' > sha-map.json | |
| sep="" | |
| for entry in $PLATFORMS; do | |
| platform="${entry%%:*}" | |
| ext="${entry#*:}" | |
| asset="tracedecay-${TAG}-${platform}.${ext}" | |
| sha=$(sha256sum "assets/${asset}" | cut -d' ' -f1) | |
| printf '%s{"platform":"%s","ext":"%s","sha":"%s"}' "$sep" "$platform" "$ext" "$sha" >> sha-map.json | |
| sep="," | |
| done | |
| printf ']' >> sha-map.json | |
| jq --arg v "$VERSION" --arg tag "$TAG" --arg repo "$REPO" --slurpfile map sha-map.json ' | |
| .version = $v | |
| | .packages = ($map[0] | map( | |
| { | |
| "registryType": "mcpb", | |
| "identifier": "https://github.com/\($repo)/releases/download/\($tag)/tracedecay-\($tag)-\(.platform).\(.ext)", | |
| "version": $v, | |
| "fileSha256": .sha, | |
| "packageArguments": [ | |
| { | |
| "type": "positional", | |
| "valueHint": "serve" | |
| } | |
| ], | |
| "transport": { | |
| "type": "stdio" | |
| } | |
| } | |
| ) | |
| ) | |
| ' server.json > server.json.tmp | |
| mv server.json.tmp server.json | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| git add server.json | |
| git diff --cached --quiet || git commit -m "chore(release): update server.json for ${VERSION}" | |
| git push |