Use @actions-rs/core for cargo/cross execution.

Add problem matcher for cargo output
This commit is contained in:
svartalf 2019-09-25 10:08:33 +03:00
parent 5c0786fa0f
commit e35786a472
12 changed files with 109 additions and 116 deletions

View file

@ -6,6 +6,11 @@ jobs:
check_pr: check_pr:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Create npm configuration
run: echo "//npm.pkg.github.com/:_authToken=${token}" >> ~/.npmrc
env:
token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/checkout@v1 - uses: actions/checkout@v1
- name: "npm ci" - name: "npm ci"

21
.matchers/rust.json Normal file
View file

@ -0,0 +1,21 @@
{
"problemMatcher": [
{
"owner": "rust",
"pattern": [
{
"regexp": "^(warning|warn|error)(\\[(.*)\\])?: (.*)$",
"severity": 1,
"message": 4,
"code": 3
},
{
"regexp": "^([\\s->=]*(.*):(\\d*):(\\d*)|.*)$",
"file": 2,
"line": 3,
"column": 4
}
]
}
]
}

1
.npmrc Normal file
View file

@ -0,0 +1 @@
@actions-rs:registry=https://npm.pkg.github.com

21
CHANGELOG.md Normal file
View file

@ -0,0 +1,21 @@
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
### Added
- Problem matcher which will highlight warnings and errors in the cargo output
### Changed
- Use `@action-rs/core` package for cargo/cross execution
## [1.0.1] - 2019-09-15
### Added
- First public version

View file

@ -8,14 +8,14 @@ const testEnvVars = {
INPUT_TOOLCHAIN: '+nightly' INPUT_TOOLCHAIN: '+nightly'
} }
describe('actions-rs/check', () => { describe('actions-rs/cargo/input', () => {
beforeEach(() => { beforeEach(() => {
for (const key in testEnvVars) for (const key in testEnvVars)
process.env[key] = testEnvVars[key as keyof typeof testEnvVars] process.env[key] = testEnvVars[key as keyof typeof testEnvVars]
}) })
it('Parses action input into cargo input', async () => { it('Parses action input into cargo input', async () => {
const result = input.parse(); const result = input.get();
expect(result.command).toBe('build'); expect(result.command).toBe('build');
expect(result.args).toStrictEqual([ expect(result.args).toStrictEqual([

21
dist/.matchers/rust.json vendored Normal file
View file

@ -0,0 +1,21 @@
{
"problemMatcher": [
{
"owner": "rust",
"pattern": [
{
"regexp": "^(warning|warn|error)(\\[(.*)\\])?: (.*)$",
"severity": 1,
"message": 4,
"code": 3
},
{
"regexp": "^([\\s->=]*(.*):(\\d*):(\\d*)|.*)$",
"file": 2,
"line": 3,
"column": 4
}
]
}
]
}

2
dist/index.js vendored

File diff suppressed because one or more lines are too long

16
package-lock.json generated
View file

@ -4,6 +4,16 @@
"lockfileVersion": 1, "lockfileVersion": 1,
"requires": true, "requires": true,
"dependencies": { "dependencies": {
"@actions-rs/core": {
"version": "0.0.4",
"resolved": "https://npm.pkg.github.com/download/@actions-rs/core/0.0.4/d09e2c707d599f4ff4f1839f5050c452ba4b16aaa0c8d849eb4d9b87cc69a427",
"integrity": "sha512-6Lu7wqs6rf1KAlchpiBk4vq3LzCmpfEIFhvVpr7FkDgZf+e0TF8i+dx1aYGKWcAFQI40MTbqKkilqJ32CdwNtQ==",
"requires": {
"@actions/core": "^1.1.1",
"@actions/exec": "^1.0.1",
"@actions/io": "^1.0.1"
}
},
"@actions/core": { "@actions/core": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.1.1.tgz", "resolved": "https://registry.npmjs.org/@actions/core/-/core-1.1.1.tgz",
@ -2210,9 +2220,9 @@
"dev": true "dev": true
}, },
"handlebars": { "handlebars": {
"version": "4.2.0", "version": "4.3.1",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.2.0.tgz", "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.3.1.tgz",
"integrity": "sha512-Kb4xn5Qh1cxAKvQnzNWZ512DhABzyFNmsaJf3OAkWNa4NkaqWcNI8Tao8Tasi0/F4JD9oyG0YxuFyvyR57d+Gw==", "integrity": "sha512-c0HoNHzDiHpBt4Kqe99N8tdLPKAnGCQ73gYMPWtAYM4PwGnf7xl8PBUHJqh9ijlzt2uQKaSRxbXRt+rZ7M2/kA==",
"dev": true, "dev": true,
"requires": { "requires": {
"neo-async": "^2.6.0", "neo-async": "^2.6.0",

View file

@ -28,9 +28,8 @@
"url": "https://github.com/actions-rs/cargo/issues" "url": "https://github.com/actions-rs/cargo/issues"
}, },
"dependencies": { "dependencies": {
"@actions-rs/core": "0.0.4",
"@actions/core": "^1.1.1", "@actions/core": "^1.1.1",
"@actions/exec": "^1.0.1",
"@actions/io": "^1.0.1",
"string-argv": "^0.3.1" "string-argv": "^0.3.1"
}, },
"devDependencies": { "devDependencies": {

View file

@ -2,37 +2,10 @@
* Parse action input into a some proper thing. * Parse action input into a some proper thing.
*/ */
import * as core from '@actions/core'; import {input} from '@actions-rs/core';
import * as exec from '@actions/exec';
import stringArgv from 'string-argv'; import stringArgv from 'string-argv';
// Workaround for a GH bug: https://github.com/actions/toolkit/issues/127
//
// For input `all-features: true` it will generate the `INPUT_ALL-FEATURES: true`
// env variable, which looks too weird.
// Here we are trying to get proper name `INPUT_NO_DEFAULT_FEATURES` first,
// and if it does not exist, trying the `INPUT_NO-DEFAULT-FEATURES`
function getInput(name: string): string {
const inputFullName = name.replace(/-/g, '_');
let value = core.getInput(inputFullName);
if (value.length > 0) {
return value
}
return core.getInput(name)
}
function getInputBool(name: string): boolean {
const value = getInput(name);
if (value && (value == 'true' || value == '1')) {
return true;
} else {
return false;
}
}
// Parsed action input // Parsed action input
export interface Input { export interface Input {
command: string, command: string,
@ -41,14 +14,14 @@ export interface Input {
useCross: boolean, useCross: boolean,
} }
export function parse(): Input { export function get(): Input {
const command = getInput('command'); const command = input.getInput('command', {required: true});
const args = stringArgv(getInput('args')); const args = stringArgv(input.getInput('args'));
let toolchain = getInput('toolchain'); let toolchain = input.getInput('toolchain');
if (toolchain.startsWith('+')) { if (toolchain.startsWith('+')) {
toolchain = toolchain.slice(1); toolchain = toolchain.slice(1);
} }
const useCross = getInputBool('use-cross'); const useCross = input.getInputBool('use-cross');
return { return {
command: command, command: command,

View file

@ -1,79 +1,16 @@
const os = require('os'); const path = require('path');
const process = require('process');
import * as core from '@actions/core'; import * as core from '@actions/core';
import * as exec from '@actions/exec';
import * as io from '@actions/io';
import * as input from './input'; import * as input from './input';
import {Cargo, Cross} from '@actions-rs/core';
const CROSS_REV: string = '69b8da7da287055127812c9e4b071756c2b98545'; export async function run(actionInput: input.Input): Promise<void> {
async function getCargo(): Promise<string> {
try {
return await io.which('cargo', true);
} catch (error) {
core.info('cargo is not installed by default for some virtual environments, \
see https://help.github.com/en/articles/software-in-virtual-environments-for-github-actions');
core.info('To install it, use this action: https://github.com/actions-rs/toolchain');
throw error;
}
}
async function getCross(cargoPath: string): Promise<string> {
try {
return await io.which('cross', true);
} catch (error) {
core.debug('Unable to find cross, installing it now');
}
// Somewhat new Rust is required to compile `cross`
// (TODO: Not sure what version exactly, should clarify)
// but if some action will set an override toolchain before this action called
// (ex. `@actions-rs/toolchain` with `toolchain: 1.31.0`)
// `cross` compilation will fail.
//
// In order to skip this problem and install `cross` globally
// using the pre-installed system Rust,
// we are going to jump to the tmpdir (skipping directory override that way)
// install `cross` from there and then jump back.
const cwd = process.cwd();
process.chdir(os.tmpdir());
try {
core.startGroup('Install cross');
core.warning('Git version of cross will be installed, \
see https://github.com/actions-rs/cargo/issues/1');
await exec.exec(cargoPath, [
'install',
'--rev',
CROSS_REV,
'--git',
'https://github.com/rust-embedded/cross.git'
]);
} catch (error) {
throw error;
} finally {
// It is important to chdir back!
process.chdir(cwd);
core.endGroup();
}
// Expecting it to be in PATH already
return 'cross';
}
async function run(): Promise<void> {
const actionInput = input.parse();
const cargo = await getCargo();
let program; let program;
if (actionInput.useCross) { if (actionInput.useCross) {
program = await getCross(cargo); program = await Cross.getOrInstall();
} else { } else {
program = cargo; program = await Cargo.get();
} }
let args: string[] = []; let args: string[] = [];
@ -83,12 +20,17 @@ async function run(): Promise<void> {
args.push(actionInput.command); args.push(actionInput.command);
args = args.concat(actionInput.args); args = args.concat(actionInput.args);
await exec.exec(program, args); await program.call(args);
} }
async function main(): Promise<void> { async function main(): Promise<void> {
const matchersPath = path.join(__dirname, '.matchers');
console.log(`##[add-matcher]${path.join(matchersPath, 'rust.json')}`);
const actionInput = input.get();
try { try {
await run(); await run(actionInput);
} catch (error) { } catch (error) {
core.setFailed(error.message); core.setFailed(error.message);
} }

View file

@ -4,7 +4,7 @@
// "incremental": true, /* Enable incremental compilation */ // "incremental": true, /* Enable incremental compilation */
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ "target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "allowJs": true, /* Allow javascript files to be compiled. */ "allowJs": false, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */ // "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */ // "declaration": true, /* Generates corresponding '.d.ts' file. */
@ -32,10 +32,10 @@
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */ /* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */ "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */ "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
/* Module Resolution Options */ /* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */