diff --git a/.github/workflows/docs-dispatch.yml b/.github/workflows/docs-dispatch.yml new file mode 100644 index 0000000..05cabae --- /dev/null +++ b/.github/workflows/docs-dispatch.yml @@ -0,0 +1,83 @@ +name: Docs dispatch + +# Fires on push to main when content that affects the published docs site +# changes (docs/, README, or CHANGELOG). Notifies makegov/docs via +# repository_dispatch so the docs site rebuilds without waiting for someone +# to push to the composer. +# +# tango-rust is a `coloc-source` repo: its docs/ folder is the authoritative +# source for the Rust SDK pages on docs.makegov.com. +# +# Required secrets: +# DOCS_DISPATCH_TOKEN — GitHub token with contents:write on makegov/docs. +# +# Required variables (optional): +# DOCS_TARGET_REPO — override the dispatch target (default: makegov/docs). + +on: + push: + branches: + - main + paths: + - "docs/**" + - "README.md" + - "CHANGELOG.md" + workflow_dispatch: + +jobs: + dispatch: + runs-on: ubuntu-latest + permissions: + contents: read + steps: + - uses: actions/checkout@v6 + with: + 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 + # 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" + else + 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, -) + if [ -n "$external" ] || [ "$force" = true ]; then + has_external=true + else + has_external=false + fi + { + echo "external=$external" + echo "has_external=$has_external" + } >> "$GITHUB_OUTPUT" + + - name: Dispatch to docs composer (makegov/docs) + if: steps.changes.outputs.has_external == 'true' + 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]=$SOURCE_REPO" \ + -f "client_payload[source_ref]=$SOURCE_REF" \ + -f "client_payload[changed_paths]=$CHANGED_PATHS"