Skip to content

Commit 2abe4e5

Browse files
authored
feat: sync static-site docs verbatim, and allow syncing a ref by hand (#401)
## Summary Stacked on #400. Three changes to the static-site sync. - **Pages land verbatim.** The `dfx` translation and the brand normalizations are gone. Link mapping, the `source_repo` / `source_ref` frontmatter and the do-not-edit marker stay. - **Banned content stops the sync** (em dash, en-dash separator, `dfx`), naming the page, for upstream to fix. Softer house style is reported only. - **The workflow takes an optional `ref`** (sha, tag or branch) to sync a docs fix that upstream has shipped but not released. Dispatching the pinned release is a no-op; a ref behind the pin runs but warns that the pin moves backwards. - **A release that changes no page opens no PR**, unless the pin is a commit, where moving it onto a tag is the point. - `.agents/upstream-tracking.md` updated to match. Verified at `59641fc`: output byte-identical to the eight upstream files apart from the marker, two provenance fields and three link rewrites; `validate` and `build` pass. The sync itself is not included. Merge this, then dispatch with `ref=59641fc`.
1 parent 2ba8af0 commit 2abe4e5

4 files changed

Lines changed: 187 additions & 92 deletions

File tree

‎.agents/upstream-tracking.md‎

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -253,17 +253,29 @@ markdown links, which is why there is no submodule to hold the pin.
253253

254254
### How the pin moves
255255

256-
The workflow runs weekly, resolves the latest release tag, and opens a bump PR
257-
for every release the pin does not already contain. Two shapes come out of it:
256+
The workflow runs weekly and resolves the latest release tag. What comes out of
257+
it depends on what the release carries:
258258

259-
- **Pages changed.** The usual case: review the diff.
260-
- **Nothing under `docs/` changed.** The pages are byte-identical and the only
261-
diff is `source_ref` on each of them, but the PR still opens, because that is
262-
what moves the pin off a commit and onto a release tag. Skipping these would
259+
- **Pages changed.** A PR to review the diff. The usual case.
260+
- **Nothing under `docs/` changed, and the pin is a commit.** A PR whose only
261+
diff is the pin and the `source_ref` each page records. It opens because that
262+
is what moves the pin off a commit and onto a release tag; skipping it would
263263
strand a temporary commit pin for good.
264-
265-
The PR body says which of the two it is. The recipe version readers type is a
266-
separate axis, covered by the `static-site` entry under `watched`.
264+
- **Nothing under `docs/` changed, and the pin is a tag.** Nothing. A PR would
265+
carry an empty page diff for someone to review and merge. The pin then lags
266+
the latest release and stays accurate, since it records the ref this copy came
267+
from and the copy still matches it, and the release is not missed, because the
268+
recipe that deploys this canister releases in lockstep and is tracked under
269+
`watched`.
270+
271+
The PR body says which of the first two it is.
272+
273+
To sync a ref rather than a release, dispatch the workflow with `ref`: a sha,
274+
tag, or branch. That is for a docs fix that has shipped upstream but is not in a
275+
release, and it leaves the pin on a commit until the next release moves it onto
276+
a tag. The release checks do not apply to a dispatched ref, so it can also move
277+
the pin backwards, which a rollback wants and a mistyped sha does not: the run
278+
says so and the PR body repeats it.
267279

268280
To sync by hand, or to trial a ref before pinning it:
269281

‎.github/workflows/sync-static-site.yml‎

Lines changed: 109 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,14 @@ on:
44
schedule:
55
- cron: '0 9 * * 3' # Weekly on Wednesday
66
workflow_dispatch:
7+
inputs:
8+
ref:
9+
description: >-
10+
Ref to sync, for a docs fix that has shipped upstream but not been
11+
released. Any commit-ish the clone can resolve. Leave empty to sync
12+
the latest release, which is what the weekly run does.
13+
required: false
14+
type: string
715

816
jobs:
917
sync:
@@ -31,25 +39,70 @@ jobs:
3139
id: check
3240
env:
3341
GH_TOKEN: ${{ steps.app-token.outputs.token }}
42+
# A dispatch input reaches the shell as data, never as script.
43+
INPUT_REF: ${{ inputs.ref }}
3444
run: |
3545
PIN=$(node -p "require('./.sources/upstream.json').synced.find(e => e.repo === 'dfinity/certified-assets').pinned")
3646
echo "pin=$PIN" >> $GITHUB_OUTPUT
3747
38-
# Stable releases only, the same pattern the upstream.json watcher uses.
39-
# `^v[0-9]` would accept v0.4.0-rc.1 and publish docs for a prerelease.
40-
TAG=$(git -C /tmp/certified-assets tag --sort=-version:refname \
41-
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
42-
echo "Pinned: $PIN. Latest release: $TAG."
43-
echo "tag=$TAG" >> $GITHUB_OUTPUT
48+
if [ -n "$INPUT_REF" ]; then
49+
# A ref given by hand is the maintainer's call, so the release
50+
# checks below do not apply: the reason to pass one is a docs fix
51+
# that is not in a release yet.
52+
#
53+
# Tried as given and then under `origin/`, because a clone creates a
54+
# local branch only for the default branch and leaves every other
55+
# one reachable as `origin/<branch>` alone. A sha and a tag resolve
56+
# on the first attempt.
57+
REF_COMMIT=$(git -C /tmp/certified-assets rev-parse --verify --quiet "${INPUT_REF}^{commit}" \
58+
|| git -C /tmp/certified-assets rev-parse --verify --quiet "origin/${INPUT_REF}^{commit}") || {
59+
echo "::error::Cannot resolve ref '$INPUT_REF' in dfinity/certified-assets."
60+
exit 1
61+
}
62+
TAG=$(git -C /tmp/certified-assets rev-parse --short "$REF_COMMIT")
63+
echo "Manual ref: $INPUT_REF resolved to $TAG. Pinned: $PIN."
4464
45-
# The pin is allowed to sit ahead of the latest release while a docs
46-
# fix has shipped but a release has not (the state this sync started
47-
# in). Syncing the tag then would publish older prose.
48-
if git -C /tmp/certified-assets merge-base --is-ancestor "$TAG" "$PIN"; then
49-
echo "Pin already contains $TAG. Nothing to sync."
50-
echo "needed=false" >> $GITHUB_OUTPUT
51-
exit 0
65+
# Peel the pin to a commit before comparing. The tags here are
66+
# annotated, so an unpeeled tag name resolves to the tag object and
67+
# would never equal a commit: dispatching the pinned tag would then
68+
# read as a change and rewrite the pin from that tag to its own
69+
# commit sha, moving a tag pin onto a commit for no reason.
70+
PIN_COMMIT=$(git -C /tmp/certified-assets rev-parse --verify --quiet "${PIN}^{commit}") || {
71+
echo "::error::Pin '$PIN' does not resolve in dfinity/certified-assets."
72+
exit 1
73+
}
74+
if [ "$REF_COMMIT" = "$PIN_COMMIT" ]; then
75+
echo "That is the pin already. Nothing to sync."
76+
echo "needed=false" >> $GITHUB_OUTPUT
77+
exit 0
78+
fi
79+
80+
# A ref the pin already contains moves the pin backwards. That is
81+
# what a rollback is, so it runs, but it is also what a mistyped sha
82+
# looks like, so it is not silent: the run warns and the PR body
83+
# says so, which is the difference between the two.
84+
if git -C /tmp/certified-assets merge-base --is-ancestor \
85+
"$REF_COMMIT" "$PIN_COMMIT"; then
86+
echo "::warning::$INPUT_REF is behind the pin $PIN. This will move the pin backwards."
87+
echo "backwards=true" >> $GITHUB_OUTPUT
88+
fi
89+
else
90+
# Stable releases only, the same pattern the upstream.json watcher uses.
91+
# `^v[0-9]` would accept v0.4.0-rc.1 and publish docs for a prerelease.
92+
TAG=$(git -C /tmp/certified-assets tag --sort=-version:refname \
93+
| grep -E '^v[0-9]+\.[0-9]+\.[0-9]+$' | head -1)
94+
echo "Pinned: $PIN. Latest release: $TAG."
95+
96+
# The pin is allowed to sit ahead of the latest release while a docs
97+
# fix has shipped but a release has not (the state this sync started
98+
# in). Syncing the tag then would publish older prose.
99+
if git -C /tmp/certified-assets merge-base --is-ancestor "$TAG" "$PIN"; then
100+
echo "Pin already contains $TAG. Nothing to sync."
101+
echo "needed=false" >> $GITHUB_OUTPUT
102+
exit 0
103+
fi
52104
fi
105+
echo "tag=$TAG" >> $GITHUB_OUTPUT
53106
54107
# Skip only when a PR is actually open. A branch on its own proves
55108
# nothing: if a previous run pushed and then failed at `gh pr create`,
@@ -68,18 +121,34 @@ jobs:
68121
git push origin --delete "$BRANCH"
69122
fi
70123
71-
# A release that ships canister changes without touching docs/ leaves
72-
# the synced pages byte-identical, so there is no content to review.
73-
# The pin still has to move: it is allowed to sit on a commit only
74-
# while no release carries the pages, and skipping here would strand
75-
# it on that commit for good. So the PR is opened either way, and the
76-
# body says which of the two it is.
77124
CHANGED=$(git -C /tmp/certified-assets diff --name-only "${PIN}..${TAG}" -- docs/)
78-
echo "needed=true" >> $GITHUB_OUTPUT
79125
if [ -z "$CHANGED" ]; then
80-
echo "No docs/ changes between $PIN and $TAG: advancing the pin only."
81-
echo "pin_only=true" >> $GITHUB_OUTPUT
126+
# A release that ships canister changes without touching docs/ leaves
127+
# the synced pages byte-identical, so there is nothing to review. Two
128+
# cases, and only one of them is worth a pull request.
129+
if [ -n "$INPUT_REF" ] || ! git -C /tmp/certified-assets show-ref \
130+
--verify --quiet "refs/tags/${PIN}"; then
131+
# The pin is a commit (or a ref was dispatched by hand). Moving it
132+
# onto the tag is the point: a commit pin is allowed only while no
133+
# release carries the pages, and skipping here would strand it
134+
# there for good.
135+
echo "No docs/ changes between $PIN and $TAG: advancing the pin only."
136+
echo "needed=true" >> $GITHUB_OUTPUT
137+
echo "pin_only=true" >> $GITHUB_OUTPUT
138+
else
139+
# The pin is already a tag, so a pull request would carry an empty
140+
# page diff and a bumped ref, for a reader to review and merge with
141+
# nothing in it. The pin lags the release and stays accurate: it
142+
# says which ref this copy came from, and the copy still matches it.
143+
# The release itself is not lost, since the recipe that deploys this
144+
# canister releases in lockstep and is tracked under `watched`.
145+
echo "No docs/ changes between $PIN and $TAG, and the pin is a tag."
146+
echo "Nothing to sync."
147+
echo "needed=false" >> $GITHUB_OUTPUT
148+
exit 0
149+
fi
82150
else
151+
echo "needed=true" >> $GITHUB_OUTPUT
83152
echo "Changed upstream pages:"
84153
echo "$CHANGED"
85154
echo "pin_only=false" >> $GITHUB_OUTPUT
@@ -158,11 +227,24 @@ jobs:
158227
echo ""
159228
echo "Automated sync of the certified-assets user docs."
160229
echo ""
161-
echo "**Release:** \`$TAG\` (pinned from \`$PIN\`)"
230+
if [ -n "$INPUT_REF" ]; then
231+
echo "**Ref:** \`$TAG\` (pinned from \`$PIN\`), dispatched by hand as \`$INPUT_REF\`."
232+
echo "A ref is synced by hand when a docs fix has shipped upstream but not"
233+
echo "been released; the next release moves the pin back onto a tag."
234+
if [ "$BACKWARDS" = "true" ]; then
235+
echo ""
236+
echo "> [!WARNING]"
237+
echo "> This ref is **behind** the pin, so the pin moves backwards and any"
238+
echo "> page below is reverted to the older text. Intended for a rollback."
239+
echo "> If you meant to move forward, close this and dispatch the right ref."
240+
fi
241+
else
242+
echo "**Release:** \`$TAG\` (pinned from \`$PIN\`)"
243+
fi
162244
echo ""
163245
if [ "$PIN_ONLY" = "true" ]; then
164-
echo "No page changed in this range. The pin moves off a commit and onto"
165-
echo "the release tag, so the only diff is \`source_ref\` on each page."
246+
echo "No page changed in this range, so the only diff is the pin and the"
247+
echo "\`source_ref\` each page records."
166248
else
167249
echo "**Changed upstream files:**"
168250
while IFS= read -r f; do
@@ -192,3 +274,5 @@ jobs:
192274
PIN: ${{ steps.check.outputs.pin }}
193275
CHANGED: ${{ steps.check.outputs.changed_files }}
194276
PIN_ONLY: ${{ steps.check.outputs.pin_only }}
277+
INPUT_REF: ${{ inputs.ref }}
278+
BACKWARDS: ${{ steps.check.outputs.backwards }}

‎.sources/upstream.json‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,11 @@
6565
"range contains before pinning past a tag, and prefer a tag whenever one",
6666
"carries the pages. The sync workflow moves the pin onto a tag at the next",
6767
"release even when no page changed, so a commit pin is never permanent.",
68+
"Once it is a tag, a release that changes no page is skipped instead: the",
69+
"pin then lags the latest release and stays accurate, since it records the",
70+
"ref this copy came from and the copy still matches it. The release is not",
71+
"missed either way, because the recipe that deploys this canister releases",
72+
"in lockstep and is tracked under `watched`.",
6873
"History: the first sync used d9cb7df, because certified-assets#124 landed",
6974
"the frontmatter contract this sync requires after the v0.3.3 tag."
7075
]

0 commit comments

Comments
 (0)