-
Notifications
You must be signed in to change notification settings - Fork 2
Description
Overview (TL;DR)
Upgrading templates in most SSGs is manual and brittle. Blake should make it safe, predictable, and boring to stay current: no DSLs, no arcane scripts. Template authors ship small, declarative "hops" (A→B). The CLI finds your current version, walks the hops sequentially to the target version, applies simple text/file operations, and creates a branch and generates an upgrade report. If there’s no supported upgrade, the CLI tells you so gracefully.
Why this sets Blake apart: users can actually upgrade without fear, and template authors can evolve templates confidently.
Principles
- No DSLs or scripting: A small, fixed set of declarative operations
- Work with existing tools: Use the project’s existing
.csprojfor template identity (i.e. nolockfiles or other bespoke solutions) - Safety first: Branch by default, dry-run support, stash user-diverged files instead of overwriting.
- Idempotent where possible: Re-running an upgrade shouldn’t duplicate changes.
High-level idea
-
Template metadata lives in the site’s
.csprojwhen a site is created:BlakeTemplate.Id(e.g.,blake/docs@github:owner/repo)BlakeTemplate.Version(semantic version)BlakeTemplate.Commit(optional, for traceability)
-
Hop files live in the template repo under
.blakeupgrade/and describe a single version step{from}→{to}. -
Operations supported in hop files (keep it tiny but useful):
addText(anchor-based insert, before/after/start/end)replaceText(string or regex match replacement)addFile(copy in if missing)replaceFile(whole-file replace, with guard hash and conflict strategy)
CLI behavior
blake upgrade [--to <version>] [--dry-run] [--no-branch]
- Detect current template ID/version from
.csproj. - Discover latest (or requested) target version in the template repo.
- Build a sequential path of hops (e.g.,
0.4→0.5,0.5→0.6,0.6→0.7). - Create a branch (e.g.,
blake-upgrade-v0.7.0) unless--no-branch. - Apply ops hop-by-hop. On conflicts, stash user files and continue.
- Emit a human-readable report in
.blake/upgrade_reports/….
When no upgrade path exists
-
If hop files for the required path are missing, show:
- clear message: “No supported upgrade path from vX to vY for template Z”
- suggest: check template repo or upgrade manually
- non-error exit code (unless
--strict), so it fails gracefully
Dry-run
- Print the plan and a per-op preview diff where possible. No files changed.
Template metadata (in .csproj)
Authors of site templates ensure sites record template identity on creation:
<PropertyGroup>
<BlakeTemplate_Id>github:owner/repo</BlakeTemplate_Id>
<BlakeTemplate_Version>0.4.0</BlakeTemplate_Version>
<BlakeTemplate_Commit>1a2b3c4</BlakeTemplate_Commit>
</PropertyGroup>We deliberately don’t introduce a lock file; we stay in the ecosystem’s existing project file.
Hop file shape (example)
/.blakeupgrade/0.4.0→0.5.0.json
{
"from": "0.4.0",
"to": "0.5.0",
"ops": [
{
"op": "addText",
"file": "src/_Imports.razor",
"anchor": "using Markdig;",
"position": "after",
"text": "using Blake.Docs;",
"ensureOnce": true
},
{
"op": "replaceText",
"file": "tailwind.config.cjs",
"match": "content: \\[.*?\\]",
"regex": true,
"with": "content: [\"**/*.razor\", \"**/*.md\"]",
"fallback": "skip"
},
{
"op": "replaceFile",
"fromTemplate": "files/_Layout.razor",
"to": "Pages/_Layout.razor",
"guards": {
"expectedBaseVersionHash": "sha256:abc123…",
"onMismatch": "stash"
}
}
]
}Notes
ensureOnceavoids duplicate inserts across re-runs.fallbackcan beskiporerrorif a regex doesn’t match.expectedBaseVersionHashdetects divergence from the old template file and triggers stashing.
Safety defaults
- Branch-first: create a working branch by default.
- Stash on mismatch: for
replaceFile, move user-diverged files to.blake/upgrade_stash/...and report. - No deletes: hop files never remove user files; authors can document removals as manual steps.
- Fail-fast with context: stop on hard errors; show how to resume.
Future enhancements (optional, not required for MVP)
- GitHub Action that auto-generates hop files on template release (diff previous tag → current tag) and opens a PR.
- Structured ops (opt-in): JSON Patch for configs, XML node setters for
.csproj. - Interactive mode: prompt per op when ambiguity is detected.
MVP scope & steps
- Define and publish the JSON schema for hop files (docs, examples).
- Build the op engine in the Build Tools (parser, validator, executor, report).
- Expose the upgrade command in the CLI
- Read template identity from
.csproj; resolve hops and apply sequentially. - Implement
--dry-run, branch creation, stash and report. - Document authoring guidance for template maintainers.
Out of scope (for now)
- Automated file deletions or mass renames.
- Arbitrary shell/script execution from hop files.
- Handling binary merges.
Success criteria
-
A site created from
template Z v0.4.0can runblake upgrade --to 0.7.0and:- ends with updated files matching template intent;
- preserves (or stashes) user changes safely;
- produces a clear, human‑readable report;
- exits non‑fatally with guidance if no hop path exists.