Template Engine
Relevant source files
The following files were used as context for generating this wiki page:
The Template Engine is the core component responsible for generating GitHub Actions workflow files from canonical templates. It processes managed workflows by identifying specialized metadata, injecting user-defined parameters into Jinja2-style templates via the Tera library, and performing post-processing to ensure valid YAML output and version consistency.
This system allows organizations to define centralized CI/CD logic while allowing individual repositories to provide specific configurations such as toolchain versions, feature flags, or environment variables.
Sources: src/template/render.rs:8-12, README.md:16-24
Core Architecture
The engine functions through three primary stages: frontmatter parsing, template rendering, and version preservation. The TemplateRenderer acts as the coordinator for these operations.
Data Flow Overview
This diagram illustrates the sequence from reading a local or remote workflow file to producing the final rendered content ready for synchronization.
Sources: src/template/render.rs:60-67, src/template/frontmatter.rs:25-30
Frontmatter Parsing
Workflows opt-in to management through a comment block known as frontmatter. The parser looks for specific markers: # @orcastrate and # @end-orcastrate.
- Markers: The parser scans the file for
MARKER_STARTandMARKER_END. - Extraction: It strips the comment prefixes (
#) to isolate a YAML block containing thetemplateidentifier and aparamsmap. - Result: The process returns a
ParsedWorkflowstruct containing the configuration and the original metadata block to be prepended to the final output.
Sources: src/template/frontmatter.rs:7-23, src/template/frontmatter.rs:32-47
Frontmatter Structure
| Field | Type | Description |
|---|---|---|
template | String | The filename (without .yml) of the template in the orchestrator repo. |
params | HashMap | Key-value pairs injected into the Tera context. |
Sources: src/template/frontmatter.rs:11-15
Template Rendering via Tera
The engine uses the Tera library for rendering. Templates are stored as .yml files in a configured directory (defaulting to templates/).
- Initialization:
TemplateRendererloads all.ymlfiles from the target directory into the Tera registry using a glob pattern. - Context Creation: Parameters from the frontmatter are converted from
serde_norway::Valuetoserde_json::Valueto be compatible with Tera's context. - Rendering: Tera processes the template, resolving variables (e.g.,
{{ toolchain }}) and control structures (e.g.,{% if features %}). - Validation: The engine attempts to parse the final string back into a YAML structure (
serde_norway::Value) to ensure the rendering did not produce malformed syntax.
Sources: src/template/render.rs:13-25, src/template/render.rs:41-55, src/template/render.rs:71-77
Action Version Preservation
By default, Orcastrate preserves existing GitHub Action versions (tags or SHAs) in the target workflow to avoid overwriting updates managed by tools like Renovate.
- Detection: The system scans the current workflow for
uses:lines and maps them to specific jobs and steps. - Matching: If
ignore_action_versionsis enabled, the renderer replaces the template's action versions with the versions currently found in the repository's file. - Layout Requirements: This feature requires single-line, block-style
uses:fields. If the layout is ambiguous or complex (e.g., multi-line strings), the preservation fails to prevent accidental corruption.
Template Example (Rust CI)
Templates use standard Jinja2 syntax. The following snippet demonstrates how a template handles optional parameters like features.
# templates/rust-ci.yml
name: CI
jobs:
check:
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@{{ toolchain | default(value="stable") }}
- run: cargo check --all-features
{% if features %}
feature-check:
strategy:
matrix:
feature: {{ features }}
steps:
- run: cargo check --features ${{ "{{ matrix.feature }}" }}
{% endif %}
Sources: templates/rust-ci.yml:16-20, templates/rust-ci.yml:51-65
Summary
The Template Engine provides a robust mechanism for centralizing workflow management. By combining the flexibility of the Tera engine with a strict opt-in frontmatter system and automated version preservation, it ensures that organization-wide standards can be enforced without breaking repository-specific versioning or local overrides.
Sources: src/sync.rs:296-310, AGENTS.md:25-30