Record what bumps a page's version, and what a CI workflow should do about it - #155
Merged
Conversation
Measured for #149, which needs the page version to mean "the content moved on". It does: version.number tracks the body and the title and nothing else. Neither content property write, neither label write, and an attachment upload all leave it -- and version.createdAt -- exactly as they were, while a body or title change bumps both. Two consequences the issue depends on. A publish advances the page by exactly one version, even though update writes width, labels and attachments after the body, so the version the body PUT returned is still the live one afterwards. And that returned version is what a later GET reports, so a caller recording what it published needs no re-read. A content property also carries its own version counter -- it went 1 -> 2 across a create-then-update while the page stayed at 1 -- so a property's version says nothing about the page's in either direction. Cross-referenced from labels.md, page-width.md and attachments.md, since each is a place someone would look first for "does this write touch the page". Not verified, and said so: whether the v1 move route (#10) bumps the version, and whether a UI version restore does.
A CI workflow only makes sense when the repository is the source of truth and the page is a published copy, and saying so decides two things the page did not answer. --force, because without it publishing is non-deterministic rather than merely unprotected. git does not preserve mtimes, so a fresh checkout stamps every file with the clone time, and the skip compares that against Atlassian's clock -- so whether a page publishes depends on wall-clock ordering between two unsynchronized clocks, and one that should have synced can be reported skipped. The mtime check exists to protect an edit made in Confluence, which is the thing this arrangement deliberately does not want (#149). And a callout on the page, since a UI edit here is drift that the next push overwrites. A GitHub alert converts to a Confluence panel, so the mechanism already exists; linking the source file is what makes "do not edit" actionable. Permissions are suggested as the mechanism a banner only approximates. Plus an explicit "do not run this in CI" for the inverse arrangement, where Confluence is the source of truth: update has no record of which page version a local copy came from, so two divergent publishes resolve to whoever went last.
paths: on the trigger gates whether the job runs, not what the glob matches, so update --force docs/**/*.md republishes the whole tree on every merge. The reason that matters is not tidiness: Confluence notifies watchers on update, so one typo fix emails everyone watching any of 200 pages, and a run of identical new versions makes the page history unanswerable. The recipe uses plain git rather than a marketplace changed-files action, since this is the step holding the Confluence token. Two details it gets wrong easily: --diff-filter=ACMRT excludes deletions, which would otherwise land in the list and fail the run because update cannot publish a file that is not there; and an empty diff has to skip the step, because update with no FILE arguments is an error. The all-zero base sha from a new branch or a force-push falls back to the first commit, so that case publishes everything rather than failing on an unknown ref.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Documentation only. Three commits: one measured Confluence fact, and two things about running markfluence in CI that came out of the #149 design discussion.
What bumps a page's version
docs/confluence/api.mdgains a section, because #149 needs the page version to mean "the content moved on" and nothing recorded whether it does.It does.
version.numbertracks the body and the title and nothing else — verified against a scratch page in a personal space, created and then written to seven ways. Neither content-property write, neither label write, and an attachment upload all leave both the number andversion.createdAtuntouched, while a body or title change bumps both. A content property turns out to carry its own independent version counter: it went 1 → 2 across a create-then-update while the page stayed at 1.Two consequences the design depends on. A publish advances the page by exactly one version, even though
updatewrites width, labels and attachments after the body — so the version the body PUT returned is still the live one when the run finishes. And that returned version is what a later GET reports, so a caller recording what it published needs no re-read.Cross-referenced from
labels.md,page-width.mdandattachments.md, since each is where somebody would look first for "does this write touch the page". Said explicitly what is not verified: whether the v1 move route (#10) bumps the version, whether a UI version restore does, and that this is one measurement on one Cloud instance through the gateway.Scratch page purged.
Name the source of truth, and recommend
--forcedocs/github-actions.mddid not say what arrangement a CI workflow assumes, and that assumption decides two things the page left unanswered.A workflow only makes sense when the repository is the source of truth and the page is a published copy. In that model an edit made in the Confluence UI is drift, not work — the next push overwrites it. So the page now says that outright, and then says what follows:
Use
--force, and for a sharper reason than "avoid the skip". Without it, publishing is non-deterministic rather than merely unprotected: git does not preserve mtimes, so a fresh checkout stamps every file with the clone time, and the skip compares that against Atlassian's clock — whether a given page publishes depends on wall-clock ordering between two unsynchronized clocks, and a page that should have synced can be silently reportedskipped. The workflow example is updated to match.Say so on the page. Since UI edits are going to be overwritten, readers should know before they spend an afternoon in the editor. A GitHub alert converts to a Confluence panel, so the mechanism already exists; linking the source file is what turns "do not edit" into something actionable. Page permissions are suggested as the mechanism a banner only approximates.
And an explicit "if Confluence is the source of truth, do not run this workflow" —
updatehas no record of which page version a local copy was made from, so two people publishing divergent copies silently resolves to whoever went last. That is #149, and until it is closed that arrangement stays manual.Publish only the files that changed
paths:on the trigger gates whether the job runs; it does not narrow the glob. Soupdate --force docs/**/*.mdrepublishes every managed page on every merge, and one typo fix bumps the whole tree.The reason that matters is not tidiness. Confluence notifies watchers on update, so republishing 200 pages emails everyone watching any of them — the cost that gets a publishing bot switched off. A run of identical new versions also makes "who changed this, and why" unanswerable in the UI, and it is N times the API calls on a rate limit shared with everyone else.
So the page now carries a
git diffrecipe, using plain git rather than a marketplace changed-files action, since this is the step holding the Confluence token. Two details it is easy to get wrong, both called out:--diff-filter=ACMRTexcludes deletions. Without it a deleted file lands in the list and fails the run, becauseupdatecannot publish a file that is not there — deleting a page is deliberately not something a publish does.updatewith no FILE arguments is an error.Plus
fetch-depth: 0, since both ends of the push range have to be present, and a fallback for the all-zerogithub.event.beforea new branch or force-push reports — falling back to publishing everything rather than failing on an unknown ref.Notes
updatebehaviour is being designed; this PR only records what is true today and what CI should do about it.make checkgreen on each commit.action.ymldoes not exist yet.