Skip to content

check_interface() False-Flags a Release Gate Written as a Folded Scalar, Because #949's Fix Drops Every Block-Scalar Body Including an if: Expression #1402

Description

@ptr727

#949 taught _code_view() to drop block-scalar bodies, so a token sitting in a documentation
string could not be read as structure. That defense does not distinguish a documentation
block scalar from an expression one, and if: is routinely written as a folded scalar. The
body it drops there is not prose about the gate. It is the gate.

The result is inverted: check_interface() reports a required release gate as missing on a
workflow that has it.

Reproduction, constructed

jobs:
  publish:
    name: Publish project release job
    needs: [plan, validate]
    if: >-
      ${{ needs.plan.outputs.publish == 'true' && needs.validate.result == 'success' }}
    uses: owner/repo/.github/workflows/build-release-task.yml@<pin>

requireTokensInJob looks for needs.validate.result == 'success' in this job. Run
_code_view() over it and the job reduces to:

  publish:
    name: Publish project release job
    needs: [plan, validate]
    if: >-
    uses: owner/repo/.github/workflows/build-release-task.yml@<pin>

The if: key survives and its entire condition is gone, so the token is absent and the audit
emits:

DRIFT  interface: .github/workflows/publish-release.yml job 'publish' missing required 'needs.validate.result == 'success''

Measured directly, importing the module and calling it on that job text: token present in the raw
job text True, token present in the _code_view() output False.

Writing the same condition inline on one line passes. The two forms are identical to GitHub
Actions, so the check is testing how the YAML is wrapped rather than whether the gate exists.

Where it showed up

The 2.0.577 resync pilot, audit run 2026-09-07T02:37:02Z | hub f8e7491, reported this against
PlexCleaner's publish-release.yml. The condition is present and correct there at both main
and develop, byte-identical, in the folded form above. The finding was carried into the resync
as real work before being checked, which is the cost this issue is about: a false positive on a
release gate invites someone to "fix" a workflow that is not broken, and the plausible fix is to
rewrite a correct condition.

Why a blanket rule cannot resolve it

The two cases genuinely conflict, and neither yields to a heuristic over the text:

The distinguishing fact is the key, not the scalar style: if, and the other
expression-bearing keys, hold a value that is always structure. A candidate fix is to keep the
folded or literal body for a known expression-bearing key set (if at minimum) and keep dropping
it everywhere else. Parsing the YAML and reading the value, rather than substring-matching the
text, resolves it more completely, and #949's own reasoning about the text view would then apply
only to the keys where a string body really is prose.

Whichever way it goes, spec/audit.py's self-test deserves a case for each of the two forms, since
the current suite passes with the inline form only and that is why this reached a downstream
repository.

Found during the #1399 fleet resync pilot.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    duplicateThis issue or pull request already exists

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions