Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions TODO.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -33,6 +33,21 @@ The site is built and gated in CI. It is on GitHub, and it is not yet serving it
- Add the weekly non-blocking external-link-check workflow, which is the one gate that cannot be blocking because it fails on other people's outages.
- Decommission WordPress.com only after **30 clean days**, and downgrade to free rather than deleting, which keeps the media reachable as a safety net and preserves the ability to re-export. Do not start sooner: the conversion fetched media over HTTP from the live site.

## Owed to the hub

The hub is owed a spec update for this repo's publishing type, tracked in [ProjectTemplate#456][hub-issue]. The measured deploy shape is reported there.

**Frame it as a variant of the existing registry-push leaf, not a new release surface.** A NuGet or PyPI leaf builds an artifact and pushes it to its own destination, contributing no `release-asset-*`. This repo does exactly that. Only two things differ, and neither changes the seam:

| Same as NuGet and PyPI | Unique here |
| --- | --- |
| A leaf builds, then pushes to its own destination | The build is Hugo rather than a language toolchain |
| No `release-asset-*` contributed | The transport is rsync over SSH to a host the project owns |
| Publish is dispatch-gated, never a merge | The destination is a filesystem, so the artifact carries its own version |
| Credentials come from a GitHub Environment | Two environments serve the same artifact, so a deploy must prove which one answered |

What the type genuinely needs is therefore small: a destination row in `Output Seam by Destination`, and one guarantee that a deploy is verified against the running host by release rather than by transport success. The release model, the branching model, and the never-publish-on-merge rule all hold unchanged.

## Open decisions

- `/robots.txt/` and `/osd.xml/` currently sit in `slugs.map` pointing at `/`. The first would be better pointing at the real `/robots.txt`.
Expand Down
2 changes: 1 addition & 1 deletion WORKFLOW.md
Original file line numberDiff line numberDiff line change
Expand Up@@ -150,7 +150,7 @@ The required behaviors, organized by domain. Each is a **MUST**, stated as input
### D2 - Input/State Validation at Entry

- **D2.1 Validate before expensive work.** Output: a dedicated entry job/step asserts each cross-input/derived-state invariant and fails fast before builds. Downstream jobs `needs:` it.
- **D2.2 Release branch matches version classification.** Input: a real (non-smoke) release build. Output: the gate fails loudly if the default branch carries a prerelease suffix **or** a non-default branch carries none. It strips `+buildmetadata` before testing for the prerelease `-` (only a core/prerelease `-` counts), and it is **skipped on smoke** (a detached PR head always versions as prerelease). *Prevents: a non-default leg published as stable; a build-metadata false-positive; the gate blocking every default-base promotion PR.*
- **D2.2 Release branch matches version classification.** Input: a real (non-smoke) release build. Output: the gate fails loudly if the default branch carries a prerelease suffix **or** a non-default branch carries none. It strips `+buildmetadata` before testing for the prerelease `-` (only a core/prerelease `-` counts), and on a smoke build the **check exits early while the job still reports success** (a detached PR head always versions as prerelease). Read that as the validation being skipped rather than the job, because a job-level `if:` would skip the job itself, and a dependent skips with it unless that dependent opts out with `if: always()` and reads the result explicitly, the way the PR aggregator does. `github-release` carries `validate-release` in `needs:` and does **not** opt out, so a job-level skip there would couple the release to smoke through a second path on top of the `if:` it already carries. *Prevents: a non-default leg published as stable; a build-metadata false-positive; the gate blocking every default-base promotion PR.*
- **D2.3 Publish only from main or develop.** Input: a dispatch publish. Output: a dispatch from any ref other than `main` or `develop` fails fast. *Prevents: cutting a release from an unintended branch.*
- **D2.4 Mutually-exclusive / paired inputs are validated.** Input: a workflow with either/or or must-pair inputs (e.g. the docker-readme task's `repositories` XOR `manifest`+`manifest-jq`). Output: a half-filled or conflicting combination fails fast. *Prevents: a silent fall-through.*

Expand Down