name: actionlint # Validates GitHub Actions workflow files with actionlint, which understands the # Actions schema and expression grammar. This catches bugs that plain YAML linters # miss — most notably an unquoted `${{ }}` expression containing `#`, where YAML # treats ` #` as a comment and silently truncates the expression, producing a file # that parses as YAML but that GitHub Actions refuses to run. # See: .agents/skills/authoring-github-workflows/SKILL.md on: pull_request: paths: - ".github/workflows/**" - ".github/actions/**" - ".github/actionlint.yaml" push: branches: [main] paths: - ".github/workflows/**" - ".github/actions/**" - ".github/actionlint.yaml" workflow_dispatch: permissions: contents: read jobs: actionlint: runs-on: ubuntu-latest steps: - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v6 with: persist-credentials: false - name: Run actionlint env: ACTIONLINT_VERSION: "1.7.7" ACTIONLINT_SHA256: "023070a287cd8cccd71515fedc843f1985bf96c436b7effaecce67290e7e0757" run: | set -euo pipefail curl -fsSLo actionlint.tar.gz \ "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" # Verify the downloaded archive against the pinned checksum before # extracting/executing it, so a compromised asset or transport can't # run attacker-controlled code on the runner. echo "${ACTIONLINT_SHA256} actionlint.tar.gz" | sha256sum -c - tar -xzf actionlint.tar.gz actionlint # Lint only hand-authored workflows. Files generated by gh-aw # (`*.lock.yml` and others) carry a "DO NOT EDIT" header and are # excluded — they are compiled artifacts, not source we maintain. to_lint=() while IFS= read -r f; do if head -n 30 "$f" | grep -qiE 'DO NOT EDIT|automatically generated|gh aw'; then echo "skip (generated): $f" else to_lint+=("$f") fi done < <(find .github/workflows -type f \( -name '*.yml' -o -name '*.yaml' \) | sort) if [ "${#to_lint[@]}" -eq 0 ]; then echo "No hand-authored workflows to lint." exit 0 fi printf 'Linting:\n'; printf ' %s\n' "${to_lint[@]}" # Focus on workflow + expression correctness. shellcheck/pyflakes are # disabled to avoid failing on pre-existing shell/Python style warnings; # the goal of this gate is to block workflows GitHub Actions cannot run. ./actionlint -shellcheck= -pyflakes= -color "${to_lint[@]}"