From 5db3a9e947b9ac46243a3d76f6e677cdc5cb7ead Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 3 Mar 2026 14:14:34 +0000 Subject: [PATCH 1/6] Extract `JobSpecification` type from `Specification` --- pr-checks/sync.ts | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index ca2b069cb6..8c73e9f63d 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -29,11 +29,9 @@ type WorkflowInputs = Partial>; /** * Represents PR check specifications. */ -interface Specification { +interface Specification extends JobSpecification { /** The display name for the check. */ name: string; - /** The workflow steps specific to this check. */ - steps: any[]; /** Workflow-level input definitions forwarded to `workflow_dispatch`/`workflow_call`. */ inputs?: Record; /** CodeQL bundle versions to test against. Defaults to `DEFAULT_TEST_VERSIONS`. */ @@ -45,25 +43,31 @@ interface Specification { /** Values for the `analysis-kinds` matrix dimension. */ analysisKinds?: string[]; - installNode?: boolean; - installGo?: boolean; - installJava?: boolean; - installPython?: boolean; - installDotNet?: boolean; - installYq?: boolean; - /** Container image configuration for the job. */ container?: any; /** Service containers for the job. */ services?: any; + /** If set, this check is part of a named collection that gets its own caller workflow. */ + collection?: string; +} + +/** Represents job specifications. */ +interface JobSpecification { /** Custom permissions override for the job. */ permissions?: Record; /** Extra environment variables for the job. */ env?: Record; - /** If set, this check is part of a named collection that gets its own caller workflow. */ - collection?: string; + /** The workflow steps specific to this check. */ + steps: any[]; + + installNode?: boolean; + installGo?: boolean; + installJava?: boolean; + installPython?: boolean; + installDotNet?: boolean; + installYq?: boolean; } // The default set of CodeQL Bundle versions to use for the PR checks. From 97a3705788fc10f17713753a106ceec2a64af38a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 3 Mar 2026 13:49:12 +0000 Subject: [PATCH 2/6] Organise language-specific setup information --- .github/workflows/__all-platform-bundle.yml | 24 +- .github/workflows/__analyze-ref-input.yml | 24 +- .github/workflows/__build-mode-manual.yml | 24 +- .github/workflows/__config-input.yml | 14 +- .../__export-file-baseline-information.yml | 24 +- .github/workflows/__go-custom-queries.yml | 24 +- .github/workflows/__go.yml | 12 +- .github/workflows/__local-bundle.yml | 24 +- .../workflows/__multi-language-autodetect.yml | 24 +- ...ackaging-codescanning-config-inputs-js.yml | 38 +-- .../__packaging-config-inputs-js.yml | 36 +-- .github/workflows/__packaging-config-js.yml | 36 +-- .github/workflows/__packaging-inputs-js.yml | 36 +-- .github/workflows/__remote-config.yml | 24 +- .github/workflows/__split-workflow.yml | 24 +- .github/workflows/__swift-custom-build.yml | 24 +- .github/workflows/__unset-environment.yml | 24 +- .github/workflows/__upload-ref-sha-input.yml | 24 +- .github/workflows/__upload-sarif.yml | 24 +- .github/workflows/__with-checkout-path.yml | 24 +- pr-checks/sync.ts | 304 +++++++++++------- 21 files changed, 437 insertions(+), 375 deletions(-) diff --git a/.github/workflows/__all-platform-bundle.yml b/.github/workflows/__all-platform-bundle.yml index 1be5ba9a41..ca61c3d8b5 100644 --- a/.github/workflows/__all-platform-bundle.yml +++ b/.github/workflows/__all-platform-bundle.yml @@ -25,34 +25,34 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: - go-version: - type: string - description: The version of Go to install - required: false - default: '>=1.21.0' dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install required: false default: '>=1.21.0' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x + go-version: + type: string + description: The version of Go to install + required: false + default: '>=1.21.0' defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: all-platform-bundle-${{github.ref}}-${{inputs.go-version}}-${{inputs.dotnet-version}} + group: all-platform-bundle-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}} jobs: all-platform-bundle: strategy: @@ -82,15 +82,15 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'true' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - id: init uses: ./../action/init with: diff --git a/.github/workflows/__analyze-ref-input.yml b/.github/workflows/__analyze-ref-input.yml index 671e5f57b8..952e4a3ae0 100644 --- a/.github/workflows/__analyze-ref-input.yml +++ b/.github/workflows/__analyze-ref-input.yml @@ -25,6 +25,11 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: + dotnet-version: + type: string + description: The version of .NET to install + required: false + default: 9.x go-version: type: string description: The version of Go to install @@ -35,13 +40,13 @@ on: description: The version of Python to install required: false default: '3.13' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install @@ -52,17 +57,12 @@ on: description: The version of Python to install required: false default: '3.13' - dotnet-version: - type: string - description: The version of .NET to install - required: false - default: 9.x defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: analyze-ref-input-${{github.ref}}-${{inputs.go-version}}-${{inputs.python-version}}-${{inputs.dotnet-version}} + group: analyze-ref-input-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}}-${{inputs.python-version}} jobs: analyze-ref-input: strategy: @@ -88,6 +88,10 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: @@ -98,10 +102,6 @@ jobs: uses: actions/setup-python@v6 with: python-version: ${{ inputs.python-version || '3.13' }} - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - uses: ./../action/init with: tools: ${{ steps.prepare-test.outputs.tools-url }} diff --git a/.github/workflows/__build-mode-manual.yml b/.github/workflows/__build-mode-manual.yml index b2723d64f9..3d08a663ba 100644 --- a/.github/workflows/__build-mode-manual.yml +++ b/.github/workflows/__build-mode-manual.yml @@ -25,34 +25,34 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: - go-version: - type: string - description: The version of Go to install - required: false - default: '>=1.21.0' dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install required: false default: '>=1.21.0' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x + go-version: + type: string + description: The version of Go to install + required: false + default: '>=1.21.0' defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: build-mode-manual-${{github.ref}}-${{inputs.go-version}}-${{inputs.dotnet-version}} + group: build-mode-manual-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}} jobs: build-mode-manual: strategy: @@ -78,15 +78,15 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - uses: ./../action/init id: init with: diff --git a/.github/workflows/__config-input.yml b/.github/workflows/__config-input.yml index a2e4dba2c3..f80243926f 100644 --- a/.github/workflows/__config-input.yml +++ b/.github/workflows/__config-input.yml @@ -51,13 +51,6 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v6 - - name: Install Node.js - uses: actions/setup-node@v6 - with: - node-version: 20.x - cache: npm - - name: Install dependencies - run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -65,6 +58,13 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install Node.js + uses: actions/setup-node@v6 + with: + node-version: 20.x + cache: npm + - name: Install dependencies + run: npm ci - name: Copy queries into workspace run: | cp -a ../action/queries . diff --git a/.github/workflows/__export-file-baseline-information.yml b/.github/workflows/__export-file-baseline-information.yml index ef33c6485f..d72d27a5dc 100644 --- a/.github/workflows/__export-file-baseline-information.yml +++ b/.github/workflows/__export-file-baseline-information.yml @@ -25,34 +25,34 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: - go-version: - type: string - description: The version of Go to install - required: false - default: '>=1.21.0' dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install required: false default: '>=1.21.0' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x + go-version: + type: string + description: The version of Go to install + required: false + default: '>=1.21.0' defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: export-file-baseline-information-${{github.ref}}-${{inputs.go-version}}-${{inputs.dotnet-version}} + group: export-file-baseline-information-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}} jobs: export-file-baseline-information: strategy: @@ -82,15 +82,15 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - uses: ./../action/init id: init with: diff --git a/.github/workflows/__go-custom-queries.yml b/.github/workflows/__go-custom-queries.yml index f7d5a99f3b..895cc0c1f2 100644 --- a/.github/workflows/__go-custom-queries.yml +++ b/.github/workflows/__go-custom-queries.yml @@ -25,34 +25,34 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: - go-version: - type: string - description: The version of Go to install - required: false - default: '>=1.21.0' dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install required: false default: '>=1.21.0' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x + go-version: + type: string + description: The version of Go to install + required: false + default: '>=1.21.0' defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: go-custom-queries-${{github.ref}}-${{inputs.go-version}}-${{inputs.dotnet-version}} + group: go-custom-queries-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}} jobs: go-custom-queries: strategy: @@ -80,15 +80,15 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - uses: ./../action/init with: languages: go diff --git a/.github/workflows/__go.yml b/.github/workflows/__go.yml index 76d178b723..3688dc6fd8 100644 --- a/.github/workflows/__go.yml +++ b/.github/workflows/__go.yml @@ -10,16 +10,16 @@ env: on: workflow_dispatch: inputs: - go-version: - type: string - description: The version of Go to install - required: false - default: '>=1.21.0' dotnet-version: type: string description: The version of .NET to install required: false default: 9.x + go-version: + type: string + description: The version of Go to install + required: false + default: '>=1.21.0' jobs: go-custom-queries: name: 'Go: Custom queries' @@ -28,8 +28,8 @@ jobs: security-events: read uses: ./.github/workflows/__go-custom-queries.yml with: - go-version: ${{ inputs.go-version }} dotnet-version: ${{ inputs.dotnet-version }} + go-version: ${{ inputs.go-version }} go-indirect-tracing-workaround-diagnostic: name: 'Go: diagnostic when Go is changed after init step' permissions: diff --git a/.github/workflows/__local-bundle.yml b/.github/workflows/__local-bundle.yml index ae77983001..cb33e169fe 100644 --- a/.github/workflows/__local-bundle.yml +++ b/.github/workflows/__local-bundle.yml @@ -25,6 +25,11 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: + dotnet-version: + type: string + description: The version of .NET to install + required: false + default: 9.x go-version: type: string description: The version of Go to install @@ -35,13 +40,13 @@ on: description: The version of Python to install required: false default: '3.13' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install @@ -52,17 +57,12 @@ on: description: The version of Python to install required: false default: '3.13' - dotnet-version: - type: string - description: The version of .NET to install - required: false - default: 9.x defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: local-bundle-${{github.ref}}-${{inputs.go-version}}-${{inputs.python-version}}-${{inputs.dotnet-version}} + group: local-bundle-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}}-${{inputs.python-version}} jobs: local-bundle: strategy: @@ -88,6 +88,10 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: @@ -98,10 +102,6 @@ jobs: uses: actions/setup-python@v6 with: python-version: ${{ inputs.python-version || '3.13' }} - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Fetch latest CodeQL bundle run: | wget https://github.com/github/codeql-action/releases/latest/download/codeql-bundle-linux64.tar.zst diff --git a/.github/workflows/__multi-language-autodetect.yml b/.github/workflows/__multi-language-autodetect.yml index 9cae8d3622..c991d11b84 100644 --- a/.github/workflows/__multi-language-autodetect.yml +++ b/.github/workflows/__multi-language-autodetect.yml @@ -25,6 +25,11 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: + dotnet-version: + type: string + description: The version of .NET to install + required: false + default: 9.x go-version: type: string description: The version of Go to install @@ -35,13 +40,13 @@ on: description: The version of Python to install required: false default: '3.13' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install @@ -52,17 +57,12 @@ on: description: The version of Python to install required: false default: '3.13' - dotnet-version: - type: string - description: The version of .NET to install - required: false - default: 9.x defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: multi-language-autodetect-${{github.ref}}-${{inputs.go-version}}-${{inputs.python-version}}-${{inputs.dotnet-version}} + group: multi-language-autodetect-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}}-${{inputs.python-version}} jobs: multi-language-autodetect: strategy: @@ -122,6 +122,10 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: @@ -132,10 +136,6 @@ jobs: uses: actions/setup-python@v6 with: python-version: ${{ inputs.python-version || '3.13' }} - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Use Xcode 16 if: runner.os == 'macOS' && matrix.version != 'nightly-latest' run: sudo xcode-select -s "/Applications/Xcode_16.app" diff --git a/.github/workflows/__packaging-codescanning-config-inputs-js.yml b/.github/workflows/__packaging-codescanning-config-inputs-js.yml index d0304ecd1d..803587eee3 100644 --- a/.github/workflows/__packaging-codescanning-config-inputs-js.yml +++ b/.github/workflows/__packaging-codescanning-config-inputs-js.yml @@ -25,6 +25,11 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: + dotnet-version: + type: string + description: The version of .NET to install + required: false + default: 9.x go-version: type: string description: The version of Go to install @@ -35,13 +40,13 @@ on: description: The version of Python to install required: false default: '3.13' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install @@ -52,17 +57,12 @@ on: description: The version of Python to install required: false default: '3.13' - dotnet-version: - type: string - description: The version of .NET to install - required: false - default: 9.x defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: packaging-codescanning-config-inputs-js-${{github.ref}}-${{inputs.go-version}}-${{inputs.python-version}}-${{inputs.dotnet-version}} + group: packaging-codescanning-config-inputs-js-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}}-${{inputs.python-version}} jobs: packaging-codescanning-config-inputs-js: strategy: @@ -85,13 +85,6 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v6 - - name: Install Node.js - uses: actions/setup-node@v6 - with: - node-version: 20.x - cache: npm - - name: Install dependencies - run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -99,20 +92,27 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false + - name: Install Node.js + uses: actions/setup-node@v6 + with: + node-version: 20.x + cache: npm + - name: Install dependencies + run: npm ci - name: Install Python if: matrix.version != 'nightly-latest' uses: actions/setup-python@v6 with: python-version: ${{ inputs.python-version || '3.13' }} - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - uses: ./../action/init with: config-file: '.github/codeql/codeql-config-packaging3.yml' diff --git a/.github/workflows/__packaging-config-inputs-js.yml b/.github/workflows/__packaging-config-inputs-js.yml index f971030093..25367fd7e4 100644 --- a/.github/workflows/__packaging-config-inputs-js.yml +++ b/.github/workflows/__packaging-config-inputs-js.yml @@ -25,34 +25,34 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: - go-version: - type: string - description: The version of Go to install - required: false - default: '>=1.21.0' dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install required: false default: '>=1.21.0' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x + go-version: + type: string + description: The version of Go to install + required: false + default: '>=1.21.0' defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: packaging-config-inputs-js-${{github.ref}}-${{inputs.go-version}}-${{inputs.dotnet-version}} + group: packaging-config-inputs-js-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}} jobs: packaging-config-inputs-js: strategy: @@ -75,13 +75,6 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v6 - - name: Install Node.js - uses: actions/setup-node@v6 - with: - node-version: 20.x - cache: npm - - name: Install dependencies - run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -89,15 +82,22 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - - name: Install .NET - uses: actions/setup-dotnet@v5 + - name: Install Node.js + uses: actions/setup-node@v6 with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} + node-version: 20.x + cache: npm + - name: Install dependencies + run: npm ci - uses: ./../action/init with: config-file: '.github/codeql/codeql-config-packaging3.yml' diff --git a/.github/workflows/__packaging-config-js.yml b/.github/workflows/__packaging-config-js.yml index 99bd171f9d..bb8d0491ae 100644 --- a/.github/workflows/__packaging-config-js.yml +++ b/.github/workflows/__packaging-config-js.yml @@ -25,34 +25,34 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: - go-version: - type: string - description: The version of Go to install - required: false - default: '>=1.21.0' dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install required: false default: '>=1.21.0' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x + go-version: + type: string + description: The version of Go to install + required: false + default: '>=1.21.0' defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: packaging-config-js-${{github.ref}}-${{inputs.go-version}}-${{inputs.dotnet-version}} + group: packaging-config-js-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}} jobs: packaging-config-js: strategy: @@ -75,13 +75,6 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v6 - - name: Install Node.js - uses: actions/setup-node@v6 - with: - node-version: 20.x - cache: npm - - name: Install dependencies - run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -89,15 +82,22 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - - name: Install .NET - uses: actions/setup-dotnet@v5 + - name: Install Node.js + uses: actions/setup-node@v6 with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} + node-version: 20.x + cache: npm + - name: Install dependencies + run: npm ci - uses: ./../action/init with: config-file: '.github/codeql/codeql-config-packaging.yml' diff --git a/.github/workflows/__packaging-inputs-js.yml b/.github/workflows/__packaging-inputs-js.yml index e5cd0182ec..16ab2c0cec 100644 --- a/.github/workflows/__packaging-inputs-js.yml +++ b/.github/workflows/__packaging-inputs-js.yml @@ -25,34 +25,34 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: - go-version: - type: string - description: The version of Go to install - required: false - default: '>=1.21.0' dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install required: false default: '>=1.21.0' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x + go-version: + type: string + description: The version of Go to install + required: false + default: '>=1.21.0' defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: packaging-inputs-js-${{github.ref}}-${{inputs.go-version}}-${{inputs.dotnet-version}} + group: packaging-inputs-js-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}} jobs: packaging-inputs-js: strategy: @@ -75,13 +75,6 @@ jobs: steps: - name: Check out repository uses: actions/checkout@v6 - - name: Install Node.js - uses: actions/setup-node@v6 - with: - node-version: 20.x - cache: npm - - name: Install dependencies - run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -89,15 +82,22 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - - name: Install .NET - uses: actions/setup-dotnet@v5 + - name: Install Node.js + uses: actions/setup-node@v6 with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} + node-version: 20.x + cache: npm + - name: Install dependencies + run: npm ci - uses: ./../action/init with: config-file: '.github/codeql/codeql-config-packaging2.yml' diff --git a/.github/workflows/__remote-config.yml b/.github/workflows/__remote-config.yml index abf5cd21e2..af323ed1ac 100644 --- a/.github/workflows/__remote-config.yml +++ b/.github/workflows/__remote-config.yml @@ -25,6 +25,11 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: + dotnet-version: + type: string + description: The version of .NET to install + required: false + default: 9.x go-version: type: string description: The version of Go to install @@ -35,13 +40,13 @@ on: description: The version of Python to install required: false default: '3.13' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install @@ -52,17 +57,12 @@ on: description: The version of Python to install required: false default: '3.13' - dotnet-version: - type: string - description: The version of .NET to install - required: false - default: 9.x defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: remote-config-${{github.ref}}-${{inputs.go-version}}-${{inputs.python-version}}-${{inputs.dotnet-version}} + group: remote-config-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}}-${{inputs.python-version}} jobs: remote-config: strategy: @@ -90,6 +90,10 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: @@ -100,10 +104,6 @@ jobs: uses: actions/setup-python@v6 with: python-version: ${{ inputs.python-version || '3.13' }} - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - uses: ./../action/init with: tools: ${{ steps.prepare-test.outputs.tools-url }} diff --git a/.github/workflows/__split-workflow.yml b/.github/workflows/__split-workflow.yml index 58e547f367..7359f4d5fc 100644 --- a/.github/workflows/__split-workflow.yml +++ b/.github/workflows/__split-workflow.yml @@ -25,34 +25,34 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: - go-version: - type: string - description: The version of Go to install - required: false - default: '>=1.21.0' dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install required: false default: '>=1.21.0' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x + go-version: + type: string + description: The version of Go to install + required: false + default: '>=1.21.0' defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: split-workflow-${{github.ref}}-${{inputs.go-version}}-${{inputs.dotnet-version}} + group: split-workflow-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}} jobs: split-workflow: strategy: @@ -88,15 +88,15 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - uses: ./../action/init with: config-file: '.github/codeql/codeql-config-packaging3.yml' diff --git a/.github/workflows/__swift-custom-build.yml b/.github/workflows/__swift-custom-build.yml index 7749f1b814..7e1f15e0c3 100644 --- a/.github/workflows/__swift-custom-build.yml +++ b/.github/workflows/__swift-custom-build.yml @@ -25,34 +25,34 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: - go-version: - type: string - description: The version of Go to install - required: false - default: '>=1.21.0' dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install required: false default: '>=1.21.0' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x + go-version: + type: string + description: The version of Go to install + required: false + default: '>=1.21.0' defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: swift-custom-build-${{github.ref}}-${{inputs.go-version}}-${{inputs.dotnet-version}} + group: swift-custom-build-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}} jobs: swift-custom-build: strategy: @@ -82,15 +82,15 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: go-version: ${{ inputs.go-version || '>=1.21.0' }} cache: false - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Use Xcode 16 if: runner.os == 'macOS' && matrix.version != 'nightly-latest' run: sudo xcode-select -s "/Applications/Xcode_16.app" diff --git a/.github/workflows/__unset-environment.yml b/.github/workflows/__unset-environment.yml index 5be68f8102..5c5ee701ff 100644 --- a/.github/workflows/__unset-environment.yml +++ b/.github/workflows/__unset-environment.yml @@ -25,6 +25,11 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: + dotnet-version: + type: string + description: The version of .NET to install + required: false + default: 9.x go-version: type: string description: The version of Go to install @@ -35,13 +40,13 @@ on: description: The version of Python to install required: false default: '3.13' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install @@ -52,17 +57,12 @@ on: description: The version of Python to install required: false default: '3.13' - dotnet-version: - type: string - description: The version of .NET to install - required: false - default: 9.x defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: unset-environment-${{github.ref}}-${{inputs.go-version}}-${{inputs.python-version}}-${{inputs.dotnet-version}} + group: unset-environment-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}}-${{inputs.python-version}} jobs: unset-environment: strategy: @@ -90,6 +90,10 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: @@ -100,10 +104,6 @@ jobs: uses: actions/setup-python@v6 with: python-version: ${{ inputs.python-version || '3.13' }} - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - uses: ./../action/init id: init with: diff --git a/.github/workflows/__upload-ref-sha-input.yml b/.github/workflows/__upload-ref-sha-input.yml index f9a832d7ee..1882ec23c9 100644 --- a/.github/workflows/__upload-ref-sha-input.yml +++ b/.github/workflows/__upload-ref-sha-input.yml @@ -25,6 +25,11 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: + dotnet-version: + type: string + description: The version of .NET to install + required: false + default: 9.x go-version: type: string description: The version of Go to install @@ -35,13 +40,13 @@ on: description: The version of Python to install required: false default: '3.13' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install @@ -52,17 +57,12 @@ on: description: The version of Python to install required: false default: '3.13' - dotnet-version: - type: string - description: The version of .NET to install - required: false - default: 9.x defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: upload-ref-sha-input-${{github.ref}}-${{inputs.go-version}}-${{inputs.python-version}}-${{inputs.dotnet-version}} + group: upload-ref-sha-input-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}}-${{inputs.python-version}} jobs: upload-ref-sha-input: strategy: @@ -88,6 +88,10 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: @@ -98,10 +102,6 @@ jobs: uses: actions/setup-python@v6 with: python-version: ${{ inputs.python-version || '3.13' }} - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - uses: ./../action/init with: tools: ${{ steps.prepare-test.outputs.tools-url }} diff --git a/.github/workflows/__upload-sarif.yml b/.github/workflows/__upload-sarif.yml index 873ba5ca99..4055c08738 100644 --- a/.github/workflows/__upload-sarif.yml +++ b/.github/workflows/__upload-sarif.yml @@ -25,6 +25,11 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: + dotnet-version: + type: string + description: The version of .NET to install + required: false + default: 9.x go-version: type: string description: The version of Go to install @@ -35,13 +40,13 @@ on: description: The version of Python to install required: false default: '3.13' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install @@ -52,17 +57,12 @@ on: description: The version of Python to install required: false default: '3.13' - dotnet-version: - type: string - description: The version of .NET to install - required: false - default: 9.x defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: upload-sarif-${{github.ref}}-${{inputs.go-version}}-${{inputs.python-version}}-${{inputs.dotnet-version}} + group: upload-sarif-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}}-${{inputs.python-version}} jobs: upload-sarif: strategy: @@ -95,6 +95,10 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: @@ -105,10 +109,6 @@ jobs: uses: actions/setup-python@v6 with: python-version: ${{ inputs.python-version || '3.13' }} - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - uses: ./../action/init with: tools: ${{ steps.prepare-test.outputs.tools-url }} diff --git a/.github/workflows/__with-checkout-path.yml b/.github/workflows/__with-checkout-path.yml index 11f6e1dbc0..b0fab4b711 100644 --- a/.github/workflows/__with-checkout-path.yml +++ b/.github/workflows/__with-checkout-path.yml @@ -25,6 +25,11 @@ on: - cron: '0 5 * * *' workflow_dispatch: inputs: + dotnet-version: + type: string + description: The version of .NET to install + required: false + default: 9.x go-version: type: string description: The version of Go to install @@ -35,13 +40,13 @@ on: description: The version of Python to install required: false default: '3.13' + workflow_call: + inputs: dotnet-version: type: string description: The version of .NET to install required: false default: 9.x - workflow_call: - inputs: go-version: type: string description: The version of Go to install @@ -52,17 +57,12 @@ on: description: The version of Python to install required: false default: '3.13' - dotnet-version: - type: string - description: The version of .NET to install - required: false - default: 9.x defaults: run: shell: bash concurrency: cancel-in-progress: ${{ github.event_name == 'pull_request' || false }} - group: with-checkout-path-${{github.ref}}-${{inputs.go-version}}-${{inputs.python-version}}-${{inputs.dotnet-version}} + group: with-checkout-path-${{github.ref}}-${{inputs.dotnet-version}}-${{inputs.go-version}}-${{inputs.python-version}} jobs: with-checkout-path: strategy: @@ -89,6 +89,10 @@ jobs: version: ${{ matrix.version }} use-all-platform-bundle: 'false' setup-kotlin: 'true' + - name: Install .NET + uses: actions/setup-dotnet@v5 + with: + dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Install Go uses: actions/setup-go@v6 with: @@ -99,10 +103,6 @@ jobs: uses: actions/setup-python@v6 with: python-version: ${{ inputs.python-version || '3.13' }} - - name: Install .NET - uses: actions/setup-dotnet@v5 - with: - dotnet-version: ${{ inputs.dotnet-version || '9.x' }} - name: Delete original checkout run: | # delete the original checkout so we don't accidentally use it. diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 8c73e9f63d..f7a49b7fc8 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -5,6 +5,8 @@ import * as path from "path"; import * as yaml from "yaml"; +import { KnownLanguage } from "../src/languages"; + /** Known workflow input names. */ enum KnownInputName { GoVersion = "go-version", @@ -70,6 +72,16 @@ interface JobSpecification { installYq?: boolean; } +/** Describes language/framework-specific steps and inputs. */ +interface LanguageSetup { + specProperty: keyof JobSpecification; + inputs?: WorkflowInputs; + steps: any[]; +} + +/** Describes partial mappings from known languages to their specific setup information. */ +type LanguageSetups = Partial>; + // The default set of CodeQL Bundle versions to use for the PR checks. const defaultTestVersions = [ // The oldest supported CodeQL version. If bumping, update `CODEQL_MINIMUM_VERSION` in `codeql.ts` @@ -94,6 +106,131 @@ const defaultTestVersions = [ "nightly-latest", ]; +/** The default versions we use for languages / frameworks, if not specified as a workflow input. */ +const defaultLanguageVersions = { + javascript: "20.x", + go: ">=1.21.0", + java: "17", + python: "3.13", + csharp: "9.x", +} as const satisfies Partial>; + +/** A partial mapping from known languages to their specific setup information. */ +const languageSetups: LanguageSetups = { + javascript: { + specProperty: "installNode", + steps: [ + { + name: "Install Node.js", + uses: "actions/setup-node@v6", + with: { + "node-version": defaultLanguageVersions.javascript, + cache: "npm", + }, + }, + { + name: "Install dependencies", + run: "npm ci", + }, + ], + }, + go: { + specProperty: "installGo", + inputs: { + [KnownInputName.GoVersion]: { + type: "string", + description: "The version of Go to install", + required: false, + default: defaultLanguageVersions.go, + }, + }, + steps: [ + { + name: "Install Go", + uses: "actions/setup-go@v6", + with: { + "go-version": + "${{ inputs.go-version || '" + defaultLanguageVersions.go + "' }}", + // to avoid potentially misleading autobuilder results where we expect it to download + // dependencies successfully, but they actually come from a warm cache + cache: false, + }, + }, + ], + }, + java: { + specProperty: "installJava", + inputs: { + [KnownInputName.JavaVersion]: { + type: "string", + description: "The version of Java to install", + required: false, + default: defaultLanguageVersions.java, + }, + }, + steps: [ + { + name: "Install Java", + uses: "actions/setup-java@v5", + with: { + "java-version": + "${{ inputs.java-version || '" + + defaultLanguageVersions.java + + "' }}", + distribution: "temurin", + }, + }, + ], + }, + python: { + specProperty: "installPython", + inputs: { + [KnownInputName.PythonVersion]: { + type: "string", + description: "The version of Python to install", + required: false, + default: defaultLanguageVersions.python, + }, + }, + steps: [ + { + name: "Install Python", + if: "matrix.version != 'nightly-latest'", + uses: "actions/setup-python@v6", + with: { + "python-version": + "${{ inputs.python-version || '" + + defaultLanguageVersions.python + + "' }}", + }, + }, + ], + }, + csharp: { + specProperty: "installDotNet", + inputs: { + [KnownInputName.DotnetVersion]: { + type: "string", + description: "The version of .NET to install", + required: false, + default: defaultLanguageVersions.csharp, + }, + }, + steps: [ + { + name: "Install .NET", + uses: "actions/setup-dotnet@v5", + with: { + "dotnet-version": + "${{ inputs.dotnet-version || '" + + defaultLanguageVersions.csharp + + "' }}", + }, + }, + ], + }, +}; + const THIS_DIR = __dirname; const CHECKS_DIR = path.join(THIS_DIR, "checks"); const OUTPUT_DIR = path.join(THIS_DIR, "..", ".github", "workflows"); @@ -138,6 +275,36 @@ function stripTrailingWhitespace(content: string): string { .join("\n"); } +/** + * Retrieves setup steps and additional input definitions based on specific languages or frameworks + * that are requested by the `checkSpecification`. + * + * @returns An object containing setup steps and additional input specifications. + */ +function getSetupSteps(checkSpecification: Specification): { + inputs: WorkflowInputs; + steps: any[]; +} { + let inputs: WorkflowInputs = {}; + const steps = []; + + for (const language of Object.values(KnownLanguage).sort()) { + const setupSpec = languageSetups[language]; + + if ( + setupSpec === undefined || + checkSpecification[setupSpec.specProperty] === undefined + ) { + continue; + } + + steps.push(...setupSpec.steps); + inputs = { ...inputs, ...setupSpec.inputs }; + } + + return { inputs, steps }; +} + /** * Main entry point for the sync script. */ @@ -170,7 +337,6 @@ function main(): void { console.log(`Processing: ${checkName} — "${checkSpecification.name}"`); - const workflowInputs: WorkflowInputs = {}; let matrix: Array> = []; for (const version of checkSpecification.versions ?? defaultTestVersions) { @@ -216,134 +382,30 @@ function main(): void { matrix = newMatrix; } + // Determine which languages or frameworks have to be installed. + const setupInfo = getSetupSteps(checkSpecification); + const workflowInputs = setupInfo.inputs; + // Construct the workflow steps needed for this check. const steps: any[] = [ { name: "Check out repository", uses: "actions/checkout@v6", }, - ]; - - const installNode = checkSpecification.installNode; - - if (installNode) { - steps.push( - { - name: "Install Node.js", - uses: "actions/setup-node@v6", - with: { - "node-version": "20.x", - cache: "npm", - }, - }, - { - name: "Install dependencies", - run: "npm ci", - }, - ); - } - - steps.push({ - name: "Prepare test", - id: "prepare-test", - uses: "./.github/actions/prepare-test", - with: { - version: "${{ matrix.version }}", - "use-all-platform-bundle": useAllPlatformBundle, - // If the action is being run from a container, then do not setup kotlin. - // This is because the kotlin binaries cannot be downloaded from the container. - "setup-kotlin": "container" in checkSpecification ? "false" : "true", - }, - }); - - const installGo = checkSpecification.installGo; - - if (installGo) { - const baseGoVersionExpr = ">=1.21.0"; - workflowInputs[KnownInputName.GoVersion] = { - type: "string", - description: "The version of Go to install", - required: false, - default: baseGoVersionExpr, - }; - - steps.push({ - name: "Install Go", - uses: "actions/setup-go@v6", - with: { - "go-version": - "${{ inputs.go-version || '" + baseGoVersionExpr + "' }}", - // to avoid potentially misleading autobuilder results where we expect it to download - // dependencies successfully, but they actually come from a warm cache - cache: false, - }, - }); - } - - const installJava = checkSpecification.installJava; - - if (installJava) { - const baseJavaVersionExpr = "17"; - workflowInputs[KnownInputName.JavaVersion] = { - type: "string", - description: "The version of Java to install", - required: false, - default: baseJavaVersionExpr, - }; - - steps.push({ - name: "Install Java", - uses: "actions/setup-java@v5", - with: { - "java-version": - "${{ inputs.java-version || '" + baseJavaVersionExpr + "' }}", - distribution: "temurin", - }, - }); - } - - const installPython = checkSpecification.installPython; - - if (installPython) { - const basePythonVersionExpr = "3.13"; - workflowInputs[KnownInputName.PythonVersion] = { - type: "string", - description: "The version of Python to install", - required: false, - default: basePythonVersionExpr, - }; - - steps.push({ - name: "Install Python", - if: "matrix.version != 'nightly-latest'", - uses: "actions/setup-python@v6", - with: { - "python-version": - "${{ inputs.python-version || '" + basePythonVersionExpr + "' }}", - }, - }); - } - - const installDotNet = checkSpecification.installDotNet; - - if (installDotNet) { - const baseDotNetVersionExpr = "9.x"; - workflowInputs[KnownInputName.DotnetVersion] = { - type: "string", - description: "The version of .NET to install", - required: false, - default: baseDotNetVersionExpr, - }; - - steps.push({ - name: "Install .NET", - uses: "actions/setup-dotnet@v5", + { + name: "Prepare test", + id: "prepare-test", + uses: "./.github/actions/prepare-test", with: { - "dotnet-version": - "${{ inputs.dotnet-version || '" + baseDotNetVersionExpr + "' }}", + version: "${{ matrix.version }}", + "use-all-platform-bundle": useAllPlatformBundle, + // If the action is being run from a container, then do not setup kotlin. + // This is because the kotlin binaries cannot be downloaded from the container. + "setup-kotlin": "container" in checkSpecification ? "false" : "true", }, - }); - } + }, + ...setupInfo.steps, + ]; const installYq = checkSpecification.installYq; From 369d73b98fa4e47970096f2bc039084b89a58afd Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 3 Mar 2026 13:53:36 +0000 Subject: [PATCH 3/6] Refactor matrix generation into its own function --- pr-checks/sync.ts | 88 +++++++++++++++++++++++++---------------------- 1 file changed, 47 insertions(+), 41 deletions(-) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index f7a49b7fc8..c6d990c31a 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -275,6 +275,52 @@ function stripTrailingWhitespace(content: string): string { .join("\n"); } +/** Generates the matrix for a job. */ +function generateJobMatrix( + checkSpecification: Specification, +): Array> { + let matrix: Array> = []; + + for (const version of checkSpecification.versions ?? defaultTestVersions) { + if (version === "latest") { + throw new Error( + 'Did not recognise "version: latest". Did you mean "version: linked"?', + ); + } + + const runnerImages = ["ubuntu-latest", "macos-latest", "windows-latest"]; + const operatingSystems = checkSpecification.operatingSystems ?? ["ubuntu"]; + + for (const operatingSystem of operatingSystems) { + const runnerImagesForOs = runnerImages.filter((image) => + image.startsWith(operatingSystem), + ); + + for (const runnerImage of runnerImagesForOs) { + matrix.push({ + os: runnerImage, + version, + }); + } + } + } + + if (checkSpecification.analysisKinds) { + const newMatrix: Array> = []; + for (const matrixInclude of matrix) { + for (const analysisKind of checkSpecification.analysisKinds) { + newMatrix.push({ + ...matrixInclude, + "analysis-kinds": analysisKind, + }); + } + } + matrix = newMatrix; + } + + return matrix; +} + /** * Retrieves setup steps and additional input definitions based on specific languages or frameworks * that are requested by the `checkSpecification`. @@ -337,51 +383,11 @@ function main(): void { console.log(`Processing: ${checkName} — "${checkSpecification.name}"`); - let matrix: Array> = []; - - for (const version of checkSpecification.versions ?? defaultTestVersions) { - if (version === "latest") { - throw new Error( - 'Did not recognise "version: latest". Did you mean "version: linked"?', - ); - } - - const runnerImages = ["ubuntu-latest", "macos-latest", "windows-latest"]; - const operatingSystems = checkSpecification.operatingSystems ?? [ - "ubuntu", - ]; - - for (const operatingSystem of operatingSystems) { - const runnerImagesForOs = runnerImages.filter((image) => - image.startsWith(operatingSystem), - ); - - for (const runnerImage of runnerImagesForOs) { - matrix.push({ - os: runnerImage, - version, - }); - } - } - } - + const matrix: Array> = generateJobMatrix(checkSpecification); const useAllPlatformBundle = checkSpecification.useAllPlatformBundle ? checkSpecification.useAllPlatformBundle : "false"; - if (checkSpecification.analysisKinds) { - const newMatrix: Array> = []; - for (const matrixInclude of matrix) { - for (const analysisKind of checkSpecification.analysisKinds) { - newMatrix.push({ - ...matrixInclude, - "analysis-kinds": analysisKind, - }); - } - } - matrix = newMatrix; - } - // Determine which languages or frameworks have to be installed. const setupInfo = getSetupSteps(checkSpecification); const workflowInputs = setupInfo.inputs; From 92ab799fe0e7addb7a082bf77beb3609aeea3f02 Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 3 Mar 2026 14:00:45 +0000 Subject: [PATCH 4/6] Refactor job generation into `generateJob` --- pr-checks/sync.ts | 217 +++++++++++++++++++++++++--------------------- 1 file changed, 120 insertions(+), 97 deletions(-) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index c6d990c31a..856cf295ce 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -351,6 +351,122 @@ function getSetupSteps(checkSpecification: Specification): { return { inputs, steps }; } +/** + * Generates an Actions job from the `checkSpecification`. + * + * @param specDocument + * The raw YAML document of the PR check specification. + * Used to extract `jobs` without losing the original formatting. + * @param checkSpecification The PR check specification. + * @returns The job and additional workflow inputs. + */ +function generateJob( + specDocument: yaml.Document, + checkSpecification: Specification, +) { + const matrix: Array> = + generateJobMatrix(checkSpecification); + + const useAllPlatformBundle = checkSpecification.useAllPlatformBundle + ? checkSpecification.useAllPlatformBundle + : "false"; + + // Determine which languages or frameworks have to be installed. + const setupInfo = getSetupSteps(checkSpecification); + const workflowInputs = setupInfo.inputs; + + // Construct the workflow steps needed for this check. + const steps: any[] = [ + { + name: "Check out repository", + uses: "actions/checkout@v6", + }, + { + name: "Prepare test", + id: "prepare-test", + uses: "./.github/actions/prepare-test", + with: { + version: "${{ matrix.version }}", + "use-all-platform-bundle": useAllPlatformBundle, + // If the action is being run from a container, then do not setup kotlin. + // This is because the kotlin binaries cannot be downloaded from the container. + "setup-kotlin": "container" in checkSpecification ? "false" : "true", + }, + }, + ...setupInfo.steps, + ]; + + const installYq = checkSpecification.installYq; + + if (installYq) { + steps.push({ + name: "Install yq", + if: "runner.os == 'Windows'", + env: { + YQ_PATH: "${{ runner.temp }}/yq", + // This is essentially an arbitrary version of `yq`, which happened to be the one that + // `choco` fetched when we moved away from using that here. + // See https://github.com/github/codeql-action/pull/3423 + YQ_VERSION: "v4.50.1", + }, + run: + 'gh release download --repo mikefarah/yq --pattern "yq_windows_amd64.exe" "$YQ_VERSION" -O "$YQ_PATH/yq.exe"\n' + + 'echo "$YQ_PATH" >> "$GITHUB_PATH"', + }); + } + + // Extract the sequence of steps from the YAML document to persist as much formatting as possible. + const specSteps = specDocument.get("steps") as yaml.YAMLSeq; + + // A handful of workflow specifications use double quotes for values, while we generally use single quotes. + // This replaces double quotes with single quotes for consistency. + yaml.visit(specSteps, { + Scalar(_key, node) { + if (node.type === "QUOTE_DOUBLE") { + node.type = "QUOTE_SINGLE"; + } + }, + }); + + // Add the generated steps in front of the ones from the specification. + specSteps.items.unshift(...steps); + + const checkJob: Record = { + strategy: { + "fail-fast": false, + matrix: { + include: matrix, + }, + }, + name: checkSpecification.name, + if: "github.triggering_actor != 'dependabot[bot]'", + permissions: { + contents: "read", + "security-events": "read", + }, + "timeout-minutes": 45, + "runs-on": "${{ matrix.os }}", + steps: specSteps, + }; + + if (checkSpecification.permissions) { + checkJob.permissions = checkSpecification.permissions; + } + + for (const key of ["env", "container", "services"] as const) { + if (checkSpecification[key] !== undefined) { + checkJob[key] = checkSpecification[key]; + } + } + + checkJob.env = checkJob.env ?? {}; + if (!("CODEQL_ACTION_TEST_MODE" in checkJob.env)) { + checkJob.env.CODEQL_ACTION_TEST_MODE = true; + } + + return { checkJob, workflowInputs }; +} + /** * Main entry point for the sync script. */ @@ -383,103 +499,10 @@ function main(): void { console.log(`Processing: ${checkName} — "${checkSpecification.name}"`); - const matrix: Array> = generateJobMatrix(checkSpecification); - const useAllPlatformBundle = checkSpecification.useAllPlatformBundle - ? checkSpecification.useAllPlatformBundle - : "false"; - - // Determine which languages or frameworks have to be installed. - const setupInfo = getSetupSteps(checkSpecification); - const workflowInputs = setupInfo.inputs; - - // Construct the workflow steps needed for this check. - const steps: any[] = [ - { - name: "Check out repository", - uses: "actions/checkout@v6", - }, - { - name: "Prepare test", - id: "prepare-test", - uses: "./.github/actions/prepare-test", - with: { - version: "${{ matrix.version }}", - "use-all-platform-bundle": useAllPlatformBundle, - // If the action is being run from a container, then do not setup kotlin. - // This is because the kotlin binaries cannot be downloaded from the container. - "setup-kotlin": "container" in checkSpecification ? "false" : "true", - }, - }, - ...setupInfo.steps, - ]; - - const installYq = checkSpecification.installYq; - - if (installYq) { - steps.push({ - name: "Install yq", - if: "runner.os == 'Windows'", - env: { - YQ_PATH: "${{ runner.temp }}/yq", - // This is essentially an arbitrary version of `yq`, which happened to be the one that - // `choco` fetched when we moved away from using that here. - // See https://github.com/github/codeql-action/pull/3423 - YQ_VERSION: "v4.50.1", - }, - run: - 'gh release download --repo mikefarah/yq --pattern "yq_windows_amd64.exe" "$YQ_VERSION" -O "$YQ_PATH/yq.exe"\n' + - 'echo "$YQ_PATH" >> "$GITHUB_PATH"', - }); - } - - // Extract the sequence of steps from the YAML document to persist as much formatting as possible. - const specSteps = specDocument.get("steps") as yaml.YAMLSeq; - - // A handful of workflow specifications use double quotes for values, while we generally use single quotes. - // This replaces double quotes with single quotes for consistency. - yaml.visit(specSteps, { - Scalar(_key, node) { - if (node.type === "QUOTE_DOUBLE") { - node.type = "QUOTE_SINGLE"; - } - }, - }); - - // Add the generated steps in front of the ones from the specification. - specSteps.items.unshift(...steps); - - const checkJob: Record = { - strategy: { - "fail-fast": false, - matrix: { - include: matrix, - }, - }, - name: checkSpecification.name, - if: "github.triggering_actor != 'dependabot[bot]'", - permissions: { - contents: "read", - "security-events": "read", - }, - "timeout-minutes": 45, - "runs-on": "${{ matrix.os }}", - steps: specSteps, - }; - - if (checkSpecification.permissions) { - checkJob.permissions = checkSpecification.permissions; - } - - for (const key of ["env", "container", "services"] as const) { - if (checkSpecification[key] !== undefined) { - checkJob[key] = checkSpecification[key]; - } - } - - checkJob.env = checkJob.env ?? {}; - if (!("CODEQL_ACTION_TEST_MODE" in checkJob.env)) { - checkJob.env.CODEQL_ACTION_TEST_MODE = true; - } + const { checkJob, workflowInputs } = generateJob( + specDocument, + checkSpecification, + ); // If this check belongs to a named collection, record it. if (checkSpecification.collection) { From 95fc2f11fbd3f73b1b8df4e76a944f5fed52175c Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Wed, 4 Mar 2026 11:27:42 +0000 Subject: [PATCH 5/6] Move `yq` setup code into `getSetupSteps` --- pr-checks/sync.ts | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 856cf295ce..6a28f5d046 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -231,6 +231,11 @@ const languageSetups: LanguageSetups = { }, }; +// This is essentially an arbitrary version of `yq`, which happened to be the one that +// `choco` fetched when we moved away from using that here. +// See https://github.com/github/codeql-action/pull/3423 +const YQ_VERSION = "v4.50.1"; + const THIS_DIR = __dirname; const CHECKS_DIR = path.join(THIS_DIR, "checks"); const OUTPUT_DIR = path.join(THIS_DIR, "..", ".github", "workflows"); @@ -348,6 +353,22 @@ function getSetupSteps(checkSpecification: Specification): { inputs = { ...inputs, ...setupSpec.inputs }; } + const installYq = checkSpecification.installYq; + + if (installYq) { + steps.push({ + name: "Install yq", + if: "runner.os == 'Windows'", + env: { + YQ_PATH: "${{ runner.temp }}/yq", + YQ_VERSION, + }, + run: + 'gh release download --repo mikefarah/yq --pattern "yq_windows_amd64.exe" "$YQ_VERSION" -O "$YQ_PATH/yq.exe"\n' + + 'echo "$YQ_PATH" >> "$GITHUB_PATH"', + }); + } + return { inputs, steps }; } @@ -396,25 +417,6 @@ function generateJob( ...setupInfo.steps, ]; - const installYq = checkSpecification.installYq; - - if (installYq) { - steps.push({ - name: "Install yq", - if: "runner.os == 'Windows'", - env: { - YQ_PATH: "${{ runner.temp }}/yq", - // This is essentially an arbitrary version of `yq`, which happened to be the one that - // `choco` fetched when we moved away from using that here. - // See https://github.com/github/codeql-action/pull/3423 - YQ_VERSION: "v4.50.1", - }, - run: - 'gh release download --repo mikefarah/yq --pattern "yq_windows_amd64.exe" "$YQ_VERSION" -O "$YQ_PATH/yq.exe"\n' + - 'echo "$YQ_PATH" >> "$GITHUB_PATH"', - }); - } - // Extract the sequence of steps from the YAML document to persist as much formatting as possible. const specSteps = specDocument.get("steps") as yaml.YAMLSeq; From 2b6077152e19c9ddd8fe6e99f9512b04a839313a Mon Sep 17 00:00:00 2001 From: "Michael B. Gale" Date: Tue, 3 Mar 2026 14:56:00 +0000 Subject: [PATCH 6/6] Add support for additional, validation jobs --- pr-checks/sync.ts | 108 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 102 insertions(+), 6 deletions(-) diff --git a/pr-checks/sync.ts b/pr-checks/sync.ts index 6a28f5d046..8f2b2e80ff 100755 --- a/pr-checks/sync.ts +++ b/pr-checks/sync.ts @@ -32,8 +32,6 @@ type WorkflowInputs = Partial>; * Represents PR check specifications. */ interface Specification extends JobSpecification { - /** The display name for the check. */ - name: string; /** Workflow-level input definitions forwarded to `workflow_dispatch`/`workflow_call`. */ inputs?: Record; /** CodeQL bundle versions to test against. Defaults to `DEFAULT_TEST_VERSIONS`. */ @@ -50,12 +48,17 @@ interface Specification extends JobSpecification { /** Service containers for the job. */ services?: any; + /** Additional jobs to run after the main PR check job. */ + validationJobs?: Record; + /** If set, this check is part of a named collection that gets its own caller workflow. */ collection?: string; } /** Represents job specifications. */ interface JobSpecification { + /** The display name for the check. */ + name: string; /** Custom permissions override for the job. */ permissions?: Record; /** Extra environment variables for the job. */ @@ -469,6 +472,92 @@ function generateJob( return { checkJob, workflowInputs }; } +/** Generates a validation job. */ +function generateValidationJob( + specDocument: yaml.Document, + jobSpecification: JobSpecification, + checkName: string, + name: string, +) { + // Determine which languages or frameworks have to be installed. + const { inputs, steps } = getSetupSteps(jobSpecification); + + // Extract the sequence of steps from the YAML document to persist as much formatting as possible. + const specSteps = specDocument.getIn([ + "validationJobs", + name, + "steps", + ]) as yaml.YAMLSeq; + + // Add the generated steps in front of the ones from the specification. + specSteps.items.unshift(...steps); + + const validationJob: Record = { + name: jobSpecification.name, + if: "github.triggering_actor != 'dependabot[bot]'", + needs: [checkName], + permissions: { + contents: "read", + "security-events": "read", + }, + "timeout-minutes": 5, + "runs-on": "ubuntu-slim", + steps: specSteps, + }; + + if (jobSpecification.permissions) { + validationJob.permissions = jobSpecification.permissions; + } + + for (const key of ["env"] as const) { + if (jobSpecification[key] !== undefined) { + validationJob[key] = jobSpecification[key]; + } + } + + validationJob.env = validationJob.env ?? {}; + if (!("CODEQL_ACTION_TEST_MODE" in validationJob.env)) { + validationJob.env.CODEQL_ACTION_TEST_MODE = true; + } + + return { validationJob, inputs }; +} + +/** Generates additional jobs that run after the main check job, based on the `validationJobs` property. */ +function generateValidationJobs( + specDocument: yaml.Document, + checkSpecification: Specification, + checkName: string, +): Record { + if (checkSpecification.validationJobs === undefined) { + return {}; + } + + const validationJobs: Record = {}; + let workflowInputs: WorkflowInputs = {}; + + for (const [jobName, jobSpec] of Object.entries( + checkSpecification.validationJobs, + )) { + if (checkName === jobName) { + throw new Error( + `Validation job '${jobName}' cannot have the same name as the main job.`, + ); + } + + const { validationJob, inputs } = generateValidationJob( + specDocument, + jobSpec, + checkName, + jobName, + ); + validationJobs[jobName] = validationJob; + workflowInputs = { ...workflowInputs, ...inputs }; + } + + return { validationJobs, workflowInputs }; +} + /** * Main entry point for the sync script. */ @@ -505,6 +594,12 @@ function main(): void { specDocument, checkSpecification, ); + const { validationJobs, validationJobInputs } = generateValidationJobs( + specDocument, + checkSpecification, + checkName, + ); + const combinedInputs = { ...workflowInputs, ...validationJobInputs }; // If this check belongs to a named collection, record it. if (checkSpecification.collection) { @@ -515,12 +610,12 @@ function main(): void { collections[collectionName].push({ specification: checkSpecification, checkName, - inputs: workflowInputs, + inputs: combinedInputs, }); } let extraGroupName = ""; - for (const inputName of Object.keys(workflowInputs)) { + for (const inputName of Object.keys(combinedInputs)) { extraGroupName += "-${{inputs." + inputName + "}}"; } @@ -545,10 +640,10 @@ function main(): void { }, schedule: [{ cron }], workflow_dispatch: { - inputs: workflowInputs, + inputs: combinedInputs, }, workflow_call: { - inputs: workflowInputs, + inputs: combinedInputs, }, }, defaults: { @@ -563,6 +658,7 @@ function main(): void { }, jobs: { [checkName]: checkJob, + ...validationJobs, }, };