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 fail-fast: false
matrix: matrix:
os: os:
- ubuntu-24.04 - ubuntu-22.04
node: node:
- 22 - 22.6.0
pnpm: pnpm:
- 9 - 9.6.0
steps: steps:
- uses: actions/checkout@v4 - 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 - name: Setup Node
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:

1
.gitignore vendored
View File

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

3
.npmrc
View File

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

View File

@ -66,6 +66,7 @@
"files.insertFinalNewline": true, "files.insertFinalNewline": true,
"files.trimFinalNewlines": true, "files.trimFinalNewlines": true,
"hadolint.hadolintPath": "./target/bin/hadolint", "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", "$schema": "https://biomejs.dev/schemas/1.8.3/schema.json",
"files": { "files": {
"ignore": [ "ignore": [
"**/node_modules/**", "**/node_modules/**",
"**/.pnpm-store/**", "**/.pnpm-store/**",
"**/dist/**", "**/dist/**",
"dev/cpp_vcpkg_project/**/*", "dev/cpp_vcpkg_project/**/*",
"**/.venv/", "**/.venv/",
"**/.*cache/", "**/.*cache/",
"**/coverage/" "**/coverage/"
], ],
"ignoreUnknown": true "ignoreUnknown": true
}, },
"organizeImports": { "organizeImports": {
"enabled": true "enabled": true
}, },
"linter": { "linter": {
"enabled": true, "enabled": true,
"rules": { "rules": {
"recommended": true, "recommended": true,
"style": { "style": {
"noInferrableTypes": "off", "noInferrableTypes": "off",
"noUselessElse": "off", "noUselessElse": "off",
"noNonNullAssertion": "off", "noNonNullAssertion": "off",
"useNodejsImportProtocol": "off" "useNodejsImportProtocol": "off"
}, },
"complexity": { "complexity": {
"useLiteralKeys": "off" "useLiteralKeys": "off"
}, },
"suspicious": { "suspicious": {
"noConfusingVoidType": "off" "noConfusingVoidType": "off"
} },
} "nursery": {
}, "useImportExtensions": "warn"
"formatter": { }
"enabled": false,
"indentWidth": 4,
"indentStyle": "space"
},
"json": {
"formatter": {
"enabled": false,
"trailingCommas": "none"
},
"parser": {
"allowComments": true,
"allowTrailingCommas": true
}
} }
},
"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 - choco
- clangd - clangd
- cmake - cmake
- iarna
- cobertura - cobertura
- copr - copr
- CPATH - 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", "module.sortImportDeclarations": "maintain",
"importDeclaration.sortNamedImports": "maintain" "importDeclaration.sortNamedImports": "maintain"
}, },
"json": {}, "json": {
"trailingCommas": "never"
},
"markdown": {}, "markdown": {},
"dockerfile": {}, "dockerfile": {},
"exec": { "exec": {
@ -26,7 +28,7 @@
] ]
}, },
"includes": [ "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": [ "excludes": [
"**/node_modules", "**/node_modules",

View File

@ -8,6 +8,10 @@ const jestConfig: Config = {
transform: { transform: {
"^.+\\.(t|j)sx?$": "@swc/jest", "^.+\\.(t|j)sx?$": "@swc/jest",
}, },
// resolve js files from ts files
moduleNameMapper: {
"(.+)\\.js": "$1",
},
// coverage // coverage
collectCoverageFrom: ["src/**/*.{ts,tsx,js,jsx}"], collectCoverageFrom: ["src/**/*.{ts,tsx,js,jsx}"],
coveragePathIgnorePatterns: ["assets", ".css.d.ts"], 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" "tsconfig.json"
], ],
"scripts": { "scripts": {
"build": "run-s clean build.packages && run-p lint.tsc build.parcel copy.matchers", "build": "turbo build && run-p lint.root.tsc build.parcel copy.matchers && run-s build.babel build.modern",
"build.packages": "pnpm run -r build", "build.parcel": "cross-env NODE_ENV=production parcel build",
"build.parcel": "cross-env NODE_ENV=production parcel build && run-s build.babel && shx cp -r ./dist/actions/* ./dist/modern",
"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.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", "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": "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.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/", "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", "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", "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", "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.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.biome": "biome check --write --unsafe",
"lint.dprint": "dprint fmt", "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", "pack.exe": "shx rm -rf ./dist/tsconfig.tsbuildinfo && node ./dev/scripts/pack-exe.mjs",
"prepublishOnly": "rm ./dist/tsconfig.tsbuildinfo", "publish.all": "pnpm -r publish && pnpm publish",
"test.lint": "run-p --aggregate-output --continue-on-error lint.cspell test.lint.eslint test.lint.dprint lint.tsc test.lint.biome", "prepublishOnly": "run-s build && shx rm ./dist/tsconfig.tsbuildinfo",
"test.lint.eslint": "eslint **/*.{ts,tsx,js,jsx,cjs,mjs,json,yaml} --no-error-on-unmatched-pattern --cache --cache-location ./.cache/eslint/", "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.biome": "biome check",
"test.lint.dprint": "dprint check", "test.lint.dprint": "dprint check",
"test": "jest --runInBand --forceExit --coverage", "test": "jest --runInBand --forceExit --coverage",
@ -57,15 +58,18 @@
"devDependencies": { "devDependencies": {
"@actions/core": "^1.10.1", "@actions/core": "^1.10.1",
"@actions/exec": "^1.1.1", "@actions/exec": "^1.1.1",
"@actions/http-client": "^2.2.1",
"@actions/io": "^1.1.3", "@actions/io": "^1.1.3",
"@actions/tool-cache": "^2.0.1", "@actions/tool-cache": "^2.0.1",
"@babel/cli": "^7.24.8", "@babel/cli": "^7.24.8",
"@babel/plugin-transform-private-methods": "^7.24.7", "@babel/plugin-transform-private-methods": "^7.24.7",
"@biomejs/biome": "^1.8.3", "@biomejs/biome": "^1.8.3",
"@iarna/toml": "^2.2.5",
"@shockpkg/archive-files": "github:aminya/archive-files#54ec59fad46aca736ac6feb6c7bb526528141b9d", "@shockpkg/archive-files": "github:aminya/archive-files#54ec59fad46aca736ac6feb6c7bb526528141b9d",
"@swc/jest": "^0.2.36", "@swc/jest": "^0.2.36",
"@types/cross-spawn": "^6.0.6", "@types/cross-spawn": "^6.0.6",
"@types/eslint": "^8.56.11", "@types/eslint": "^8.56.11",
"@types/iarna__toml": "~2.0.5",
"@types/jest": "^29.5.12", "@types/jest": "^29.5.12",
"@types/node": "^12.20.55", "@types/node": "^12.20.55",
"@types/semver": "^7.5.8", "@types/semver": "^7.5.8",
@ -77,26 +81,29 @@
"ci-log": "workspace:*", "ci-log": "workspace:*",
"cross-env": "7.0.3", "cross-env": "7.0.3",
"cross-spawn": "^7.0.3", "cross-spawn": "^7.0.3",
"cspell": "^8.13.1", "cspell": "^8.13.3",
"diagnostics_channel": "^1.1.0", "diagnostics_channel": "^1.1.0",
"dprint": "^0.47.2", "dprint": "^0.47.2",
"escape-path-with-spaces": "^1.0.2", "escape-path-with-spaces": "^1.0.2",
"escape-quotes": "^1.0.2", "escape-quotes": "^1.0.2",
"escape-string-regexp": "^5.0.0", "escape-string-regexp": "^5.0.0",
"setup-apt": "workspace:*",
"eslint": "^8.57.0", "eslint": "^8.57.0",
"eslint-config-atomic": "^1.22.0", "eslint-config-atomic": "^1.22.1",
"exec-powershell": "workspace:*", "exec-powershell": "workspace:*",
"execa": "^7.2.0", "execa": "^7.2.0",
"is-url-online": "^1.5.0", "is-url-online": "^1.5.0",
"jest": "^29.7.0", "jest": "^29.7.0",
"lefthook": "^1.7.12",
"macos-release": "^3.3.0", "macos-release": "^3.3.0",
"micro-memoize": "^4.1.2", "micro-memoize": "^4.1.2",
"mkdirp": "^3.0.1", "mkdirp": "^3.0.1",
"mri": "^1.2.0", "mri": "^1.2.0",
"msvc-dev-cmd": "github:aminya/msvc-dev-cmd#c01f519bd995460228ed3dec4df51df92dc290fd", "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", "npm-run-all2": "^6.2.2",
"numerous": "1.0.3", "numerous": "1.0.3",
"os-env": "workspace:*",
"p-timeout": "^6.1.2", "p-timeout": "^6.1.2",
"parcel": "2.12.0", "parcel": "2.12.0",
"path-exists": "^5.0.0", "path-exists": "^5.0.0",
@ -113,6 +120,7 @@
"time-delta": "github:aminya/time-delta#69d91a41cef28e569be9a2991129f5f7d1f0d00e", "time-delta": "github:aminya/time-delta#69d91a41cef28e569be9a2991129f5f7d1f0d00e",
"ts-node": "^10.9.2", "ts-node": "^10.9.2",
"ts-readme": "^1.1.3", "ts-readme": "^1.1.3",
"turbo": "2.0.14",
"typescript": "^5.5.4", "typescript": "^5.5.4",
"ubuntu-version": "^2.0.0", "ubuntu-version": "^2.0.0",
"untildify-user": "workspace:*", "untildify-user": "workspace:*",
@ -123,11 +131,14 @@
"productionDependencies": [ "productionDependencies": [
"@actions/core", "@actions/core",
"@actions/exec", "@actions/exec",
"@actions/http-client",
"@actions/io", "@actions/io",
"@actions/tool-cache", "@actions/tool-cache",
"@iarna/toml",
"admina", "admina",
"ci-info", "ci-info",
"ci-log", "ci-log",
"diagnostics_channel",
"escape-path-with-spaces", "escape-path-with-spaces",
"escape-quotes", "escape-quotes",
"escape-string-regexp", "escape-string-regexp",
@ -138,23 +149,28 @@
"mri", "mri",
"msvc-dev-cmd", "msvc-dev-cmd",
"numerous", "numerous",
"os-env",
"path-exists", "path-exists",
"patha", "patha",
"retry-as-promised", "retry-as-promised",
"semver", "semver",
"setup-apt",
"setup-python", "setup-python",
"simple-update-notifier", "simple-update-notifier",
"time-delta", "time-delta",
"ubuntu-version", "ubuntu-version",
"untildify-user", "untildify-user",
"web-streams-polyfill",
"util.types", "util.types",
"diagnostics_channel" "web-streams-polyfill"
], ],
"engines": { "engines": {
"node": ">=12.x", "node": ">=12.x",
"pnpm": "^9" "pnpm": "^9"
}, },
"packageManager": "pnpm@9.6.0",
"workspaces": [
"packages/*"
],
"keywords": [ "keywords": [
"github-actions", "github-actions",
"actions", "actions",

View File

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

View File

@ -2,13 +2,17 @@
"name": "ci-log", "name": "ci-log",
"version": "1.0.0", "version": "1.0.0",
"description": "Colorful logging and print for any environment including GitHub Actions", "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", "license": "Apache-2.0",
"author": "Amin Yahyaabadi", "author": "Amin Yahyaabadi",
"main": "./dist/index.js", "main": "./dist/index.js",
"source": "./src/index.ts", "source": "./src/index.ts",
"scripts": { "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": { "dependencies": {
"@actions/core": "^1.10.1", "@actions/core": "^1.10.1",

View File

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

View File

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

View File

@ -2,17 +2,22 @@
"name": "exec-powershell", "name": "exec-powershell",
"version": "1.0.0", "version": "1.0.0",
"description": "Run a powershell command.", "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", "license": "Apache-2.0",
"author": "Amin Yahyaabadi", "author": "Amin Yahyaabadi",
"main": "./dist/index.js", "main": "./dist/index.js",
"source": "./src/index.ts", "source": "./src/index.ts",
"scripts": { "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": { "dependencies": {
"execa": "<8", "execa": "^7",
"which": "^4.0.0" "which": "^4.0.0",
"@types/node": "^14"
}, },
"devDependencies": { "devDependencies": {
"@types/which": "^3.0.0" "@types/which": "^3.0.0"

View File

@ -1,7 +1,9 @@
{ {
"extends": "../../tsconfig.json", "extends": "../../tsconfig.json",
"compilerOptions": { "compilerOptions": {
"outDir": "./dist" "outDir": "./dist",
"noEmit": false,
"allowImportingTsExtensions": false
}, },
"include": ["./src"] "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", "name": "untildify-user",
"version": "1.0.0", "version": "1.0.0",
"description": "Untildify a path for the current user even if it is root", "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", "license": "Apache-2.0",
"author": "Amin Yahyaabadi", "author": "Amin Yahyaabadi",
"main": "./dist/index.js", "main": "./dist/index.js",
"source": "./src/index.ts", "source": "./src/index.ts",
"scripts": { "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": { "dependencies": {
"admina": "1.0.1" "admina": "1.0.1"

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -1,11 +1,11 @@
import { execRootSync } from "admina" import { execRootSync } from "admina"
import { hasDnf } from "../utils/env/hasDnf" import { addAptKeyViaDownload, installAptPack } from "setup-apt"
import { isArch } from "../utils/env/isArch" import { hasDnf } from "../utils/env/hasDnf.js"
import { isUbuntu } from "../utils/env/isUbuntu" import { isArch } from "../utils/env/isArch.js"
import { addAptKeyViaDownload, setupAptPack } from "../utils/setup/setupAptPack" import { isUbuntu } from "../utils/env/isUbuntu.js"
import { setupBrewPack } from "../utils/setup/setupBrewPack" import { setupBrewPack } from "../utils/setup/setupBrewPack.js"
import { setupChocoPack } from "../utils/setup/setupChocoPack" import { setupChocoPack } from "../utils/setup/setupChocoPack.js"
import { setupDnfPack } from "../utils/setup/setupDnfPack" import { setupDnfPack } from "../utils/setup/setupDnfPack.js"
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
export async function setupBazel(version: string, _setupDir: string, _arch: string) { 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", "-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`, `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") throw new Error("Unsupported linux distribution")
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,6 @@
import { testBin } from "../../utils/tests/test-helpers" import { testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions" import { getVersion } from "../../versions/versions.js"
import { setupConan } from "../conan" import { setupConan } from "../conan.js"
jest.setTimeout(300000) jest.setTimeout(300000)
describe("setup-conan", () => { 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 // eslint-disable-next-line @typescript-eslint/no-unused-vars
export function setupConan(version: string | undefined, _setupDir: string, _arch: string) { export function setupConan(version: string | undefined, _setupDir: string, _arch: string) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,7 +1,8 @@
import { addEnv } from "os-env"
import semverMajor from "semver/functions/major" import semverMajor from "semver/functions/major"
import semverValid from "semver/functions/valid" import semverValid from "semver/functions/valid"
import { addEnv } from "../utils/env/addEnv" import { rcOptions } from "../cli-options.js"
import { setupPipPack } from "../utils/setup/setupPipPack" import { setupPipPack } from "../utils/setup/setupPipPack.js"
// eslint-disable-next-line @typescript-eslint/no-unused-vars // eslint-disable-next-line @typescript-eslint/no-unused-vars
export function setupGcovr(version: string | undefined, _setupDir: string, _arch: string) { 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() { export function activateGcovLLVM() {
return addEnv("GCOV", "llvm-cov gcov") return addEnv("GCOV", "llvm-cov gcov", rcOptions)
} }
export function activateGcovGCC(gccVersion: string) { export function activateGcovGCC(gccVersion: string) {
@ -17,5 +18,5 @@ export function activateGcovGCC(gccVersion: string) {
const gccMajor = gccSemver !== null ? semverMajor(gccSemver) : gccVersion const gccMajor = gccSemver !== null ? semverMajor(gccSemver) : gccVersion
const gcov = gccMajor !== "" ? `gcov-${gccMajor}` : "gcov" 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 { macosVersion } from "../../utils/env/macos_version.js"
import { ubuntuVersion } from "../../utils/env/ubuntu_version" import { ubuntuVersion } from "../../utils/env/ubuntu_version.js"
import type { InstallationInfo } from "../../utils/setup/setupBin" import type { InstallationInfo } from "../../utils/setup/setupBin.js"
import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers" import { cleanupTmpDir, setupTmpDir, testBin } from "../../utils/tests/test-helpers.js"
import { getVersion } from "../../versions/versions" import { getVersion } from "../../versions/versions.js"
import { setupGraphviz } from "../graphviz" import { setupGraphviz } from "../graphviz.js"
jest.setTimeout(300000) jest.setTimeout(300000)
describe("setup-graphviz", () => { describe("setup-graphviz", () => {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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