Skip to content

Add compile-time glob validation for workflow trigger filter patterns#22873

Merged
pelikhan merged 4 commits intomainfrom
copilot/add-glob-validation-using-actionlint
Mar 25, 2026
Merged

Add compile-time glob validation for workflow trigger filter patterns#22873
pelikhan merged 4 commits intomainfrom
copilot/add-glob-validation-using-actionlint

Conversation

Copy link
Contributor

Copilot AI commented Mar 25, 2026

Workflow trigger filter patterns (branches, tags, paths) were only validated by Docker-based actionlint at lint time. Invalid globs — including the always-invalid ./src/** path prefix — could silently produce broken .lock.yml files.

Changes

pkg/workflow/glob_validation.go (new)

Self-contained glob validator adapted from actionlint glob.go (MIT License, stdlib-only). The full actionlint package cannot be imported directly due to a transitive go.yaml.in/yaml/v4 rc.3→rc.4 API incompatibility.

  • validateRefGlob(pat) — Git ref pattern validation (branches, tags)
  • validatePathGlob(pat) — path pattern validation; explicitly rejects ./-prefixed patterns

pkg/workflow/compiler_filters_validation.go

  • ValidateGlobPatterns(frontmatter) — iterates over push, pull_request, pull_request_target, workflow_run events and validates all branch/tag/path filter patterns

pkg/workflow/compiler_orchestrator_frontmatter.go

  • Calls ValidateGlobPatterns in the frontmatter pipeline, immediately after the existing ValidateEventFilters check

pkg/workflow/compiler_filters_validation_test.go

  • TestValidateGlobPatterns: 18 table-driven cases covering valid patterns, invalid ref/path globs, the ./ prefix edge case, and []any list inputs
  • TestValidateGlobPatternsExtendedEvents: additional cases for pull_request_target and workflow_run events, all filter keys (branches-ignore, tags-ignore), second-invalid-pattern-in-list detection, and non-map event value handling
  • TestValidateRefGlob: 17 direct cases for the low-level ref glob helper (space, tilde, caret, colon, slash prefix/suffix, trailing dot, empty/unclosed brackets, bare !)
  • TestValidatePathGlob: 16 direct cases for the path glob helper (./ and ../ prefixes, bare ./.., whitespace, empty string, unclosed brackets)
  • TestToStringSlice: 8 cases for the conversion helper covering all supported input types and error paths

Example — caught at compile time:

on:
  push:
    paths:
      - ./src/**/*.go   # error: invalid glob pattern "./src/**/*.go" in on.push.paths
    branches:
      - main branch     # error: invalid glob pattern "main branch" in on.push.branches

💬 Send tasks to Copilot coding agent from Slack and Teams to turn conversations into code. Copilot posts an update in your thread when it's finished.

- Add glob_validation.go with self-contained ValidateRefGlob/ValidatePathGlob
  logic adapted from github.com/rhysd/actionlint (MIT License, stdlib-only deps)
- Add ValidateGlobPatterns() to compiler_filters_validation.go
- Wire ValidateGlobPatterns into compiler_orchestrator_frontmatter.go
- Add 18-case TestValidateGlobPatterns table-driven test

Catches invalid branch/tag/path globs at compile time, including the
notable ./ prefix edge case that actionlint v1.7.11 checks.

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/75dde239-a5d4-4e93-bbd9-d24252279a4e
Copilot AI changed the title [WIP] Add compile-time glob validation using actionlint.ValidateRefGlob and ValidatePathGlob Add compile-time glob validation for workflow trigger filter patterns Mar 25, 2026
Copilot AI requested a review from pelikhan March 25, 2026 11:50
@pelikhan pelikhan marked this pull request as ready for review March 25, 2026 11:52
Copilot AI review requested due to automatic review settings March 25, 2026 11:52
@pelikhan
Copy link
Contributor

@copilot add more tests

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds compile-time validation for GitHub Actions workflow trigger filter glob patterns so invalid branch/tag/path filters are caught during frontmatter compilation (instead of only at lint time).

Changes:

  • Introduces a stdlib-only glob validator (adapted from actionlint) for ref and path patterns.
  • Adds ValidateGlobPatterns to validate branches/tags/paths filters across supported trigger events.
  • Wires glob validation into the frontmatter compilation pipeline and adds table-driven tests.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 3 comments.

File Description
pkg/workflow/glob_validation.go New glob validation implementation for ref and path filter patterns (including rejecting ./ / ../ path prefixes).
pkg/workflow/compiler_filters_validation.go Adds ValidateGlobPatterns and supporting helpers to validate filter glob lists in the on: section.
pkg/workflow/compiler_orchestrator_frontmatter.go Hooks glob validation into the existing frontmatter validation pipeline.
pkg/workflow/compiler_filters_validation_test.go Adds table-driven tests covering valid/invalid ref/path patterns and list typing.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

case '[', '?', '*':
c = v.scan.Next()
if v.isRef {
v.invalidRefChar(v.scan.Peek(), "ref name cannot contain spaces, ~, ^, :, [, ?, *")
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the \\ escape handling for ref patterns, the invalid character reported is taken from v.scan.Peek() after consuming the escaped rune. This points at the next character (or EOF), producing incorrect/misleading diagnostics (and potentially odd output when at end of string). Use the consumed escaped rune (c) when calling invalidRefChar so the error reports the actual invalid character being escaped.

Suggested change
v.invalidRefChar(v.scan.Peek(), "ref name cannot contain spaces, ~, ^, :, [, ?, *")
v.invalidRefChar(c, "ref name cannot contain spaces, ~, ^, :, [, ?, *")

Copilot uses AI. Check for mistakes.
// Reject '.', '..', './<path>', and '../<path>' (#521 in actionlint)
stripped := strings.TrimPrefix(p, "!")
if stripped == "." || stripped == ".." || strings.HasPrefix(stripped, "./") || strings.HasPrefix(stripped, "../") {
errs = append(errs, invalidGlobPattern{"'.' and '..' are not allowed in glob path", 0})
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

validatePathGlob rejects patterns starting with ./ and ../, but the error message says only "'.' and '..' are not allowed". This is likely to confuse users hitting the ./src/** case called out in the PR description. Consider updating the message to explicitly mention that ./ and ../ prefixes (and ./.. themselves) are not allowed.

Suggested change
errs = append(errs, invalidGlobPattern{"'.' and '..' are not allowed in glob path", 0})
errs = append(errs, invalidGlobPattern{"'.', '..', and paths starting with './' or '../' are not allowed in glob path", 0})

Copilot uses AI. Check for mistakes.
Column int
}

func (e *invalidGlobPattern) Error() string {
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

invalidGlobPattern is stored and returned as a value type ([]invalidGlobPattern), but Error() is defined on *invalidGlobPattern. If the intent is for invalidGlobPattern itself to satisfy the error interface, consider changing Error() to a value receiver (or otherwise clarify/remove the method) to avoid surprising behavior when used without taking an address.

Suggested change
func (e *invalidGlobPattern) Error() string {
func (e invalidGlobPattern) Error() string {

Copilot uses AI. Check for mistakes.
@pelikhan
Copy link
Contributor

/cloclo apply comments

@github-actions
Copy link
Contributor

github-actions bot commented Mar 25, 2026

🎤 Bravo! /cloclo has delivered a stunning performance! Standing ovation! 🌟

…keys, and low-level helpers

- TestValidateGlobPatternsExtendedEvents: pull_request_target, workflow_run,
  branches-ignore, tags-ignore, second invalid pattern in list, non-map event value
- TestValidateRefGlob: 17 cases for the low-level validateRefGlob helper
- TestValidatePathGlob: 16 cases for the low-level validatePathGlob helper
- TestToStringSlice: 8 cases for the toStringSlice conversion helper

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/8a412c5c-7f0e-441d-a835-0947a3066501
Copy link
Contributor Author

Copilot AI commented Mar 25, 2026

@copilot add more tests

Added in ad1f719. The new tests cover:

  • TestValidateGlobPatternsExtendedEvents — previously untested events (pull_request_target, workflow_run) and filter keys (branches-ignore, tags-ignore), second-invalid-pattern-in-list, and non-map event values (graceful skip)
  • TestValidateRefGlob — 17 direct cases for the low-level ref validator: space, tilde, caret, colon, leading/trailing slash, trailing dot, empty [], unclosed [], bare !, etc.
  • TestValidatePathGlob — 16 direct cases: ./ prefix, ../ prefix, bare ./.., negated ./ prefix, leading/trailing spaces, empty string, bare !, unclosed bracket
  • TestToStringSlice — 8 cases for the helper including []string, []any, single string, mixed-type list (error), integer (error), nil (error), empty slices

@pelikhan
Copy link
Contributor

@copilot apply comments

- Use value receiver on invalidGlobPattern.Error() so the type satisfies
  the error interface when used as a value (not just pointer)
- Fix invalidRefChar call in escape handling to use the consumed rune c
  instead of v.scan.Peek() (which pointed at the next character)
- Improve error message for ./ and ../ path prefix rejection to
  explicitly mention both the bare dot forms and the prefix forms

Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Agent-Logs-Url: https://github.com/github/gh-aw/sessions/49256cc9-5d91-4606-b170-0f1fdb6ed8fd
Copy link
Contributor Author

Copilot AI commented Mar 25, 2026

@copilot apply comments

Applied all three in 383025d:

  1. invalidGlobPattern.Error() changed to value receiver so the type satisfies error without needing a pointer
  2. invalidRefChar now passes the consumed rune c instead of v.scan.Peek(), so escape-sequence diagnostics report the actual invalid character
  3. Error message updated to "'.', '..', and paths starting with './' or '../' are not allowed in glob path" for clarity on the ./src/** case

@pelikhan pelikhan merged commit 0225b81 into main Mar 25, 2026
55 checks passed
@pelikhan pelikhan deleted the copilot/add-glob-validation-using-actionlint branch March 25, 2026 14:04
github-actions bot added a commit that referenced this pull request Mar 25, 2026
…idation

- cli.md: expand gh aw audit description with the new report sections
  added in #22932 (engine config, prompt analysis, session & agent
  performance, MCP server health, safe output summary)
- github-tools.md: document toolsets shorthand values (default, all) and
  add a note that toolsets: [all] excludes dependabot (#22851)
- triggers.md: document compile-time glob pattern validation for push/
  pull_request/pull_request_target/workflow_run filter fields (#22873)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
pelikhan pushed a commit that referenced this pull request Mar 25, 2026
…idation (#22972)

- cli.md: expand gh aw audit description with the new report sections
  added in #22932 (engine config, prompt analysis, session & agent
  performance, MCP server health, safe output summary)
- github-tools.md: document toolsets shorthand values (default, all) and
  add a note that toolsets: [all] excludes dependabot (#22851)
- triggers.md: document compile-time glob pattern validation for push/
  pull_request/pull_request_target/workflow_run filter fields (#22873)

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[plan] Add compile-time glob validation using actionlint.ValidateRefGlob and ValidatePathGlob

3 participants