Skip to content

Commit 19bf09e

Browse files
committed
feat!: support addAptKey options through installAptPack
BREAKING no default keys are added during apt installations anymore. Explicitly pass the keys needed. BREAKING the arguments to addAptKeyViaServer and addAptKeyViaDownload has changed. addAptKeyViaDownload renamed to addAptKeyViaURL
1 parent 12442d6 commit 19bf09e

File tree

17 files changed

+258
-143
lines changed

17 files changed

+258
-143
lines changed

dist/actions/setup-cpp.js

Lines changed: 28 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/actions/setup-cpp.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.

dist/legacy/setup-cpp.js

Lines changed: 28 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/legacy/setup-cpp.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.

dist/modern/setup-cpp.js

Lines changed: 28 additions & 28 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/modern/setup-cpp.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.

packages/setup-apt/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ Add an apt key via a keyserver
135135

136136
**returns:** Promise<string>
137137

138-
### `addAptKeyViaDownload` (function)
138+
### `addAptKeyViaURL` (function)
139139

140140
Add an apt key via a download
141141

packages/setup-apt/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "setup-apt",
3-
"version": "1.0.1",
3+
"version": "2.0.0",
44
"description": "Setup apt packages and repositories in Debian/Ubuntu-based distributions",
55
"repository": "https://github.com/aminya/setup-cpp",
66
"homepage": "https://github.com/aminya/setup-cpp/tree/master/packages/setup-apt",

packages/setup-apt/src/apt-key.ts

Lines changed: 111 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,152 @@
11
import { tmpdir } from "os"
2+
import { join } from "path"
23
import { execRoot, execRootSync } from "admina"
34
import { warning } from "ci-log"
45
import { DownloaderHelper } from "node-downloader-helper"
56
import { pathExists } from "path-exists"
67
import { installAptPack } from "./install.js"
78

8-
function initGpg() {
9-
execRootSync("gpg", ["-k"])
9+
export type AddAptKeyOptions = KeyServerOptions | KeyUrl
10+
11+
/**
12+
* Add an apt key
13+
* @param options The options for adding the key
14+
* @returns The file name of the key that was added or `undefined` if it failed
15+
*
16+
* @example
17+
* ```ts
18+
* await addAptKey({ keys: ["3B4FE6ACC0B21F32", "40976EAF437D05B5"], fileName: "bazel-archive-keyring.gpg"})
19+
* ```
20+
*
21+
* @example
22+
* ```ts
23+
* await addAptKey({ keyUrl: "https://bazel.build/bazel-release.pub.gpg", fileName: "bazel-archive-keyring.gpg"})
24+
* ```
25+
*/
26+
export function addAptKey(options: AddAptKeyOptions) {
27+
if ("keyUrl" in options) {
28+
return addAptKeyViaURL(options)
29+
} else {
30+
return addAptKeyViaServer(options)
31+
}
1032
}
1133

34+
type GpgKeyOptions = {
35+
/**
36+
* The file name for the key (should end in `.gpg`)
37+
*/
38+
fileName: string
39+
/**
40+
* The key store path (Defaults to `/etc/apt/trusted.gpg.d`)
41+
*/
42+
keyStorePath?: string
43+
}
44+
45+
export const defaultKeyStorePath = "/etc/apt/trusted.gpg.d"
46+
47+
export type KeyServerOptions = {
48+
/**
49+
* The keys to add
50+
*
51+
* @example
52+
* ```ts
53+
* ["3B4FE6ACC0B21F32", "40976EAF437D05B5"]
54+
* ```
55+
*/
56+
keys: string[]
57+
/**
58+
* The keyserver to use (Defaults to `keyserver.ubuntu.com`)
59+
*/
60+
keyServer?: string
61+
} & GpgKeyOptions
62+
63+
export const defaultKeyServer = "keyserver.ubuntu.com"
64+
1265
/**
1366
* Add an apt key via a keyserver
14-
* @param keys The keys to add
15-
* @param name The name of the key
16-
* @param server The keyserver to use (Defaults to `keyserver.ubuntu.com`)
1767
* @returns The file name of the key that was added or `undefined` if it failed
1868
*/
19-
export async function addAptKeyViaServer(keys: string[], name: string, server = "keyserver.ubuntu.com") {
69+
export async function addAptKeyViaServer(
70+
{ keys, keyServer = defaultKeyServer, fileName, keyStorePath = defaultKeyServer }: KeyServerOptions,
71+
) {
2072
try {
21-
const fileName = `/etc/apt/trusted.gpg.d/${name}`
22-
if (!(await pathExists(fileName))) {
73+
assertGpgFileName(fileName)
74+
const filePath = join(keyStorePath, fileName)
75+
if (!(await pathExists(filePath))) {
2376
initGpg()
2477

2578
await Promise.all(
2679
keys.map(async (key) => {
2780
await execRoot("gpg", [
2881
"--no-default-keyring",
2982
"--keyring",
30-
`gnupg-ring:${fileName}`,
83+
`gnupg-ring:${filePath}`,
3184
"--keyserver",
32-
server,
85+
keyServer,
3386
"--recv-keys",
3487
key,
3588
])
36-
await execRoot("chmod", ["644", fileName])
89+
await execRoot("chmod", ["644", filePath])
3790
}),
3891
)
3992
}
40-
return fileName
93+
return filePath
4194
} catch (err) {
42-
warning(`Failed to add apt key via server ${server}: ${err}`)
95+
warning(`Failed to add apt key via server ${keyServer}: ${err}`)
4396
return undefined
4497
}
4598
}
4699

100+
export type KeyUrl = {
101+
/**
102+
* The URL to download the key from
103+
*/
104+
keyUrl: string
105+
} & GpgKeyOptions
106+
47107
/**
48108
* Add an apt key via a download
49-
* @param name The name of the key
50-
* @param url The URL of the key
109+
* @param options The options for adding the key
51110
* @returns The file name of the key that was added
52111
*/
53-
export async function addAptKeyViaDownload(name: string, url: string) {
54-
const fileName = `/etc/apt/trusted.gpg.d/${name}`
55-
if (!(await pathExists(fileName))) {
56-
initGpg()
112+
export async function addAptKeyViaURL({ keyUrl, fileName, keyStorePath = defaultKeyStorePath }: KeyUrl) {
113+
try {
114+
assertGpgFileName(fileName)
115+
const filePath = join(keyStorePath, fileName)
116+
if (!(await pathExists(filePath))) {
117+
initGpg()
118+
119+
await installAptPack([{ name: "ca-certificates" }])
120+
121+
const dlPath = join(tmpdir(), fileName)
122+
const dl = new DownloaderHelper(keyUrl, tmpdir(), { fileName })
123+
dl.on("error", (err) => {
124+
throw new Error(`Failed to download ${keyUrl}: ${err}`)
125+
})
126+
await dl.start()
57127

58-
await installAptPack([{ name: "ca-certificates" }])
59-
const dl = new DownloaderHelper(url, tmpdir(), { fileName: name })
60-
dl.on("error", (err) => {
61-
throw new Error(`Failed to download ${url}: ${err}`)
62-
})
63-
await dl.start()
128+
execRootSync("gpg", [
129+
"--no-default-keyring",
130+
"--keyring",
131+
`gnupg-ring:${filePath}`,
132+
"--import",
133+
dlPath,
134+
])
135+
execRootSync("chmod", ["644", filePath])
136+
}
137+
return filePath
138+
} catch (err) {
139+
warning(`Failed to add apt key via download ${keyUrl}: ${err}`)
140+
return undefined
141+
}
142+
}
143+
144+
function initGpg() {
145+
execRootSync("gpg", ["-k"])
146+
}
64147

65-
execRootSync("gpg", ["--no-default-keyring", "--keyring", `gnupg-ring:${fileName}`, "--import", `/tmp/${name}`])
66-
execRootSync("chmod", ["644", fileName])
148+
function assertGpgFileName(fileName: string) {
149+
if (!fileName.endsWith(".gpg")) {
150+
throw new Error(`Key file name must end with .gpg: ${fileName}`)
67151
}
68-
return fileName
69152
}

packages/setup-apt/src/install.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { info, warning } from "ci-log"
33
import escapeRegex from "escape-string-regexp"
44
import { type ExecaError, execa } from "execa"
55
import which from "which"
6-
import { addAptKeyViaServer } from "./apt-key.js"
6+
import { type AddAptKeyOptions, addAptKey } from "./apt-key.js"
77
import { isAptPackInstalled } from "./is-installed.js"
88
import { updateAptRepos } from "./update.js"
99

@@ -40,6 +40,8 @@ export type AptPackage = {
4040
version?: string
4141
/** The repositories to add before installing the package (optional) */
4242
repositories?: string[]
43+
/** The keys to add before installing the package (optional) */
44+
addAptKey?: AddAptKeyOptions[]
4345
}
4446

4547
const retryErrors = [
@@ -83,8 +85,11 @@ export async function installAptPack(packages: AptPackage[], update = false): Pr
8385
didInit = true
8486
}
8587

86-
// Install
8788
try {
89+
// Add the keys if needed
90+
await addAptKeys(packages)
91+
92+
// Install
8893
execRootSync(apt, ["install", "--fix-broken", "-y", ...needToInstall], {
8994
...defaultExecOptions,
9095
env: getAptEnv(apt),
@@ -107,6 +112,14 @@ export async function installAptPack(packages: AptPackage[], update = false): Pr
107112
return { binDir: "/usr/bin/" }
108113
}
109114

115+
async function addAptKeys(packages: AptPackage[]) {
116+
await Promise.all(packages.map(async (pack) => {
117+
if (pack.addAptKey !== undefined) {
118+
await Promise.all(pack.addAptKey.map(addAptKey))
119+
}
120+
}))
121+
}
122+
110123
function isExecaError(err: unknown): err is ExecaError {
111124
return typeof (err as ExecaError).stderr === "string"
112125
}
@@ -285,9 +298,4 @@ async function initApt(apt: string) {
285298
env: getAptEnv(apt),
286299
})
287300
}
288-
289-
await Promise.all([
290-
addAptKeyViaServer(["3B4FE6ACC0B21F32", "40976EAF437D05B5"], "setup-cpp-ubuntu-archive.gpg"),
291-
addAptKeyViaServer(["1E9377A2BA9EF27F"], "launchpad-toolchain.gpg"),
292-
])
293301
}

0 commit comments

Comments
 (0)