Skip to content

Commit fd2c1df

Browse files
authored
Merge pull request #350 from aminya/install-tool [skip ci]
feat: install setup-cpp CLI in GitHub Actions
2 parents 4136222 + 43d46ef commit fd2c1df

File tree

10 files changed

+108
-38
lines changed

10 files changed

+108
-38
lines changed

.github/workflows/CI.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ jobs:
200200
uses: actions/setup-node@v4
201201
with:
202202
node-version: 20
203+
203204
- name: Smoke Test Modern Bundle
204205
if: ${{ !contains(github.event.head_commit.message, '[skip test]') }}
205206
run: |
@@ -208,6 +209,11 @@ jobs:
208209
env:
209210
RUNNER_OS_NAME: ${{ matrix.os }}
210211

212+
- name: Smoke Test Global Install
213+
if: ${{ !contains(github.event.head_commit.message, '[skip test]') }}
214+
run: |
215+
setup-cpp --help
216+
211217
- name: Setup Node 12
212218
if: ${{ !contains(matrix.os, 'macos-14') && !contains(matrix.os, 'macos-15') }}
213219
uses: actions/setup-node@v4

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Setting up a **cross-platform** environment for building and testing C++/C proje
3131
| --------------- | ----------------------------------------------------------------------------------------------------------- |
3232
| compiler | llvm, gcc, msvc, apple-clang, vcvarsall |
3333
| build system | cmake, ninja, meson, make, task, bazel |
34-
| package manager | vcpkg, conan, choco, brew, nala |
34+
| package manager | vcpkg, conan, choco, brew, nala, setup-cpp |
3535
| analyzer/linter | clang-tidy, clang-format, cppcheck, cpplint, flawfinder, lizard, infer, cmakelang, cmake-format, cmake-lint |
3636
| cache | ccache, sccache |
3737
| documentation | doxygen, graphviz |
@@ -195,6 +195,19 @@ jobs:
195195
cppcheck: true # instead of `true`, which chooses the default version, you can pass a specific version.
196196
```
197197
198+
When using the `setup-cpp` action in GitHub Actions, by default it will also install the `setup-cpp` CLI, which you can use in the subsequent commands. You can modify the default behaviour if needed.
199+
200+
```yaml
201+
- name: Setup Cpp
202+
uses: aminya/setup-cpp@v1
203+
with:
204+
setup-cpp: true
205+
node-package-manager: "npm"
206+
207+
- name: Use Setup Cpp CLI
208+
run: setup-cpp --compiler llvm --cmake true --ninja true --ccache true --vcpkg true
209+
```
210+
198211
### Prebuilt Docker Images
199212

200213
To provide fast development environments, `setup-cpp` provides several prebuilt docker images that have the tools you need. You can use these images as a base image for your project.

action.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,12 @@ inputs:
157157
python:
158158
description: "Wether to install python (true/false) or the specific version to install."
159159
required: false
160+
setup-cpp:
161+
description: "Wether to install setup-cpp (true/false) or the specific version to install. (Default to the current version called by the action)"
162+
required: false
163+
node-package-manager:
164+
description: "The node package manager to use (npm/yarn/pnpm) when installing setup-cpp globally"
165+
required: false
160166

161167
runs:
162168
using: "node20"

dist/legacy/setup-cpp.js

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.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.mjs

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

dist/modern/setup-cpp.mjs.map

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/cli-options.ts

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import { type Inputs, inputs } from "./tool.js"
66
import type { InstallationInfo } from "./utils/setup/setupBin.js"
77

88
export function parseArgs(args: string[]): Opts {
9-
return mri<Record<Inputs, string | undefined> & { help: boolean }>(args, {
10-
string: [...inputs, "timeout"],
11-
default: Object.fromEntries(inputs.map((inp) => [inp, maybeGetInput(inp)])),
12-
alias: { h: "help" },
13-
boolean: "help",
9+
const defaults = Object.fromEntries(inputs.map((inp) => [inp, maybeGetInput(inp)]))
10+
return mri<Record<Inputs, string | undefined> & { help: boolean; version: boolean; "setup-cpp": boolean }>(args, {
11+
string: [...inputs, "timeout", "node-package-manager"],
12+
default: defaults,
13+
alias: { h: "help", v: "version" },
14+
boolean: ["help", "version", "setup-cpp"],
1415
})
1516
}
1617

@@ -25,7 +26,10 @@ Install all the tools required for building and testing C++/C projects.
2526
--timeout\t the timeout for the installation of each tool in minutes. By default it is 10 minutes.
2627
--compiler\t the <compiler> to install.
2728
\t You can specify the version instead of specifying just the name e.g: --compiler 'llvm-13.0.0'
28-
--$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"
29+
--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"
30+
--nodePackageManager\t the node package manager to use (npm/yarn/pnpm) when installing setup-cpp globally
31+
--help\t show this help message
32+
--version\t show the version of setup-cpp
2933
3034
All the available tools:
3135
`)
@@ -38,7 +42,7 @@ All the available tools:
3842
"build system": {
3943
tools: "--cmake, --ninja, --meson, --make, --task, --bazel",
4044
},
41-
"package manager": { tools: "--vcpkg, --conan, --choco, --brew, --nala" },
45+
"package manager": { tools: "--vcpkg, --conan, --choco, --brew, --nala, --setup-cpp" },
4246
"analyzer/linter": {
4347
tools:
4448
"--clang-tidy, --clang-format, --cppcheck, --cpplint, --flawfinder, --lizard, --infer, , --cmakelang, --cmake-lint, --cmake-format",
@@ -63,7 +67,10 @@ export function maybeGetInput(key: string) {
6367
export type Opts = mri.Argv<
6468
Record<Inputs, string | undefined> & {
6569
help: boolean
70+
version: boolean
71+
"setup-cpp"?: boolean
6672
timeout?: string
73+
"node-package-manager"?: string
6774
}
6875
>
6976

src/setup-cpp-installer.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { error, info } from "ci-log"
2+
import { execa } from "execa"
3+
import which from "which"
4+
/**
5+
* Install the setup-cpp CLI globally
6+
* @param version - The version of setup-cpp to install
7+
* @param packageManager - The package manager to use
8+
*/
9+
export async function installSetupCpp(version: string, packageManager: string = "npm") {
10+
try {
11+
// check if `setup-cpp` is available in the shell, if so, skip the installation to avoid overwriting the existing version
12+
const setupCppPath = await which("setup-cpp", { nothrow: true })
13+
if (setupCppPath !== null) {
14+
return
15+
}
16+
17+
// Install setup-cpp globally
18+
info(`Installing setup-cpp@${version} via ${packageManager}...`)
19+
await execa(packageManager, ["install", "-g", `setup-cpp@${version}`], {
20+
stdio: "inherit",
21+
// 1 minutes timeout
22+
timeout: 1000 * 60 * 1,
23+
})
24+
} catch (err) {
25+
error(`Failed to install the setup-cpp@${version} CLI: ${err}. Ignoring...`)
26+
}
27+
}

src/setup-cpp.ts

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ import numerousLocale from "numerous/locales/en.js"
99
import timeDelta from "time-delta"
1010
import timeDeltaLocale from "time-delta/locales/en.js"
1111
import { untildifyUser } from "untildify-user"
12+
import packageJson from "../package-version.json"
1213
import { checkUpdates } from "./check-updates.js"
1314
import { parseArgs, printHelp, rcOptions } from "./cli-options.js"
1415
import { getCompilerInfo, installCompiler } from "./compilers.js"
1516
import { installTool } from "./installTool.js"
17+
import { installSetupCpp } from "./setup-cpp-installer.js"
1618
import { type Inputs, llvmTools, tools } from "./tool.js"
1719
import { isArch } from "./utils/env/isArch.js"
1820
import { ubuntuVersion } from "./utils/env/ubuntu_version.js"
@@ -21,11 +23,7 @@ import { syncVersions } from "./versions/versions.js"
2123

2224
/** The main entry function */
2325
async function main(args: string[]): Promise<number> {
24-
let checkUpdatePromise = Promise.resolve()
25-
if (!GITHUB_ACTIONS) {
26-
checkUpdatePromise = checkUpdates()
27-
process.env.ACTIONS_ALLOW_UNSECURE_COMMANDS = "true"
28-
}
26+
const checkUpdatePromise = GITHUB_ACTIONS ? Promise.resolve() : checkUpdates()
2927

3028
// parse options using mri or github actions
3129
const opts = parseArgs(args)
@@ -35,6 +33,11 @@ async function main(args: string[]): Promise<number> {
3533
printHelp()
3634
}
3735

36+
// print version
37+
if (opts.version) {
38+
info(`${packageJson.version}`)
39+
}
40+
3841
// cpu architecture
3942
const arch = opts.architecture ?? process.arch
4043

@@ -122,11 +125,20 @@ async function main(args: string[]): Promise<number> {
122125

123126
await finalizeRC(rcOptions)
124127

125-
if (successMessages.length === 0 && errorMessages.length === 0) {
126-
warning("setup-cpp was called without any arguments. Nothing to do.")
127-
return 0
128+
const noTool = successMessages.length === 0 && errorMessages.length === 0
129+
130+
// if setup-cpp option is not passed, install setup-cpp by default unless only help or version is passed
131+
// So that --help and --version are immutable
132+
if (opts["setup-cpp"] === undefined) {
133+
opts["setup-cpp"] = !(noTool && (opts.version || opts.help))
128134
}
129135

136+
const installSetupCppPromise = opts["setup-cpp"]
137+
? installSetupCpp(packageJson.version, opts["node-package-manager"])
138+
: Promise.resolve()
139+
140+
await Promise.all([checkUpdatePromise, installSetupCppPromise])
141+
130142
// report the messages in the end
131143
for (const tool of successMessages) {
132144
success(tool)
@@ -135,27 +147,26 @@ async function main(args: string[]): Promise<number> {
135147
error(tool)
136148
}
137149

138-
info("setup-cpp finished")
139-
140-
if (!GITHUB_ACTIONS) {
141-
switch (process.platform) {
142-
case "win32": {
143-
warning("Run `RefreshEnv.cmd` or restart your shell to update the environment.")
144-
break
145-
}
146-
case "linux":
147-
case "darwin": {
148-
warning("Run `source ~/.cpprc` or restart your shell to update the environment.")
149-
break
150-
}
151-
default: {
152-
// nothing
150+
if (successMessages.length !== 0 || errorMessages.length !== 0) {
151+
info("setup-cpp finished")
152+
153+
if (!GITHUB_ACTIONS) {
154+
switch (process.platform) {
155+
case "win32": {
156+
warning("Run `RefreshEnv.cmd` or restart your shell to update the environment.")
157+
break
158+
}
159+
case "linux":
160+
case "darwin": {
161+
warning("Run `source ~/.cpprc` or restart your shell to update the environment.")
162+
break
163+
}
164+
default: {
165+
// nothing
166+
}
153167
}
154168
}
155169
}
156-
157-
await checkUpdatePromise
158-
159170
return errorMessages.length === 0 ? 0 : 1 // exit with non-zero if any error message
160171
}
161172

0 commit comments

Comments
 (0)