From c025af6e54f41f796a4e28deb14f2f86c59df144 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Tue, 30 Jun 2026 09:37:17 -0700 Subject: [PATCH 1/3] fix(ci): force-stage version snapshots in publish-docs sync MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The publish-docs workflow preserves the downstream-owned versioning files (versions.json, versioned_docs/, versioned_sidebars/) before wiping docs-site/, then restores them after copying the SDK source over the top. But the SDK's docs-site/.gitignore (added in PR #2167 alongside the SidebarVersionSelect component, to keep local `docusaurus docs:version` scratch from accidentally being committed in the SDK) is itself copied down with the sync. So the subsequent `git add docs docs-site .nvmrc` silently skips the restored or newly-created snapshots, and the already-issued `git rm -rf docs-site` drops them from the index — net effect: every sync after the .gitignore landed deleted the snapshots from the docs repo. Force-add the three known snapshot paths to stage them regardless of the synced .gitignore. Mirrors the pattern Marie used in PR #2143 for docs/api/ (`git add -f docs/api`) before that path stopped needing it. After merging this, a manual `workflow_dispatch` is needed to re-create the version-0.48 snapshot downstream — subsequent NPM publishes will then keep snapshots intact automatically. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-docs.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/publish-docs.yaml b/.github/workflows/publish-docs.yaml index 3554d14ee..bb68816af 100644 --- a/.github/workflows/publish-docs.yaml +++ b/.github/workflows/publish-docs.yaml @@ -232,6 +232,20 @@ jobs: # pick up unrelated tree changes if anything went sideways. git add docs docs-site .nvmrc + # Force-add the downstream-owned version snapshots. docs-site/.gitignore + # excludes versions.json / versioned_docs/ / versioned_sidebars/ in the + # SDK source so a local `docusaurus docs:version` scratch run doesn't + # accidentally land in upstream commits. That same .gitignore is then + # synced down with the rest of docs-site/, so the bare `git add` above + # silently skips the restored-or-newly-created snapshots here. Without + # this force-add, every sync after the gitignore landed dropped the + # snapshots — see the picker-disappeared incident from June. + for path in versions.json versioned_docs versioned_sidebars; do + if [ -e "docs-site/$path" ]; then + git add -f "docs-site/$path" + fi + done + # Defense in depth: refuse to push if any staged change escapes # the managed allowlist. No-op when the workflow is correct; # catches future drift. From 297724220f107002d77626bf175d42d15bab9e0e Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Tue, 30 Jun 2026 12:35:47 -0700 Subject: [PATCH 2/3] fix at source: drop version-snapshot gitignores; revert workflow workaround MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per review feedback (#2313 — thanks Marie), addressing the root cause rather than working around it. The previous commit added `git add -f` to the publish-docs workflow to bypass docs-site/.gitignore for versions.json / versioned_docs/ / versioned_sidebars/. That worked, but left the downstream `.gitignore` "lying" — claiming to ignore paths the docs repo actually tracks. That kind of incoherence is exactly what caused this incident in the first place (Aaron's ignore looked correct in source isolation, but broke a sync invariant nobody had encoded). Cleaner fix: just don't ignore them. The protection these entries provided (preventing local `docusaurus docs:version` scratch from accidentally landing in SDK PRs) was guarding a workflow that's architecturally out-of-place anyway — versioning lives downstream, so nobody should be generating snapshots locally in the SDK. If someone does, `git status` will show 138+ untracked files and review catches it. Re-ran all three dry-run scenarios against the actual embedded-sdk-docs @origin/main without force-add — all pass: - workflow_dispatch + MINOR=0.48 (bootstrap): 287 staged, 139 version-related - workflow_run + MINOR=0.49 (next minor): versions.json = ["0.49", "0.48"] - workflow_run + MINOR=0.48 (patch refresh): refresh path executes cleanly Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-docs.yaml | 14 -------------- docs-site/.gitignore | 6 ------ 2 files changed, 20 deletions(-) diff --git a/.github/workflows/publish-docs.yaml b/.github/workflows/publish-docs.yaml index bb68816af..3554d14ee 100644 --- a/.github/workflows/publish-docs.yaml +++ b/.github/workflows/publish-docs.yaml @@ -232,20 +232,6 @@ jobs: # pick up unrelated tree changes if anything went sideways. git add docs docs-site .nvmrc - # Force-add the downstream-owned version snapshots. docs-site/.gitignore - # excludes versions.json / versioned_docs/ / versioned_sidebars/ in the - # SDK source so a local `docusaurus docs:version` scratch run doesn't - # accidentally land in upstream commits. That same .gitignore is then - # synced down with the rest of docs-site/, so the bare `git add` above - # silently skips the restored-or-newly-created snapshots here. Without - # this force-add, every sync after the gitignore landed dropped the - # snapshots — see the picker-disappeared incident from June. - for path in versions.json versioned_docs versioned_sidebars; do - if [ -e "docs-site/$path" ]; then - git add -f "docs-site/$path" - fi - done - # Defense in depth: refuse to push if any staged change escapes # the managed allowlist. No-op when the workflow is correct; # catches future drift. diff --git a/docs-site/.gitignore b/docs-site/.gitignore index de5de29cb..d1a5d2b54 100644 --- a/docs-site/.gitignore +++ b/docs-site/.gitignore @@ -2,9 +2,3 @@ node_modules/ .docusaurus/ build/ .cache-loader/ - -# Version snapshots are owned by Gusto/embedded-sdk-docs; only created locally -# to develop the version-dropdown UI. -versions.json -versioned_docs/ -versioned_sidebars/ From 7745672502799e64e9a6b04ac5a3da8628c2dc73 Mon Sep 17 00:00:00 2001 From: Jeff Johnson Date: Tue, 30 Jun 2026 12:45:03 -0700 Subject: [PATCH 3/3] fix(ci): assert downstream-owned paths aren't gitignored in publish-docs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Defense-in-depth check in publish-docs.yaml that runs `git check-ignore` against the synced docs-site/.gitignore for the three downstream-owned snapshot paths (versions.json, versioned_docs/, versioned_sidebars/). If a future SDK change re-introduces ignore rules for any of these (as #2167 did, silently deleting snapshots from the docs repo for two weeks), the sync now fails loudly with a clear error message pointing at the fix — instead of `git add` quietly skipping the restored snapshots and the workflow happily pushing the deletion downstream. Fails fast: runs in step 3a, before snapshot creation/refresh, so a gitignore regression never gets the chance to corrupt the archive. Tested both directions: - Positive (gitignore clean, this PR's state): check passes, all 3 dry-run scenarios (bootstrap, new minor, patch refresh) succeed - Negative (gitignore entries re-added): check fires with the exact error message before any data is staged Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/publish-docs.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/publish-docs.yaml b/.github/workflows/publish-docs.yaml index 3554d14ee..c19c7b656 100644 --- a/.github/workflows/publish-docs.yaml +++ b/.github/workflows/publish-docs.yaml @@ -169,6 +169,22 @@ jobs: # Strip anything that shouldn't ship with source. rm -rf docs-site/node_modules docs-site/build + # ---- Step 3a: gitignore precondition check ---- + # This sync's correctness depends on docs-site/.gitignore NOT + # ignoring the downstream-owned snapshot paths. If the SDK ever + # re-introduces such rules (as #2167 did, causing snapshots to + # silently disappear from the docs repo for two weeks), fail + # loudly here rather than letting `git add` quietly skip the + # restored snapshots below. + for path in docs-site/versions.json docs-site/versioned_docs docs-site/versioned_sidebars; do + if git check-ignore -q "$path"; then + echo "ERROR: $path is gitignored by the synced docs-site/.gitignore." >&2 + echo "Cross-repo sync requires this path to be tracked downstream." >&2 + echo "Remove the corresponding entry from the SDK's docs-site/.gitignore." >&2 + exit 1 + fi + done + # Restore the versioned files (or initialize empty placeholders if # downstream was bare — the snapshot step below populates them). for v in versioned_docs versioned_sidebars versions.json; do