mirror of
https://github.com/awalsh128/cache-apt-pkgs-action.git
synced 2026-11-13 21:36:56 +00:00
build: remove unused dependencies and address npm audit findings (#239)
* chore: remove unused dist directory * build: remove unused dependencies and address npm audit findings Remove dependencies nothing imports or runs: class-transformer, tar and @types/tar (archives use system tar), internet-message, @devcontainers/cli, @typescript-eslint/eslint-plugin, typedoc and typedoc-plugin-markdown (with the dead docs:api script). Move rollup to devDependencies since it is only used to build the bundle. Update dependencies within their declared ranges and add scoped overrides: glob 9.0.0 - 14.0.1 to ^14.0.4, and minimatch ^11.0.5 for eslint, @typescript-eslint/parser and type-coverage only. minimatch is not overridden for @actions/glob because minimatch 11 removed matchOne, which @actions/glob calls (breaking cache hashFiles). npm audit goes from 66 (2 critical, 10 high) to 39 (0 critical, 0 high). Remaining: minimatch inside @actions/glob (production), npm's bundled dependencies under @semantic-release/npm, and deepmerge (no fix). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
06c1af1b1c
commit
728251154e
53
dist/action.d.ts
vendored
53
dist/action.d.ts
vendored
|
|
@ -1,53 +0,0 @@
|
|||
import { type PackageManager, type CommandRunner } from "../../ts-apt/dist/index.js";
|
||||
import winston from "winston";
|
||||
type TarModule = typeof import("tar");
|
||||
type EmptyPackageBehavior = "error" | "warn" | "ignore";
|
||||
interface PackageName {
|
||||
readonly name: string;
|
||||
readonly version?: string;
|
||||
readonly distro?: string;
|
||||
serialize(): string;
|
||||
}
|
||||
export interface ActionInputs {
|
||||
readonly packages: string;
|
||||
readonly version: string;
|
||||
readonly executeInstallScripts: boolean;
|
||||
readonly emptyPackagesBehavior: EmptyPackageBehavior;
|
||||
readonly debug: boolean;
|
||||
}
|
||||
export interface ActionOutputs {
|
||||
readonly cacheHit: boolean;
|
||||
readonly packageVersionList: string;
|
||||
readonly allPackageVersionList: string;
|
||||
}
|
||||
export declare class ActionPackageName implements PackageName {
|
||||
readonly name: string;
|
||||
readonly version?: string | undefined;
|
||||
constructor(name: string, version?: string | undefined);
|
||||
serialize(): string;
|
||||
}
|
||||
export declare function parseBoolean(value: string, fieldName: string): boolean;
|
||||
export declare function normalizeInputPackages(inputPackages: string): string[];
|
||||
export declare class ActionRunner {
|
||||
private readonly commandRunner;
|
||||
private readonly tar;
|
||||
private readonly logger;
|
||||
constructor(commandRunner: CommandRunner, tarModule: TarModule, logger: winston.Logger);
|
||||
parseBoolean(value: string, fieldName: string): boolean;
|
||||
normalizeInputPackages(inputPackages: string): string[];
|
||||
resolvePackageVersion(packageManager: PackageManager, packageName: string): Promise<string>;
|
||||
normalizePackagesWithVersions(packageManager: PackageManager, inputPackages: string): Promise<string[]>;
|
||||
validateEmptyPackages(behavior: EmptyPackageBehavior, packages: string[]): void;
|
||||
getCacheRoot(): string;
|
||||
getCacheKey(normalizedPackages: string[], version: string): Promise<string>;
|
||||
findInstallScript(packageName: string, extension: "preinst" | "postinst", root: string): string | undefined;
|
||||
tarRelativePath(filePath: string): string;
|
||||
buildFileListForPackage(packageManager: PackageManager, packageName: string): Promise<string[]>;
|
||||
updateAptLists(packageManager: PackageManager): Promise<void>;
|
||||
packageSpecifierToName(packageSpecifier: string): string;
|
||||
installAndCachePackages(cacheDir: string, packages: string[], packageManager: PackageManager): Promise<void>;
|
||||
restorePackages(cacheDir: string, executeInstallScripts: boolean): Promise<void>;
|
||||
runAction(inputs: ActionInputs): Promise<ActionOutputs>;
|
||||
}
|
||||
export declare function runAction(inputs: ActionInputs, logger: winston.Logger): Promise<ActionOutputs>;
|
||||
export {};
|
||||
265
dist/action.js
vendored
265
dist/action.js
vendored
|
|
@ -1,265 +0,0 @@
|
|||
import * as cache from "@actions/cache";
|
||||
import crypto from "node:crypto";
|
||||
import fs from "node:fs";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { createPackageManager, DefaultCommandRunner, } from "../../ts-apt/dist/index.js";
|
||||
import { isAptListsFresh } from "./io.js";
|
||||
import { readManifestAsCsv, writeManifest } from "./manifest.js";
|
||||
import * as tar from "tar";
|
||||
const FORCE_UPDATE_INCREMENT = "3";
|
||||
const CACHE_DIRNAME = "cache-apt-pkgs";
|
||||
const CACHE_PREFIX = "cache-apt-pkgs_";
|
||||
export class ActionPackageName {
|
||||
name;
|
||||
version;
|
||||
constructor(name, version) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
}
|
||||
serialize() {
|
||||
return this.version ? `${this.name}=${this.version}` : this.name;
|
||||
}
|
||||
}
|
||||
function toPackageName(packageSpecifier) {
|
||||
const [name, version] = packageSpecifier.split("=");
|
||||
if (!name) {
|
||||
throw new Error("Package name cannot be empty.");
|
||||
}
|
||||
return new ActionPackageName(name, version);
|
||||
}
|
||||
export function parseBoolean(value, fieldName) {
|
||||
if (value === "true") {
|
||||
return true;
|
||||
}
|
||||
if (value === "false") {
|
||||
return false;
|
||||
}
|
||||
throw new Error(`${fieldName} value '${value}' must be either true or false.`);
|
||||
}
|
||||
export function normalizeInputPackages(inputPackages) {
|
||||
return inputPackages
|
||||
.replace(/[,\\]/g, " ")
|
||||
.replace(/\s+/g, " ")
|
||||
.trim()
|
||||
.split(" ")
|
||||
.map((part) => part.trim())
|
||||
.filter(Boolean)
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
}
|
||||
export class ActionRunner {
|
||||
commandRunner;
|
||||
tar;
|
||||
logger;
|
||||
constructor(commandRunner, tarModule, logger) {
|
||||
this.commandRunner = commandRunner;
|
||||
this.tar = tarModule;
|
||||
this.logger = logger;
|
||||
}
|
||||
parseBoolean(value, fieldName) {
|
||||
return parseBoolean(value, fieldName);
|
||||
}
|
||||
normalizeInputPackages(inputPackages) {
|
||||
return normalizeInputPackages(inputPackages);
|
||||
}
|
||||
async resolvePackageVersion(packageManager, packageName) {
|
||||
const packageInfo = await packageManager.getPackageInfo([
|
||||
toPackageName(packageName),
|
||||
]);
|
||||
const version = packageInfo[0]?.version;
|
||||
if (!version) {
|
||||
throw new Error(`Unable to resolve package version for '${packageName}'.`);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
async normalizePackagesWithVersions(packageManager, inputPackages) {
|
||||
const raw = this.normalizeInputPackages(inputPackages);
|
||||
const packages = await Promise.all(raw.map(async (pkg) => {
|
||||
if (pkg.includes("=")) {
|
||||
return pkg;
|
||||
}
|
||||
return `${pkg}=${await this.resolvePackageVersion(packageManager, pkg)}`;
|
||||
}));
|
||||
return packages.sort((a, b) => a.localeCompare(b));
|
||||
}
|
||||
validateEmptyPackages(behavior, packages) {
|
||||
if (packages.length > 0) {
|
||||
return;
|
||||
}
|
||||
if (behavior === "ignore") {
|
||||
return;
|
||||
}
|
||||
if (behavior === "warn") {
|
||||
process.stdout.write("::warning::Packages argument is empty.\n");
|
||||
return;
|
||||
}
|
||||
throw new Error("Packages argument is empty.");
|
||||
}
|
||||
getCacheRoot() {
|
||||
return path.join(os.homedir(), CACHE_DIRNAME);
|
||||
}
|
||||
async getCacheKey(normalizedPackages, version) {
|
||||
const architecture = (await this.commandRunner.run("arch")).stdout.trim();
|
||||
let value = `${normalizedPackages.join(" ")} @ ${version} ${FORCE_UPDATE_INCREMENT}`;
|
||||
if (architecture !== "x86_64") {
|
||||
value = `${value} ${architecture}`;
|
||||
}
|
||||
const hash = crypto.createHash("md5").update(value).digest("hex");
|
||||
return `${CACHE_PREFIX}${hash}`;
|
||||
}
|
||||
findInstallScript(packageName, extension, root) {
|
||||
const scriptsDir = path.join(root, "var", "lib", "dpkg", "info");
|
||||
if (!fs.existsSync(scriptsDir)) {
|
||||
return undefined;
|
||||
}
|
||||
const pattern = new RegExp(`^${packageName}(:.*)?\\.${extension}$`);
|
||||
const matches = fs
|
||||
.readdirSync(scriptsDir)
|
||||
.filter((entry) => pattern.test(entry))
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
const candidate = matches[0];
|
||||
if (!candidate) {
|
||||
return undefined;
|
||||
}
|
||||
return path.join(scriptsDir, candidate);
|
||||
}
|
||||
tarRelativePath(filePath) {
|
||||
return filePath.startsWith("/") ? filePath.slice(1) : filePath;
|
||||
}
|
||||
async buildFileListForPackage(packageManager, packageName) {
|
||||
const files = (await packageManager.listInstalledFiles(toPackageName(packageName)))
|
||||
.filter((filePath) => {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return false;
|
||||
}
|
||||
const stat = fs.lstatSync(filePath);
|
||||
return stat.isFile() || stat.isSymbolicLink();
|
||||
})
|
||||
.map(this.tarRelativePath);
|
||||
const preinst = this.findInstallScript(packageName, "preinst", "/");
|
||||
const postinst = this.findInstallScript(packageName, "postinst", "/");
|
||||
if (preinst) {
|
||||
files.push(this.tarRelativePath(preinst));
|
||||
}
|
||||
if (postinst) {
|
||||
files.push(this.tarRelativePath(postinst));
|
||||
}
|
||||
return Array.from(new Set(files)).sort((a, b) => a.localeCompare(b));
|
||||
}
|
||||
async updateAptLists(packageManager) {
|
||||
if (isAptListsFresh()) {
|
||||
return;
|
||||
}
|
||||
await packageManager.update();
|
||||
}
|
||||
packageSpecifierToName(packageSpecifier) {
|
||||
return packageSpecifier.split("=")[0] ?? packageSpecifier;
|
||||
}
|
||||
async installAndCachePackages(cacheDir, packages, packageManager) {
|
||||
await this.updateAptLists(packageManager);
|
||||
writeManifest(path.join(cacheDir, "manifest_main.log"), packages);
|
||||
const installedPackages = await packageManager.install(packages.map(toPackageName));
|
||||
const manifestAll = [];
|
||||
for (const pkg of installedPackages) {
|
||||
const packageName = pkg.name;
|
||||
const packageVersion = pkg.version;
|
||||
if (!packageName || !packageVersion) {
|
||||
continue;
|
||||
}
|
||||
const archivePath = path.join(cacheDir, `${packageName}=${packageVersion}.tar`);
|
||||
if (!fs.existsSync(archivePath)) {
|
||||
const filesToArchive = await this.buildFileListForPackage(packageManager, packageName);
|
||||
await this.tar.create({
|
||||
cwd: "/",
|
||||
file: archivePath,
|
||||
portable: false,
|
||||
preservePaths: false,
|
||||
follow: false,
|
||||
noDirRecurse: false,
|
||||
}, filesToArchive);
|
||||
}
|
||||
manifestAll.push(`${packageName}=${packageVersion}`);
|
||||
}
|
||||
writeManifest(path.join(cacheDir, "manifest_all.log"), manifestAll);
|
||||
}
|
||||
async restorePackages(cacheDir, executeInstallScripts) {
|
||||
const archives = fs
|
||||
.readdirSync(cacheDir)
|
||||
.filter((entry) => entry.endsWith(".tar"))
|
||||
.sort((a, b) => a.localeCompare(b));
|
||||
for (const archive of archives) {
|
||||
const archivePath = path.join(cacheDir, archive);
|
||||
await this.tar.extract({
|
||||
cwd: "/",
|
||||
file: archivePath,
|
||||
preservePaths: true,
|
||||
});
|
||||
if (!executeInstallScripts) {
|
||||
continue;
|
||||
}
|
||||
const packageName = archive.split("=")[0] ?? "";
|
||||
if (!packageName) {
|
||||
continue;
|
||||
}
|
||||
const preinst = this.findInstallScript(packageName, "preinst", "/");
|
||||
if (preinst) {
|
||||
this.logger.info(`Running pre-install script for ${packageName}`);
|
||||
await this.commandRunner.run("sudo", ["sh", "-x", preinst, "install"]);
|
||||
}
|
||||
const postinst = this.findInstallScript(packageName, "postinst", "/");
|
||||
if (postinst) {
|
||||
this.logger.info(`Running post-install script for ${packageName}`);
|
||||
await this.commandRunner.run("sudo", [
|
||||
"sh",
|
||||
"-x",
|
||||
postinst,
|
||||
"configure",
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
async runAction(inputs) {
|
||||
if (/\s/.test(inputs.version)) {
|
||||
throw new Error(`Version value '${inputs.version}' cannot contain spaces.`);
|
||||
}
|
||||
const packageInfoManager = await createPackageManager(false);
|
||||
const normalizedPackages = await this.normalizePackagesWithVersions(packageInfoManager, inputs.packages);
|
||||
this.validateEmptyPackages(inputs.emptyPackagesBehavior, normalizedPackages);
|
||||
const cacheDir = this.getCacheRoot();
|
||||
fs.mkdirSync(cacheDir, { recursive: true });
|
||||
if (normalizedPackages.length === 0) {
|
||||
writeManifest(path.join(cacheDir, "manifest_main.log"), []);
|
||||
writeManifest(path.join(cacheDir, "manifest_all.log"), []);
|
||||
return {
|
||||
cacheHit: false,
|
||||
packageVersionList: "",
|
||||
allPackageVersionList: "",
|
||||
};
|
||||
}
|
||||
const key = await this.getCacheKey(normalizedPackages, inputs.version);
|
||||
fs.writeFileSync(path.join(cacheDir, "cache_key.md5"), key.replace(CACHE_PREFIX, ""), "utf8");
|
||||
const restoredKey = await cache.restoreCache([cacheDir], key);
|
||||
const cacheHit = restoredKey === key;
|
||||
if (cacheHit) {
|
||||
await this.restorePackages(cacheDir, inputs.executeInstallScripts);
|
||||
}
|
||||
else {
|
||||
const installManager = await createPackageManager(true);
|
||||
const installTargets = normalizedPackages.map((packageSpecifier) => this.packageSpecifierToName(packageSpecifier));
|
||||
await this.installAndCachePackages(cacheDir, installTargets, installManager);
|
||||
await cache.saveCache([cacheDir], key);
|
||||
}
|
||||
return {
|
||||
cacheHit,
|
||||
packageVersionList: readManifestAsCsv(path.join(cacheDir, "manifest_main.log")),
|
||||
allPackageVersionList: readManifestAsCsv(path.join(cacheDir, "manifest_all.log")),
|
||||
};
|
||||
}
|
||||
}
|
||||
export async function runAction(inputs, logger) {
|
||||
const packageManager = (await createPackageManager(true, logger, logger));
|
||||
const commandRunner = new DefaultCommandRunner(logger, logger);
|
||||
const actionRunner = new ActionRunner(commandRunner, tar, logger);
|
||||
return await actionRunner.runAction(inputs);
|
||||
}
|
||||
//# sourceMappingURL=action.js.map
|
||||
1
dist/action.js.map
vendored
1
dist/action.js.map
vendored
File diff suppressed because one or more lines are too long
1
dist/index.d.ts
vendored
1
dist/index.d.ts
vendored
|
|
@ -1 +0,0 @@
|
|||
export {};
|
||||
41
dist/index.js
vendored
41
dist/index.js
vendored
|
|
@ -1,41 +0,0 @@
|
|||
import * as core from "@actions/core";
|
||||
import { parseBoolean, runAction } from "./action.js";
|
||||
import winston from "winston";
|
||||
function parseEmptyPackagesBehavior(value) {
|
||||
if (value === "error" || value === "warn" || value === "ignore") {
|
||||
return value;
|
||||
}
|
||||
throw new Error(`empty_packages_behavior value '${value}' must be one of: error, warn, ignore.`);
|
||||
}
|
||||
function getInputs() {
|
||||
const executeInstallScriptsRaw = core.getInput("execute_install_scripts");
|
||||
const debugRaw = core.getInput("debug");
|
||||
const emptyPackagesBehaviorRaw = core.getInput("empty_packages_behavior") || "error";
|
||||
return {
|
||||
packages: core.getInput("packages", { required: true }),
|
||||
version: core.getInput("version"),
|
||||
executeInstallScripts: parseBoolean(executeInstallScriptsRaw, "execute_install_scripts"),
|
||||
emptyPackagesBehavior: parseEmptyPackagesBehavior(emptyPackagesBehaviorRaw),
|
||||
debug: parseBoolean(debugRaw, "debug"),
|
||||
};
|
||||
}
|
||||
async function main() {
|
||||
try {
|
||||
const inputs = getInputs();
|
||||
const logger = winston.createLogger({
|
||||
level: inputs.debug ? "debug" : "info",
|
||||
format: winston.format.combine(winston.format.colorize(), winston.format.printf(({ level, message }) => `${level}: ${message}`)),
|
||||
transports: [new winston.transports.Console()],
|
||||
});
|
||||
const outputs = await runAction(inputs, logger);
|
||||
core.setOutput("cache-hit", String(outputs.cacheHit));
|
||||
core.setOutput("package-version-list", outputs.packageVersionList);
|
||||
core.setOutput("all-package-version-list", outputs.allPackageVersionList);
|
||||
}
|
||||
catch (error) {
|
||||
const message = error instanceof Error ? error.message : String(error);
|
||||
core.setFailed(message);
|
||||
}
|
||||
}
|
||||
void main();
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
dist/index.js.map
vendored
1
dist/index.js.map
vendored
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,eAAe,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAqB,MAAM,aAAa,CAAC;AACzE,OAAO,OAAO,MAAM,SAAS,CAAC;AAE9B,SAAS,0BAA0B,CACjC,KAAa;IAEb,IAAI,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChE,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,KAAK,CACb,kCAAkC,KAAK,wCAAwC,CAChF,CAAC;AACJ,CAAC;AAED,SAAS,SAAS;IAChB,MAAM,wBAAwB,GAAG,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;IAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IACxC,MAAM,wBAAwB,GAC5B,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC,IAAI,OAAO,CAAC;IAEtD,OAAO;QACL,QAAQ,EAAE,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;QACvD,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;QACjC,qBAAqB,EAAE,YAAY,CACjC,wBAAwB,EACxB,yBAAyB,CAC1B;QACD,qBAAqB,EAAE,0BAA0B,CAAC,wBAAwB,CAAC;QAC3E,KAAK,EAAE,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC;KACvC,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;YAClC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM;YACtC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,OAAO,CAC5B,OAAO,CAAC,MAAM,CAAC,QAAQ,EAAE,EACzB,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,GAAG,KAAK,KAAK,OAAO,EAAE,CAAC,CACtE;YACD,UAAU,EAAE,CAAC,IAAI,OAAO,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;SAC/C,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QAEhD,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QACtD,IAAI,CAAC,SAAS,CAAC,sBAAsB,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;QACnE,IAAI,CAAC,SAAS,CAAC,0BAA0B,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC5E,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC1B,CAAC;AACH,CAAC;AAED,KAAK,IAAI,EAAE,CAAC"}
|
||||
23
dist/io.d.ts
vendored
23
dist/io.d.ts
vendored
|
|
@ -1,23 +0,0 @@
|
|||
import { type CommandRunner } from "../../ts-apt/dist/index.js";
|
||||
export declare function isAptListsFresh(): boolean;
|
||||
export declare class Package {
|
||||
readonly name: string;
|
||||
readonly version: string;
|
||||
constructor(name: string, version: string);
|
||||
serialize(): string;
|
||||
}
|
||||
export declare class CacheKey {
|
||||
readonly version: string;
|
||||
readonly forceUpdateIncrement: string;
|
||||
readonly arch: string;
|
||||
readonly normalizedPackages: string[];
|
||||
constructor(version: string, forceUpdateIncrement: string, arch: string, normalizedPackages: string[]);
|
||||
serialize(): string;
|
||||
}
|
||||
export declare function deserializeCacheKey(serialized: string): CacheKey;
|
||||
export declare class Cache {
|
||||
private readonly cachePath;
|
||||
private readonly commandRunner;
|
||||
constructor(cacheDir: string | undefined, commandRunner: CommandRunner);
|
||||
getKey(normalizedPackages: string[], version: string): Promise<string>;
|
||||
}
|
||||
88
dist/io.js
vendored
88
dist/io.js
vendored
|
|
@ -1,88 +0,0 @@
|
|||
import * as fs from "fs";
|
||||
import * as path from "path";
|
||||
import * as crypto from "crypto";
|
||||
import * as os from "os";
|
||||
export function isAptListsFresh() {
|
||||
const aptListsPath = "/var/lib/apt/lists";
|
||||
const maxDepth = 5;
|
||||
function search(currentPath, currentDepth) {
|
||||
if (currentDepth > maxDepth)
|
||||
return false;
|
||||
try {
|
||||
const stats = fs.statSync(currentPath);
|
||||
if (stats.isDirectory()) {
|
||||
const entries = fs.readdirSync(currentPath);
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(currentPath, entry);
|
||||
if (search(fullPath, currentDepth + 1)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
// Ignore permission errors or inaccessible paths
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return search(aptListsPath, 0);
|
||||
}
|
||||
export class Package {
|
||||
name;
|
||||
version;
|
||||
constructor(name, version) {
|
||||
this.name = name;
|
||||
this.version = version;
|
||||
}
|
||||
serialize() {
|
||||
return `${this.name}@${this.version}`;
|
||||
}
|
||||
}
|
||||
const FORCE_UPDATE_INCREMENT = "4";
|
||||
const CACHE_DIRNAME = "cache-apt-pkgs";
|
||||
const CACHE_PREFIX = "cache-apt-pkgs_";
|
||||
export class CacheKey {
|
||||
version;
|
||||
forceUpdateIncrement;
|
||||
arch;
|
||||
normalizedPackages;
|
||||
constructor(version, forceUpdateIncrement, arch, normalizedPackages) {
|
||||
this.version = version;
|
||||
this.forceUpdateIncrement = forceUpdateIncrement;
|
||||
this.arch = arch;
|
||||
this.normalizedPackages = normalizedPackages;
|
||||
}
|
||||
serialize() {
|
||||
return `${this.version}|${this.forceUpdateIncrement}|${this.arch}|${this.normalizedPackages.join(",")}`;
|
||||
}
|
||||
}
|
||||
export function deserializeCacheKey(serialized) {
|
||||
const parts = serialized.split("|");
|
||||
if (parts.length !== 4) {
|
||||
throw new Error(`Invalid serialized cache key: ${serialized}`);
|
||||
}
|
||||
const [version, forceUpdateIncrement, arch, normalizedPackagesStr] = parts;
|
||||
const normalizedPackages = normalizedPackagesStr.split(",");
|
||||
return new CacheKey(version, forceUpdateIncrement, arch, normalizedPackages);
|
||||
}
|
||||
export class Cache {
|
||||
cachePath;
|
||||
commandRunner;
|
||||
constructor(cacheDir = CACHE_DIRNAME, commandRunner) {
|
||||
this.cachePath = path.join(os.homedir(), cacheDir);
|
||||
this.commandRunner = commandRunner;
|
||||
}
|
||||
async getKey(normalizedPackages, version) {
|
||||
const architecture = await (await this.commandRunner.run("arch")).stdout.trim();
|
||||
let value = `${normalizedPackages.join(" ")} @ ${version} ${FORCE_UPDATE_INCREMENT}`;
|
||||
if (architecture !== "x86_64") {
|
||||
value = `${value} ${architecture}`;
|
||||
}
|
||||
const hash = crypto.createHash("md5").update(value).digest("hex");
|
||||
return `${CACHE_PREFIX}${hash}`;
|
||||
}
|
||||
}
|
||||
//# sourceMappingURL=io.js.map
|
||||
1
dist/io.js.map
vendored
1
dist/io.js.map
vendored
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"io.js","sourceRoot":"","sources":["../src/io.ts"],"names":[],"mappings":"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"}
|
||||
2
dist/manifest.d.ts
vendored
2
dist/manifest.d.ts
vendored
|
|
@ -1,2 +0,0 @@
|
|||
export declare function writeManifest(filePath: string, entries: string[]): void;
|
||||
export declare function readManifestAsCsv(filePath: string): string;
|
||||
17
dist/manifest.js
vendored
17
dist/manifest.js
vendored
|
|
@ -1,17 +0,0 @@
|
|||
import fs from "node:fs";
|
||||
export function writeManifest(filePath, entries) {
|
||||
const normalized = [...entries].filter(Boolean).sort((a, b) => a.localeCompare(b));
|
||||
fs.writeFileSync(filePath, normalized.join("\n"), "utf8");
|
||||
}
|
||||
export function readManifestAsCsv(filePath) {
|
||||
if (!fs.existsSync(filePath)) {
|
||||
return "";
|
||||
}
|
||||
return fs
|
||||
.readFileSync(filePath, "utf8")
|
||||
.split(/\r?\n/)
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean)
|
||||
.join(",");
|
||||
}
|
||||
//# sourceMappingURL=manifest.js.map
|
||||
1
dist/manifest.js.map
vendored
1
dist/manifest.js.map
vendored
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../src/manifest.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AAEzB,MAAM,UAAU,aAAa,CAAC,QAAgB,EAAE,OAAiB;IAC/D,MAAM,UAAU,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;AAC5D,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC7B,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,OAAO,EAAE;SACN,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC;SAC9B,KAAK,CAAC,OAAO,CAAC;SACd,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC"}
|
||||
9
dist/shell.d.ts
vendored
9
dist/shell.d.ts
vendored
|
|
@ -1,9 +0,0 @@
|
|||
import { type SpawnSyncOptions } from "node:child_process";
|
||||
export interface CommandResult {
|
||||
readonly status: number;
|
||||
readonly stdout: string;
|
||||
readonly stderr: string;
|
||||
}
|
||||
export declare function runCommand(command: string, args?: string[], options?: SpawnSyncOptions): CommandResult;
|
||||
export declare function runCommandOrThrow(command: string, args?: string[], options?: SpawnSyncOptions): CommandResult;
|
||||
export declare function fileIsFresh(path: string, withinMinutes: number): boolean;
|
||||
46
dist/shell.js
vendored
46
dist/shell.js
vendored
|
|
@ -1,46 +0,0 @@
|
|||
import { spawnSync } from "node:child_process";
|
||||
import fs from "node:fs";
|
||||
export function runCommand(command, args = [], options = {}) {
|
||||
const result = spawnSync(command, args, {
|
||||
encoding: "utf8",
|
||||
...options,
|
||||
});
|
||||
const stdout = typeof result.stdout === "string"
|
||||
? result.stdout
|
||||
: result.stdout
|
||||
? result.stdout.toString("utf8")
|
||||
: "";
|
||||
const stderr = typeof result.stderr === "string"
|
||||
? result.stderr
|
||||
: result.stderr
|
||||
? result.stderr.toString("utf8")
|
||||
: "";
|
||||
return {
|
||||
status: result.status ?? 1,
|
||||
stdout,
|
||||
stderr,
|
||||
};
|
||||
}
|
||||
export function runCommandOrThrow(command, args = [], options = {}) {
|
||||
const result = runCommand(command, args, options);
|
||||
if (result.status !== 0) {
|
||||
throw new Error([
|
||||
`Command failed: ${command} ${args.join(" ")}`,
|
||||
`exit: ${result.status}`,
|
||||
result.stdout ? `stdout:\n${result.stdout.trim()}` : "",
|
||||
result.stderr ? `stderr:\n${result.stderr.trim()}` : "",
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join("\n"));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
export function fileIsFresh(path, withinMinutes) {
|
||||
if (!fs.existsSync(path)) {
|
||||
return false;
|
||||
}
|
||||
const stat = fs.statSync(path);
|
||||
const maxAgeMs = withinMinutes * 60 * 1000;
|
||||
return Date.now() - stat.mtimeMs <= maxAgeMs;
|
||||
}
|
||||
//# sourceMappingURL=shell.js.map
|
||||
1
dist/shell.js.map
vendored
1
dist/shell.js.map
vendored
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"shell.js","sourceRoot":"","sources":["../src/shell.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAyB,MAAM,oBAAoB,CAAC;AACtE,OAAO,EAAE,MAAM,SAAS,CAAC;AAQzB,MAAM,UAAU,UAAU,CACxB,OAAe,EACf,OAAiB,EAAE,EACnB,UAA4B,EAAE;IAE9B,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE;QACtC,QAAQ,EAAE,MAAM;QAChB,GAAG,OAAO;KACX,CAAC,CAAC;IAEH,MAAM,MAAM,GACV,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ;QAC/B,CAAC,CAAC,MAAM,CAAC,MAAM;QACf,CAAC,CAAC,MAAM,CAAC,MAAM;YACb,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YAChC,CAAC,CAAC,EAAE,CAAC;IACX,MAAM,MAAM,GACV,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ;QAC/B,CAAC,CAAC,MAAM,CAAC,MAAM;QACf,CAAC,CAAC,MAAM,CAAC,MAAM;YACb,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC;YAChC,CAAC,CAAC,EAAE,CAAC;IAEX,OAAO;QACL,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,CAAC;QAC1B,MAAM;QACN,MAAM;KACP,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,OAAe,EACf,OAAiB,EAAE,EACnB,UAA4B,EAAE;IAE9B,MAAM,MAAM,GAAG,UAAU,CAAC,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;IAClD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb;YACE,mBAAmB,OAAO,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;YAC9C,SAAS,MAAM,CAAC,MAAM,EAAE;YACxB,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE;YACvD,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE;SACxD;aACE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,IAAI,CAAC,CACd,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,aAAqB;IAC7D,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,IAAI,GAAG,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/B,MAAM,QAAQ,GAAG,aAAa,GAAG,EAAE,GAAG,IAAI,CAAC;IAC3C,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,IAAI,QAAQ,CAAC;AAC/C,CAAC"}
|
||||
3441
package-lock.json
generated
3441
package-lock.json
generated
File diff suppressed because it is too large
Load diff
23
package.json
23
package.json
|
|
@ -72,7 +72,6 @@
|
|||
"repo:tags:upload": "npm run repo::sync -- upload --target tags",
|
||||
"repo:all:download": "npm run repo::sync -- download --target all",
|
||||
"repo:all:upload": "npm run repo::sync -- upload --target all",
|
||||
"docs:api": "typedoc --options typedoc.json",
|
||||
"release": "semantic-release",
|
||||
"release:dry-run": "semantic-release --dry-run",
|
||||
"lint": "eslint src test scripts --ext .ts,.mts",
|
||||
|
|
@ -85,14 +84,10 @@
|
|||
"@actions/artifact": "^6.2.1",
|
||||
"@actions/cache": "^6.1.0",
|
||||
"@actions/core": "^3.0.1",
|
||||
"class-transformer": "^0.5.1",
|
||||
"rollup": "^4.62.2",
|
||||
"tar": "^7.4.3",
|
||||
"ts-apt": "git+https://github.com/awalsh128/ts-apt.git#342c7d0f453dcf1a69da83d7d195f9df2611a351",
|
||||
"winston": "^3.19.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@devcontainers/cli": "^0.87.0",
|
||||
"@robingenz/zli": "^0.2.0",
|
||||
"@rollup/plugin-commonjs": "^29.0.3",
|
||||
"@rollup/plugin-json": "^6.1.0",
|
||||
|
|
@ -104,19 +99,27 @@
|
|||
"@semantic-release/npm": "^13.1.5",
|
||||
"@semantic-release/release-notes-generator": "^14.1.1",
|
||||
"@types/node": "^24.1.0",
|
||||
"@types/tar": "^6.1.13",
|
||||
"@typescript-eslint/eslint-plugin": "^8.62.1",
|
||||
"@typescript-eslint/parser": "^8.62.1",
|
||||
"@vitest/coverage-v8": "^4.1.9",
|
||||
"eslint": "^10.6.0",
|
||||
"internet-message": "^1.0.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rollup": "^4.68.0",
|
||||
"semantic-release": "^25.0.5",
|
||||
"type-coverage": "^2.29.7",
|
||||
"typedoc": "^0.28.19",
|
||||
"typedoc-plugin-markdown": "^4.12.0",
|
||||
"typescript": "^6.0.3",
|
||||
"vitest": "^4.1.10",
|
||||
"zod": "^4.4.3"
|
||||
},
|
||||
"overrides": {
|
||||
"glob@>=9.0.0 <14.0.2": "^14.0.4",
|
||||
"eslint": {
|
||||
"minimatch": "^11.0.5"
|
||||
},
|
||||
"@typescript-eslint/parser": {
|
||||
"minimatch": "^11.0.5"
|
||||
},
|
||||
"type-coverage": {
|
||||
"minimatch": "^11.0.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue