Repository navigation
133 lines (120 loc) · 5.03 KB
/
Copy pathcheck-source-text.yml
File metadata and controls
133 lines (120 loc) · 5.03 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
name: Check Source Text
# Source-hygiene + shell-script lint. Runs on drafts too - fast feedback.
#
# Checks:
# * check-source-text.sh: trailing whitespace, hard tabs in C/H, CRLF,
# BOM / non-ASCII.
# * bash -n + shellcheck (warning level) on shell scripts.
# * check-workflows.py: every `run:` step against GitHub's 21000
# character cap, past which GitHub stops loading the workflow file
# altogether and its runs fail in 0s with zero jobs.
# * check-ci-deps.py: every install-apt-deps call against the .deb bundle
# it names, since a package missing from the bundle costs that job the
# apt mirror without failing anything.
#
# Scope:
# * pull_request: only files changed in the PR (catches new violations
# without failing on historical debt).
# * push: scan the full tree (baseline guard on master).
on:
push:
branches: [ master, main ]
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
branches: [ master, main ]
concurrency:
group: check-source-text-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
check:
# Only run from the wolfssl org to avoid burning forks' CI minutes.
if: github.repository_owner == 'wolfssl'
runs-on: ubuntu-24.04
timeout-minutes: 5
steps:
- uses: actions/checkout@v5
with:
fetch-depth: 0
# python3-yaml backs check-workflows.py, which measures run: steps
# from the parsed YAML rather than from the raw text.
- name: Install shellcheck
uses: ./.github/actions/install-apt-deps
with:
# Fit the loop inside this job's timeout-minutes.
budget-seconds: '120'
pull-timeout: '60'
packages: shellcheck python3-yaml
ghcr-debs-tag: ubuntu-24.04-full
- name: Collect files to check
id: files
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
BASE_SHA="${{ github.event.pull_request.base.sha }}"
HEAD_SHA="${{ github.event.pull_request.head.sha }}"
git diff --name-only --diff-filter=ACMR "$BASE_SHA" "$HEAD_SHA" \
> changed.txt || true
grep -E '\.sh$' changed.txt > changed-sh.txt || true
echo "Files changed in PR:"
cat changed.txt
echo "Shell scripts changed:"
cat changed-sh.txt
echo "count=$(wc -l < changed.txt)" >> "$GITHUB_OUTPUT"
echo "sh_count=$(wc -l < changed-sh.txt)" >> "$GITHUB_OUTPUT"
else
: > changed.txt
git ls-files '*.sh' > changed-sh.txt
echo "count=0" >> "$GITHUB_OUTPUT"
echo "sh_count=$(wc -l < changed-sh.txt)" >> "$GITHUB_OUTPUT"
fi
# Always over the whole set, not just PR-changed files: the cap is a
# property of each file on its own, the check takes well under a
# second for the ~110 of them, and a workflow can be pushed over the
# line by a change to a file the PR does not otherwise touch.
- name: Lint workflow files
run: ./.github/scripts/check-workflows.py
# Same reasoning as above: over the whole set, because a package list
# and the workflow that consumes it are rarely touched by one PR.
- name: Check the ci-deps bundle contract
run: ./.github/scripts/check-ci-deps.py
- name: Run check-source-text (PR changed files)
if: github.event_name == 'pull_request' && steps.files.outputs.count != '0'
run: |
# shellcheck disable=SC2046
./.github/scripts/check-source-text.sh $(cat changed.txt)
- name: Run check-source-text (full tree)
if: github.event_name != 'pull_request'
run: ./.github/scripts/check-source-text.sh
- name: bash -n (syntax check)
if: steps.files.outputs.sh_count != '0'
run: |
fail=0
while IFS= read -r f; do
[ -f "$f" ] || continue
if ! bash -n "$f"; then
echo "::error file=$f::bash -n syntax error"
fail=1
fi
done < changed-sh.txt
exit "$fail"
- name: shellcheck (warning level)
if: steps.files.outputs.sh_count != '0'
run: |
# Mirrors the internal multi-test check-shell-scripts subtest:
# --severity=warning
# -e SC2226,SC2166,SC2164,SC2046,SC2034,SC2188,SC2043
# SC2226 (no ln destination), SC2166 ([ p -a q ]), SC2164 (cd ||),
# SC2046 (word splitting), SC2034 (unused var), SC2188 (redirect
# w/o command), SC2043 (loop runs once) - common in this codebase,
# suppressed in the internal multi-test for the same reason.
fail=0
while IFS= read -r f; do
[ -f "$f" ] || continue
if ! shellcheck --severity=warning \
--exclude=SC2226,SC2166,SC2164,SC2046,SC2034,SC2188,SC2043 \
--format=gcc "$f"; then
fail=1
fi
done < changed-sh.txt
exit "$fail"