Skip to content

Chore: Bump lfreleng-actions/generic-workflows/.github/workflows/clear-action-cache.yaml from 0.0.5 to 0.2.1 #41

Chore: Bump lfreleng-actions/generic-workflows/.github/workflows/clear-action-cache.yaml from 0.0.5 to 0.2.1

Chore: Bump lfreleng-actions/generic-workflows/.github/workflows/clear-action-cache.yaml from 0.0.5 to 0.2.1 #41

---
# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: 2026 The Linux Foundation
# Organisation-wide AI slop / code quality scan using aislop.
#
# This workflow lives in lfreleng-actions/.github and runs across the
# organisation as a "required workflow" via an organisation ruleset
# (Settings -> Rules -> Rulesets at the org level), so it executes on
# every selected repository without a per-repository file. It also
# audits this repository on demand (workflow_dispatch) and on its
# own pull requests.
#
# Scope: the scan covers ONLY the files changed on the pull request
# (aislop --changes --base), not the whole repository, so the check
# reports on what the PR introduces rather than pre-existing state.
# The scheduled aislop-sarif-publish.yaml workflow owns whole-repo
# scanning and default-branch code-scanning SARIF.
#
# Gating: the scan (delegated to aislop-scan-action, which pins and
# verifies the aislop CLI) never fails on findings by itself; a
# separate gate step decides enforcement. The gate level is chosen by
# the organisation variable AISLOP_GATE_LEVEL:
#
# any (default) Block the run when the pull request's changed
# files carry ANY finding, at any severity: high,
# medium and low all block. This is the "no new
# slop" gate: the scan scope is the changed files,
# so passing it means the pull request is not adding
# findings.
# high Block only on HIGH-severity findings (aislop
# error-severity). Medium and low remain advisory.
# The previous default; use it as a per-repository
# escape hatch while a backlog is remediated.
# all Block on the full aislop quality gate (score below
# the configured threshold OR any high-severity
# finding).
# off Advisory only: report via the step summary and
# inline annotations without blocking anything.
#
# A repository variable of the same name overrides the organisation
# value, so a repository carrying a pre-existing backlog can sit at
# 'high' without weakening the estate-wide default.
#
# For backward compatibility, when AISLOP_GATE_LEVEL is unset the
# legacy AISLOP_ENFORCE='true' variable still selects the 'all' tier;
# otherwise the default is 'any'.
#
# See README.md ("Organisation-wide aislop scan") for org-admin setup.
name: 'AI Slop Scan 🧹'
# yamllint disable-line rule:truthy
on:
workflow_dispatch:
pull_request:
permissions: {}
# Scope the group to this check, not to '${{ github.workflow }}', which
# resolves to the workflow NAME and so collides with any workflow in
# the target repository sharing it. See semantic-pull-request.yaml.
concurrency:
group: 'org-aislop-${{ github.ref }}'
cancel-in-progress: true
jobs:
audit:
name: 'Audit changes'
runs-on: 'ubuntu-latest'
timeout-minutes: 15
permissions:
contents: read
steps:
# Load the egress allow-list out-of-band from
# lfreleng-actions/.github and publish it as
# $CONNECTION_ALLOW_LIST for the harden-runner step below.
# yamllint disable-line rule:line-length
- uses: lfreleng-actions/harden-runner-block-action@805eedb0508c07714b61887a2b87a5c4bbeff22a # v0.12.1
with:
config: '@8f4f0cf83e6a015957e83261ed379fd811fc060e' # v0.5.1
# Harden the runner with the just-loaded allow-list.
- name: 'Harden runner (block)'
# yamllint disable-line rule:line-length
uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
with:
egress-policy: 'block'
allowed-endpoints: >
${{ env.CONNECTION_ALLOW_LIST }}
- name: 'Checkout repository under audit'
# yamllint disable-line rule:line-length
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
# Full history so aislop can resolve the merge base of the
# pull request branch against the base branch.
fetch-depth: 0
persist-credentials: false
- name: 'Run aislop quality gate (changed files)'
id: 'scan'
# yamllint disable-line rule:line-length
uses: lfreleng-actions/aislop-scan-action@4004a907f2894763ff1f9fc904b2f7b4b7a7cc40 # v0.2.7
with:
# On pull_request events the diff base is the PR base branch;
# on workflow_dispatch fall back to the default branch (an
# empty diff, so the run is a no-op smoke test).
scan-mode: 'changes'
# yamllint disable-line rule:line-length
base: 'origin/${{ github.base_ref || github.event.repository.default_branch }}'
- name: 'Enforce quality gate'
shell: 'bash'
env:
# Gate level: 'any' (default) blocks on any finding at any
# severity on the changed files; 'high' blocks on
# high-severity only; 'all' blocks on the full aislop gate;
# 'off' keeps the run advisory. AISLOP_ENFORCE is the legacy
# switch honoured only when AISLOP_GATE_LEVEL is unset.
AISLOP_GATE_LEVEL: '${{ vars.AISLOP_GATE_LEVEL }}'
AISLOP_ENFORCE: '${{ vars.AISLOP_ENFORCE }}'
SCAN_RC: '${{ steps.scan.outputs.exit-code }}'
REPORT_FILE: '${{ steps.scan.outputs.report-file }}'
run: |
# Enforce quality gate
set -euo pipefail
# Resolve the effective gate level. AISLOP_GATE_LEVEL wins;
# when it is unset, the legacy AISLOP_ENFORCE='true' selects
# the strict 'all' tier, otherwise the default is 'any'.
level="${AISLOP_GATE_LEVEL:-}"
if [ -z "${level}" ]; then
if [ "${AISLOP_ENFORCE:-}" = 'true' ]; then
level='all'
else
level='any'
fi
fi
case "${level}" in
any|high|all|off) ;;
*)
echo "::error::invalid AISLOP_GATE_LEVEL '${level}';" \
"expected 'any', 'high', 'all', or 'off'"
exit 1
;;
esac
# 'off' is advisory and never blocks, not even on a broken
# scan: surface the high-severity count when a report is
# available, then pass regardless.
if [ "${level}" = 'off' ]; then
if [ -n "${REPORT_FILE}" ] && [ -f "${REPORT_FILE}" ]; then
high="$(jq '[.diagnostics[]?
| select(.severity == "error")] | length' \
"${REPORT_FILE}")"
if [ "${high}" != '0' ]; then
msg="aislop found ${high} high-severity finding(s)"
msg="${msg} (advisory mode; not enforced)"
echo "::warning::${msg}"
fi
fi
echo 'Advisory mode (AISLOP_GATE_LEVEL=off): passing.'
exit 0
fi
# Enforcing tiers ('high' and 'all') need a readable report
# to evaluate, so fail closed when it is missing: a broken
# scan must not let findings slip past an active gate. (The
# action already fails its own step when the tool produces no
# readable report, so this is a defensive backstop.)
if [ -z "${REPORT_FILE}" ] || [ ! -f "${REPORT_FILE}" ]; then
echo "::error::aislop report not found; cannot evaluate gate"
exit 1
fi
# A failed scan can still emit valid JSON, for example an
# object carrying an 'error' key and no diagnostics. The
# counting below uses jq's optional iterator, which turns
# such a report into zero findings and would pass the gate
# on a scan that never ran. Require the diagnostics array
# explicitly and fail closed when it is absent.
if ! jq -e '(.diagnostics | type) == "array"' \
"${REPORT_FILE}" > /dev/null 2>&1; then
echo "::error::aislop report carries no diagnostics array;" \
"treating this as a failed scan rather than a clean" \
"result (gate exit code ${SCAN_RC})"
exit 1
fi
# Count findings on the changed files. aislop maps
# error-severity diagnostics to SARIF 'error' (high in code
# scanning), warning to medium, and info to low. The action
# leaves the JSON report in place (only its install dir is
# cleaned), so the report path stays readable here.
high="$(jq '[.diagnostics[]?
| select(.severity == "error")] | length' \
"${REPORT_FILE}")"
medium="$(jq '[.diagnostics[]?
| select(.severity == "warning")] | length' \
"${REPORT_FILE}")"
low="$(jq '[.diagnostics[]?
| select(.severity == "info")] | length' \
"${REPORT_FILE}")"
# Total counts every diagnostic, whatever its severity, so a
# severity this gate does not name still blocks.
total="$(jq '[.diagnostics[]?] | length' "${REPORT_FILE}")"
echo "aislop findings on changed files: ${total}" \
"(high ${high}, medium ${medium}, low ${low})"
echo "aislop gate exit code: ${SCAN_RC}"
case "${level}" in
any)
# The scan scope is the changed files, so a finding here
# is one this pull request adds, or leaves behind in code
# it touched. Every severity blocks, low included.
if [ "${total}" != '0' ]; then
echo "::error::aislop quality gate failed:" \
"${total} finding(s) on the changed files" \
"(high ${high}, medium ${medium}, low ${low});" \
"a pull request must not add findings." \
"Remediate them, or set the repository variable" \
"AISLOP_GATE_LEVEL=high while an existing backlog" \
"is cleared."
exit 1
fi
if [ "${SCAN_RC}" != '0' ]; then
msg='aislop score gate did not pass (advisory at the'
msg="${msg} 'any' gate level; set AISLOP_GATE_LEVEL=all"
msg="${msg} to enforce the score threshold too)"
echo "::warning::${msg}"
fi
echo 'aislop quality gate passed (no findings).'
;;
high)
if [ "${high}" != '0' ]; then
echo "::error::aislop quality gate failed:" \
"${high} high-severity finding(s) on this" \
"pull request"
exit 1
fi
if [ "${SCAN_RC}" != '0' ]; then
msg='aislop score gate did not pass (advisory at the'
msg="${msg} 'high' gate level; set AISLOP_GATE_LEVEL=all"
msg="${msg} to enforce it)"
echo "::warning::${msg}"
fi
echo 'aislop quality gate passed (no high-severity findings).'
;;
all)
# Fail on the full aislop gate. aislop ci already exits
# non-zero on any high-severity finding, but check high
# explicitly too so the tier matches its documented
# "score below threshold OR any high-severity finding"
# even if that coupling ever changes.
if [ "${high}" != '0' ] || [ "${SCAN_RC}" != '0' ]; then
echo "::error::aislop quality gate failed (rc=${SCAN_RC};" \
"${high} high-severity finding(s))"
exit 1
fi
echo 'aislop quality gate passed.'
;;
esac