fix: inline the options into all apt exec calls + improve errors

This commit is contained in:
Amin Yahyaabadi 2024-08-16 01:09:26 -07:00
parent 080dafd056
commit 1704d8457d
No known key found for this signature in database
GPG Key ID: F52AF77F636088F0
8 changed files with 119 additions and 123 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -30,6 +30,9 @@ export async function installTool(
} catch (e) { } catch (e) {
// push error message to the logger // push error message to the logger
error(e as string | Error) error(e as string | Error)
if (e instanceof Error && e.stack !== undefined) {
error(e.stack)
}
errorMessages.push(`${tool} failed to install`) errorMessages.push(`${tool} failed to install`)
} }
endGroup() endGroup()

View File

@ -2,9 +2,8 @@ import { defaultExecOptions, execRoot, execRootSync } from "admina"
import { GITHUB_ACTIONS } from "ci-info" import { GITHUB_ACTIONS } from "ci-info"
import { info, warning } from "ci-log" import { info, warning } from "ci-log"
import escapeRegex from "escape-string-regexp" import escapeRegex from "escape-string-regexp"
import { type ExecaError, type SyncOptions, execa } from "execa" import { type ExecaError, execa } from "execa"
import { appendFile } from "fs/promises" import { appendFile } from "fs/promises"
import memoize from "micro-memoize"
import { sourceRC } from "os-env" import { sourceRC } from "os-env"
import { pathExists } from "path-exists" import { pathExists } from "path-exists"
import which from "which" import which from "which"
@ -62,16 +61,15 @@ export async function setupAptPack(packages: AptPackage[], update = false): Prom
// Install // Install
try { try {
execRootSync(apt, ["install", "--fix-broken", "-y", ...needToInstall], getAptExecOptions({ apt })) execRootSync(apt, ["install", "--fix-broken", "-y", ...needToInstall], { ...defaultExecOptions, env: getEnv(apt) })
} catch (err) { } catch (err) {
if ("stderr" in (err as ExecaError)) { if (isExecaError(err)) {
const stderr = (err as ExecaError).stderr if (retryErrors.some((error) => err.stderr.includes(error))) {
if (retryErrors.some((error) => stderr.includes(error))) {
warning(`Failed to install packages ${needToInstall}. Retrying...`) warning(`Failed to install packages ${needToInstall}. Retrying...`)
execRootSync( execRootSync(
apt, apt,
["install", "--fix-broken", "-y", "-o", aptTimeout, ...needToInstall], ["install", "--fix-broken", "-y", "-o", aptTimeout, ...needToInstall],
getAptExecOptions({ apt }), { ...defaultExecOptions, env: getEnv(apt) },
) )
} }
} else { } else {
@ -82,6 +80,10 @@ export async function setupAptPack(packages: AptPackage[], update = false): Prom
return { binDir: "/usr/bin/" } return { binDir: "/usr/bin/" }
} }
function isExecaError(err: unknown): err is ExecaError {
return typeof (err as ExecaError).stderr === "string"
}
export function hasNala() { export function hasNala() {
return which.sync("nala", { nothrow: true }) !== null return which.sync("nala", { nothrow: true }) !== null
} }
@ -112,18 +114,6 @@ function getEnv(apt: string) {
return env return env
} }
function getAptExecOptionsRaw(givenOpts: { apt?: string; pipe?: boolean } = {}): SyncOptions {
const opts = {
apt: "apt-get",
pipe: false,
...givenOpts,
}
return { env: getEnv(opts.apt), ...defaultExecOptions, stdio: opts.pipe ? "pipe" : "inherit" }
}
const getAptExecOptions = memoize(getAptExecOptionsRaw)
export enum AptPackageType { export enum AptPackageType {
NameDashVersion = 0, NameDashVersion = 0,
NameEqualsVersion = 1, NameEqualsVersion = 1,
@ -156,7 +146,7 @@ async function addRepositories(apt: string, packages: AptPackage[]) {
await installAddAptRepo(apt) await installAddAptRepo(apt)
for (const repo of allRepositories) { for (const repo of allRepositories) {
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
execRootSync("add-apt-repository", ["-y", "--no-update", repo], getAptExecOptions()) execRootSync("add-apt-repository", ["-y", "--no-update", repo], { ...defaultExecOptions, env: getEnv(apt) })
} }
updateRepos(apt) updateRepos(apt)
didUpdate = true didUpdate = true
@ -169,7 +159,7 @@ async function aptPackageType(apt: string, name: string, version: string | undef
"search", "search",
"--names-only", "--names-only",
`^${escapeRegex(name)}-${escapeRegex(version)}$`, `^${escapeRegex(name)}-${escapeRegex(version)}$`,
], getAptExecOptions({ apt, pipe: true })) ], { env: getEnv(apt), stdio: "pipe" })
if (stdout.trim() !== "") { if (stdout.trim() !== "") {
return AptPackageType.NameDashVersion return AptPackageType.NameDashVersion
} }
@ -177,7 +167,7 @@ async function aptPackageType(apt: string, name: string, version: string | undef
try { try {
// check if apt-get show can find the version // check if apt-get show can find the version
// eslint-disable-next-line @typescript-eslint/no-shadow // eslint-disable-next-line @typescript-eslint/no-shadow
const { stdout } = await execa("apt-cache", ["show", `${name}=${version}`], getAptExecOptions()) const { stdout } = await execa("apt-cache", ["show", `${name}=${version}`], { env: getEnv(apt) })
if (stdout.trim() === "") { if (stdout.trim() === "") {
return AptPackageType.NameEqualsVersion return AptPackageType.NameEqualsVersion
} }
@ -187,7 +177,7 @@ async function aptPackageType(apt: string, name: string, version: string | undef
} }
try { try {
const { stdout: showStdout } = await execa("apt-cache", ["show", name], getAptExecOptions({ pipe: true })) const { stdout: showStdout } = await execa("apt-cache", ["show", name], { env: getEnv(apt), stdio: "pipe" })
if (showStdout.trim() !== "") { if (showStdout.trim() !== "") {
return AptPackageType.Name return AptPackageType.Name
} }
@ -213,8 +203,8 @@ async function getAptArg(apt: string, name: string, version: string | undefined)
case AptPackageType.NameEqualsVersion: case AptPackageType.NameEqualsVersion:
return `${name}=${version}` return `${name}=${version}`
case AptPackageType.Name: case AptPackageType.Name:
if (version !== undefined) { if (version !== undefined && version !== "") {
warning(`Could not find package ${name} ${version}. Installing the latest version.`) warning(`Could not find package ${name} with version ${version}. Installing the latest version.`)
} }
return name return name
default: default:
@ -226,7 +216,7 @@ function updateRepos(apt: string) {
execRootSync( execRootSync(
apt, apt,
apt !== "nala" ? ["update", "-y", "-o", aptTimeout] : ["update", "-o", aptTimeout], apt !== "nala" ? ["update", "-y", "-o", aptTimeout] : ["update", "-o", aptTimeout],
getAptExecOptions({ apt }), { ...defaultExecOptions, env: getEnv(apt) },
) )
} }
@ -237,7 +227,7 @@ async function installAddAptRepo(apt: string) {
execRootSync( execRootSync(
apt, apt,
["install", "-y", "--fix-broken", "-o", aptTimeout, "software-properties-common"], ["install", "-y", "--fix-broken", "-o", aptTimeout, "software-properties-common"],
getAptExecOptions({ apt }), { ...defaultExecOptions, env: getEnv(apt) },
) )
} }
@ -256,7 +246,10 @@ async function initApt(apt: string) {
]) ])
if (toInstall.length !== 0) { if (toInstall.length !== 0) {
execRootSync(apt, ["install", "-y", "--fix-broken", "-o", aptTimeout, ...toInstall], getAptExecOptions({ apt })) execRootSync(apt, ["install", "-y", "--fix-broken", "-o", aptTimeout, ...toInstall], {
...defaultExecOptions,
env: getEnv(apt),
})
} }
const promises: Promise<string | void>[] = [ const promises: Promise<string | void>[] = [
@ -325,7 +318,7 @@ export async function updateAptAlternatives(name: string, path: string, rcPath:
export async function isPackageInstalled(pack: string) { export async function isPackageInstalled(pack: string) {
try { try {
// check if a package is installed // check if a package is installed
const { stdout } = await execa("dpkg", ["-s", pack], getAptExecOptions({ pipe: true })) const { stdout } = await execa("dpkg", ["-s", pack], { env: getEnv("apt-get"), stdio: "pipe" })
if (typeof stdout !== "string") { if (typeof stdout !== "string") {
return false return false
} }
@ -340,7 +333,7 @@ export async function isPackageInstalled(pack: string) {
export async function isPackageRegexInstalled(regexp: string) { export async function isPackageRegexInstalled(regexp: string) {
try { try {
// check if a package matching the regexp is installed // check if a package matching the regexp is installed
const { stdout } = await execa("dpkg", ["-l", regexp], getAptExecOptions({ pipe: true })) const { stdout } = await execa("dpkg", ["-l", regexp], { env: getEnv("apt-get"), stdio: "pipe" })
if (typeof stdout !== "string") { if (typeof stdout !== "string") {
return false return false
} }