name: PR Check on: [ pull_request, merge_group ] # When a new revision is pushed to a PR, cancel all in-progress CI runs for that # PR. See https://docs.github.com/en/actions/using-jobs/using-concurrency concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true permissions: contents: read security-events: write jobs: # Check what types of changes this PR contains check-changes: name: Check what files changed runs-on: ubuntu-24.04 outputs: go: ${{ steps.changes.outputs.go }} wasm: ${{ steps.changes.outputs.wasm }} docs: ${{ steps.changes.outputs.docs }} rego: ${{ steps.changes.outputs.rego }} yaml: ${{ steps.changes.outputs.yaml }} proto: ${{ steps.changes.outputs.proto }} steps: - name: Check out repository code # Shallow checkout for a faster clone; merge_group fetches the base below. uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Download OPA uses: open-policy-agent/setup-opa@b2b258e089860efaadaaf71bf6e3aecb4a3eeff1 # v2.4.0 with: version: latest - name: Check for file changes id: changes run: | # zizmor: ignore[template-injection] These SHAs are generated by GitHub, not user-controlled. set -e # Default to running all checks echo "go=true" >> $GITHUB_OUTPUT echo "wasm=true" >> $GITHUB_OUTPUT echo "docs=true" >> $GITHUB_OUTPUT echo "rego=true" >> $GITHUB_OUTPUT echo "yaml=true" >> $GITHUB_OUTPUT echo "proto=true" >> $GITHUB_OUTPUT # Get changed files: use git diff for merge_group, PR API for pull_request if [ -n "${{ github.event.merge_group.base_sha }}" ]; then # Fetch just the base commit; shallow checkout above omits it. git fetch --no-tags --depth=1 origin "${{ github.event.merge_group.base_sha }}" git diff --name-only "${{ github.event.merge_group.base_sha }}" "${{ github.event.merge_group.head_sha }}" \ | jq -R '{filename: .}' | jq -s '.' > changed_files.json elif ! curl -s -o changed_files.json -H "Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}" \ "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files"; then echo "Error: Failed to fetch changed files from GitHub API" echo "Defaulting to running all checks (go=true, wasm=true, docs=true, rego=true, yaml=true, proto=true)" exit 0 fi if [ ! -s changed_files.json ]; then echo "Warning: No changed files found" echo "Defaulting to running all checks (go=true, wasm=true, docs=true, rego=true, yaml=true, proto=true)" exit 0 fi echo "Changed files:" jq -r '.[].filename' changed_files.json opa eval \ --data build/policy/pr-check/pr_check.rego \ --input changed_files.json \ --format pretty \ 'data.policy["pr-check"].changes' > changes.json echo "Final outputs:" jq -r ' ["go","wasm","docs","rego","yaml","proto"][] as $k | "\($k)=\(.[$k] // false)" ' changes.json | tee -a "$GITHUB_OUTPUT" | sed 's/^/ /' # All jobs essentially re-create the `ci-release-test` make target, but are split # up for parallel runners for faster PR feedback and a nicer UX. generate: name: Generate Code runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.go == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Generate run: make clean generate - name: Upload generated artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: generated path: | internal/compiler/wasm/opa capabilities.json go-build: name: Go Build (${{ matrix.os }}${{ matrix.arch && format(' {0}', matrix.arch) || '' }}${{ matrix.go_tags }}) runs-on: ${{ matrix.run }} needs: [generate, check-changes] if: ${{ needs.check-changes.outputs.go == 'true' }} strategy: fail-fast: false matrix: include: - os: linux run: ubuntu-24.04 targets: ci-go-ci-build-linux ci-go-ci-build-linux-static arch: amd64 - os: linux run: ubuntu-24.04 targets: ci-go-ci-build-linux ci-go-ci-build-linux-static arch: arm64 - os: windows run: ubuntu-24.04 targets: ci-build-windows arch: amd64 - os: darwin run: macos-15-intel targets: ci-build-darwin arch: amd64 - os: darwin run: macos-15 targets: ci-build-darwin ci-build-darwin-arm64-static arch: arm64 - # NB(sr): We're only building this to see that it still builds. # The resulting binary is not used in any other way. os: linux run: ubuntu-24.04 targets: ci-build-linux-static go_tags: GO_TAGS="-tags=opa_no_oci" arch: arm64 steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version-file: .go-version if: matrix.os != 'linux' - uses: jdx/mise-action@9e7f7633ff6f6d6048a9418a68d48f288f50eb14 # v4.2.3 with: install: true cache: true mise_toml: | [tools] zig = "0.16.0" if: matrix.os == 'windows' - name: Download generated artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: generated - name: Build run: make ${{ matrix.go_tags }} ${{ matrix.targets }} env: GOARCH: ${{ matrix.arch }} timeout-minutes: 30 - name: Upload binaries - No Go tags uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: ${{ matrix.go_tags == '' }} with: name: binaries-${{ matrix.os }}-${{ matrix.arch }} path: _release go-test: name: Go Test (${{ matrix.os }}) runs-on: ${{ matrix.run }} needs: [generate, check-changes] if: ${{ needs.check-changes.outputs.go == 'true' }} strategy: fail-fast: false matrix: include: - os: linux run: ubuntu-24.04 - os: darwin run: macos-15 steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version-file: .go-version - name: Install Node # docs/.nvmrc is the source of truth for the Node version across the repo. uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: docs/.nvmrc - name: Download generated artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: generated - name: Unit Test Golang run: make test-coverage timeout-minutes: 30 - name: E2E Test Golang run: make e2e go-lint: name: Go Lint runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.go == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Golang Style and Lint Check run: make check timeout-minutes: 30 release-tool: name: Release Tool runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.go == 'true' }} steps: - name: Check out code uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: false - name: Vet, Test and Lint build/release run: make check-release-tool timeout-minutes: 10 yaml-lint: name: YAML Lint runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.yaml == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: YAML Style and Lint Check run: make check-yaml-tests timeout-minutes: 30 env: YAML_LINT_FORMAT: github proto-check: name: Proto Lint and Breaking runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.proto == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: buf lint and breaking uses: bufbuild/buf-action@8c6a16e16f12ba20b6470afa9c2ba9b5ba8c97c3 # v1.5.0 with: github_token: ${{ secrets.GITHUB_TOKEN }} lint: true format: false breaking: true # zizmor: ignore[template-injection] These SHAs are generated by GitHub, not user-controlled. breaking_against: ${{ format('{0}#format=git,commit={1}', github.event.repository.clone_url, github.event.pull_request.base.sha || github.event.merge_group.base_sha) }} pr_comment: false gh-actions-lint: name: Github Actions Lint runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.yaml == 'true' }} steps: - name: Checkout repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Run zizmor uses: zizmorcore/zizmor-action@6fc4b006235f201fdab3722e17240ab420d580e5 # v0.6.1 wasm: name: WASM runs-on: ubuntu-24.04 needs: [generate, check-changes] if: ${{ needs.check-changes.outputs.wasm == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Download generated artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: generated - name: Build and Test Wasm run: make ci-wasm timeout-minutes: 15 - name: Build and Test Wasm SDK run: make ci-go-wasm-sdk-e2e-test timeout-minutes: 30 env: DOCKER_RUNNING: 0 check-generated: name: Check Generated runs-on: ubuntu-24.04 needs: [generate, check-changes] if: ${{ needs.check-changes.outputs.go == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Download generated artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: generated - name: Check Working Copy run: make ci-check-working-copy timeout-minutes: 15 env: DOCKER_RUNNING: 0 race-detector: name: Go Race Detector runs-on: ubuntu-24.04 needs: [generate, check-changes] if: ${{ needs.check-changes.outputs.go == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Download generated artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: generated - name: Test with Race Detector run: make ci-go-race-detector env: DOCKER_RUNNING: 0 smoke-test-docker-images: name: docker image smoke test runs-on: ubuntu-24.04 needs: [go-build, check-changes] if: ${{ needs.check-changes.outputs.go == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Set up QEMU uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 with: platforms: arm64 - name: Download release binaries uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: pattern: binaries-* merge-multiple: true path: _release - name: Test amd64 images run: make ci-image-smoke-test - name: Test arm64 images run: make ci-image-smoke-test env: GOARCH: arm64 # Note(philipc): We only run the amd64 targets for windows/linux smoke-test-binaries: runs-on: ${{ matrix.run }} needs: [go-build, check-changes] if: ${{ needs.check-changes.outputs.go == 'true' }} strategy: matrix: include: - os: linux run: ubuntu-24.04 exec: opa_linux_amd64 arch: amd64 - os: linux run: ubuntu-24.04 exec: opa_linux_amd64_static arch: amd64 wasm: disabled - os: darwin run: macos-15-intel exec: opa_darwin_amd64 arch: amd64 - os: darwin run: macos-15 exec: opa_darwin_arm64_static arch: arm64 wasm: disabled - os: windows run: windows-latest exec: opa_windows_amd64.exe arch: amd64 steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Go uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: stable - name: Download release binaries uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: binaries-${{ matrix.os }}-${{ matrix.arch }} path: _release - name: Prep tests run: cd build/tools && go install tool - name: CLI E2E tests run: | matches=($BINARY_PATH_GLOB) # expand glob export OPA="$(pwd)/${matches[0]}" chmod +x "$OPA" find . -type f -name '*.txtar' -path '*/script/*' -print0 \ | xargs -0 -I{} testscript -e OPA {} shell: bash env: BINARY_PATH_GLOB: _release/*/${{ matrix.exec }} - name: wasm smoke test run: _release/*/${{ matrix.exec }} eval --target wasm 'time.now_ns()' shell: bash if: matrix.wasm != 'disabled' go-version-build: name: Go compat build/test needs: [generate, check-changes] if: ${{ needs.check-changes.outputs.go == 'true' }} runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-24.04, macos-15] version: ["1.26.6"] steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Download generated artifacts uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 with: name: generated - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 with: go-version: ${{ matrix.version }} - run: make build env: DOCKER_RUNNING: 0 - run: make go-test env: DOCKER_RUNNING: 0 # Run PR metadata against Rego policies rego-check-pr: name: Rego PR checks runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.rego == 'true' }} steps: - name: Checkout code # Shallow checkout for a faster clone; merge_group fetches the base below. uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Download OPA uses: open-policy-agent/setup-opa@b2b258e089860efaadaaf71bf6e3aecb4a3eeff1 # v2.4.0 with: version: edge - name: Test policies run: opa test --schema build/policy/schema --bundle build/policy - name: Test embedded Rego policies run: ./build/run-rego-tests.sh - name: Run file policy checks on changed files run: | if [ -n "${{ github.event.merge_group.base_sha }}" ]; then # Fetch just the base commit; shallow checkout above omits it. git fetch --no-tags --depth=1 origin "${{ github.event.merge_group.base_sha }}" git diff --name-only "${{ github.event.merge_group.base_sha }}" "${{ github.event.merge_group.head_sha }}" \ | jq -R '{filename: .}' | jq -s '.' > files.json else curl --silent --fail --header 'Authorization: Bearer ${{ secrets.GITHUB_TOKEN }}' -o files.json \ https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}/files fi opa eval --bundle build/policy --format values --input files.json --fail-defined 'data.files.deny[message]' env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Download Regal uses: open-policy-agent/setup-regal@761188c3b435761fa254beca508a44875619648f # v2.0.0 with: version: latest - name: Run Regal lint # Current configuration ensures anything but build/policy is ignored. While this could point Regal only at that # directory, this will serve as a reminder when more Rego policies are added, as they should be linted by default. run: regal lint --format github . docs-build: name: Build Docs runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.docs == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: docs/.nvmrc cache: npm cache-dependency-path: docs/package-lock.json - name: Build docs run: make docs-ci docs-build docs-fmt-check: name: Docs Format Check runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.docs == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: docs/.nvmrc cache: npm cache-dependency-path: docs/package-lock.json - name: Check docs formatting run: make docs-ci docs-fmt-check docs-lint-check: name: Docs Lint Check runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.docs == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: docs/.nvmrc cache: npm cache-dependency-path: docs/package-lock.json - name: Lint docs run: make docs-ci docs-lint-check docs-markdownlint-check: name: Docs Markdownlint Check runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.docs == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Node uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: node-version-file: docs/.nvmrc cache: npm cache-dependency-path: docs/package-lock.json - name: Check markdown linting run: make docs-ci docs-markdownlint-check docs-gen-check: name: Docs Gen Check runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.docs == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Build OPA uses: ./.github/actions/build-opa - name: Check generated docs are up to date run: make docs-gen-check docs-spell-check: name: Docs Spell Check runs-on: ubuntu-24.04 needs: check-changes if: ${{ needs.check-changes.outputs.docs == 'true' }} steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Install Vale run: | wget -O vale.tar.gz https://github.com/errata-ai/vale/releases/download/v3.13.0/vale_3.13.0_Linux_64-bit.tar.gz sudo tar xzf vale.tar.gz -C /usr/local/bin vale rm vale.tar.gz vale --version - name: Run Vale spell check run: make docs-spell-check benchmarks: name: Benchmarks needs: check-changes if: github.event_name == 'merge_group' && needs.check-changes.outputs.go == 'true' uses: ./.github/workflows/run-benchmarks.yaml with: publish: false test-ocp-with-opa: needs: check-changes if: github.event_name == 'merge_group' && needs.check-changes.outputs.go == 'true' uses: ./.github/workflows/test-ocp-with-opa.yaml test-regal-with-opa: needs: check-changes if: github.event_name == 'merge_group' && needs.check-changes.outputs.go == 'true' uses: ./.github/workflows/test-regal-with-opa.yaml # This job is required to complete before merging, and is set as a branch # protection rule: # https://github.com/open-policy-agent/opa/settings/branch_protection_rules pr-check-summary: name: PR Check Summary runs-on: ubuntu-24.04 needs: [ check-changes, generate, go-build, go-test, go-lint, release-tool, yaml-lint, gh-actions-lint, proto-check, wasm, check-generated, race-detector, smoke-test-docker-images, smoke-test-binaries, go-version-build, rego-check-pr, docs-build, docs-fmt-check, docs-lint-check, docs-markdownlint-check, docs-gen-check, docs-spell-check, benchmarks, test-ocp-with-opa, test-regal-with-opa, ] if: always() steps: - name: Check out code uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: persist-credentials: false - name: Download OPA uses: open-policy-agent/setup-opa@b2b258e089860efaadaaf71bf6e3aecb4a3eeff1 # v2.4.0 with: version: edge - name: Check job results run: | # zizmor: ignore[template-injection] The 'needs' var is controlled by us. # Create the input file with all job results echo '${{ toJSON(needs) }}' > input.json # Find failed or cancelled jobs using OPA opa eval -d .github/workflows/pull-request.yaml \ --input=input.json \ '{job|some _, job in data.jobs["pr-check-summary"].needs} & {job | input[job].result in {"failure", "cancelled"}}' \ --format=raw > failed_jobs.json # Check for failures and display a nice message if [ "$(cat failed_jobs.json)" != "[]" ]; then echo "The following required jobs did not complete successfully:" jq -r '.[]' failed_jobs.json | sed 's/^/- /' exit 1 fi echo "All jobs completed successfully or were skipped"