Skip to content

Commit ffa1b05

Browse files
committed
Only try zstd for specified version ranges of tar
1 parent cf64c3e commit ffa1b05

File tree

6 files changed

+201
-48
lines changed

6 files changed

+201
-48
lines changed

lib/setup-codeql.js

Lines changed: 2 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/setup-codeql.js.map

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/tar.js

Lines changed: 102 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/tar.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/setup-codeql.ts

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import * as api from "./api-client";
1717
import * as defaults from "./defaults.json";
1818
import { CodeQLDefaultVersionInfo } from "./feature-flags";
1919
import { Logger } from "./logging";
20+
import * as tar from "./tar";
2021
import * as util from "./util";
2122
import { isGoodVersion } from "./util";
2223

@@ -461,10 +462,8 @@ export async function tryGetFallbackToolcacheVersion(
461462
return fallbackVersion;
462463
}
463464

464-
type CompressionMethod = "gzip" | "zstd";
465-
466465
export interface ToolsDownloadStatusReport {
467-
compressionMethod: CompressionMethod;
466+
compressionMethod: tar.CompressionMethod;
468467
downloadDurationMs: number;
469468
extractionDurationMs: number;
470469
}
@@ -529,9 +528,8 @@ export const downloadCodeQL = async function (
529528

530529
logger.debug("Extracting CodeQL bundle.");
531530
const extractionStart = performance.now();
532-
const { extractedBundlePath, compressionMethod } = await extractBundle(
533-
archivedBundlePath,
534-
);
531+
const { compressionMethod, outputPath: extractedBundlePath } =
532+
await tar.extract(archivedBundlePath);
535533
const extractionDurationMs = Math.round(performance.now() - extractionStart);
536534
logger.debug(
537535
`Finished extracting CodeQL bundle to ${extractedBundlePath} (${extractionDurationMs} ms).`,
@@ -706,27 +704,3 @@ async function cleanUpGlob(glob: string, name: string, logger: Logger) {
706704
logger.warning(`Failed to clean up ${name}: ${e}.`);
707705
}
708706
}
709-
710-
async function extractBundle(archivedBundlePath: string): Promise<{
711-
compressionMethod: CompressionMethod;
712-
extractedBundlePath: string;
713-
}> {
714-
if (archivedBundlePath.endsWith(".tar.gz")) {
715-
return {
716-
compressionMethod: "gzip",
717-
// While we could also ask tar to autodetect the compression method,
718-
// we defensively keep the gzip call identical as requesting a gzipped
719-
// bundle will soon be a fallback option.
720-
extractedBundlePath: await toolcache.extractTar(archivedBundlePath),
721-
};
722-
}
723-
return {
724-
compressionMethod: "zstd",
725-
// tar will autodetect the compression method
726-
extractedBundlePath: await toolcache.extractTar(
727-
archivedBundlePath,
728-
undefined,
729-
"x",
730-
),
731-
};
732-
}

src/tar.ts

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import { ToolRunner } from "@actions/exec/lib/toolrunner";
2+
import * as toolcache from "@actions/tool-cache";
3+
import { safeWhich } from "@chrisgavin/safe-which";
4+
5+
import { Logger } from "./logging";
6+
import { assertNever } from "./util";
7+
8+
const MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3";
9+
const MIN_REQUIRED_GNU_TAR_VERSION = "1.31";
10+
11+
type TarVersion = {
12+
type: "gnu" | "bsd";
13+
version: string;
14+
};
15+
16+
async function getTarVersion(): Promise<TarVersion> {
17+
const tar = await safeWhich("tar");
18+
let stdout = "";
19+
const exitCode = await new ToolRunner(tar, ["--version"], {
20+
listeners: {
21+
stdout: (data: Buffer) => {
22+
stdout += data.toString();
23+
},
24+
},
25+
}).exec();
26+
if (exitCode !== 0) {
27+
throw new Error("Failed to call tar --version");
28+
}
29+
// Return whether this is GNU tar or BSD tar, and the version number
30+
if (stdout.includes("GNU tar")) {
31+
const match = stdout.match(/tar \(GNU tar\) ([0-9.]+)/);
32+
if (!match || !match[1]) {
33+
throw new Error("Failed to parse output of tar --version.");
34+
}
35+
36+
return { type: "gnu", version: match[1] };
37+
} else if (stdout.includes("bsdtar")) {
38+
const match = stdout.match(/bsdtar ([0-9.]+)/);
39+
if (!match || !match[1]) {
40+
throw new Error("Failed to parse output of tar --version.");
41+
}
42+
43+
return { type: "bsd", version: match[1] };
44+
} else {
45+
throw new Error("Unknown tar version");
46+
}
47+
}
48+
49+
export async function isZstdAvailable(logger: Logger): Promise<boolean> {
50+
try {
51+
const { type, version } = await getTarVersion();
52+
logger.info(`Found ${type} tar version ${version}.`);
53+
switch (type) {
54+
case "gnu":
55+
return version >= MIN_REQUIRED_GNU_TAR_VERSION;
56+
case "bsd":
57+
return version >= MIN_REQUIRED_BSD_TAR_VERSION;
58+
default:
59+
assertNever(type);
60+
}
61+
} catch (e) {
62+
logger.error(
63+
"Failed to determine tar version, therefore will assume zstd may not be available. " +
64+
`The underlying error was: ${e}`,
65+
);
66+
return false;
67+
}
68+
}
69+
70+
export type CompressionMethod = "gzip" | "zstd";
71+
72+
export async function extract(path: string): Promise<{
73+
compressionMethod: CompressionMethod;
74+
outputPath: string;
75+
}> {
76+
if (path.endsWith(".tar.gz")) {
77+
return {
78+
compressionMethod: "gzip",
79+
// While we could also ask tar to autodetect the compression method,
80+
// we defensively keep the gzip call identical as requesting a gzipped
81+
// bundle will soon be a fallback option.
82+
outputPath: await toolcache.extractTar(path),
83+
};
84+
}
85+
return {
86+
compressionMethod: "zstd",
87+
// By specifying only the "x" flag, we ask tar to autodetect the compression
88+
// method.
89+
outputPath: await toolcache.extractTar(path, undefined, "x"),
90+
};
91+
}

0 commit comments

Comments
 (0)