Skip to content

Commit c99df21

Browse files
authored
Merge pull request #188 from aminya/llvm [skip ci]
2 parents 912cd9a + 54cbc0f commit c99df21

25 files changed

+222
-143
lines changed

action.yml

+4
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ inputs:
8484
powershell:
8585
description: "The powershell version to install."
8686
required: false
87+
timeout:
88+
description: "The timeout for installation of one tool (in minutes)."
89+
default: "20"
90+
required: false
8791

8892
runs:
8993
using: "node16"

dist/actions/actions_python.0e245fb6.js

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/actions/actions_python.dac7d648.js.map dist/actions/actions_python.0e245fb6.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/actions/actions_python.dac7d648.js

-7
This file was deleted.

dist/actions/setup-cpp.js

+19-17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/actions/setup-cpp.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/legacy/actions_python.30df6221.js

-7
This file was deleted.

dist/legacy/actions_python.cd609164.js

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/legacy/actions_python.30df6221.js.map dist/legacy/actions_python.cd609164.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/legacy/setup-cpp.js

+19-17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/legacy/setup-cpp.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/modern/actions_python.7a34735b.js

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/modern/actions_python.d4cc9106.js.map dist/modern/actions_python.7a34735b.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/modern/actions_python.d4cc9106.js

-7
This file was deleted.

dist/modern/setup-cpp.js

+19-17
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/modern/setup-cpp.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@
112112
"npm-check-updates": "^16.10.17",
113113
"npm-run-all2": "^6.0.6",
114114
"numerous": "1.0.3",
115+
"p-timeout": "^6.1.2",
115116
"parcel": "2.9.3",
116117
"path-exists": "^5.0.0",
117118
"patha": "^0.4.1",

pnpm-lock.yaml

+8
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/__tests__/main.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { syncVersions, getVersion } from "../versions/versions"
22
import { parseArgs } from "../cli-options"
3-
import { Inputs } from "../tool"
43
import { getCompilerInfo } from "../compilers"
4+
import { Inputs } from "../tool"
55

66
jest.setTimeout(300000)
77
describe("getCompilerInfo", () => {

src/cli-options.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Inputs, inputs } from "./tool"
66

77
export function parseArgs(args: string[]): Opts {
88
return mri<Record<Inputs, string | undefined> & { help: boolean }>(args, {
9-
string: inputs,
9+
string: [...inputs, "timeout"],
1010
default: Object.fromEntries(inputs.map((inp) => [inp, maybeGetInput(inp)])),
1111
alias: { h: "help" },
1212
boolean: "help",
@@ -21,9 +21,9 @@ setup-cpp --compiler llvm --cmake true --ninja true --ccache true --vcpkg true
2121
Install all the tools required for building and testing C++/C projects.
2222
2323
--architecture\t the cpu architecture to install the tools for. By default it uses the current CPU architecture.
24+
--timeout\t the timeout for the installation of each tool in minutes. By default it is 10 minutes.
2425
--compiler\t the <compiler> to install.
2526
\t You can specify the version instead of specifying just the name e.g: --compiler 'llvm-13.0.0'
26-
2727
--$tool_name\t pass "true" or pass the <version> you would like to install for this tool. e.g. --conan true or --conan "1.42.1"
2828
2929
All the available tools:
@@ -54,6 +54,7 @@ export function maybeGetInput(key: string) {
5454
export type Opts = mri.Argv<
5555
Record<Inputs, string | undefined> & {
5656
help: boolean
57+
timeout?: string
5758
}
5859
>
5960

src/installTool.ts

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { endGroup, startGroup } from "@actions/core"
2+
import { error } from "ci-log"
3+
import { join } from "patha"
4+
import { getSuccessMessage } from "./cli-options"
5+
import { InstallationInfo } from "./utils/setup/setupBin"
6+
import { setupVCVarsall } from "./vcvarsall/vcvarsall"
7+
import { getVersion } from "./versions/versions"
8+
import pTimeout from "p-timeout"
9+
import { ToolName, setups } from "./tool"
10+
11+
export const DEFAULT_TIMEOUT = 20 * 60 * 1000 // 20 minutes
12+
13+
export async function installTool(
14+
tool: ToolName,
15+
version: string,
16+
osVersion: number[] | null,
17+
arch: string,
18+
setupCppDir: string,
19+
successMessages: string[],
20+
errorMessages: string[],
21+
timeout: number = DEFAULT_TIMEOUT,
22+
) {
23+
startGroup(`Installing ${tool} ${version}`)
24+
let hasLLVM = false
25+
try {
26+
hasLLVM = await pTimeout(installToolImpl(tool, version, osVersion, arch, hasLLVM, setupCppDir, successMessages), {
27+
milliseconds: timeout,
28+
message: `Timeout while installing ${tool} ${version}. You can increase the timeout from options`,
29+
})
30+
} catch (e) {
31+
// push error message to the logger
32+
error(e as string | Error)
33+
errorMessages.push(`${tool} failed to install`)
34+
}
35+
endGroup()
36+
return hasLLVM
37+
}
38+
39+
async function installToolImpl(
40+
tool: ToolName,
41+
version: string,
42+
osVersion: number[] | null,
43+
arch: string,
44+
hasLLVM: boolean,
45+
setupCppDir: string,
46+
successMessages: string[],
47+
) {
48+
let installationInfo: InstallationInfo | undefined | void
49+
if (tool === "vcvarsall") {
50+
// eslint-disable-next-line no-await-in-loop
51+
await setupVCVarsall(getVersion(tool, version, osVersion), undefined, arch, undefined, undefined, false, false)
52+
} else {
53+
// get the setup function
54+
const setupFunction = setups[tool]
55+
56+
// eslint-disable-next-line no-param-reassign
57+
hasLLVM = ["llvm", "clangformat", "clangtidy"].includes(tool)
58+
59+
// the tool installation directory (for the functions that ue it)
60+
const setupDir = join(setupCppDir, hasLLVM ? "llvm" : tool)
61+
62+
// eslint-disable-next-line no-await-in-loop
63+
installationInfo = await setupFunction(getVersion(tool, version, osVersion), setupDir, arch)
64+
}
65+
// preparing a report string
66+
successMessages.push(getSuccessMessage(tool, installationInfo))
67+
return hasLLVM
68+
}

src/llvm/llvm.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ async function setupLLVMWithoutActivation_raw(version: string, setupDir: string,
3535
const setupLLVMWithoutActivation = memoize(setupLLVMWithoutActivation_raw, { isPromise: true })
3636

3737
/** Setup llvm tools (clang tidy, clang format, etc) without activating llvm and using it as the compiler */
38-
export const setupClangTools = setupLLVMWithoutActivation
38+
export function setupClangTools(version: string, setupDir: string, arch: string) {
39+
return setupLLVMOnly(version, setupDir, arch)
40+
}
3941

4042
async function setupLLVMOnly(version: string, setupDir: string, arch: string) {
4143
const coeredVersion = semverCoerceIfInvalid(version)

src/llvm/llvm_installer.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { hasNala, isPackageInstalled, setupAptPack } from "../utils/setup/setupA
55
import { InstallationInfo } from "../utils/setup/setupBin"
66
import { promises } from "fs"
77
import { info } from "console"
8+
import { DEFAULT_TIMEOUT } from "../installTool"
89
const { readFile, writeFile, chmod } = promises
910

1011
export async function setupLLVMApt(majorVersion: number): Promise<InstallationInfo> {
@@ -19,6 +20,7 @@ export async function setupLLVMApt(majorVersion: number): Promise<InstallationIn
1920
await execRoot("bash", ["/tmp/llvm-setup-cpp.sh", `${majorVersion}`, "all"], {
2021
stdio: "inherit",
2122
shell: true,
23+
timeout: DEFAULT_TIMEOUT,
2224
})
2325

2426
await addPath(`${installationFolder}/bin`)
@@ -33,6 +35,7 @@ export async function setupLLVMApt(majorVersion: number): Promise<InstallationIn
3335
async function patchAptLLVMScript(path: string, target_path: string) {
3436
let script = await readFile(path, "utf-8")
3537

38+
script = debugScript(script)
3639
script = nonInteractiveScript(script)
3740
script = await removeConflictingPAckages(script)
3841
script = useNalaScript(script)
@@ -42,9 +45,17 @@ async function patchAptLLVMScript(path: string, target_path: string) {
4245
// the packages needed by the script
4346
return [{ name: "lsb-release" }, { name: "wget" }, { name: "software-properties-common" }, { name: "gnupg" }]
4447
}
45-
function nonInteractiveScript(givenScript: string) {
48+
49+
function debugScript(script: string) {
50+
if (!process.env.NODE_DEBUG) {
51+
return script.replace(/set -eux/g, "set -eu")
52+
}
53+
return script
54+
}
55+
56+
function nonInteractiveScript(script: string) {
4657
// make the scirpt non-interactive and fix broken packages
47-
return givenScript.replace(
58+
return script.replace(
4859
/add-apt-repository "\${REPO_NAME}"/g,
4960
// eslint-disable-next-line no-template-curly-in-string
5061
'add-apt-repository -y "${REPO_NAME}"',

src/main.ts

+32-10
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env node
22
/* eslint-disable node/shebang */
33

4-
import { GITHUB_ACTIONS } from "ci-info"
4+
import { GITHUB_ACTIONS, isCI } from "ci-info"
55
import { error, info, success, warning } from "ci-log"
66
import * as numerous from "numerous"
77
import numerousLocale from "numerous/locales/en.js"
@@ -11,12 +11,13 @@ import { untildifyUser } from "untildify-user"
1111
import { checkUpdates } from "./check-updates"
1212
import { parseArgs, printHelp } from "./cli-options"
1313
import { installCompiler } from "./compilers"
14-
import { installTool, tools } from "./tool"
1514
import { finalizeCpprc } from "./utils/env/addEnv"
1615
import { isArch } from "./utils/env/isArch"
1716
import { ubuntuVersion } from "./utils/env/ubuntu_version"
1817
import { setupPacmanPack } from "./utils/setup/setupPacmanPack"
1918
import { syncVersions } from "./versions/versions"
19+
import { installTool } from "./installTool"
20+
import { tools } from "./tool"
2021

2122
/** The main entry function */
2223
async function main(args: string[]): Promise<number> {
@@ -69,7 +70,17 @@ async function main(args: string[]): Promise<number> {
6970
let hasLLVM = false
7071

7172
// loop over the tools and run their setup function
73+
74+
let failedFast = false
7275
for (const tool of tools) {
76+
// fail fast inside CI when any tool fails
77+
if (isCI) {
78+
if (errorMessages.length !== 0) {
79+
failedFast = true
80+
break
81+
}
82+
}
83+
7384
// get the version or "true" or undefined for this tool from the options
7485
const version = opts[tool]
7586

@@ -78,19 +89,30 @@ async function main(args: string[]): Promise<number> {
7889
// running the setup function for this tool
7990
time1 = Date.now()
8091
// eslint-disable-next-line no-await-in-loop
81-
hasLLVM = await installTool(tool, version, osVersion, arch, setupCppDir, successMessages, errorMessages)
92+
hasLLVM = await installTool(
93+
tool,
94+
version,
95+
osVersion,
96+
arch,
97+
setupCppDir,
98+
successMessages,
99+
errorMessages,
100+
parseFloat(opts.timeout ?? "20") * 60 * 1000,
101+
)
82102
time2 = Date.now()
83103
info(`took ${timeFormatter.format(time1, time2) || "0 seconds"}`)
84104
}
85105
}
86106

87-
// installing the specified compiler
88-
const maybeCompiler = opts.compiler
89-
if (maybeCompiler !== undefined) {
90-
const time1Compiler = Date.now()
91-
await installCompiler(maybeCompiler, osVersion, setupCppDir, arch, successMessages, hasLLVM, errorMessages)
92-
const time2Compiler = Date.now()
93-
info(`took ${timeFormatter.format(time1Compiler, time2Compiler) || "0 seconds"}`)
107+
if (!failedFast) {
108+
// installing the specified compiler
109+
const maybeCompiler = opts.compiler
110+
if (maybeCompiler !== undefined) {
111+
const time1Compiler = Date.now()
112+
await installCompiler(maybeCompiler, osVersion, setupCppDir, arch, successMessages, hasLLVM, errorMessages)
113+
const time2Compiler = Date.now()
114+
info(`took ${timeFormatter.format(time1Compiler, time2Compiler) || "0 seconds"}`)
115+
}
94116
}
95117

96118
await finalizeCpprc()

src/tool.ts

+5-49
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,7 @@
1-
import { endGroup, startGroup } from "@actions/core"
2-
import { error } from "ci-log"
3-
import { join } from "patha"
41
import { setupBazel } from "./bazel/bazel"
52
import { setupBrew } from "./brew/brew"
63
import { setupCcache } from "./ccache/ccache"
74
import { setupChocolatey } from "./chocolatey/chocolatey"
8-
import { getSuccessMessage } from "./cli-options"
95
import { setupCmake } from "./cmake/cmake"
106
import { setupConan } from "./conan/conan"
117
import { setupCppcheck } from "./cppcheck/cppcheck"
@@ -26,50 +22,10 @@ import { setupPython } from "./python/python"
2622
import { setupSccache } from "./sccache/sccache"
2723
import { setupSevenZip } from "./sevenzip/sevenzip"
2824
import { setupTask } from "./task/task"
29-
import { InstallationInfo } from "./utils/setup/setupBin"
3025
import { setupVcpkg } from "./vcpkg/vcpkg"
3126
import { setupVCVarsall } from "./vcvarsall/vcvarsall"
32-
import { getVersion } from "./versions/versions"
33-
34-
export async function installTool(
35-
tool: ToolName,
36-
version: string,
37-
osVersion: number[] | null,
38-
arch: string,
39-
setupCppDir: string,
40-
successMessages: string[],
41-
errorMessages: string[],
42-
) {
43-
startGroup(`Installing ${tool} ${version}`)
44-
let hasLLVM = false
45-
try {
46-
let installationInfo: InstallationInfo | undefined | void
47-
if (tool === "vcvarsall") {
48-
// eslint-disable-next-line no-await-in-loop
49-
await setupVCVarsall(getVersion(tool, version, osVersion), undefined, arch, undefined, undefined, false, false)
50-
} else {
51-
// get the setup function
52-
const setupFunction = setups[tool]
53-
54-
hasLLVM = ["llvm", "clangformat", "clangtidy"].includes(tool)
55-
56-
// the tool installation directory (for the functions that ue it)
57-
const setupDir = join(setupCppDir, hasLLVM ? "llvm" : tool)
58-
59-
// eslint-disable-next-line no-await-in-loop
60-
installationInfo = await setupFunction(getVersion(tool, version, osVersion), setupDir, arch)
61-
}
62-
// preparing a report string
63-
successMessages.push(getSuccessMessage(tool, installationInfo))
64-
} catch (e) {
65-
// push error message to the logger
66-
error(e as string | Error)
67-
errorMessages.push(`${tool} failed to install`)
68-
}
69-
endGroup()
70-
return hasLLVM
71-
} /** The setup functions */
7227

28+
/** The setup functions */
7329
export const setups = {
7430
nala: setupNala,
7531
cmake: setupCmake,
@@ -102,12 +58,12 @@ export const setups = {
10258
}
10359

10460
export type ToolName = keyof typeof setups
105-
/** The tools that can be installed */
10661

62+
/** The tools that can be installed */
10763
export const tools = Object.keys(setups) as Array<ToolName>
64+
10865
/** The possible inputs to the program */
66+
export type Inputs = keyof typeof setups | "compiler" | "architecture" | "timeout"
10967

110-
export type Inputs = keyof typeof setups | "compiler" | "architecture"
11168
/** ‌ an array of possible inputs */
112-
113-
export const inputs: Array<Inputs> = ["compiler", "architecture", ...tools]
69+
export const inputs: Array<Inputs> = ["compiler", "architecture", "timeout", ...tools]

0 commit comments

Comments
 (0)