From 57dc3fba35fb585e75c306bb7054cb46c2ce5972 Mon Sep 17 00:00:00 2001 From: "V. David Zvenyach" Date: Mon, 19 Oct 2026 14:32:54 -0500 Subject: [PATCH 1/2] ci(docs-dispatch): diff the whole push and pass values through env Change detection diffed only `HEAD~1..HEAD`, so a multi-commit push dispatched only the last commit's docs paths; it now diffs `github.event.before..HEAD` with full history, falling back to `HEAD~1` for a new branch, a force-push whose old tip is gone, or a manual run. A manual run now always dispatches. Step outputs and event fields were interpolated straight into the `run:` scripts; every value now reaches them through `env:` as a quoted variable. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/docs-dispatch.yml | 34 ++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docs-dispatch.yml b/.github/workflows/docs-dispatch.yml index f1c9e66..598c679 100644 --- a/.github/workflows/docs-dispatch.yml +++ b/.github/workflows/docs-dispatch.yml @@ -32,17 +32,36 @@ jobs: steps: - uses: actions/checkout@v6 with: - fetch-depth: 2 + fetch-depth: 0 + # Every `${{ }}` value reaches the scripts through `env:`, never inline, so a file name or event field cannot inject shell. - name: Detect changed paths id: changes + env: + EVENT_NAME: ${{ github.event_name }} + BEFORE: ${{ github.event.before }} run: | set -euo pipefail - base=$(git rev-parse HEAD~1 2>/dev/null || git rev-parse HEAD) + # The empty-tree object: diffing against it lists every tracked file. + empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 + if [ "$EVENT_NAME" = "push" ] && [ -n "$BEFORE" ] && ! echo "$BEFORE" | grep -qx '0*' && git cat-file -e "$BEFORE^{commit}" 2>/dev/null; then + base="$BEFORE" + elif git rev-parse --verify -q HEAD~1 >/dev/null; then + # New branch, force-push whose old tip is gone, or a manual run. + base=HEAD~1 + else + base="$empty_tree" + fi external=$(git diff --name-only "$base" HEAD -- 'docs' 'README.md' 'CHANGELOG.md' | paste -sd, -) + # A manual run always dispatches: that is why someone runs it by hand. + if [ -n "$external" ] || [ "$EVENT_NAME" = "workflow_dispatch" ]; then + has_external=true + else + has_external=false + fi { echo "external=$external" - echo "has_external=$([ -n "$external" ] && echo true || echo false)" + echo "has_external=$has_external" } >> "$GITHUB_OUTPUT" - name: Dispatch to docs composer (makegov/docs) @@ -50,9 +69,12 @@ jobs: env: GH_TOKEN: ${{ secrets.DOCS_DISPATCH_TOKEN }} TARGET: ${{ vars.DOCS_TARGET_REPO || 'makegov/docs' }} + SOURCE_REPO: ${{ github.repository }} + SOURCE_REF: ${{ github.sha }} + CHANGED_PATHS: ${{ steps.changes.outputs.external }} run: | gh api "repos/$TARGET/dispatches" \ -f event_type=external_updated \ - -f "client_payload[source_repo]=${{ github.repository }}" \ - -f "client_payload[source_ref]=${{ github.sha }}" \ - -f "client_payload[changed_paths]=${{ steps.changes.outputs.external }}" + -f "client_payload[source_repo]=$SOURCE_REPO" \ + -f "client_payload[source_ref]=$SOURCE_REF" \ + -f "client_payload[changed_paths]=$CHANGED_PATHS" From 217e63f996341e90e264b271844fbcb4d1b1d50a Mon Sep 17 00:00:00 2001 From: "V. David Zvenyach" Date: Mon, 19 Oct 2026 14:42:28 -0500 Subject: [PATCH 2/2] ci(docs-dispatch): always dispatch when the push range is unknown Without a usable `before` (an all-zero one, one missing from the clone after a force-push, or a manual run), the earlier docs changes in the push can't be seen, so diffing only the tip commit could skip a needed rebuild. That branch now sets `force=true` and always dispatches, reporting the tip commit's paths. The workflow now matches the other SDK repos' copy apart from its header and checkout version. Co-Authored-By: Claude Opus 5.5 --- .github/workflows/docs-dispatch.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/docs-dispatch.yml b/.github/workflows/docs-dispatch.yml index 598c679..6643648 100644 --- a/.github/workflows/docs-dispatch.yml +++ b/.github/workflows/docs-dispatch.yml @@ -44,17 +44,20 @@ jobs: set -euo pipefail # The empty-tree object: diffing against it lists every tracked file. empty_tree=4b825dc642cb6eb9a060e54bf8d69288fbee4904 + # Without a usable `before` (a manual run, a new branch, or a force-push whose old tip is gone) the push range is unknown, so dispatch regardless and report the tip commit's paths. + force=false if [ "$EVENT_NAME" = "push" ] && [ -n "$BEFORE" ] && ! echo "$BEFORE" | grep -qx '0*' && git cat-file -e "$BEFORE^{commit}" 2>/dev/null; then base="$BEFORE" - elif git rev-parse --verify -q HEAD~1 >/dev/null; then - # New branch, force-push whose old tip is gone, or a manual run. - base=HEAD~1 else - base="$empty_tree" + force=true + if git rev-parse --verify -q HEAD~1 >/dev/null; then + base=HEAD~1 + else + base="$empty_tree" + fi fi external=$(git diff --name-only "$base" HEAD -- 'docs' 'README.md' 'CHANGELOG.md' | paste -sd, -) - # A manual run always dispatches: that is why someone runs it by hand. - if [ -n "$external" ] || [ "$EVENT_NAME" = "workflow_dispatch" ]; then + if [ -n "$external" ] || [ "$force" = true ]; then has_external=true else has_external=false