CI #737
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: CI | |
on: | |
schedule: | |
- cron: '0 0 * * 0' | |
push: | |
branches: | |
- master | |
- staging | |
- trying | |
tags: | |
- 'v[0-9]+.[0-9]+.[0-9]+**' | |
pull_request: | |
env: | |
RESOLVE_VERSIONS_PY: | | |
from argparse import ArgumentParser | |
import json | |
import urllib.request | |
import re | |
CRATE_SPEC = re.compile(r'\A([a-zA-Z0-9_-]+)@\^([0-9]+)\.([0-9]+)\Z') | |
def main() -> None: | |
parser = ArgumentParser() | |
parser.add_argument('specs', metavar='PSEUDO_SPECS', type=CrateSpec, nargs='+') | |
print('\n'.join(map(resolve, parser.parse_args().specs))) | |
class CrateSpec: | |
def __init__(self, s: str): | |
if not (m := CRATE_SPEC.match(s)): | |
raise RuntimeError(f'the version must be `{CRATE_SPEC.pattern}`') | |
self.package_name = m.group(1) | |
self.version_req_major = int(m.group(2)) | |
self.version_req_minor = int(m.group(3)) | |
def resolve(spec: CrateSpec) -> str: | |
with urllib.request.urlopen(f'https://crates.io/api/v1/crates/{spec.package_name}') as res: | |
versions = json.load(res)['versions'] | |
matched = set() | |
for version in versions: | |
major, minor, patch_pre_build = version['num'].split('.') | |
major, minor = (int(major), int(minor)) | |
if ((major, spec.version_req_major) == (0, 0) and minor == spec.version_req_minor or major == spec.version_req_major and minor >= spec.version_req_minor) and patch_pre_build.isdecimal(): | |
matched.add((minor, int(patch_pre_build))) | |
if not matched: | |
raise RuntimeError(f'No such package: `{spec.package_name} ^{spec.version_req_major}.{spec.version_req_minor}`') | |
minor, patch = max(matched) | |
return f'::set-output name={spec.package_name}::{spec.version_req_major}.{minor}.{patch}' | |
if __name__ == '__main__': | |
main() | |
jobs: | |
rustfmt: | |
name: Rustfmt | |
runs-on: ubuntu-20.04 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v2 | |
- name: Set up `stable-x86_64-unknown-linux-gnu` | |
uses: actions-rs/toolchain@v1 | |
with: | |
toolchain: stable-x86_64-unknown-linux-gnu | |
default: true | |
profile: minimal | |
components: rustfmt | |
- name: cargo-fmt | |
uses: actions-rs/cargo@v1 | |
with: | |
command: fmt | |
args: --all -- --check | |
cargo-udeps: | |
name: cargo-udeps | |
runs-on: ubuntu-20.04 | |
env: | |
NIGHTLY_CHANNEL: nightly-2021-09-19 | |
if: "false" # https://github.com/rust-lang/cargo/issues/9919 | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v2 | |
- name: Set up `stable-x86_64-unknown-linux-gnu` | |
uses: actions-rs/toolchain@v1 | |
with: | |
toolchain: stable-x86_64-unknown-linux-gnu | |
default: true | |
- name: Set up `${{ env.NIGHTLY_CHANNEL }}-x86_64-unknown-linux-gnu` | |
id: install-nightly | |
uses: actions-rs/toolchain@v1 | |
with: | |
toolchain: ${{ env.NIGHTLY_CHANNEL }}-x86_64-unknown-linux-gnu | |
- name: Set up Python 3.9 | |
uses: actions/setup-python@v2 | |
with: | |
python-version: '3.9' | |
- name: Resolve `cargo-udeps ^0.1` | |
id: resolve-versions | |
run: python -c "$RESOLVE_VERSIONS_PY" cargo-udeps@^0.1 | |
- name: Cache for cargo-udeps | |
uses: actions/cache@v2 | |
with: | |
path: | | |
~/.cargo/.crates.toml | |
~/.cargo/.crates2.json | |
~/.cargo/bin/cargo-udeps | |
key: cargo-udeps-installed-crates-${{ steps.resolve-versions.outputs.cargo-udeps }} | |
- name: Cache for build cache | |
uses: actions/cache@v2 | |
with: | |
path: | | |
~/.cargo/git | |
~/.cargo/registry | |
./target | |
key: cargo-udeps-build-${{ steps.install-nightly.outputs.rustc_hash }}-${{ hashFiles('./Cargo.*') }} | |
- name: Install cargo-udeps v${{ steps.resolve-versions.outputs.cargo-udeps }} | |
uses: actions-rs/cargo@v1 | |
with: | |
command: install | |
args: cargo-udeps --version '=${{ steps.resolve-versions.outputs.cargo-udeps }}' --locked | |
toolchain: stable | |
- name: cargo-udeps | |
uses: actions-rs/cargo@v1 | |
with: | |
command: udeps | |
args: --all-targets | |
toolchain: ${{ env.NIGHTLY_CHANNEL }}-x86_64-unknown-linux-gnu | |
grcov: | |
name: grcov | |
runs-on: ubuntu-20.04 | |
if: ${{ github.repository_owner == 'qryxip' && github.ref == 'refs/heads/master' }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v2 | |
- name: Set up `stable-x86_64-unknown-linux-gnu` | |
uses: actions-rs/toolchain@v1 | |
with: | |
toolchain: stable | |
- name: Set up `nightly-x86_64-unknown-linux-gnu` | |
uses: actions-rs/toolchain@v1 | |
with: | |
toolchain: nightly | |
- name: Set up Python 3.9 | |
uses: actions/setup-python@v2 | |
with: | |
python-version: '3.9' | |
- name: Resolve `grcov ^0.8` | |
id: resolve-versions | |
run: python -c "$RESOLVE_VERSIONS_PY" grcov@^0.8 | |
- name: Cache | |
uses: actions/cache@v2 | |
with: | |
path: | | |
~/.cargo/.crates.toml | |
~/.cargo/.crates2.json | |
~/.cargo/bin/grcov | |
key: grcov-${{ steps.resolve-versions.outputs.grcov }} | |
- name: Install grcov v${{ steps.resolve-versions.outputs.grcov }} | |
uses: actions-rs/cargo@v1 | |
with: | |
command: install | |
args: grcov --version '=${{ steps.resolve-versions.outputs.grcov }}' | |
toolchain: stable | |
- name: cargo-test | |
uses: actions-rs/cargo@v1 | |
with: | |
command: test | |
args: --no-fail-fast --features __test_with_credentials | |
toolchain: nightly | |
env: | |
RUSTFLAGS: '-Zinstrument-coverage' | |
RUST_BACKTRACE: full | |
LLVM_PROFILE_FILE: '%p-%m.profraw' | |
ATCODER_USERNAME: ${{ secrets.ATCODER_USERNAME }} | |
ATCODER_PASSWORD: ${{ secrets.ATCODER_PASSWORD }} | |
- name: grcov | |
run: rustup run "$NIGHTLY_CHANNEL" grcov . -b ./target/debug -s . -t lcov --branch --ignore-not-existing --ignore "/*" -o lcov.info | |
- name: Codecov | |
uses: codecov/codecov-action@v1 | |
with: | |
token: ${{ secrets.CODECOV_TOKEN }} | |
file: lcov.info | |
build: | |
strategy: | |
fail-fast: false | |
matrix: | |
name: | |
- stable-x86_64-pc-windows-msvc | |
- stable-x86_64-apple-darwin | |
- stable-x86_64-unknown-linux-gnu | |
include: | |
- { name: stable-x86_64-pc-windows-msvc , channel: stable, target-triple: x86_64-pc-windows-msvc , host-triple: x86_64-pc-windows-msvc , os: windows-2019 } | |
- { name: stable-x86_64-apple-darwin , channel: stable, target-triple: x86_64-apple-darwin , host-triple: x86_64-apple-darwin , os: macos-11 } | |
- { name: stable-x86_64-unknown-linux-gnu, channel: stable, target-triple: x86_64-unknown-linux-gnu , host-triple: x86_64-unknown-linux-gnu, os: ubuntu-20.04 } | |
name: ${{ matrix.name }} | |
runs-on: ${{ matrix.os }} | |
steps: | |
- name: Disable `core.autocrlf` | |
run: git config --global core.autocrlf false | |
if: ${{ matrix.os == 'windows-2019' }} | |
- name: Checkout | |
uses: actions/checkout@v2 | |
- name: 'Set up `${{ matrix.channel }}-${{ matrix.host-triple }}` (target: `${{ matrix.target-triple }}`)' | |
id: install-toolchain | |
uses: actions-rs/toolchain@v1 | |
with: | |
toolchain: ${{ matrix.channel }}-${{ matrix.host-triple }} | |
target: ${{ matrix.target-triple }} | |
default: true | |
profile: minimal | |
components: clippy | |
- name: Cache | |
uses: actions/cache@v2 | |
with: | |
path: | | |
~/.cargo/git | |
~/.cargo/registry | |
./target | |
key: build-${{ matrix.name }}-${{ steps.install-toolchain.outputs.rustc_hash }}-${{ hashFiles('./Cargo.*') }} | |
- name: cargo-clippy | |
uses: actions-rs/cargo@v1 | |
with: | |
command: clippy | |
args: --all-targets --target ${{ matrix.target-triple }} -- -D warnings | |
- name: cargo-clippy (with `__test_with_credentials`) | |
uses: actions-rs/cargo@v1 | |
with: | |
command: clippy | |
args: --all-targets --features __test_with_credentials --target ${{ matrix.target-triple }} -- -D warnings | |
- name: Determine `cargo test` features | |
id: cargo-test-features | |
run: | | |
if ${{ !!secrets.ATCODER_USERNAME }}; then | |
echo '::set-output name=features::--features __test_with_credentials' | |
else | |
echo '::set-output name=features::' | |
fi | |
shell: bash | |
- name: cargo-test | |
uses: actions-rs/cargo@v1 | |
with: | |
command: test | |
args: --no-fail-fast ${{ steps.cargo-test-features.outputs.features }} --target ${{ matrix.target-triple }} | |
env: | |
RUST_BACKTRACE: full | |
ATCODER_USERNAME: ${{ secrets.ATCODER_USERNAME }} | |
ATCODER_PASSWORD: ${{ secrets.ATCODER_PASSWORD }} | |
if: false # perhaps AtCoder no longer allows tests like ours | |
upload-archives: | |
strategy: | |
fail-fast: false | |
matrix: | |
target-triple: | |
- x86_64-pc-windows-msvc | |
- x86_64-apple-darwin | |
- x86_64-unknown-linux-gnu | |
include: | |
- { target-triple: x86_64-pc-windows-msvc , host-triple: x86_64-pc-windows-msvc , os: windows-2019 } | |
- { target-triple: x86_64-apple-darwin , host-triple: x86_64-apple-darwin , os: macos-11 } | |
- { target-triple: x86_64-unknown-linux-gnu, host-triple: x86_64-unknown-linux-gnu, os: ubuntu-20.04 } | |
name: Upload (${{ matrix.target-triple }}) | |
runs-on: ${{ matrix.os }} | |
if: ${{ startsWith(github.ref, 'refs/tags/') }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v2 | |
- name: 'Set up `stable-${{ matrix.host-triple }}` (target: `${{ matrix.target-triple }}`)' | |
uses: actions-rs/toolchain@v1 | |
with: | |
toolchain: stable-${{ matrix.host-triple }} | |
target: ${{ matrix.target-triple }} | |
default: true | |
profile: minimal | |
- name: cargo-install | |
uses: actions-rs/cargo@v1 | |
with: | |
command: install | |
args: --path . --target ${{ matrix.target-triple }} -v --locked | |
- name: cargo-build | |
uses: actions-rs/cargo@v1 | |
with: | |
command: build | |
args: --release --target ${{ matrix.target-triple }} | |
- name: Create an asset | |
id: asset | |
run: | | |
BIN_TARGET=cargo-compete | |
if ${{ contains(matrix.target-triple, 'pc-windows') }}; then | |
DOT_EXE=.exe | |
fi | |
ASSET_STEM="$BIN_TARGET-${GITHUB_REF#refs/tags/}-${{ matrix.target-triple }}" | |
git archive -o "./$ASSET_STEM.tar" --prefix "$ASSET_STEM/" HEAD | |
tar -xf "./$ASSET_STEM.tar" | |
mv "$HOME/.cargo/bin/$BIN_TARGET$DOT_EXE" "./$ASSET_STEM/" | |
if ${{ contains(matrix.target-triple, 'pc-windows') }}; then | |
ASSET="$ASSET_STEM.zip" | |
7z a "$ASSET" "./$ASSET_STEM" | |
zipinfo "./$ASSET" | |
else | |
ASSET="$ASSET_STEM.tar.gz" | |
tar -czvf "./$ASSET" "./$ASSET_STEM" | |
fi | |
echo "::set-output name=asset::$ASSET" | |
shell: bash | |
- name: Upload the artifact | |
uses: actions/upload-artifact@v2 | |
with: | |
name: assets | |
path: ${{ steps.asset.outputs.asset }} | |
upload-release-notes: | |
name: Upload the release notes | |
runs-on: ubuntu-20.04 | |
if: ${{ startsWith(github.ref, 'refs/tags/') }} | |
steps: | |
- name: Checkout | |
uses: actions/checkout@v2 | |
- name: Set up Python 3.9 | |
uses: actions/setup-python@v2 | |
with: | |
python-version: '3.9' | |
- name: Prepare release notes | |
run: | | |
with open('./CHANGELOG.md') as file: | |
changelog = file.read() | |
output = '' | |
inside_subsection = False | |
for line in changelog.splitlines(): | |
is_h2 = line.startswith('## ') | |
if not inside_subsection and is_h2: | |
inside_subsection = True | |
elif inside_subsection and not is_h2: | |
output += line + '\n' | |
elif inside_subsection: | |
break | |
with open('./release-notes.md', 'w') as file: | |
file.write(output) | |
shell: python | |
- name: Upload the release notes | |
uses: actions/upload-artifact@v2 | |
with: | |
name: release-notes | |
path: release-notes.md | |
release: | |
name: GitHub Release | |
runs-on: ubuntu-20.04 | |
needs: | |
- rustfmt | |
#- cargo-udeps | |
- upload-archives | |
- upload-release-notes | |
steps: | |
- name: Download the assets | |
uses: actions/download-artifact@v2 | |
with: | |
name: assets | |
path: ./assets | |
- name: Download the release notes | |
uses: actions/download-artifact@v2 | |
with: | |
name: release-notes | |
path: . | |
- name: GH Release | |
uses: softprops/action-gh-release@v1 | |
with: | |
body_path: ./release-notes.md | |
files: ./assets/* | |
env: | |
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |