name: code-intel-release on: push: tags: - "v*" # Build jobs only need to read the repository. The write-capable scopes # (contents for release creation, id-token/attestations for provenance) # are granted only to the publish job below, so no build or validation # step ever holds a token that could publish or mutate a release. permissions: contents: read # DR-0018: no PowerShell. Step logic shared with ci.yml lives in # .github/scripts/ci.py. defaults: run: shell: bash jobs: admission-policy: uses: ./.github/workflows/admission-policy.yml release-gate: needs: admission-policy # Tag and version validation plus the full test suites. Publishing # happens only in the publish job, after every platform package has # passed its own gates. runs-on: windows-latest steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - name: Setup Python uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.14" # GA tags must be signed (docs/RELEASE_SIGNING.md); beta/rc tags skip that. - name: Validate release tag, package version and signature run: python .github/scripts/ci.py release-tag --tag "$GITHUB_REF_NAME" - name: Validate Skill package and bootstrap security run: | python tests/test_repository_layout.py -v python tests/test_skill_package.py -v python tests/test_skill_attestation.py -v - name: Setup Rust run: | rustup toolchain install rustup show active-toolchain - name: Install pinned ripgrep run: python .github/scripts/ci.py install-tool rg - name: Rust format run: cargo fmt -p code-intel -- --check - name: Rust check run: cargo check --locked - name: Rust tests run: cargo test -p code-intel --locked package: needs: release-gate # Each platform package must pass the candidate's own self-scan, then # install through the Skill bootstrap and pass the same Sentrux closure # from the installed release before publish may take it. strategy: fail-fast: false matrix: os: - windows-latest - macos-latest - ubuntu-latest runs-on: ${{ vars.CI_5070X_ENABLED == 'true' && (((github.event_name == 'push' || github.event_name == 'workflow_dispatch') && startsWith(github.ref, 'refs/heads/')) || (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository)) && (contains(fromJSON('["ubuntu-latest","ubuntu-24.04"]'), matrix.os) && 'ci-5070x-linux' || contains(fromJSON('["windows-latest","windows-2025"]'), matrix.os) && 'ci-5070x-windows') || matrix.os }} steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - name: Setup Python uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: python-version: "3.14" - name: Setup Rust run: | rustup toolchain install rustup show active-toolchain - name: Install pinned ripgrep run: python .github/scripts/ci.py install-tool rg - name: Build Rust CLI run: cargo build -p code-intel --release --locked - name: Authoritative self-scan (release blocking) run: python .github/scripts/ci.py sentrux-closure --binary target/release/code-intel --repo . --work "$RUNNER_TEMP/release-self-scan" --final-name release-self-scan --require-pass # Packaged from `git archive HEAD`, never the working tree, so no # earlier step can change what ships. - name: Package id: package run: python .github/scripts/ci.py package --tag "$GITHUB_REF_NAME" --out dist - name: Install the package through the Skill bootstrap id: install run: python .github/scripts/ci.py install-package --zip "${{ steps.package.outputs.zip }}" --tag "$GITHUB_REF_NAME" --report "$RUNNER_TEMP/bootstrap.json" - name: Installed graph binary, PATH and CODE_INTEL_HOME run: python .github/scripts/ci.py installed-checks --report "$RUNNER_TEMP/bootstrap.json" # The installed release, not the checkout, must publish a committed, # snapshot-bound Sentrux closure; stdout is never authority. - name: Packaged Sentrux capability closure run: python .github/scripts/ci.py sentrux-closure --binary "${{ steps.install.outputs.release_bin }}/code-intel" --repo "${{ steps.install.outputs.release_root }}" --work "$RUNNER_TEMP/packaged-scan" --final-name "release-packaged-sentrux-$GITHUB_RUN_ID" --require-pass - name: Upload release dist artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: release-dist-${{ steps.package.outputs.platform }} path: | dist/code-intel-pipeline-*.zip dist/code-intel-pipeline-*.zip.sha256 dist/code-intel-pipeline-*.zip.release-manifest.json if-no-files-found: error publish: # Single release creator: every platform package must already have # passed its gates, and only this job holds a write-capable token. runs-on: ubuntu-latest needs: package permissions: contents: write id-token: write attestations: write steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 - name: Download release dist artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: "release-dist-*" path: dist merge-multiple: true # A partial or mismatched inventory must never publish. - name: Verify release inventory run: python3 .github/scripts/ci.py verify-inventory --dir dist --tag "$GITHUB_REF_NAME" --commit "$GITHUB_SHA" - name: Attest build provenance uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2 with: subject-path: "dist/code-intel-pipeline-*.zip" - name: Create GitHub Release env: GH_TOKEN: ${{ github.token }} run: | tag="$GITHUB_REF_NAME" assets=() for platform in windows macos linux; do asset="dist/code-intel-pipeline-$tag-$platform.zip" assets+=("$asset" "$asset.sha256" "$asset.release-manifest.json") done if gh release view "$tag" >/dev/null 2>&1; then # No --clobber: a leaked contents:write token must not be able to # silently replace published assets. Delete deliberately first # (gh release delete-asset) if a re-run truly needs to. gh release upload "$tag" "${assets[@]}" elif [[ "$tag" == *-* ]]; then gh release create "$tag" "${assets[@]}" --title "$tag" --prerelease \ --notes "Code Intel Pipeline $tag. Pre-release build for integration testing before stable promotion." else gh release create "$tag" "${assets[@]}" --title "$tag" \ --notes "Code Intel Pipeline $tag. Stable release." fi