Skip to content

Commit

Permalink
Merge pull request #2771 from github/revert-2767-cklin/prefer-gtar
Browse files Browse the repository at this point in the history
Revert "Prefer gtar if available"
  • Loading branch information
henrymercer authored Feb 18, 2025
2 parents 1bb15d0 + 906452d commit d99c7e8
Show file tree
Hide file tree
Showing 4 changed files with 24 additions and 55 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ See the [releases page](https://github.com/github/codeql-action/releases) for th

## [UNRELEASED]

- Update the action to prefer `gtar` over `tar` to make zstd archive extraction more robust. [2767](https://github.com/github/codeql-action/pull/2767)
- Address an issue where the CodeQL Bundle would occasionally fail to decompress on macOS. [#2768](https://github.com/github/codeql-action/pull/2768)

## 3.28.9 - 07 Feb 2025

Expand Down
37 changes: 11 additions & 26 deletions lib/tar.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion lib/tar.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 11 additions & 27 deletions src/tar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,12 @@ const MIN_REQUIRED_BSD_TAR_VERSION = "3.4.3";
const MIN_REQUIRED_GNU_TAR_VERSION = "1.31";

export type TarVersion = {
name: string;
type: "gnu" | "bsd";
version: string;
};

async function getTarVersion(programName: string): Promise<TarVersion> {
const tar = await io.which(programName, true);
async function getTarVersion(): Promise<TarVersion> {
const tar = await io.which("tar", true);
let stdout = "";
const exitCode = await new ToolRunner(tar, ["--version"], {
listeners: {
Expand All @@ -31,43 +30,28 @@ async function getTarVersion(programName: string): Promise<TarVersion> {
},
}).exec();
if (exitCode !== 0) {
throw new Error(`Failed to call ${programName} --version`);
throw new Error("Failed to call tar --version");
}
// Return whether this is GNU tar or BSD tar, and the version number
if (stdout.includes("GNU tar")) {
const match = stdout.match(/tar \(GNU tar\) ([0-9.]+)/);
if (!match || !match[1]) {
throw new Error(`Failed to parse output of ${programName} --version.`);
throw new Error("Failed to parse output of tar --version.");
}

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

return { name: programName, type: "bsd", version: match[1] };
return { type: "bsd", version: match[1] };
} else {
throw new Error("Unknown tar version");
}
}

async function pickTarCommand(): Promise<TarVersion> {
// bsdtar 3.5.3 on the macos-14 (arm) action runner image is prone to crash with the following
// error messages when extracting zstd archives:
//
// tar: Child process exited with status 1
// tar: Error exit delayed from previous errors.
//
// To avoid this problem, prefer GNU tar under the name "gtar" if it is available.
try {
return await getTarVersion("gtar");
} catch {
return await getTarVersion("tar");
}
}

export interface ZstdAvailability {
available: boolean;
foundZstdBinary: boolean;
Expand All @@ -79,7 +63,7 @@ export async function isZstdAvailable(
): Promise<ZstdAvailability> {
const foundZstdBinary = await isBinaryAccessible("zstd", logger);
try {
const tarVersion = await pickTarCommand();
const tarVersion = await getTarVersion();
const { type, version } = tarVersion;
logger.info(`Found ${type} tar version ${version}.`);
switch (type) {
Expand Down Expand Up @@ -187,10 +171,10 @@ export async function extractTarZst(

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

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

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

let stdout = "";
tarProcess.stdout?.on("data", (data: Buffer) => {
Expand Down Expand Up @@ -221,7 +205,7 @@ export async function extractTarZst(
if (code !== 0) {
reject(
new CommandInvocationError(
tarVersion.name,
"tar",
args,
code ?? undefined,
stdout,
Expand Down

0 comments on commit d99c7e8

Please sign in to comment.