diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1d9c70e..a5e80d7 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -7,6 +7,10 @@ updates: open-pull-requests-limit: 5 commit-message: prefix: "build(deps)" + groups: + minor-and-patch: + patterns: ["*"] + update-types: ["minor", "patch"] - package-ecosystem: cargo directory: / @@ -15,6 +19,10 @@ updates: open-pull-requests-limit: 5 commit-message: prefix: "build(deps)" + groups: + minor-and-patch: + patterns: ["*"] + update-types: ["minor", "patch"] - package-ecosystem: npm directory: / @@ -23,6 +31,10 @@ updates: open-pull-requests-limit: 5 commit-message: prefix: "build(deps)" + groups: + minor-and-patch: + patterns: ["*"] + update-types: ["minor", "patch"] - package-ecosystem: npm directory: /bindings/node @@ -31,6 +43,10 @@ updates: open-pull-requests-limit: 5 commit-message: prefix: "build(deps)" + groups: + minor-and-patch: + patterns: ["*"] + update-types: ["minor", "patch"] - package-ecosystem: pip directory: /bindings/python @@ -39,6 +55,10 @@ updates: open-pull-requests-limit: 5 commit-message: prefix: "build(deps)" + groups: + minor-and-patch: + patterns: ["*"] + update-types: ["minor", "patch"] - package-ecosystem: nuget directory: /dotnet @@ -47,6 +67,10 @@ updates: open-pull-requests-limit: 5 commit-message: prefix: "build(deps)" + groups: + minor-and-patch: + patterns: ["*"] + update-types: ["minor", "patch"] - package-ecosystem: github-actions directory: / @@ -55,3 +79,7 @@ updates: open-pull-requests-limit: 5 commit-message: prefix: "ci(deps)" + groups: + minor-and-patch: + patterns: ["*"] + update-types: ["minor", "patch"] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7636adc..e80e16f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,259 +3,341 @@ name: CI on: pull_request: branches: [master] + push: + branches: [master] + +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true permissions: contents: read + # Required by dorny/paths-filter on pull_request events. + pull-requests: read jobs: - quality: - name: commit + docs + secrets - runs-on: blacksmith-2vcpu-ubuntu-2404 + changes: + name: detect changes + runs-on: ubuntu-latest + outputs: + global: ${{ github.event_name == 'push' || steps.filter.outputs.global == 'true' }} + go: ${{ github.event_name == 'push' || steps.filter.outputs.go == 'true' }} + rust: ${{ github.event_name == 'push' || steps.filter.outputs.rust == 'true' }} + node: ${{ github.event_name == 'push' || steps.filter.outputs.node == 'true' }} + python: ${{ github.event_name == 'push' || steps.filter.outputs.python == 'true' }} + dotnet: ${{ github.event_name == 'push' || steps.filter.outputs.dotnet == 'true' }} + steps: + - name: Filter changed paths + uses: dorny/paths-filter@v4 + id: filter + if: github.event_name == 'pull_request' + with: + filters: | + global: + - 'devbox.json' + - 'devbox.lock' + - '.justfile' + - '.github/workflows/**' + # Checkout transformations apply to every file, so a change here + # can break any lane, not just the one that owns the paths. + - '.gitattributes' + go: + - '*.go' + - '**/*.go' + - 'go.mod' + - 'go.sum' + - '.golangci.yml' + - '.goreleaser.yaml' + # The bindings are members of the Cargo workspace, so their Rust + # sources are inputs to the workspace-wide fmt/clippy/audit/deny. + rust: + - 'crates/**' + - 'Cargo.toml' + - 'Cargo.lock' + - 'rust-toolchain.toml' + - 'deny.toml' + - '.cargo/**' + - 'bindings/node/Cargo.toml' + - 'bindings/node/build.rs' + - 'bindings/node/src/**' + - 'bindings/python/Cargo.toml' + - 'bindings/python/src/**' + # The repo-root package.json is tooling only (commitlint, husky, + # lint-staged) and is not an input to the native addon. + node: + - 'bindings/node/**' + python: + - 'bindings/python/**' + # `dotnet format` is the only checker here that reads .editorconfig, + # and it inherits the root file because dotnet/.editorconfig does + # not set `root = true`. rustfmt, gofumpt and markdownlint-cli2 all + # ignore it, so it does not belong in their lanes. + dotnet: + - 'dotnet/**' + - '.editorconfig' + + ci: + name: ci + needs: changes + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v7 with: fetch-depth: 0 + # Restore and save are split so the cache is still written when a check + # fails: the post step of actions/cache only runs on success. + # + # Under GOTOOLCHAIN=auto a `go` directive newer than the devbox toolchain + # is downloaded into GOMODCACHE, which lives inside this cache and is not + # recorded in go.sum. go.mod and devbox.lock are part of the key so that + # switch produces a miss instead of a permanent stale hit. + - name: Restore Go cache + id: go-cache + uses: actions/cache/restore@v6 + with: + path: | + ~/go/pkg/mod + ~/.cache/go-build + key: ${{ runner.os }}-${{ runner.arch }}-go-${{ hashFiles('go.mod', 'go.sum', 'devbox.lock') }} + restore-keys: ${{ runner.os }}-${{ runner.arch }}-go- + - name: Install devbox uses: jetify-com/devbox-install-action@v0.15.0 with: enable-cache: true devbox-version: 0.17.4 + # devbox.lock is in the key because this job restores with the devbox SDK. + - name: Restore NuGet cache + id: nuget-cache + uses: actions/cache/restore@v6 + with: + path: ~/.nuget/packages + key: ${{ runner.os }}-${{ runner.arch }}-nuget-${{ hashFiles('dotnet/**/*.csproj', 'dotnet/Directory.Build.props', 'devbox.lock') }} + restore-keys: ${{ runner.os }}-${{ runner.arch }}-nuget- + - name: Install Node tooling run: devbox run -- pnpm install --frozen-lockfile + # The gate skips the restore when no Cargo lane is scheduled; `save-if` + # then requires one to have actually reached cargo, since a lane dying + # before it compiles would otherwise freeze an empty target under the + # exact key. `save-if` is read by the post step, so it sees these + # outcomes. `cache-on-failure` stays because the action declares + # `post-if: success() || env.CACHE_ON_FAILURE == 'true'`, and the + # aggregator has already made the job red by then. + - name: Cache cargo and target + if: needs.changes.outputs.rust == 'true' || needs.changes.outputs.node == 'true' || needs.changes.outputs.python == 'true' || needs.changes.outputs.global == 'true' + uses: Swatinem/rust-cache@v2 + with: + cache-on-failure: true + save-if: ${{ steps.rust-ci.outcome == 'success' || steps.node-ci.outcome == 'success' || steps.py-ci.outcome == 'success' }} + - name: Lint commit messages + id: commitlint + continue-on-error: true + if: github.event_name == 'pull_request' env: BASE_SHA: ${{ github.event.pull_request.base.sha }} HEAD_SHA: ${{ github.event.pull_request.head.sha }} run: devbox run -- pnpm exec commitlint --config commitlint.config.cjs --from "$BASE_SHA" --to "$HEAD_SHA" - name: Run quality gates + id: quality + continue-on-error: true env: # Lychee falls back to anonymous GitHub requests without this, which # are heavily rate-limited in CI. GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: devbox run -- just quality - go-test: - name: go / tidy + vet + test - runs-on: blacksmith-2vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v7 - - name: Install devbox - uses: jetify-com/devbox-install-action@v0.15.0 - with: - enable-cache: true - devbox-version: 0.17.4 - - name: Cache Go modules and build - uses: actions/cache@v6 - with: - path: | - ~/go/pkg/mod - ~/.cache/go-build - key: ubuntu-go-${{ hashFiles('**/go.sum') }} - restore-keys: ubuntu-go- - - name: Tidy check + - name: go / tidy check + id: go-tidy-check + continue-on-error: true + if: needs.changes.outputs.go == 'true' || needs.changes.outputs.global == 'true' run: devbox run -- just go-tidy-check - - name: Vet + + - name: go / vet + id: go-vet + continue-on-error: true + if: needs.changes.outputs.go == 'true' || needs.changes.outputs.global == 'true' run: devbox run -- just go-vet - - name: Test - run: devbox run -- go test -race -count=1 -coverprofile=coverage.out ./... - - name: Upload coverage - if: always() - uses: actions/upload-artifact@v7 - with: - name: coverage - path: coverage.out - retention-days: 7 - go-lint: - name: go / golangci-lint - runs-on: blacksmith-2vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v7 - - name: Install devbox - uses: jetify-com/devbox-install-action@v0.15.0 - with: - enable-cache: true - devbox-version: 0.17.4 - - name: Run golangci-lint + - name: go / golangci-lint + id: go-lint + continue-on-error: true + if: needs.changes.outputs.go == 'true' || needs.changes.outputs.global == 'true' run: devbox run -- just go-lint - go-security: - name: go / gosec + govulncheck - runs-on: blacksmith-2vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v7 - - name: Install devbox - uses: jetify-com/devbox-install-action@v0.15.0 - with: - enable-cache: true - devbox-version: 0.17.4 - - name: Static security analysis (gosec) + - name: go / gosec + id: go-lint-sec + continue-on-error: true + if: needs.changes.outputs.go == 'true' || needs.changes.outputs.global == 'true' run: devbox run -- just go-lint-sec - - name: Vulnerability scan (govulncheck) + + - name: go / govulncheck + id: go-lint-vuln + continue-on-error: true + if: needs.changes.outputs.go == 'true' || needs.changes.outputs.global == 'true' run: devbox run -- just go-lint-vuln - go-build: - name: go / build / ${{ matrix.os }} - runs-on: ${{ matrix.runs-on }} - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - runs-on: blacksmith-2vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v7 - - name: Install devbox - uses: jetify-com/devbox-install-action@v0.15.0 - with: - enable-cache: true - devbox-version: 0.17.4 - - name: Cache Go modules and build - uses: actions/cache@v6 + # Single test invocation covering both the race lane of `just go-ci` and + # the coverage profile. + - name: go / test + id: go-test + continue-on-error: true + if: needs.changes.outputs.go == 'true' || needs.changes.outputs.global == 'true' + run: devbox run -- go test -race -count=1 -coverprofile=coverage.out ./... + + - name: go / build + id: go-build + continue-on-error: true + if: needs.changes.outputs.go == 'true' || needs.changes.outputs.global == 'true' + run: devbox run -- just go-build + + # Publishing under the exact primary key is irreversible, and a later run + # that hits it skips its own save. So only save once a step that actually + # populates this cache has completed. + - name: Save Go cache + if: >- + always() && !cancelled() + && steps.go-cache.outcome == 'success' + && steps.go-cache.outputs.cache-hit != 'true' + && (steps.go-tidy-check.outcome == 'success' || steps.go-test.outcome == 'success' || steps.go-build.outcome == 'success') + continue-on-error: true + uses: actions/cache/save@v6 with: path: | ~/go/pkg/mod ~/.cache/go-build - key: ${{ matrix.os }}-go-${{ hashFiles('**/go.sum') }} - restore-keys: ${{ matrix.os }}-go- - - name: Build - run: devbox run -- just go-build + key: ${{ steps.go-cache.outputs.cache-primary-key }} - rust: - name: rust / fmt + clippy + test + audit - runs-on: blacksmith-2vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v7 - - name: Install devbox - uses: jetify-com/devbox-install-action@v0.15.0 - with: - enable-cache: true - devbox-version: 0.17.4 - - name: Cache cargo and target - uses: Swatinem/rust-cache@v2 - - name: Format check - run: devbox run -- just rust-fmt-check - - name: Clippy - run: devbox run -- just rust-lint - - name: Test - run: devbox run -- just rust-test - - name: Audit - run: devbox run -- just rust-audit - - node: - name: node / ${{ matrix.os }} - runs-on: ${{ matrix.runs-on }} - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - runs-on: blacksmith-2vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v7 - - name: Install devbox - uses: jetify-com/devbox-install-action@v0.15.0 - with: - enable-cache: true - devbox-version: 0.17.4 - - name: Cache cargo and target - uses: Swatinem/rust-cache@v2 - - name: Build native addon - run: devbox run -- just node-build - - name: Test - run: devbox run -- just node-test - - dotnet: - name: dotnet / build + fmt + test - runs-on: blacksmith-2vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v7 - - name: Install devbox - uses: jetify-com/devbox-install-action@v0.15.0 + - name: Upload coverage + id: upload-coverage + if: always() && steps.go-test.outcome != 'skipped' + continue-on-error: true + uses: actions/upload-artifact@v7 with: - enable-cache: true - devbox-version: 0.17.4 - - name: Cache NuGet packages - uses: actions/cache@v6 + name: coverage + path: coverage.out + if-no-files-found: error + retention-days: 7 + + # RUST_TEST_THREADS caps the parallelism of `cargo test`. It is a + # migration guard: the 4 vCPU GitHub-hosted runner makes the ETXTBSY race + # in the fake-executable fixtures likely enough to force reruns. The real + # fix belongs in the fixture and is tracked separately. + - name: rust / fmt + clippy + test + audit + id: rust-ci + continue-on-error: true + if: needs.changes.outputs.rust == 'true' || needs.changes.outputs.global == 'true' + env: + RUST_TEST_THREADS: 2 + run: devbox run -- just rust-ci + + # The addon is compiled from the workspace crate, so a Rust change has to + # rebuild it even when bindings/node is untouched. + - name: node / build + test + id: node-ci + continue-on-error: true + if: needs.changes.outputs.node == 'true' || needs.changes.outputs.rust == 'true' || needs.changes.outputs.global == 'true' + run: devbox run -- just node-ci + + - name: python / build + test + id: py-ci + continue-on-error: true + if: needs.changes.outputs.python == 'true' || needs.changes.outputs.rust == 'true' || needs.changes.outputs.global == 'true' + run: devbox run -- just py-ci + + - name: dotnet / build + fmt + test + id: dotnet-ci + continue-on-error: true + if: needs.changes.outputs.dotnet == 'true' || needs.changes.outputs.global == 'true' + run: devbox run -- just dotnet-ci + + - name: dotnet / verify package + id: dotnet-verify-pack + continue-on-error: true + if: needs.changes.outputs.dotnet == 'true' || needs.changes.outputs.global == 'true' + run: devbox run -- just dotnet-verify-pack + + - name: Save NuGet cache + if: >- + always() && !cancelled() + && steps.nuget-cache.outcome == 'success' + && steps.nuget-cache.outputs.cache-hit != 'true' + && (steps.dotnet-ci.outcome == 'success' || steps.dotnet-verify-pack.outcome == 'success') + continue-on-error: true + uses: actions/cache/save@v6 with: path: ~/.nuget/packages - key: ubuntu-nuget-${{ hashFiles('dotnet/**/*.csproj', 'dotnet/Directory.Build.props') }} - restore-keys: ubuntu-nuget- - - name: Build - run: devbox run -- just dotnet-build - - name: Format check - run: devbox run -- just dotnet-fmt-check - - name: Test - run: devbox run -- just dotnet-test - - name: Verify package - run: devbox run -- just dotnet-verify-pack + key: ${{ steps.nuget-cache.outputs.cache-primary-key }} + + - name: Aggregate check results + if: always() + env: + STEPS: ${{ toJSON(steps) }} + run: | + set -euo pipefail + failed=$(printf '%s' "$STEPS" | jq -r ' + to_entries[] + | select([.value.outcome, .value.conclusion] | any(. == "failure" or . == "cancelled")) + | .key') + if [ -n "$failed" ]; then + printf 'failed checks:\n%s\n' "$failed" + printf '%s\n' "$failed" | while read -r s; do echo "::error::check failed: $s"; done + exit 1 + fi + echo "all checks passed" dotnet-compat: name: dotnet / runtime matrix - runs-on: ${{ matrix.runs-on }} + needs: changes + if: needs.changes.outputs.dotnet == 'true' || needs.changes.outputs.global == 'true' + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: - include: - # net8.0 is the oldest published target; the devbox lane only ships - # SDK 10, so this lane installs both runtimes and runs the suite on - # each TFM. - - os: ubuntu-latest - runs-on: blacksmith-2vcpu-ubuntu-2404 - # The package has no OS restriction; Windows runs the build and the - # platform-independent tests (process tests are Unix-only). - - os: windows-latest - runs-on: windows-latest + # net8.0 is the oldest published target and the devbox lane only ships + # SDK 10, so this job installs both runtimes and runs the suite on each + # TFM. Linux is where the Unix-only process tests actually execute; + # Windows covers the platform-independent surface. + os: [ubuntu-latest, windows-latest] steps: - name: Checkout uses: actions/checkout@v7 + - name: Setup .NET uses: actions/setup-dotnet@v6 with: dotnet-version: | 8.0.x 10.0.x - - name: Cache NuGet packages - uses: actions/cache@v6 + + # No devbox.lock in the key: this job takes its SDK from setup-dotnet + # above, not from devbox. + - name: Restore NuGet cache + id: nuget-cache + uses: actions/cache/restore@v6 with: path: ~/.nuget/packages key: ${{ matrix.os }}-nuget-${{ hashFiles('dotnet/**/*.csproj', 'dotnet/Directory.Build.props') }} restore-keys: ${{ matrix.os }}-nuget- + - name: Test (net8.0 and net10.0) + id: dotnet-test run: dotnet test dotnet/Codexcw.slnx -p:TestAllFrameworks=true - python: - name: python / ${{ matrix.os }} - runs-on: ${{ matrix.runs-on }} - strategy: - fail-fast: false - matrix: - include: - - os: ubuntu-latest - runs-on: blacksmith-2vcpu-ubuntu-2404 - steps: - - name: Checkout - uses: actions/checkout@v7 - - name: Install devbox - uses: jetify-com/devbox-install-action@v0.15.0 + - name: Save NuGet cache + if: >- + always() && !cancelled() + && steps.nuget-cache.outcome == 'success' + && steps.nuget-cache.outputs.cache-hit != 'true' + && steps.dotnet-test.outcome == 'success' + continue-on-error: true + uses: actions/cache/save@v6 with: - enable-cache: true - devbox-version: 0.17.4 - - name: Cache cargo and target - uses: Swatinem/rust-cache@v2 - - name: Build extension - run: devbox run -- just py-build - - name: Test - run: devbox run -- just py-test + path: ~/.nuget/packages + key: ${{ steps.nuget-cache.outputs.cache-primary-key }} diff --git a/.github/workflows/release-crate.yml b/.github/workflows/release-crate.yml index 60ad543..e615d19 100644 --- a/.github/workflows/release-crate.yml +++ b/.github/workflows/release-crate.yml @@ -17,7 +17,7 @@ permissions: jobs: publish: if: startsWith(github.ref, 'refs/tags/rust-v') - runs-on: blacksmith-2vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v7 diff --git a/.github/workflows/release-go.yml b/.github/workflows/release-go.yml index 90cb96f..32ec9a0 100644 --- a/.github/workflows/release-go.yml +++ b/.github/workflows/release-go.yml @@ -11,7 +11,7 @@ permissions: jobs: goreleaser: if: startsWith(github.ref, 'refs/tags/v') - runs-on: blacksmith-2vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v7 diff --git a/.github/workflows/release-npm.yml b/.github/workflows/release-npm.yml index 6853035..a999729 100644 --- a/.github/workflows/release-npm.yml +++ b/.github/workflows/release-npm.yml @@ -21,17 +21,17 @@ defaults: jobs: build: name: build / ${{ matrix.target }} - runs-on: ${{ matrix.runs-on }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: x86_64-unknown-linux-gnu } - - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: aarch64-unknown-linux-gnu, cross: true } - - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: x86_64-unknown-linux-musl, cross: true } - - { os: macos-latest, runs-on: blacksmith-6vcpu-macos-latest, target: x86_64-apple-darwin } - - { os: macos-latest, runs-on: blacksmith-6vcpu-macos-latest, target: aarch64-apple-darwin } - - { os: windows-latest, runs-on: blacksmith-2vcpu-windows-2025, target: x86_64-pc-windows-msvc } + - { os: ubuntu-latest, target: x86_64-unknown-linux-gnu } + - { os: ubuntu-latest, target: aarch64-unknown-linux-gnu, cross: true } + - { os: ubuntu-latest, target: x86_64-unknown-linux-musl, cross: true } + - { os: macos-latest, target: x86_64-apple-darwin } + - { os: macos-latest, target: aarch64-apple-darwin } + - { os: windows-latest, target: x86_64-pc-windows-msvc } steps: - name: Checkout uses: actions/checkout@v7 @@ -71,9 +71,7 @@ jobs: name: publish needs: build if: startsWith(github.ref, 'refs/tags/node-v') - # npm provenance is only issued on GitHub-hosted runners; Blacksmith is - # self-hosted. The heavy build matrix stays on Blacksmith; this small - # publish job runs github-hosted (free on public repos) to keep provenance. + # npm provenance is only issued on GitHub-hosted runners. runs-on: ubuntu-latest steps: - name: Checkout diff --git a/.github/workflows/release-pypi.yml b/.github/workflows/release-pypi.yml index e9ac844..5966308 100644 --- a/.github/workflows/release-pypi.yml +++ b/.github/workflows/release-pypi.yml @@ -17,18 +17,18 @@ permissions: jobs: wheels: name: wheels / ${{ matrix.os }} / ${{ matrix.target }} - runs-on: ${{ matrix.runs-on }} + runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: include: - - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: x86_64, manylinux: auto } - - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: aarch64, manylinux: auto } - - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: x86_64, manylinux: musllinux_1_1 } - - { os: ubuntu-latest, runs-on: blacksmith-2vcpu-ubuntu-2404, target: aarch64, manylinux: musllinux_1_1 } - - { os: macos-latest, runs-on: blacksmith-6vcpu-macos-latest, target: x86_64, manylinux: auto } - - { os: macos-latest, runs-on: blacksmith-6vcpu-macos-latest, target: aarch64, manylinux: auto } - - { os: windows-latest, runs-on: blacksmith-2vcpu-windows-2025, target: x64, manylinux: auto } + - { os: ubuntu-latest, target: x86_64, manylinux: auto } + - { os: ubuntu-latest, target: aarch64, manylinux: auto } + - { os: ubuntu-latest, target: x86_64, manylinux: musllinux_1_1 } + - { os: ubuntu-latest, target: aarch64, manylinux: musllinux_1_1 } + - { os: macos-latest, target: x86_64, manylinux: auto } + - { os: macos-latest, target: aarch64, manylinux: auto } + - { os: windows-latest, target: x64, manylinux: auto } steps: - name: Checkout uses: actions/checkout@v7 @@ -50,7 +50,7 @@ jobs: sdist: name: sdist - runs-on: blacksmith-2vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@v7 @@ -72,7 +72,7 @@ jobs: name: publish needs: [wheels, sdist] if: startsWith(github.ref, 'refs/tags/py-v') - runs-on: blacksmith-2vcpu-ubuntu-2404 + runs-on: ubuntu-latest steps: - name: Download artifacts uses: actions/download-artifact@v8 diff --git a/devbox.json b/devbox.json index 5003ec1..4910c6e 100644 --- a/devbox.json +++ b/devbox.json @@ -4,6 +4,8 @@ "go": "1.26", "golangci-lint": "2.12", "gofumpt": "0.10", + "govulncheck": "1.6.0", + "gosec": "2.28.0", "goreleaser": "2.15", "syft": "1.18", "rustup": "1.28.2", @@ -33,10 +35,8 @@ "init_hook": [ "export GOBIN=$PWD/bin", "export CARGO_HOME=${CARGO_HOME:-$HOME/.cargo}", - "export PATH=$GOBIN:$CARGO_HOME/bin:$PATH", + "export PATH=$PATH:$CARGO_HOME/bin:$GOBIN", "rustup show active-toolchain >/dev/null 2>&1 || rustup toolchain install 1.90.0 --profile minimal --component rustfmt --component clippy", - "if [ ! -x \"$GOBIN/govulncheck\" ]; then go install golang.org/x/vuln/cmd/govulncheck@latest; fi", - "if [ ! -x \"$GOBIN/gosec\" ]; then go install github.com/securego/gosec/v2/cmd/gosec@latest; fi", "if [ -z \"${CI:-}\" ]; then pnpm install --frozen-lockfile && pnpm exec husky; fi" ] } diff --git a/devbox.lock b/devbox.lock index 0b1e3d4..7e30e28 100644 --- a/devbox.lock +++ b/devbox.lock @@ -404,6 +404,82 @@ } } }, + "gosec@2.28.0": { + "last_modified": "2026-08-01T16:34:20Z", + "resolved": "github:NixOS/nixpkgs/a5cbcfe954791221bfffe2307f7d1a1bf61a871e#gosec", + "source": "devbox-search", + "version": "2.28.0", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/libarzfjp8ql7zsfgmlx7isgfd0b751x-gosec-2.28.0", + "default": true + } + ], + "store_path": "/nix/store/libarzfjp8ql7zsfgmlx7isgfd0b751x-gosec-2.28.0" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/1gkyi3chzsg9mh889dya8cjn2hgfiasi-gosec-2.28.0", + "default": true + } + ], + "store_path": "/nix/store/1gkyi3chzsg9mh889dya8cjn2hgfiasi-gosec-2.28.0" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/i2kcnx89xl4airnl35fq8ql9ndf1nbza-gosec-2.28.0", + "default": true + } + ], + "store_path": "/nix/store/i2kcnx89xl4airnl35fq8ql9ndf1nbza-gosec-2.28.0" + } + } + }, + "govulncheck@1.6.0": { + "last_modified": "2026-08-01T16:34:20Z", + "resolved": "github:NixOS/nixpkgs/a5cbcfe954791221bfffe2307f7d1a1bf61a871e#govulncheck", + "source": "devbox-search", + "version": "1.6.0", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/ly0apvkva44w1kycvhdnb1z1sg4isvl6-govulncheck-1.6.0", + "default": true + } + ], + "store_path": "/nix/store/ly0apvkva44w1kycvhdnb1z1sg4isvl6-govulncheck-1.6.0" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/hlkcpib5bxrc8567cr2rah9xfiqj0c6j-govulncheck-1.6.0", + "default": true + } + ], + "store_path": "/nix/store/hlkcpib5bxrc8567cr2rah9xfiqj0c6j-govulncheck-1.6.0" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/jal1aq2n1kn41h6akxgghnn9zbsdahml-govulncheck-1.6.0", + "default": true + } + ], + "store_path": "/nix/store/jal1aq2n1kn41h6akxgghnn9zbsdahml-govulncheck-1.6.0" + } + } + }, "just@1.51": { "last_modified": "2026-05-21T08:15:18Z", "resolved": "github:NixOS/nixpkgs/4a29d733e8a7d5b824c3d8c958a946a9867b3eb2#just",