From c3ef13296be0f90de0ebf0b4056d9fe386df044a Mon Sep 17 00:00:00 2001 From: Miles Johnson Date: Sat, 15 Apr 2023 16:57:29 -0700 Subject: [PATCH] Implement action. --- CHANGELOG.md | 27 +-------- README.md | 18 ++++++ action.yml | 14 ++++- index.ts | 141 +++++++++++++++++++++++++++++++++++++++++- package.json | 5 +- pnpm-lock.yaml | 162 ++++++------------------------------------------- 6 files changed, 192 insertions(+), 175 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d4efc0c..0dbeb4f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,28 +1,3 @@ -# 1.5.0 - -- Support moon v1. -- Support `PROTO` env vars. - -# 1.4.0 - -- Support moon v0.24 comparison estimate changes. - -# 1.3.0 - -- Support new remote caching status. -- Use human readable status labels. - -# 1.2.0 - -- Added `limit` input setting, that limits the number of actions in the table. Overflow actions will - be displayed in an expandable section. -- Fixed some issues around duration calculation. - -# 1.1.0 - -- Added total time, projected time, and estimated savings/loss information. Requires moon >= 0.15. -- Added `slow-threshold` input setting. - -# 1.0.0 +# Unreleased - Initial release. diff --git a/README.md b/README.md index 1ceafce..d4aae2a 100644 --- a/README.md +++ b/README.md @@ -1 +1,19 @@ # Setup Rust + +A GitHub action for setting up Rust and Cargo. Will automatically install the appropriate toolchain +with `rustup` by inspecting the `RUSTUP_TOOLCHAIN` environment variable or the `rust-toolchain.toml` +configuration file. + +## Installation + +```yaml +# ... +jobs: + ci: + name: CI + runs-on: ubuntu-latest + steps: + # ... + - uses: moonrepo/setup-rust@v0 + - run: cargo test +``` diff --git a/action.yml b/action.yml index 8f6b660..97b1171 100644 --- a/action.yml +++ b/action.yml @@ -1,11 +1,19 @@ name: 'Setup Rust' author: 'Miles Johnson' description: 'Sets up Rust and Cargo.' -inputs: {} +inputs: + channel: + description: 'Toolchain specification/channel to install.' + components: + description: 'Comma-separated list of additional components to install.' + targets: + description: 'Comma-separated list of additional targets to install.' + profile: + description: 'Profile to install. Defaults to "minimal".' outputs: {} runs: using: 'node16' main: 'dist/index.js' branding: - icon: 'moon' - color: 'purple' + icon: 'settings' + color: 'orange' diff --git a/index.ts b/index.ts index cb0ff5c..651b7f5 100644 --- a/index.ts +++ b/index.ts @@ -1 +1,140 @@ -export {}; +import fs from 'fs'; +import path from 'path'; +import * as core from '@actions/core'; +import * as exec from '@actions/exec'; +import TOML from '@ltd/j-toml'; + +interface Toolchain { + channel: string; + components: string[]; + targets: string[]; + profile: string; +} + +interface ToolchainConfig { + toolchain: Partial; +} + +const DEFAULT_TOOLCHAIN: Toolchain = { + channel: 'stable', + components: [], + profile: 'minimal', + targets: [], +}; + +function parseConfig(configPath: string): Partial { + const contents = fs.readFileSync(configPath, 'utf8').trim(); + + if (!contents.includes('[toolchain]')) { + core.debug('No [toolchain] section found, assuming legacy format'); + + return { channel: contents }; + } + + const config = TOML.parse(contents) as unknown as ToolchainConfig; + + if (config.toolchain.channel) { + core.debug('Found channel in [toolchain] section'); + + return { channel: config.toolchain.channel }; + } + + core.debug('No channel found in [toolchain] section'); + + return {}; +} + +// https://rust-lang.github.io/rustup/overrides.html +function detectToolchain(): Toolchain { + core.info('Detecting toolchain'); + + const toolchain = { ...DEFAULT_TOOLCHAIN }; + + if (process.env.RUSTUP_TOOLCHAIN) { + core.info('Using toolchain from RUSTUP_TOOLCHAIN environment variable'); + + Object.assign(toolchain, { + channel: process.env.RUSTUP_TOOLCHAIN, + }); + } else { + core.info('Searching for rust-toolchain.toml or rust-toolchain file'); + + for (const configName of ['rust-toolchain.toml', 'rust-toolchain']) { + const configPath = path.join(process.cwd(), configName); + + if (fs.existsSync(configPath)) { + core.debug(`Found ${configName}, parsing TOML`); + + Object.assign(toolchain, parseConfig(configPath)); + break; + } + } + } + + core.info('Inheriting toolchain settings from inputs'); + + (Object.keys(DEFAULT_TOOLCHAIN) as (keyof typeof DEFAULT_TOOLCHAIN)[]).forEach((key) => { + const input = core.getInput(key); + + if (input) { + core.debug(`Found input for ${key}: ${input}`); + + if (key === 'components' || key === 'targets') { + input.split(',').forEach((part) => { + toolchain[key].push(part.trim()); + }); + } else { + toolchain[key] = input; + } + } + }); + + return toolchain; +} + +async function installToolchain(toolchain: Toolchain) { + core.info('Installing toolchain with rustup'); + + const args = ['toolchain', 'install', toolchain.channel, '--profile', toolchain.profile]; + + toolchain.targets.forEach((target) => { + args.push('--target', target); + }); + + toolchain.components.forEach((component) => { + args.push('--component', component); + }); + + if (toolchain.channel === 'nightly' && toolchain.components.length > 0) { + args.push('--allow-downgrade'); + } + + args.push('--no-self-update'); + + await exec.exec('rustup', args); + await exec.exec('rustup', ['default', toolchain.channel]); + + core.info('Logging installed toolchain versions'); + + await exec.exec('rustc', [`+${toolchain.channel}`, '--version', '--verbose']); +} + +async function run() { + try { + await installToolchain(detectToolchain()); + } catch (error: unknown) { + core.setFailed((error as Error).message); + + throw error; + } + + core.info('Setting cargo environment variables'); + + // Disable incremental compilation + core.exportVariable('CARGO_INCREMENTAL', '0'); + + // Always enable colored output + core.exportVariable('CARGO_TERM_COLOR', 'always'); +} + +void run(); diff --git a/package.json b/package.json index b34ff0e..87e1e83 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@moonrepo/setup-rust", "version": "0.1.0", - "description": "A GitHub action that for setting up Rust and Cargo.", + "description": "A GitHub action for setting up Rust and Cargo.", "main": "dist/index.js", "scripts": { "build": "ncc build ./index.ts", @@ -17,7 +17,8 @@ "license": "MIT", "dependencies": { "@actions/core": "^1.10.0", - "@actions/github": "^5.1.1" + "@actions/exec": "^1.1.1", + "@ltd/j-toml": "^1.38.0" }, "devDependencies": { "@types/node": "^18.15.10", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 632eb91..3ee9830 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,9 +4,12 @@ dependencies: '@actions/core': specifier: ^1.10.0 version: 1.10.0 - '@actions/github': - specifier: ^5.1.1 - version: 5.1.1 + '@actions/exec': + specifier: ^1.1.1 + version: 1.1.1 + '@ltd/j-toml': + specifier: ^1.38.0 + version: 1.38.0 devDependencies: '@types/node': @@ -43,15 +46,10 @@ packages: uuid: 8.3.2 dev: false - /@actions/github@5.1.1: - resolution: {integrity: sha512-Nk59rMDoJaV+mHCOJPXuvB1zIbomlKS0dmSIqPGxd0enAXBnOfn4VWF+CGtRCwXZG9Epa54tZA7VIRlJDS8A6g==} + /@actions/exec@1.1.1: + resolution: {integrity: sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==} dependencies: - '@actions/http-client': 2.1.0 - '@octokit/core': 3.6.0 - '@octokit/plugin-paginate-rest': 2.21.3(@octokit/core@3.6.0) - '@octokit/plugin-rest-endpoint-methods': 5.16.2(@octokit/core@3.6.0) - transitivePeerDependencies: - - encoding + '@actions/io': 1.1.3 dev: false /@actions/http-client@2.1.0: @@ -60,6 +58,10 @@ packages: tunnel: 0.0.6 dev: false + /@actions/io@1.1.3: + resolution: {integrity: sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==} + dev: false + /@babel/code-frame@7.21.4: resolution: {integrity: sha512-LYvhNKfwWSPpocw8GI7gpK2nq3HSDuEPC/uSYaALSJu9xjsalaaYFOq0Pwt5KmVqwEbZlDu81aLXwBOmD/Fv9g==} engines: {node: '>=6.9.0'} @@ -145,6 +147,10 @@ packages: resolution: {integrity: sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==} dev: true + /@ltd/j-toml@1.38.0: + resolution: {integrity: sha512-lYtBcmvHustHQtg4X7TXUu1Xa/tbLC3p2wLvgQI+fWVySguVZJF60Snxijw5EiohumxZbR10kWYFFebh1zotiw==} + dev: false + /@mdn/browser-compat-data@5.2.50: resolution: {integrity: sha512-3qGRdT2lrIloY8xotSRTW7k3oIRJAO7WSsJymTLN1sqeB1qiWPcbQdAiDG/IQWCA2QCVQewTeT2kfZf/you94w==} dev: true @@ -179,94 +185,6 @@ packages: fastq: 1.15.0 dev: true - /@octokit/auth-token@2.5.0: - resolution: {integrity: sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==} - dependencies: - '@octokit/types': 6.41.0 - dev: false - - /@octokit/core@3.6.0: - resolution: {integrity: sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==} - dependencies: - '@octokit/auth-token': 2.5.0 - '@octokit/graphql': 4.8.0 - '@octokit/request': 5.6.3 - '@octokit/request-error': 2.1.0 - '@octokit/types': 6.41.0 - before-after-hook: 2.2.3 - universal-user-agent: 6.0.0 - transitivePeerDependencies: - - encoding - dev: false - - /@octokit/endpoint@6.0.12: - resolution: {integrity: sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==} - dependencies: - '@octokit/types': 6.41.0 - is-plain-object: 5.0.0 - universal-user-agent: 6.0.0 - dev: false - - /@octokit/graphql@4.8.0: - resolution: {integrity: sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==} - dependencies: - '@octokit/request': 5.6.3 - '@octokit/types': 6.41.0 - universal-user-agent: 6.0.0 - transitivePeerDependencies: - - encoding - dev: false - - /@octokit/openapi-types@12.11.0: - resolution: {integrity: sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==} - dev: false - - /@octokit/plugin-paginate-rest@2.21.3(@octokit/core@3.6.0): - resolution: {integrity: sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==} - peerDependencies: - '@octokit/core': '>=2' - dependencies: - '@octokit/core': 3.6.0 - '@octokit/types': 6.41.0 - dev: false - - /@octokit/plugin-rest-endpoint-methods@5.16.2(@octokit/core@3.6.0): - resolution: {integrity: sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==} - peerDependencies: - '@octokit/core': '>=3' - dependencies: - '@octokit/core': 3.6.0 - '@octokit/types': 6.41.0 - deprecation: 2.3.1 - dev: false - - /@octokit/request-error@2.1.0: - resolution: {integrity: sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==} - dependencies: - '@octokit/types': 6.41.0 - deprecation: 2.3.1 - once: 1.4.0 - dev: false - - /@octokit/request@5.6.3: - resolution: {integrity: sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==} - dependencies: - '@octokit/endpoint': 6.0.12 - '@octokit/request-error': 2.1.0 - '@octokit/types': 6.41.0 - is-plain-object: 5.0.0 - node-fetch: 2.6.9 - universal-user-agent: 6.0.0 - transitivePeerDependencies: - - encoding - dev: false - - /@octokit/types@6.41.0: - resolution: {integrity: sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==} - dependencies: - '@octokit/openapi-types': 12.11.0 - dev: false - /@tsconfig/node14@1.0.3: resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} dev: true @@ -561,10 +479,6 @@ packages: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} dev: true - /before-after-hook@2.2.3: - resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} - dev: false - /brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} dependencies: @@ -744,10 +658,6 @@ packages: object-keys: 1.1.1 dev: true - /deprecation@2.3.1: - resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} - dev: false - /dir-glob@3.0.1: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} @@ -1720,11 +1630,6 @@ packages: engines: {node: '>=8'} dev: true - /is-plain-object@5.0.0: - resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} - engines: {node: '>=0.10.0'} - dev: false - /is-regex@1.1.4: resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} engines: {node: '>= 0.4'} @@ -1974,18 +1879,6 @@ packages: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} dev: true - /node-fetch@2.6.9: - resolution: {integrity: sha512-DJm/CJkZkRjKKj4Zi4BsKVZh3ValV5IR5s7LVZnW+6YMh0W1BfNA8XSs6DLMGYlId5F3KnA70uu2qepcR08Qqg==} - engines: {node: 4.x || >=6.0.0} - peerDependencies: - encoding: ^0.1.0 - peerDependenciesMeta: - encoding: - optional: true - dependencies: - whatwg-url: 5.0.0 - dev: false - /node-releases@2.0.10: resolution: {integrity: sha512-5GFldHPXVG/YZmFzJvKK2zDSzPKhEp0+ZR5SVaoSag9fsL5YgHbUHDfnG5494ISANDcK4KwPXAx2xqVEydmd7w==} dev: true @@ -2076,6 +1969,7 @@ packages: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 + dev: true /onetime@5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} @@ -2511,10 +2405,6 @@ packages: is-number: 7.0.0 dev: true - /tr46@0.0.3: - resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: false - /tsconfig-moon@1.3.0: resolution: {integrity: sha512-OVa+cjaKIsXIQqEWVqvF3xH6xmFOjKnbwiCmAKx2J8uq7M1KTX/NFFi/YXZdKb6YjHJhq8tvg2JsGSBTxTANcQ==} dev: true @@ -2592,10 +2482,6 @@ packages: which-boxed-primitive: 1.0.2 dev: true - /universal-user-agent@6.0.0: - resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} - dev: false - /update-browserslist-db@1.0.11(browserslist@4.21.5): resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} hasBin: true @@ -2625,17 +2511,6 @@ packages: spdx-expression-parse: 3.0.1 dev: true - /webidl-conversions@3.0.1: - resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: false - - /whatwg-url@5.0.0: - resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} - dependencies: - tr46: 0.0.3 - webidl-conversions: 3.0.1 - dev: false - /which-boxed-primitive@1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} dependencies: @@ -2682,6 +2557,7 @@ packages: /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true /yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}