mirror of
https://github.com/moonrepo/setup-rust.git
synced 2025-04-20 01:28:43 +00:00
build: Move code around.
This commit is contained in:
parent
63072407f0
commit
d19bea4f65
3 changed files with 209 additions and 207 deletions
204
index.ts
204
index.ts
|
@ -1,206 +1,20 @@
|
|||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import * as core from '@actions/core';
|
||||
import * as exec from '@actions/exec';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import TOML from '@ltd/j-toml';
|
||||
import { CACHE_ENABLED, CARGO_HOME, restoreCache } from './src/cargo';
|
||||
import { extractRustVersion } from './src/rust';
|
||||
|
||||
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: [],
|
||||
};
|
||||
|
||||
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.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('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;
|
||||
}
|
||||
|
||||
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 extractRustVersion(toolchain.channel);
|
||||
}
|
||||
|
||||
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 'arm64':
|
||||
arch = 'aarch64';
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported architecture: ${process.arch}`);
|
||||
}
|
||||
|
||||
switch (process.platform) {
|
||||
case 'linux':
|
||||
file = `${arch}-unknown-linux-gnu.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}`);
|
||||
}
|
||||
|
||||
const url = `https://github.com/cargo-bins/cargo-binstall/releases/latest/download/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);
|
||||
}
|
||||
}
|
||||
|
||||
async function installBins() {
|
||||
const bins = core
|
||||
.getInput('bins')
|
||||
.split(',')
|
||||
.map((bin) => bin.trim())
|
||||
.filter(Boolean)
|
||||
.map((bin) => (bin.startsWith('cargo-') ? bin : `cargo-${bin}`));
|
||||
|
||||
if (CACHE_ENABLED) {
|
||||
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]);
|
||||
}
|
||||
import { CARGO_HOME, installBins, restoreCache } from './src/cargo';
|
||||
import { installToolchain } from './src/rust';
|
||||
|
||||
async function run() {
|
||||
core.info('Setting cargo environment variables');
|
||||
|
||||
// Disable incremental compilation
|
||||
core.exportVariable('CARGO_INCREMENTAL', '0');
|
||||
|
||||
// Always enable colored output
|
||||
core.exportVariable('CARGO_TERM_COLOR', 'always');
|
||||
|
||||
core.info('Adding ~/.cargo/bin to PATH');
|
||||
|
||||
core.addPath(path.join(CARGO_HOME, 'bin'));
|
||||
|
||||
try {
|
||||
await installToolchain(detectToolchain());
|
||||
await installToolchain();
|
||||
await installBins();
|
||||
|
||||
// Restore cache after the toolchain has been installed,
|
||||
|
@ -211,10 +25,6 @@ async function run() {
|
|||
|
||||
throw error;
|
||||
}
|
||||
|
||||
core.info('Adding ~/.cargo/bin to PATH');
|
||||
|
||||
core.addPath(path.join(CARGO_HOME, 'bin'));
|
||||
}
|
||||
|
||||
void run();
|
||||
|
|
69
src/cargo.ts
69
src/cargo.ts
|
@ -7,12 +7,81 @@ import * as core from '@actions/core';
|
|||
import * as exec from '@actions/exec';
|
||||
import * as glob from '@actions/glob';
|
||||
import * as io from '@actions/io';
|
||||
import * as tc from '@actions/tool-cache';
|
||||
import { RUST_HASH, RUST_VERSION } from './rust';
|
||||
|
||||
export const CARGO_HOME = process.env.CARGO_HOME ?? path.join(os.homedir(), '.cargo');
|
||||
|
||||
export const CACHE_ENABLED = core.getBooleanInput('cache') || cache.isFeatureAvailable();
|
||||
|
||||
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 'arm64':
|
||||
arch = 'aarch64';
|
||||
break;
|
||||
default:
|
||||
throw new Error(`Unsupported architecture: ${process.arch}`);
|
||||
}
|
||||
|
||||
switch (process.platform) {
|
||||
case 'linux':
|
||||
file = `${arch}-unknown-linux-gnu.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}`);
|
||||
}
|
||||
|
||||
const url = `https://github.com/cargo-bins/cargo-binstall/releases/latest/download/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)
|
||||
.map((bin) => (bin.startsWith('cargo-') ? bin : `cargo-${bin}`));
|
||||
|
||||
if (CACHE_ENABLED) {
|
||||
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 function getCachePaths(): string[] {
|
||||
return [
|
||||
// ~/.cargo/registry
|
||||
|
|
143
src/rust.ts
143
src/rust.ts
|
@ -1,10 +1,31 @@
|
|||
/* eslint-disable import/no-mutable-exports */
|
||||
|
||||
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';
|
||||
|
||||
export let RUST_VERSION = '';
|
||||
export let RUST_HASH = '';
|
||||
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 = '';
|
||||
|
@ -17,19 +38,121 @@ export async function extractRustVersion(toolchain: string) {
|
|||
},
|
||||
});
|
||||
|
||||
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')) {
|
||||
const value = line.split(':')[1].trim();
|
||||
|
||||
core.setOutput('rust-hash', value);
|
||||
RUST_HASH = value;
|
||||
RUST_HASH = extract('rust-hash', line);
|
||||
|
||||
// version
|
||||
} else if (line.startsWith('release')) {
|
||||
const value = line.split(':')[1].trim();
|
||||
|
||||
core.setOutput('rust-version', value);
|
||||
RUST_VERSION = value;
|
||||
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.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);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue