Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions pkg/workflow/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ const (
// This includes environment variable values, if conditions, and other expression contexts
// See: https://docs.github.com/en/actions/learn-github-actions/usage-limits-billing-and-administration
MaxExpressionSize = 21000 // 21KB in bytes

// MaxPromptChunkSize is the maximum size for each chunk when splitting prompt text (20KB)
// This limit ensures each heredoc block stays under GitHub Actions step size limits (21KB)
MaxPromptChunkSize = 20000 // 20KB limit for each chunk

// MaxPromptChunks is the maximum number of chunks allowed when splitting prompt text
// This prevents excessive step generation for extremely large prompt texts
MaxPromptChunks = 5 // Maximum number of chunks
)

//go:embed schemas/github-workflow.json
Expand Down
65 changes: 60 additions & 5 deletions pkg/workflow/sh.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,67 @@ func WriteShellScriptToYAML(yaml *strings.Builder, script string, indent string)
}
}

// WritePromptTextToYAML writes prompt text to a YAML heredoc with proper indentation
// WritePromptTextToYAML writes prompt text to a YAML heredoc with proper indentation.
// It chunks the text into groups of lines of less than MaxPromptChunkSize characters, with a maximum of MaxPromptChunks chunks.
// Each chunk is written as a separate heredoc to avoid GitHub Actions step size limits (21KB).
func WritePromptTextToYAML(yaml *strings.Builder, text string, indent string) {
yaml.WriteString(indent + "cat >> $GITHUB_AW_PROMPT << 'EOF'\n")
textLines := strings.Split(text, "\n")
for _, line := range textLines {
fmt.Fprintf(yaml, "%s%s\n", indent, line)
chunks := chunkLines(textLines, indent, MaxPromptChunkSize, MaxPromptChunks)

// Write each chunk as a separate heredoc
for _, chunk := range chunks {
yaml.WriteString(indent + "cat >> $GITHUB_AW_PROMPT << 'EOF'\n")
for _, line := range chunk {
fmt.Fprintf(yaml, "%s%s\n", indent, line)
}
yaml.WriteString(indent + "EOF\n")
}
}

// chunkLines splits lines into chunks where each chunk's total size (including indent) is less than maxSize.
// Returns at most maxChunks chunks. If content exceeds the limit, it truncates at the last chunk.
func chunkLines(lines []string, indent string, maxSize int, maxChunks int) [][]string {
if len(lines) == 0 {
return [][]string{{}}
}

var chunks [][]string
var currentChunk []string
currentSize := 0

for _, line := range lines {
// Calculate size including indent and newline
lineSize := len(indent) + len(line) + 1

// If adding this line would exceed the limit, start a new chunk
if currentSize+lineSize > maxSize && len(currentChunk) > 0 {
// Check if we've reached the maximum number of chunks
if len(chunks) >= maxChunks-1 {
// We're at the last allowed chunk, so add remaining lines to current chunk
currentChunk = append(currentChunk, line)
currentSize += lineSize
continue
}

// Start a new chunk
chunks = append(chunks, currentChunk)
currentChunk = []string{line}
currentSize = lineSize
} else {
currentChunk = append(currentChunk, line)
currentSize += lineSize
}
}

// Add the last chunk if there's content
if len(currentChunk) > 0 {
chunks = append(chunks, currentChunk)
}
yaml.WriteString(indent + "EOF\n")

// If we still have no chunks, return an empty chunk
if len(chunks) == 0 {
return [][]string{{}}
}

return chunks
}
Loading
Loading