wiki updates and file cleanup

This commit is contained in:
xcad
2026-04-22 17:19:02 +02:00
parent b54623f246
commit f64137a60f
13 changed files with 190 additions and 556 deletions
-26
View File
@@ -1,26 +0,0 @@
# https://editorconfig.org/
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 4
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.json]
indent_size = 2
[*.{js,jsx,ts,tsx}]
indent_size = 2
[*.md]
indent_size = unset
trim_trailing_whitespace = false
[*.py]
indent_size = 4
[{*.{yaml,yml},.yamllint}]
indent_size = 2
-252
View File
@@ -1,252 +0,0 @@
#!/usr/bin/env python3
"""Generate GitHub Wiki documentation for module variables.
This script auto-generates variable documentation in GitHub Wiki markdown format
for all registered modules, using the latest schema version for each.
"""
import sys
from pathlib import Path
# Add project root to path (script is in .github/scripts, so go up twice)
project_root = Path(__file__).parent.parent.parent
sys.path.insert(0, str(project_root))
# ruff: noqa: E402
# Import all modules to register them
import cli.modules.ansible
import cli.modules.compose
import cli.modules.helm
import cli.modules.kubernetes
import cli.modules.packer
import cli.modules.terraform # noqa: F401
from cli.core.registry import registry # Module import after path manipulation
def format_value(value):
"""Format value for markdown display."""
if value is None or value == "":
return "_none_"
if isinstance(value, bool):
return "" if value else ""
if isinstance(value, list):
return ", ".join(f"`{v}`" for v in value)
return f"`{value}`"
def generate_module_docs(module_name: str, output_dir: Path): # noqa: PLR0912, PLR0915
"""Generate wiki documentation for a single module."""
# Get module class from registry
module_classes = dict(registry.iter_module_classes())
if module_name not in module_classes:
sys.stderr.write(f"Warning: Module '{module_name}' not found, skipping\n")
return False
module_cls = module_classes[module_name]
schema_version = module_cls.schema_version
# Get the spec for the latest schema version
if hasattr(module_cls, "schemas") and schema_version in module_cls.schemas:
spec = module_cls.schemas[schema_version]
elif hasattr(module_cls, "spec"):
spec = module_cls.spec
else:
sys.stderr.write(f"Warning: No spec found for module '{module_name}', skipping\n")
return False
# Generate markdown content
lines = []
# Header
lines.append(f"# {module_name.title()} Variables")
lines.append("")
lines.append(f"**Module:** `{module_name}` ")
lines.append(f"**Schema Version:** `{schema_version}` ")
lines.append(f"**Description:** {module_cls.description}")
lines.append("")
lines.append("---")
lines.append("")
lines.append(
"This page documents all available variables for the "
+ f"{module_name} module. Variables are organized into sections "
+ "that can be enabled/disabled based on your configuration needs."
)
lines.append("")
# Table of contents
lines.append("## Table of Contents")
lines.append("")
for section_key, section_data in spec.items():
section_title = section_data.get("title", section_key)
anchor = section_title.lower().replace(" ", "-").replace("/", "")
lines.append(f"- [{section_title}](#{anchor})")
lines.append("")
lines.append("---")
lines.append("")
# Process each section
for section_key, section_data in spec.items():
section_title = section_data.get("title", section_key)
section_desc = section_data.get("description", "")
section_toggle = section_data.get("toggle", "")
section_needs = section_data.get("needs", "")
section_required = section_data.get("required", False)
section_vars = section_data.get("vars", {})
# Section header
lines.append(f"## {section_title}")
lines.append("")
# Section metadata
metadata = []
if section_required:
metadata.append("**Required:** Yes")
if section_toggle:
metadata.append(f"**Toggle Variable:** `{section_toggle}`")
if section_needs:
if isinstance(section_needs, list):
needs_str = ", ".join(f"`{n}`" for n in section_needs)
else:
needs_str = f"`{section_needs}`"
metadata.append(f"**Depends On:** {needs_str}")
if metadata:
lines.append(" \n".join(metadata))
lines.append("")
if section_desc:
lines.append(section_desc)
lines.append("")
# Skip sections with no variables
if not section_vars:
lines.append("_No variables defined in this section._")
lines.append("")
continue
# Variables table
lines.append("| Variable | Type | Default | Description |")
lines.append("|----------|------|---------|-------------|")
for var_name, var_data in section_vars.items():
var_type = var_data.get("type", "str")
var_default = format_value(var_data.get("default"))
var_description = var_data.get("description", "").replace("\n", " ")
# Add extra metadata to description
extra_parts = []
if var_data.get("sensitive"):
extra_parts.append("**Sensitive**")
if var_data.get("autogenerated"):
extra_parts.append("**Auto-generated**")
if "options" in var_data:
opts = ", ".join(f"`{o}`" for o in var_data["options"])
extra_parts.append(f"**Options:** {opts}")
if "needs" in var_data:
extra_parts.append(f"**Needs:** `{var_data['needs']}`")
if "extra" in var_data:
extra_parts.append(var_data["extra"])
if extra_parts:
var_description += "<br>" + "".join(extra_parts)
lines.append(f"| `{var_name}` | `{var_type}` | {var_default} | {var_description} |")
lines.append("")
lines.append("---")
lines.append("")
# Footer
lines.append("## Notes")
lines.append("")
lines.append("- **Required sections** must be configured")
lines.append("- **Toggle variables** enable/disable entire sections")
lines.append("- **Dependencies** (`needs`) control when sections/variables are available")
lines.append("- **Sensitive variables** are masked during prompts")
lines.append("- **Auto-generated variables** are populated automatically if not provided")
lines.append("")
lines.append("---")
lines.append("")
lines.append(f"_Last updated: Schema version {schema_version}_")
# Write to file
output_file = output_dir / f"Variables-{module_name.title()}.md"
output_file.write_text("\n".join(lines))
sys.stdout.write(f"Generated: {output_file.name}\n")
return True
def generate_variables_index(modules: list[str], output_dir: Path):
"""Generate index page for all variable documentation."""
lines = []
lines.append("# Variables Documentation")
lines.append("")
lines.append("This section contains auto-generated documentation for all " + "available variables in each module.")
lines.append("")
lines.append("## Available Modules")
lines.append("")
for module_name in sorted(modules):
lines.append(f"- [{module_name.title()}](Variables-{module_name.title()})")
lines.append("")
lines.append("---")
lines.append("")
lines.append("Each module page includes:")
lines.append("")
lines.append("- Schema version information")
lines.append("- Complete list of sections and variables")
lines.append("- Variable types, defaults, and descriptions")
lines.append("- Section dependencies and toggle configurations")
lines.append("")
lines.append("---")
lines.append("")
lines.append("_This documentation is auto-generated from module schemas._")
output_file = output_dir / "Variables.md"
output_file.write_text("\n".join(lines))
sys.stdout.write(f"Generated: {output_file.name}\n")
# Minimum required arguments
MIN_ARGS = 2
def main():
"""Main entry point."""
if len(sys.argv) < MIN_ARGS:
sys.stderr.write("Usage: python3 scripts/generate_wiki_docs.py <output_directory>\n")
sys.exit(1)
output_dir = Path(sys.argv[1])
output_dir.mkdir(parents=True, exist_ok=True)
sys.stdout.write(f"Generating wiki documentation in: {output_dir}\n")
sys.stdout.write("\n")
# Get all registered modules
module_classes = dict(registry.iter_module_classes())
successful_modules = []
for module_name in sorted(module_classes.keys()):
if generate_module_docs(module_name, output_dir):
successful_modules.append(module_name)
sys.stdout.write("\n")
# Generate index page
if successful_modules:
generate_variables_index(successful_modules, output_dir)
sys.stdout.write("\n")
sys.stdout.write(f"✓ Successfully generated documentation for {len(successful_modules)} module(s)\n")
else:
sys.stderr.write("Error: No documentation generated\n")
sys.exit(1)
if __name__ == "__main__":
main()
-98
View File
@@ -1,98 +0,0 @@
---
name: Docs - Update Wiki
'on':
push:
branches:
- main
paths:
- 'cli/core/schema/**/*.json' # JSON schema files
- '.wiki/**' # Static wiki pages
- '.github/scripts/generate_wiki_docs.py' # Wiki generation script
- '.github/workflows/docs-update-wiki.yaml' # This workflow
workflow_dispatch: # Allow manual trigger
permissions:
contents: write
jobs:
update-wiki:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v6
with:
fetch-depth: 1
- name: Checkout wiki repository
uses: actions/checkout@v6
with:
repository: ${{ github.repository }}.wiki
path: wiki
token: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Python
uses: actions/setup-python@v6
with:
python-version: '3.14'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
- name: Generate variable documentation
run: |
python3 .github/scripts/generate_wiki_docs.py wiki/
- name: Sync wiki pages from .wiki directory
run: |
# Copy all markdown files from .wiki/ to wiki/ (except Variables-*.md which are auto-generated)
if [ -d ".wiki" ]; then
echo "Syncing wiki pages from .wiki/ directory..."
for file in .wiki/*.md; do
filename=$(basename "$file")
# Skip auto-generated variable documentation files
if [[ ! "$filename" =~ ^Variables- ]]; then
echo " Copying $filename"
cp "$file" "wiki/$filename"
fi
done
else
echo "No .wiki directory found, skipping static wiki pages sync"
fi
- name: Check for changes
id: changes
working-directory: wiki
run: |
git add .
if git diff --staged --quiet; then
echo "has_changes=false" >> $GITHUB_OUTPUT
echo "No changes detected in wiki documentation"
else
echo "has_changes=true" >> $GITHUB_OUTPUT
echo "Changes detected in wiki documentation"
fi
- name: Commit and push changes
if: steps.changes.outputs.has_changes == 'true'
working-directory: wiki
run: |
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git commit -m "Auto-update wiki pages"
# Pull with rebase to handle any remote changes, then push
# GitHub wikis use master as default branch
git pull --rebase origin master
git push origin master
- name: Summary
run: |
if [ "${{ steps.changes.outputs.has_changes }}" == "true" ]; then
echo "Wiki variable documentation updated successfully"
echo "View at: https://github.com/${{ github.repository }}/wiki"
else
echo "No changes to wiki documentation"
fi
+22 -15
View File
@@ -4,7 +4,7 @@ Save time by setting default values for variables you use frequently. This page
## What are Default Variables?
**Default variables** are user-defined values that override module and template defaults. They allow you to:
**Default variables** are user-defined values that override template manifest values for a module. They allow you to:
- Avoid repetitive typing during template generation
- Standardize values across multiple templates
- Customize your environment once, use everywhere
@@ -13,13 +13,13 @@ Save time by setting default values for variables you use frequently. This page
Variables are resolved in this order (lowest to highest priority):
1. Module runtime defaults
2. Template defaults from `template.json`
3. **User config** (your saved defaults) ← This page
4. `--var-file`
5. CLI arguments (`--var`)
1. Template manifest values from `template.json`
2. **User config** (your saved defaults) ← This page
3. `--var-file`
4. CLI arguments (`--var`)
5. Interactive prompt answers
Your saved defaults override module and template defaults, but they can still be overridden at generation time.
Your saved defaults override template manifest values, but they can still be overridden at generation time.
## Managing Defaults
@@ -104,7 +104,7 @@ Response:
Removed default: container_timezone
```
The variable will now use module/template defaults again.
The variable will now use template manifest values again.
### Clear All Defaults
@@ -123,11 +123,13 @@ Cleared all defaults for compose
## Configuration Storage
Defaults are stored in:
Defaults are usually stored in:
```
~/.config/boilerplates/config.yaml
```
If a local `./config.yaml` exists in your current working directory, the CLI uses that file instead.
Example content:
```yaml
libraries:
@@ -153,13 +155,15 @@ defaults:
You can manually edit the config file:
```bash
# Edit configuration
# Edit the global configuration example
nano ~/.config/boilerplates/config.yaml
# Verify defaults
boilerplates compose defaults list
```
If you are using a local `./config.yaml`, edit that file instead.
## Common Use Cases
### Timezone Configuration
@@ -251,6 +255,8 @@ Defaults don't transfer between modules—they're module-specific.
## Backup and Restore
The examples below use the global config path. If the CLI is using a local `./config.yaml`, substitute that path instead.
### Backup Configuration
Save your configuration:
@@ -332,7 +338,7 @@ cat ~/.config/boilerplates/config.yaml
If config file is corrupted:
```bash
# Validate YAML syntax
# Validate global config YAML syntax
python3 -c "import yaml; yaml.safe_load(open('~/.config/boilerplates/config.yaml'))"
# Or remove and recreate
@@ -346,15 +352,16 @@ If wrong values appear:
```bash
# Check precedence
# 1. Module spec
# 2. Template spec
# 3. User defaults ← Check here
# 1. Template manifest values
# 2. User defaults ← Check here
# 3. --var-file
# 4. CLI --var
# 5. Interactive answers
# Verify your defaults
boilerplates compose defaults list
# Check template spec
# Check the loaded template state
boilerplates compose show <template-name>
```
+26 -8
View File
@@ -40,14 +40,28 @@ libraries:
## Local Storage
Git libraries are stored under:
Git libraries are stored under the active config directory's `libraries/` folder.
Global-config default:
```text
~/.config/boilerplates/libraries/
```
If the CLI is using a local `./config.yaml`, the library checkout location becomes `./libraries/`.
The configured `directory` is applied inside that checkout. For the official library the directory is `.`.
## Configuration Location
By default, Boilerplates uses:
```text
~/.config/boilerplates/config.yaml
```
If a local `./config.yaml` exists in your current working directory, the CLI uses that file instead.
## Discovery Rules
Boilerplates discovers templates by module directory, for example:
@@ -79,11 +93,21 @@ boilerplates repo update
Add a custom Git library:
```bash
boilerplates repo add my-templates https://github.com/user/templates \
boilerplates repo add my-templates \
--library-type git \
--url https://github.com/user/templates \
--directory . \
--branch main
```
Add a static library:
```bash
boilerplates repo add local \
--library-type static \
--path ~/my-templates
```
Remove a library:
```bash
@@ -127,12 +151,6 @@ Templates with `metadata.draft: true` are excluded from normal listings and look
## Config File
Library configuration lives in:
```text
~/.config/boilerplates/config.yaml
```
Example:
```yaml
+70 -64
View File
@@ -1,10 +1,8 @@
# Templates
Templates are the core unit of Boilerplates. A template is a directory with a `template.json` manifest and a `files/` directory containing the files to render.
Templates are the core unit of Boilerplates. A supported template is a directory with a `template.json` manifest and a `files/` directory containing every renderable output file.
## Template Structure
Every supported template looks like this:
## Required Layout
```text
my-template/
@@ -16,11 +14,13 @@ my-template/
└── app.yaml
```
Only `template.json` is a supported manifest format. Legacy `template.yaml` and `template.yml` manifests are not supported.
Rules:
- `template.json` is the only supported manifest format
- all rendered content must live under `files/`
- legacy `template.yaml`, `template.yml`, and top-level `.j2` layouts are incompatible with the current runtime
## Manifest Shape
## Top-Level Manifest Shape
Top-level fields:
- `slug`
- `kind`
- `metadata`
@@ -35,6 +35,8 @@ Example:
"metadata": {
"name": "My Template",
"description": "Short human description",
"author": "Your Name",
"date": "2026-04-22",
"tags": ["infra", "dev"],
"icon": {
"provider": "mdi",
@@ -48,7 +50,7 @@ Example:
"source_dep_version": "1.1.0",
"source_dep_digest": "sha256:abc123def456",
"upstream_ref": "release-2026-04-22",
"notes": "Tracks upstream container release used by this template snapshot"
"notes": "Tracks the tested upstream dependency snapshot"
}
},
"variables": [
@@ -68,24 +70,38 @@ Example:
}
```
## `slug` and Template IDs
`slug` is the canonical template ID exposed by the CLI.
Behavior:
- if `slug` is present, it wins over the directory name
- if `slug` ends with `-<kind>`, that suffix is normalized away for CLI use
- if `slug` is missing, the directory name is used
Example:
- directory: `portainer/`
- `kind`: `compose`
- `slug`: `portainer-compose`
- CLI ID: `portainer`
## Metadata
Common metadata fields:
- `name`
- `description`
- `author`
- `date`
- `tags`
- `icon`
- `draft`
- `author`
- `date`
- `guide`
- `version`
### Version Metadata
`metadata.version` is optional. If present, it must be an object.
`metadata.version` is optional, but when present it must be an object.
Supported version fields:
Supported fields:
- `name`
- `source_dep_name`
- `source_dep_version`
@@ -93,57 +109,34 @@ Supported version fields:
- `upstream_ref`
- `notes`
Important rules:
- the whole `version` object may be omitted
- any individual `version` field may be omitted
- the CLI uses `metadata.version.name` as the visible version label in list/show output
Important behavior:
- `metadata.version.name` is the user-facing version label shown in list/show output
- the rest of the version object is for upstream dependency tracking
- the full object may be omitted
- individual fields inside the object may also be omitted
This means these are all valid:
## Variable Declarations Are Mandatory
```json
{
"metadata": {
"name": "My Template"
}
}
```
Any variable used in files under `files/` must be declared in `template.json`.
```json
{
"metadata": {
"name": "My Template",
"version": {
"name": "v1.1"
}
}
}
```
If a file references an undeclared variable, the template fails validation and load/render operations surface a template error.
```json
{
"metadata": {
"name": "My Template",
"version": {
"source_dep_name": "ghcr.io/example/my-image",
"source_dep_version": "1.1.0"
}
}
}
```
Use the [Variables](Core-Concepts-Variables) page for the manifest structure.
## Files and Rendering
All files inside `files/` are part of the template output.
Everything under `files/` is part of the output tree.
Rendering rules:
- Boilerplates renders every file under `files/`
- files without template expressions pass through unchanged
- output paths currently match the relative file paths under `files/`
- template discovery ignores anything without `template.json`
Rendering behavior:
- Boilerplates walks every file under `files/`
- files are rendered with the custom delimiter set
- files without template expressions still pass through the render pipeline
- output paths currently mirror the relative paths inside `files/`
- rendered output is sanitized to normalize blank lines and trailing whitespace
## Delimiters
Templates use custom delimiters, not default Jinja syntax:
Templates use custom delimiters rather than default Jinja syntax:
- variables: `<< value >>`
- blocks: `<% if condition %>`
@@ -165,17 +158,21 @@ Legacy `{{ }}`, `{% %}`, and `{# #}` delimiters are rejected.
## Includes and Imports
Includes and imports are resolved relative to the template's `files/` directory.
Example:
Includes and imports resolve relative to the template's `files/` directory.
```jinja
<% include 'partials/header.yaml' %>
```
## Template Discovery
## Discovery Rules
Templates are discovered from configured libraries. A directory is considered a template only when it contains `template.json`.
Templates are discovered from configured libraries.
A directory is considered a valid template only when:
- `template.json` exists
- `files/` exists
In practice, Boilerplates discovers templates by module directory path such as `compose/<template>/` or `terraform/<template>/`.
Useful commands:
@@ -186,11 +183,11 @@ boilerplates compose show nginx
```
Draft templates:
- set `metadata.draft` to `true` to hide a template from normal discovery
- set `metadata.draft` to `true` to hide the template from normal discovery
## Generation
## Generation Workflow
Typical generation flow:
Typical workflow:
```bash
boilerplates compose show nginx
@@ -204,6 +201,7 @@ Useful flags:
- `--var` for direct CLI overrides
- `--no-interactive` for non-interactive generation
- `--dry-run` to preview generation without writing files
- `--show-files` to print rendered files during dry-run
## Validation
@@ -219,11 +217,19 @@ Validate all templates in a module:
boilerplates compose validate
```
Validation covers:
- manifest structure
- variable declaration coverage
- delimiter compatibility
- renderability
- optional semantic validators for module-specific output
## Best Practices
- keep manifests in `template.json`
- keep all generated content under `files/`
- keep every generated file under `files/`
- declare every variable that appears in rendered content
- use the custom delimiter set consistently
- hardcode tested upstream application versions in rendered files unless a variable is truly required
- hardcode tested upstream application versions in rendered files unless a variable is actually needed
- use `metadata.version.name` for the user-facing label
- use the remaining `metadata.version` fields to track upstream dependency context when useful
- use the remaining `metadata.version` fields for upstream snapshot context when useful
+62 -42
View File
@@ -1,10 +1,10 @@
# Variables
Variables define the configurable inputs available to a template. In the current runtime they live in `template.json` under `variables`, grouped into sections with `items`.
Variables are defined per template in `template.json` under the top-level `variables` array. There is no separate schema reference layer anymore, so the manifest is the source of truth.
## Variable Layout
## Runtime Shape
Example:
Each entry in `variables` is a group. Each group contains `items`.
```json
{
@@ -24,7 +24,7 @@ Example:
"name": "environment",
"type": "enum",
"title": "Environment",
"default": "prod",
"value": "stage",
"config": {
"options": ["prod", "stage", "dev"]
}
@@ -35,15 +35,16 @@ Example:
}
```
Each group requires:
Group fields:
- `name`
- `title`
- `description`
- `toggle`
- `needs`
- `items`
Each item requires:
Item fields:
- `name`
Common item fields:
- `type`
- `title`
- `description`
@@ -54,11 +55,13 @@ Common item fields:
- `extra`
- `config`
`title` is used as the prompt label. If `description` is omitted, the runtime falls back to `title`.
Runtime mapping notes:
- `title` is used as the prompt label
- `description` is used as the display/help text
- if `description` is omitted, the runtime falls back to `title`
## Variable Types
## Supported Types
Supported types:
- `str`
- `int`
- `float`
@@ -69,25 +72,37 @@ Supported types:
- `hostname`
- `secret`
### Secret Variables
Type notes:
- `bool` defaults to `false` when omitted
- other types default to empty unless a `default` or `value` is provided
- `secret` values are masked in prompts and display output
Use `type: "secret"` for values that should be masked in prompts and output.
## `default` vs `value`
Use `default` for the normal manifest default.
Use `value` when the template should pin the runtime value directly. If both are present, `value` wins.
Example:
```json
{
"name": "api_token",
"type": "secret",
"title": "API token"
"name": "environment",
"type": "enum",
"title": "Environment",
"default": "prod",
"value": "stage",
"config": {
"options": ["prod", "stage", "dev"]
}
}
```
## Config Object
Extra behavior is defined under `config`.
Additional behavior is configured through `config`.
Supported config fields:
Supported fields:
- `placeholder`
- `textarea`
- `unit`
@@ -143,7 +158,7 @@ Supported config fields:
}
```
### Autogenerated Secret Values
### Autogenerated Secrets
`config.autogenerated` is supported only for `secret` variables.
@@ -180,22 +195,12 @@ Base64 example:
}
```
## Default Values and Overrides
Rules:
- autogenerated secrets cannot define `default`
- base64 generation uses `bytes`, not `length`
- `autogenerated` on non-secret variables is rejected
Value precedence is:
1. module runtime defaults
2. template defaults from `template.json`
3. saved user defaults in `config.yaml`
4. `--var-file`
5. `--var`
Useful notes:
- `default` defines the standard value
- `value` lets a template pin a value more directly in the manifest
- autogenerated secrets cannot also define a default
## Dependencies
## Dependencies with `needs`
Both groups and items support `needs`.
@@ -207,14 +212,18 @@ Examples:
Semantics:
- semicolon means AND
- comma means OR within the same comparison
- `!=` means the current value must not match
- comma means OR within a single comparison
- `=` means the value must match
- `!=` means the value must not match
## Toggles
Behavior notes:
- group `needs` controls whether the group is considered available
- item `needs` controls whether the item is shown and validated
- disabled boolean items are reset to `false` unless they were explicitly set via CLI
Groups may define `toggle`, but the toggle variable must exist as a boolean item in that same group.
## Group Toggles
Example:
Groups may define `toggle`, but the referenced toggle variable must exist as a boolean item in that same group.
```json
{
@@ -237,14 +246,25 @@ Example:
}
```
If a referenced toggle variable is not present, the runtime drops the toggle behavior.
If the toggle variable is missing, the runtime ignores the toggle.
## Override Order
For a loaded template, values are applied in this order:
1. `default` / `value` from `template.json`
2. saved defaults from the active config file
3. `--var-file`
4. `--var`
5. interactive prompt answers
## Inspecting Variables
The fastest way to see the actual variables for a template is still:
Use `show` against the template you care about:
```bash
boilerplates compose show nginx
boilerplates terraform show cloudflare-dns-record
```
That reflects the template as the runtime sees it, including defaults, dependencies, and optional sections.
That view reflects the actual runtime state for that template, including defaults, dependencies, toggle state, and file structure.
-4
View File
@@ -20,10 +20,6 @@ The current runtime supports:
- [Libraries](Core-Concepts-Libraries) - official and custom libraries, discovery, priority, and config
- [Defaults](Core-Concepts-Defaults) - saved default values and precedence
## Variable Discovery
- [Variables](Variables) - how to inspect the variables a template actually exposes
## Additional Docs
- [Repository README](https://github.com/ChristianLempa/boilerplates/blob/main/README.md)
+6 -1
View File
@@ -283,11 +283,16 @@ Sync the default template library:
boilerplates repo update
```
This downloads all available templates to:
This syncs the configured Git library checkouts under the active config directory's `libraries/` folder.
Global-config default:
```
~/.config/boilerplates/libraries/
```
If the CLI is using a local `./config.yaml`, the sync location becomes `./libraries/`.
### Shell Completion (Optional)
Enable tab completion for your shell:
-35
View File
@@ -1,35 +0,0 @@
# Variables Reference
Boilerplates no longer publishes static schema-version variable reference pages.
The current runtime is template-driven:
- modules provide baseline variable behavior
- each template can override defaults and add template-specific variables
- the exact variable set depends on the template you are inspecting
## How to Inspect Variables
Use the CLI against the template itself:
```bash
boilerplates compose show nginx
boilerplates terraform show cloudflare-dns-record
boilerplates ansible show ubuntu-vm-core
```
This shows:
- template metadata
- rendered version label from `metadata.version.name` when present
- the template file tree
- the actual variable groups and items exposed by that template
## Recommended Workflow
1. List templates for a module.
2. Show the template you want to use.
3. Review defaults, dependencies, and optional sections.
4. Generate with `--output`, `--var-file`, and `--var` as needed.
## Why the Old Pages Were Removed
The older wiki pages were generated from schema-version snapshots and no longer matched the current `template.json` runtime. They were removed to avoid documenting variables that may not exist, may have changed shape, or may be template-specific.
-3
View File
@@ -11,6 +11,3 @@
- [Variables](Core-Concepts-Variables)
- [Libraries](Core-Concepts-Libraries)
- [Defaults](Core-Concepts-Defaults)
### Reference
- [Variables](Variables)
+4 -6
View File
@@ -6,8 +6,7 @@ Create reusable templates and turn them into configurable workloads for homelabs
Create reusable templates for infrastructure expertise like Docker, Kubernetes, Terraform, Ansible, Python, and more. Use the built-in *Jinja2-like* templating syntax with `<< >>` variables, `<% %>` blocks, and `<# #>` comments to keep configuration modular and conditional. Sync with Git in both directions or manage everything locally. Render templates, configure variables through a guided wizard, and wire up secrets. Copy them to remote servers and environments or any local directory.
*Don't want to start from scratch?*
> Explore 100+ template presets for homelabs and self-hosted infrastructure: https://github.com/ChristianLempa/boilerplates-library
✨ Explore 100+ template presets for homelabs and self-hosted infrastructure: https://github.com/ChristianLempa/boilerplates-library
## Boilerplates CLI
@@ -15,10 +14,9 @@ The Boilerplates CLI is the main interface for working with template libraries l
It combines template-defined variables and defaults, guided interactive prompts, CLI variable overrides, and git-backed template libraries into one workflow. In practice, that means you can keep reusable boilerplates in a repository and turn them into concrete, environment-specific configurations with a single command.
> **WARNING**
> Boilerplates `0.2.0` introduced the new template format. Legacy `template.yaml` / `template.yml` manifests and `.j2` template files are no longer supported.
>
> New templates must use `template.json`, keep renderable content under `files/`, and use the custom *Jinja2*-like delimiters `<< >>`, `<% %>`, and `<# #>` instead of default *Jinja2* syntax.
⚠️ Boilerplates `0.2.0` introduced the new template format. Legacy `template.yaml` / `template.yml` manifests and `.j2` template files are no longer supported.
️ New templates must use `template.json`, keep renderable content under `files/`, and use the custom *Jinja2*-like delimiters `<< >>`, `<% %>`, and `<# #>` instead of default *Jinja2* syntax.
### Installation
-2
View File
@@ -203,7 +203,6 @@ class TemplateMetadata:
library: str = "unknown"
library_type: str = "git"
draft: bool = False
guide: str = ""
icon: dict[str, Any] = field(default_factory=dict)
def __init__(
@@ -226,7 +225,6 @@ class TemplateMetadata:
self.library = library_name or "unknown"
self.library_type = library_type
self.draft = bool(metadata.get("draft", False))
self.guide = str(metadata.get("guide", "")).rstrip("\n")
self.icon = metadata.get("icon", {}) if isinstance(metadata.get("icon"), dict) else {}