{"record":{"id":"52f446daa0a119fa","repo":"ZhuLinsen/daily_stock_analysis","slug":"expected-00-daily-analysis-yml-job-analyze-to-incl","errorCode":null,"errorMessage":"Expected 00-daily-analysis.yml job analyze to include a step named {ANALYZE_STEP_NAME!r}; available step names: {available_step_names}","messagePattern":"Expected 00-daily-analysis\\.yml job analyze to include a step named (.+?); available step names: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"scripts/generate_notification_actions_env_table.py","lineNumber":52,"sourceCode":"\n@dataclass(frozen=True)\nclass EnvTableRow:\n    key: str\n    tier: str\n    channels: tuple[str, ...]\n    source: str\n    default: str\n\n\ndef load_daily_analysis_env(workflow_path: Path = WORKFLOW_PATH) -> dict[str, str]:\n    \"\"\"Load the env block from the daily analysis workflow.\"\"\"\n\n    workflow = yaml.safe_load(workflow_path.read_text(encoding=\"utf-8\"))\n    steps = workflow[\"jobs\"][\"analyze\"][\"steps\"]\n    analyze_step = next((step for step in steps if step.get(\"name\") == ANALYZE_STEP_NAME), None)\n    available_step_names = [step.get(\"name\", \"<unnamed>\") for step in steps]\n    if analyze_step is None:\n        raise ValueError(\n            f\"Expected 00-daily-analysis.yml job analyze to include a step named \"\n            f\"{ANALYZE_STEP_NAME!r}; available step names: {available_step_names}\"\n        )\n    return analyze_step[\"env\"]\n\n\ndef _ordered_unique(values: Iterable[str]) -> tuple[str, ...]:\n    seen: set[str] = set()\n    ordered: list[str] = []\n    for value in values:\n        if value in seen:\n            continue\n        seen.add(value)\n        ordered.append(value)\n    return tuple(ordered)\n\n\ndef _key_metadata() -> dict[str, tuple[str, tuple[str, ...]]]:","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/ZhuLinsen/daily_stock_analysis/blob/5159bd72e8373d215492dff122acc9d389e219c9/scripts/generate_notification_actions_env_table.py#L34-L70","documentation":"scripts/generate_notification_actions_env_table.py parses .github/workflows/00-daily-analysis.yml, navigates jobs.analyze.steps, and requires exactly one step named '执行股票分析' (ANALYZE_STEP_NAME) to read its env block for the docs table. If the workflow has no step with that name, it raises ValueError listing the step names it did find — a consistency check between CI workflow and generated documentation.","triggerScenarios":"Renaming the analyze step in 00-daily-analysis.yml; splitting it into multiple steps; reordering jobs so the analyze job id changes; YAML restructuring (steps moved to a composite action). Any of these without updating ANALYZE_STEP_NAME breaks the script.","commonSituations":"A PR edits the daily-analysis workflow (step rename, added checkout steps with names) and CI/docs generation then fails; local doc regeneration after pulling a workflow change; the 'available step names' list in the message shows what the script saw — compare it against the constant.","solutions":["Open .github/workflows/00-daily-analysis.yml, find jobs.analyze.steps, and restore/assign the step name '执行股票分析' on the step that carries the analysis env block.","If the rename was intentional, update ANALYZE_STEP_NAME in scripts/generate_notification_actions_env_table.py:32 to the new name in the same PR.","Confirm the job is still keyed 'analyze' — a job rename breaks workflow['jobs']['analyze'] with a different (KeyError) failure that should be fixed alongside.","Re-run the script to confirm it now extracts the env block."],"exampleFix":"# before (.github/workflows/00-daily-analysis.yml)\n- name: Run Analysis   # renamed step\n  env: ...\n\n# after\n- name: 执行股票分析    # must match ANALYZE_STEP_NAME\n  env: ...","handlingStrategy":"validation","validationCode":"import yaml\nfrom pathlib import Path\n\nwf = yaml.safe_load(Path(\".github/workflows/00-daily-analysis.yml\").read_text())\nsteps = wf[\"jobs\"][\"analyze\"][\"steps\"]\nnames = [s.get(\"name\") for s in steps]\nassert \"执行股票分析\" in names, f\"analyze step missing; got {names}\"","typeGuard":null,"tryCatchPattern":"try:\n    env = load_daily_analysis_env()\nexcept ValueError as e:\n    # CI/docs pipeline failure: fix workflow or ANALYZE_STEP_NAME, do not skip\n    raise SystemExit(f\"workflow/docs drift: {e}\")","preventionTips":["When renaming workflow steps, grep scripts/ for the literal step name first.","Keep ANALYZE_STEP_NAME and the workflow step name in the same PR.","Run the doc generator in CI so drift is caught at PR time, not release time."],"tags":["ci","github-actions","workflow","docs-generation"],"backgroundTag":null,"analyzedSha":"5159bd72e8373d215492dff122acc9d389e219c9","analyzedAt":"2026-08-15T01:59:36.292Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}