brand-new action in node.js (#4)

This commit is contained in:
Mieszko Grodzicki 2023-01-09 00:46:08 +01:00 committed by Predrag Gruevski
parent a708ddccfe
commit 893685e69b
11 changed files with 3863 additions and 76 deletions

View file

@ -6,52 +6,21 @@ on:
branches:
- main
env:
RUST_BACKTRACE: 1
CARGO_TERM_COLOR: always
jobs:
test-action:
name: Test the action
runs-on: ubuntu-latest
steps:
- name: Checkout the test repository
uses: actions/checkout@v3
with:
repository: mgr0dzicki/cargo-semver-action-ref-slice
fetch-depth: 0
persist-credentials: true
- name: Checkout the action
uses: actions/checkout@v3
with:
path: action
# Assumes that the latest published normal version of `ref_slice` smaller
# than 1.2.2 is 1.2.1.
# TODO: Change the crate version in the corresponding branch `patch_change`
# to 1.2.1 once new logic of choosing baseline is adapted. Otherwise
# if new version 1.2.2 of `ref_slice` is released, the tests might stop
# working correctly.
- name: Checkout the test with patch change and patch version bump
run: git checkout patch_change
- name: Run the action
uses: ./action/
# Assumes that the latest published normal version of `ref_slice` smaller
# than 1.2.2 exports a public function `ref_slice`.
# TODO: Change the crate version in the corresponding branch `major_change`
# to 1.2.1 once new logic of choosing baseline is adapted. Otherwise
# if new version 1.2.2 of `ref_slice` is released, the tests might stop
# working correctly.
- name: Checkout the test with major change and patch version bump
run: git checkout major_change
- name: Run the action (allowed to fail)
id: action_major
uses: ./action/
continue-on-error: true
- name: Check the action outcome
run: |
if [[ "${{ steps.action_major.outcome }}" != 'failure' ]]; then
echo "Error! The action should have failed because of the breaking change, but it has not."
exit 1
else
echo "OK! The action has failed as expected on the breaking change."
fi
name: Test the action on ubuntu-latest
uses: ./.github/workflows/test-action.yml
with:
runs-on: ubuntu-latest
test-action-windows-latest:
name: Test the action on windows-latest
uses: ./.github/workflows/test-action.yml
with:
runs-on: windows-latest
test-action-macos-latest:
name: Test the action on macos-latest
uses: ./.github/workflows/test-action.yml
with:
runs-on: macos-latest

59
.github/workflows/test-action.yml vendored Normal file
View file

@ -0,0 +1,59 @@
name: Test the action
on:
workflow_call:
inputs:
runs-on:
required: true
type: string
env:
RUST_BACKTRACE: 1
CARGO_TERM_COLOR: always
jobs:
run-tests:
name: Run tests
runs-on: ${{ inputs.runs-on }}
steps:
- name: Checkout the test repository
uses: actions/checkout@v3
with:
repository: mgr0dzicki/cargo-semver-action-ref-slice
fetch-depth: 0
persist-credentials: true
- name: Checkout the action
uses: actions/checkout@v3
with:
path: action
# Assumes that the latest published normal version of `ref_slice` smaller
# than 1.2.2 is 1.2.1.
# TODO: Change the crate version in the corresponding branch `patch_change`
# to 1.2.1 once new logic of choosing baseline is adapted. Otherwise
# if new version 1.2.2 of `ref_slice` is released, the tests might stop
# working correctly.
- name: Checkout the test with patch change and patch version bump
run: git checkout patch_change
- name: Run the action
uses: ./action/
env:
GITHUB_TOKEN: ${{ github.token }}
# Assumes that the latest published normal version of `ref_slice` smaller
# than 1.2.2 exports a public function `ref_slice`.
# TODO: Change the crate version in the corresponding branch `major_change`
# to 1.2.1 once new logic of choosing baseline is adapted. Otherwise
# if new version 1.2.2 of `ref_slice` is released, the tests might stop
# working correctly.
- name: Checkout the test with major change and patch version bump
run: git checkout major_change
- name: Run the action (allowed to fail)
id: action_major
uses: ./action/
env:
GITHUB_TOKEN: ${{ github.token }}
continue-on-error: true
- name: Fail if the action has not returned any errors (but it should have)
if: steps.action_major.outcome != 'failure'
run: |
echo "Error! The action should have failed because of the breaking change, but it has not."
exit 1

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
node_modules
.idea
.vscode

1
.npmrc Normal file
View file

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

View file

@ -18,32 +18,5 @@ inputs:
required: true
default: false
runs:
using: "composite"
steps:
- name: Install rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
profile: minimal
- name: Check for semver violations
shell: bash
run: |
set -euxo pipefail
# Colorize output, since GitHub Actions terminals support color.
export CARGO_TERM_COLOR=always
export CRATE_NAME="${{ inputs.crate-name }}"
export MANIFEST_PATH="${{ inputs.manifest-path }}"
if [[ ${{ inputs.verbose }} == 'true' ]]; then
export VERBOSE_FLAG="--verbose"
else
export VERBOSE_FLAG=""
fi
export SEMVER_CHECKS_OPTIONS="${CRATE_NAME:+"--package $CRATE_NAME"} ${MANIFEST_PATH:+"--manifest-path $MANIFEST_PATH"} $VERBOSE_FLAG"
# Check for semver violations.
cargo install cargo-semver-checks --locked
cargo semver-checks check-release $SEMVER_CHECKS_OPTIONS
using: 'node16'
main: 'dist/index.js'

201
dist/index.js vendored Normal file

File diff suppressed because one or more lines are too long

1710
dist/licenses.txt vendored Normal file

File diff suppressed because it is too large Load diff

1706
package-lock.json generated Normal file

File diff suppressed because it is too large Load diff

31
package.json Normal file
View file

@ -0,0 +1,31 @@
{
"name": "cargo-semver-checks-action",
"version": "2.0.0",
"description": "Lint your crate API changes for semver violations.",
"main": "index.js",
"scripts": {
"build": "ncc build src/main.ts --license licenses.txt --minify"
},
"repository": {
"type": "git",
"url": "git+https://github.com/mgr0dzicki/cargo-semver-checks-action.git"
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": "https://github.com/mgr0dzicki/cargo-semver-checks-action/issues"
},
"homepage": "https://github.com/mgr0dzicki/cargo-semver-checks-action#readme",
"dependencies": {
"@actions-rs/core": "^0.1.6",
"@actions/core": "^1.10.0",
"@actions/github": "^5.1.1",
"@actions/io": "^1.1.2",
"@actions/tool-cache": "^2.0.1",
"@types/node-fetch": "^2.6.2"
},
"devDependencies": {
"@types/node": "^18.11.18"
}
}

124
src/main.ts Normal file
View file

@ -0,0 +1,124 @@
import os = require('os');
import * as core from '@actions/core';
import * as github from '@actions/github';
import * as io from '@actions/io';
import * as toolCache from '@actions/tool-cache';
import * as rustCore from '@actions-rs/core';
function getPlatformMatchingTarget(): string {
const platform = os.platform() as string;
switch (platform) {
case "linux":
return "x86_64-unknown-linux-gnu"
case "win32":
return "x86_64-pc-windows-msvc"
case "darwin":
return "x86_64-apple-darwin"
default:
throw new Error("Unsupported runner");
}
}
function optionIfValueProvided(option: string, value?: string): string {
return value ? ` ${option} ${value}` : '';
}
function getCheckReleaseArguments(): string[] {
return [
optionIfValueProvided('--package', rustCore.input.getInput('crate-name')),
optionIfValueProvided('--manifest-path', rustCore.input.getInput('manifest-path')),
rustCore.input.getInputBool('verbose') ? ' --verbose' : ''
].filter(el => el != '');
}
function getGitHubToken(): string {
const token = process.env['GITHUB_TOKEN'] || rustCore.input.getInput('github-token');
if (!token)
throw new Error('Querying the GitHub API is possible only if the GitHub token is set.');
return token;
}
async function getCargoSemverChecksDownloadURL(target: string): Promise<string> {
const octokit = github.getOctokit(getGitHubToken());
const getReleaseUrl = await octokit.rest.repos.getLatestRelease({
owner: 'obi1kenobi',
repo: 'cargo-semver-checks'
});
const asset = getReleaseUrl.data.assets.find(asset => {
return asset['name'].endsWith(`${target}.tar.gz`)
});
if (!asset) {
throw new Error(`Couldn't find a release for target ${target}.`);
}
return asset.url;
}
async function installRustUp(): Promise<void> {
const rustup = await rustCore.RustUp.getOrInstall();
await rustup.call(['show']);
await rustup.setProfile('minimal');
await rustup.installToolchain('stable');
}
async function runCargoSemverChecks(cargo: rustCore.Cargo): Promise<void> {
await cargo.call(['semver-checks', 'check-release'].concat(getCheckReleaseArguments()));
}
async function installCargoSemverChecksFromPrecompiledBinary(): Promise<void> {
const url = await getCargoSemverChecksDownloadURL(getPlatformMatchingTarget());
core.info(`downloading cargo-semver-checks from ${url}`);
const tarballPath = await toolCache.downloadTool(url, undefined, `token ${getGitHubToken()}`, {
accept: 'application/octet-stream'
});
core.info(`extracting ${tarballPath}`);
const binPath = await toolCache.extractTar(tarballPath, undefined, ["xz"]);
core.addPath(binPath);
}
async function installCargoSemverChecksUsingCargo(cargo: rustCore.Cargo): Promise<void> {
await cargo.call(['install', 'cargo-semver-checks', '--locked']);
}
async function installCargoSemverChecks(cargo: rustCore.Cargo): Promise<void> {
if (await io.which('cargo-semver-checks') != '') {
return;
}
core.info('cargo-semver-checks is not installed, installing now...');
try {
await installCargoSemverChecksFromPrecompiledBinary();
} catch (error: any) {
core.info('Failed to download precompiled binary of cargo-semver-checks.');
core.info(`Error: ${error.message}`);
core.info('Installing using cargo install...');
await installCargoSemverChecksUsingCargo(cargo);
}
}
async function run(): Promise<void> {
await installRustUp();
const cargo = await rustCore.Cargo.get();
await installCargoSemverChecks(cargo);
await runCargoSemverChecks(cargo);
}
async function main() {
try {
await run();
} catch (error: any) {
core.setFailed(error.message);
}
}
main();

10
tsconfig.json Normal file
View file

@ -0,0 +1,10 @@
{
"compilerOptions": {
"module": "commonjs",
"outDir": "dist",
"strict": true,
},
"include": [
"src/**/*.ts"
]
}