Findings No. 48
GitHub Actions rejects a workflow file that PyYAML calls valid
A workflow step left with two run: keys parses fine in PyYAML, which keeps the last duplicate, but GitHub rejects the whole file. Three daily data refreshes failed.
A YAML file can be valid to PyYAML and invalid to GitHub Actions. PyYAML accepts a mapping with a duplicate key and silently keeps the last value; GitHub rejects the entire workflow when it parses it.
On the CCRTA website, a commit that added a check to refresh-gtfs.yml, the workflow that refreshes the transit schedule data every day, accidentally swallowed the next step's - name: line. One step was left with two run: keys. We had checked the edit with yaml.safe_load, which reported the file as fine. GitHub refused to run it, and all three daily refreshes from October 26 to 28 failed at parse, so no new schedule data was committed for three days.
The fix restored the missing step and was checked with a loader that rejects duplicate keys. We now also compare the list of step names before and after any scripted edit to a workflow (grep '^ - name:'), which would have shown the missing step immediately.
The general rule: validate GitHub Actions workflows with a duplicate-key-strict loader or with actionlint, never with plain yaml.safe_load. A parser that is more forgiving than the real consumer approves exactly the mistakes you are trying to catch.
Receipt: CCRTA Website commit d6b7bfd (.github/workflows/refresh-gtfs.yml; FINDINGS.md, "CI / GitHub Actions").