Skip to content

Standardize heredoc delimiters with GH_AW_ prefix - #14942

Merged
pelikhan merged 6 commits into
mainfrom
copilot/add-go-helper-function
Feb 11, 2026
Merged

Standardize heredoc delimiters with GH_AW_ prefix#14942
pelikhan merged 6 commits into
mainfrom
copilot/add-go-helper-function

Conversation

CopilotAI commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

Heredoc delimiters in compiled lock.yml files were inconsistent (EOF, PROMPT_EOF, MCPCONFIG_EOF, EOFJS_<name>, etc.). Created GenerateHeredocDelimiter() helper to enforce GH_AW_<NAME>_EOF format across all 100+ occurrences.

Implementation

// pkg/workflow/strings.gofuncGenerateHeredocDelimiter(namestring) string {
ifname=="" {
return"GH_AW_EOF"
}
return"GH_AW_"+strings.ToUpper(name) +"_EOF"
}
// Usagedelimiter:=GenerateHeredocDelimiter("PROMPT")
yaml.WriteString(fmt.Sprintf("cat << '%s' >> \"$GH_AW_PROMPT\"\n", delimiter))
// Generates: cat << 'GH_AW_PROMPT_EOF' >> "$GH_AW_PROMPT"

Changes

  • Helper function: pkg/workflow/strings.go - GenerateHeredocDelimiter() with comprehensive test coverage
  • Core files: Updated prompt_step.go, sh.go, mcp_renderer.go, mcp_setup_generator.go, bundler_file_mode.go, copilot_srt.go, codex_mcp.go
  • Test assertions: Updated all test files checking heredoc format
  • Lock files: 147 workflow files recompiled with standardized delimiters

Delimiter Mapping

BeforeAfter
PROMPT_EOFGH_AW_PROMPT_EOF
MCPCONFIG_EOFGH_AW_MCP_CONFIG_EOF
SRT_CONFIG_EOFGH_AW_SRT_CONFIG_EOF
EOF_TOOLS_JSONGH_AW_SAFE_INPUTS_TOOLS_EOF
EOFJS_<name>GH_AW_SAFE_INPUTS_JS_<NAME>_EOF
EOF_<hash>GH_AW_FILE_<HASH>_EOF
Original prompt

All heredoc delimiters used in tbe compiled lock.yml files should be prefixed formatted as GH_AW_..._EOF . Create go helper function to generator those names.


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.


Changeset

  • Type: patch
  • Description: Added a helper to generate GH_AW_* heredoc delimiters and updated workflows to use the standardized names.

Generated by Changeset Generator

CopilotAIand others added 2 commits February 11, 2026 12:34
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
CopilotAIand others added 2 commits February 11, 2026 12:40
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
CopilotAI changed the title [WIP] Add go helper function for heredoc delimiter generationStandardize heredoc delimiters with GH_AW_ prefixFeb 11, 2026
CopilotAI requested a review from pelikhanFebruary 11, 2026 12:50
@pelikhan
pelikhan marked this pull request as ready for review February 11, 2026 12:51
CopilotAI review requested due to automatic review settings February 11, 2026 12:51
@github-actions

Copy link
Copy Markdown
Contributor

🧪 Smoke Project is now testing project operations...

@github-actions

Copy link
Copy Markdown
Contributor

📰 BREAKING: Smoke Copilot is now investigating this pull request. Sources say the story is developing...

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

🎬 THE ENDSmoke ClaudeMISSION: ACCOMPLISHED! The hero saves the day! ✨

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

✨ The prophecy is fulfilled... Smoke Codex has completed its mystical journey. The stars align. 🌟

@github-actions

github-actionsBot commented Feb 11, 2026

Copy link
Copy Markdown
Contributor

Changeset Generator completed successfully!

@github-actions

Copy link
Copy Markdown
Contributor

Agent Container Tool Check ✅

ToolStatusVersion
bash5.2.21
shavailable
git2.52.0
jq1.7
yq4.52.2
curl8.5.0
gh2.86.0
node20.20.0
python33.12.3
go1.24.12
java21.0.10
dotnet10.0.102

Result: 12/12 tools available ✅

All required development tools are present and functional in the agent container environment.

AI generated by Agent Container Smoke Test

@github-actions

Copy link
Copy Markdown
Contributor

Smoke Project completed successfully. All project operations validated.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR standardizes heredoc delimiters emitted by the workflow compiler so compiled *.lock.yml files consistently use a GH_AW_<NAME>_EOF-style delimiter, reducing inconsistency across generated shell snippets.

Changes:

  • Added GenerateHeredocDelimiter() helper and tests to centralize delimiter naming.
  • Updated multiple workflow compilation/generation paths (prompt writing, MCP setup/config rendering, bundled file writing, SRT wrapper generation) to use the helper.
  • Recompiled a large set of *.lock.yml workflow outputs to reflect the standardized delimiters (and incidentally updated at least one pinned action SHA).

Reviewed changes

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

Show a summary per file
FileDescription
pkg/workflow/strings.goIntroduces GenerateHeredocDelimiter() helper for consistent heredoc delimiter generation.
pkg/workflow/strings_test.goAdds unit tests covering delimiter generation and basic format assertions.
pkg/workflow/sh.goUses generated delimiter for prompt heredocs written into YAML.
pkg/workflow/prompt_step.goUses generated delimiter in prompt step heredoc emission.
pkg/workflow/prompt_step_test.goUpdates expected compiled output strings for new prompt delimiter.
pkg/workflow/prompt_step_helper_test.goUpdates expected compiled output strings for new prompt delimiter.
pkg/workflow/mcp_setup_generator.goStandardizes delimiters for safe-outputs/safe-inputs file generation and tool scripts.
pkg/workflow/mcp_renderer.goStandardizes the MCP config heredoc delimiter used for gateway startup piping.
pkg/workflow/heredoc_interpolation_test.goUpdates assertions to the new prompt delimiter naming.
pkg/workflow/engine_helpers_shared_test.goUpdates MCP config rendering expectations for the new delimiter.
pkg/workflow/custom_engine_test.goUpdates MCP config rendering expectations for the new delimiter.
pkg/workflow/copilot_srt.goUses generated delimiters for SRT wrapper/config heredocs.
pkg/workflow/codex_mcp.goUses generated delimiter for Codex TOML config heredoc end marker.
pkg/workflow/codex_engine_test.goUpdates expectations for Codex MCP config heredoc delimiters.
pkg/workflow/bundler_file_mode.goUses generated delimiter for file hash based heredocs when writing bundled scripts.
pkg/workflow/data/action_pins.jsonAdds an action pin entry for docker/build-push-action@v6.
.github/aw/actions-lock.jsonMirrors the docker/build-push-action@v6 pin in the GitHub config lock file.
.github/workflows/*.lock.yml (147 files)Recompiled workflow lockfiles to reflect standardized heredoc delimiters (and updated some pinned SHAs).
Comments suppressed due to low confidence (1)

.github/workflows/release.lock.yml:1299

  • This workflow lock file changes the pinned commit for docker/build-push-action@v6. Because action pin changes are security- and behavior-sensitive, it would be good to confirm this update is expected as part of the recompile (and ideally mention it in the PR description alongside the delimiter changes).

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

Comment on lines +274 to +304
// GenerateHeredocDelimiter creates a standardized heredoc delimiter with the GH_AW prefix.
// All heredoc delimiters in compiled lock.yml files should use this format for consistency.
//
// The function generates delimiters in the format: GH_AW_<NAME>_EOF
//
// Parameters:
// - name: A descriptive identifier for the heredoc content (e.g., "PROMPT", "MCP_CONFIG", "TOOLS_JSON")
// The name should use SCREAMING_SNAKE_CASE without the _EOF suffix.
//
// Returns a delimiter string in the format "GH_AW_<NAME>_EOF"
//
// Example:
//
// GenerateHeredocDelimiter("PROMPT") // returns "GH_AW_PROMPT_EOF"
// GenerateHeredocDelimiter("MCP_CONFIG") // returns "GH_AW_MCP_CONFIG_EOF"
// GenerateHeredocDelimiter("TOOLS_JSON") // returns "GH_AW_TOOLS_JSON_EOF"
// GenerateHeredocDelimiter("SRT_CONFIG") // returns "GH_AW_SRT_CONFIG_EOF"
// GenerateHeredocDelimiter("FILE_123ABC") // returns "GH_AW_FILE_123ABC_EOF"
//
// Usage in heredoc generation:
//
// delimiter := GenerateHeredocDelimiter("PROMPT")
// yaml.WriteString(fmt.Sprintf("cat << '%s' >> \"$GH_AW_PROMPT\"\n", delimiter))
// yaml.WriteString("content here\n")
// yaml.WriteString(delimiter + "\n")
func GenerateHeredocDelimiter(name string) string {
if name == "" {
return "GH_AW_EOF"
}
return "GH_AW_" + strings.ToUpper(name) + "_EOF"
}

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

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

GenerateHeredocDelimiter()’s docstring says the input should be SCREAMING_SNAKE_CASE and the examples imply delimiters only contain A–Z/0–9/underscores, but the implementation only uppercases and will preserve dashes or other characters. This already shows up in recompiled lock files (e.g. SAFE_INPUTS_* tool names include '-'). Consider normalizing the name (e.g., replace '-' with '_' and strip any trailing '_EOF') so the function enforces the documented format and avoids surprising delimiters.

Copilot uses AI. Check for mistakes.
Comment on lines 342 to +357
for _, toolName := range safeInputToolNames {
toolConfig := workflowData.SafeInputs.Tools[toolName]
if toolConfig.Script != "" {
// JavaScript tool
toolScript := generateSafeInputJavaScriptToolScript(toolConfig)
fmt.Fprintf(yaml, " cat > /opt/gh-aw/safe-inputs/%s.cjs << 'EOFJS_%s'\n", toolName, toolName)
jsDelimiter := GenerateHeredocDelimiter(fmt.Sprintf("SAFE_INPUTS_JS_%s", strings.ToUpper(toolName)))
fmt.Fprintf(yaml, " cat > /opt/gh-aw/safe-inputs/%s.cjs << '%s'\n", toolName, jsDelimiter)
for _, line := range FormatJavaScriptForYAML(toolScript) {
yaml.WriteString(line)
}
fmt.Fprintf(yaml, " EOFJS_%s\n", toolName)
fmt.Fprintf(yaml, " %s\n", jsDelimiter)
} else if toolConfig.Run != "" {
// Shell script tool
toolScript := generateSafeInputShellToolScript(toolConfig)
fmt.Fprintf(yaml, " cat > /opt/gh-aw/safe-inputs/%s.sh << 'EOFSH_%s'\n", toolName, toolName)
shDelimiter := GenerateHeredocDelimiter(fmt.Sprintf("SAFE_INPUTS_SH_%s", strings.ToUpper(toolName)))
fmt.Fprintf(yaml, " cat > /opt/gh-aw/safe-inputs/%s.sh << '%s'\n", toolName, shDelimiter)

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

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

These heredoc delimiters are derived from safe-inputs toolName, and tool names are allowed to contain '-' per schema; as written this produces delimiters with '-' which conflicts with the stated GH_AW_EOF convention and makes delimiter format less predictable. Either normalize toolName before passing it (e.g., convert '-'→'' using existing normalization helpers) or rely on GenerateHeredocDelimiter() to do that normalization centrally.

Copilot uses AI. Check for mistakes.
Comment on lines +510 to +623
func TestGenerateHeredocDelimiter(t *testing.T) {
tests := []struct {
name string
input string
expected string
}{
{
name: "simple name",
input: "PROMPT",
expected: "GH_AW_PROMPT_EOF",
},
{
name: "multi-word name with underscores",
input: "MCP_CONFIG",
expected: "GH_AW_MCP_CONFIG_EOF",
},
{
name: "tools json",
input: "TOOLS_JSON",
expected: "GH_AW_TOOLS_JSON_EOF",
},
{
name: "SRT config",
input: "SRT_CONFIG",
expected: "GH_AW_SRT_CONFIG_EOF",
},
{
name: "SRT wrapper",
input: "SRT_WRAPPER",
expected: "GH_AW_SRT_WRAPPER_EOF",
},
{
name: "file with hash",
input: "FILE_123ABC",
expected: "GH_AW_FILE_123ABC_EOF",
},
{
name: "safe inputs",
input: "SAFE_INPUTS",
expected: "GH_AW_SAFE_INPUTS_EOF",
},
{
name: "JS file suffix",
input: "EOFJS_TOOL_NAME",
expected: "GH_AW_EOFJS_TOOL_NAME_EOF",
},
{
name: "shell file suffix",
input: "EOFSH_TOOL_NAME",
expected: "GH_AW_EOFSH_TOOL_NAME_EOF",
},
{
name: "python file suffix",
input: "EOFPY_TOOL_NAME",
expected: "GH_AW_EOFPY_TOOL_NAME_EOF",
},
{
name: "go file suffix",
input: "EOFGO_TOOL_NAME",
expected: "GH_AW_EOFGO_TOOL_NAME_EOF",
},
{
name: "lowercase input gets uppercased",
input: "prompt",
expected: "GH_AW_PROMPT_EOF",
},
{
name: "mixed case input",
input: "Mcp_Config",
expected: "GH_AW_MCP_CONFIG_EOF",
},
{
name: "empty string returns default",
input: "",
expected: "GH_AW_EOF",
},
{
name: "single character",
input: "A",
expected: "GH_AW_A_EOF",
},
{
name: "numbers only",
input: "123",
expected: "GH_AW_123_EOF",
},
{
name: "alphanumeric with underscores",
input: "CONFIG_V2_TEST",
expected: "GH_AW_CONFIG_V2_TEST_EOF",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := GenerateHeredocDelimiter(tt.input)
assert.Equal(t, tt.expected, result, "GenerateHeredocDelimiter failed for test case: %s", tt.name)
})
}
}

func TestGenerateHeredocDelimiter_Usage(t *testing.T) {
// Test that the delimiter can be used in actual heredoc patterns
delimiter := GenerateHeredocDelimiter("TEST")
assert.Equal(t, "GH_AW_TEST_EOF", delimiter)

// Verify format is correct for heredoc usage
assert.True(t, strings.HasPrefix(delimiter, "GH_AW_"), "Delimiter should start with GH_AW_")
assert.True(t, strings.HasSuffix(delimiter, "_EOF"), "Delimiter should end with _EOF")

// Test that it contains only uppercase alphanumeric and underscores (valid for heredoc)
validPattern := regexp.MustCompile(`^[A-Z0-9_]+$`)
assert.True(t, validPattern.MatchString(delimiter), "Delimiter should contain only uppercase alphanumeric and underscores")
}

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

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

TestGenerateHeredocDelimiter currently doesn’t cover inputs containing dashes (which occur in safe-inputs tool names) even though other tests assert delimiters should match ^[A-Z0-9_]+$. Add a test case with a dashed name (e.g. "github-discussion-query") to lock in the intended normalization behavior once GenerateHeredocDelimiter is updated.

Copilot uses AI. Check for mistakes.
Comment on lines +128 to +132
"docker/build-push-action@v6": {
"repo": "docker/build-push-action",
"version": "v6",
"sha": "ee4ca427a2f43b6a16632044ca514c076267da23"
},

CopilotAIFeb 11, 2026

Copy link

Choose a reason for hiding this comment

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

This PR’s stated scope is heredoc delimiter standardization, but it also adds a new action pin for docker/build-push-action@v6. If this is intentional (e.g., needed because source workflows reference @v6), please call it out explicitly in the PR description/changelog since changing action pins affects supply-chain posture and may alter which exact version is used.

Copilot uses AI. Check for mistakes.
@github-actions

Copy link
Copy Markdown
Contributor

Smoke test (Codex)
PRs: Revert unintended action pin changes from documentation PR; docs: fix tokens page build errors - stable anchor IDs and proper image containers
GitHub MCP: ✅
Serena MCP: ✅
Playwright: ✅
File write+cat: ✅
Build: ✅
Overall: PASS

AI generated by Smoke Codex

@pelikhan
pelikhan merged commit 215a84a into mainFeb 11, 2026
@pelikhan
pelikhan deleted the copilot/add-go-helper-function branch February 11, 2026 12:57
@github-actions

Copy link
Copy Markdown
Contributor

Smoke Test Results

Status: ⚠️ PASS (8/9)

PRs:

Tests: ✅ GitHub MCP | ✅ Safe Inputs | ✅ Serena | ❌ Playwright | ✅ File Ops | ✅ Bash | ✅ Discussion | ✅ Build | ✅ Dispatch

cc @pelikhan@Copilot

AI generated by Smoke Copilot

@github-actions

Copy link
Copy Markdown
Contributor

📰 VERDICT: Smoke Copilot has concluded. All systems operational. This is a developing story. 🎤

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@pelikhan