mirror of
https://github.com/dotnet/skills.git
synced 2026-09-20 09:49:54 +08:00
01b4875ac2
* Fix evaluation.yml: quote run-name so '#' is not parsed as a YAML comment The run-name added in #746 is an unquoted plain scalar containing ` #{0}`. In YAML, a space followed by '#' starts a comment, so everything from '#{0} ...' onward was stripped, leaving an unterminated ${{ }} expression. The file still parses as YAML (yaml.safe_load succeeds) but GitHub Actions rejects it ("This run likely failed because of a workflow file issue"), which broke every evaluation run on main after #746 merged. Wrapping the value in double quotes keeps the full expression intact; verified with actionlint. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Add authoring-github-workflows skill + actionlint CI gate Prevents the class of bug that broke evaluation on main (#746): an unquoted `${{ }}` workflow expression containing `#`, which YAML treats as a comment and silently truncates, producing a file that parses as YAML but that GitHub Actions refuses to run ("This run likely failed because of a workflow file issue", no jobs started). Two layers: - Knowledge: .agents/skills/authoring-github-workflows/SKILL.md teaches the `#`-as-comment trap and other quoting rules, and to validate with actionlint (plain YAML linters accept the truncated form). - Enforcement: .github/workflows/actionlint.yml runs a pinned actionlint on hand-authored workflows for any PR/push touching .github/workflows. Generated gh-aw files (DO NOT EDIT headers) are skipped; shellcheck/pyflakes are off so the gate focuses on workflow/expression errors. .github/actionlint.yaml declares the repo's custom runner labels (ubuntu-slim, windows-11-arm). Verified locally: actionlint exits 0 on all hand-authored workflows, and exits 1 on the original unquoted run-name, confirming the gate catches it. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Fix markdownlint MD038: remove spaces inside code spans in SKILL.md Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Address PR review comments: actionlint config trigger, curl -f, syntactic-vs-semantic scope Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Harden actionlint workflow: pin checkout to SHA, disable persisted creds, verify actionlint checksum Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
72 lines
2.8 KiB
YAML
72 lines
2.8 KiB
YAML
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@de0fac2e4500dabe0009e67214ff5f5447ce83dd # 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[@]}"
|