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.
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