Skip to content

Commit 8c1551c

Browse files
authored
Merge pull request #2767 from github/cklin/prefer-gtar
Prefer gtar if available
2 parents 1c15a48 + fc4873b commit 8c1551c

File tree

4 files changed

+55
-24
lines changed

4 files changed

+55
-24
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th
44

55
## [UNRELEASED]
66

7-
No user facing changes.
7+
- Update the action to prefer `gtar` over `tar` to make zstd archive extraction more robust. [2767](https://github.com/github/codeql-action/pull/2767)
88

99
## 3.28.9 - 07 Feb 2025
1010

lib/tar.js

Lines changed: 26 additions & 11 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 & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/tar.ts

Lines changed: 27 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,13 @@ const MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3";
1515
const MIN_REQUIRED_GNU_TAR_VERSION = "1.31";
1616

1717
export type TarVersion = {
18+
name: string;
1819
type: "gnu" | "bsd";
1920
version: string;
2021
};
2122

22-
async function getTarVersion(): Promise<TarVersion> {
23-
const tar = await io.which("tar", true);
23+
async function getTarVersion(programName: string): Promise<TarVersion> {
24+
const tar = await io.which(programName, true);
2425
let stdout = "";
2526
const exitCode = await new ToolRunner(tar, ["--version"], {
2627
listeners: {
@@ -30,28 +31,43 @@ async function getTarVersion(): Promise<TarVersion> {
3031
},
3132
}).exec();
3233
if (exitCode !== 0) {
33-
throw new Error("Failed to call tar --version");
34+
throw new Error(`Failed to call ${programName} --version`);
3435
}
3536
// Return whether this is GNU tar or BSD tar, and the version number
3637
if (stdout.includes("GNU tar")) {
3738
const match = stdout.match(/tar \(GNU tar\) ([0-9.]+)/);
3839
if (!match || !match[1]) {
39-
throw new Error("Failed to parse output of tar --version.");
40+
throw new Error(`Failed to parse output of ${programName} --version.`);
4041
}
4142

42-
return { type: "gnu", version: match[1] };
43+
return { name: programName, type: "gnu", version: match[1] };
4344
} else if (stdout.includes("bsdtar")) {
4445
const match = stdout.match(/bsdtar ([0-9.]+)/);
4546
if (!match || !match[1]) {
46-
throw new Error("Failed to parse output of tar --version.");
47+
throw new Error(`Failed to parse output of ${programName} --version.`);
4748
}
4849

49-
return { type: "bsd", version: match[1] };
50+
return { name: programName, type: "bsd", version: match[1] };
5051
} else {
5152
throw new Error("Unknown tar version");
5253
}
5354
}
5455

56+
async function pickTarCommand(): Promise<TarVersion> {
57+
// bsdtar 3.5.3 on the macos-14 (arm) action runner image is prone to crash with the following
58+
// error messages when extracting zstd archives:
59+
//
60+
// tar: Child process exited with status 1
61+
// tar: Error exit delayed from previous errors.
62+
//
63+
// To avoid this problem, prefer GNU tar under the name "gtar" if it is available.
64+
try {
65+
return await getTarVersion("gtar");
66+
} catch {
67+
return await getTarVersion("tar");
68+
}
69+
}
70+
5571
export interface ZstdAvailability {
5672
available: boolean;
5773
foundZstdBinary: boolean;
@@ -63,7 +79,7 @@ export async function isZstdAvailable(
6379
): Promise<ZstdAvailability> {
6480
const foundZstdBinary = await isBinaryAccessible("zstd", logger);
6581
try {
66-
const tarVersion = await getTarVersion();
82+
const tarVersion = await pickTarCommand();
6783
const { type, version } = tarVersion;
6884
logger.info(`Found ${type} tar version ${version}.`);
6985
switch (type) {
@@ -162,10 +178,10 @@ export async function extractTarZst(
162178

163179
args.push("-f", tar instanceof stream.Readable ? "-" : tar, "-C", dest);
164180

165-
process.stdout.write(`[command]tar ${args.join(" ")}\n`);
181+
process.stdout.write(`[command]${tarVersion.name} ${args.join(" ")}\n`);
166182

167183
await new Promise<void>((resolve, reject) => {
168-
const tarProcess = spawn("tar", args, { stdio: "pipe" });
184+
const tarProcess = spawn(tarVersion.name, args, { stdio: "pipe" });
169185

170186
let stdout = "";
171187
tarProcess.stdout?.on("data", (data: Buffer) => {
@@ -196,7 +212,7 @@ export async function extractTarZst(
196212
if (code !== 0) {
197213
reject(
198214
new CommandInvocationError(
199-
"tar",
215+
tarVersion.name,
200216
args,
201217
code ?? undefined,
202218
stdout,

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy