Skip to content

Commit 9e5d149

Browse files
committed
Use dynamic CI scripts
Signed-off-by: Wiktor Kwapisiewicz <wiktor@metacode.biz>
1 parent 4e5d5cd commit 9e5d149

9 files changed

Lines changed: 408 additions & 126 deletions

File tree

.env

Lines changed: 0 additions & 6 deletions
This file was deleted.

.github/workflows/ci.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: CI
2+
3+
on: [pull_request]
4+
5+
jobs:
6+
generate-matrix:
7+
name: Generate jobs
8+
runs-on: ubuntu-latest
9+
outputs:
10+
jobs: ${{ steps.set-matrix.outputs.jobs }}
11+
steps:
12+
- uses: actions/checkout@v6
13+
- uses: taiki-e/install-action@just
14+
- run: node ./scripts/ci/create-github-checks.js
15+
id: set-matrix
16+
17+
run-task:
18+
name: ${{ matrix.jobs.doc }}
19+
runs-on: ubuntu-latest
20+
needs: [generate-matrix]
21+
container:
22+
image: archlinux
23+
strategy:
24+
fail-fast: false
25+
max-parallel: 6
26+
matrix: ${{fromJSON(needs.generate-matrix.outputs.jobs)}}
27+
28+
steps:
29+
- uses: actions/checkout@v6
30+
- run: pacman-key --init
31+
- run: pacman -Sy --needed --noconfirm archlinux-keyring
32+
- run: pacman -Syu --needed --noconfirm ${{ matrix.jobs.packages }}
33+
- run: just --justfile ${{ matrix.jobs.file }} ${{ matrix.jobs.name }}

.github/workflows/misc.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ jobs:
3131
steps:
3232
- uses: actions/checkout@v4
3333
- uses: taiki-e/install-action@just
34-
- run: just install-packages
34+
- run: sudo apt-get install --assume-yes --no-install-recommends libpcsclite-dev
35+
name: Install packages
36+
if: ${{ matrix.os == "ubuntu-latest" }}
3537
# If the example doesn't compile the integration test will
3638
# be stuck. Check for compilation issues earlier to abort the job
3739
- name: Check if the key-storage example compiles

.github/workflows/rust.yml

Lines changed: 0 additions & 79 deletions
This file was deleted.

.justfile

Lines changed: 174 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,209 @@
11
#!/usr/bin/env -S just --working-directory . --justfile
2-
# Load project-specific properties from the `.env` file
32

4-
set dotenv-load := true
5-
6-
# Since this is a first recipe it's being run by default.
7-
# Faster checks need to be executed first for better UX. For example
8-
# codespell is very fast. cargo fmt does not need to download crates etc.
3+
clippy := "cargo clippy --quiet --workspace --no-deps --all-targets"
4+
clippy_args := "-D warnings"
5+
nextest_args := "--locked --workspace"
6+
udeps_args := "--quiet --workspace --all-features --all-targets"
97

108
# Perform all checks
11-
check: spelling formatting docs lints dependencies tests
9+
[parallel]
10+
check: spell fmt doc lints deps unused-deps recipes test integration-test
1211

13-
# Checks common spelling mistakes
14-
spelling:
12+
# Check spelling
13+
[group('ci')]
14+
[metadata('pacman', 'codespell')]
15+
spell:
1516
codespell
1617

17-
# Checks source code formatting
18-
formatting:
18+
# Check source code formatting
19+
[group('ci')]
20+
[metadata('pacman', 'rustup')]
21+
fmt:
1922
just --unstable --fmt --check
2023
# We're using nightly to properly group imports, see .rustfmt.toml
21-
cargo +nightly fmt --all -- --check
24+
rustup component add --toolchain nightly rustfmt
25+
cargo +nightly fmt --quiet --all -- --check
2226

23-
# Lints the source code
27+
# Lint the source code
28+
[group('ci')]
29+
[metadata('gitlabci-job', '{"artifacts":{"when":"always","paths":["target/clippy"]}}')]
30+
[metadata('pacman', 'rust')]
2431
lints:
25-
cargo clippy --workspace --no-deps --all-targets -- -D warnings
32+
#!/usr/bin/bash
33+
set -euo pipefail
2634

27-
# Checks for issues with dependencies
28-
dependencies:
29-
cargo deny check
35+
if [ "${CI:-}" = "true" ]; then
36+
ARGS=(--message-format=json)
37+
else
38+
ARGS=()
39+
fi
3040

31-
# Runs all unit tests. By default ignored tests are not run. Run with `ignored=true` to run only ignored tests
32-
tests:
33-
cargo test --all
41+
mkdir -p target
42+
{{ clippy }} "${ARGS[@]}" -- {{ clippy_args }} | tee target/clippy
3443

35-
# Build docs for this crate only
36-
docs:
37-
cargo doc --no-deps
44+
# Create lints report
45+
[metadata('gitlabci-job', '{"stage":"deploy","when":"always","artifacts":{"reports":{"codequality":"target/codeclimate.json"}}}')]
46+
[metadata('pacman', 'cargo-sonar', 'rust')]
47+
create-codeclimate:
48+
# deny reports can be tested by adding a yanked dep e.g. `cargo add ed25519-dalek@0.9.0`
49+
cargo codeclimate \
50+
--clippy --clippy-path "target/clippy" \
51+
--deny --deny-path "target/deny" \
52+
--udeps --udeps-path "target/udeps" \
53+
--codeclimate-path target/codeclimate.json
54+
55+
# Check for issues with dependencies
56+
[group('ci')]
57+
[metadata('gitlabci-job', '{"artifacts":{"when":"always","paths":["target/deny"]}}')]
58+
[metadata('pacman', 'cargo-deny')]
59+
deps:
60+
#!/usr/bin/bash
61+
set -euo pipefail
3862

39-
# Installs packages required to build
40-
[linux]
41-
install-packages:
42-
sudo apt-get install --assume-yes --no-install-recommends $UBUNTU_PACKAGES
63+
if [ "${CI:-}" = "true" ]; then
64+
ARGS=(--format json)
65+
else
66+
ARGS=()
67+
fi
4368

44-
[macos]
45-
[windows]
46-
install-packages:
47-
echo no-op
69+
mkdir -p target
70+
cargo deny "${ARGS[@]}" check -D advisory-not-detected -D license-not-encountered -D no-license-field 2>&1 | tee target/deny
4871

49-
# Checks for commit messages
50-
check-commits REFS='main..':
51-
#!/usr/bin/env bash
72+
# Check for unused dependencies
73+
[group('ci')]
74+
[metadata('gitlabci-job', '{"artifacts":{"when":"always","paths":["target/udeps"]}}')]
75+
[metadata('pacman', 'cargo-machete', 'cargo-udeps', 'rust')]
76+
unused-deps:
77+
#!/usr/bin/bash
5278
set -euo pipefail
53-
for commit in $(git rev-list "{{ REFS }}"); do
79+
80+
if [ "${CI:-}" = "true" ]; then
81+
ARGS=(--output json)
82+
else
83+
ARGS=()
84+
fi
85+
86+
mkdir -p target
87+
cargo +nightly udeps {{ udeps_args }} "${ARGS[@]}" | tee target/udeps
88+
cargo +nightly machete
89+
90+
# Run unit tests
91+
[group('ci')]
92+
[metadata('pacman', 'cargo-nextest', 'rustup')]
93+
test:
94+
#!/usr/bin/bash
95+
set -euxo pipefail
96+
97+
if [ "${CI:-}" = "true" ]; then
98+
PROFILE=ci
99+
else
100+
PROFILE=default
101+
fi
102+
103+
cargo +nightly nextest run {{ nextest_args }} --profile "$PROFILE"
104+
cargo +nightly nextest run --no-default-features {{ nextest_args }} --profile "$PROFILE"
105+
106+
# Run integration tests
107+
[metadata('pacman', 'git', 'jq', 'openssh', 'tangler', 'tree')]
108+
integration-test:
109+
#!/usr/bin/bash
110+
set -euo pipefail
111+
cargo +nightly build --locked
112+
target=$(cargo +nightly metadata --format-version 1 | jq --raw-output '.target_directory')
113+
tangler sh < README.md | sed --quiet --regexp-extended 's/^\$ (.*)/\1/p' | PATH="$target/debug:$PATH" bash -euxo pipefail -
114+
115+
# Report on all tests
116+
[metadata('gitlabci-job', '{"coverage":"/Line coverage: ([0-9.]*)%/","artifacts":{"when":"always","reports":{"junit":"target/nextest/ci/junit.xml","metrics":"target/metrics.txt","coverage_report":{"coverage_format":"cobertura","path":"target/coverage.xml"}}}}')]
117+
[metadata('pacman', 'rust', 'cargo-llvm-cov', 'rustup')]
118+
report-test:
119+
#!/usr/bin/bash
120+
# enabling "x" here will garble text output that's parsed by GitLab for code coverage
121+
set -euo pipefail
122+
123+
rustup component add --toolchain nightly llvm-tools-preview
124+
125+
# shellcheck disable=SC1090
126+
source <(cargo +nightly llvm-cov show-env --export-prefix --doctests --branch)
127+
cargo +nightly llvm-cov clean
128+
129+
just test integration-test
130+
131+
# explicitly use "target" (even if CARGO_TARGET_DIR is somewhere else) so that
132+
# local tools (such as https://github.com/ryanluker/vscode-coverage-gutters) can find the file
133+
cargo +nightly llvm-cov --quiet report --cobertura --output-path target/coverage.xml > /dev/null 2>&1
134+
135+
LINE_RATE=$(head target/coverage.xml | sed -nE 's/(.*coverage.*line-rate=")([^"]*)".*/\2/p')
136+
LINE_PERCENT=$(echo "$LINE_RATE" | awk '{print $1 * 100}')
137+
printf 'Line coverage: %s%%\n' "$LINE_PERCENT"
138+
139+
BRANCH_RATE=$(head target/coverage.xml | sed -nE 's/(.*coverage.*branch-rate=")([^"]*)".*/\2/p')
140+
printf 'line_coverage_ratio %s\nbranch_coverage_ratio %s\n' "$LINE_RATE" "$BRANCH_RATE" > target/metrics.txt
141+
142+
# Generate HTML report for the coverage
143+
coverage-html-report: report-test
144+
#!/usr/bin/bash
145+
set -euo pipefail
146+
# shellcheck disable=SC1090
147+
source <(cargo +nightly llvm-cov show-env --export-prefix)
148+
cargo +nightly llvm-cov --quiet report --html > /dev/null 2>&1
149+
printf "The coverage report is in file://%s/llvm-cov/html/index.html\n" "${CARGO_TARGET_DIR:-target}"
150+
151+
# Build docs
152+
[group('ci')]
153+
[metadata('pacman', 'rust')]
154+
doc:
155+
RUSTDOCFLAGS='-D warnings' cargo doc --quiet --no-deps --document-private-items
156+
157+
# Check commit messages
158+
[metadata('pacman', 'codespell', 'git')]
159+
commits:
160+
#!/usr/bin/env bash
161+
set -Eeuo pipefail
162+
163+
# fetch default branch if it is set
164+
if [[ -v CI_DEFAULT_BRANCH ]]; then
165+
git fetch origin "$CI_DEFAULT_BRANCH"
166+
refs="origin/$CI_DEFAULT_BRANCH"
167+
else
168+
refs="main"
169+
fi
170+
171+
commits=$(git rev-list "${refs}..")
172+
for commit in $commits; do
54173
MSG="$(git show -s --format=%B "$commit")"
55174
CODESPELL_RC="$(mktemp)"
56175
git show "$commit:.codespellrc" > "$CODESPELL_RC"
57176
if ! grep -q "Signed-off-by: " <<< "$MSG"; then
58-
printf "Commit %s lacks \"Signed-off-by\" line.\n" "$commit"
177+
printf "Commit %s lacks \"Signed-off-by\" line.\n" "$commit"
59178
printf "%s\n" \
60179
" Please use:" \
61180
" git rebase --signoff main && git push --force-with-lease" \
62181
" See https://developercertificate.org/ for more details."
63182
exit 1;
64183
elif ! codespell --config "$CODESPELL_RC" - <<< "$MSG"; then
65-
printf "The spelling in commit %s needs improvement.\n" "$commit"
184+
printf "⛔ The spelling in commit %s needs improvement.\n" "$commit"
185+
exit 1;
186+
elif grep "WIP: " <<< "$MSG"; then
187+
printf "⛔ Commit %s includes a 'WIP' marker which should be removed.\n" "$commit"
66188
exit 1;
67189
else
68-
printf "Commit %s is good.\n" "$commit"
190+
printf "Commit %s is good.\n" "$commit"
69191
fi
70192
done
71193
194+
# Lint justfile recipes
195+
[group('ci')]
196+
[metadata('pacman', 'nodejs', 'shellcheck')]
197+
recipes:
198+
#!/usr/bin/env bash
199+
set -euo pipefail
200+
T=$(mktemp -d)
201+
node scripts/ci/export-shell.ts "$T"
202+
for file in "$T"/*.sh; do
203+
echo "Checking $file..."
204+
shellcheck --shell bash "$file"
205+
done
206+
72207
# Fixes common issues. Files need to be git add'ed
73208
fix:
74209
#!/usr/bin/env bash
@@ -85,5 +220,5 @@ fix:
85220
# try to fix clippy issues
86221
cargo clippy --fix --allow-staged
87222
88-
# fmt must be last as clippy's changes may break formatting
223+
# fmt must be last as clippy changes may break formatting
89224
cargo +nightly fmt --all

0 commit comments

Comments
 (0)