From f3242adba7294de8c3230edd2812bf66de9f2eba Mon Sep 17 00:00:00 2001 From: Sarav Date: Fri, 7 Aug 2026 12:38:57 +0530 Subject: [PATCH 1/5] ci: notify help-docs hub on docs changes (bidirectional sync) --- .github/workflows/notify-help-docs.yml | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 .github/workflows/notify-help-docs.yml diff --git a/.github/workflows/notify-help-docs.yml b/.github/workflows/notify-help-docs.yml new file mode 100644 index 000000000..affe536e3 --- /dev/null +++ b/.github/workflows/notify-help-docs.yml @@ -0,0 +1,34 @@ +name: Notify help-docs (docs changed) + +# On a merge that touches docs on the default branch, tell the help-docs hub to +# promote the change up (product -> help-docs). Requires the shared docs-sync +# GitHub App: set vars.DOCS_SYNC_APP_ID and secrets.DOCS_SYNC_APP_PRIVATE_KEY. +# Sync-generated merges carry a [docs-sync] marker and are skipped (no loop). + +on: + push: + branches: [main] + paths: ["docs/docs/**"] + +permissions: + contents: read + +jobs: + notify: + if: ${{ !contains(github.event.head_commit.message, '[docs-sync]') }} + runs-on: ubuntu-latest + steps: + - uses: actions/create-github-app-token@v1 + id: tok + with: + app-id: ${{ vars.DOCS_SYNC_APP_ID }} + private-key: ${{ secrets.DOCS_SYNC_APP_PRIVATE_KEY }} + owner: AltimateAI + repositories: help-docs + - uses: peter-evans/repository-dispatch@v3 + with: + token: ${{ steps.tok.outputs.token }} + repository: AltimateAI/help-docs + event-type: promote-from-product + client-payload: | + {"product":"code","before":"${{ github.event.before }}","after":"${{ github.sha }}"} From 5fc6c28612a6c7e49a054f5a8e1d17027efbab0d Mon Sep 17 00:00:00 2001 From: Sarav Date: Fri, 7 Aug 2026 12:50:56 +0530 Subject: [PATCH 2/5] ci: resolve original PR author for hub notifications --- .github/workflows/notify-help-docs.yml | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/workflows/notify-help-docs.yml b/.github/workflows/notify-help-docs.yml index affe536e3..caaf1b026 100644 --- a/.github/workflows/notify-help-docs.yml +++ b/.github/workflows/notify-help-docs.yml @@ -1,9 +1,10 @@ name: Notify help-docs (docs changed) # On a merge that touches docs on the default branch, tell the help-docs hub to -# promote the change up (product -> help-docs). Requires the shared docs-sync -# GitHub App: set vars.DOCS_SYNC_APP_ID and secrets.DOCS_SYNC_APP_PRIVATE_KEY. -# Sync-generated merges carry a [docs-sync] marker and are skipped (no loop). +# promote the change up (product -> help-docs) as a review PR. Requires the +# shared docs-sync GitHub App: vars.DOCS_SYNC_APP_ID + +# secrets.DOCS_SYNC_APP_PRIVATE_KEY. Sync-generated merges carry a [docs-sync] +# marker and are skipped, so this never loops. on: push: @@ -12,12 +13,26 @@ on: permissions: contents: read + pull-requests: read jobs: notify: if: ${{ !contains(github.event.head_commit.message, '[docs-sync]') }} runs-on: ubuntu-latest steps: + - name: Resolve merged PR (author for notifications) + id: src + env: + GH_TOKEN: ${{ github.token }} + run: | + J="$(gh api repos/${{ github.repository }}/commits/${{ github.sha }}/pulls --jq '.[0] // {}')" + LOGIN="$(echo "$J" | jq -r '.user.login // ""')" + echo "num=$(echo "$J" | jq -r '.number // ""')" >> "$GITHUB_OUTPUT" + echo "login=$LOGIN" >> "$GITHUB_OUTPUT" + echo "url=$(echo "$J" | jq -r '.html_url // ""')" >> "$GITHUB_OUTPUT" + EMAIL=""; [ -n "$LOGIN" ] && EMAIL="$(gh api users/$LOGIN --jq '.email // ""' 2>/dev/null || echo '')" + echo "email=$EMAIL" >> "$GITHUB_OUTPUT" + - uses: actions/create-github-app-token@v1 id: tok with: @@ -25,10 +40,11 @@ jobs: private-key: ${{ secrets.DOCS_SYNC_APP_PRIVATE_KEY }} owner: AltimateAI repositories: help-docs + - uses: peter-evans/repository-dispatch@v3 with: token: ${{ steps.tok.outputs.token }} repository: AltimateAI/help-docs event-type: promote-from-product client-payload: | - {"product":"code","before":"${{ github.event.before }}","after":"${{ github.sha }}"} + {"product":"code","before":"${{ github.event.before }}","after":"${{ github.sha }}","source_pr":"${{ steps.src.outputs.num }}","source_author":"${{ steps.src.outputs.login }}","source_url":"${{ steps.src.outputs.url }}","source_email":"${{ steps.src.outputs.email }}"} From 1ceb638bf50e893f7ae0ef49e060d3faabca723b Mon Sep 17 00:00:00 2001 From: Sarav Date: Fri, 7 Aug 2026 12:56:49 +0530 Subject: [PATCH 3/5] ci: drop unused email lookup from hub notify payload --- .github/workflows/notify-help-docs.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/notify-help-docs.yml b/.github/workflows/notify-help-docs.yml index caaf1b026..b1819acbc 100644 --- a/.github/workflows/notify-help-docs.yml +++ b/.github/workflows/notify-help-docs.yml @@ -26,12 +26,9 @@ jobs: GH_TOKEN: ${{ github.token }} run: | J="$(gh api repos/${{ github.repository }}/commits/${{ github.sha }}/pulls --jq '.[0] // {}')" - LOGIN="$(echo "$J" | jq -r '.user.login // ""')" echo "num=$(echo "$J" | jq -r '.number // ""')" >> "$GITHUB_OUTPUT" - echo "login=$LOGIN" >> "$GITHUB_OUTPUT" + echo "login=$(echo "$J" | jq -r '.user.login // ""')" >> "$GITHUB_OUTPUT" echo "url=$(echo "$J" | jq -r '.html_url // ""')" >> "$GITHUB_OUTPUT" - EMAIL=""; [ -n "$LOGIN" ] && EMAIL="$(gh api users/$LOGIN --jq '.email // ""' 2>/dev/null || echo '')" - echo "email=$EMAIL" >> "$GITHUB_OUTPUT" - uses: actions/create-github-app-token@v1 id: tok @@ -47,4 +44,4 @@ jobs: repository: AltimateAI/help-docs event-type: promote-from-product client-payload: | - {"product":"code","before":"${{ github.event.before }}","after":"${{ github.sha }}","source_pr":"${{ steps.src.outputs.num }}","source_author":"${{ steps.src.outputs.login }}","source_url":"${{ steps.src.outputs.url }}","source_email":"${{ steps.src.outputs.email }}"} + {"product":"code","before":"${{ github.event.before }}","after":"${{ github.sha }}","source_pr":"${{ steps.src.outputs.num }}","source_author":"${{ steps.src.outputs.login }}","source_url":"${{ steps.src.outputs.url }}"} From e897998a3f76aa8d3c22c3407d4deac45380ad92 Mon Sep 17 00:00:00 2001 From: Sarav Date: Fri, 7 Aug 2026 13:23:02 +0530 Subject: [PATCH 4/5] ci: harden notify (fallback, concurrency, jq payload, pinned action, arc runner) --- .github/workflows/notify-help-docs.yml | 38 ++++++++++++++++++++------ 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/.github/workflows/notify-help-docs.yml b/.github/workflows/notify-help-docs.yml index b1819acbc..0bf165a2c 100644 --- a/.github/workflows/notify-help-docs.yml +++ b/.github/workflows/notify-help-docs.yml @@ -15,22 +15,43 @@ permissions: contents: read pull-requests: read +concurrency: + group: notify-help-docs-${{ github.ref }} + cancel-in-progress: false + jobs: notify: if: ${{ !contains(github.event.head_commit.message, '[docs-sync]') }} - runs-on: ubuntu-latest + runs-on: arc-runner-gke steps: - name: Resolve merged PR (author for notifications) id: src env: GH_TOKEN: ${{ github.token }} run: | - J="$(gh api repos/${{ github.repository }}/commits/${{ github.sha }}/pulls --jq '.[0] // {}')" - echo "num=$(echo "$J" | jq -r '.number // ""')" >> "$GITHUB_OUTPUT" - echo "login=$(echo "$J" | jq -r '.user.login // ""')" >> "$GITHUB_OUTPUT" - echo "url=$(echo "$J" | jq -r '.html_url // ""')" >> "$GITHUB_OUTPUT" + J="$(gh api repos/${{ github.repository }}/commits/${{ github.sha }}/pulls --jq '.[0] // {}' 2>/dev/null || echo '{}')" + { + echo "num=$(echo "$J" | jq -r '.number // ""')" + echo "login=$(echo "$J" | jq -r '.user.login // ""')" + echo "url=$(echo "$J" | jq -r '.html_url // ""')" + } >> "$GITHUB_OUTPUT" + + - name: Build dispatch payload + id: payload + env: + BEFORE: ${{ github.event.before }} + AFTER: ${{ github.sha }} + SRC_PR: ${{ steps.src.outputs.num }} + SRC_AUTHOR: ${{ steps.src.outputs.login }} + SRC_URL: ${{ steps.src.outputs.url }} + run: | + JSON="$(jq -cn --arg product code \ + --arg before "$BEFORE" --arg after "$AFTER" \ + --arg source_pr "$SRC_PR" --arg source_author "$SRC_AUTHOR" --arg source_url "$SRC_URL" \ + '{product:$product,before:$before,after:$after,source_pr:$source_pr,source_author:$source_author,source_url:$source_url}')" + echo "json=$JSON" >> "$GITHUB_OUTPUT" - - uses: actions/create-github-app-token@v1 + - uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1 id: tok with: app-id: ${{ vars.DOCS_SYNC_APP_ID }} @@ -38,10 +59,9 @@ jobs: owner: AltimateAI repositories: help-docs - - uses: peter-evans/repository-dispatch@v3 + - uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3 with: token: ${{ steps.tok.outputs.token }} repository: AltimateAI/help-docs event-type: promote-from-product - client-payload: | - {"product":"code","before":"${{ github.event.before }}","after":"${{ github.sha }}","source_pr":"${{ steps.src.outputs.num }}","source_author":"${{ steps.src.outputs.login }}","source_url":"${{ steps.src.outputs.url }}"} + client-payload: ${{ steps.payload.outputs.json }} From cba8741e981a52c2ee60fbce8d6b6a7249a7d37d Mon Sep 17 00:00:00 2001 From: Sarav Date: Mon, 10 Aug 2026 13:39:41 +0530 Subject: [PATCH 5/5] =?UTF-8?q?ci:=20address=20consensus=20review=20?= =?UTF-8?q?=E2=80=94=20secrets=20(not=20vars)=20for=20App=20ID,=20robust?= =?UTF-8?q?=20loop=20guard,=20config=20gate,=20drop=20concurrency,=20ubunt?= =?UTF-8?q?u-latest?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - CRITICAL: App ID is stored as a repo *secret*, not a variable — use secrets.DOCS_SYNC_APP_ID (vars.* resolved empty and failed every run). - loop guard checks every commit (toJSON(github.event.commits.*.message)) so the [docs-sync] marker survives merge-commit merges, not just squash/rebase. - add a config-check step: skip (notice) instead of red-failing when the App is not configured (forks, key rotation). - drop the concurrency group (a 3rd rapid push cancelled the pending run and dropped that range permanently); dispatch is cheap. - run on ubuntu-latest (arc-runner-gke is unverified on this repo and would queue with no signal; matches the repo\ s other jobs + dispatch-code-review). - add timeout-minutes + workflow_dispatch (manual re-fire / smoke test). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_011fcN8kPwzjDeBysYUzKfJU --- .github/workflows/notify-help-docs.yml | 40 ++++++++++++++++++-------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/.github/workflows/notify-help-docs.yml b/.github/workflows/notify-help-docs.yml index 0bf165a2c..6c916ac5b 100644 --- a/.github/workflows/notify-help-docs.yml +++ b/.github/workflows/notify-help-docs.yml @@ -1,31 +1,44 @@ name: Notify help-docs (docs changed) -# On a merge that touches docs on the default branch, tell the help-docs hub to -# promote the change up (product -> help-docs) as a review PR. Requires the -# shared docs-sync GitHub App: vars.DOCS_SYNC_APP_ID + -# secrets.DOCS_SYNC_APP_PRIVATE_KEY. Sync-generated merges carry a [docs-sync] -# marker and are skipped, so this never loops. +# When a push to the default branch changes published docs, tell the help-docs +# hub to promote the change up (product -> help-docs) as a review PR. Requires +# the shared docs-sync GitHub App as repo secrets: DOCS_SYNC_APP_ID and +# DOCS_SYNC_APP_PRIVATE_KEY — if either is unset the job skips (no red run). +# The loop guard checks every commit in the push for the [docs-sync] marker, so +# it holds across squash, rebase, and merge-commit strategies. on: push: branches: [main] paths: ["docs/docs/**"] + workflow_dispatch: permissions: contents: read pull-requests: read -concurrency: - group: notify-help-docs-${{ github.ref }} - cancel-in-progress: false - jobs: notify: - if: ${{ !contains(github.event.head_commit.message, '[docs-sync]') }} - runs-on: arc-runner-gke + if: ${{ !contains(toJSON(github.event.commits.*.message), '[docs-sync]') }} + runs-on: ubuntu-latest + timeout-minutes: 5 steps: + - name: Check docs-sync App is configured + id: config + env: + APP_ID: ${{ secrets.DOCS_SYNC_APP_ID }} + APP_KEY: ${{ secrets.DOCS_SYNC_APP_PRIVATE_KEY }} + run: | + if [ -n "$APP_ID" ] && [ -n "$APP_KEY" ]; then + echo "enabled=true" >> "$GITHUB_OUTPUT" + else + echo "enabled=false" >> "$GITHUB_OUTPUT" + echo "::notice::docs-sync App not configured — skipping dispatch." + fi + - name: Resolve merged PR (author for notifications) id: src + if: steps.config.outputs.enabled == 'true' env: GH_TOKEN: ${{ github.token }} run: | @@ -38,6 +51,7 @@ jobs: - name: Build dispatch payload id: payload + if: steps.config.outputs.enabled == 'true' env: BEFORE: ${{ github.event.before }} AFTER: ${{ github.sha }} @@ -53,13 +67,15 @@ jobs: - uses: actions/create-github-app-token@d72941d797fd3113feb6b93fd0dec494b13a2547 # v1 id: tok + if: steps.config.outputs.enabled == 'true' with: - app-id: ${{ vars.DOCS_SYNC_APP_ID }} + app-id: ${{ secrets.DOCS_SYNC_APP_ID }} private-key: ${{ secrets.DOCS_SYNC_APP_PRIVATE_KEY }} owner: AltimateAI repositories: help-docs - uses: peter-evans/repository-dispatch@ff45666b9427631e3450c54a1bcbee4d9ff4d7c0 # v3 + if: steps.config.outputs.enabled == 'true' with: token: ${{ steps.tok.outputs.token }} repository: AltimateAI/help-docs