Skip to content

Feature request: first-class label-name filter on pull_request_target.types: [labeled] (avoid red "skip via exit 1" idiom) #28678

@danielmeppiel

Description

@danielmeppiel

Problem

pull_request_target doesn't support names: [...] to filter by label name. The documented gh-aw idiom (per gh aw new examples and our own usage) is to put a step in on.steps: that does:

if [ "$LABEL_NAME" = "panel-review" ]; then exit 0; fi
exit 1   # short-circuit downstream pipeline

This works correctly -- downstream jobs skip via the needs: chain -- but the side-effect is a red ❌ "Filter on panel-review label" check on every PR that gets any label other than panel-review. PRs that just got type/bug or area/docs-site show a failed status check, which:

  • looks alarming to contributors
  • looks like a CI regression to maintainers reviewing the dashboard
  • becomes blocking if the org promotes the workflow to a required check
  • creates noise in gh run list (every label add is a red run)

Real example in the wild: https://github.com/microsoft/apm/actions/runs/24983384641/job/73150687473?pr=981 -- a one-line .github/workflows/docs.yml fix PR shows a red pre_activation failure simply because someone applied area/ci-cd.

Why naive workarounds don't fix it

We tried these in microsoft/apm:

Approach Why it fails
continue-on-error: true on the filter step Step soft-fails, JOB succeeds, but downstream runs anyway because the auto-generated activation gate (needs.pre_activation.outputs.activated == 'true') only checks team membership, not the filter step's outcome. Cosmetics fixed, semantics broken.
Filter step writes should_run to $GITHUB_OUTPUT, exits 0 Same problem -- the auto-generated activation gate doesn't know about should_run.
if: on the filter step itself Skips the step, not the job; downstream still proceeds.
Job-level if: github.event.label.name == 'panel-review' on pre_activation This is the idiomatic GitHub Actions pattern and would yield gray ⊘ Skipped (not red ❌ Failed) on unrelated labels -- but gh-aw doesn't expose any way to inject a job-level if: from the .md on: block.

Proposal

Add a first-class label-name filter to on:. Most natural shape (mirroring how roles: already works):

on:
  pull_request_target:
    types: [labeled]
  label-names: [panel-review]   # NEW -- only fire when the triggering label matches

Compile semantics: emit if: github.event.label.name == 'panel-review' || github.event_name == 'workflow_dispatch' on the pre_activation job. Drop the exit 1 step. Result: unrelated label triggers Skipped state on entire workflow (gray ⊘), zero noise.

This composes cleanly with existing roles: filtering -- roles: gates write-permission, label-names: gates the trigger condition.

Variants worth considering:

  • label-names: accepts a string or list (matches the roles: shape).
  • Combine with types: [labeled, unlabeled] if a workflow wants to react to a specific label being removed; gh-aw could special-case that on the matching event.

Workaround in the meantime

We're documenting in our .md that the red check is cosmetic and accepting it until this lands. We don't want to hand-edit .lock.yml because gh aw compile regenerates it, so any patch on pre_activation.if: would drift on the next compile.

Affected workflows we know of

In microsoft/apm alone:

Both use the same exit 1 pattern, both produce the same red ❌ noise on unrelated label adds.

Acceptance

  • on.label-names: [<name> | *] accepted in .md frontmatter
  • gh aw compile emits a pre_activation.if: that combines event/role gating with label-name match
  • The compiled workflow shows pre_activation as Skipped (not Failed) when an unrelated label is added
  • Existing workflows without label-names: are unchanged (backwards-compatible)

cc the microsoft/apm maintainers -- happy to test once a preview is available.

Metadata

Metadata

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions