Remove the Kotlin implementation; the Rust CLI is now the only one #1318
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: CI | |
| on: | |
| push: | |
| branches: [ master ] | |
| pull_request: | |
| branches: [ master ] | |
| # Job ids and display names are load-bearing: branch protection on master | |
| # requires them by name (`Rust candidate (Bazel 8.x)`, `test-jre21 (...)`, | |
| # `test-jre11-run-example (...)`, `release-artifacts (...)`). Several predate | |
| # the Kotlin implementation's removal and no longer describe what they run; | |
| # rename them only together with the branch-protection rule. | |
| jobs: | |
| # Every Rust check here runs through Bazel, with no cargo and no host Rust | |
| # toolchain: rules_rust downloads the compiler pinned in MODULE.bazel, so CI | |
| # and a local `bazel test` agree on the exact rustc. //:rust_clippy_check and | |
| # //:rust_format_check below stand in for `cargo clippy -- -D warnings` and | |
| # `cargo fmt --all -- --check`. //tools/... is the Python/Go release, e2e-split | |
| # and coverage tooling. | |
| rust-candidate: | |
| name: Rust candidate (Bazel ${{ matrix.bazel }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| bazel: ['8.x', '9.x'] | |
| steps: | |
| - name: Setup Go environment | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ^1.17 | |
| - name: Setup Bazelisk | |
| # Retries guard against transient proxy.golang.org/sum.golang.org module-fetch errors. | |
| run: | | |
| for i in 1 2 3; do | |
| go install github.com/bazelbuild/bazelisk@latest && break | |
| echo "bazelisk install failed (attempt $i); retrying in 10s..." | |
| sleep 10 | |
| done | |
| - uses: actions/checkout@v4 | |
| - name: Check Bazel build and tests | |
| env: | |
| USE_BAZEL_VERSION: ${{ matrix.bazel }} | |
| CARGO_BAZEL_ISOLATED: 'false' | |
| run: ~/go/bin/bazelisk test //:rust_tests //:rust_clippy_check //:rust_format_check //tools/... --enable_bzlmod=true --enable_workspace=false | |
| rust-candidate-e2e: | |
| name: Rust candidate E2E | |
| runs-on: ubuntu-latest | |
| steps: | |
| # bazel-diff itself needs no JDK, but the suite drives a nested Bazel over | |
| # fixture workspaces with Java targets, and Bazel's default | |
| # --java_runtime_version=local_jdk wants a host JDK for those. | |
| - name: Setup Java JDK | |
| uses: actions/setup-java@v4 | |
| with: | |
| distribution: 'temurin' | |
| java-version: '21' | |
| - name: Setup Go environment | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ^1.17 | |
| - name: Setup Bazelisk | |
| # $BAZEL is the nested Bazel //tests:e2e_test spawns for each fixture | |
| # workspace. Set explicitly because the fallback -- first `bazel` on | |
| # PATH -- resolves to the *outer* Bazel's own binary inside a test, | |
| # which ignores USE_BAZEL_VERSION. It reaches the test through the | |
| # target's env_inherit. | |
| run: | | |
| for i in 1 2 3; do | |
| go install github.com/bazelbuild/bazelisk@latest && break | |
| echo "bazelisk install failed (attempt $i); retrying in 10s..." | |
| sleep 10 | |
| done | |
| echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" | |
| echo "BAZEL=$(go env GOPATH)/bin/bazelisk" >> "$GITHUB_ENV" | |
| - uses: actions/checkout@v4 | |
| - name: Run native behavioral suite | |
| env: | |
| # Read twice: by the outer bazelisk, and by the nested one. | |
| USE_BAZEL_VERSION: '8.x' | |
| run: bazelisk test //tests:e2e_test --enable_bzlmod=true --enable_workspace=false | |
| # The e2e suites are split into one Bazel test target per case by | |
| # //tools/e2e:regen, whose output is checked in. This job is the gate that | |
| # keeps the checked-in split honest: :regen_check re-derives the case list | |
| # from the sources and fails when they differ, so an e2e test added, renamed | |
| # or removed without `make regen-e2e` cannot merge. | |
| # :split_e2e_tests_test covers the generator itself. | |
| e2e-split-regen: | |
| name: E2E split regen | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Setup Go environment | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ^1.17 | |
| - name: Setup Bazelisk | |
| # Retries guard against transient proxy.golang.org/sum.golang.org module-fetch errors. | |
| run: | | |
| for i in 1 2 3; do | |
| go install github.com/bazelbuild/bazelisk@latest && break | |
| echo "bazelisk install failed (attempt $i); retrying in 10s..." | |
| sleep 10 | |
| done | |
| - uses: actions/checkout@v4 | |
| - name: Check the e2e test split is up to date | |
| env: | |
| USE_BAZEL_VERSION: '8.x' | |
| run: ~/go/bin/bazelisk test //tools/e2e:regen_check //tools/e2e:split_e2e_tests_test --enable_bzlmod=true --enable_workspace=false --test_output=errors | |
| rust-candidate-msrv: | |
| name: Rust candidate MSRV | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Setup Go environment | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ^1.17 | |
| - name: Setup Bazelisk | |
| # Retries guard against transient proxy.golang.org/sum.golang.org module-fetch errors. | |
| run: | | |
| for i in 1 2 3; do | |
| go install github.com/bazelbuild/bazelisk@latest && break | |
| echo "bazelisk install failed (attempt $i); retrying in 10s..." | |
| sleep 10 | |
| done | |
| - uses: actions/checkout@v4 | |
| # Builds the crate with the toolchain pinned to `rust-version` in | |
| # Cargo.toml instead of the repo default. --extra_toolchains outranks the | |
| # registered toolchains, which is what makes the swap take: the MSRV | |
| # toolchain is declared in MODULE.bazel but deliberately not preferred. | |
| # Bazel has no `cargo check` equivalent, so this is a full build -- which | |
| # is strictly stronger, since it links as well as type-checks. | |
| # | |
| # The lint output groups are dropped because this job asks one question: | |
| # does the crate still compile on the oldest Rust it claims to support. | |
| # 1.85's clippy has a different lint set than the pinned toolchain's, so | |
| # leaving them on would fail this job for warnings that say nothing about | |
| # MSRV. //:rust_clippy_check and //:rust_format_check own that gate. | |
| - name: Check declared minimum Rust version | |
| env: | |
| USE_BAZEL_VERSION: '8.x' | |
| run: | | |
| ~/go/bin/bazelisk build //src:bazel-diff \ | |
| --extra_toolchains=@rust_toolchains//:rust_msrv__x86_64-unknown-linux-gnu__stable \ | |
| --output_groups=-clippy_checks,-rustfmt_checks \ | |
| --enable_bzlmod=true --enable_workspace=false | |
| # The coverage gate. The job id is historical (it used to run the JVM suites | |
| # on a JDK 21) and is kept because branch protection requires the | |
| # `test-jre21 (<os>, <bazel>)` checks by that name. | |
| test-jre21: | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| bazel: '8.x' | |
| - os: ubuntu-latest | |
| bazel: '9.x' | |
| - os: macos-latest | |
| bazel: '8.x' | |
| - os: macos-latest | |
| bazel: '9.x' | |
| steps: | |
| - name: Setup Go environment | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ^1.17 | |
| id: go | |
| - name: Setup Bazelisk | |
| # Retries guard against transient proxy.golang.org/sum.golang.org module-fetch errors. | |
| run: | | |
| for i in 1 2 3; do | |
| go install github.com/bazelbuild/bazelisk@latest && break | |
| echo "bazelisk install failed (attempt $i); retrying in 10s..." | |
| sleep 10 | |
| done | |
| export PATH=$PATH:$(go env GOPATH)/bin | |
| - uses: actions/checkout@v4 | |
| - name: Build license target | |
| env: | |
| USE_BAZEL_VERSION: ${{ matrix.bazel }} | |
| run: ~/go/bin/bazelisk build //:license --enable_bzlmod=true --enable_workspace=false | |
| - name: Run bazel-diff tests with coverage | |
| env: | |
| USE_BAZEL_VERSION: ${{ matrix.bazel }} | |
| # Retries guard against transient toolchain/crate fetch errors failing the whole job. | |
| run: | | |
| for i in 1 2 3; do | |
| ~/go/bin/bazelisk coverage --combined_report=lcov //src:cli_tests //src:rust_tests //tools:coverage_check_test //tools/coverage/... //tools/go/... --enable_bzlmod=true --enable_workspace=false && break | |
| if [ "$i" = 3 ]; then exit 1; fi | |
| echo "coverage run failed (attempt $i); retrying in 15s..." | |
| sleep 15 | |
| done | |
| - name: Upload coverage report | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: coverage-report-jre21-${{ matrix.os }}-bazel-${{ matrix.bazel }} | |
| path: bazel-out/_coverage/_coverage_report.dat | |
| if-no-files-found: warn | |
| - name: Enforce coverage threshold (>= 90% main-source line coverage) | |
| env: | |
| # Must match the coverage step above, otherwise bazelisk downloads the | |
| # default bazel from .bazelversion and starts a fresh server whose | |
| # output base loses track of the coverage report symlink (seen flaking | |
| # on macos-latest x bazel 9.x). | |
| USE_BAZEL_VERSION: ${{ matrix.bazel }} | |
| COVERAGE_THRESHOLD: '90' | |
| run: ~/go/bin/bazelisk run //tools:coverage-check -- --badge-json coverage.json bazel-out/_coverage/_coverage_report.dat | |
| - name: Enforce Go coverage threshold (>= 90% line coverage under tools/go/) | |
| env: | |
| # Must match the coverage step above; see the note on the previous step. | |
| USE_BAZEL_VERSION: ${{ matrix.bazel }} | |
| # Gate Go independently of the Rust overall so thin Go coverage can't hide | |
| # behind well-covered Rust (and vice versa). --include scopes the report to | |
| # Go production source only (tools/go/, which excludes tools/coverage_check.py). | |
| run: ~/go/bin/bazelisk run //tools:coverage-check -- --include tools/go/ --threshold 90 bazel-out/_coverage/_coverage_report.dat | |
| - name: Upload test logs | |
| uses: actions/upload-artifact@v4 | |
| if: always() | |
| with: | |
| name: test-logs-jre21-${{ matrix.os }}-bazel-${{ matrix.bazel }} | |
| path: bazel-testlogs/ | |
| if-no-files-found: warn | |
| # Runs the example script end to end against this repository, on every Bazel | |
| # version and workspace mode the tool supports. The job id is historical (the | |
| # JVM CLI was exercised on a JDK 11 here) and is kept because branch protection | |
| # requires the `test-jre11-run-example (...)` checks by that name. | |
| test-jre11-run-example: | |
| runs-on: ${{ matrix.os }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: ubuntu-latest | |
| bazel: '7.x' | |
| disable_workspace: 'false' | |
| extra_flags: '' | |
| - os: ubuntu-latest | |
| bazel: '7.x' | |
| disable_workspace: 'false' | |
| extra_flags: '--incompatible_disable_native_repo_rules' | |
| - os: ubuntu-latest | |
| bazel: '8.x' | |
| disable_workspace: 'true' | |
| extra_flags: '' | |
| - os: ubuntu-latest | |
| bazel: '8.6.0rc1' | |
| disable_workspace: 'true' | |
| extra_flags: '' | |
| - os: ubuntu-latest | |
| bazel: '8.x' | |
| disable_workspace: 'true' | |
| extra_flags: '--incompatible_disable_native_repo_rules' | |
| - os: ubuntu-latest | |
| bazel: '9.x' | |
| disable_workspace: 'true' | |
| extra_flags: '' | |
| - os: ubuntu-latest | |
| bazel: '9.x' | |
| disable_workspace: 'true' | |
| extra_flags: '--incompatible_disable_native_repo_rules' | |
| # Skip Windows + Bazel 7.x due to protobuf compilation issues on MSVC | |
| # Windows is tested with Bazel 8.x and 9.x which are more current | |
| - os: windows-latest | |
| bazel: '8.x' | |
| disable_workspace: 'true' | |
| extra_flags: '' | |
| - os: windows-latest | |
| bazel: '9.x' | |
| disable_workspace: 'true' | |
| extra_flags: '' | |
| steps: | |
| - name: Setup Go environment | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ^1.17 | |
| id: go | |
| - name: Setup Bazelisk (Linux/macOS) | |
| if: runner.os != 'Windows' | |
| # Retries guard against transient proxy.golang.org/sum.golang.org module-fetch errors. | |
| run: | | |
| for i in 1 2 3; do | |
| go install github.com/bazelbuild/bazelisk@latest && break | |
| echo "bazelisk install failed (attempt $i); retrying in 10s..." | |
| sleep 10 | |
| done | |
| export PATH=$PATH:$(go env GOPATH)/bin | |
| - name: Setup Bazelisk (Windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| for ($i = 1; $i -le 3; $i++) { | |
| go install github.com/bazelbuild/bazelisk@latest | |
| if ($LASTEXITCODE -eq 0) { break } | |
| Write-Host "bazelisk install failed (attempt $i); retrying in 10s..." | |
| Start-Sleep -Seconds 10 | |
| } | |
| $env:PATH = "$env:PATH;$(go env GOPATH)\bin" | |
| echo "$env:USERPROFILE\go\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append | |
| - uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Run bazel-diff example script (Linux) | |
| if: runner.os != 'Windows' | |
| env: | |
| USE_BAZEL_VERSION: ${{ matrix.bazel }} | |
| BAZEL_DIFF_DISABLE_WORKSPACE: ${{ matrix.disable_workspace }} | |
| BAZEL_DIFF_FORCE_CHECKOUT: true | |
| BAZEL_EXTRA_COMMAND_OPTIONS: ${{ matrix.extra_flags }} | |
| # Retries guard against transient release-asset fetch errors (e.g. a 500 from | |
| # GitHub Releases downloading Bazel module deps). | |
| run: | | |
| for i in 1 2 3; do | |
| ./bazel-diff-example.sh "$GITHUB_WORKSPACE" ~/go/bin/bazelisk $(git rev-parse HEAD~1) $(git rev-parse HEAD) && break | |
| if [ "$i" = 3 ]; then exit 1; fi | |
| echo "example script failed (attempt $i); retrying in 15s..." | |
| sleep 15 | |
| done | |
| - name: Run bazel-diff example script (Windows) | |
| if: runner.os == 'Windows' | |
| env: | |
| USE_BAZEL_VERSION: ${{ matrix.bazel }} | |
| BAZEL_DIFF_DISABLE_WORKSPACE: ${{ matrix.disable_workspace }} | |
| BAZEL_DIFF_FORCE_CHECKOUT: true | |
| BAZEL_EXTRA_COMMAND_OPTIONS: ${{ matrix.extra_flags }} | |
| shell: pwsh | |
| # Retries guard against transient release-asset fetch errors (e.g. a 500 from | |
| # GitHub Releases downloading Bazel module deps). | |
| run: | | |
| $prevRev = git rev-parse HEAD~1 | |
| $currRev = git rev-parse HEAD | |
| for ($i = 1; $i -le 3; $i++) { | |
| .\bazel-diff-example.ps1 -WorkspacePath "$env:GITHUB_WORKSPACE" -BazelPath "$env:USERPROFILE\go\bin\bazelisk.exe" -PreviousRevision $prevRev -FinalRevision $currRev | |
| if ($LASTEXITCODE -eq 0) { break } | |
| if ($i -eq 3) { exit 1 } | |
| Write-Host "example script failed (attempt $i); retrying in 15s..." | |
| Start-Sleep -Seconds 15 | |
| } | |
| # Verifies per-PR that everything a release ships still builds, on every | |
| # platform it ships for. It publishes nothing: release.yaml owns that, via | |
| # release_prep.sh (source archive) and its rust-binaries matrix. This | |
| # job predates that flow -- it used to *be* the deploy -- so its uploads are | |
| # a build check whose output happens to be downloadable, nothing more. | |
| release-artifacts: | |
| # Explicit name so the status check is stable. Left implicit, GitHub derives | |
| # it from every matrix value -- which is how branch protection ended up | |
| # requiring `deploy (11)`, a check that stopped existing the moment this job | |
| # grew an os/rust_asset matrix. Adding a matrix key must not rename a check. | |
| name: release-artifacts (${{ matrix.os }}) | |
| needs: [test-jre21] | |
| runs-on: ${{ matrix.os }} | |
| permissions: | |
| # Read-only: nothing here attests or publishes. The id-token/attestations | |
| # writes this job used to request were left over from the old deploy. | |
| contents: read | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # rust_asset is the name //release:bazel-diff-rust gives the binary on | |
| # that platform -- it is asserted, not applied (see the upload step). | |
| # | |
| # The two Windows-only Bazel flags can't move into --config=release: | |
| # startup flags can't live in a --config at all, and .bazelrc expands | |
| # platform-specific config for the bare `build` config name only. | |
| # bazel_startup_flags shortens the output root because MSVC's link.exe | |
| # is MAX_PATH-bound (260): under the default root, the Rust stdlib path | |
| # ...rust_toolchain\lib\rustlib\x86_64-pc-windows-msvc\lib\ | |
| # librustc_std_workspace_alloc-<hash>.rlib comes to 263 characters and | |
| # the link fails with LNK1181. C:/b buys back 35. | |
| # | |
| # release_config is `release-musl` on Linux: the published Linux amd64 | |
| # binary is statically linked against musl so it does not inherit the | |
| # runner's glibc as a floor. It is a cross-compile, not a different | |
| # runner, so it stays in this row. The linux-arm64 musl asset is built | |
| # in extra steps on this same job (not a second matrix row) so the | |
| # check name stays `release-artifacts (ubuntu-latest)`. macOS and | |
| # Windows link their platform's own libc and use the plain `release` | |
| # config. | |
| include: | |
| - os: ubuntu-latest | |
| rust_asset: bazel-diff-rust-linux-amd64 | |
| release_config: release-musl | |
| bazel_startup_flags: '' | |
| bazel_extra_flags: '' | |
| upload_archive: true | |
| - os: macos-latest | |
| rust_asset: bazel-diff-rust-macos-arm64 | |
| release_config: release | |
| bazel_startup_flags: '' | |
| bazel_extra_flags: '' | |
| upload_archive: false | |
| - os: windows-latest | |
| rust_asset: bazel-diff-rust-windows-amd64.exe | |
| release_config: release | |
| bazel_startup_flags: '--output_user_root=C:/b' | |
| bazel_extra_flags: '--legacy_external_runfiles' | |
| upload_archive: false | |
| steps: | |
| - name: Setup Go environment | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ^1.17 | |
| id: go | |
| - name: Setup Bazelisk (Linux/macOS) | |
| if: runner.os != 'Windows' | |
| # Retries guard against transient proxy.golang.org/sum.golang.org module-fetch errors. | |
| run: | | |
| for i in 1 2 3; do | |
| go install github.com/bazelbuild/bazelisk@latest && break | |
| echo "bazelisk install failed (attempt $i); retrying in 10s..." | |
| sleep 10 | |
| done | |
| echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" | |
| - name: Setup Bazelisk (Windows) | |
| if: runner.os == 'Windows' | |
| shell: pwsh | |
| run: | | |
| for ($i = 1; $i -le 3; $i++) { | |
| go install github.com/bazelbuild/bazelisk@latest | |
| if ($LASTEXITCODE -eq 0) { break } | |
| Write-Host "bazelisk install failed (attempt $i); retrying in 10s..." | |
| Start-Sleep -Seconds 10 | |
| } | |
| echo "$(go env GOPATH)\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append | |
| - uses: actions/checkout@v4 | |
| # The same script release_prep.sh packs the shipped archive with, so this | |
| # check can't pass on an archive the release would not produce. It used to | |
| # call `make release_source_archive`, a second tar recipe that had already | |
| # drifted (no __pycache__/*.pyc excludes). | |
| - name: Build release source archive | |
| if: matrix.upload_archive | |
| run: .github/workflows/pack_release_archive.sh archives/release.tar.gz | |
| - uses: actions/upload-artifact@v4 | |
| if: matrix.upload_archive | |
| with: | |
| name: release.tar.gz | |
| path: archives/release.tar.gz | |
| if-no-files-found: error | |
| # //release:bazel-diff-rust names the binary for the platform Bazel built | |
| # it for, so this step neither renames nor relocates anything: whatever | |
| # lands in bazel-bin/release/ is the published asset. matrix.release_config | |
| # carries the flags (see .bazelrc) -- including, on Linux, the musl target | |
| # platform. `if-no-files-found: error` below is the assertion that Bazel's | |
| # name still matches matrix.rust_asset. | |
| - name: Build Rust binary | |
| shell: bash | |
| env: | |
| # Windows runs this under Git bash, whose MSYS runtime rewrites any | |
| # argument starting with `//package` into a `/package` Windows path -- | |
| # Bazel then rejects "invalid package name '/release'". (`//:target` | |
| # survived only because it has no path-like segment to convert.) | |
| MSYS2_ARG_CONV_EXCL: '//' | |
| run: bazelisk ${{ matrix.bazel_startup_flags }} build //release:bazel-diff-rust --config=${{ matrix.release_config }} ${{ matrix.bazel_extra_flags }} | |
| - name: Assert Linux binary is statically linked | |
| if: runner.os == 'Linux' | |
| run: .github/workflows/assert_static_binary.sh "bazel-bin/release/${{ matrix.rust_asset }}" | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: ${{ matrix.rust_asset }} | |
| path: bazel-bin/release/${{ matrix.rust_asset }} | |
| if-no-files-found: error | |
| # Second published Linux asset, built in this same job so the status check | |
| # stays `release-artifacts (ubuntu-latest)`. A matrix row with the same | |
| # `os` would duplicate that name and break branch protection. | |
| - name: Build Rust binary (linux-arm64 musl) | |
| if: runner.os == 'Linux' | |
| run: bazelisk build //release:bazel-diff-rust --config=release-musl-arm64 | |
| - name: Assert Linux arm64 binary is statically linked | |
| if: runner.os == 'Linux' | |
| run: .github/workflows/assert_static_binary.sh bazel-bin/release/bazel-diff-rust-linux-arm64 | |
| - uses: actions/upload-artifact@v4 | |
| if: runner.os == 'Linux' | |
| with: | |
| name: bazel-diff-rust-linux-arm64 | |
| path: bazel-bin/release/bazel-diff-rust-linux-arm64 | |
| if-no-files-found: error |