From c86cdcf33527997e40f6f0256606e19bd7376c85 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Tue, 3 Mar 2026 20:28:15 -0800 Subject: [PATCH] Add Forgejo template variable expansion for automatic repo customization Replace hardcoded TODO markers with Forgejo template variables (${REPO_NAME}, ${REPO_OWNER}, etc.) so new repos created from this template are auto-customized. Use Forgejo Actions context variables in build.yaml for dynamic FORGE_URL. Hardcode forge.eblu.me as the Forgejo instance. Update CLAUDE.md and README.md to reflect reduced manual setup steps. Python class names kept as manual TODO (same as directory rename) since template variables in Python code positions aren't valid syntax for linters. Co-Authored-By: Claude Opus 4.6 --- .dagger/pyproject.toml | 3 +-- .dagger/src/project_template_ci/__init__.py | 4 ++-- .dagger/src/project_template_ci/main.py | 2 +- .forgejo/workflows/build.yaml | 9 +++----- .gitea/template | 9 ++++++++ CLAUDE.md | 13 ++++++------ README.md | 21 ++++++++----------- dagger.json | 3 +-- ...eature-forgejo-template-variables.infra.md | 1 + docs/index.md | 4 +--- docs/quartz.config.ts | 2 +- docs/quartz.layout.ts | 2 +- mise-tasks/docs-mikado | 5 ++--- mise-tasks/pr-comments | 7 +++---- prek.toml | 5 ++++- 15 files changed, 46 insertions(+), 44 deletions(-) create mode 100644 .gitea/template create mode 100644 docs/changelog.d/feature-forgejo-template-variables.infra.md diff --git a/.dagger/pyproject.toml b/.dagger/pyproject.toml index b42621c..2deb3ef 100644 --- a/.dagger/pyproject.toml +++ b/.dagger/pyproject.toml @@ -1,6 +1,5 @@ [project] -# TODO: Rename to match your project (also rename the src/ directory) -name = "project-template-ci" +name = "${REPO_NAME}-ci" version = "0.1.0" requires-python = ">=3.13" dependencies = ["dagger-io"] diff --git a/.dagger/src/project_template_ci/__init__.py b/.dagger/src/project_template_ci/__init__.py index 5ff5a10..35ae5cd 100644 --- a/.dagger/src/project_template_ci/__init__.py +++ b/.dagger/src/project_template_ci/__init__.py @@ -1,4 +1,4 @@ -# TODO: Update module docstring and class name to match your project -"""Project Template CI — Dagger build functions.""" +"""${REPO_NAME_TITLE} CI — Dagger build functions.""" +# TODO: Rename class to match your project (also rename the src/ directory) from .main import ProjectTemplateCi as ProjectTemplateCi diff --git a/.dagger/src/project_template_ci/main.py b/.dagger/src/project_template_ci/main.py index 46b8ccb..30bc50c 100644 --- a/.dagger/src/project_template_ci/main.py +++ b/.dagger/src/project_template_ci/main.py @@ -2,7 +2,7 @@ import dagger from dagger import dag, function, object_type -# TODO: Rename class to match your project (e.g. MyProjectCi) +# TODO: Rename class to match your project (also rename the src/ directory) @object_type class ProjectTemplateCi: @function diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index 381aa98..af9f8a8 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -42,8 +42,7 @@ jobs: SPECIFIC_VERSION="${{ inputs.specific_version }}" # Fetch latest release - # TODO: Update FORGE_URL to match your Forgejo instance and repo - FORGE_URL="https://forge.example.com/api/v1/repos/owner/repo" + FORGE_URL="${{ github.server_url }}/api/v1/repos/${{ github.repository }}" echo "Fetching latest release..." LATEST=$(curl -s "${FORGE_URL}/releases/latest" | jq -r '.tag_name // empty' || true) @@ -152,8 +151,7 @@ jobs: TARBALL="docs-${VERSION}.tar.gz" CHANGELOG_UPDATED="${{ steps.changelog.outputs.changelog_updated }}" - # TODO: Update FORGE_URL to match your Forgejo instance and repo - FORGE_URL="https://forge.example.com/api/v1/repos/owner/repo" + FORGE_URL="${{ github.server_url }}/api/v1/repos/${{ github.repository }}" echo "Creating release $VERSION..." @@ -221,9 +219,8 @@ jobs: exit 0 fi - # TODO: Update git identity to match your Forgejo instance git config user.name "Forgejo Actions" - git config user.email "actions@forge.example.com" + git config user.email "actions@forge.eblu.me" git add CHANGELOG.md docs/changelog.d/ diff --git a/.gitea/template b/.gitea/template new file mode 100644 index 0000000..7dd645b --- /dev/null +++ b/.gitea/template @@ -0,0 +1,9 @@ +CLAUDE.md +docs/index.md +dagger.json +.dagger/pyproject.toml +.dagger/src/**/*.py +docs/quartz.config.ts +docs/quartz.layout.ts +mise-tasks/pr-comments +mise-tasks/docs-mikado diff --git a/CLAUDE.md b/CLAUDE.md index 54dc58f..05f89ba 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -4,8 +4,7 @@ Guidance for Claude Code working in this repository. See also [[ai-assistance-gu ## Overview - -**PROJECT_NAME** — description goes here. +**${REPO_NAME}** — ${REPO_DESCRIPTION} **CRITICAL: Public repo — never commit secrets!** @@ -13,11 +12,13 @@ Guidance for Claude Code working in this repository. See also [[ai-assistance-gu ## First-Time Setup -This repository is a **project template**. All customization points are marked with `TODO` comments throughout the codebase. Before any other work, you should: +This repository is a **Forgejo template**. Most customization points are auto-resolved by Forgejo's template variable expansion when a new repo is created. The remaining manual steps are: -1. **Suggest resolving TODOs first.** Even if the user gives you a different task, check whether TODOs remain by searching for `TODO` across all files. If unresolved TODOs exist, inform the user that the template hasn't been fully customized yet and suggest resolving them first (the user may decline — that's fine, proceed with their request). -2. **To resolve TODOs:** search all files for `TODO`, update each value to match the new project, rename the `.dagger/src/project_template_ci/` directory, and verify nothing was missed. -3. **When all TODOs are resolved:** delete this "First-Time Setup" section entirely from `CLAUDE.md` — it is only needed once. +1. **Set `baseUrl`** in `docs/quartz.config.ts` — this is the hosted docs domain, not the repo URL +2. **Rename `.dagger/src/project_template_ci/`** directory to match your project, and update the class names inside +3. **Fill in project structure** in the `CLAUDE.md` Project Structure section +4. **Fill in license info** in `README.md` +5. **When all TODOs are resolved:** delete this "First-Time Setup" section entirely from `CLAUDE.md` — it is only needed once ## Rules diff --git a/README.md b/README.md index 5b3b2fb..ff7b9d1 100644 --- a/README.md +++ b/README.md @@ -13,20 +13,17 @@ A personal project template with opinionated infrastructure for documentation, C ## Forking This Template -The template contains `TODO` markers at every point that needs customization. To set up a new project: +This is a **Forgejo template repository**. When you create a new repo from this template, Forgejo automatically expands variables like `${REPO_NAME}` and `${REPO_OWNER}` in key files — handling most customization automatically. -1. Fork or copy this repository -2. Search for `TODO` across all files — each one marks a value you need to update: - - Project name and description (`CLAUDE.md`, `docs/index.md`) - - Forgejo/forge instance URLs (`build.yaml`, `mise-tasks/docs-mikado`, `mise-tasks/pr-comments`) - - Dagger module name and class (`dagger.json`, `.dagger/`) - - Quartz site title and URLs (`docs/quartz.config.ts`, `docs/quartz.layout.ts`) - - CI git identity (`.forgejo/workflows/build.yaml`) -3. Rename the `.dagger/src/project_template_ci/` directory to match your new Dagger module name -4. Remove the "First-Time Setup" section from `CLAUDE.md` once all TODOs are resolved -5. Delete this "Forking This Template" section from `README.md` and write your own project description +After creating your repo, the remaining manual steps are: -If you use Claude Code, it will prompt you to resolve these TODOs at the start of your first session. +1. Set `baseUrl` in `docs/quartz.config.ts` to your docs site domain +2. Rename `.dagger/src/project_template_ci/` directory and update class names to match your project +3. Fill in the project structure section in `CLAUDE.md` +4. Add license information to `README.md` +5. Remove the "First-Time Setup" section from `CLAUDE.md` and this section from `README.md` + +If you use Claude Code, it will prompt you to resolve remaining TODOs at the start of your first session. ## Getting Started diff --git a/dagger.json b/dagger.json index 9003632..96dc33d 100644 --- a/dagger.json +++ b/dagger.json @@ -1,6 +1,5 @@ { - "_comment": "TODO: Rename 'project-template-ci' to match your project", - "name": "project-template-ci", + "name": "${REPO_NAME}-ci", "engineVersion": "v0.19.11", "sdk": { "source": "python" diff --git a/docs/changelog.d/feature-forgejo-template-variables.infra.md b/docs/changelog.d/feature-forgejo-template-variables.infra.md new file mode 100644 index 0000000..6c20d1a --- /dev/null +++ b/docs/changelog.d/feature-forgejo-template-variables.infra.md @@ -0,0 +1 @@ +Add Forgejo template repository variable expansion — most TODO markers are now auto-resolved when creating a new repo from this template. diff --git a/docs/index.md b/docs/index.md index e536718..2fe332b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -7,9 +7,7 @@ tags: # Project Documentation - - -Welcome to the **PROJECT_NAME** documentation. +Welcome to the **${REPO_NAME}** documentation. ## Navigation diff --git a/docs/quartz.config.ts b/docs/quartz.config.ts index 047d796..43f1e86 100644 --- a/docs/quartz.config.ts +++ b/docs/quartz.config.ts @@ -7,7 +7,7 @@ import * as Plugin from "./quartz/plugins" */ const config: QuartzConfig = { configuration: { - pageTitle: "Project Docs", // TODO: Update to your project name + pageTitle: "${REPO_NAME_TITLE} Docs", pageTitleSuffix: "", enableSPA: true, enablePopovers: true, diff --git a/docs/quartz.layout.ts b/docs/quartz.layout.ts index 1573cb8..017cc98 100644 --- a/docs/quartz.layout.ts +++ b/docs/quartz.layout.ts @@ -13,7 +13,7 @@ export const sharedPageComponents: SharedLayout = { afterBody: [], footer: Component.Footer({ links: { - "Repository": "https://CHANGEME.example.com/owner/repo", // TODO: Update to your repo URL + "Repository": "${REPO_LINK}", }, }), } diff --git a/mise-tasks/docs-mikado b/mise-tasks/docs-mikado index 1061948..6113e6e 100755 --- a/mise-tasks/docs-mikado +++ b/mise-tasks/docs-mikado @@ -38,9 +38,8 @@ REPO_DIR = Path(__file__).parent.parent C2_COMMIT_RE = re.compile(r"^C2\(([^)]+)\):\s+(plan|impl|close|finalize)\s+(.+)$") -# TODO: Update to match your Forgejo instance and repo -FORGE_API = "https://forge.example.com/api/v1" -FORGE_REPO = "owner/repo" +FORGE_API = "https://forge.eblu.me/api/v1" +FORGE_REPO = "${REPO_OWNER}/${REPO_NAME}" def extract_frontmatter(file_path: Path) -> dict | None: diff --git a/mise-tasks/pr-comments b/mise-tasks/pr-comments index 0e80338..c06e17c 100755 --- a/mise-tasks/pr-comments +++ b/mise-tasks/pr-comments @@ -20,10 +20,9 @@ import httpx from rich.console import Console from rich.text import Text -# TODO: Update to match your Forgejo instance and repo -FORGE_API_BASE = "https://forge.example.com/api/v1" -REPO_OWNER = "owner" -REPO_NAME = "repo" +FORGE_API_BASE = "https://forge.eblu.me/api/v1" +REPO_OWNER = "${REPO_OWNER}" +REPO_NAME = "${REPO_NAME}" def get_reviews(client: httpx.Client, pr_number: int) -> list[dict]: diff --git a/prek.toml b/prek.toml index 5311d68..41532f3 100644 --- a/prek.toml +++ b/prek.toml @@ -63,7 +63,10 @@ hooks = [{ id = "shfmt", args = ["-i", "2", "-ci", "-bn"] }] [[repos]] repo = "https://github.com/ComPWA/taplo-pre-commit" rev = "v0.9.3" -hooks = [{ id = "taplo-format" }, { id = "taplo-lint" }] +hooks = [ + { id = "taplo-format" }, + { id = "taplo-lint", exclude = '\.dagger/pyproject\.toml$' }, +] # JSON formatting (prettier for consistent style) [[repos]]