Documentation
¶
Index ¶
- Constants
- func ExpandMatrix(matrix map[string]any, answers map[string]interface{}, render AxisRenderer, ...) ([]map[string]string, error)
- type AxisRenderer
- type File
- type FileSkippedError
- type Processor
- func (p *Processor) ContainsUnprocessedTemplates(content string) bool
- func (p *Processor) ContainsUnprocessedTemplatesWithDelimiters(content string, delimiters []string) bool
- func (p *Processor) Merge(base, ours, theirs, fileName string) (*merge.MergeResult, error)
- func (p *Processor) ProcessFile(file File, targetPath string, force, update bool, scaffoldConfig interface{}, ...) error
- func (p *Processor) ProcessTemplate(content string, targetPath string, scaffoldConfig interface{}, ...) (string, error)
- func (p *Processor) ProcessTemplateWithDelimiters(content string, targetPath string, scaffoldConfig interface{}, ...) (string, error)
- func (p *Processor) RenderMatrixAxisExpression(expr string, answers map[string]interface{}, delimiters []string) ([]string, error)
- func (p *Processor) SetConflictStrategy(strategy merge.ConflictStrategy)
- func (p *Processor) SetDryRun(dryRun bool)
- func (p *Processor) SetMaxChanges(thresholdPercent int)
- func (p *Processor) SetMergeDriver(driver merge.Driver)
- func (p *Processor) SetupGitStorage(targetPath string, baseRef string) error
- func (p *Processor) ShouldSkipFile(renderedPath string) bool
- func (p *Processor) ValidateNoUnprocessedTemplates(content string) error
- func (p *Processor) ValidateNoUnprocessedTemplatesWithDelimiters(content string, delimiters []string) error
Constants ¶
const MatrixKey = "Matrix"
MatrixKey is the reserved answers key one resolved matrix combination travels under, from ExpandMatrix's result being stashed in the per-combination values map (see pkg/generator/ui) through to ProcessTemplateWithDelimiters, which hoists it onto the template root as "matrix" -- so a template writes .matrix.<axis> directly, matching the namespace the workflow matrix step's own {{ .matrix.<axis> }} uses.
Variables ¶
This section is empty.
Functions ¶
func ExpandMatrix ¶
func ExpandMatrix(matrix map[string]any, answers map[string]interface{}, render AxisRenderer, delimiters []string) ([]map[string]string, error)
ExpandMatrix resolves a FileSpec's Matrix axes against answers and returns their full Cartesian product as one row (map[axis]value) per combination, expanded in a sorted, deterministic order per axis -- the same behavior pkg/workflow's own matrix step expansion has, so regenerating the same answers produces the same file set, in the same order, every time. Delimiters is the active scaffold's left/right template delimiter pair (see defaultAxisDelimiters for what an empty/nil value defaults to).
Types ¶
type AxisRenderer ¶
type AxisRenderer func(expr string, answers map[string]interface{}, delimiters []string) ([]string, error)
AxisRenderer renders a Go-template matrix-axis expression (e.g. "{{ collectKeys answers.environments }}") against answers into its resolved list of string values, honoring the scaffold's own spec.delimiters override. A nil renderer disables template-expression axes, keeping ExpandMatrix's core algorithm free of any templating dependency -- see Processor.RenderMatrixAxisExpression in funcs.go for the real implementation.
type File ¶
type File struct {
Path string // Path to the file, may contain template syntax for dynamic naming
Content string // File content, processed as template if IsTemplate is true
IsTemplate bool // Whether to process Content as a Go template
Permissions os.FileMode // Unix file permissions to apply when creating the file
}
File represents a file to be processed by the templating engine. It contains the file path (which can itself be a template), the content, whether the content should be processed as a template, and the file permissions.
type FileSkippedError ¶
type FileSkippedError struct {
Path string // Original file path from the template
RenderedPath string // Rendered path after template processing
}
FileSkippedError represents when a file is intentionally skipped during processing. Files may be skipped when their rendered path contains empty segments, special values like "false" or "<no value>", or other indicators that the file should not be created.
func (*FileSkippedError) Error ¶
func (e *FileSkippedError) Error() string
Error returns a formatted error message indicating the file was skipped.
type Processor ¶
type Processor struct {
DryRun bool // When true, compute rendering/merge but skip writing to disk
// contains filtered or unexported fields
}
Processor handles template processing for scaffold and init commands. It provides template rendering with Gomplate and Sprig functions, file path templating, and intelligent file merging capabilities.
func NewProcessor ¶
func NewProcessor() *Processor
NewProcessor creates a new template processor with default settings. The processor is initialized with a 50% threshold for 3-way merges, meaning merges will be rejected if more than 50% of lines would change.
func (*Processor) ContainsUnprocessedTemplates ¶
ContainsUnprocessedTemplates checks if the given content contains unprocessed template syntax.
func (*Processor) ContainsUnprocessedTemplatesWithDelimiters ¶
func (p *Processor) ContainsUnprocessedTemplatesWithDelimiters(content string, delimiters []string) bool
ContainsUnprocessedTemplatesWithDelimiters checks if the given content contains unprocessed template syntax with custom delimiters.
func (*Processor) Merge ¶
func (p *Processor) Merge(base, ours, theirs, fileName string) (*merge.MergeResult, error)
Merge performs a 3-way merge using the internal merger. Parameters:
- base: The original template content (before any processing)
- ours: The user's current version (what exists on disk)
- theirs: The new template content (after processing)
- fileName: The file name for merge strategy detection
func (*Processor) ProcessFile ¶
func (p *Processor) ProcessFile(file File, targetPath string, force, update bool, scaffoldConfig interface{}, userValues map[string]interface{}) error
ProcessFile processes a file with templating support, handling path rendering, skip logic, and merge/overwrite behavior based on flags.
The method performs the following steps:
- Renders the file path as a template (supports dynamic file naming)
- Checks if the file should be skipped based on the rendered path
- Creates necessary directories
- Handles existing files based on force/update flags: - force: overwrites existing files - update: performs a 3-way merge with existing content - neither: returns an error if file exists
- Processes file content as a template if IsTemplate is true
- Writes the final content to disk with specified permissions
Returns FileSkippedError if the file is intentionally skipped (not considered an error).
func (*Processor) ProcessTemplate ¶
func (p *Processor) ProcessTemplate(content string, targetPath string, scaffoldConfig interface{}, userValues map[string]interface{}) (string, error)
ProcessTemplate processes Go templates in file content.
func (*Processor) ProcessTemplateWithDelimiters ¶
func (p *Processor) ProcessTemplateWithDelimiters(content string, targetPath string, scaffoldConfig interface{}, userValues map[string]interface{}, delimiters []string) (string, error)
ProcessTemplateWithDelimiters processes Go templates in file content with custom delimiters.
func (*Processor) RenderMatrixAxisExpression ¶
func (p *Processor) RenderMatrixAxisExpression(expr string, answers map[string]interface{}, delimiters []string) ([]string, error)
RenderMatrixAxisExpression renders a Go-template matrix-axis expression (e.g. "{{ collectKeys answers.environments }}") against answers and returns its resolved list of string values. Satisfies the AxisRenderer type ExpandMatrix accepts, so an axis expression gets the same FuncMap and delimiters override scaffold templates already use.
Answers is exposed as a zero-arg function rather than a data field: Go's template grammar only chains ".field" off "." or a "$var", never off a bare identifier -- but it does chain off that identifier's call result, which is what lets "answers.environments" read as "call answers(), then select .environments".
Go's text/template can only render text, not the typed []string a function like collectKeys returns, so the pipeline gets "| toJson" appended internally and the result is decoded with json.Unmarshal -- transparent to scaffold.yaml authors, who never write toJson themselves.
func (*Processor) SetConflictStrategy ¶
func (p *Processor) SetConflictStrategy(strategy merge.ConflictStrategy)
SetConflictStrategy sets how a real ours/theirs divergence is resolved during a 3-way merge. Note: SetMaxChanges replaces p.merger wholesale, so call SetConflictStrategy after SetMaxChanges if both are used, or the strategy set here would be discarded.
func (*Processor) SetDryRun ¶
SetDryRun toggles dry-run mode. When enabled, ProcessFile still renders templates, loads the git merge base, performs the 3-way merge, and runs conflict/threshold checks — every step that can fail — but skips the final write to disk, so a dry-run preview reports real conflicts instead of only listing file paths.
func (*Processor) SetMaxChanges ¶
SetMaxChanges sets the maximum percentage of changes allowed for 3-way merge operations. The thresholdPercent parameter controls how aggressive the merge behavior is: a lower value (e.g., 30) is more conservative, while a higher value (e.g., 80) allows more extensive changes during merges.
func (*Processor) SetMergeDriver ¶
SetMergeDriver sets which merger handles every file during a 3-way merge.
func (*Processor) SetupGitStorage ¶
SetupGitStorage initializes git-based storage for 3-way merges. The targetPath is used to find the git repository and resolve relative file paths. The baseRef specifies which git reference to use as the base for merges (e.g., "main", "v1.0.0").
Returns an error if:
- targetPath is not in a git repository
- baseRef cannot be resolved
func (*Processor) ShouldSkipFile ¶
ShouldSkipFile determines if a file should be skipped based on its rendered path.
Files are skipped in the following cases:
- Empty path or special values: "", "false", "null", "<no value>"
- Paths with empty segments: "foo//bar", "/foo", "foo/"
- Paths that would create invalid filesystem entries
This is useful for conditional file generation where template variables may evaluate to empty or false values, indicating the file should not be created.
func (*Processor) ValidateNoUnprocessedTemplates ¶
ValidateNoUnprocessedTemplates validates that the processed content doesn't contain unprocessed template syntax.
func (*Processor) ValidateNoUnprocessedTemplatesWithDelimiters ¶
func (p *Processor) ValidateNoUnprocessedTemplatesWithDelimiters(content string, delimiters []string) error
ValidateNoUnprocessedTemplatesWithDelimiters validates that the processed content doesn't contain unprocessed template syntax with custom delimiters.