diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 1a9461d5..d1f8e775 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -35,11 +35,11 @@ jobs: persist-credentials: false - name: Initialize CodeQL - uses: github/codeql-action/init@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 + uses: github/codeql-action/init@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 with: languages: ${{ matrix.language }} - name: Perform CodeQL analysis - uses: github/codeql-action/analyze@8aad20d150bbac5944a9f9d289da16a4b0d87c1e # v4.36.2 + uses: github/codeql-action/analyze@db488ddef3bf6cb639b32c2e9a7c0a7ea8271d28 # v4.37.8 with: category: "/language:${{ matrix.language }}" diff --git a/tests/unit/coverage-script-contract.test.mjs b/tests/unit/coverage-script-contract.test.mjs index 149440e5..f41843e7 100644 --- a/tests/unit/coverage-script-contract.test.mjs +++ b/tests/unit/coverage-script-contract.test.mjs @@ -45,4 +45,29 @@ assert.doesNotMatch( 'coverage cases never recursively invoke a coverage wrapper', ); +const codeqlWorkflow = readFileSync( + new URL('../../.github/workflows/codeql.yml', import.meta.url), + 'utf8', +); +const codeqlActions = [ + ...codeqlWorkflow.matchAll( + /uses:\s*github\/codeql-action\/(init|analyze)@([0-9a-f]{40})\s*#\s*v(\d+\.\d+\.\d+)/g, + ), +].map(([, action, digest, version]) => ({ action, digest, version })); +assert.deepEqual( + codeqlActions.map(({ action }) => action).sort(), + ['analyze', 'init'], + 'CodeQL workflow must pin exactly the init and analyze actions covered by this contract', +); +assert.equal( + new Set(codeqlActions.map(({ version }) => version)).size, + 1, + 'CodeQL init and analyze must use the same released action version', +); +assert.equal( + new Set(codeqlActions.map(({ digest }) => digest)).size, + 1, + 'CodeQL init and analyze must use the same immutable action commit', +); + console.log('✓ coverage script contract tests passed');