diff --git a/.github/workflows/pr-code-quality-reviewer.lock.yml b/.github/workflows/pr-code-quality-reviewer.lock.yml index 40f9477777c..5c633517b95 100644 --- a/.github/workflows/pr-code-quality-reviewer.lock.yml +++ b/.github/workflows/pr-code-quality-reviewer.lock.yml @@ -1,4 +1,4 @@ -# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"661ab4bd42bd83eff79d7d460f50a12e3cee567ac434b2d37a2480d9a0e20965","body_hash":"4d3260d49c3010a13ea7c49bba10f51f2b9f1c1473ceca69008cfe766a9b273c","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.63","copilot-sdk":"1.0.1"}} +# gh-aw-metadata: {"schema_version":"v4","frontmatter_hash":"57c59bcb86591e8b21ad20298687f8d1adf895d5c4cf6f909d3339905428cc28","body_hash":"4d3260d49c3010a13ea7c49bba10f51f2b9f1c1473ceca69008cfe766a9b273c","strict":true,"agent_id":"copilot","engine_versions":{"copilot":"1.0.63","copilot-sdk":"1.0.1"}} # gh-aw-manifest: {"version":1,"secrets":["GH_AW_GITHUB_MCP_SERVER_TOKEN","GH_AW_GITHUB_TOKEN","GH_AW_OTEL_GRAFANA_AUTHORIZATION","GH_AW_OTEL_GRAFANA_ENDPOINT","GH_AW_OTEL_SENTRY_AUTHORIZATION","GH_AW_OTEL_SENTRY_ENDPOINT","GITHUB_TOKEN"],"actions":[{"repo":"actions/cache/restore","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/cache/save","sha":"27d5ce7f107fe9357f9df03efb73ab90386fccae","version":"v5.0.5"},{"repo":"actions/checkout","sha":"df4cb1c069e1874edd31b4311f1884172cec0e10","version":"v6.0.3"},{"repo":"actions/download-artifact","sha":"3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c","version":"v8.0.1"},{"repo":"actions/github-script","sha":"3a2844b7e9c422d3c10d287c895573f7108da1b3","version":"v9.0.0"},{"repo":"actions/setup-node","sha":"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e","version":"v6.4.0"},{"repo":"actions/upload-artifact","sha":"043fb46d1a93c77aae656e7c1c64a875d1fc6a0a","version":"v7.0.1"}],"containers":[{"image":"ghcr.io/github/gh-aw-firewall/agent:0.27.4","digest":"sha256:b268ebf37df2428b19efcb383f001d65dc6a5ec10af43feb886d1a8477ab0e3a","pinned_image":"ghcr.io/github/gh-aw-firewall/agent:0.27.4@sha256:b268ebf37df2428b19efcb383f001d65dc6a5ec10af43feb886d1a8477ab0e3a"},{"image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.4","digest":"sha256:3ea0d12a2d124db8ed6e2d18aff040e30ab3568161f258a132fccdeede4198cd","pinned_image":"ghcr.io/github/gh-aw-firewall/api-proxy:0.27.4@sha256:3ea0d12a2d124db8ed6e2d18aff040e30ab3568161f258a132fccdeede4198cd"},{"image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.4","digest":"sha256:72c378c029d2fad4684847ab44c329e526ac6b1a78cdf97656870ea11d201545","pinned_image":"ghcr.io/github/gh-aw-firewall/cli-proxy:0.27.4@sha256:72c378c029d2fad4684847ab44c329e526ac6b1a78cdf97656870ea11d201545"},{"image":"ghcr.io/github/gh-aw-firewall/squid:0.27.4","digest":"sha256:87979038897e40caed22245b64d1daa796390d2dca289b99d3d1174c85740af8","pinned_image":"ghcr.io/github/gh-aw-firewall/squid:0.27.4@sha256:87979038897e40caed22245b64d1daa796390d2dca289b99d3d1174c85740af8"},{"image":"ghcr.io/github/gh-aw-mcpg:v0.3.26","digest":"sha256:d3b03f54eee3a8176818c9a52087623e45b7f644a28814337fcc0838e2534490","pinned_image":"ghcr.io/github/gh-aw-mcpg:v0.3.26@sha256:d3b03f54eee3a8176818c9a52087623e45b7f644a28814337fcc0838e2534490"},{"image":"ghcr.io/github/github-mcp-server:v1.3.0","digest":"sha256:5c83359327a0bacc3d34db730bea6557d39d341cee0bf6c58c9a896e33150e80","pinned_image":"ghcr.io/github/github-mcp-server:v1.3.0@sha256:5c83359327a0bacc3d34db730bea6557d39d341cee0bf6c58c9a896e33150e80"}]} # This file was automatically generated by gh-aw. DO NOT EDIT. To debug this workflow, load the skill at https://github.com/github/gh-aw/blob/main/debug.md # diff --git a/pkg/workflow/template.go b/pkg/workflow/template.go index 6d2bddb33b8..f589002b742 100644 --- a/pkg/workflow/template.go +++ b/pkg/workflow/template.go @@ -9,6 +9,7 @@ import ( ) var templateLog = logger.New("workflow:template") +var inlineSubAgentPattern = regexp.MustCompile("(?m)^##[ \t]+agent:[ \t]+`[a-z][a-z0-9_-]*`[ \t]*$") // wrapExpressionsInTemplateConditionals transforms template conditionals by wrapping // expressions in ${{ }}. For example: @@ -99,7 +100,8 @@ func (c *Compiler) generateInterpolationAndTemplateStep(yaml *strings.Builder, e // Check if we need template rendering hasTemplatePattern := strings.Contains(data.MarkdownContent, "{{#if ") hasGitHubContext := hasGitHubTool(data.ParsedTools) - hasTemplates := hasTemplatePattern || hasGitHubContext + hasInlineSubAgents := inlineSubAgentPattern.MatchString(data.MarkdownContent) + hasTemplates := hasTemplatePattern || hasGitHubContext || hasInlineSubAgents // Skip if neither interpolation nor template rendering is needed if !hasExpressions && !hasTemplates { @@ -107,8 +109,8 @@ func (c *Compiler) generateInterpolationAndTemplateStep(yaml *strings.Builder, e return } - templateLog.Printf("Generating interpolation and template step: expressions=%d, hasPattern=%v, hasGitHubContext=%v", - len(expressionMappings), hasTemplatePattern, hasGitHubContext) + templateLog.Printf("Generating interpolation and template step: expressions=%d, hasPattern=%v, hasGitHubContext=%v, hasInlineSubAgents=%v", + len(expressionMappings), hasTemplatePattern, hasGitHubContext, hasInlineSubAgents) yaml.WriteString(" - name: Interpolate variables and render templates\n") fmt.Fprintf(yaml, " uses: %s\n", getCachedActionPin("actions/github-script", data)) diff --git a/pkg/workflow/template_test.go b/pkg/workflow/template_test.go index a95c38e4847..cf068c3a343 100644 --- a/pkg/workflow/template_test.go +++ b/pkg/workflow/template_test.go @@ -72,3 +72,22 @@ func TestGenerateInterpolationAndTemplateStep_GeneratePath(t *testing.T) { assert.Contains(t, result, "interpolate_prompt.cjs", "interpolate_prompt script should be referenced in the step") assert.Contains(t, result, "setupGlobals", "setupGlobals helper should be called to initialise GitHub Actions objects") } + +// TestGenerateInterpolationAndTemplateStep_WithInlineSubAgent ensures inline sub-agent +// workflows still run interpolate_prompt.cjs even when github context templates are absent. +// ParsedTools uses an empty map (no github key) so hasGitHubTool returns false, +// confirming that the inline sub-agent marker alone is sufficient to trigger the step. +func TestGenerateInterpolationAndTemplateStep_WithInlineSubAgent(t *testing.T) { + compiler := &Compiler{} + data := &WorkflowData{ + MarkdownContent: "Main prompt\n\n## agent: `planner`\nDo planning.", + ParsedTools: NewTools(map[string]any{}), + } + + var yaml strings.Builder + compiler.generateInterpolationAndTemplateStep(&yaml, nil, data) + + result := yaml.String() + assert.Contains(t, result, "Interpolate variables and render templates", "step should be present when inline sub-agents are defined") + assert.Contains(t, result, "interpolate_prompt.cjs", "interpolate_prompt script should run to extract inline sub-agents") +}