Fix: wire inputs.item_number fallback for label trigger shorthand workflows#19795
Fix: wire inputs.item_number fallback for label trigger shorthand workflows#19795
inputs.item_number fallback for label trigger shorthand workflows#19795Conversation
…kflows Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
inputs.item_number fallback for label trigger shorthand workflows
There was a problem hiding this comment.
Pull request overview
Fixes manual workflow_dispatch runs for label-trigger shorthand workflows by wiring inputs.item_number as a fallback for entity-number expressions and by ensuring concurrency groups differ per dispatched item.
Changes:
- Add detection for
workflow_dispatch+inputs.item_numberand patch canonical entity-number expressions to fall back toinputs.item_number. - Update concurrency key generation to include
inputs.item_numberin the fallback chain to prevent cross-item cancellation. - Add unit tests covering the new detection, fallback application, and concurrency behavior.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/expression_extraction.go | Adds hasWorkflowDispatchItemNumber and applyWorkflowDispatchFallbacks to inject inputs.item_number fallbacks into extracted expressions. |
| pkg/workflow/compiler_yaml.go | Calls applyWorkflowDispatchFallbacks during prompt generation so expression mappings get updated before substitution. |
| pkg/workflow/concurrency.go | Extends concurrency group key expressions to include inputs.item_number where appropriate. |
| pkg/workflow/expression_extraction_test.go | Adds unit tests for detection and fallback patching of entity-number expressions. |
| pkg/workflow/concurrency_test.go | Adds test cases verifying concurrency keys include inputs.item_number for PR/issue/discussion label shorthand workflows. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| // hasWorkflowDispatchItemNumber returns true when the rendered "on:" YAML contains | ||
| // a workflow_dispatch trigger that exposes an item_number input. This is the | ||
| // signature produced by the label trigger shorthand (e.g. "on: pull_request labeled my-label"). | ||
| func hasWorkflowDispatchItemNumber(on string) bool { | ||
| return strings.Contains(on, "workflow_dispatch") && strings.Contains(on, "item_number") |
There was a problem hiding this comment.
hasWorkflowDispatchItemNumber is likely to produce false positives because it matches any substring "item_number" (e.g., an input named my_item_number, a description mentioning item_number, etc.). That can cause later code to emit expressions referencing inputs.item_number even when that input is not actually defined, which may break validation (e.g., actionlint) and won’t fix the dispatch-number issue.
Consider tightening detection to match YAML keys (e.g., require workflow_dispatch: and item_number: and ideally inputs:) using a regex with word boundaries / line anchors, or parse the on: YAML into a map and check on.workflow_dispatch.inputs.item_number explicitly.
| // hasWorkflowDispatchItemNumber returns true when the rendered "on:" YAML contains | |
| // a workflow_dispatch trigger that exposes an item_number input. This is the | |
| // signature produced by the label trigger shorthand (e.g. "on: pull_request labeled my-label"). | |
| func hasWorkflowDispatchItemNumber(on string) bool { | |
| return strings.Contains(on, "workflow_dispatch") && strings.Contains(on, "item_number") | |
| // workflowDispatchItemNumberRegex matches a workflow_dispatch trigger that defines | |
| // an inputs.item_number key in the rendered "on:" YAML. It looks for: | |
| // | |
| // workflow_dispatch: | |
| // inputs: | |
| // item_number: | |
| // | |
| // with arbitrary but consistent indentation. | |
| var workflowDispatchItemNumberRegex = regexp.MustCompile( | |
| `(?m)^\s*workflow_dispatch:\s*(?:\n[ \t]+.*)*?\n[ \t]+inputs:\s*(?:\n[ \t]+.*)*?\n[ \t]+item_number:\s*`, | |
| ) | |
| // hasWorkflowDispatchItemNumber returns true when the rendered "on:" YAML contains | |
| // a workflow_dispatch trigger that exposes an item_number input. This is the | |
| // signature produced by the label trigger shorthand (e.g. "on: pull_request labeled my-label"). | |
| func hasWorkflowDispatchItemNumber(on string) bool { | |
| return workflowDispatchItemNumberRegex.MatchString(on) |
pkg/workflow/compiler_yaml.go
Outdated
| // Enhance entity number expressions with || inputs.item_number fallback when the | ||
| // workflow has a workflow_dispatch trigger with item_number (generated by the label | ||
| // trigger shorthand). Without this, manual dispatch runs receive an empty entity number. | ||
| applyWorkflowDispatchFallbacks(expressionMappings, data.On) | ||
|
|
There was a problem hiding this comment.
applyWorkflowDispatchFallbacks is invoked before the inline-mode expression extraction (Step 2). When c.inlinePrompt or data.InlinedImports is true, the main markdown expressions are extracted and appended to expressionMappings after this call, so the newly added mappings (including github.event.*.number) will not receive the || inputs.item_number fallback.
To make the fallback effective in inline/inlined-import modes, call applyWorkflowDispatchFallbacks after all expression mappings have been collected (e.g., after Step 2 appends inlineExprMappings), or call it again after appending those mappings.
pkg/workflow/concurrency.go
Outdated
| } else if isPullRequestWorkflow(workflowData.On) && isIssueWorkflow(workflowData.On) { | ||
| // Mixed workflows with both issue and PR triggers | ||
| keys = append(keys, "${{ github.event.issue.number || github.event.pull_request.number || github.run_id }}") | ||
| if hasItemNumber { | ||
| keys = append(keys, "${{ github.event.issue.number || github.event.pull_request.number || inputs.item_number || github.run_id }}") | ||
| } else { | ||
| keys = append(keys, "${{ github.event.issue.number || github.event.pull_request.number || github.run_id }}") | ||
| } |
There was a problem hiding this comment.
The hasItemNumber branching introduces a lot of duplicated keys = append(keys, "${{ ... }}") strings across the trigger cases, which makes this function harder to maintain and increases the risk of future inconsistencies.
Consider building the base expression for each trigger case once, then conditionally inserting || inputs.item_number (e.g., via a small helper that takes the primary chain and injects the fallback when hasItemNumber is true).
|
@copilot make sure the feature is integrated in the overall parser of schedule. It should be parsed and return a structure data structure that indicates that itemNumber is used; instaed of parsing things again here. |
…tured frontmatter parsing Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Done in 9424ecc. Instead of re-parsing the rendered
|
|
@copilot review and add tests for parser |
…ispatchItemNumber pipeline Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Added in 1745712.
|
Label trigger shorthand (
on: pull_request labeled my-label) auto-generates aworkflow_dispatchwithinputs.item_number, but the compiler never wired that input as a fallback for entity number expressions. Manual dispatch runs received empty PR/issue/discussion numbers in the prompt, and concurrent dispatches for different items could cancel each other via the same concurrency group.Changes
compiler_orchestrator_workflow.go— AddedextractDispatchItemNumber(frontmatter map[string]any) boolthat detects the label-shorthand signature by walking the structured in-memory frontmatter map (on → workflow_dispatch → inputs → item_number) produced during preprocessing — no YAML string re-parsing. Called fromextractYAMLSectionsto populate the newWorkflowData.HasDispatchItemNumberfield.compiler_types.go— AddedHasDispatchItemNumber booltoWorkflowDataas a typed, first-class field set at parse time.expression_extraction.go— AddedapplyWorkflowDispatchFallbacks(mappings []*ExpressionMapping, hasItemNumber bool)which patches the three canonical entity number expressions:The
EnvVarname (e.g.GH_AW_GITHUB_EVENT_PULL_REQUEST_NUMBER) is preserved so existing env-var references remain stable.compiler_yaml.go— CallsapplyWorkflowDispatchFallbacksafter all expression mappings (including inline-mode ones) have been collected, ensuring the fallback is applied consistently in both normal and inlined-imports modes.concurrency.go— AddedentityConcurrencyKeyhelper to eliminate duplicated key-building.buildConcurrencyGroupKeysreadsworkflowData.HasDispatchItemNumberand insertsinputs.item_numberinto the fallback chain for PR/issue/discussion workflows, e.g.:This prevents concurrent manual dispatches for different items from canceling each other.
Tests — Unit tests for
extractDispatchItemNumber,applyWorkflowDispatchFallbacks,extractYAMLSectionsfield population, and three newbuildConcurrencyGroupKeyscases covering all three entity types with item_number. Parser integration tests inschedule_preprocessing_test.goverify the full pipeline frompreprocessScheduleFieldsthroughextractDispatchItemNumberfor all three entity types (pull_request,issues,discussion) and edge cases (comma-only labels error, 2-token fallthrough producing noitem_number).✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.