cache-apt-pkgs-action/test/action-runner.test.ts
awalsh128 2e80d3bfa8 perf: speed up cache restores
- Upload the diagnostic artifact only when debug is on or the action
  fails. The upload took ~1.4s of a ~3.7s restore in CI.
- Extract all package archives in one sudo shell when install scripts
  are off, instead of a sudo and tar process per package. Per-package
  extraction stays when scripts run, to keep install ordering (#196).
- Skip the apt-fast availability probe on a cache hit, where nothing is
  installed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 15:17:32 -08:00

116 lines
3.8 KiB
TypeScript

import { afterEach, describe, expect, it, vi } from "vitest";
import winston from "winston";
import { Manifest, ManifestEntry } from "../src/manifest.js";
import { CacheKey } from "../src/cache.js";
import { ActionPackageNames } from "../src/packages.js";
import { createPackageManager, createPackageName } from "ts-apt";
import { ActionRunner } from "../src/action.js";
vi.mock("ts-apt", async (importOriginal) => {
const actual = await importOriginal<typeof import("ts-apt")>();
return {
...actual,
createPackageManager: vi.fn(),
};
});
const NATIVE_ARCH = "amd64";
describe("ActionRunner", () => {
afterEach(() => {
vi.restoreAllMocks();
vi.mocked(createPackageManager).mockReset();
});
function createRunner() {
const cache = {
loadAndRestore: vi.fn(),
archiveAndSave: vi.fn(),
};
const commandRunner = {
run: vi.fn(),
};
const logger = winston.createLogger({ silent: true });
return {
runner: new ActionRunner(cache as never, commandRunner as never, logger),
cache,
commandRunner,
};
}
it("returns cache-hit outputs when manifest is restored", async () => {
const { runner, cache } = createRunner();
const packageNames = ActionPackageNames.fromInput("curl git");
const cacheKey = new CacheKey("v1", "0", process.arch, packageNames);
const restored = new Manifest(new Date(), [], cacheKey);
cache.loadAndRestore.mockResolvedValue(restored);
vi.mocked(createPackageManager).mockResolvedValue({
getNativeArchitecture: vi.fn().mockResolvedValue(NATIVE_ARCH),
} as never);
const result = await runner.runAction({
packages: "curl git",
version: "v1",
executeInstallScripts: false,
emptyPackagesBehavior: "error",
debug: false,
});
expect(result.cacheHit).toBe(true);
expect(cache.archiveAndSave).not.toHaveBeenCalled();
});
it("runAction cache hit creates package manager without apt-fast", async () => {
const { runner, cache } = createRunner();
const packageNames = ActionPackageNames.fromInput("curl");
const cacheKey = new CacheKey("v1", "0", process.arch, packageNames);
cache.loadAndRestore.mockResolvedValue(
new Manifest(new Date(), [], cacheKey),
);
vi.mocked(createPackageManager).mockResolvedValue({
getNativeArchitecture: vi.fn().mockResolvedValue(NATIVE_ARCH),
} as never);
await runner.runAction({
packages: "curl",
version: "v1",
executeInstallScripts: false,
emptyPackagesBehavior: "error",
debug: false,
});
expect(vi.mocked(createPackageManager).mock.calls[0]?.[0]).toBe(false);
});
it("runAction cache miss archives installed packages with their files", async () => {
// Unlikely to have dpkg install scripts on the test host.
const installedPackage = createPackageName("test-pkg-not-real", "1.0.0");
// buildFileList keeps only files that exist, so use this test file.
const installedFile = import.meta.filename;
const { runner, cache } = createRunner();
cache.loadAndRestore.mockResolvedValue(undefined);
vi.mocked(createPackageManager).mockResolvedValue({
install: vi.fn().mockResolvedValue([{ name: installedPackage }]),
listInstalledFiles: vi.fn().mockResolvedValue([installedFile]),
getNativeArchitecture: vi.fn().mockResolvedValue(NATIVE_ARCH),
} as never);
await runner.runAction({
packages: installedPackage.serialize(),
version: "v1",
executeInstallScripts: false,
emptyPackagesBehavior: "error",
debug: false,
});
expect(cache.archiveAndSave).toHaveBeenCalledTimes(1);
const [manifest] = cache.archiveAndSave.mock.calls[0]!;
expect(manifest.entries).toEqual([
new ManifestEntry(installedPackage, [installedFile.slice(1)]),
]);
});
});