Add authoring-github-workflows skill + actionlint CI gate (prevent workflow-YAML breakage) - #760
Conversation
…ment The run-name added in dotnet#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 dotnet#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>
Prevents the class of bug that broke evaluation on main (dotnet#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>
|
Note This PR is from a fork and modifies infrastructure files ( Changes to infrastructure typically need to be submitted from a branch in Please consider recreating this PR from an upstream branch. If you don't have push access to |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR prevents GitHub Actions workflow-YAML breakage from reaching main by documenting YAML-vs-Actions parsing traps and adding an actionlint CI gate, alongside a targeted fix to evaluation.yml’s run-name expression quoting.
Changes:
- Quote
evaluation.yml’srun-nameexpression so#can’t be interpreted as a YAML comment. - Add an
actionlintworkflow that lints hand-authored workflows on PRs/pushes. - Add
actionlintconfiguration for custom runner labels and a new repository “skill” doc describing safe workflow authoring.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
.github/workflows/evaluation.yml |
Quotes run-name expression to avoid YAML comment truncation. |
.github/workflows/actionlint.yml |
Adds CI gate to lint workflows with actionlint, skipping generated files. |
.github/actionlint.yaml |
Configures actionlint with repo-specific runner labels. |
.agents/skills/authoring-github-workflows/SKILL.md |
Documents common workflow authoring pitfalls and validation steps. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
👋 @YuliiaKovalova — this PR has 3 unresolved review thread(s). When you're ready, please address the feedback and push an update; the triage bot will pick up the next state automatically. (Add the |
…ctic-vs-semantic scope Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…eds, verify actionlint checksum Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
/evaluate |
|
⏭️ No skills to evaluate — no changed skills with tests were found in this PR. View workflow run |
| # 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 |
Why
Eval on
mainbroke for every run after #746 merged, with GitHub reporting "This run likely failed because of a workflow file issue" and no jobs starting. Root cause: an unquoted${{ }}expression inrun-namecontaining#. In YAML,#starts a comment, so the expression was silently truncated to...format('Evaluate PR— an unterminated${{. The file still parsed as valid YAML (soyaml.safe_loadand review passed), but GitHub Actions rejected it.This PR makes sure we never see that class of bug again, with two layers:
1. Knowledge — a skill
.agents/skills/authoring-github-workflows/SKILL.md(alongside the existing repo contributor meta-skills likecreate-skill) documents:#-as-comment trap and the quoting rule for expression scalars.yaml.safe_load,yamllint) is not enough — onlyactionlintunderstands the Actions expression grammar.2. Enforcement — an actionlint CI gate
.github/workflows/actionlint.ymlruns a pinnedactionlinton every PR/push that touches.github/workflows/:DO NOT EDITheaders, e.g.*.lock.yml,agentics-maintenance.yml) are skipped — they're compiled artifacts.-shellcheck= -pyflakes=so the gate targets workflow/expression correctness, not pre-existing shell/Python style noise..github/actionlint.yamldeclares the repo's custom runner labels (ubuntu-slim,windows-11-arm).Verification
actionlintexits 0 on all 14 hand-authored workflows (including the fixedevaluation.yml).got unexpected EOF while lexing end of string literal [expression]andactionlintexits 1 — confirming the gate would have caught the original bug.Note
This PR is stacked on #759 (the one-line
evaluation.ymlhotfix) so the new gate is green here. The fix commit is identical, so it merges cleanly whether #759 lands first or this PR does. If you prefer, merge #759 for the urgent fix and this PR for the durable prevention.Co-authored-by: Copilot 223556219+Copilot@users.noreply.github.com