@@ -41129,26 +41129,17 @@ const cmdTailscale = "tailscale";
4112941129const cmdTailscaleFullPath = "/usr/local/bin/tailscale";
4113041130const cmdTailscaled = "tailscaled";
4113141131const cmdTailscaledFullPath = "/usr/local/bin/tailscaled";
41132- const platformWin32 = "win32";
41133- const platformDarwin = "darwin";
4113441132const runnerLinux = "Linux";
4113541133const runnerWindows = "Windows";
4113641134const runnerMacOS = "macOS";
4113741135const versionLatest = "latest";
4113841136const versionUnstable = "unstable";
4113941137// Cross-platform Tailscale local API status check
4114041138async function getTailscaleStatus() {
41141- const { exitCode, stdout, stderr } = await exec.getExecOutput(cmdTailscale, ["status", "--json"], {
41142- silent: true,
41143- ignoreReturnCode: true,
41144- });
41145- if (exitCode !== 0) {
41146- process.stderr.write(stderr);
41147- throw new Error(`tailscale status failed with exit code ${exitCode}`);
41148- }
41149- if (core.isDebug()) {
41150- process.stdout.write(stdout);
41151- }
41139+ const { stdout } = await execSilent("get tailscale status", cmdTailscale, [
41140+ "status",
41141+ "--json",
41142+ ]);
4115241143 return JSON.parse(stdout);
4115341144}
4115441145async function run() {
@@ -41236,15 +41227,23 @@ async function pingHost(host) {
4123641227 core.debug(`Waiting ${waitTime} milliseconds before pinging`);
4123741228 await (0, promises_1.setTimeout)(waitTime);
4123841229 }
41239- let result = await exec.getExecOutput(cmdTailscale, ["ping", "-c", "1", host], { ignoreReturnCode: true });
41240- if (result.exitCode === 0) {
41230+ try {
41231+ let result = await execSilent("ping host", cmdTailscale, [
41232+ "ping",
41233+ "-c",
41234+ "1",
41235+ host,
41236+ ]);
4124141237 core.info(`✅ Ping host ${host} reachable via direct connection!`);
4124241238 return;
4124341239 }
41244- else if (result.stderr.includes("direct connection not established")) {
41245- // Relayed connectivity is good enough, we don't want to tie up a CI job waiting for a direct connection.
41246- core.info(`✅ Ping host ${host} reachable via DERP!`);
41247- return;
41240+ catch (err) {
41241+ if (err instanceof execError &&
41242+ err.stderr.includes("direct connection not established")) {
41243+ // Relayed connectivity is good enough, we don't want to tie up a CI job waiting for a direct connection.
41244+ core.info(`✅ Ping host ${host} reachable via DERP!`);
41245+ return;
41246+ }
4124841247 }
4124941248 i++;
4125041249 }
@@ -41295,11 +41294,12 @@ async function resolveVersion(version, runnerOS) {
4129541294 }
4129641295 if (version === versionLatest || version === versionUnstable) {
4129741296 let path = version === versionUnstable ? versionUnstable : "stable";
41298- const { stdout } = await exec.getExecOutput("curl", [
41297+ let pkg = `https://pkgs.tailscale.com/${path}/?mode=json`;
41298+ const { stdout } = await execSilent(`curl ${pkg}`, "curl", [
4129941299 "-H",
4130041300 "user-agent:action-setup-tailscale",
4130141301 "-s",
41302- `https://pkgs.tailscale.com/${path}/?mode=json` ,
41302+ pkg ,
4130341303 ]);
4130441304 const response = JSON.parse(stdout);
4130541305 return response.Version;
@@ -41400,7 +41400,7 @@ async function installTailscaleLinux(config, toolPath) {
4140041400 // Get SHA256 if not provided
4140141401 if (!config.sha256Sum) {
4140241402 const shaUrl = `${baseUrl}/tailscale_${config.resolvedVersion}_${config.arch}.tgz.sha256`;
41403- const { stdout } = await exec.getExecOutput( "curl", [
41403+ const { stdout } = await execSilent(`curl ${shaUrl}`, "curl", [
4140441404 "-H",
4140541405 "user-agent:action-setup-tailscale",
4140641406 "-L",
@@ -41429,15 +41429,23 @@ async function installTailscaleLinux(config, toolPath) {
4142941429 fs.copyFileSync(path.join(extractedDir, cmdTailscale), path.join(toolPath, cmdTailscale));
4143041430 fs.copyFileSync(path.join(extractedDir, cmdTailscaled), path.join(toolPath, cmdTailscaled));
4143141431 // Install binaries to /usr/local/bin
41432- await exec.exec( "sudo", [
41432+ await execSilent("copy tailscale binaries to /usr/local/bin", "sudo", [
4143341433 "cp",
4143441434 path.join(toolPath, cmdTailscale),
4143541435 path.join(toolPath, cmdTailscaled),
4143641436 "/usr/local/bin",
4143741437 ]);
4143841438 // Make sure they're executable
41439- await exec.exec("sudo", ["chmod", "+x", cmdTailscaleFullPath]);
41440- await exec.exec("sudo", ["chmod", "+x", cmdTailscaledFullPath]);
41439+ await execSilent("chmod tailscale binary", "sudo", [
41440+ "chmod",
41441+ "+x",
41442+ cmdTailscaleFullPath,
41443+ ]);
41444+ await execSilent("chmod tailscaled binary", "sudo", [
41445+ "chmod",
41446+ "+x",
41447+ cmdTailscaledFullPath,
41448+ ]);
4144141449}
4144241450async function installTailscaleWindows(config, toolPath, fromCache = false) {
4144341451 // Create tool directory
@@ -41461,7 +41469,7 @@ async function installTailscaleWindows(config, toolPath, fromCache = false) {
4146141469 // Get SHA256 if not provided
4146241470 if (!config.sha256Sum) {
4146341471 const shaUrl = `${baseUrl}/tailscale-setup-${config.resolvedVersion}-${config.arch}.msi.sha256`;
41464- const { stdout } = await exec.getExecOutput( "curl", [
41472+ const { stdout } = await execSilent(`curl ${shaUrl}`, "curl", [
4146541473 "-H",
4146641474 "user-agent:action-setup-tailscale",
4146741475 "-L",
@@ -41489,7 +41497,7 @@ async function installTailscaleWindows(config, toolPath, fromCache = false) {
4148941497 }
4149041498 }
4149141499 // Install MSI (same for both fresh and cached)
41492- await exec.exec( "msiexec.exe", [
41500+ await execSilent("install msi", "msiexec.exe", [
4149341501 "/quiet",
4149441502 `/l*v`,
4149541503 path.join(process.env.RUNNER_TEMP || "", "tailscale.log"),
@@ -41502,16 +41510,16 @@ async function installTailscaleWindows(config, toolPath, fromCache = false) {
4150241510async function installTailscaleMacOS(config, toolPath) {
4150341511 core.info("Building tailscale from src on macOS...");
4150441512 // Clone the repo
41505- await exec.exec( "git clone https://github.com/tailscale/tailscale.git tailscale");
41513+ await execSilent("glone tailscale repo", "git clone https://github.com/tailscale/tailscale.git tailscale");
4150641514 // Checkout the resolved version
41507- await exec.exec( `git checkout v${config.resolvedVersion}`, [], {
41515+ await execSilent("checkout resolved version", `git checkout v${config.resolvedVersion}`, [], {
4150841516 cwd: cmdTailscale,
4150941517 });
4151041518 // Create tool directory and copy binaries there for caching
4151141519 fs.mkdirSync(toolPath, { recursive: true });
4151241520 // Build tailscale and tailscaled into tool directory
4151341521 for (const binary of [cmdTailscale, cmdTailscaled]) {
41514- await exec.exec( `./build_dist.sh -o ${path.join(toolPath, binary)} ./cmd/${binary}`, [], {
41522+ await execSilent(`build ${binary}`, `./build_dist.sh -o ${path.join(toolPath, binary)} ./cmd/${binary}`, [], {
4151541523 cwd: cmdTailscale,
4151641524 env: {
4151741525 ...process.env,
@@ -41520,15 +41528,23 @@ async function installTailscaleMacOS(config, toolPath) {
4152041528 });
4152141529 }
4152241530 // Install binaries to /usr/local/bin
41523- await exec.exec( "sudo", [
41531+ await execSilent("copy binaries to /usr/local/bin", "sudo", [
4152441532 "cp",
4152541533 path.join(toolPath, cmdTailscale),
4152641534 path.join(toolPath, cmdTailscaled),
4152741535 "/usr/local/bin",
4152841536 ]);
4152941537 // Make sure they're executable
41530- await exec.exec("sudo", ["chmod", "+x", cmdTailscaleFullPath]);
41531- await exec.exec("sudo", ["chmod", "+x", cmdTailscaledFullPath]);
41538+ await execSilent("chmod tailscale", "sudo", [
41539+ "chmod",
41540+ "+x",
41541+ cmdTailscaleFullPath,
41542+ ]);
41543+ await execSilent("chmod tailscaled", "sudo", [
41544+ "chmod",
41545+ "+x",
41546+ cmdTailscaledFullPath,
41547+ ]);
4153241548 core.info("✅ Tailscale installed successfully on macOS from source");
4153341549}
4153441550async function startTailscaleDaemon(config) {
@@ -41599,7 +41615,7 @@ async function connectToTailscale(config, runnerOS) {
4159941615 hostname = `github-${process.env.COMPUTERNAME}`;
4160041616 }
4160141617 else {
41602- const { stdout } = await exec.getExecOutput( "hostname");
41618+ const { stdout } = await execSilent("hostname", "hostname");
4160341619 hostname = `github-${stdout.trim()}`;
4160441620 }
4160541621 }
@@ -41642,9 +41658,8 @@ async function connectToTailscale(config, runnerOS) {
4164241658 execArgs = ["sudo", "-E", cmdTailscale, ...upArgs];
4164341659 }
4164441660 const timeoutMs = parseTimeout(config.timeout);
41645- core.info(`Running: ${execArgs.join(" ")} (timeout: ${timeoutMs}ms)`);
4164641661 await Promise.race([
41647- exec.exec( execArgs[0], execArgs.slice(1)),
41662+ execSilent("tailscale up", execArgs[0], execArgs.slice(1)),
4164841663 new Promise((_, reject) => setTimeout(() => reject(new Error("Timeout")), timeoutMs)),
4164941664 ]);
4165041665 // Success
@@ -41701,10 +41716,26 @@ async function installCachedBinaries(toolPath, runnerOS) {
4170141716 const tailscaleBin = path.join(toolPath, cmdTailscale);
4170241717 const tailscaledBin = path.join(toolPath, cmdTailscaled);
4170341718 if (fs.existsSync(tailscaleBin) && fs.existsSync(tailscaledBin)) {
41704- await exec.exec("sudo", ["cp", tailscaleBin, cmdTailscaleFullPath]);
41705- await exec.exec("sudo", ["cp", tailscaledBin, cmdTailscaledFullPath]);
41706- await exec.exec("sudo", ["chmod", "+x", cmdTailscaleFullPath]);
41707- await exec.exec("sudo", ["chmod", "+x", cmdTailscaledFullPath]);
41719+ await execSilent("copy tailscale from cache", "sudo", [
41720+ "cp",
41721+ tailscaleBin,
41722+ cmdTailscaleFullPath,
41723+ ]);
41724+ await execSilent("copy tailscaled from cache", "sudo", [
41725+ "cp",
41726+ tailscaledBin,
41727+ cmdTailscaledFullPath,
41728+ ]);
41729+ await execSilent("chmod tailscale", "sudo", [
41730+ "chmod",
41731+ "+x",
41732+ cmdTailscaleFullPath,
41733+ ]);
41734+ await execSilent("chmod tailscaled", "sudo", [
41735+ "chmod",
41736+ "+x",
41737+ cmdTailscaledFullPath,
41738+ ]);
4170841739 }
4170941740 else {
4171041741 throw new Error(`Cached binaries not found in ${toolPath}`);
@@ -41718,12 +41749,12 @@ async function configureDNSOnMacOS(status) {
4171841749 }
4171941750 core.info(`Setting system DNS server to 100.100.100.100 and searchdomains to ${status.CurrentTailnet.MagicDNSSuffix}`);
4172041751 try {
41721- await exec.exec( "networksetup", [
41752+ await execSilent("set dns servers", "networksetup", [
4172241753 "-setdnsservers",
4172341754 "Ethernet",
4172441755 "100.100.100.100",
4172541756 ]);
41726- await exec.exec( "networksetup", [
41757+ await execSilent("set search domains", "networksetup", [
4172741758 "-setsearchdomains",
4172841759 "Ethernet",
4172941760 status.CurrentTailnet.MagicDNSSuffix,
@@ -41734,6 +41765,45 @@ async function configureDNSOnMacOS(status) {
4173441765 }
4173541766}
4173641767run();
41768+ /**
41769+ * Executes the given command, logging the given label as info, but suppressing
41770+ * all other output including the command line itself (unless debug logging is enabled,
41771+ * see https://docs.github.com/en/actions/how-tos/monitor-workflows/enable-debug-logging).
41772+ *
41773+ * If the command fails, stderr is written to the console.
41774+ *
41775+ * @param label a label to use for info logging what's happening
41776+ * @param cmd the command to run
41777+ * @param args arguments to the command
41778+ * @returns stdout (if command was successful)
41779+ * @throws execError if exec returned a non-zero status code
41780+ */
41781+ async function execSilent(label, cmd, args, opts) {
41782+ core.info(`▶️ ${label}`);
41783+ const out = await exec.getExecOutput(cmd, args, {
41784+ ...opts,
41785+ silent: !core.isDebug(),
41786+ ignoreReturnCode: true,
41787+ });
41788+ if (out.exitCode !== 0) {
41789+ if (!core.isDebug) {
41790+ // When debug logging is off, stderr won't have been written to console, write it now.
41791+ process.stderr.write(out.stderr);
41792+ }
41793+ throw new execError(`${cmd} failed with exit code ${out.exitCode}`, out.exitCode, out.stderr);
41794+ }
41795+ return out;
41796+ }
41797+ class execError {
41798+ constructor(msg, exitCode, stderr) {
41799+ this.msg = msg;
41800+ this.exitCode = exitCode;
41801+ this.stderr = stderr;
41802+ }
41803+ toString() {
41804+ return this.msg;
41805+ }
41806+ }
4173741807
4173841808
4173941809/***/ }),
0 commit comments