From ca51ec148462d60acd3595c71545863374306537 Mon Sep 17 00:00:00 2001 From: Scott Lamb Date: Wed, 15 Dec 2021 08:12:32 -0800 Subject: [PATCH] CI setup --- .github/workflows/check-license.py | 66 ++++++++++++++++++++++++++++++ .github/workflows/ci.yml | 49 ++++++++++++++++++++++ 2 files changed, 115 insertions(+) create mode 100755 .github/workflows/check-license.py create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/check-license.py b/.github/workflows/check-license.py new file mode 100755 index 0000000..b95acb4 --- /dev/null +++ b/.github/workflows/check-license.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# Copyright (C) 2021 Scott Lamb +# SPDX-License-Identifier: MIT OR Apache-2.0 +"""Checks that expected header lines are present. + +Call in either of two modes: + +has-license.py FILE [...] + check if all files with certain extensions have expected lines. + This is useful in a CI action. + +has-license.py + check if stdin has expected lines. + This is useful in a pre-commit hook, as in + git-format-staged --no-write --formatter '.../has-license.py' '*.rs' +""" +import re +import sys + +# Filenames matching this regexp are expected to have the header lines. +FILENAME_MATCHER = re.compile(r'.*\.rs$') + +MAX_LINE_COUNT = 10 + +EXPECTED_LINES = [ + re.compile(r'Copyright \(C\) 20\d{2} Scott Lamb '), + re.compile(r'SPDX-License-Identifier: MIT OR Apache-2\.0'), +] + +def has_license(f): + """Returns if all of EXPECTED_LINES are present within the first + MAX_LINE_COUNT lines of f.""" + needed = set(EXPECTED_LINES) + i = 0 + for line in f: + if i == 10: + break + i += 1 + for e in needed: + if e.search(line): + needed.remove(e) + break + if not needed: + return True + return False + + +def file_has_license(filename): + with open(filename, 'r') as f: + return has_license(f) + + +def main(args): + if not args: + sys.exit(0 if has_license(sys.stdin) else 1) + + missing = [f for f in args + if FILENAME_MATCHER.match(f) and not file_has_license(f)] + if missing: + print('The following files are missing expected copyright/license headers:', file=sys.stderr) + print('\n'.join(missing), file=sys.stderr) + sys.exit(1) + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ae41ef7 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,49 @@ +name: CI +on: [push, pull_request] + +env: + CARGO_TERM_COLOR: always + RUST_BACKTRACE: 1 + +jobs: + rust: + name: Test + strategy: + matrix: + rust: + - stable + - 1.56 + include: + - rust: stable + extra_components: rustfmt + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Cache + uses: actions/cache@v2 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + target + key: ${{ matrix.rust }}-cargo-${{ hashFiles('**/Cargo.lock') }} + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + components: ${{ matrix.extra_components }} + - name: Test + run: cargo test --all-features + - name: Check formatting + if: matrix.rust == 'stable' + run: cargo fmt -- --check + license: + name: Check copyright/license headers + runs-on: ubuntu-20.04 + steps: + - name: Checkout + uses: actions/checkout@v2 + - run: find . -type f -print0 | xargs -0 .github/workflows/check-license.py