diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 00000000..b0883ecd --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,172 @@ +name: ci + +# Combined CI pipeline. `fix` runs first, post-processing same-repo PRs +# that bump Go modules / npm manifests so the workspace ends up in a +# state the Nix build can consume (per-module `go mod tidy` plus +# `nix-update` of vendor hashes; see https://github.com/golang/go/issues/63901). +# If `fix` pushed a corrective commit, downstream nix-checks jobs are +# skipped — the resulting `pull_request synchronize` triggers a fresh +# CI run on the corrected SHA, and branch protection on the PR HEAD +# prevents merging until that fresh run reports success. + +on: + pull_request: + +permissions: + contents: read + +concurrency: + group: ci-${{ github.head_ref || github.ref }} + cancel-in-progress: true + +jobs: + fix: + # Forks can't be pushed to (their GITHUB_TOKEN is read-only and + # secrets are not exposed); skip the job entirely there. + if: github.event.pull_request.head.repo.full_name == github.repository + runs-on: ubuntu-latest + outputs: + pushed: ${{ steps.push.outputs.pushed }} + steps: + - uses: dorny/paths-filter@v3 + id: filter + with: + filters: | + relevant: + - 'go.mod' + - 'go.sum' + - 'bindings/go/scip/go.mod' + - 'bindings/go/scip/go.sum' + - 'reprolang/go.mod' + - 'reprolang/go.sum' + - 'bindings/typescript/package.json' + - 'bindings/typescript/package-lock.json' + + - name: Generate GitHub App token + if: steps.filter.outputs.relevant == 'true' + id: app-token + uses: actions/create-github-app-token@v3 + with: + app-id: ${{ vars.RENOVATE_FIX_APP_ID }} + private-key: ${{ secrets.RENOVATE_FIX_APP_PRIVATE_KEY }} + + - if: steps.filter.outputs.relevant == 'true' + uses: actions/checkout@v6 + with: + ref: ${{ github.event.pull_request.head.ref }} + # Pushing under the App identity (not GITHUB_TOKEN) makes + # `git push` fire `pull_request synchronize`, which triggers + # a fresh CI run that revalidates the corrected SHA. + token: ${{ steps.app-token.outputs.token }} + + - if: steps.filter.outputs.relevant == 'true' + uses: DeterminateSystems/nix-installer-action@v22 + with: + summarize: false + - if: steps.filter.outputs.relevant == 'true' + uses: DeterminateSystems/magic-nix-cache-action@v13 + + - name: Tidy Go modules + if: steps.filter.outputs.relevant == 'true' + env: + GOWORK: 'off' + # https://github.com/golang/go/issues/63901 + run: | + set -euo pipefail + for dir in bindings/go/scip . reprolang; do + (cd "$dir" && nix develop --command go mod tidy) + done + + - name: Recompute vendor hashes with nix-update + if: steps.filter.outputs.relevant == 'true' + run: | + set -euo pipefail + # nix-update only auto-resolves packages..; for + # attributes under `checks` we must pass the full dotted path. + # One attribute per invocation; sequential to avoid concurrent + # writes to the same .nix files. + for attr in \ + packages.x86_64-linux.scip \ + checks.x86_64-linux.go-bindings \ + checks.x86_64-linux.reprolang \ + checks.x86_64-linux.typescript-bindings; do + nix run github:Mic92/nix-update -- \ + --flake --version=skip "$attr" + done + + - name: Commit and push + id: push + if: steps.filter.outputs.relevant == 'true' + run: | + set -euo pipefail + if git diff --quiet; then + echo "No changes; nothing to push." + echo "pushed=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' + git commit -am 'chore: tidy Go modules and update vendor hashes' + git push + echo "pushed=true" >> "$GITHUB_OUTPUT" + + list: + needs: fix + # Skip downstream when `fix` pushed corrective commits — the + # resulting `pull_request synchronize` triggers a fresh CI run that + # validates the corrected SHA, and branch protection on the PR + # HEAD prevents merging until that fresh run reports success. + if: always() && needs.fix.outputs.pushed != 'true' + runs-on: ubuntu-latest + outputs: + checks: ${{ steps.checks.outputs.result }} + packages: ${{ steps.packages.outputs.result }} + steps: + - uses: actions/checkout@v6 + - uses: DeterminateSystems/nix-installer-action@v22 + - id: checks + run: | + CHECKS=$(nix eval .#checks.x86_64-linux \ + --apply builtins.attrNames --json) + echo "result=$CHECKS" >> "$GITHUB_OUTPUT" + - id: packages + run: | + PACKAGES=$(nix eval .#packages.x86_64-linux \ + --apply 'ps: builtins.attrNames (removeAttrs ps ["default"])' \ + --json) + echo "result=$PACKAGES" >> "$GITHUB_OUTPUT" + + checks: + needs: list + runs-on: ubuntu-latest + strategy: + matrix: + check: ${{ fromJSON(needs.list.outputs.checks) }} + steps: + - uses: actions/checkout@v6 + - uses: DeterminateSystems/nix-installer-action@v22 + - uses: DeterminateSystems/magic-nix-cache-action@v13 + - run: nix build .#checks.x86_64-linux.${{ matrix.check }} + + packages: + needs: list + runs-on: ubuntu-latest + strategy: + matrix: + package: ${{ fromJSON(needs.list.outputs.packages) }} + steps: + - uses: actions/checkout@v6 + - uses: DeterminateSystems/nix-installer-action@v22 + - uses: DeterminateSystems/magic-nix-cache-action@v13 + - run: nix run .#${{ matrix.package }} + - run: git diff --exit-code + + ci-pass: + if: always() + needs: [fix, list, checks, packages] + runs-on: ubuntu-latest + steps: + - if: >- + contains(needs.*.result, 'failure') || + contains(needs.*.result, 'cancelled') + run: exit 1 diff --git a/.github/workflows/nix-checks.yaml b/.github/workflows/nix-checks.yaml deleted file mode 100644 index acde58be..00000000 --- a/.github/workflows/nix-checks.yaml +++ /dev/null @@ -1,66 +0,0 @@ -name: Nix - -on: - pull_request: - -# Cancel an in-progress run when a newer commit supersedes it on the same -# branch (e.g. when update-vendor-hash pushes a hash fix). -concurrency: - group: nix-checks-${{ github.head_ref || github.ref }} - cancel-in-progress: true - -jobs: - list: - runs-on: ubuntu-latest - outputs: - checks: ${{ steps.checks.outputs.result }} - packages: ${{ steps.packages.outputs.result }} - steps: - - uses: actions/checkout@v6 - - uses: DeterminateSystems/nix-installer-action@v22 - - id: checks - run: | - CHECKS=$(nix eval .#checks.x86_64-linux \ - --apply builtins.attrNames --json) - echo "result=$CHECKS" >> "$GITHUB_OUTPUT" - - id: packages - run: | - PACKAGES=$(nix eval .#packages.x86_64-linux \ - --apply 'ps: builtins.attrNames (removeAttrs ps ["default"])' \ - --json) - echo "result=$PACKAGES" >> "$GITHUB_OUTPUT" - - checks: - needs: list - runs-on: ubuntu-latest - strategy: - matrix: - check: ${{ fromJSON(needs.list.outputs.checks) }} - steps: - - uses: actions/checkout@v6 - - uses: DeterminateSystems/nix-installer-action@v22 - - uses: DeterminateSystems/magic-nix-cache-action@v13 - - run: nix build .#checks.x86_64-linux.${{ matrix.check }} - - packages: - needs: list - runs-on: ubuntu-latest - strategy: - matrix: - package: ${{ fromJSON(needs.list.outputs.packages) }} - steps: - - uses: actions/checkout@v6 - - uses: DeterminateSystems/nix-installer-action@v22 - - uses: DeterminateSystems/magic-nix-cache-action@v13 - - run: nix run .#${{ matrix.package }} - - run: git diff --exit-code - - nix-checks-pass: - if: always() - needs: [list, checks, packages] - runs-on: ubuntu-latest - steps: - - if: >- - contains(needs.*.result, 'failure') || - contains(needs.*.result, 'cancelled') - run: exit 1 diff --git a/.github/workflows/update-vendor-hash.yaml b/.github/workflows/update-vendor-hash.yaml deleted file mode 100644 index 57954447..00000000 --- a/.github/workflows/update-vendor-hash.yaml +++ /dev/null @@ -1,89 +0,0 @@ -name: update-vendor-hash - -# Renovate updates go.mod / go.sum (and TypeScript package manifests) but -# cannot update the vendor hashes in flake.nix / checks.nix, which causes -# the Nix build to fail until the hashes are fixed by hand. This workflow -# watches PRs that modify those files, recomputes the affected hashes with -# `nix-update`, and pushes the corrected files back to the PR branch using -# a GitHub App token. Pushing under a non-GITHUB_TOKEN identity makes the -# push fire `pull_request synchronize` naturally, producing a check_suite -# the PR UI displays. - -on: - pull_request: - paths: - - go.mod - - go.sum - - bindings/go/scip/go.mod - - bindings/go/scip/go.sum - - reprolang/go.mod - - reprolang/go.sum - - bindings/typescript/package.json - - bindings/typescript/package-lock.json - -permissions: - contents: read - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -jobs: - update: - if: github.event.pull_request.head.repo.full_name == github.repository - runs-on: ubuntu-latest - steps: - - name: Generate GitHub App token - id: app-token - uses: actions/create-github-app-token@v3 - with: - app-id: ${{ vars.RENOVATE_FIX_APP_ID }} - private-key: ${{ secrets.RENOVATE_FIX_APP_PRIVATE_KEY }} - - - uses: actions/checkout@v6 - with: - ref: ${{ github.event.pull_request.head.ref }} - token: ${{ steps.app-token.outputs.token }} - - - uses: DeterminateSystems/nix-installer-action@v22 - with: - summarize: false - - uses: DeterminateSystems/magic-nix-cache-action@v13 - - - name: Tidy Go modules - env: - GOWORK: 'off' - run: | - set -euo pipefail - # https://github.com/golang/go/issues/63901 - for dir in bindings/go/scip . reprolang; do - (cd "$dir" && nix develop --command go mod tidy) - done - - - name: Recompute vendor hashes with nix-update - run: | - set -euo pipefail - # nix-update only auto-resolves packages..; for - # attributes under `checks` we must pass the full dotted path. - # One attribute per invocation; sequential to avoid concurrent - # writes to the same .nix files. - for attr in \ - packages.x86_64-linux.scip \ - checks.x86_64-linux.go-bindings \ - checks.x86_64-linux.reprolang \ - checks.x86_64-linux.typescript-bindings; do - nix run github:Mic92/nix-update -- \ - --flake --version=skip "$attr" - done - - - name: Commit and push - run: | - set -euo pipefail - if git diff --quiet; then - echo "No changes; nothing to push." - exit 0 - fi - git config user.name 'github-actions[bot]' - git config user.email '41898282+github-actions[bot]@users.noreply.github.com' - git commit -am 'chore: tidy Go modules and update vendor hashes' - git push