1+ name : Lint and Security Checks
2+
3+ on :
4+ workflow_call :
5+ inputs :
6+ run_php :
7+ description : " Run PHP lint & security job"
8+ required : false
9+ type : boolean
10+ default : true
11+ run_js :
12+ description : " Run JS lint & security job"
13+ required : false
14+ type : boolean
15+ default : true
16+ run_secrets :
17+ description : " Run secret leakage detection job"
18+ required : false
19+ type : boolean
20+ default : true
21+
22+ permissions :
23+ contents : read
24+ security-events : write
25+
26+ concurrency :
27+ group : lint-security-${{ github.ref }}
28+ cancel-in-progress : true
29+
30+ jobs :
31+ # Lints PHP code style (Pint) and audits Composer dependencies for vulnerabilities
32+ php :
33+ if : ${{ inputs.run_php }}
34+ name : PHP Lint & Security
35+ runs-on : ubuntu-latest
36+ steps :
37+ - name : Checkout
38+ uses : actions/checkout@v4
39+
40+ - name : Setup PHP
41+ uses : shivammathur/setup-php@v2
42+ with :
43+ php-version : ' 8.3'
44+ coverage : none
45+ tools : composer
46+ extensions : mbstring, intl, pdo, pdo_mysql, pdo_pgsql
47+ ini-values : memory_limit=512M
48+
49+ - name : Cache Composer dependencies
50+ uses : actions/cache@v4
51+ with :
52+ path : |
53+ ~/.composer/cache/files
54+ ~/.cache/composer/files
55+ key : ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
56+ restore-keys : |
57+ ${{ runner.os }}-composer-
58+ - name : Validate composer.json
59+ run : composer validate --no-check-publish --strict
60+
61+ - name : Install PHP dependencies
62+ run : composer install --no-interaction --prefer-dist --no-progress
63+
64+ - name : PHP code style (Pint)
65+ run : vendor/bin/pint --test
66+
67+ - name : Composer security audit
68+ run : composer audit --no-interaction --locked
69+
70+ # Runs JS/Vue linting (ESLint), formatting check (Prettier), and npm security audit
71+ js :
72+ if : ${{ inputs.run_js }}
73+ name : JS Lint & Security
74+ runs-on : ubuntu-latest
75+ steps :
76+ - name : Checkout
77+ uses : actions/checkout@v4
78+
79+ - name : Setup Node.js
80+ uses : actions/setup-node@v4
81+ with :
82+ node-version : ' 20'
83+ cache : ' npm'
84+
85+ - name : Install Node dependencies
86+ run : npm ci
87+
88+ - name : ESLint
89+ run : npx eslint --ext .js,.vue --ignore-path .gitignore resources/js
90+
91+ - name : Prettier (check)
92+ run : npx prettier resources/js --check
93+
94+ - name : npm audit (high+)
95+ run : npm audit --audit-level=high
96+
97+ # Scans the repository for hard-coded secrets using Gitleaks
98+ secrets :
99+ if : ${{ inputs.run_secrets }}
100+ name : Secret Leakage Scan
101+ runs-on : ubuntu-latest
102+ steps :
103+ - name : Checkout
104+ uses : actions/checkout@v4
105+
106+ - name : Install Gitleaks
107+ run : |
108+ set -e
109+ GITLEAKS_VERSION=8.18.4
110+ curl -sSL -o gitleaks.tar.gz "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz"
111+ tar -xzf gitleaks.tar.gz gitleaks
112+ sudo mv gitleaks /usr/local/bin/gitleaks
113+ gitleaks version
114+
115+ - name : Gitleaks scan
116+ id : gitleaks
117+ run : |
118+ set +e
119+ gitleaks detect --source . --no-git --redact --report-format sarif --report-path gitleaks.sarif
120+ code=$?
121+ echo "$code" > gitleaks-exit-code.txt
122+ if [ ! -f gitleaks.sarif ]; then
123+ echo "Gitleaks did not produce SARIF file; creating empty stub." >&2
124+ printf '%s\n' '{' \
125+ ' "version": "2.1.0",' \
126+ ' "runs": [' \
127+ ' {' \
128+ ' "tool": { "driver": { "name": "Gitleaks", "informationUri": "https://github.com/gitleaks/gitleaks" } },' \
129+ ' "results": []' \
130+ ' }' \
131+ ' ]' \
132+ '}' > gitleaks.sarif
133+ fi
134+ # Always succeed here; we fail after uploading SARIF for annotations
135+ exit 0
136+
137+ - name : Upload SARIF (code scanning)
138+ if : always()
139+ uses : github/codeql-action/upload-sarif@v3
140+ with :
141+ sarif_file : gitleaks.sarif
142+ - name : Fail if Gitleaks found leaks
143+ run : |
144+ code=$(cat gitleaks-exit-code.txt || echo 0)
145+ if [ "$code" -ne 0 ]; then
146+ echo "Gitleaks detected potential secrets (exit code $code). Failing job after SARIF upload." >&2
147+ exit 1
148+ fi
0 commit comments