Merge pull request #258 from aminya/packages

This commit is contained in:
Amin Yahyaabadi 2024-08-16 02:39:36 -07:00 committed by GitHub
commit a4b28aacb7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
146 changed files with 2514 additions and 1622 deletions

View File

@ -22,24 +22,14 @@ jobs:
fail-fast: false
matrix:
os:
- ubuntu-24.04
- ubuntu-22.04
node:
- 22
- 22.6.0
pnpm:
- 9
- 9.6.0
steps:
- uses: actions/checkout@v4
- name: Cache
uses: actions/cache@v4
with:
path: |
~/.pnpm-store
D:\.pnpm-store
key: "setupcpp-cache-OS:${{ matrix.os }}-node:${{ matrix.node }}-pnpm:${{ matrix.pnpm }}-${{ hashFiles('./.npmrc') }}-deps:${{ hashFiles('./package.json') }}"
restore-keys: |
"setupcpp-cache-OS:${{ matrix.os }}-"
- name: Setup Node
uses: actions/setup-node@v4
with:

1
.gitignore vendored
View File

@ -19,3 +19,4 @@ exe/
.cache/
coverage
.turbo

3
.npmrc
View File

@ -1,5 +1,2 @@
package-lock=false
lockfile=true
node-linker=hoisted
prefer-frozen-lockfile=true
side-effects-cache=true

View File

@ -66,6 +66,7 @@
"files.insertFinalNewline": true,
"files.trimFinalNewlines": true,
"hadolint.hadolintPath": "./target/bin/hadolint",
// use dprint instead
"prettier.enable": false
"prettier.enable": false,
"javascript.preferences.importModuleSpecifierEnding": "js",
"typescript.preferences.importModuleSpecifierEnding": "js"
}

View File

@ -1,51 +1,54 @@
{
"$schema": "https://biomejs.dev/schemas/1.7.3/schema.json",
"files": {
"ignore": [
"**/node_modules/**",
"**/.pnpm-store/**",
"**/dist/**",
"dev/cpp_vcpkg_project/**/*",
"**/.venv/",
"**/.*cache/",
"**/coverage/"
],
"ignoreUnknown": true
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"style": {
"noInferrableTypes": "off",
"noUselessElse": "off",
"noNonNullAssertion": "off",
"useNodejsImportProtocol": "off"
},
"complexity": {
"useLiteralKeys": "off"
},
"suspicious": {
"noConfusingVoidType": "off"
}
}
},
"formatter": {
"enabled": false,
"indentWidth": 4,
"indentStyle": "space"
},
"json": {
"formatter": {
"enabled": false,
"trailingCommas": "none"
},
"parser": {
"allowComments": true,
"allowTrailingCommas": true
}
"$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
"files": {
"ignore": [
"**/node_modules/**",
"**/.pnpm-store/**",
"**/dist/**",
"dev/cpp_vcpkg_project/**/*",
"**/.venv/",
"**/.*cache/",
"**/coverage/"
],
"ignoreUnknown": true
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"style": {
"noInferrableTypes": "off",
"noUselessElse": "off",
"noNonNullAssertion": "off",
"useNodejsImportProtocol": "off"
},
"complexity": {
"useLiteralKeys": "off"
},
"suspicious": {
"noConfusingVoidType": "off"
},
"nursery": {
"useImportExtensions": "warn"
}
}
},
"formatter": {
"enabled": false,
"indentWidth": 4,
"indentStyle": "space"
},
"json": {
"formatter": {
"enabled": false,
"trailingCommas": "none"
},
"parser": {
"allowComments": true,
"allowTrailingCommas": true
}
}
}

View File

@ -25,6 +25,7 @@ words:
- choco
- clangd
- cmake
- iarna
- cobertura
- copr
- CPATH

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

1
dist/actions/hdi.647acde1.js.map vendored Normal file

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

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

1
dist/legacy/hdi.619de66c.js.map vendored Normal file

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

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

1
dist/modern/hdi.647acde1.js.map vendored Normal file

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

@ -11,7 +11,9 @@
"module.sortImportDeclarations": "maintain",
"importDeclaration.sortNamedImports": "maintain"
},
"json": {},
"json": {
"trailingCommas": "never"
},
"markdown": {},
"dockerfile": {},
"exec": {
@ -26,7 +28,7 @@
]
},
"includes": [
"**/*{.ts,.tsx,.mts,.cts,.js,.jsx,.cjs,.mjs,.json,.md,.yaml,.yml,.dockerfile}"
"**/*{.ts,.tsx,.mts,.cts,.js,.jsx,.cjs,.mjs,.json,.jsonc,.md,.yaml,.yml,.dockerfile}"
],
"excludes": [
"**/node_modules",

View File

@ -8,6 +8,10 @@ const jestConfig: Config = {
transform: {
"^.+\\.(t|j)sx?$": "@swc/jest",
},
// resolve js files from ts files
moduleNameMapper: {
"(.+)\\.js": "$1",
},
// coverage
collectCoverageFrom: ["src/**/*.{ts,tsx,js,jsx}"],
coveragePathIgnorePatterns: ["assets", ".css.d.ts"],

7
lefthook.yml Normal file
View File

@ -0,0 +1,7 @@
pre-commit:
parallel: false
commands:
test.lint:
run: pnpm run test.lint
build:
run: pnpm run clean && pnpm i && pnpm run build -- --no-color && git add ./dist

View File

@ -27,28 +27,29 @@
"tsconfig.json"
],
"scripts": {
"build": "run-s clean build.packages && run-p lint.tsc build.parcel copy.matchers",
"build.packages": "pnpm run -r build",
"build.parcel": "cross-env NODE_ENV=production parcel build && run-s build.babel && shx cp -r ./dist/actions/* ./dist/modern",
"build": "turbo build && run-p lint.root.tsc build.parcel copy.matchers && run-s build.babel build.modern",
"build.parcel": "cross-env NODE_ENV=production parcel build",
"build.babel": "babel ./dist --out-dir dist --plugins @upleveled/babel-plugin-remove-node-prefix --plugins @babel/plugin-transform-private-methods --compact --no-babelrc --source-maps true",
"build.modern": "shx cp -r ./dist/actions/* ./dist/modern",
"bump": "ncu -u -x numerous,execa,prettier,@types/node,eslint,@types/eslint && pnpm update && pnpx typesync && pnpm run clean",
"clean": "shx rm -rf ./dist ./exe ./packages/*/dist/ ./.parcel-cache && shx mkdir -p ./dist/legacy ./dist/actions ./dist/modern ",
"clean": "shx rm -rf ./dist ./exe ./.parcel-cache && shx mkdir -p ./dist/legacy ./dist/actions ./dist/modern ",
"copy.matchers": "run-p copy.matchers.legacy copy.matchers.actions",
"copy.matchers.legacy": "shx cp ./src/gcc/gcc_matcher.json ./dist/legacy/ && shx cp ./src/msvc/msvc_matcher.json ./dist/legacy/ && shx cp ./src/python/python_matcher.json ./dist/legacy/ && shx cp ./src/llvm/llvm_matcher.json ./dist/legacy/",
"copy.matchers.actions": "shx cp ./src/gcc/gcc_matcher.json ./dist/actions/ && shx cp ./src/msvc/msvc_matcher.json ./dist/actions/ && shx cp ./src/python/python_matcher.json ./dist/actions/ && shx cp ./src/llvm/llvm_matcher.json ./dist/actions/",
"dev": "cross-env NODE_ENV=development parcel watch",
"docs": "shx rm -rf packages/*/README.md && pnpm -r exec readme --path ../../dev/readme/template.md -y && pnpm -r exec ts-readme",
"format": "run-s lint.dprint",
"lint": "run-p --aggregate-output --continue-on-error lint.cspell lint.eslint lint.dprint lint.tsc lint.biome",
"lint": "turbo lint && run-p --aggregate-output --continue-on-error lint.**",
"lint.cspell": "cspell lint --no-progress --show-suggestions --cache --cache-location ./.cache/cspell/.cspellcache",
"lint.eslint": "eslint **/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/ --fix",
"lint.biome": "biome check --write --unsafe",
"lint.dprint": "dprint fmt",
"lint.tsc": "tsc --noEmit --pretty",
"lint.root.tsc": "tsc --noEmit --pretty",
"lint.root.eslint": "eslint ./{src,dev}/**/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/ --fix",
"pack.exe": "shx rm -rf ./dist/tsconfig.tsbuildinfo && node ./dev/scripts/pack-exe.mjs",
"prepublishOnly": "rm ./dist/tsconfig.tsbuildinfo",
"test.lint": "run-p --aggregate-output --continue-on-error lint.cspell test.lint.eslint test.lint.dprint lint.tsc test.lint.biome",
"test.lint.eslint": "eslint **/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/",
"publish.all": "pnpm -r publish && pnpm publish",
"prepublishOnly": "run-s build && shx rm ./dist/tsconfig.tsbuildinfo",
"test.lint": "run-p --aggregate-output --continue-on-error test.lint.** lint.cspell lint.root.tsc",
"test.lint.root.eslint": "eslint ./{src,dev}/**/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/",
"test.lint.biome": "biome check",
"test.lint.dprint": "dprint check",
"test": "jest --runInBand --forceExit --coverage",
@ -57,15 +58,18 @@
"devDependencies": {
"@actions/core": "^1.10.1",
"@actions/exec": "^1.1.1",
"@actions/http-client": "^2.2.1",
"@actions/io": "^1.1.3",
"@actions/tool-cache": "^2.0.1",
"@babel/cli": "^7.24.8",
"@babel/plugin-transform-private-methods": "^7.24.7",
"@biomejs/biome": "^1.8.3",
"@iarna/toml": "^2.2.5",
"@shockpkg/archive-files": "github:aminya/archive-files#54ec59fad46aca736ac6feb6c7bb526528141b9d",
"@swc/jest": "^0.2.36",
"@types/cross-spawn": "^6.0.6",
"@types/eslint": "^8.56.11",
"@types/iarna__toml": "~2.0.5",
"@types/jest": "^29.5.12",
"@types/node": "^12.20.55",
"@types/semver": "^7.5.8",
@ -77,26 +81,29 @@
"ci-log": "workspace:*",
"cross-env": "7.0.3",
"cross-spawn": "^7.0.3",
"cspell": "^8.13.1",
"cspell": "^8.13.3",
"diagnostics_channel": "^1.1.0",
"dprint": "^0.47.2",
"escape-path-with-spaces": "^1.0.2",
"escape-quotes": "^1.0.2",
"escape-string-regexp": "^5.0.0",
"setup-apt": "workspace:*",
"eslint": "^8.57.0",
"eslint-config-atomic": "^1.22.0",
"eslint-config-atomic": "^1.22.1",
"exec-powershell": "workspace:*",
"execa": "^7.2.0",
"is-url-online": "^1.5.0",
"jest": "^29.7.0",
"lefthook": "^1.7.12",
"macos-release": "^3.3.0",
"micro-memoize": "^4.1.2",
"mkdirp": "^3.0.1",
"mri": "^1.2.0",
"msvc-dev-cmd": "github:aminya/msvc-dev-cmd#c01f519bd995460228ed3dec4df51df92dc290fd",
"npm-check-updates": "^17.0.3",
"npm-check-updates": "^17.0.6",
"npm-run-all2": "^6.2.2",
"numerous": "1.0.3",
"os-env": "workspace:*",
"p-timeout": "^6.1.2",
"parcel": "2.12.0",
"path-exists": "^5.0.0",
@ -113,6 +120,7 @@
"time-delta": "github:aminya/time-delta#69d91a41cef28e569be9a2991129f5f7d1f0d00e",
"ts-node": "^10.9.2",
"ts-readme": "^1.1.3",
"turbo": "2.0.14",
"typescript": "^5.5.4",
"ubuntu-version": "^2.0.0",
"untildify-user": "workspace:*",
@ -123,11 +131,14 @@
"productionDependencies": [
"@actions/core",
"@actions/exec",
"@actions/http-client",
"@actions/io",
"@actions/tool-cache",
"@iarna/toml",
"admina",
"ci-info",
"ci-log",
"diagnostics_channel",
"escape-path-with-spaces",
"escape-quotes",
"escape-string-regexp",
@ -138,23 +149,28 @@
"mri",
"msvc-dev-cmd",
"numerous",
"os-env",
"path-exists",
"patha",
"retry-as-promised",
"semver",
"setup-apt",
"setup-python",
"simple-update-notifier",
"time-delta",
"ubuntu-version",
"untildify-user",
"web-streams-polyfill",
"util.types",
"diagnostics_channel"
"web-streams-polyfill"
],
"engines": {
"node": ">=12.x",
"pnpm": "^9"
},
"packageManager": "pnpm@9.6.0",
"workspaces": [
"packages/*"
],
"keywords": [
"github-actions",
"actions",

View File

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json"
}

View File

@ -2,13 +2,17 @@
"name": "ci-log",
"version": "1.0.0",
"description": "Colorful logging and print for any environment including GitHub Actions",
"homepage": "https://github.com/aminya/setup-cpp",
"repository": "https://github.com/aminya/setup-cpp",
"homepage": "https://github.com/aminya/setup-cpp/tree/master/packages/ci-log",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc"
"build": "tsc --pretty",
"lint.tsc": "tsc --noEmit --pretty",
"lint.eslint": "eslint **/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/ --fix",
"prepublishOnly": "pnpm run build"
},
"dependencies": {
"@actions/core": "^1.10.1",

View File

@ -1,7 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
"outDir": "./dist",
"noEmit": false,
"allowImportingTsExtensions": false
},
"include": ["./src"]
}

View File

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json"
}

View File

@ -2,17 +2,22 @@
"name": "exec-powershell",
"version": "1.0.0",
"description": "Run a powershell command.",
"homepage": "https://github.com/aminya/setup-cpp",
"repository": "https://github.com/aminya/setup-cpp",
"homepage": "https://github.com/aminya/setup-cpp/tree/master/packages/exec-powershell",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc"
"build": "tsc --pretty",
"lint.tsc": "tsc --noEmit --pretty",
"lint.eslint": "eslint **/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/ --fix",
"prepublishOnly": "pnpm run build"
},
"dependencies": {
"execa": "<8",
"which": "^4.0.0"
"execa": "^7",
"which": "^4.0.0",
"@types/node": "^14"
},
"devDependencies": {
"@types/which": "^3.0.0"

View File

@ -1,7 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
"outDir": "./dist",
"noEmit": false,
"allowImportingTsExtensions": false
},
"include": ["./src"]
}

View File

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json"
}

87
packages/os-env/README.md Normal file
View File

@ -0,0 +1,87 @@
<h1 align="center">os-env</h1>
<p>
<img alt="Version" src="https://img.shields.io/badge/version-1.0.0-blue.svg?cacheSeconds=2592000" />
<img src="https://img.shields.io/badge/node-%3E%3D12-blue.svg" />
<a href="#" target="_blank">
<img alt="License: Apache--2.0" src="https://img.shields.io/badge/License-Apache--2.0-yellow.svg" />
</a>
</p>
> Manage environment variables, PATH, and rc files
## Install
```sh
npm install --save os-env
```
## Usage
<!-- INSERT GENERATED DOCS START -->
### `defaultRcPath` (variable)
### `RcOptions` (type)
### `sourceRCInRc` (variable)
handles adding conditions to source rc file from .bashrc and .profile
### `finalizeRC` (function)
**Parameters:**
- rcOptions (`RcOptions`)
**returns:** Promise<void>
### `escapeString` (function)
Escape a string for use in a shell command
**Parameters:**
- valGiven (`string`) - The string to escape
- shouldEscapeSpace (`boolean`) - Whether to escape spaces in the string
**returns:** any
### `AddEnvOptions` (type)
### `addEnv` (function)
Add an environment variable.
This function is cross-platforms and works in all the local or CI systems.
**Parameters:**
- name (`string`)
- valGiven (`string`)
- givenOptions (`Partial<AddEnvOptions>`)
**returns:** Promise<void>
### `addPath` (function)
Add a path to the PATH environment variable.
This function is cross-platforms and works in all the local or CI systems.
**Parameters:**
- path (`string`)
- givenOptions (`Partial<AddPathOptions>`)
**returns:** Promise<void>
<!-- INSERT GENERATED DOCS END -->
## 🤝 Contributing
You can sponsor my work here:
https://github.com/sponsors/aminya
Pull requests, issues and feature requests are welcome.
See the [Contributing guide](https://github.com/aminya/setup-cpp/blob/master/CONTRIBUTING.md).

View File

@ -0,0 +1,47 @@
{
"name": "os-env",
"version": "1.0.0",
"description": "Manage environment variables, PATH, and rc files",
"repository": "https://github.com/aminya/setup-cpp",
"homepage": "https://github.com/aminya/setup-cpp/tree/master/packages/os-env",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc --pretty",
"lint.tsc": "tsc --noEmit --pretty",
"lint.eslint": "eslint **/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/ --fix",
"prepublishOnly": "pnpm run build"
},
"dependencies": {
"@actions/core": "^1.10.1",
"@types/node": "^12",
"admina": "^1.0.1",
"ci-info": "^4.0.0",
"escape-path-with-spaces": "^1.0.2",
"escape-quotes": "^1.0.2",
"micro-memoize": "^4.1.2",
"path-exists": "^5.0.0",
"ci-log": "workspace:*",
"exec-powershell": "workspace:*",
"untildify-user": "workspace:*"
},
"engines": {
"node": ">=12"
},
"keywords": [
"env",
"path",
"dotenv",
"rc",
"addEnv",
"addPath",
"setEnv",
"linux",
"windows",
"unix",
"macos"
],
"devDependencies": {}
}

View File

@ -0,0 +1,98 @@
import { promises } from "fs"
import { exportVariable as ghExportVariable } from "@actions/core"
import { GITHUB_ACTIONS } from "ci-info"
import { error, info } from "ci-log"
import { execPowershell } from "exec-powershell"
import { defaultRcPath, sourceRCInRc } from "./rc-file.js"
import { escapeString } from "./utils.js"
const { appendFile } = promises
/**
* The options for adding an environment variable
*/
export type AddEnvOptions = {
/** If true, the value will be escaped with quotes and spaces will be escaped with backslash */
escapeSpace: boolean
/** If false, the variable will be only added if it is not already defined (Default to true) */
overwrite: boolean
/**
* The path to the RC file that the env variables should be added to.
*/
rcPath: string
/** Provide a name (your tool) to add a variable guard for sourcing your rc file */
guard?: string
}
/**
* Add an environment variable.
*
* This function is cross-platforms and works in all the local or CI systems.
*/
export async function addEnv(
name: string,
valGiven: string | undefined,
givenOptions: Partial<AddEnvOptions> = {},
) {
const options = {
escapeSpace: false,
overwrite: true,
rcPath: defaultRcPath,
...givenOptions,
}
const val = escapeString(valGiven ?? "", options.escapeSpace)
try {
if (GITHUB_ACTIONS) {
try {
if (!options.overwrite) {
if (process.env[name] !== undefined) {
info(`Environment variable ${name} is already defined. Skipping.`)
return
}
}
ghExportVariable(name, val)
} catch (err) {
error(err as Error)
await addEnvSystem(name, val, options)
}
} else {
await addEnvSystem(name, val, options)
}
} catch (err) {
error(`${err}\nFailed to export environment variable ${name}=${val}. You should add it manually.`)
}
}
async function addEnvSystem(name: string, valGiven: string | undefined, options: AddEnvOptions) {
const val = valGiven ?? ""
switch (process.platform) {
case "win32": {
if (!options.overwrite) {
if (process.env[name] !== undefined) {
info(`Environment variable ${name} is already defined. Skipping.`)
return
}
}
// We do not use `execaSync(`setx PATH "${path};%PATH%"`)` because of its character limit
await execPowershell(`[Environment]::SetEnvironmentVariable('${name}', '${val}', "User")`)
info(`${name}='${val}' was set in the environment.`)
return
}
case "linux":
case "darwin": {
await sourceRCInRc(options)
if (!options.overwrite) {
await appendFile(options.rcPath, `\nif [ -z "\${${name}}" ]; then export ${name}="${val}"; fi\n`)
info(`if not defined ${name} then ${name}="${val}" was added to "${options.rcPath}`)
} else {
await appendFile(options.rcPath, `\nexport ${name}="${val}"\n`)
info(`${name}="${val}" was added to "${options.rcPath}`)
}
return
}
default: {
// fall through shell path modification
}
}
process.env[name] = val
}

View File

@ -0,0 +1,83 @@
import { promises } from "fs"
import { delimiter } from "path"
import { addPath as ghAddPath } from "@actions/core"
import { GITHUB_ACTIONS } from "ci-info"
import { error, info } from "ci-log"
import { execPowershell } from "exec-powershell"
import { defaultRcPath, sourceRCInRc } from "./rc-file.js"
const { appendFile } = promises
/**
* The options for adding a PATH variable
*/
type AddPathOptions = {
/**
* The path to the RC file that the PATH variables should be added to.
*/
rcPath: string
/** Provide a name (your tool) to add a variable guard for sourcing your rc file */
guard?: string
}
/**
* Add a path to the PATH environment variable.
*
* This function is cross-platforms and works in all the local or CI systems.
*/
export async function addPath(path: string, givenOptions: Partial<AddPathOptions> = {}) {
const options = { rcPath: defaultRcPath, ...givenOptions }
if (isIgnoredPath(path)) {
return
}
process.env.PATH = `${path}${delimiter}${process.env.PATH}`
try {
if (GITHUB_ACTIONS) {
try {
ghAddPath(path)
} catch (err) {
error(err as Error)
await addPathSystem(path, options)
}
} else {
await addPathSystem(path, options)
}
} catch (err) {
error(`${err}\nFailed to add ${path} to the percistent PATH. You should add it manually.`)
}
}
async function addPathSystem(path: string, options: AddPathOptions) {
switch (process.platform) {
case "win32": {
// We do not use `execaSync(`setx PATH "${path};%PATH%"`)` because of its character limit and also because %PATH% is different for user and system
await execPowershell(
`$USER_PATH=([Environment]::GetEnvironmentVariable("PATH", "User")); [Environment]::SetEnvironmentVariable("PATH", "${path};$USER_PATH", "User")`,
)
info(`"${path}" was added to the PATH.`)
return
}
case "linux":
case "darwin": {
await sourceRCInRc(options)
await appendFile(options.rcPath, `\nexport PATH="${path}:$PATH"\n`)
info(`"${path}" was added to "${options.rcPath}"`)
return
}
default: {
return
}
}
}
const ignoredPaths = [/\/usr\/bin\/?/, /\/usr\/local\/bin\/?/]
/** Skip adding /usr/bin to PATH if it is already there */
function isIgnoredPath(path: string) {
if (ignoredPaths.some((checkedPath) => checkedPath.test(path))) {
const paths = process.env.PATH?.split(delimiter) ?? []
return paths.includes(path)
}
return false
}

17
packages/os-env/src/escape-quotes.d.ts vendored Normal file
View File

@ -0,0 +1,17 @@
declare module "escape-quotes" {
/**
* Escape `'` with `\\`
* @param input the input string
*/
declare function escapeQuote(input: string): string
/**
* Escape the given character with the given escape character
* @param input the input string
* @param character the character to escape (e.g. `'`)
* @param escape_character the character to escape with (e.g. `\\`)
*/
declare function escapeQuote(input: string, character: string, escape_character: string): string
export = escapeQuote
}

View File

@ -0,0 +1,3 @@
export { addEnv } from "./add-env.js"
export { addPath } from "./add-path.js"
export { finalizeRC, sourceRCInRc as sourceRC } from "./rc-file.js"

View File

@ -0,0 +1,79 @@
import { promises } from "fs"
import { grantUserWriteAccess } from "admina"
import { info, warning } from "ci-log"
import memoize from "micro-memoize"
import { pathExists } from "path-exists"
import { untildifyUser } from "untildify-user"
const { appendFile, readFile, writeFile } = promises
export const defaultRcPath = untildifyUser("~/.bashrc")
/**
* Options for adding an rc file
*/
export type RcOptions = {
/** The path to the RC file that the env variables should be added to. */
rcPath: string
/** Provide a name (your tool) to add a variable guard for sourcing your rc file */
guard?: string
}
async function sourceRCInRc_(options: RcOptions) {
const sourceRcString = options.guard === undefined
? `\nsource "${options.rcPath}"\n`
: `\n# ${options.guard}\nif [[ "$SOURCE_${options.guard.toUpperCase()}RC" != 0 && -f "${options.rcPath}" ]]; then source "${options.rcPath}"; fi\n`
try {
await Promise.all([
addRCHeader(options),
addSourceToTargetRc(sourceRcString, untildifyUser("~/.bashrc")),
addSourceToTargetRc(sourceRcString, untildifyUser("~/.profile")),
])
} catch (err) {
warning(`Failed to add ${sourceRcString} to .profile or .bashrc. You should add it manually: ${err}`)
}
}
/**
* handles adding conditions to source rc file from .bashrc and .profile
*/
export const sourceRCInRc = memoize(sourceRCInRc_, { isPromise: true })
async function addRCHeader(options: RcOptions) {
// a variable that prevents source rc from being called from .bashrc and .profile
const rcHeader = options.guard === undefined
? "\n# Automatically Generated by os-env\n"
: `\n# Automatically Generated by os-env ${options.guard}\nexport SOURCE_${options.guard.toUpperCase()}RC=0\n`
if (await pathExists(options.rcPath)) {
const rcContent = await readFile(options.rcPath, "utf8")
if (!rcContent.includes(rcHeader)) {
// already executed setupCppInProfile
await appendFile(options.rcPath, `\n${rcHeader}\n`)
info(`Added ${rcHeader} to ${options.rcPath}`)
}
}
}
async function addSourceToTargetRc(sourceRcString: string, targetRcPath: string) {
if (await pathExists(targetRcPath)) {
const bashrcContent = await readFile(targetRcPath, "utf-8")
if (!bashrcContent.includes(sourceRcString)) {
await appendFile(targetRcPath, sourceRcString)
info(`${sourceRcString} was added to ${targetRcPath}`)
}
}
}
export async function finalizeRC(rcOptions: RcOptions) {
if (await pathExists(rcOptions.rcPath)) {
const entries = (await readFile(rcOptions.rcPath, "utf-8")).split("\n")
const uniqueEntries = [...new Set(entries.reverse())].reverse() // remove duplicates, keeping the latest entry
await writeFile(rcOptions.rcPath, uniqueEntries.join("\n"))
await grantUserWriteAccess(rcOptions.rcPath)
}
}

View File

@ -0,0 +1,14 @@
import escapeSpace from "escape-path-with-spaces"
import escapeQuote from "escape-quotes"
/**
* Escape a string for use in a shell command
* @param valGiven The string to escape
* @param shouldEscapeSpace Whether to escape spaces in the string
*
* @private
*/
export function escapeString(valGiven: string, shouldEscapeSpace: boolean = false) {
const spaceEscaped = shouldEscapeSpace ? escapeSpace(valGiven) : valGiven
return escapeQuote(spaceEscaped, "\"", "\\")
}

View File

@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"noEmit": false,
"allowImportingTsExtensions": false
},
"include": ["./src"]
}

View File

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json"
}

View File

@ -0,0 +1,156 @@
<h1 align="center">setup-apt</h1>
<p>
<img alt="Version" src="https://img.shields.io/badge/version-1.0.0-blue.svg?cacheSeconds=2592000" />
<img src="https://img.shields.io/badge/node-%3E%3D12-blue.svg" />
<a href="#" target="_blank">
<img alt="License: Apache--2.0" src="https://img.shields.io/badge/License-Apache--2.0-yellow.svg" />
</a>
</p>
> Setup apt packages and repositories in Debian/Ubuntu-based distributions
## Install
```sh
npm install --save setup-apt
```
## Usage
<!-- INSERT GENERATED DOCS START -->
### `updateAptAlternatives` (function)
Update the alternatives for a package
**Parameters:**
- name (`string`) - The name of the package
- path (`string`) - The path to the binary
- priority (`number`) - The priority of the alternative (Defaults to `40`)
**returns:** Promise<void>
### `addUpdateAlternativesToRc` (function)
Add the update-alternatives command to the rc file
**Parameters:**
- name (`string`) - The name of the package
- path (`string`) - The path to the binary
- rcOptions (`RcOptions`) - The options for the rc file to add the update-alternatives command to
- priority (`number`) - The priority of the alternative (Defaults to `40`)
**returns:** Promise<void>
### `isAptPackInstalled` (function)
Check if a package is installed
**Parameters:**
- pack (`string`) - The package to check
**returns:** Promise<boolean>
### `isAptPackRegexInstalled` (function)
Check if a package matching a regexp is installed
**Parameters:**
- regexp (`string`) - The regexp to check
**returns:** Promise<boolean>
### `updateAptRepos` (function)
Update the apt repositories
**Parameters:**
- apt (`string`) - The apt command to use (optional)
**returns:** void
### `InstallationInfo` (type)
The information about an installation result
### `aptTimeout` (variable)
The timeout to use for apt commands
Wait up to 300 seconds if the apt-get lock is held
### `AptPackage` (type)
The information about an apt package
### `installAptPack` (function)
Install a package using apt
**Parameters:**
- packages (`AptPackage[]`) - The packages to install (name, and optional info like version and repositories)
- update (`boolean`) - Whether to update the package list before installing (Defaults to `false`)
**returns:** Promise<InstallationInfo>
### `hasNala` (function)
Check if nala is installed
**returns:** boolean
### `getApt` (function)
Get the apt command to use
If nala is installed, use that, otherwise use apt-get
**returns:** string
### `getAptEnv` (function)
Get the environment variables to use for the apt command
**Parameters:**
- apt (`string`) - The apt command to use
**returns:** ProcessEnv
### `addAptKeyViaServer` (function)
Add an apt key via a keyserver
**Parameters:**
- keys (`string[]`) - The keys to add
- name (`string`) - The name of the key
- server (`string`) - The keyserver to use (Defaults to `keyserver.ubuntu.com`)
**returns:** Promise<string>
### `addAptKeyViaDownload` (function)
Add an apt key via a download
**Parameters:**
- name (`string`) - The name of the key
- url (`string`) - The URL of the key
**returns:** Promise<string>
<!-- INSERT GENERATED DOCS END -->
## 🤝 Contributing
You can sponsor my work here:
https://github.com/sponsors/aminya
Pull requests, issues and feature requests are welcome.
See the [Contributing guide](https://github.com/aminya/setup-cpp/blob/master/CONTRIBUTING.md).

View File

@ -0,0 +1,49 @@
{
"name": "setup-apt",
"version": "1.0.0",
"description": "Setup apt packages and repositories in Debian/Ubuntu-based distributions",
"repository": "https://github.com/aminya/setup-cpp",
"homepage": "https://github.com/aminya/setup-cpp/tree/master/packages/setup-apt",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc --pretty",
"lint.tsc": "tsc --noEmit --pretty",
"lint.eslint": "eslint **/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/ --fix",
"prepublishOnly": "pnpm run build"
},
"dependencies": {
"@types/node": "^12",
"admina": "^1.0.1",
"ci-info": "^4.0.0",
"path-exists": "^5.0.0",
"ci-log": "workspace:*",
"os-env": "workspace:*",
"which": "4.0.0",
"execa": "^7.2.0",
"escape-string-regexp": "^5.0.0"
},
"engines": {
"node": ">=12"
},
"keywords": [
"setup",
"apt",
"apt-get",
"repository",
"add-apt-repository",
"apt-cache",
"aptitude",
"install",
"setup-apt",
"repositories",
"linux",
"ubuntu",
"debian",
"package",
"apt-key"
],
"devDependencies": {}
}

View File

@ -0,0 +1,40 @@
import { promises } from "fs"
import { execRoot } from "admina"
import { GITHUB_ACTIONS } from "ci-info"
import { sourceRC } from "os-env"
import type { RcOptions } from "os-env/dist/rc-file.js"
const { appendFile } = promises
/**
* Update the alternatives for a package
* @param name The name of the package
* @param path The path to the binary
* @param priority The priority of the alternative (Defaults to `40`)
*/
export async function updateAptAlternatives(name: string, path: string, priority: number = 40) {
await execRoot("update-alternatives", ["--install", `/usr/bin/${name}`, name, path, priority.toString()])
}
/**
* Add the update-alternatives command to the rc file
* @param name The name of the package
* @param path The path to the binary
* @param rcOptions The options for the rc file to add the update-alternatives command to
* @param priority The priority of the alternative (Defaults to `40`)
*/
export async function addUpdateAlternativesToRc(
name: string,
path: string,
rcOptions: RcOptions,
priority: number = 40,
) {
if (GITHUB_ACTIONS) {
await updateAptAlternatives(name, path, priority)
} else {
await sourceRC(rcOptions)
await appendFile(
rcOptions.rcPath,
`\nif [ $UID -eq 0 ]; then update-alternatives --install /usr/bin/${name} ${name} ${path} ${priority}; fi\n`,
)
}
}

View File

@ -0,0 +1,62 @@
import { execRoot, execRootSync } from "admina"
import { warning } from "ci-log"
import { execa } from "execa"
import { pathExists } from "path-exists"
import { installAptPack } from "./install.js"
function initGpg() {
execRootSync("gpg", ["-k"])
}
/**
* Add an apt key via a keyserver
* @param keys The keys to add
* @param name The name of the key
* @param server The keyserver to use (Defaults to `keyserver.ubuntu.com`)
* @returns The file name of the key that was added or `undefined` if it failed
*/
export async function addAptKeyViaServer(keys: string[], name: string, server = "keyserver.ubuntu.com") {
try {
const fileName = `/etc/apt/trusted.gpg.d/${name}`
if (!(await pathExists(fileName))) {
initGpg()
await Promise.all(
keys.map(async (key) => {
await execRoot("gpg", [
"--no-default-keyring",
"--keyring",
`gnupg-ring:${fileName}`,
"--keyserver",
server,
"--recv-keys",
key,
])
await execRoot("chmod", ["644", fileName])
}),
)
}
return fileName
} catch (err) {
warning(`Failed to add apt key via server ${server}: ${err}`)
return undefined
}
}
/**
* Add an apt key via a download
* @param name The name of the key
* @param url The URL of the key
* @returns The file name of the key that was added
*/
export async function addAptKeyViaDownload(name: string, url: string) {
const fileName = `/etc/apt/trusted.gpg.d/${name}`
if (!(await pathExists(fileName))) {
initGpg()
await installAptPack([{ name: "curl" }, { name: "ca-certificates" }], undefined)
await execa("curl", ["-s", url, "-o", `/tmp/${name}`])
execRootSync("gpg", ["--no-default-keyring", "--keyring", `gnupg-ring:${fileName}`, "--import", `/tmp/${name}`])
execRootSync("chmod", ["644", fileName])
}
return fileName
}

View File

@ -0,0 +1,5 @@
export * from "./alternatives.js"
export * from "./apt-key.js"
export * from "./install.js"
export * from "./is-installed.js"
export * from "./update.js"

View File

@ -0,0 +1,293 @@
import { defaultExecOptions, execRootSync } from "admina"
import { info, warning } from "ci-log"
import escapeRegex from "escape-string-regexp"
import { type ExecaError, execa } from "execa"
import which from "which"
import { addAptKeyViaServer } from "./apt-key.js"
import { isAptPackInstalled } from "./is-installed.js"
import { updateAptRepos } from "./update.js"
/**
* The information about an installation result
*/
export type InstallationInfo = {
/** The install dir of the package (Defaults to `undefined`) */
installDir?: string
/** The bin dir of the package (Defaults to `/usr/bin`) */
binDir: string
/** The bin path of the package (Defaults to `undefined`) */
bin?: string
}
/* eslint-disable require-atomic-updates */
let didUpdate: boolean = false
let didInit: boolean = false
/**
* The timeout to use for apt commands
* Wait up to 300 seconds if the apt-get lock is held
* @private Used internally
*/
export const aptTimeout = "Dpkg::Lock::Timeout=300"
/**
* The information about an apt package
*/
export type AptPackage = {
/** The name of the package */
name: string
/** The version of the package (optional) */
version?: string
/** The repositories to add before installing the package (optional) */
repositories?: string[]
}
const retryErrors = [
"E: Could not get lock",
"dpkg: error processing archive",
"dpkg: error: dpkg status database is locked by another process",
]
/**
* Install a package using apt
*
* @param packages The packages to install (name, and optional info like version and repositories)
* @param update Whether to update the package list before installing (Defaults to `false`)
*/
export async function installAptPack(packages: AptPackage[], update = false): Promise<InstallationInfo> {
const apt: string = getApt()
for (const { name, version } of packages) {
info(`Installing ${name} ${version ?? ""} via ${apt}`)
}
// Update the repos if needed
if (update) {
updateAptRepos(apt)
didUpdate = true
}
// Add the repos if needed
await addRepositories(apt, packages)
const needToInstall = await filterAndQualifyAptPackages(apt, packages)
if (needToInstall.length === 0) {
info("All packages are already installed")
return { binDir: "/usr/bin/" }
}
// Initialize apt if needed
if (!didInit) {
await initApt(apt)
didInit = true
}
// Install
try {
execRootSync(apt, ["install", "--fix-broken", "-y", ...needToInstall], {
...defaultExecOptions,
env: getAptEnv(apt),
})
} catch (err) {
if (isExecaError(err)) {
if (retryErrors.some((error) => err.stderr.includes(error))) {
warning(`Failed to install packages ${needToInstall}. Retrying...`)
execRootSync(
apt,
["install", "--fix-broken", "-y", "-o", aptTimeout, ...needToInstall],
{ ...defaultExecOptions, env: getAptEnv(apt) },
)
}
} else {
throw err
}
}
return { binDir: "/usr/bin/" }
}
function isExecaError(err: unknown): err is ExecaError {
return typeof (err as ExecaError).stderr === "string"
}
/**
* Check if nala is installed
*/
export function hasNala() {
return which.sync("nala", { nothrow: true }) !== null
}
/**
* Get the apt command to use
* If nala is installed, use that, otherwise use apt-get
*/
export function getApt() {
let apt: string
if (hasNala()) {
apt = "nala"
} else {
apt = "apt-get"
}
return apt
}
/**
* Get the environment variables to use for the apt command
* @param apt The apt command to use
* @private Used internally
*/
export function getAptEnv(apt: string) {
const env: NodeJS.ProcessEnv = { ...process.env, DEBIAN_FRONTEND: "noninteractive" }
if (apt === "nala") {
// if LANG/LC_ALL is not set, enable utf8 otherwise nala fails because of ASCII encoding
if (env.LANG === undefined) {
env.LANG = "C.UTF-8"
}
if (env.LC_ALL === undefined) {
env.LC_ALL = "C.UTF-8"
}
}
return env
}
/**
* The type of apt package to install
*/
export enum AptPackageType {
NameDashVersion = 0,
NameEqualsVersion = 1,
Name = 2,
None = 3,
}
/**
* Filter out the packages that are already installed and qualify the packages into a full package name/version
*/
async function filterAndQualifyAptPackages(apt: string, packages: AptPackage[]) {
return (await Promise.all(packages.map((pack) => qualifiedNeededAptPackage(apt, pack))))
.filter((pack) => pack !== undefined)
}
async function qualifiedNeededAptPackage(apt: string, pack: AptPackage) {
// Qualify the packages into full package name/version
const qualified = await getAptArg(apt, pack.name, pack.version)
// filter out the packages that are already installed
return (await isAptPackInstalled(qualified)) ? undefined : qualified
}
async function addRepositories(apt: string, packages: AptPackage[]) {
const allRepositories = [...new Set(packages.flatMap((pack) => pack.repositories ?? []))]
if (allRepositories.length !== 0) {
if (!didInit) {
await initApt(apt)
didInit = true
}
await installAddAptRepo(apt)
for (const repo of allRepositories) {
// eslint-disable-next-line no-await-in-loop
execRootSync("add-apt-repository", ["-y", "--no-update", repo], { ...defaultExecOptions, env: getAptEnv(apt) })
}
updateAptRepos(apt)
didUpdate = true
}
}
async function aptPackageType(apt: string, name: string, version: string | undefined): Promise<AptPackageType> {
if (version !== undefined && version !== "") {
const { stdout } = await execa("apt-cache", [
"search",
"--names-only",
`^${escapeRegex(name)}-${escapeRegex(version)}$`,
], { env: getAptEnv(apt), stdio: "pipe" })
if (stdout.trim() !== "") {
return AptPackageType.NameDashVersion
}
try {
// check if apt-get show can find the version
// eslint-disable-next-line @typescript-eslint/no-shadow
const { stdout } = await execa("apt-cache", ["show", `${name}=${version}`], { env: getAptEnv(apt) })
if (stdout.trim() === "") {
return AptPackageType.NameEqualsVersion
}
} catch {
// ignore
}
}
try {
const { stdout: showStdout } = await execa("apt-cache", ["show", name], { env: getAptEnv(apt), stdio: "pipe" })
if (showStdout.trim() !== "") {
return AptPackageType.Name
}
} catch {
// ignore
}
// If apt-cache fails, update the repos and try again
if (!didUpdate) {
updateAptRepos(getApt())
didUpdate = true
return aptPackageType(apt, name, version)
}
return AptPackageType.None
}
async function getAptArg(apt: string, name: string, version: string | undefined) {
const package_type = await aptPackageType(apt, name, version)
switch (package_type) {
case AptPackageType.NameDashVersion:
return `${name}-${version}`
case AptPackageType.NameEqualsVersion:
return `${name}=${version}`
case AptPackageType.Name:
if (version !== undefined && version !== "") {
warning(`Could not find package ${name} with version ${version}. Installing the latest version.`)
}
return name
default:
throw new Error(`Could not find package ${name} ${version ?? ""}`)
}
}
async function installAddAptRepo(apt: string) {
if (await isAptPackInstalled("software-properties-common")) {
return
}
execRootSync(
apt,
["install", "-y", "--fix-broken", "-o", aptTimeout, "software-properties-common"],
{ ...defaultExecOptions, env: getAptEnv(apt) },
)
}
/** Install gnupg and certificates (usually missing from docker containers) */
async function initApt(apt: string) {
// Update the repos if needed
if (!didUpdate) {
updateAptRepos(apt)
didUpdate = true
}
const toInstall = await filterAndQualifyAptPackages(apt, [
{ name: "ca-certificates" },
{ name: "gnupg" },
{ name: "apt-utils" },
])
if (toInstall.length !== 0) {
execRootSync(apt, ["install", "-y", "--fix-broken", "-o", aptTimeout, ...toInstall], {
...defaultExecOptions,
env: getAptEnv(apt),
})
}
await Promise.all([
addAptKeyViaServer(["3B4FE6ACC0B21F32", "40976EAF437D05B5"], "setup-cpp-ubuntu-archive.gpg"),
addAptKeyViaServer(["1E9377A2BA9EF27F"], "launchpad-toolchain.gpg"),
])
}

View File

@ -0,0 +1,42 @@
import { execa } from "execa"
import { getAptEnv } from "./install.js"
/**
* Check if a package is installed
* @param pack The package to check
* @returns `true` if the package is installed, `false` otherwise
*/
export async function isAptPackInstalled(pack: string) {
try {
// check if a package is installed
const { stdout } = await execa("dpkg", ["-s", pack], { env: getAptEnv("apt-get"), stdio: "pipe" })
if (typeof stdout !== "string") {
return false
}
const lines = stdout.split("\n")
// check if the output contains a line that starts with "Status: install ok installed"
return lines.some((line) => line.startsWith("Status: install ok installed"))
} catch {
return false
}
}
/**
* Check if a package matching a regexp is installed
* @param regexp The regexp to check
* @returns `true` if a package is installed, `false` otherwise
*/
export async function isAptPackRegexInstalled(regexp: string) {
try {
// check if a package matching the regexp is installed
const { stdout } = await execa("dpkg", ["-l", regexp], { env: getAptEnv("apt-get"), stdio: "pipe" })
if (typeof stdout !== "string") {
return false
}
const lines = stdout.split("\n")
// check if the output contains any lines that start with "ii"
return lines.some((line) => line.startsWith("ii"))
} catch {
return false
}
}

View File

@ -0,0 +1,14 @@
import { defaultExecOptions, execRootSync } from "admina"
import { aptTimeout, getApt, getAptEnv } from "./install.js"
/**
* Update the apt repositories
* @param apt The apt command to use (optional)
*/
export function updateAptRepos(apt: string = getApt()) {
execRootSync(
apt,
apt !== "nala" ? ["update", "-y", "-o", aptTimeout] : ["update", "-o", aptTimeout],
{ ...defaultExecOptions, env: getAptEnv(apt) },
)
}

View File

@ -0,0 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"noEmit": false,
"allowImportingTsExtensions": false
},
"include": ["./src"]
}

View File

@ -0,0 +1,3 @@
{
"extends": "../../.eslintrc.json"
}

View File

@ -2,13 +2,17 @@
"name": "untildify-user",
"version": "1.0.0",
"description": "Untildify a path for the current user even if it is root",
"homepage": "https://github.com/aminya/setup-cpp",
"repository": "https://github.com/aminya/setup-cpp",
"homepage": "https://github.com/aminya/setup-cpp/tree/master/packages/untildify-user",
"license": "Apache-2.0",
"author": "Amin Yahyaabadi",
"main": "./dist/index.js",
"source": "./src/index.ts",
"scripts": {
"build": "tsc"
"build": "tsc --pretty",
"lint.tsc": "tsc --noEmit --pretty",
"lint.eslint": "eslint **/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/ --fix",
"prepublishOnly": "pnpm run build"
},
"dependencies": {
"admina": "1.0.1"

View File

@ -1,7 +1,9 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist"
"outDir": "./dist",
"noEmit": false,
"allowImportingTsExtensions": false
},
"include": ["./src"]
}

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,2 @@
packages:
- "./"
- "packages/*"

View File

@ -1,8 +1,8 @@
import { parseArgs } from "../cli-options"
import { getCompilerInfo } from "../compilers"
import type { Inputs } from "../tool"
import { DefaultLinuxVersion } from "../versions/default_versions"
import { getVersion, syncVersions } from "../versions/versions"
import { parseArgs } from "../cli-options.js"
import { getCompilerInfo } from "../compilers.js"
import type { Inputs } from "../tool.js"
import { DefaultLinuxVersion } from "../versions/default_versions.js"
import { getVersion, syncVersions } from "../versions/versions.js"
jest.setTimeout(300000)
describe("getCompilerInfo", () => {

View File

@ -1,6 +1,6 @@
import type { InstallationInfo } from "../../utils/setup/setupBin"
import { testBin } from "../../utils/tests/test-helpers"
import { setupBazel } from "../bazel"
import type { InstallationInfo } from "../../utils/setup/setupBin.js"
import { testBin } from "../../utils/tests/test-helpers.js"
import { setupBazel } from "../bazel.js"
jest.setTimeout(300000)
describe("setup-bazel", () => {

View File

@ -1,11 +1,11 @@
import { execRootSync } from "admina"
import { hasDnf } from "../utils/env/hasDnf"
import { isArch } from "../utils/env/isArch"
import { isUbuntu } from "../utils/env/isUbuntu"
import { addAptKeyViaDownload, setupAptPack } from "../utils/setup/setupAptPack"
import { setupBrewPack } from "../utils/setup/setupBrewPack"
import { setupChocoPack } from "../utils/setup/setupChocoPack"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { addAptKeyViaDownload, installAptPack } from "setup-apt"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import { setupBrewPack } from "../utils/setup/setupBrewPack.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function setupBazel(version: string, _setupDir: string, _arch: string) {
@ -36,7 +36,7 @@ export async function setupBazel(version: string, _setupDir: string, _arch: stri
"-c",
`echo "deb [arch=amd64 signed-by=${keyFileName}] https://storage.googleapis.com/bazel-apt stable jdk1.8" | tee /etc/apt/sources.list.d/bazel.list`,
])
return setupAptPack([{ name: "bazel", version }], true)
return installAptPack([{ name: "bazel", version }], true)
}
throw new Error("Unsupported linux distribution")
}

View File

@ -1,5 +1,5 @@
import { testBin } from "../../utils/tests/test-helpers"
import { setupBrew } from "../brew"
import { testBin } from "../../utils/tests/test-helpers.js"
import { setupBrew } from "../brew.js"
jest.setTimeout(300000)
describe("setup-brew", () => {

View File

@ -3,9 +3,10 @@ import path, { join } from "path"
import { mkdirP } from "@actions/io"
import { execaSync } from "execa"
import { readFile } from "fs/promises"
import { addPath } from "os-env"
import { dirname } from "patha"
import which from "which"
import { addPath } from "../utils/env/addEnv"
import { rcOptions } from "../cli-options.js"
/* eslint-disable require-atomic-updates */
let binDir: string | undefined
@ -47,7 +48,7 @@ export async function setupBrew(_version: string, _setupDir: string, _arch: stri
})
binDir = getBrewPath()
await addPath(binDir)
await addPath(binDir, rcOptions)
return { binDir }
}

View File

@ -1,6 +1,6 @@
import type { InstallationInfo } from "../../utils/setup/setupBin"
import { testBin } from "../../utils/tests/test-helpers"
import { setupCcache } from "../ccache"
import type { InstallationInfo } from "../../utils/setup/setupBin.js"
import { testBin } from "../../utils/tests/test-helpers.js"
import { setupCcache } from "../ccache.js"
jest.setTimeout(300000)
describe("setup-ccache", () => {

View File

@ -1,11 +1,11 @@
import { hasDnf } from "../utils/env/hasDnf"
import { isArch } from "../utils/env/isArch"
import { isUbuntu } from "../utils/env/isUbuntu"
import { setupAptPack } from "../utils/setup/setupAptPack"
import { setupBrewPack } from "../utils/setup/setupBrewPack"
import { setupChocoPack } from "../utils/setup/setupChocoPack"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
import { installAptPack } from "setup-apt"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import { setupBrewPack } from "../utils/setup/setupBrewPack.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function setupCcache(version: string, _setupDir: string, _arch: string) {
@ -22,7 +22,7 @@ export function setupCcache(version: string, _setupDir: string, _arch: string) {
} else if (hasDnf()) {
return setupDnfPack([{ name: "ccache", version }])
} else if (isUbuntu()) {
return setupAptPack([{ name: "ccache", version }])
return installAptPack([{ name: "ccache", version }])
}
throw new Error("Unsupported linux distribution")
}

View File

@ -1,6 +1,6 @@
import type { InstallationInfo } from "../../utils/setup/setupBin"
import { testBin } from "../../utils/tests/test-helpers"
import { setupChocolatey } from "../chocolatey"
import type { InstallationInfo } from "../../utils/setup/setupBin.js"
import { testBin } from "../../utils/tests/test-helpers.js"
import { setupChocolatey } from "../chocolatey.js"
jest.setTimeout(300000)
describe("setup-chocolatey", () => {

View File

@ -1,11 +1,12 @@
/* eslint-disable require-atomic-updates */
import { execaSync } from "execa"
import { addPath } from "os-env"
import { pathExists } from "path-exists"
import { dirname } from "patha"
import which from "which"
import { addPath } from "../utils/env/addEnv"
import type { InstallationInfo } from "../utils/setup/setupBin"
import { rcOptions } from "../cli-options.js"
import type { InstallationInfo } from "../utils/setup/setupBin.js"
/* eslint-disable require-atomic-updates */
let binDir: string | undefined
export async function setupChocolatey(
@ -54,7 +55,7 @@ export async function setupChocolatey(
)
const chocoPath = `${process.env.ALLUSERSPROFILE}\\chocolatey\\bin`
await addPath(chocoPath)
await addPath(chocoPath, rcOptions)
const maybeChoco = which.sync("choco", { nothrow: true })
if (maybeChoco !== null) {

View File

@ -1,8 +1,9 @@
import { getInput } from "@actions/core"
import { info } from "ci-log"
import mri from "mri"
import { type Inputs, inputs } from "./tool"
import type { InstallationInfo } from "./utils/setup/setupBin"
import { untildifyUser } from "untildify-user"
import { type Inputs, inputs } from "./tool.js"
import type { InstallationInfo } from "./utils/setup/setupBin.js"
export function parseArgs(args: string[]): Opts {
return mri<Record<Inputs, string | undefined> & { help: boolean }>(args, {
@ -71,3 +72,8 @@ export function getSuccessMessage(tool: string, installationInfo: InstallationIn
}
return msg
}
export const rcOptions = {
rcPath: untildifyUser("~/.cpprc"),
guard: "cpp",
}

View File

@ -1,7 +1,7 @@
import { GITHUB_ACTIONS } from "ci-info"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { getVersion } from "../../versions/versions"
import { setupCmake } from "../cmake"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions.js"
import { setupCmake } from "../cmake.js"
jest.setTimeout(300000)

View File

@ -1,8 +1,8 @@
import { addExeExt } from "patha"
import semverCoerce from "semver/functions/coerce"
import semverLte from "semver/functions/lte"
import { extractTarByExe, extractZip } from "../utils/setup/extract"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin"
import { extractTarByExe, extractZip } from "../utils/setup/extract.js"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
/** Get the platform data for cmake */
function getCmakePackageInfo(version: string, platform: NodeJS.Platform, arch: string): PackageInfo {

View File

@ -1,14 +1,14 @@
import { join } from "path"
import { endGroup, notice, startGroup } from "@actions/core"
import { error, info } from "ci-log"
import { addEnv } from "os-env"
import semverValid from "semver/functions/valid"
import { getSuccessMessage } from "./cli-options"
import { setupGcc, setupMingw } from "./gcc/gcc"
import { activateGcovGCC, activateGcovLLVM } from "./gcovr/gcovr"
import { setupLLVM } from "./llvm/llvm"
import { setupMSVC } from "./msvc/msvc"
import { addEnv } from "./utils/env/addEnv"
import { getVersion } from "./versions/versions"
import { getSuccessMessage, rcOptions } from "./cli-options.js"
import { setupGcc, setupMingw } from "./gcc/gcc.js"
import { activateGcovGCC, activateGcovLLVM } from "./gcovr/gcovr.js"
import { setupLLVM } from "./llvm/llvm.js"
import { setupMSVC } from "./msvc/msvc.js"
import { getVersion } from "./versions/versions.js"
/** Detecting the compiler version. Divide the given string by `-` and use the second element as the version */
export function getCompilerInfo(compilerAndVersion: string) {
@ -69,7 +69,7 @@ export async function installCompiler(
if (hasLLVM) {
// remove back the added CPPFLAGS of LLVM that include the LLVM headers
await addEnv("CPPFLAGS", "")
await addEnv("CPPFLAGS", "", rcOptions)
}
await activateGcovGCC(gccVersion)
@ -92,7 +92,7 @@ export async function installCompiler(
if (hasLLVM) {
// remove the CPPFLAGS of LLVM that include the LLVM headers
await addEnv("CPPFLAGS", "")
await addEnv("CPPFLAGS", "", rcOptions)
}
successMessages.push(getSuccessMessage("msvc", installationInfo))
@ -101,7 +101,7 @@ export async function installCompiler(
case "appleclang":
case "applellvm": {
notice("Assuming apple-clang is already installed")
await Promise.all([addEnv("CC", "clang"), addEnv("CXX", "clang++")])
await Promise.all([addEnv("CC", "clang", rcOptions), addEnv("CXX", "clang++", rcOptions)])
successMessages.push(getSuccessMessage("apple-clang", undefined))
break
}

View File

@ -1,6 +1,6 @@
import { testBin } from "../../utils/tests/test-helpers"
import { getVersion } from "../../versions/versions"
import { setupConan } from "../conan"
import { testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions.js"
import { setupConan } from "../conan.js"
jest.setTimeout(300000)
describe("setup-conan", () => {

View File

@ -1,4 +1,4 @@
import { setupPipPack } from "../utils/setup/setupPipPack"
import { setupPipPack } from "../utils/setup/setupPipPack.js"
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function setupConan(version: string | undefined, _setupDir: string, _arch: string) {

View File

@ -1,6 +1,6 @@
import { testBin } from "../../utils/tests/test-helpers"
import { getVersion } from "../../versions/versions"
import { setupCppcheck } from "../cppcheck"
import { testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions.js"
import { setupCppcheck } from "../cppcheck.js"
jest.setTimeout(300000)
describe("setup-cppcheck", () => {

View File

@ -1,12 +1,13 @@
import { addPath } from "../utils/env/addEnv"
import { hasDnf } from "../utils/env/hasDnf"
import { isArch } from "../utils/env/isArch"
import { isUbuntu } from "../utils/env/isUbuntu"
import { setupAptPack } from "../utils/setup/setupAptPack"
import { setupBrewPack } from "../utils/setup/setupBrewPack"
import { setupChocoPack } from "../utils/setup/setupChocoPack"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
import { addPath } from "os-env"
import { installAptPack } from "setup-apt"
import { rcOptions } from "../cli-options.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import { setupBrewPack } from "../utils/setup/setupBrewPack.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function setupCppcheck(version: string | undefined, _setupDir: string, _arch: string) {
@ -25,7 +26,7 @@ export async function setupCppcheck(version: string | undefined, _setupDir: stri
} else if (hasDnf()) {
return setupDnfPack([{ name: "ccache", version }])
} else if (isUbuntu()) {
return setupAptPack([{ name: "cppcheck", version }])
return installAptPack([{ name: "cppcheck", version }])
}
throw new Error("Unsupported linux distribution")
}
@ -37,6 +38,6 @@ export async function setupCppcheck(version: string | undefined, _setupDir: stri
async function activateWinCppcheck() {
const binDir = "C:/Program Files/Cppcheck"
await addPath(binDir)
await addPath(binDir, rcOptions)
return binDir
}

View File

@ -1,10 +1,10 @@
import which from "which"
import { macosVersion } from "../../utils/env/macos_version"
import { ubuntuVersion } from "../../utils/env/ubuntu_version"
import type { InstallationInfo } from "../../utils/setup/setupBin"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { getVersion } from "../../versions/versions"
import { setupDoxygen } from "../doxygen"
import { macosVersion } from "../../utils/env/macos_version.js"
import { ubuntuVersion } from "../../utils/env/ubuntu_version.js"
import type { InstallationInfo } from "../../utils/setup/setupBin.js"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions.js"
import { setupDoxygen } from "../doxygen.js"
jest.setTimeout(300000)
describe("setup-doxygen", () => {

View File

@ -1,24 +1,25 @@
import { info, notice } from "ci-log"
import { addPath } from "os-env"
import { addExeExt, join } from "patha"
import { setupGraphviz } from "../graphviz/graphviz"
import { addPath } from "../utils/env/addEnv"
import { extractTar, extractZip } from "../utils/setup/extract"
import { setupAptPack } from "../utils/setup/setupAptPack"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin"
import { setupBrewPack } from "../utils/setup/setupBrewPack"
import { setupChocoPack } from "../utils/setup/setupChocoPack"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
import { getVersion } from "../versions/versions"
import { installAptPack } from "setup-apt"
import { setupGraphviz } from "../graphviz/graphviz.js"
import { extractTar, extractZip } from "../utils/setup/extract.js"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
import { setupBrewPack } from "../utils/setup/setupBrewPack.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
import { getVersion } from "../versions/versions.js"
import { pathExists } from "path-exists"
import retry from "retry-as-promised"
import { hasDnf } from "../utils/env/hasDnf"
import { isArch } from "../utils/env/isArch"
import { isUbuntu } from "../utils/env/isUbuntu"
import { macosVersion } from "../utils/env/macos_version"
import { ubuntuVersion } from "../utils/env/ubuntu_version"
import { setupDmg } from "../utils/setup/setupDmg"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { rcOptions } from "../cli-options.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import { macosVersion } from "../utils/env/macos_version.js"
import { ubuntuVersion } from "../utils/env/ubuntu_version.js"
import { setupDmg } from "../utils/setup/setupDmg.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
/** Get the platform data for cmake */
// eslint-disable-next-line @typescript-eslint/no-unused-vars
@ -96,7 +97,7 @@ export async function setupDoxygen(version: string, setupDir: string, arch: stri
} else if (hasDnf()) {
return setupDnfPack([{ name: "doxygen", version }])
} else if (isUbuntu()) {
installationInfo = await setupAptPack([{ name: "doxygen", version }])
installationInfo = await installAptPack([{ name: "doxygen", version }])
} else {
throw new Error("Unsupported linux distributions")
}
@ -105,13 +106,13 @@ export async function setupDoxygen(version: string, setupDir: string, arch: stri
// doxygen on stable Ubuntu repositories is very old. So, we use get the binary from the website itself
installationInfo = await setupBin("doxygen", version, getDoxygenPackageInfo, setupDir, arch)
try {
await setupAptPack([{ name: "libclang-cpp9" }])
await installAptPack([{ name: "libclang-cpp9" }])
} catch (err) {
info(`Failed to download libclang-cpp9 that might be needed for running doxygen. ${err}`)
}
} catch (err) {
notice(`Failed to download doxygen binary. ${err}. Falling back to apt-get.`)
installationInfo = await setupAptPack([{ name: "doxygen" }])
installationInfo = await installAptPack([{ name: "doxygen" }])
}
} else {
throw new Error("Unsupported linux distributions")
@ -138,7 +139,7 @@ async function activateWinDoxygen() {
// eslint-disable-next-line no-await-in-loop
if (await pathExists(join(binDir, "doxygen.exe"))) {
// eslint-disable-next-line no-await-in-loop
await addPath(binDir)
await addPath(binDir, rcOptions)
return binDir
}
}

View File

@ -1,10 +1,10 @@
import { execaSync } from "execa"
import { chmod } from "fs/promises"
import { addExeExt, join } from "patha"
import { ubuntuVersion } from "../../utils/env/ubuntu_version"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { getVersion } from "../../versions/versions"
import { setupGcc } from "../gcc"
import { ubuntuVersion } from "../../utils/env/ubuntu_version.js"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions.js"
import { setupGcc } from "../gcc.js"
jest.setTimeout(3000000)
describe("setup-gcc", () => {

View File

@ -1,4 +1,4 @@
import { addEnv, addPath } from "../utils/env/addEnv"
import { addEnv, addPath } from "os-env"
import { GITHUB_ACTIONS } from "ci-info"
import { info, warning } from "ci-log"
@ -7,17 +7,18 @@ import { pathExists } from "path-exists"
import { addExeExt, join } from "patha"
import semverCoerce from "semver/functions/coerce"
import semverMajor from "semver/functions/major"
import { setupMacOSSDK } from "../macos-sdk/macos-sdk"
import { hasDnf } from "../utils/env/hasDnf"
import { isArch } from "../utils/env/isArch"
import { isUbuntu } from "../utils/env/isUbuntu"
import { extract7Zip } from "../utils/setup/extract"
import { setupAptPack, updateAptAlternatives } from "../utils/setup/setupAptPack"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin"
import { setupBrewPack } from "../utils/setup/setupBrewPack"
import { setupChocoPack } from "../utils/setup/setupChocoPack"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
import { addUpdateAlternativesToRc, installAptPack } from "setup-apt"
import { rcOptions } from "../cli-options.js"
import { setupMacOSSDK } from "../macos-sdk/macos-sdk.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import { extract7Zip } from "../utils/setup/extract.js"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
import { setupBrewPack } from "../utils/setup/setupBrewPack.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
interface MingwInfo {
releaseName: string
@ -109,7 +110,7 @@ export async function setupGcc(version: string, setupDir: string, arch: string,
{ name: "libstdc++-devel" },
])
} else if (isUbuntu()) {
installationInfo = await setupAptPack([
installationInfo = await installAptPack([
{ name: "gcc", version, repositories: ["ppa:ubuntu-toolchain-r/test"] },
{ name: "g++", version, repositories: ["ppa:ubuntu-toolchain-r/test"] },
])
@ -119,7 +120,7 @@ export async function setupGcc(version: string, setupDir: string, arch: string,
if (isArch()) {
await setupPacmanPack("gcc-multilib", version)
} else if (isUbuntu()) {
await setupAptPack([{ name: "gcc-multilib", version, repositories: ["ppa:ubuntu-toolchain-r/test"] }])
await installAptPack([{ name: "gcc-multilib", version, repositories: ["ppa:ubuntu-toolchain-r/test"] }])
}
}
break
@ -128,7 +129,7 @@ export async function setupGcc(version: string, setupDir: string, arch: string,
// TODO support abi
// case "none": {
// if (arch === "arm" || arch === "arm64") {
// return setupAptPack("gcc-arm-none-eabi", version, [
// return installAptPack("gcc-arm-none-eabi", version, [
// "ppa:ubuntu-toolchain-r/test",
// ])
// } else {
@ -160,7 +161,7 @@ export async function setupMingw(version: string, setupDir: string, arch: string
} else if (hasDnf()) {
installationInfo = await setupDnfPack([{ name: "mingw64-gcc", version }])
} else if (isUbuntu()) {
installationInfo = await setupAptPack([
installationInfo = await installAptPack([
{ name: "mingw-w64", version, repositories: ["ppa:ubuntu-toolchain-r/test"] },
])
}
@ -187,10 +188,10 @@ async function setupChocoMingw(version: string, arch: string): Promise<Installat
let binDir: string | undefined
if (arch === "x64" && (await pathExists("C:/tools/mingw64/bin"))) {
binDir = "C:/tools/mingw64/bin"
await addPath(binDir)
await addPath(binDir, rcOptions)
} else if (arch === "ia32" && (await pathExists("C:/tools/mingw32/bin"))) {
binDir = "C:/tools/mingw32/bin"
await addPath(binDir)
await addPath(binDir, rcOptions)
} else if (await pathExists(`${process.env.ChocolateyInstall ?? "C:/ProgramData/chocolatey"}/bin/g++.exe`)) {
binDir = `${process.env.ChocolateyInstall ?? "C:/ProgramData/chocolatey"}/bin`
}
@ -208,37 +209,46 @@ async function activateGcc(version: string, binDir: string, priority: number = 4
// const ld = process.env.LD_LIBRARY_PATH ?? ""
// const dyld = process.env.DYLD_LIBRARY_PATH ?? ""
// promises.push(
// addEnv("LD_LIBRARY_PATH", `${installDir}/lib${path.delimiter}${ld}`),
// addEnv("DYLD_LIBRARY_PATH", `${installDir}/lib${path.delimiter}${dyld}`),
// addEnv("CPATH", `${installDir}/lib/gcc/${majorVersion}/include`),
// addEnv("LDFLAGS", `-L${installDir}/lib`),
// addEnv("CPPFLAGS", `-I${installDir}/include`)
// addEnv("LD_LIBRARY_PATH", `${installDir}/lib${path.delimiter}${ld}`, rcOptions),
// addEnv("DYLD_LIBRARY_PATH", `${installDir}/lib${path.delimiter}${dyld}`, rcOptions),
// addEnv("CPATH", `${installDir}/lib/gcc/${majorVersion}/include`, rcOptions),
// addEnv("LDFLAGS", `-L${installDir}/lib`, rcOptions),
// addEnv("CPPFLAGS", `-I${installDir}/include`, rcOptions),
// )
if (process.platform === "win32") {
promises.push(addEnv("CC", addExeExt(`${binDir}/gcc`)), addEnv("CXX", addExeExt(`${binDir}/g++`)))
promises.push(
addEnv("CC", addExeExt(`${binDir}/gcc`), rcOptions),
addEnv("CXX", addExeExt(`${binDir}/g++`), rcOptions),
)
} else {
const majorVersion = semverMajor(semverCoerce(version) ?? version)
if (majorVersion >= 5) {
promises.push(addEnv("CC", `${binDir}/gcc-${majorVersion}`), addEnv("CXX", `${binDir}/g++-${majorVersion}`))
promises.push(
addEnv("CC", `${binDir}/gcc-${majorVersion}`, rcOptions),
addEnv("CXX", `${binDir}/g++-${majorVersion}`, rcOptions),
)
if (isUbuntu()) {
promises.push(
updateAptAlternatives("cc", `${binDir}/gcc-${majorVersion}`, priority),
updateAptAlternatives("cxx", `${binDir}/g++-${majorVersion}`, priority),
updateAptAlternatives("gcc", `${binDir}/gcc-${majorVersion}`, priority),
updateAptAlternatives("g++", `${binDir}/g++-${majorVersion}`, priority),
addUpdateAlternativesToRc("cc", `${binDir}/gcc-${majorVersion}`, rcOptions, priority),
addUpdateAlternativesToRc("cxx", `${binDir}/g++-${majorVersion}`, rcOptions, priority),
addUpdateAlternativesToRc("gcc", `${binDir}/gcc-${majorVersion}`, rcOptions, priority),
addUpdateAlternativesToRc("g++", `${binDir}/g++-${majorVersion}`, rcOptions, priority),
)
}
} else {
promises.push(addEnv("CC", `${binDir}/gcc-${version}`), addEnv("CXX", `${binDir}/g++-${version}`))
promises.push(
addEnv("CC", `${binDir}/gcc-${version}`, rcOptions),
addEnv("CXX", `${binDir}/g++-${version}`, rcOptions),
)
if (isUbuntu()) {
promises.push(
updateAptAlternatives("cc", `${binDir}/gcc-${version}`, priority),
updateAptAlternatives("cxx", `${binDir}/g++-${version}`, priority),
updateAptAlternatives("gcc", `${binDir}/gcc-${version}`, priority),
updateAptAlternatives("g++", `${binDir}/g++-${version}`, priority),
addUpdateAlternativesToRc("cc", `${binDir}/gcc-${version}`, rcOptions, priority),
addUpdateAlternativesToRc("cxx", `${binDir}/g++-${version}`, rcOptions, priority),
addUpdateAlternativesToRc("gcc", `${binDir}/gcc-${version}`, rcOptions, priority),
addUpdateAlternativesToRc("g++", `${binDir}/g++-${version}`, rcOptions, priority),
)
}
}

View File

@ -1,7 +1,7 @@
import { ubuntuVersion } from "../../utils/env/ubuntu_version"
import { testBin } from "../../utils/tests/test-helpers"
import { getVersion } from "../../versions/versions"
import { setupGcovr } from "../gcovr"
import { ubuntuVersion } from "../../utils/env/ubuntu_version.js"
import { testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions.js"
import { setupGcovr } from "../gcovr.js"
jest.setTimeout(300000)
describe("setup-gcovr", () => {

View File

@ -1,7 +1,8 @@
import { addEnv } from "os-env"
import semverMajor from "semver/functions/major"
import semverValid from "semver/functions/valid"
import { addEnv } from "../utils/env/addEnv"
import { setupPipPack } from "../utils/setup/setupPipPack"
import { rcOptions } from "../cli-options.js"
import { setupPipPack } from "../utils/setup/setupPipPack.js"
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export function setupGcovr(version: string | undefined, _setupDir: string, _arch: string) {
@ -9,7 +10,7 @@ export function setupGcovr(version: string | undefined, _setupDir: string, _arch
}
export function activateGcovLLVM() {
return addEnv("GCOV", "llvm-cov gcov")
return addEnv("GCOV", "llvm-cov gcov", rcOptions)
}
export function activateGcovGCC(gccVersion: string) {
@ -17,5 +18,5 @@ export function activateGcovGCC(gccVersion: string) {
const gccMajor = gccSemver !== null ? semverMajor(gccSemver) : gccVersion
const gcov = gccMajor !== "" ? `gcov-${gccMajor}` : "gcov"
return addEnv("GCOV", gcov)
return addEnv("GCOV", gcov, rcOptions)
}

View File

@ -1,9 +1,9 @@
import { macosVersion } from "../../utils/env/macos_version"
import { ubuntuVersion } from "../../utils/env/ubuntu_version"
import type { InstallationInfo } from "../../utils/setup/setupBin"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { getVersion } from "../../versions/versions"
import { setupGraphviz } from "../graphviz"
import { macosVersion } from "../../utils/env/macos_version.js"
import { ubuntuVersion } from "../../utils/env/ubuntu_version.js"
import type { InstallationInfo } from "../../utils/setup/setupBin.js"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions.js"
import { setupGraphviz } from "../graphviz.js"
jest.setTimeout(300000)
describe("setup-graphviz", () => {

View File

@ -1,13 +1,14 @@
import { addPath } from "../utils/env/addEnv"
import { hasDnf } from "../utils/env/hasDnf"
import { isArch } from "../utils/env/isArch"
import { isUbuntu } from "../utils/env/isUbuntu"
import { setupAptPack } from "../utils/setup/setupAptPack"
import type { InstallationInfo } from "../utils/setup/setupBin"
import { setupBrewPack } from "../utils/setup/setupBrewPack"
import { setupChocoPack } from "../utils/setup/setupChocoPack"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
import { addPath } from "os-env"
import { installAptPack } from "setup-apt"
import { rcOptions } from "../cli-options.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import type { InstallationInfo } from "../utils/setup/setupBin.js"
import { setupBrewPack } from "../utils/setup/setupBrewPack.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
// eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function setupGraphviz(version: string, _setupDir: string, _arch: string) {
@ -25,7 +26,7 @@ export async function setupGraphviz(version: string, _setupDir: string, _arch: s
} else if (hasDnf()) {
return setupDnfPack([{ name: "graphviz", version }])
} else if (isUbuntu()) {
return setupAptPack([{ name: "graphviz", version }])
return installAptPack([{ name: "graphviz", version }])
}
throw new Error("Unsupported linux distribution")
}
@ -39,7 +40,7 @@ async function activateGraphviz(): Promise<InstallationInfo> {
switch (process.platform) {
case "win32": {
const binDir = "C:/Program Files/Graphviz/bin"
await addPath(binDir)
await addPath(binDir, rcOptions)
return { binDir }
}
default: {

View File

@ -2,11 +2,11 @@ import { endGroup, startGroup } from "@actions/core"
import { error } from "ci-log"
import pTimeout from "p-timeout"
import { join } from "patha"
import { getSuccessMessage } from "./cli-options"
import { type ToolName, setups } from "./tool"
import type { InstallationInfo } from "./utils/setup/setupBin"
import { setupVCVarsall } from "./vcvarsall/vcvarsall"
import { getVersion } from "./versions/versions"
import { getSuccessMessage } from "./cli-options.js"
import { type ToolName, setups } from "./tool.js"
import type { InstallationInfo } from "./utils/setup/setupBin.js"
import { setupVCVarsall } from "./vcvarsall/vcvarsall.js"
import { getVersion } from "./versions/versions.js"
export const DEFAULT_TIMEOUT = 20 * 60 * 1000 // 20 minutes
@ -30,6 +30,9 @@ export async function installTool(
} catch (e) {
// push error message to the logger
error(e as string | Error)
if (e instanceof Error && e.stack !== undefined) {
error(e.stack)
}
errorMessages.push(`${tool} failed to install`)
}
endGroup()

View File

@ -1,8 +1,8 @@
import { info } from "@actions/core"
import which from "which"
import type { InstallationInfo } from "../../utils/setup/setupBin"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { setupKcov } from "../kcov"
import type { InstallationInfo } from "../../utils/setup/setupBin.js"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers.js"
import { setupKcov } from "../kcov.js"
jest.setTimeout(300000)
describe("setup-Kcov", () => {

View File

@ -1,21 +1,21 @@
import { info } from "ci-log"
import { execa } from "execa"
import { addExeExt, join } from "patha"
import { installAptPack } from "setup-apt"
import { untildifyUser } from "untildify-user"
import which from "which"
import { setupCmake } from "../cmake/cmake"
import { setupNinja } from "../ninja/ninja"
import { hasDnf } from "../utils/env/hasDnf"
import { isArch } from "../utils/env/isArch"
import { isUbuntu } from "../utils/env/isUbuntu"
import { ubuntuVersion } from "../utils/env/ubuntu_version"
import { extractTarByExe } from "../utils/setup/extract"
import { setupAptPack } from "../utils/setup/setupAptPack"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin"
import { setupDnfPack } from "../utils/setup/setupDnfPack"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack"
import { addVPrefix, removeVPrefix } from "../utils/setup/version"
import { getVersion } from "../versions/versions"
import { setupCmake } from "../cmake/cmake.js"
import { setupNinja } from "../ninja/ninja.js"
import { hasDnf } from "../utils/env/hasDnf.js"
import { isArch } from "../utils/env/isArch.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import { ubuntuVersion } from "../utils/env/ubuntu_version.js"
import { extractTarByExe } from "../utils/setup/extract.js"
import { type InstallationInfo, type PackageInfo, setupBin } from "../utils/setup/setupBin.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
import { setupPacmanPack } from "../utils/setup/setupPacmanPack.js"
import { addVPrefix, removeVPrefix } from "../utils/setup/version.js"
import { getVersion } from "../versions/versions.js"
function getDownloadKcovPackageInfo(version: string): PackageInfo {
return {
@ -49,7 +49,7 @@ async function buildKcov(file: string, dest: string) {
} else if (hasDnf()) {
await setupDnfPack([{ name: "libdwarf-devel" }, { name: "libcurl-devel" }])
} else if (isUbuntu()) {
await setupAptPack([{ name: "libdw-dev" }, { name: "libcurl4-openssl-dev" }])
await installAptPack([{ name: "libdw-dev" }, { name: "libcurl4-openssl-dev" }])
}
}
@ -117,7 +117,7 @@ export async function setupKcov(versionGiven: string, setupDir: string, arch: st
} else if (hasDnf()) {
await setupDnfPack([{ name: "binutils" }])
} else if (isUbuntu()) {
await setupAptPack([{ name: "libbinutils" }])
await installAptPack([{ name: "libbinutils" }])
}
return installationInfo
} else {

View File

@ -3,12 +3,12 @@ import { execaSync } from "execa"
import { chmod } from "fs/promises"
import { isUrlOnline } from "is-url-online"
import { addExeExt, join } from "patha"
import { ubuntuVersion } from "../../utils/env/ubuntu_version"
import { getSpecificVersionAndUrl } from "../../utils/setup/version"
import { setupTmpDir, testBin } from "../../utils/tests/test-helpers"
import { getVersion } from "../../versions/versions"
import { setupClangFormat, setupClangTools, setupLLVM } from "../llvm"
import { VERSIONS, getLinuxUrl, getUrl } from "../llvm_url"
import { ubuntuVersion } from "../../utils/env/ubuntu_version.js"
import { getSpecificVersionAndUrl } from "../../utils/setup/version.js"
import { setupTmpDir, testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions.js"
import { setupClangFormat, setupClangTools, setupLLVM } from "../llvm.js"
import { VERSIONS, getLinuxUrl, getUrl } from "../llvm_url.js"
jest.setTimeout(400000)
async function testUrl(version: string) {

View File

@ -2,19 +2,20 @@ import { delimiter } from "path"
import { GITHUB_ACTIONS } from "ci-info"
import { info, warning } from "ci-log"
import memoize from "micro-memoize"
import { addEnv } from "os-env"
import { pathExists } from "path-exists"
import { addExeExt, join } from "patha"
import { setupGcc } from "../gcc/gcc"
import { setupMacOSSDK } from "../macos-sdk/macos-sdk"
import { addEnv } from "../utils/env/addEnv"
import { isUbuntu } from "../utils/env/isUbuntu"
import { ubuntuVersion } from "../utils/env/ubuntu_version"
import { setupAptPack, updateAptAlternatives } from "../utils/setup/setupAptPack"
import { type InstallationInfo, setupBin } from "../utils/setup/setupBin"
import { semverCoerceIfInvalid } from "../utils/setup/version"
import { getVersion } from "../versions/versions"
import { LLVMPackages, setupLLVMApt } from "./llvm_installer"
import { getLLVMPackageInfo } from "./llvm_url"
import { addUpdateAlternativesToRc, installAptPack } from "setup-apt"
import { rcOptions } from "../cli-options.js"
import { setupGcc } from "../gcc/gcc.js"
import { setupMacOSSDK } from "../macos-sdk/macos-sdk.js"
import { isUbuntu } from "../utils/env/isUbuntu.js"
import { ubuntuVersion } from "../utils/env/ubuntu_version.js"
import { type InstallationInfo, setupBin } from "../utils/setup/setupBin.js"
import { semverCoerceIfInvalid } from "../utils/setup/version.js"
import { getVersion } from "../versions/versions.js"
import { LLVMPackages, setupLLVMApt } from "./llvm_installer.js"
import { getLLVMPackageInfo } from "./llvm_url.js"
export async function setupLLVM(version: string, setupDir: string, arch: string): Promise<InstallationInfo> {
const installationInfo = await setupLLVMWithoutActivation(version, setupDir, arch)
@ -74,9 +75,9 @@ async function setupLLVMOnly(
async function llvmBinaryDeps_raw(majorVersion: number) {
if (isUbuntu()) {
if (majorVersion <= 10) {
await setupAptPack([{ name: "libtinfo5" }])
await installAptPack([{ name: "libtinfo5" }])
} else {
await setupAptPack([{ name: "libtinfo-dev" }])
await installAptPack([{ name: "libtinfo-dev" }])
}
}
}
@ -97,21 +98,21 @@ export async function activateLLVM(directory: string) {
const actPromises: Promise<void>[] = [
// the output of this action
addEnv("LLVM_PATH", directory),
addEnv("LLVM_PATH", directory, rcOptions),
// Setup LLVM as the compiler
addEnv("LD_LIBRARY_PATH", `${directory}/lib${delimiter}${ld}`),
addEnv("DYLD_LIBRARY_PATH", `${directory}/lib${delimiter}${dyld}`),
addEnv("LD_LIBRARY_PATH", `${directory}/lib${delimiter}${ld}`, rcOptions),
addEnv("DYLD_LIBRARY_PATH", `${directory}/lib${delimiter}${dyld}`, rcOptions),
// compiler flags
addEnv("LDFLAGS", `-L"${directory}/lib"`),
addEnv("CPPFLAGS", `-I"${directory}/include"`),
addEnv("LDFLAGS", `-L"${directory}/lib"`, rcOptions),
addEnv("CPPFLAGS", `-I"${directory}/include"`, rcOptions),
// compiler paths
addEnv("CC", addExeExt(`${directory}/bin/clang`)),
addEnv("CXX", addExeExt(`${directory}/bin/clang++`)),
addEnv("CC", addExeExt(`${directory}/bin/clang`), rcOptions),
addEnv("CXX", addExeExt(`${directory}/bin/clang++`), rcOptions),
addEnv("LIBRARY_PATH", `${directory}/lib`),
addEnv("LIBRARY_PATH", `${directory}/lib`, rcOptions),
// os sdks
setupMacOSSDK(),
@ -121,22 +122,22 @@ export async function activateLLVM(directory: string) {
// TODO Windows builds fail with llvm's CPATH
// if (process.platform !== "win32") {
// if (await pathExists(`${directory}/lib/clang/${version}/include`)) {
// promises.push(addEnv("CPATH", `${directory}/lib/clang/${version}/include`))
// promises.push(addEnv("CPATH", `${directory}/lib/clang/${version}/include`, rcOptions))
// } else if (await pathExists(`${directory}/lib/clang/${llvmMajor}/include`)) {
// promises.push(addEnv("CPATH", `${directory}/lib/clang/${llvmMajor}/include`))
// promises.push(addEnv("CPATH", `${directory}/lib/clang/${llvmMajor}/include`, rcOptions))
// }
// }
if (isUbuntu()) {
const priority = 60
actPromises.push(
updateAptAlternatives("cc", `${directory}/bin/clang`, priority),
updateAptAlternatives("cxx", `${directory}/bin/clang++`, priority),
updateAptAlternatives("clang", `${directory}/bin/clang`),
updateAptAlternatives("clang++", `${directory}/bin/clang++`),
updateAptAlternatives("lld", `${directory}/bin/lld`),
updateAptAlternatives("ld.lld", `${directory}/bin/ld.lld`),
updateAptAlternatives("llvm-ar", `${directory}/bin/llvm-ar`),
addUpdateAlternativesToRc("cc", `${directory}/bin/clang`, rcOptions, priority),
addUpdateAlternativesToRc("cxx", `${directory}/bin/clang++`, rcOptions, priority),
addUpdateAlternativesToRc("clang", `${directory}/bin/clang`, rcOptions),
addUpdateAlternativesToRc("clang++", `${directory}/bin/clang++`, rcOptions),
addUpdateAlternativesToRc("lld", `${directory}/bin/lld`, rcOptions),
addUpdateAlternativesToRc("ld.lld", `${directory}/bin/ld.lld`, rcOptions),
addUpdateAlternativesToRc("llvm-ar", `${directory}/bin/llvm-ar`, rcOptions),
)
}

View File

@ -2,10 +2,11 @@ import { info } from "console"
import { execRoot } from "admina"
import { execa } from "execa"
import { chmod, readFile, writeFile } from "fs/promises"
import { DEFAULT_TIMEOUT } from "../installTool"
import { addPath } from "../utils/env/addEnv"
import { aptTimeout, hasNala, isPackageRegexInstalled, setupAptPack } from "../utils/setup/setupAptPack"
import type { InstallationInfo } from "../utils/setup/setupBin"
import { addPath } from "os-env"
import { aptTimeout, hasNala, installAptPack, isAptPackRegexInstalled } from "setup-apt"
import { rcOptions } from "../cli-options.js"
import { DEFAULT_TIMEOUT } from "../installTool.js"
import type { InstallationInfo } from "../utils/setup/setupBin.js"
export enum LLVMPackages {
All = 0,
@ -20,10 +21,10 @@ export async function setupLLVMApt(
// TODO for older versions, this also includes the minor version
const installationFolder = `/usr/lib/llvm-${majorVersion}`
await setupAptPack([{ name: "curl" }])
await installAptPack([{ name: "curl" }])
await execa("curl", ["-LJO", "https://apt.llvm.org/llvm.sh"], { cwd: "/tmp" })
const neededPackages = await patchAptLLVMScript("/tmp/llvm.sh", "/tmp/llvm-setup-cpp.sh", majorVersion, packages)
await setupAptPack(neededPackages)
await installAptPack(neededPackages)
await chmod("/tmp/llvm-setup-cpp.sh", "755")
await execRoot(
"bash",
@ -35,7 +36,7 @@ export async function setupLLVMApt(
},
)
await addPath(`${installationFolder}/bin`)
await addPath(`${installationFolder}/bin`, rcOptions)
return {
installDir: `${installationFolder}`,
@ -87,7 +88,7 @@ async function removeConflictingPackages(givenScript: string) {
await Promise.all(
conflictingPackages.map(async (pack) => {
const installingPack = pack.replace("$LLVM_VERSION", "*")
if (await isPackageRegexInstalled(installingPack)) {
if (await isAptPackRegexInstalled(installingPack)) {
info(`Removing conflicting package ${installingPack}`)
script = script.replace(pack, "")
}

View File

@ -2,9 +2,9 @@ import { info, warning } from "ci-log"
import { isUrlOnline } from "is-url-online"
import { addExeExt } from "patha"
import semverLte from "semver/functions/lte"
import { extractExe, extractTarByExe } from "../utils/setup/extract"
import type { PackageInfo } from "../utils/setup/setupBin"
import { getSpecificVersionAndUrl, getSpecificVersions, getVersions } from "../utils/setup/version"
import { extractExe, extractTarByExe } from "../utils/setup/extract.js"
import type { PackageInfo } from "../utils/setup/setupBin.js"
import { getSpecificVersionAndUrl, getSpecificVersions, getVersions } from "../utils/setup/version.js"
// ================================================
// Version

Some files were not shown because too many files have changed in this diff Show More