code-buster 0.11.0

Repository-aware static analysis for AI-assisted development
Documentation
name: Code Buster Release

on:
  workflow_dispatch:
    inputs:
      version:
        description: Cargo package version already prepared on main, without the v prefix
        required: true
        type: string

concurrency:
  group: code-buster-release
  cancel-in-progress: false

permissions:
  contents: read

jobs:
  verify:
    runs-on: ubuntu-latest
    outputs:
      tag: ${{ steps.release.outputs.tag }}
    steps:
      - name: Require the main branch
        if: github.ref != 'refs/heads/main'
        run: |
          echo 'Releases must be dispatched from main.' >&2
          exit 1
      - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
        with:
          fetch-depth: 0
      - uses: dtolnay/rust-toolchain@360a4e93673de6630fac2478bc9e35244b01a759 # 1.88.0
        with:
          components: clippy,rustfmt
      - name: Validate release version
        id: release
        env:
          REQUESTED_VERSION: ${{ inputs.version }}
        run: |
          if ! [[ "$REQUESTED_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?(\+[0-9A-Za-z]+([.-][0-9A-Za-z]+)*)?$ ]]; then
            echo "invalid semantic version: $REQUESTED_VERSION" >&2
            exit 1
          fi
          PACKAGE_VERSION="$(cargo metadata --no-deps --format-version 1 | jq -r '.packages[] | select(.name == "code-buster") | .version')"
          if [[ "$PACKAGE_VERSION" != "$REQUESTED_VERSION" ]]; then
            echo "Cargo version $PACKAGE_VERSION does not match requested version $REQUESTED_VERSION" >&2
            exit 1
          fi
          if ! grep -Fqx "## $REQUESTED_VERSION" CHANGELOG.md; then
            echo "CHANGELOG.md has no release heading for $REQUESTED_VERSION" >&2
            exit 1
          fi
          if ! grep -Fqx 'cargo install code-buster --locked' README.md; then
            echo 'README.md does not contain the crates.io install command' >&2
            exit 1
          fi
          if ! grep -Fq -- "cargo install code-buster --version $REQUESTED_VERSION --locked" integrations/github/code-buster.yml; then
            echo "GitHub integration does not pin crates.io version $REQUESTED_VERSION" >&2
            exit 1
          fi
          echo "tag=v$REQUESTED_VERSION" >> "$GITHUB_OUTPUT"
      - name: Verify reviewed changelog release notes
        env:
          RELEASE_VERSION: ${{ inputs.version }}
        run: |
          python3 -B -m unittest tool/test_release_notes.py
          python3 tool/release_notes.py "v$RELEASE_VERSION" "$RUNNER_TEMP/release-notes.md"
      - run: cargo fmt --all -- --check
      - run: cargo clippy --all-targets --all-features --locked -- -D warnings
      - run: cargo test --all-targets --all-features --locked
      - run: cargo package --locked

  resolve-tag:
    needs: verify
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
        with:
          fetch-depth: 0
      - name: Resolve release tag
        env:
          RELEASE_TAG: ${{ needs.verify.outputs.tag }}
        run: |
          if git show-ref --verify --quiet "refs/tags/$RELEASE_TAG"; then
            TAG_REVISION="$(git rev-list -n 1 "$RELEASE_TAG")"
            if [[ "$TAG_REVISION" != "$GITHUB_SHA" ]]; then
              echo "$RELEASE_TAG already points to $TAG_REVISION instead of $GITHUB_SHA" >&2
              exit 1
            fi
            echo "Using existing tag $RELEASE_TAG."
          else
            git tag "$RELEASE_TAG" "$GITHUB_SHA"
            git push origin "$RELEASE_TAG"
          fi

  artifacts:
    needs: [verify, resolve-tag]
    strategy:
      fail-fast: false
      matrix:
        include:
          - os: ubuntu-latest
            platform: linux-x64
            executable: target/release/cb
            archive: code-buster-linux-x64.tar.gz
          - os: macos-15
            platform: macos-arm64
            executable: target/release/cb
            archive: code-buster-macos-arm64.tar.gz
          - os: windows-latest
            platform: windows-x64
            executable: target/release/cb.exe
            archive: code-buster-windows-x64.zip
    runs-on: ${{ matrix.os }}
    steps:
      - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
        with:
          ref: ${{ needs.verify.outputs.tag }}
      - uses: dtolnay/rust-toolchain@360a4e93673de6630fac2478bc9e35244b01a759 # 1.88.0
      - run: cargo build --release --locked
      - name: Smoke release binary
        shell: bash
        run: |
          '${{ matrix.executable }}' version
          '${{ matrix.executable }}' config --files --root tests/fixtures/preview --format json > files.json
          '${{ matrix.executable }}' summary --root tests/fixtures/preview --format json --advisory --allow-empty > summary.json
      - name: Archive Unix artifact
        if: runner.os != 'Windows'
        shell: bash
        run: |
          cp '${{ matrix.executable }}' cb
          tar -czf '${{ matrix.archive }}' cb LICENSE README.md
      - name: Archive Windows artifact
        if: runner.os == 'Windows'
        shell: pwsh
        run: Compress-Archive -Path '${{ matrix.executable }}',LICENSE,README.md -DestinationPath '${{ matrix.archive }}'
      - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
        with:
          name: ${{ matrix.platform }}
          path: ${{ matrix.archive }}
          if-no-files-found: error

  publish-crate:
    needs: [verify, resolve-tag, artifacts]
    runs-on: ubuntu-latest
    environment: release
    permissions:
      contents: read
      id-token: write
    steps:
      - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
        with:
          ref: ${{ needs.verify.outputs.tag }}
      - uses: dtolnay/rust-toolchain@360a4e93673de6630fac2478bc9e35244b01a759 # 1.88.0
      - name: Authenticate with crates.io
        id: crates-auth
        uses: rust-lang/crates-io-auth-action@c6f97d42243bad5fab37ca0427f495c86d5b1a18 # v1.0.5
      - name: Publish crate
        run: cargo publish --locked
        env:
          CARGO_REGISTRY_TOKEN: ${{ steps.crates-auth.outputs.token }}

  publish-github-release:
    needs: [verify, artifacts, publish-crate]
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5
        with:
          ref: ${{ needs.verify.outputs.tag }}
      - name: Extract reviewed changelog notes
        run: python3 tool/release_notes.py '${{ needs.verify.outputs.tag }}' release-notes.md
      - uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8
        with:
          path: dist
          merge-multiple: true
      - name: Create checksums
        run: cd dist && sha256sum -- * > SHA256SUMS
      - name: Publish GitHub release with changelog notes
        uses: softprops/action-gh-release@3bb12739c298aeb8a4eeaf626c5b8d85266b0e65 # v2
        with:
          tag_name: ${{ needs.verify.outputs.tag }}
          body_path: release-notes.md
          files: |
            dist/*