Automatic compilation

This commit is contained in:
github-actions[bot] 2025-02-20 18:04:21 +00:00 committed by GitHub
parent 52e0bc3392
commit ede6de059f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
19 changed files with 192278 additions and 4567 deletions

View file

@ -1,6 +0,0 @@
coverage/
dist/
node_modules/
*.min.js
*.map
*.snap

View file

@ -1,13 +0,0 @@
/* eslint-disable sort-keys */
module.exports = {
root: true,
extends: ['moon', 'moon/node'],
parserOptions: {
project: 'tsconfig.json',
tsconfigRootDir: __dirname,
},
rules: {
'unicorn/prefer-top-level-await': 'off',
},
};

View file

@ -1,50 +0,0 @@
name: 'Pipeline'
on:
push:
branches:
- 'master'
pull_request:
jobs:
ci:
name: 'CI'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm install -g pnpm
- run: pnpm install
- run: pnpm run check
action-default:
name: 'Action - Default'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm install -g pnpm
- run: pnpm install
- run: pnpm run build
- uses: ./ # self
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
action-warmup:
name: 'Action - Cache warmup'
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
fail-fast: false
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- run: npm install -g pnpm
- run: pnpm install
- run: pnpm run build
- uses: ./ # self
with:
cache-base: master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -1,20 +0,0 @@
name: Publish
on:
release:
types: [published, edited]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
ref: ${{ github.event.release.tag_name }}
- uses: actions/setup-node@v4
- run: npm install -g pnpm
- run: pnpm install
- run: pnpm run build
- uses: aboutte/build-and-tag-action@v2
with:
additional_files: 'dist/post/index.js'
env:
GITHUB_TOKEN: ${{ github.token }}

2
.gitignore vendored
View file

@ -1,2 +0,0 @@
node_modules/
dist/

View file

@ -1,54 +0,0 @@
# 1.2.2
- Updated dependencies.
# 1.2.1
- Pinned the `cargo-binstall` version to v1.8 to work around the 404 errors in CI.
- Added support for the `CARGO_BINSTALL_VERSION` environment variable.
# 1.2.0
- Added a `target-dirs` input, allowing the target folders to be specified. Can now cache multiple
target folders.
- Updated to skip caching a directory if it does not exist, instead of failing.
- Updated dependencies.
# 1.1.0
- Added a `cache-base` input. When provided, will only save cache on this branch/ref, but will
restore cache on all branches/refs.
- Updated dependencies.
# 1.0.3
- Include `GITHUB_WORKFLOW` in cache key.
- Updated dependencies.
# 1.0.2
- Switch to Node.js v20.
# 1.0.1
- Fixed an issue where a module was missing from the build.
# 1.0.0
- Will now install `rustup` if it does not exist in the environment.
- Added musl support to `cargo-binstall`.
# 0.6.0
- Breaking: Cargo `bins` must provide the `cargo-` crate prefix manually. This change allows
non-crate globals to be installed.
- Added a `cache-target` input, to customize which target profile is cached. Defaults to `debug`.
# 0.5.0
- Added `inherit-toolchain` input to inherit all settings from `rust-toolchain.toml`, and not just
`channel`.
# 0.1.0
- Initial release.

197
README.md
View file

@ -1,197 +0,0 @@
# Setup Rust and Cargo
A one-stop-shop GitHub action for setting up Rust and Cargo. Will automatically setup the Rust
toolchain with `rustup`, cache the `~/.cargo/registry` and `/target/debug` directories, and install
Cargo binaries (when applicable).
```yaml
jobs:
ci:
name: CI
runs-on: ubuntu-latest
steps:
# ...
- uses: moonrepo/setup-rust@v1
- run: cargo test
```
## Inputs
The following inputs are available for the action, and can be passed via `with`. All inputs are
optional.
- `bins` - Comma-separated list of global binaries to install into Cargo.
- `cache` - Toggle caching of directories. Defaults to `true`.
- `cache-base` - Base branch/ref to save a warmup cache on. Other branches/refs will restore from
this base.
- `cache-target` - Name of the target profile to cache. Defaults to `debug`.
- `channel` - Toolchain specification/channel to explicitly install.
- `components` - Comma-separated list of additional components to install.
- `inherit-toolchain` - Inherit all toolchain settings from the `rust-toolchain.toml` file. Defaults
to `false`.
- `targets` - Comma-separated list of additional targets to install.
- `target-dirs` - Comma-separated list of target folder paths, relative from the repository root.
Defaults to `target`.
- `profile` - Profile to install. Defaults to `minimal`.
## Configuring the Rust toolchain
This action will automatically install the appropriate toolchain with `rustup` by inspecting the
`RUSTUP_TOOLCHAIN` environment variable or the `rust-toolchain.toml` (preferred) or `rust-toolchain`
configuration files. If no toolchain found, will default to `stable`.
```toml
# rust-toolchain.toml
[toolchain]
channel = "1.68.0"
```
> When loading a configuration file, only the `channel` field is used, while the other fields are
> ignored. We chose this approach, as those other fields are typically for develop/release
> workflows, but not for CI, which requires a minimal/granular setup. However, this can be
> overwritten with the `inherit-toolchain` input.
The toolchain/channel can also be explicitly configured with the `channel` input, which takes
highest precedence.
```yaml
- uses: moonrepo/setup-rust@v1
with:
channel: '1.65.0'
```
### Profile, components, and targets
Furthermore, this action supports rustup profiles, components, and targets, which can be configured
with the `profile`, `components`, and `targets` inputs respectively. When not defined, profile
defaults to `minimal`.
```yaml
- uses: moonrepo/setup-rust@v1
with:
profile: complete
```
When using components, the input requires a comma separated list of component names.
```yaml
- uses: moonrepo/setup-rust@v1
with:
components: clippy
- run: cargo clippy --workspace
```
When using targets, the input requires a comma separated list of target triples.
```yaml
- uses: moonrepo/setup-rust@v1
with:
targets: 'x86_64-pc-windows-msvc,x86_64-pc-windows-gnu'
```
## Installing Cargo binaries
If you require `cargo-make`, `cargo-nextest`, or other global binaries, this action supports
installing Cargo binaries through the `bins` input, which requires a comma-separated list of crate
names.
```yaml
- uses: moonrepo/setup-rust@v1
with:
bins: cargo-nextest, cargo-insta@1.28.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```
> Binaries are installed with [`cargo-binstall`](https://crates.io/crates/cargo-binstall) under the
> hood. We suggest setting `GITHUB_TOKEN` to avoid rate limiting.
## Caching in CI
By default this action will cache the `~/.cargo/registry` and `/target/debug` directories to improve
CI times. To disable caching, set the `cache` input to `false`. Furthermore, the target profile can
be changed with the `cache-target` input, which defaults to `debug`.
```yaml
- uses: moonrepo/setup-rust@v1
with:
cache: false
cache-target: release
```
The following optimizations and considerations are taken into account when caching:
- `~/.cargo`
- The `/bin` directory is not cached as we manage binary installation in this action via the
`bins` input.
- The `/git` directory is not cached as it's not necessary for CI. When required by Cargo or a
crate, a checkout will be performed on-demand.
- The `/registry` directory is _cleaned_ before saving the cache. This includes removing `src`,
`.cache`, and any other unnecessary files.
- `/target`
- Only the `/debug` profile is cached, as this profile is typically used for formatting, linting,
and testing. This can be changed with the `cache-target` input.
- The `/examples` and `/incremental` sub-directories are not cached as they are not necessary for
CI.
- All dep-info (`*.d`) files are removed, as they're meant for build systems and signaling
re-executions.
> The following sources are hashed for the generated cache key: `$GITHUB_JOB`, `Cargo.lock`, Rust
> version, Rust commit hash, and OS.
### Warmup strategy
Another strategy that we support is called a warmup cache, where a base branch/ref is used to
generate and save the cache (like master), and all other branches/refs will _only_ restore this
cache (and not save).
This can be enabled with the `cache-base` input, which requires a branch/ref name. This input also
supports regex.
```yaml
- uses: moonrepo/setup-rust@v1
with:
cache-base: master
# With regex
cache-base: (master|main|develop)
```
## Compared to
### `actions-rs/*`
The "official" actions have served their purpose, but after 3 years of no updates, severe lack of
maintenance, and being full of deprecation warnings, it was time to create something new.
Outside of being evergreen, this action also supports the following features:
- Automatically caches.
- Installs Cargo bins.
- Assumes `rustup`, `cargo`, and other commands are available globally. This allows you to use them
directly in a `run` command, without having to use `actions-rs/cargo`.
### `dtolnay/rust-toolchain`
Our action is very similar to theirs, which was a great implementation reference, but our action
also supports the following features:
- Extracts the toolchain/channel from `rust-toolchain.toml` and `rust-toolchain` configuration
files.
- Automatically caches.
- Installs Cargo bins.
### `Swatinem/rust-cache`
Their action only caches for Rust/Cargo, it doesn't actually setup Rust/Cargo. Our action is meant
to do _everything_, but it's not as configurable as the alternatives.
Here are the key differences between the two:
- Theirs caches the entire `~/.cargo` directory, while our action only caches `~/.cargo/registry`.
[View the reasoning above](#caching-in-ci).
- Our action also avoids an array of `~/.cargo/bin` issues that theirs currently has.
- Theirs includes compiler specific environment variables in the cache key, while our action
currently does not.
- Theirs supports a handful of inputs for controlling the cache key, while ours does not.
- Theirs is a bit more smart in what it caches, while ours is a bit more brute force. We simply
cache specific directories as-is after cleaning.

96156
dist/index.js vendored Normal file

File diff suppressed because one or more lines are too long

96122
dist/post/index.js vendored Normal file

File diff suppressed because one or more lines are too long

View file

@ -1,62 +0,0 @@
import fs from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as io from '@actions/io';
import * as tc from '@actions/tool-cache';
import { CARGO_HOME } from './src/cache';
import { installBins, restoreCache } from './src/cargo';
import { installToolchain } from './src/rust';
export async function installRustup() {
try {
await io.which('rustup', true);
return;
} catch {
// Doesn't exist
}
core.info('rustup does not exist, attempting to install');
const script = await tc.downloadTool(
process.platform === 'win32' ? 'https://win.rustup.rs' : 'https://sh.rustup.rs',
path.join(os.tmpdir(), 'rustup-init'),
);
core.info(`Downloaded installation script to ${script}`);
// eslint-disable-next-line no-magic-numbers
await fs.promises.chmod(script, 0o755);
await exec.exec(script, ['--default-toolchain', 'none', '-y']);
core.info('Installed rustup');
}
async function run() {
core.info('Setting cargo environment variables');
core.exportVariable('CARGO_INCREMENTAL', '0');
core.exportVariable('CARGO_TERM_COLOR', 'always');
core.info('Adding ~/.cargo/bin to PATH');
core.addPath(path.join(CARGO_HOME, 'bin'));
try {
await installRustup();
await installToolchain();
await installBins();
// Restore cache after the toolchain has been installed,
// as we use the rust version and commit hashes in the cache key!
await restoreCache();
} catch (error: unknown) {
core.setFailed((error as Error).message);
throw error;
}
}
void run();

View file

@ -1,41 +0,0 @@
{
"name": "@moonrepo/setup-rust",
"version": "1.2.2",
"description": "A GitHub action for setting up Rust and Cargo.",
"main": "dist/index.js",
"scripts": {
"build": "ncc build ./index.ts && ncc build ./post.ts --out ./dist/post",
"check": "pnpm run lint && pnpm run typecheck",
"lint": "eslint --ext .ts,.js --fix .",
"typecheck": "tsc --noEmit"
},
"repository": {
"type": "git",
"url": "https://github.com/moonrepo/setup-rust"
},
"author": "Miles Johnson",
"license": "MIT",
"dependencies": {
"@actions/cache": "^4.0.0",
"@actions/core": "^1.10.1",
"@actions/exec": "^1.1.1",
"@actions/glob": "^0.5.0",
"@actions/io": "^1.1.3",
"@actions/tool-cache": "^2.0.1",
"@ltd/j-toml": "^1.38.0",
"detect-libc": "^2.0.3"
},
"devDependencies": {
"@types/node": "^20.13.4",
"@vercel/ncc": "^0.38.1",
"eslint": "^8.53.0",
"eslint-config-moon": "^2.0.11",
"prettier": "^3.2.5",
"prettier-config-moon": "^1.1.2",
"tsconfig-moon": "^1.3.0",
"typescript": "^5.4.5"
},
"engines": {
"node": ">=20.0.0"
}
}

3576
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

19
post.ts
View file

@ -1,19 +0,0 @@
import * as core from '@actions/core';
import { saveCache } from './src/cargo';
async function run() {
try {
const base = core.getInput('cache-base');
// Only save the cache for the following 2 scenarios:
// - If not using the base warmup strategy.
// - If using the base warmup strategy, and the current ref matches.
if (!base || (base && !!(process.env.GITHUB_REF_NAME ?? '').match(base))) {
await saveCache();
}
} catch (error: unknown) {
core.setFailed((error as Error).message);
}
}
void run();

View file

@ -1 +0,0 @@
module.exports = 'prettier-config-moon';

View file

@ -1,102 +0,0 @@
import crypto from 'node:crypto';
import os from 'node:os';
import path from 'node:path';
import * as cache from '@actions/cache';
import * as core from '@actions/core';
import * as glob from '@actions/glob';
import { RUST_HASH, RUST_VERSION } from './rust';
export const CARGO_HOME = process.env.CARGO_HOME ?? path.join(os.homedir(), '.cargo');
export const WORKSPACE_ROOT = process.env.GITHUB_WORKSPACE ?? process.cwd();
export function isCacheEnabled(): boolean {
return core.getBooleanInput('cache') && cache.isFeatureAvailable();
}
export function getCacheTarget(): string {
return core.getInput('cache-target') || 'debug';
}
export function getTargetPaths(): string[] {
const profile = getCacheTarget();
const dirs = core.getInput('target-dirs', { required: true }).split(',');
return dirs
.map((dir) => dir.trim())
.filter(Boolean)
.map((dir) => path.join(WORKSPACE_ROOT, dir, profile));
}
export function getCachePaths(): string[] {
return [
// ~/.cargo/registry
path.join(CARGO_HOME, 'registry'),
// /workspace/target/debug
...getTargetPaths(),
];
}
export function getCachePrefixes(): string[] {
return [`setup-rustcargo-v1-${process.platform}`, 'setup-rustcargo-v1'];
}
export async function getPrimaryCacheKey() {
const hasher = crypto.createHash('sha1');
core.info('Generating cache key');
core.debug(`Hashing Rust version = ${RUST_VERSION}`);
hasher.update(RUST_VERSION);
core.debug(`Hashing Rust commit hash = ${RUST_HASH}`);
hasher.update(RUST_HASH);
const cacheTarget = getCacheTarget();
core.debug(`Hashing target profile = ${cacheTarget}`);
hasher.update(cacheTarget);
// When warming up, loosen the cache key to allow for more cache hits
if (core.getInput('cache-base')) {
core.debug('Using warmup strategy, not hashing Cargo.lock, GITHUB_WORKFLOW, or GITHUB_JOB');
hasher.update('warmup');
const baseRef = process.env.GITHUB_BASE_REF ?? '';
if (
baseRef === 'master' ||
baseRef === 'main' ||
baseRef === 'trunk' ||
baseRef.startsWith('develop') ||
baseRef.startsWith('release')
) {
core.debug(`Hashing GITHUB_BASE_REF = ${baseRef}`);
hasher.update(baseRef);
}
}
// Otherwise, these add far too much granularity to the cache key
else {
const lockHash = await glob.hashFiles('Cargo.lock');
core.debug(`Hashing Cargo.lock = ${lockHash}`);
hasher.update(lockHash);
const workflow = process.env.GITHUB_WORKFLOW;
if (workflow) {
core.debug(`Hashing GITHUB_WORKFLOW = ${workflow}`);
hasher.update(workflow);
}
const job = process.env.GITHUB_JOB;
if (job) {
core.debug(`Hashing GITHUB_JOB = ${job}`);
hasher.update(job);
}
}
return `${getCachePrefixes()[0]}-${hasher.digest('hex')}`;
}

View file

@ -1,230 +0,0 @@
import fs from 'node:fs';
import path from 'node:path';
import { family } from 'detect-libc';
import * as cache from '@actions/cache';
import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as glob from '@actions/glob';
import * as tc from '@actions/tool-cache';
import {
CARGO_HOME,
getCachePaths,
getCachePrefixes,
getCacheTarget,
getPrimaryCacheKey,
isCacheEnabled,
WORKSPACE_ROOT,
} from './cache';
import { rmrf } from './fs';
// eslint-disable-next-line complexity
export async function downloadAndInstallBinstall(binDir: string) {
core.info('cargo-binstall does not exist, attempting to install');
let arch;
let file;
switch (process.arch) {
case 'x64':
arch = 'x86_64';
break;
case 'arm':
arch = 'armv7';
break;
case 'arm64':
arch = 'aarch64';
break;
default:
throw new Error(`Unsupported architecture: ${process.arch}`);
}
switch (process.platform) {
case 'linux': {
let lib = 'gnu';
if ((await family()) === 'musl') {
lib = 'musl';
}
if (process.arch === 'arm') {
lib += 'eabihf';
}
file = `${arch}-unknown-linux-${lib}.tgz`;
break;
}
case 'darwin':
file = `${arch}-apple-darwin.zip`;
break;
case 'win32':
file = `${arch}-pc-windows-msvc.zip`;
break;
default:
throw new Error(`Unsupported platform: ${process.platform}`);
}
// https://github.com/cargo-bins/cargo-binstall/issues/1864
const version = process.env.CARGO_BINSTALL_VERSION ?? 'v1.8.0';
const url = version === 'latest'
? `https://github.com/cargo-bins/cargo-binstall/releases/latest/download/cargo-binstall-${file}`
: `https://github.com/cargo-bins/cargo-binstall/releases/download/${version}/cargo-binstall-${file}`;
const dlPath = await tc.downloadTool(url);
if (url.endsWith('.zip')) {
await tc.extractZip(dlPath, binDir);
} else if (url.endsWith('.tgz')) {
await tc.extractTar(dlPath, binDir);
}
}
export async function installBins() {
const bins = core
.getInput('bins')
.split(',')
.map((bin) => bin.trim())
.filter(Boolean);
if (isCacheEnabled()) {
bins.push('cargo-cache');
}
if (bins.length === 0) {
return;
}
core.info('Installing additional binaries');
const binDir = path.join(CARGO_HOME, 'bin');
if (!fs.existsSync(path.join(binDir, 'cargo-binstall'))) {
await downloadAndInstallBinstall(binDir);
}
await exec.exec('cargo', ['binstall', '--no-confirm', '--log-level', 'info', ...bins]);
}
export async function cleanCargoRegistry() {
core.info('Cleaning ~/.cargo before saving');
const registryDir = path.join(CARGO_HOME, 'registry');
// .cargo/registry/src - Delete entirely
await exec.exec('cargo', ['cache', '--autoclean']);
// .cargo/registry/index - Delete .cache directories
const indexDir = path.join(registryDir, 'index');
if (fs.existsSync(indexDir)) {
await Promise.all(
fs.readdirSync(indexDir).map(async (index) => {
if (fs.existsSync(path.join(indexDir, index, '.git'))) {
await rmrf(path.join(indexDir, index, '.cache'));
}
}),
);
}
// .cargo/registry/cache - Do nothing?
}
// https://doc.rust-lang.org/cargo/guide/build-cache.html
export async function cleanTargetProfile() {
const targetProfile = getCacheTarget();
core.info(`Cleaning target/${targetProfile} before saving`);
const targetDir = path.join(WORKSPACE_ROOT, 'target', targetProfile);
// target/*/{examples,incremental} - Not required in CI
core.info('Removing examples and incremental directories');
await Promise.all(
['examples', 'incremental'].map(async (dirName) => {
const dir = path.join(targetDir, dirName);
if (fs.existsSync(dir)) {
await rmrf(dir);
}
}),
);
// target/**/*.d - Not required in CI?
core.info('Removing dep-info files (*.d)');
const globber = await glob.create(path.join(targetDir, '**/*.d'));
const files = await globber.glob();
await Promise.all(files.map(rmrf));
}
export async function saveCache() {
if (!isCacheEnabled()) {
return;
}
const primaryKey = await getPrimaryCacheKey();
const cacheHitKey = core.getState('cache-hit-key');
if (cacheHitKey === primaryKey) {
core.info(`Cache hit occured on the key ${cacheHitKey}, not saving cache`);
return;
}
const cachePaths = getCachePaths().filter((cachePath) => {
if (!fs.existsSync(cachePath)) {
core.info(`Cache path ${cachePath} does not exist, skipping`);
return false;
}
return true;
});
if (cachePaths.length === 0) {
core.info('No paths to cache, skipping save entirely');
return;
}
await cleanCargoRegistry();
await cleanTargetProfile();
core.info(`Saving cache with key ${primaryKey}`);
core.debug(`Cache key: ${primaryKey}`);
core.debug('Cache paths:');
for (const cachePath of cachePaths) {
core.debug(`- ${cachePath}`);
}
await cache.saveCache(cachePaths, primaryKey);
}
export async function restoreCache() {
if (!isCacheEnabled()) {
return;
}
core.info('Attempting to restore cache');
const primaryKey = await getPrimaryCacheKey();
const cachePaths = getCachePaths();
core.debug(`Cache key: ${primaryKey}`);
core.debug('Cache paths:');
for (const cachePath of cachePaths) {
core.debug(`- ${cachePath}`);
}
const cacheKey = await cache.restoreCache(getCachePaths(), primaryKey, getCachePrefixes());
if (cacheKey) {
core.saveState('cache-hit-key', cacheKey);
core.info(`Cache restored using key ${primaryKey}`);
} else {
core.info(`Cache does not exist using key ${primaryKey}`);
}
core.setOutput('cache-key', cacheKey ?? primaryKey);
core.setOutput('cache-hit', !!cacheKey);
}

View file

@ -1,12 +0,0 @@
import * as core from '@actions/core';
import * as io from '@actions/io';
export async function rmrf(dir: string) {
core.debug(`Deleting ${dir}`);
try {
await io.rmRF(dir);
} catch (error: unknown) {
core.warning(`Failed to delete ${dir}: ${error}`);
}
}

View file

@ -1,166 +0,0 @@
/* eslint-disable import/no-mutable-exports */
import fs from 'node:fs';
import path from 'node: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<Toolchain>;
}
const DEFAULT_TOOLCHAIN: Toolchain = {
channel: 'stable',
components: [],
profile: 'minimal',
targets: [],
};
export let RUST_VERSION = core.getState('rust-version');
export let RUST_HASH = core.getState('rust-hash');
export async function extractRustVersion(toolchain: string) {
let out = '';
await exec.exec('rustc', [`+${toolchain}`, '--version', '--verbose'], {
listeners: {
stdout(data: Buffer) {
out += data.toString();
},
},
});
const extract = (key: string, line: string) => {
const value = line.split(':')[1].trim();
core.setOutput(key, value);
core.saveState(key, value);
return value;
};
out.split('\n').forEach((line) => {
if (line.startsWith('commit-hash')) {
RUST_HASH = extract('rust-hash', line);
// version
} else if (line.startsWith('release')) {
RUST_VERSION = extract('rust-version', line);
}
});
}
export function parseConfig(configPath: string): Partial<Toolchain> {
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) {
if (core.getBooleanInput('inherit-toolchain')) {
core.debug('Inheriting entire [toolchain] section');
return { ...config.toolchain };
}
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
export 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('Loading 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;
}
export async function installToolchain() {
const toolchain = detectToolchain();
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 extractRustVersion(toolchain.channel);
}

View file

@ -1,16 +0,0 @@
{
"extends": "tsconfig-moon/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"module": "NodeNext",
"moduleResolution": "NodeNext",
"noEmit": true,
"verbatimModuleSyntax": false
},
"include": [
".eslintrc.js",
"*.js",
"*.ts",
"tests/*.ts"
]
}