robust installs (PEP668) + resilient report-only
quality / python-lint (push) Skipped
quality / node-lint (push) Skipped
quality / php-lint (push) Skipped
quality / secret-scan (push) Successful in 5s
quality / sast (push) Successful in 20s
quality / vuln-scan (push) Successful in 11s
quality / actionlint (push) Successful in 3s
selftest / quality (push) Successful in 40s

This commit is contained in:
2026-08-25 12:42:09 +00:00
parent ae94d4a4a1
commit 64c50da902
+33 -27
View File
@@ -1,8 +1,8 @@
name: quality
# Reusable Quality-Gate. Semantik: Scans laufen per DEFAULT (opt-out via skip_*),
# Sprach-Linter sind opt-in (python/node/php). Grund: Gitea wendet Input-Defaults
# reusable-seitig NICHT an -> unset ist falsy, daher !skip_* = an.
# blocking=true macht SAST/Vuln/Lint zum harten Gate (Secrets sind immer hart).
# Reusable Quality-Gate. Scans laufen per DEFAULT (opt-out via skip_*),
# Sprach-Linter opt-in (python/node/php). Report-only per Default;
# blocking=true macht SAST/Vuln/Lint hart. Secrets sind IMMER hart.
# Runner=catthehacker (Debian, PEP668) -> pip mit --break-system-packages.
# KEINE Docker-Hub-Pulls -> Tools via GitHub-Release/pip.
on:
workflow_call:
@@ -24,7 +24,7 @@ jobs:
with: { fetch-depth: 0 }
- name: gitleaks (Secrets = immer blockierend)
run: |
set -o pipefail
set -eo pipefail
GLV=$(curl -fsSL -o /dev/null -w '%{url_effective}' https://github.com/gitleaks/gitleaks/releases/latest | sed 's#.*/tag/v##')
[ -n "$GLV" ] || GLV=8.21.2
echo "::notice::gitleaks v$GLV"
@@ -38,13 +38,14 @@ jobs:
- uses: actions/checkout@v4
- name: semgrep
run: |
set -o pipefail
python3 -m pip install --quiet --user semgrep
set +e
python3 -m pip install --user --break-system-packages --quiet semgrep
export PATH="$HOME/.local/bin:$PATH"
rc=0
SEMGREP_SEND_METRICS=off semgrep scan --config p/ci --error --quiet || rc=$?
SEMGREP_SEND_METRICS=off semgrep scan --config p/ci --error --quiet; rc=$?
if [ "${{ inputs.blocking }}" = "true" ] && [ "$rc" -ne 0 ]; then exit "$rc"; fi
[ "$rc" -ne 0 ] && echo "::warning::semgrep findings (report-only)"; true
[ "$rc" -ne 0 ] && echo "::warning::semgrep findings/inconclusive (report-only)"
exit 0
vuln-scan:
if: ${{ !inputs.skip_vuln }}
@@ -53,12 +54,13 @@ jobs:
- uses: actions/checkout@v4
- name: trivy fs
run: |
set -o pipefail
set +e
curl -fsSL https://raw.githubusercontent.com/aquasecurity/trivy/main/contrib/install.sh | sh -s -- -b /tmp
rc=0
/tmp/trivy fs --scanners vuln,misconfig,secret --severity HIGH,CRITICAL --exit-code 1 --no-progress . || rc=$?
/tmp/trivy fs --scanners vuln,misconfig,secret --severity HIGH,CRITICAL --exit-code 1 --no-progress .; rc=$?
if [ "${{ inputs.blocking }}" = "true" ] && [ "$rc" -ne 0 ]; then exit "$rc"; fi
[ "$rc" -ne 0 ] && echo "::warning::trivy findings (report-only)"; true
[ "$rc" -ne 0 ] && echo "::warning::trivy findings (report-only)"
exit 0
actionlint:
runs-on: ubuntu-latest
@@ -66,13 +68,14 @@ jobs:
- uses: actions/checkout@v4
- name: actionlint
run: |
set -o pipefail
set +e
bash <(curl -fsSL https://raw.githubusercontent.com/rhysd/actionlint/main/scripts/download-actionlint.bash)
files=$(ls .gitea/workflows/*.y*ml .github/workflows/*.y*ml 2>/dev/null || true)
files=$(ls .gitea/workflows/*.y*ml .github/workflows/*.y*ml 2>/dev/null)
rc=0
if [ -n "$files" ]; then ./actionlint -color $files || rc=$?; else echo "keine Workflows"; fi
if [ -n "$files" ]; then ./actionlint -color $files; rc=$?; else echo "keine Workflows"; fi
if [ "${{ inputs.blocking }}" = "true" ] && [ "$rc" -ne 0 ]; then exit "$rc"; fi
[ "$rc" -ne 0 ] && echo "::warning::actionlint findings (report-only)"; true
[ "$rc" -ne 0 ] && echo "::warning::actionlint findings (report-only)"
exit 0
python-lint:
if: ${{ inputs.python }}
@@ -81,14 +84,15 @@ jobs:
- uses: actions/checkout@v4
- name: ruff
run: |
set -o pipefail
python3 -m pip install --quiet --user ruff
set +e
python3 -m pip install --user --break-system-packages --quiet ruff
export PATH="$HOME/.local/bin:$PATH"
rc=0
ruff check --output-format=github . || rc=$?
ruff format --check . || rc=$?
ruff check --output-format=github .; rc=$?
ruff format --check .; [ $? -ne 0 ] && rc=1
if [ "${{ inputs.blocking }}" = "true" ] && [ "$rc" -ne 0 ]; then exit "$rc"; fi
[ "$rc" -ne 0 ] && echo "::warning::ruff findings (report-only)"; true
[ "$rc" -ne 0 ] && echo "::warning::ruff findings (report-only)"
exit 0
node-lint:
if: ${{ inputs.node }}
@@ -97,12 +101,13 @@ jobs:
- uses: actions/checkout@v4
- name: eslint
run: |
set -o pipefail
set +e
if [ ! -f package.json ]; then echo "kein package.json - skip"; exit 0; fi
rc=0
npx --yes eslint . || rc=$?
npx --yes eslint .; rc=$?
if [ "${{ inputs.blocking }}" = "true" ] && [ "$rc" -ne 0 ]; then exit "$rc"; fi
[ "$rc" -ne 0 ] && echo "::warning::eslint findings (report-only)"; true
[ "$rc" -ne 0 ] && echo "::warning::eslint findings (report-only)"
exit 0
php-lint:
if: ${{ inputs.php }}
@@ -111,8 +116,9 @@ jobs:
- uses: actions/checkout@v4
- name: php -l
run: |
set -o pipefail
set +e
rc=0
find . -name '*.php' -not -path '*/vendor/*' -print0 | xargs -0 -r -n1 -P4 php -l >/dev/null || rc=$?
find . -name '*.php' -not -path '*/vendor/*' -print0 | xargs -0 -r -n1 -P4 php -l >/dev/null; rc=$?
if [ "${{ inputs.blocking }}" = "true" ] && [ "$rc" -ne 0 ]; then exit "$rc"; fi
[ "$rc" -ne 0 ] && echo "::warning::php -l findings (report-only)"; true
[ "$rc" -ne 0 ] && echo "::warning::php -l findings (report-only)"
exit 0