diff --git a/.github/workflows/__bundle-toolcache.yml b/.github/workflows/__bundle-toolcache.yml index 0055f9470..96a901cf3 100644 --- a/.github/workflows/__bundle-toolcache.yml +++ b/.github/workflows/__bundle-toolcache.yml @@ -50,6 +50,15 @@ jobs: steps: - name: Check out repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Install Node.js + uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0 + with: + node-version: 20.x + cache: npm + - name: Install newer npm + run: npm install -g npm@11.19.1 + - name: Install dependencies + run: npm ci - name: Prepare test id: prepare-test uses: ./.github/actions/prepare-test @@ -58,47 +67,30 @@ jobs: use-all-platform-bundle: 'false' setup-kotlin: 'true' - name: Remove CodeQL from toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const fs = require('fs'); - const path = require('path'); - const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL'); - fs.rmdirSync(codeqlPath, { recursive: true }); - - name: Install @actions/tool-cache - run: npm install @actions/tool-cache@3 + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts clear + - name: Check toolcache does not contain CodeQL - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - if (allCodeqlVersions.length !== 0) { - throw new Error(`CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`); - } - console.log('No versions of CodeQL found in the toolcache'); + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts absent + - id: init uses: ./../action/init with: # Request multiple languages so this check uses the combined bundle. languages: javascript,python tools: ${{ steps.prepare-test.outputs.tools-url }} + - uses: ./../action/analyze with: output: ${{ runner.temp }}/results upload-database: false + - name: Check CodeQL is installed within the toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - console.log(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { - throw new Error('CodeQL not found in toolcache'); - } - if (allCodeqlVersions.length > 1) { - throw new Error('Multiple CodeQL versions found in toolcache'); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed -n 1 env: CODEQL_ACTION_TEST_MODE: true diff --git a/pr-checks/checks/bundle-toolcache.yml b/pr-checks/checks/bundle-toolcache.yml index f74c6af75..3317a45f4 100644 --- a/pr-checks/checks/bundle-toolcache.yml +++ b/pr-checks/checks/bundle-toolcache.yml @@ -6,47 +6,31 @@ operatingSystems: - ubuntu - macos - windows +installNode: true steps: - name: Remove CodeQL from toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const fs = require('fs'); - const path = require('path'); - const codeqlPath = path.join(process.env['RUNNER_TOOL_CACHE'], 'CodeQL'); - fs.rmdirSync(codeqlPath, { recursive: true }); - - name: Install @actions/tool-cache - run: npm install @actions/tool-cache@3 + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts clear + - name: Check toolcache does not contain CodeQL - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - if (allCodeqlVersions.length !== 0) { - throw new Error(`CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`); - } - console.log('No versions of CodeQL found in the toolcache'); + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts absent + - id: init uses: ./../action/init with: # Request multiple languages so this check uses the combined bundle. languages: javascript,python tools: ${{ steps.prepare-test.outputs.tools-url }} + - uses: ./../action/analyze with: output: ${{ runner.temp }}/results upload-database: false + - name: Check CodeQL is installed within the toolcache - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - with: - script: | - const toolcache = require('@actions/tool-cache'); - const allCodeqlVersions = toolcache.findAllVersions('CodeQL'); - console.log(`Found CodeQL versions: ${allCodeqlVersions}`); - if (allCodeqlVersions.length === 0) { - throw new Error('CodeQL not found in toolcache'); - } - if (allCodeqlVersions.length > 1) { - throw new Error('Multiple CodeQL versions found in toolcache'); - } + run: | + cd ./../action + npx tsx ./pr-checks/toolcache.ts installed -n 1 diff --git a/pr-checks/toolcache.ts b/pr-checks/toolcache.ts new file mode 100755 index 000000000..a14605e38 --- /dev/null +++ b/pr-checks/toolcache.ts @@ -0,0 +1,94 @@ +#!/usr/bin/env npx tsx + +/** + * Provides utility commands for working with the Actions toolcache in PR checks. + */ + +import fs from "fs"; +import { parseArgs } from "node:util"; +import path from "path"; + +import * as core from "@actions/core"; +import * as toolcache from "@actions/tool-cache"; + +function removeCodeQLFromToolcache() { + const toolcachePath = process.env["RUNNER_TOOL_CACHE"]; + + if (toolcachePath === undefined) { + throw new Error("Expected RUNNER_TOOL_CACHE to be defined"); + } + + const codeqlPath = path.join(toolcachePath, "CodeQL"); + fs.rmdirSync(codeqlPath, { recursive: true }); + + core.info(`Removed '${codeqlPath}' from the toolcache.`); +} + +function findCodeQL() { + return toolcache.findAllVersions("CodeQL"); +} + +function noCodeQLInToolcache() { + const allCodeqlVersions = findCodeQL(); + if (allCodeqlVersions.length !== 0) { + throw new Error( + `CodeQL should not be found in the toolcache, but found ${allCodeqlVersions}`, + ); + } + core.info("No versions of CodeQL found in the toolcache"); +} + +function hasCodeQLInToolcache(expectedNumber?: string) { + const expected = + expectedNumber !== undefined + ? Number.parseInt(expectedNumber, 10) + : undefined; + + const allCodeqlVersions = findCodeQL(); + core.info(`Found CodeQL versions: ${allCodeqlVersions}`); + + if (allCodeqlVersions.length === 0) { + throw new Error("CodeQL not found in toolcache"); + } + if (expected !== undefined && allCodeqlVersions.length > expected) { + throw new Error( + `Expected ${expected} versions of CodeQL in the toolcache, but found ${allCodeqlVersions.length}`, + ); + } +} + +function main() { + const { positionals, values } = parseArgs({ + options: { + // The *number* of expected versions in the toolcache. + expectedVersions: { type: "string", short: "n" }, + }, + allowPositionals: true, + }); + + if (positionals.length < 1) { + throw new Error("Command not specified."); + } + + const cmd = positionals[0]; + + switch (cmd.trim().toLowerCase()) { + case "clear": + removeCodeQLFromToolcache(); + return; + case "absent": + noCodeQLInToolcache(); + return; + case "installed": + hasCodeQLInToolcache(values.expectedVersions); + return; + default: + throw new Error(`Unknown command '${cmd}'.`); + } +} + +try { + main(); +} catch (err) { + core.setFailed(err instanceof Error ? err.message : String(err)); +}