Skip to content

Commit 0c1b789

Browse files
committed
fix(e2e): 232 must not require PyYAML
macOS runner 没有 PyYAML,`ModuleNotFoundError: No module named 'yaml'` 让这条新测试 在那台机器上必红。硬依赖一个开发库的测试,最后会被删掉而不是被修好。 改成两档:有 PyYAML 就整份解析(并要求声明了 jobs),没有就退化成针对性 lint —— 正则命中的正是这条测试存在的那个缺陷形态:引号标量闭合后还有内容 (`run: "$BENCH" --list`)。**并且明说跑的是哪一档**:一个悄悄比它所替代的检查更弱的 回落,就是绿色开始失去意义的方式。 两档都验过:干净树上都通过;植入缺陷后**两档都失败**。
1 parent d1911bb commit 0c1b789

1 file changed

Lines changed: 34 additions & 9 deletions

File tree

tests/e2e/232_workflow_syntax.sh

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,53 @@
1414
#
1515
# The check is deliberately syntax-only. Validating the schema would need the
1616
# full Actions grammar; the failure mode that actually happened is a file that
17-
# does not parse, and that costs three lines to rule out forever.
17+
# does not parse, and that costs a few lines to rule out forever.
1818
set -e
1919

2020
REPO="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
2121
DIR="$REPO/.github/workflows"
2222
[ -d "$DIR" ] || { echo "no workflows directory at $DIR"; exit 1; }
2323

24-
count=$(find "$DIR" -maxdepth 1 -name '*.yml' -o -maxdepth 1 -name '*.yaml' | wc -l)
24+
count=$(find "$DIR" -maxdepth 1 \( -name '*.yml' -o -name '*.yaml' \) | wc -l)
2525
[ "$count" -gt 0 ] || { echo "no workflow files found under $DIR"; exit 1; }
2626

27-
python3 - "$DIR" <<'PY'
28-
import pathlib, sys, yaml
27+
python3 - "$DIR" <<'PYEOF'
28+
import pathlib, re, sys
29+
30+
# PyYAML is not everywhere — the macOS runner has none, and a test that
31+
# hard-fails on a missing dev dependency is a test that gets deleted. So: full
32+
# parse where it exists, targeted lint where it does not, and SAY WHICH RAN. A
33+
# fallback that is quietly weaker than the check it replaces is how a green
34+
# stops meaning anything.
35+
try:
36+
import yaml
37+
HAVE_YAML = True
38+
except ImportError:
39+
HAVE_YAML = False
40+
41+
# The exact failure this test exists for: a scalar that opens with a quote and
42+
# carries more content after the closing one —
43+
# run: "$BENCH" --list
44+
# YAML reads that as a quoted scalar followed by garbage and refuses the file.
45+
TRAILING_AFTER_QUOTED = re.compile(r'^\s*[\w.-]+:\s*"[^"]*"\s*\S')
2946
3047
bad = []
3148
files = sorted(p for p in pathlib.Path(sys.argv[1]).iterdir()
3249
if p.suffix in (".yml", ".yaml"))
3350
for p in files:
51+
text = p.read_text()
52+
for n, line in enumerate(text.splitlines(), 1):
53+
if TRAILING_AFTER_QUOTED.match(line):
54+
bad.append(f"{p.name}:{n}: content after a quoted scalar: {line.strip()}")
55+
if not HAVE_YAML:
56+
continue
3457
try:
35-
doc = yaml.safe_load(p.read_text())
58+
doc = yaml.safe_load(text)
3659
except Exception as e:
3760
bad.append(f"{p.name}: {e}")
3861
continue
39-
# A workflow with no `jobs` parses but can never do anything — the same
40-
# class of silent nothing, so it is reported the same way.
62+
# A workflow with no `jobs` parses but can never do anything — the same class
63+
# of silent nothing, so it is reported the same way.
4164
if not isinstance(doc, dict) or not doc.get("jobs"):
4265
bad.append(f"{p.name}: parsed, but declares no jobs")
4366
@@ -46,7 +69,9 @@ if bad:
4669
for b in bad:
4770
print(" " + b)
4871
sys.exit(1)
49-
print(f"{len(files)} workflow files parse and declare jobs")
50-
PY
72+
73+
mode = "parsed" if HAVE_YAML else "linted (no PyYAML here — quoted-scalar check only)"
74+
print(f"{len(files)} workflow files {mode}")
75+
PYEOF
5176

5277
echo "workflow syntax OK"

0 commit comments

Comments
 (0)