Skip to content

Commit 7909a93

Browse files
committed
github action: move the clippy management into a script
1 parent dfd95e3 commit 7909a93

File tree

4 files changed

+121
-35
lines changed

4 files changed

+121
-35
lines changed

.github/workflows/code-quality.yml

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -127,37 +127,18 @@ jobs:
127127
shell: bash
128128
command: |
129129
## `cargo clippy` lint testing
130-
unset fault
131-
fault_type="${{ steps.vars.outputs.FAULT_TYPE }}"
132-
fault_prefix=$(echo "$fault_type" | tr '[:lower:]' '[:upper:]')
133-
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
134-
if [[ "${{ matrix.job.features }}" == "all" ]]; then
135-
extra="--all-features"
136-
else
137-
extra="--features ${{ matrix.job.features }}"
130+
ARGS="--features ${{ matrix.job.features }}"
131+
ARGS="${ARGS} --fault-type ${{ steps.vars.outputs.FAULT_TYPE }}"
132+
if [[ "${{ matrix.job.workspace }}" =~ ^(1|t|true|y|yes)$ ]]; then
133+
ARGS="${ARGS} --workspace"
138134
fi
139-
case '${{ matrix.job.workspace }}' in
140-
1|t|true|y|yes)
141-
extra="${extra} --workspace"
142-
;;
143-
esac
144135
if [[ -n "${{ matrix.job.target }}" ]]; then
145-
extra="${extra} --no-default-features --target ${{ matrix.job.target }}"
136+
ARGS="${ARGS} --target ${{ matrix.job.target }}"
146137
fi
147-
# * determine sub-crate utility list (similar to FreeBSD workflow)
148-
if [[ -n "${{ matrix.job.target }}" ]]; then
149-
# For cross-compilation targets, just check -pcoreutils (show-utils.sh over-resolves due to default features)
150-
S=$(cargo clippy $extra -pcoreutils -- -D warnings 2>&1) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*$/::${fault_type} file=\2,line=\3,col=\4::${fault_prefix}: \`cargo clippy\`: \1 (file:'\2', line:\3)/p;" -e '}' ; fault=true ; }
151-
else
152-
if [[ "${{ matrix.job.features }}" == "all" ]]; then
153-
UTILITY_LIST="$(./util/show-utils.sh --all-features)"
154-
else
155-
UTILITY_LIST="$(./util/show-utils.sh --features ${{ matrix.job.features }})"
156-
fi
157-
CARGO_UTILITY_LIST_OPTIONS="$(for u in ${UTILITY_LIST}; do echo -n "-puu_${u} "; done;)"
158-
S=$(cargo clippy --all-targets $extra --tests --benches -pcoreutils ${CARGO_UTILITY_LIST_OPTIONS} -- -D warnings 2>&1) && printf "%s\n" "$S" || { printf "%s\n" "$S" ; printf "%s" "$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*$/::${fault_type} file=\2,line=\3,col=\4::${fault_prefix}: \`cargo clippy\`: \1 (file:'\2', line:\3)/p;" -e '}' ; fault=true ; }
138+
if [[ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ]]; then
139+
ARGS="${ARGS} --fail-on-fault"
159140
fi
160-
if [ -n "${{ steps.vars.outputs.FAIL_ON_FAULT }}" ] && [ -n "$fault" ]; then exit 1 ; fi
141+
python3 util/run-clippy.py ${ARGS}
161142
- name: "cargo clippy on fuzz dir"
162143
if: runner.os != 'Windows' && !matrix.job.target
163144
shell: bash

.github/workflows/freebsd.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ jobs:
4141
sync: rsync
4242
copyback: false
4343
# We need jq and GNU coreutils to run show-utils.sh and bash to use inline shell string replacement
44-
prepare: pkg install -y curl sudo jq coreutils bash
44+
prepare: pkg install -y curl sudo jq coreutils bash python3
4545
run: |
4646
## Prepare, build, and test
4747
# implementation modelled after ref: <https://github.com/rust-lang/rustup/pull/2783>
@@ -73,7 +73,6 @@ jobs:
7373
FAULT_PREFIX=\$(echo "\${FAULT_TYPE}" | tr '[:lower:]' '[:upper:]')
7474
# * determine sub-crate utility list
7575
UTILITY_LIST="\$(./util/show-utils.sh --features ${{ matrix.job.features }})"
76-
CARGO_UTILITY_LIST_OPTIONS="\$(for u in \${UTILITY_LIST}; do echo -n "-puu_\${u} "; done;)"
7776
## Info
7877
# environment
7978
echo "## environment"
@@ -101,8 +100,9 @@ jobs:
101100
## cargo clippy lint testing
102101
if [ -z "\${FAULT}" ]; then
103102
echo "## cargo clippy lint testing"
104-
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
105-
S=\$(cargo clippy --all-targets \${CARGO_UTILITY_LIST_OPTIONS} -- -D warnings 2>&1) && printf "%s\n" "\$S" || { printf "%s\n" "\$S" ; printf "%s" "\$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*\$/::\${FAULT_TYPE} file=\2,line=\3,col=\4::\${FAULT_PREFIX}: \\\`cargo clippy\\\`: \1 (file:'\2', line:\3)/p;" -e '}' ; FAULT=true ; }
103+
CLIPPY_ARGS="--features ${{ matrix.job.features }} --fault-type \${FAULT_TYPE}"
104+
if [ -n "\${FAIL_ON_FAULT}" ]; then CLIPPY_ARGS="\${CLIPPY_ARGS} --fail-on-fault"; fi
105+
python3 util/run-clippy.py \${CLIPPY_ARGS} || FAULT=true
106106
fi
107107
# Clean to avoid to rsync back the files
108108
cargo clean

.github/workflows/openbsd.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ jobs:
4747
prepare: |
4848
# Clean up disk space before installing packages
4949
df -h
50-
pkg_add curl sudo-- jq coreutils bash rust rust-clippy rust-rustfmt llvm--
50+
pkg_add curl sudo-- jq coreutils bash rust rust-clippy rust-rustfmt llvm-- python3
5151
rm -rf /usr/share/relink/* /usr/X11R6/* /usr/share/doc/* /usr/share/man/* &
5252
# Clean up package cache after installation
5353
pkg_delete -a &
@@ -84,7 +84,6 @@ jobs:
8484
FAULT_PREFIX=\$(echo "\${FAULT_TYPE}" | tr '[:lower:]' '[:upper:]')
8585
# * determine sub-crate utility list
8686
UTILITY_LIST="\$(./util/show-utils.sh --features ${{ matrix.job.features }})"
87-
CARGO_UTILITY_LIST_OPTIONS="\$(for u in \${UTILITY_LIST}; do echo -n "-puu_\${u} "; done;)"
8887
## Info
8988
# environment
9089
echo "## environment"
@@ -111,8 +110,9 @@ jobs:
111110
## cargo clippy lint testing
112111
if [ -z "\${FAULT}" ]; then
113112
echo "## cargo clippy lint testing"
114-
# * convert any warnings to GHA UI annotations; ref: <https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-a-warning-message>
115-
S=\$(cargo clippy --all-targets \${CARGO_UTILITY_LIST_OPTIONS} -- -D warnings 2>&1) && printf "%s\n" "\$S" || { printf "%s\n" "\$S" ; printf "%s" "\$S" | sed -E -n -e '/^error:/{' -e "N; s/^error:[[:space:]]+(.*)\\n[[:space:]]+-->[[:space:]]+(.*):([0-9]+):([0-9]+).*\$/::\${FAULT_TYPE} file=\2,line=\3,col=\4::\${FAULT_PREFIX}: \\\`cargo clippy\\\`: \1 (file:'\2', line:\3)/p;" -e '}' ; FAULT=true ; }
113+
CLIPPY_ARGS="--features ${{ matrix.job.features }} --fault-type \${FAULT_TYPE}"
114+
if [ -n "\${FAIL_ON_FAULT}" ]; then CLIPPY_ARGS="\${CLIPPY_ARGS} --fail-on-fault"; fi
115+
python3 util/run-clippy.py \${CLIPPY_ARGS} || FAULT=true
116116
fi
117117
# Clean to avoid to rsync back the files and free up disk space
118118
cargo clean

util/run-clippy.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env python3
2+
# SPDX-License-Identifier: MIT
3+
"""Run cargo clippy with appropriate flags and emit GitHub Actions annotations."""
4+
5+
import argparse
6+
import re
7+
import subprocess
8+
import sys
9+
10+
11+
def get_utility_list(features: str) -> list[str]:
12+
"""Get list of utilities via show-utils.sh."""
13+
if features == "all":
14+
cmd = ["./util/show-utils.sh", "--all-features"]
15+
else:
16+
cmd = ["./util/show-utils.sh", "--features", features]
17+
result = subprocess.run(cmd, capture_output=True, text=True, check=True)
18+
return result.stdout.split()
19+
20+
21+
def build_clippy_command(
22+
features: str, workspace: bool, target: str | None
23+
) -> list[str]:
24+
"""Build the cargo clippy command line."""
25+
cmd = ["cargo", "clippy"]
26+
27+
extra = []
28+
if features == "all":
29+
extra.append("--all-features")
30+
else:
31+
extra.extend(["--features", features])
32+
33+
if workspace:
34+
extra.append("--workspace")
35+
36+
if target:
37+
extra.extend(["--no-default-features", "--target", target])
38+
# For cross-compilation targets, just check -pcoreutils
39+
# (show-utils.sh over-resolves due to default features)
40+
extra.append("-pcoreutils")
41+
else:
42+
extra.extend(["--all-targets", "--tests", "--benches", "-pcoreutils"])
43+
utilities = get_utility_list(features)
44+
for u in utilities:
45+
extra.append(f"-puu_{u}")
46+
47+
cmd.extend(extra)
48+
cmd.extend(["--", "-D", "warnings"])
49+
return cmd
50+
51+
52+
# Pattern to match clippy/rustc errors for GHA annotations
53+
ERROR_PATTERN = re.compile(r"^error:\s+(.*)\n\s+-->\s+(.*):(\d+):(\d+)", re.MULTILINE)
54+
55+
56+
def emit_annotations(output: str, fault_type: str) -> None:
57+
"""Emit GitHub Actions annotations from cargo clippy errors."""
58+
fault_prefix = fault_type.upper()
59+
for m in ERROR_PATTERN.finditer(output):
60+
message, file, line, col = m.groups()
61+
print(
62+
f"::{fault_type} file={file},line={line},col={col}"
63+
f"::{fault_prefix}: `cargo clippy`: {message} (file:'{file}', line:{line})"
64+
)
65+
66+
67+
def main() -> int:
68+
parser = argparse.ArgumentParser(description="Run cargo clippy for CI")
69+
parser.add_argument("--features", required=True, help="Feature set to use")
70+
parser.add_argument(
71+
"--workspace", action="store_true", help="Include --workspace flag"
72+
)
73+
parser.add_argument("--target", default=None, help="Cross-compilation target")
74+
parser.add_argument(
75+
"--fault-type",
76+
default="warning",
77+
choices=["warning", "error"],
78+
help="GHA annotation type",
79+
)
80+
parser.add_argument(
81+
"--fail-on-fault",
82+
action="store_true",
83+
help="Exit with error code on clippy failures",
84+
)
85+
args = parser.parse_args()
86+
87+
cmd = build_clippy_command(args.features, args.workspace, args.target)
88+
print(f"Running: {' '.join(cmd)}", file=sys.stderr)
89+
90+
result = subprocess.run(cmd, capture_output=True, text=True)
91+
output = result.stdout + result.stderr
92+
93+
# Always print the full output
94+
print(output)
95+
96+
if result.returncode != 0:
97+
emit_annotations(output, args.fault_type)
98+
if args.fail_on_fault:
99+
return 1
100+
101+
return 0
102+
103+
104+
if __name__ == "__main__":
105+
sys.exit(main())

0 commit comments

Comments
 (0)