Skip to content

feat: support glob patterns in allowed for add-labels safe-outputsΒ #32022

@yskopets

Description

@yskopets

πŸ€– This comment has been generated by Claude Code.

Summary

safe-outputs: add-labels supports two list-based constraints:

  • blocked β€” filters out label names matching glob patterns (e.g. ~*, *[bot])
  • allowed β€” restricts labels to an exact-match allowlist

The two lists are documented and treated symmetrically in the schema (ListJobConfig has both Allowed []string and Blocked []string with the glob-support note on Blocked), but the runtime enforcement is asymmetric:

// blocked β€” uses glob matching (safe_output_validator.cjs)
const isBlocked = blockedPatterns.some(pattern => matchesSimpleGlob(labelStr, pattern));

// allowed β€” uses exact string match only
validLabels = validLabels.filter(label => allowedLabels.includes(label));

Motivation

There are real use cases where glob patterns in allowed would be useful:

  • team-* β€” allow any team-scoped label without listing every team
  • priority-* β€” allow any priority tier label
  • area/* β€” namespaced label schemes

Currently, workflows that use such label naming conventions must enumerate every variant in allowed or omit the list entirely (permitting all labels).

Proposed change

Extend the allowed list in add-labels (and by extension remove-labels) to support the same matchesSimpleGlob logic already used for blocked. This would make the two lists consistent in capability.

// After
validLabels = validLabels.filter(label =>
  allowedLabels.some(pattern => matchesSimpleGlob(label, pattern))
);

The change is backwards-compatible: exact strings are valid glob patterns that match themselves.

Notes

  • The same asymmetry likely applies to other ListJobConfig-based outputs (add-reviewer, assign-milestone) β€” worth checking.
  • If exact-only allowed is intentional for security reasons (avoiding accidental over-permissioning), this issue can serve as the tracking point for documenting that rationale instead.

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