From 8aa8f4624432ea6b02f24f91852a57ba71ed6c50 Mon Sep 17 00:00:00 2001 From: awalsh128 Date: Thu, 5 Nov 2026 18:30:20 -0800 Subject: [PATCH] fix: ship ts-apt's apt-fast script with the bundle On runners with aria2 installed, ts-apt uses apt-fast and spawns scripts/dist/apt-fast.sh relative to its own module. Bundling moved that module, so the action failed with "spawn .../scripts/dist/apt-fast.sh ENOENT". Write the bundle to dist/action/index.js and copy ts-apt's scripts/dist to dist/scripts/dist, which is where ts-apt looks from there. Point action.yml at the new entrypoint and include both in the action bundle artifact. Workflow artifacts drop file modes, so the action marks the script executable at startup. Co-Authored-By: Claude Opus 5.5 --- .github/actions/setup/action.yml | 2 +- .github/workflows/ci.yml | 4 ++-- action.yml | 2 +- rollup.config.mjs | 24 +++++++++++++++++++++--- src/index.ts | 27 +++++++++++++++++++++++++++ 5 files changed, 52 insertions(+), 7 deletions(-) diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml index 85f2239..8af401d 100644 --- a/.github/actions/setup/action.yml +++ b/.github/actions/setup/action.yml @@ -35,7 +35,7 @@ runs: - name: Build if: steps.try-download-artifact.outputs.found_artifact != 'true' shell: bash - run: npm run build # Generates dist/ folder, including the dist/index.js bundle + run: npm run build # Generates dist/ folder, including the dist/action/index.js bundle - name: Upload Build Artifacts if: steps.try-download-artifact.outputs.found_artifact != 'true' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1583b80..7db24b1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,8 +48,8 @@ jobs: name: action-bundle-${{ github.event.pull_request.head.sha || github.sha }} path: | action.yml - dist/index.js - dist/index.js.map + dist/action/ + dist/scripts/ if-no-files-found: error retention-days: 1 diff --git a/action.yml b/action.yml index f70c6cf..5da11b0 100644 --- a/action.yml +++ b/action.yml @@ -43,4 +43,4 @@ outputs: runs: using: "node24" - main: "dist/index.js" + main: "dist/action/index.js" diff --git a/rollup.config.mjs b/rollup.config.mjs index 5a314f6..e4e4b6f 100644 --- a/rollup.config.mjs +++ b/rollup.config.mjs @@ -1,10 +1,27 @@ import commonjs from "@rollup/plugin-commonjs"; import json from "@rollup/plugin-json"; import { nodeResolve } from "@rollup/plugin-node-resolve"; +import fs from "node:fs"; + +// ts-apt runs scripts/dist/apt-fast.sh, which it finds relative to its own +// module (i.e. ../scripts/dist from the bundle). Bundling moves that module +// into dist/action/index.js, so ship the scripts at dist/scripts/dist. +const TS_APT_SCRIPTS_SRC = "node_modules/ts-apt/scripts/dist"; +const TS_APT_SCRIPTS_DEST = "dist/scripts/dist"; + +/** Copies the ts-apt shell scripts next to the bundle after it's written. */ +function copyTsAptScripts() { + return { + name: "copy-ts-apt-scripts", + writeBundle() { + fs.cpSync(TS_APT_SCRIPTS_SRC, TS_APT_SCRIPTS_DEST, { recursive: true }); + }, + }; +} /** - * Bundles the action and all of its dependencies into dist/index.js, the - * entrypoint action.yml runs. GitHub Actions doesn't install node_modules, so + * Bundles the action and all of its dependencies into dist/action/index.js, + * the entrypoint action.yml runs. GitHub Actions doesn't install node_modules, so * the bundle has to be self-contained. * * The input is the tsc output from `npm run build:lib`, so TypeScript is only @@ -15,7 +32,7 @@ import { nodeResolve } from "@rollup/plugin-node-resolve"; export default { input: "dist/src/index.js", output: { - file: "dist/index.js", + file: "dist/action/index.js", format: "es", sourcemap: true, // Some CommonJS dependencies call require() at runtime. @@ -27,6 +44,7 @@ export default { nodeResolve({ preferBuiltins: true, exportConditions: ["node"] }), commonjs(), json(), + copyTsAptScripts(), ], onwarn(warning, warn) { // Dependencies trigger these and they are harmless and very noisy: diff --git a/src/index.ts b/src/index.ts index 2e02257..8a63177 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,35 @@ import * as core from "@actions/core"; +import fs from "node:fs"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; import { runAction, type ActionInputs } from "./action.js"; import { DefaultCommandRunner } from "ts-apt"; import { Cache, CACHE_DEFAULT_DIRNAME } from "./cache.js"; import { Instruments } from "./instrumentation.js"; +/** + * Marks the bundled ts-apt apt-fast script executable when it's present. + * + * ts-apt spawns the script directly, and some ways of shipping the bundle + * (e.g. workflow artifacts) drop file modes. + * + * @param bundleDir Directory of the running bundle (i.e. dist/action). + */ +function ensureBundledScriptsExecutable( + bundleDir: string = path.dirname(fileURLToPath(import.meta.url)), +): void { + const aptFastPath = path.join( + bundleDir, + "..", + "scripts", + "dist", + "apt-fast.sh", + ); + if (fs.existsSync(aptFastPath)) { + fs.chmodSync(aptFastPath, 0o755); + } +} + /** * Parses empty package behavior input from workflow configuration. * @@ -51,6 +77,7 @@ async function main(): Promise { const inputs = getInputs(); const instruments = new Instruments(cacheDir, inputs.debug || core.isDebug()); try { + ensureBundledScriptsExecutable(); const commandRunner = new DefaultCommandRunner( instruments.execLogger, instruments.execLogger,