Quick Start¶
Repolish is nothing without a provider. This guide builds a minimal local
provider from scratch - one that scans your .github/workflows/ directory and
generates a WORKFLOWS.md summary table. The same pattern works for any
file-discovery task.
What you will build¶
my-project/
├── .github/
│ └── workflows/
│ ├── ci.yml
│ └── release.yml
├── local/
│ ├── repolish.py ← provider logic
│ └── repolish/
│ └── WORKFLOWS.md.jinja ← template
├── repolish.yaml
└── WORKFLOWS.md ← generated by repolish
1. Write the provider¶
Create local/repolish.py:
import yaml
from pathlib import Path
from pydantic import BaseModel
from repolish import BaseContext, Provider
class Workflow(BaseModel):
name: str
file: str
triggers: list[str]
class Ctx(BaseContext):
workflows: list[Workflow] = []
def _parse_triggers(on_val: object) -> list[str]:
if isinstance(on_val, str):
return [on_val]
if isinstance(on_val, list):
return [str(t) for t in on_val]
if isinstance(on_val, dict):
return list(on_val.keys())
return []
def _scan_workflows() -> list[Workflow]:
workflows = []
for yml_path in sorted(Path('.github/workflows').glob('*.yml')):
raw = yaml.safe_load(yml_path.read_text())
name = raw.get('name', yml_path.stem)
# PyYAML parses bare `on` as the boolean True
on_val = raw.get(True, raw.get('on', {}))
workflows.append(Workflow(name=name, file=yml_path.name, triggers=_parse_triggers(on_val)))
return workflows
class WorkflowSummaryProvider(Provider[Ctx, BaseModel]):
def create_context(self) -> Ctx:
return Ctx(workflows=_scan_workflows())
BaseContext gives the provider access to the built-in repolish namespace
(repo name, year, etc.). The Ctx model is the data contract between your
Python logic and your Jinja2 templates.
2. Write the template¶
Create local/repolish/WORKFLOWS.md.jinja:
# Workflows
<!-- Auto-generated by repolish - do not edit directly -->
| Workflow | File | Triggers |
| -------- | ---- | -------- |
{% for wf in workflows -%}
| {{ wf.name }} | `{{ wf.file }}` | `{{ wf.triggers | join('`, `') }}` |
{% endfor %}
Repolish strips the .jinja extension automatically, so this template renders
to WORKFLOWS.md.
3. Configure repolish¶
Create repolish.yaml at the project root:
provider_root points to the directory that contains repolish.py and the
repolish/ template folder. No install step is needed for a local provider.
4. Run it¶
Check what would be generated without writing anything:
Apply and write the file:
WORKFLOWS.md is now in your project:
# Workflows
<!-- Auto-generated by repolish - do not edit directly -->
| Workflow | File | Triggers |
| -------- | ------------- | ---------------------- |
| CI | `ci.yml` | `push`, `pull_request` |
| Release | `release.yml` | `push` |
Run repolish apply again whenever you add or rename a workflow file and the
table updates automatically.
Every marker and annotation the summary trees print is documented in the Summary Trees reference.
What's next¶
This example only scratches the surface. Providers can:
- supply multiple templates from the same context
- preserve hand-edited sections in the output with preprocessor directives
- accept inputs from other providers
- delete obsolete files as part of migration
For a complete walkthrough with multiple providers, a monorepo, and published packages, follow the Tutorial.
Other useful references:
- Configuration reference - all
repolish.yamlfields - Templates guide - file mappings and create-only files
- Context - how context values are sourced and overridden