Skip to content

Commit 3da852e

Browse files
committed
Capture stderr from extracting .tar.zst
1 parent 1aa7f6f commit 3da852e

File tree

6 files changed

+147
-28
lines changed

6 files changed

+147
-28
lines changed

lib/setup-codeql.js

Lines changed: 8 additions & 4 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: 56 additions & 10 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/setup-codeql.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { default as deepEqual } from "fast-deep-equal";
99
import * as semver from "semver";
1010
import { v4 as uuidV4 } from "uuid";
1111

12-
import { isRunningLocalAction } from "./actions-util";
12+
import { CommandInvocationError, isRunningLocalAction } from "./actions-util";
1313
import * as api from "./api-client";
1414
// Note: defaults.json is referenced from the CodeQL Action sync tool and the Actions runner image
1515
// creation scripts. Ensure that any changes to the format of this file are compatible with both of
@@ -497,6 +497,7 @@ export const downloadCodeQL = async function (
497497
maybeBundleVersion: string | undefined,
498498
maybeCliVersion: string | undefined,
499499
apiDetails: api.GitHubApiDetails,
500+
tarVersion: tar.TarVersion | undefined,
500501
tempDir: string,
501502
logger: Logger,
502503
): Promise<{
@@ -554,6 +555,7 @@ export const downloadCodeQL = async function (
554555
const extractedBundlePath = await tar.extract(
555556
archivedBundlePath,
556557
compressionMethod,
558+
tarVersion,
557559
);
558560
const extractionDurationMs = Math.round(performance.now() - extractionStart);
559561
logger.debug(
@@ -700,6 +702,10 @@ export async function setupCodeQLBundle(
700702
);
701703
} catch (e) {
702704
zstdFailureReason = util.getErrorMessage(e) || "unknown error";
705+
if (e instanceof CommandInvocationError) {
706+
zstdFailureReason += ` Full error: ${e.stderr}`;
707+
logger.debug(`Invocation output the following to stderr: ${e.stderr}`);
708+
}
703709
logger.warning(
704710
`Failed to set up CodeQL tools with zstd. Falling back to gzipped version. Error: ${util.getErrorMessage(
705711
e,
@@ -755,7 +761,11 @@ async function setupCodeQLBundleWithCompressionMethod(
755761
const compressionMethod = tar.inferCompressionMethod(
756762
source.codeqlTarPath,
757763
);
758-
codeqlFolder = await tar.extract(source.codeqlTarPath, compressionMethod);
764+
codeqlFolder = await tar.extract(
765+
source.codeqlTarPath,
766+
compressionMethod,
767+
zstdAvailability.version,
768+
);
759769
toolsSource = ToolsSource.Local;
760770
break;
761771
}
@@ -770,6 +780,7 @@ async function setupCodeQLBundleWithCompressionMethod(
770780
source.bundleVersion,
771781
source.cliVersion,
772782
apiDetails,
783+
zstdAvailability.version,
773784
tempDir,
774785
logger,
775786
);

src/tar.ts

Lines changed: 68 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1+
import * as fs from "fs";
2+
import path from "path";
3+
14
import { ToolRunner } from "@actions/exec/lib/toolrunner";
25
import * as toolcache from "@actions/tool-cache";
36
import { safeWhich } from "@chrisgavin/safe-which";
7+
import { v4 as uuidV4 } from "uuid";
48

9+
import { getTemporaryDirectory, runTool } from "./actions-util";
510
import { Logger } from "./logging";
611
import { assertNever } from "./util";
712

@@ -84,24 +89,77 @@ export async function isZstdAvailable(
8489
export type CompressionMethod = "gzip" | "zstd";
8590

8691
export async function extract(
87-
path: string,
92+
tarPath: string,
8893
compressionMethod: CompressionMethod,
94+
tarVersion: TarVersion | undefined,
8995
): Promise<string> {
9096
switch (compressionMethod) {
9197
case "gzip":
92-
// While we could also ask tar to autodetect the compression method,
93-
// we defensively keep the gzip call identical as requesting a gzipped
94-
// bundle will soon be a fallback option.
95-
return await toolcache.extractTar(path);
98+
// Defensively continue to call the toolcache API as requesting a gzipped
99+
// bundle may be a fallback option.
100+
return await toolcache.extractTar(tarPath);
96101
case "zstd":
97-
// By specifying only the "x" flag, we ask tar to autodetect the
98-
// compression method.
99-
return await toolcache.extractTar(path, undefined, "x");
102+
if (!tarVersion) {
103+
throw new Error(
104+
"Could not determine tar version, which is required to extract a Zstandard archive.",
105+
);
106+
}
107+
return await extractTarZst(tarPath, tarVersion);
108+
}
109+
}
110+
111+
/**
112+
* Extract a compressed tar archive
113+
*
114+
* @param file path to the tar
115+
* @param dest destination directory. Optional.
116+
* @returns path to the destination directory
117+
*/
118+
export async function extractTarZst(
119+
file: string,
120+
tarVersion: TarVersion,
121+
): Promise<string> {
122+
if (!file) {
123+
throw new Error("parameter 'file' is required");
124+
}
125+
126+
// Create dest
127+
const dest = await createExtractFolder();
128+
129+
// Initialize args
130+
const args = ["-x", "-v"];
131+
132+
let destArg = dest;
133+
let fileArg = file;
134+
if (process.platform === "win32" && tarVersion.type === "gnu") {
135+
args.push("--force-local");
136+
destArg = dest.replace(/\\/g, "/");
137+
138+
// Technically only the dest needs to have `/` but for aesthetic consistency
139+
// convert slashes in the file arg too.
140+
fileArg = file.replace(/\\/g, "/");
141+
}
142+
143+
if (tarVersion.type === "gnu") {
144+
// Suppress warnings when using GNU tar to extract archives created by BSD tar
145+
args.push("--warning=no-unknown-keyword");
146+
args.push("--overwrite");
100147
}
148+
149+
args.push("-C", destArg, "-f", fileArg);
150+
await runTool(`tar`, args);
151+
152+
return dest;
153+
}
154+
155+
async function createExtractFolder(): Promise<string> {
156+
const dest = path.join(getTemporaryDirectory(), uuidV4());
157+
fs.mkdirSync(dest, { recursive: true });
158+
return dest;
101159
}
102160

103-
export function inferCompressionMethod(path: string): CompressionMethod {
104-
if (path.endsWith(".tar.gz")) {
161+
export function inferCompressionMethod(tarPath: string): CompressionMethod {
162+
if (tarPath.endsWith(".tar.gz")) {
105163
return "gzip";
106164
}
107165
return "zstd";

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