Skip to content

Commit a47717b

Browse files
committed
ci: add GitHub Actions, dependabot, and CRS bump
Workflows (.github/workflows/ci.yml — runs on push + pull_request): - bash -n syntax check (blocking) - shellcheck --severity=error (blocking) - shellcheck --severity=warning (non-blocking, annotates only) - shfmt --diff (non-blocking, annotates only) - gitleaks secret scan (blocking) - markdown-link-check on README (non-blocking) Plus: - .github/dependabot.yml — weekly bump of GitHub Action versions - .github/workflows/crs-bump.yml — weekly check of OWASP CRS releases, opens a PR when the pinned default in bootstrap/10-caddy.sh is behind. (Dependabot can't track variables in shell scripts, so this is a small custom job.)
1 parent bbe172b commit a47717b

4 files changed

Lines changed: 194 additions & 0 deletions

File tree

.github/dependabot.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
version: 2
2+
updates:
3+
- package-ecosystem: github-actions
4+
directory: /
5+
schedule:
6+
interval: weekly
7+
day: sunday
8+
time: "06:00"
9+
timezone: Etc/UTC
10+
open-pull-requests-limit: 5
11+
commit-message:
12+
prefix: "ci"
13+
labels:
14+
- dependencies
15+
- github-actions

.github/markdown-link-check.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"ignorePatterns": [
3+
{ "pattern": "^https?://(srv1\\.)?example\\." },
4+
{ "pattern": "^https?://<" },
5+
{ "pattern": "^https?://[^/]+\\.local" }
6+
],
7+
"timeout": "10s",
8+
"retryOn429": true,
9+
"retryCount": 2,
10+
"fallbackRetryDelay": "30s",
11+
"aliveStatusCodes": [200, 206, 301, 302, 308, 401, 403]
12+
}

.github/workflows/ci.yml

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
bash-syntax:
13+
name: bash -n (syntax)
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v4
17+
- name: Syntax-check every shell script
18+
run: |
19+
set -e
20+
rc=0
21+
while IFS= read -r f; do
22+
if ! bash -n "$f"; then
23+
echo "::error file=$f::bash -n failed"
24+
rc=1
25+
fi
26+
done < <(find . -type f -name '*.sh' -not -path './.git/*')
27+
exit $rc
28+
29+
shellcheck-error:
30+
name: shellcheck (errors block merge)
31+
runs-on: ubuntu-latest
32+
steps:
33+
- uses: actions/checkout@v4
34+
- name: Install shellcheck
35+
run: sudo apt-get update -qq && sudo apt-get install -y shellcheck
36+
- name: shellcheck --severity=error
37+
run: |
38+
set -e
39+
shellcheck \
40+
--shell=bash \
41+
--severity=error \
42+
--external-sources \
43+
-e SC1090,SC1091 \
44+
$(find . -type f -name '*.sh' -not -path './.git/*')
45+
46+
shellcheck-warn:
47+
name: shellcheck (warnings — non-blocking)
48+
runs-on: ubuntu-latest
49+
continue-on-error: true
50+
steps:
51+
- uses: actions/checkout@v4
52+
- name: Install shellcheck
53+
run: sudo apt-get update -qq && sudo apt-get install -y shellcheck
54+
- name: shellcheck --severity=warning
55+
run: |
56+
shellcheck \
57+
--shell=bash \
58+
--severity=warning \
59+
--external-sources \
60+
-e SC1090,SC1091,SC2012,SC2015,SC2034,SC2153,SC2317 \
61+
$(find . -type f -name '*.sh' -not -path './.git/*') \
62+
|| echo "::warning::shellcheck warnings present — see job log"
63+
64+
shfmt:
65+
name: shfmt (format — non-blocking)
66+
runs-on: ubuntu-latest
67+
continue-on-error: true
68+
steps:
69+
- uses: actions/checkout@v4
70+
- name: Install shfmt
71+
run: |
72+
curl -fsSL -o /tmp/shfmt \
73+
https://github.com/mvdan/sh/releases/download/v3.8.0/shfmt_v3.8.0_linux_amd64
74+
chmod +x /tmp/shfmt
75+
sudo mv /tmp/shfmt /usr/local/bin/shfmt
76+
- name: shfmt --diff
77+
run: |
78+
set +e
79+
shfmt -d -i 4 -ci -bn $(find . -type f -name '*.sh' -not -path './.git/*')
80+
if [ $? -ne 0 ]; then
81+
echo "::warning::shfmt formatting differences detected — run 'shfmt -w -i 4 -ci -bn .' locally"
82+
fi
83+
exit 0
84+
85+
gitleaks:
86+
name: gitleaks (secret scan)
87+
runs-on: ubuntu-latest
88+
steps:
89+
- uses: actions/checkout@v4
90+
with:
91+
fetch-depth: 0
92+
- name: gitleaks
93+
uses: gitleaks/gitleaks-action@v2
94+
env:
95+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
96+
97+
markdown-links:
98+
name: markdown-link-check (non-blocking)
99+
runs-on: ubuntu-latest
100+
continue-on-error: true
101+
steps:
102+
- uses: actions/checkout@v4
103+
- name: Check links in README and docs
104+
uses: gaurav-nelson/github-action-markdown-link-check@v1
105+
with:
106+
use-quiet-mode: 'yes'
107+
use-verbose-mode: 'yes'
108+
config-file: '.github/markdown-link-check.json'

.github/workflows/crs-bump.yml

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
name: CRS bump
2+
3+
on:
4+
schedule:
5+
# Weekly Sunday 07:00 UTC
6+
- cron: '0 7 * * 0'
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: write
11+
pull-requests: write
12+
13+
jobs:
14+
bump:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Detect current + latest CRS version
20+
id: ver
21+
run: |
22+
set -e
23+
current=$(grep -oP 'CRS_VERSION:-\K[^"}]+' bootstrap/10-caddy.sh | head -1)
24+
latest=$(curl -fsSL \
25+
-H "Accept: application/vnd.github+json" \
26+
https://api.github.com/repos/coreruleset/coreruleset/releases/latest \
27+
| jq -r .tag_name)
28+
echo "current=${current}" >> "$GITHUB_OUTPUT"
29+
echo "latest=${latest}" >> "$GITHUB_OUTPUT"
30+
echo "Current pinned : ${current}"
31+
echo "Latest upstream: ${latest}"
32+
33+
- name: Open PR if behind
34+
if: steps.ver.outputs.current != steps.ver.outputs.latest
35+
env:
36+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
37+
CURRENT: ${{ steps.ver.outputs.current }}
38+
LATEST: ${{ steps.ver.outputs.latest }}
39+
run: |
40+
set -e
41+
branch="ci/crs-${LATEST}"
42+
43+
# Bail if branch already exists on origin (PR already opened)
44+
if git ls-remote --exit-code --heads origin "${branch}" >/dev/null 2>&1; then
45+
echo "Branch ${branch} already exists upstream — skipping."
46+
exit 0
47+
fi
48+
49+
git config user.name "github-actions[bot]"
50+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
51+
git checkout -b "${branch}"
52+
sed -i "s|CRS_VERSION:-${CURRENT}|CRS_VERSION:-${LATEST}|" bootstrap/10-caddy.sh
53+
git add bootstrap/10-caddy.sh
54+
git commit -m "ci: bump OWASP CRS ${CURRENT} → ${LATEST}"
55+
git push origin "${branch}"
56+
gh pr create \
57+
--title "ci: bump OWASP CRS ${CURRENT} → ${LATEST}" \
58+
--body "Automated bump from $(date -u -Iseconds).\n\nUpstream: https://github.com/coreruleset/coreruleset/releases/tag/${LATEST}\n\nThe runtime cron \`/usr/local/bin/serverdeploy-crs-refresh\` already auto-refreshes CRS quarterly on deployed servers; this PR keeps the install-time pinned default current." \
59+
--label dependencies

0 commit comments

Comments
 (0)