From 43bbf2c88c1df5fd7633fbca12bd86c83bf00738 Mon Sep 17 00:00:00 2001 From: Shrinath Rao Date: Wed, 24 Jun 2026 22:33:42 +0530 Subject: [PATCH] =?UTF-8?q?test:=20DocGen=20OSS=20caller=20=E2=80=94=20dis?= =?UTF-8?q?patch=20the=20engine=20via=20PAT=20(no=20org=20access-policy)?= =?UTF-8?q?=20(#12871)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reworks the OSS DocGen caller from a **cross-repo `workflow_call`** to **dispatching** the engine (`o2-enterprise` `docgen.yml`) via `workflow_dispatch`, authenticated with `ORG_ADMIN_TOKEN`. **Why:** `workflow_call` into the private ENT repo needs a repo/org **Actions access-policy** grant. A PAT-based dispatch doesn't — a fine-grained PAT with **`Actions: read & write`** on `o2-enterprise` can trigger it. No org settings touched. **Flow:** org-member `/docgen` (gate unchanged, = trust boundary for the PAT) → resolve PR/dry-run/actor (event data via env, not spliced into commands) → `gh workflow run docgen.yml --repo o2-enterprise …` with the PAT → ack on the OSS PR. The engine runs in ENT and comments results back via the same PAT (pairs with o2-enterprise engine PR). **PAT requirement:** `ORG_ADMIN_TOKEN` needs **Actions: R/W** on `o2-enterprise` (distinct from "Workflows"), plus Issues/Pull-requests R/W on `openobserve` + `o2-enterprise` for comments (Contents/PRs on docs already present). Merge alongside the engine PR. Stranger comments still fail the `if:` → no dispatch, PAT never used. --------- Co-authored-by: Claude Opus 4.8 --- .github/workflows/docgen-caller.yml | 117 +++++++++++++++++----------- 1 file changed, 72 insertions(+), 45 deletions(-) diff --git a/.github/workflows/docgen-caller.yml b/.github/workflows/docgen-caller.yml index 425dc1f083..d4d3111da3 100644 --- a/.github/workflows/docgen-caller.yml +++ b/.github/workflows/docgen-caller.yml @@ -1,30 +1,24 @@ name: DocGen Caller (openobserve) -# Thin caller: watches openobserve (OSS) PRs and forwards to the reusable DocGen engine that -# lives in o2-enterprise. All real logic lives in the engine; this file only decides WHETHER -# to run (command detection + org-member gate) and WHICH PR, then forwards. +# Thin caller: on an org member's `/docgen[-dryrun]` comment on an OSS PR (or manual dispatch), +# DISPATCH the DocGen engine that lives in the PRIVATE o2-enterprise repo, authenticated with the +# org-admin PAT. # -# WHY A CALLER (not dispatch the engine directly): a reusable workflow runs in the CALLER's -# context, so triggering from here makes the run use openobserve's own GITHUB_TOKEN / -# github-actions[bot] — which can comment on OSS PRs. Dispatching the engine from o2-enterprise -# would run in ENT's context (ENT bot) and could NOT comment on an OSS PR. +# WHY DISPATCH (not `workflow_call`/`uses:`): a cross-repo reusable-workflow call requires the +# private repo to grant an Actions *access policy* to this repo. Dispatch via a PAT needs no such +# org/repo setting — a PAT with `Actions: read & write` on o2-enterprise can trigger its +# `workflow_dispatch`. The engine then runs IN o2-enterprise CI and posts results back here using +# the same PAT (its own GITHUB_TOKEN can't write to this repo). # -# TWO WAYS TO TRIGGER: -# - issue_comment → an org member comments `/docgen` or `/docgen-dryrun` on an OSS PR. -# - workflow_dispatch → manual "Run workflow" button (Actions UI / gh) against a PR number. -# Dispatch is inherently restricted to users with repo write access. +# This caller only: (1) gates the command to org members, (2) resolves PR/dry-run/actor, +# (3) dispatches the engine via the PAT, (4) posts an immediate ack on the OSS PR. # -# ORG-MEMBER GATE (comment path, no API call): gate on the comment author_association — -# OWNER / MEMBER (org member) or COLLABORATOR. On this PUBLIC repo this blocks random external -# commenters from firing paid model runs. -# -# SECRETS CONTEXT: a cross-repo reusable runs in THIS (openobserve) repo's secrets context. -# We use DeepSeek precisely because DEEPSEEK_API_KEY already exists here (e2e-council.yml + -# ai-code-review.yml) — no Anthropic secret needed. E2E_DEV_CI_TOKEN is only used by the engine -# for cross-repo diff reads + Phase B docs pushes (comments post as github-actions[bot]). -# -# KILL SWITCH: the engine honors a DOCGEN_DISABLED repo/org variable — set it to 'true' to -# disable all DocGen runs without removing these files. +# REQUIRED — secrets.ORG_ADMIN_TOKEN (fine-grained PAT) permissions: +# o2-enterprise: Actions: R/W (to dispatch) + Issues/Pull requests: R/W (engine comments) +# openobserve: Issues/Pull requests: R/W (engine comments back on the source PR) +# openobserve-docs: Contents + Pull requests: R/W (docs PRs) +# NOTE: "Actions" (run triggering) is a DIFFERENT permission from "Workflows" (file editing). +# KILL SWITCH: the engine honors the DOCGEN_DISABLED variable. on: issue_comment: @@ -32,42 +26,75 @@ on: workflow_dispatch: inputs: pr_number: - description: "OSS PR number to run DocGen triage on" + description: "OSS PR number" required: true dry_run: description: "Triage only (no generation)" type: boolean - # Intentional SAFE default: a manual dispatch previews (triage only) unless you opt - # into generation by unchecking this. (Comment path is explicit: /docgen = full run, - # /docgen-dryrun = triage.) In Phase A dry_run has no effect yet — everything is - # triage-only — so this only matters once Phase B (doc generation) lands. default: true permissions: contents: read - pull-requests: write + pull-requests: write # post the ack comment on the OSS PR (this run is in OSS context) issues: write jobs: - call-docgen: - # Run on a manual dispatch, OR on an exact `/docgen[-dryrun]` comment from an org member. + dispatch-docgen: + # Manual dispatch, OR an exact `/docgen[-dryrun]` comment from an org member. This org-member + # gate is the trust boundary for the PAT — a stranger's comment fails this `if:`, so the + # dispatch step (and therefore the PAT) never runs. if: > github.event_name == 'workflow_dispatch' || (github.event.issue.pull_request && (github.event.comment.body == '/docgen' || github.event.comment.body == '/docgen-dryrun') && contains(fromJSON('["OWNER","MEMBER","COLLABORATOR"]'), github.event.comment.author_association)) - uses: openobserve/o2-enterprise/.github/workflows/docgen.yml@main - with: - source_repo: openobserve - # dispatch supplies pr_number directly (inputs.* is the typed dispatch context, empty on - # the comment path); comment path uses the commented PR. - pr_number: ${{ inputs.pr_number || github.event.issue.number }} - # dispatch: honor the (typed boolean) dry_run input; comment path: dry-run only for - # /docgen-dryrun. Use inputs.dry_run (typed bool), NOT github.event.inputs (a string). - dry_run: ${{ github.event_name == 'workflow_dispatch' && inputs.dry_run || github.event.comment.body == '/docgen-dryrun' }} - actor: ${{ github.event_name == 'workflow_dispatch' && github.actor || github.event.comment.user.login }} - secrets: - # OSS holds the DeepSeek key as DEEPSEEK_API_KEY_E2E; forward it under the engine's - # (renamed) DEEPSEEK_API_KEY_E2E input. Both repos now standardize on this name. - DEEPSEEK_API_KEY_E2E: ${{ secrets.DEEPSEEK_API_KEY_E2E }} - CROSS_REPO_TOKEN: ${{ secrets.E2E_DEV_CI_TOKEN }} + runs-on: ubuntu-latest + timeout-minutes: 10 # the dispatch is a quick API call; bound it as defense-in-depth + steps: + - name: Resolve context (untrusted event data via env, never spliced into commands) + id: ctx + env: + IN_PR: ${{ inputs.pr_number || github.event.issue.number }} + IS_DISPATCH: ${{ github.event_name == 'workflow_dispatch' }} + DISPATCH_DRY: ${{ inputs.dry_run }} + COMMENT_BODY: ${{ github.event.comment.body }} + COMMENT_LOGIN: ${{ github.event.comment.user.login }} + DISPATCH_ACTOR: ${{ github.actor }} + run: | + PR="$IN_PR" + [[ "$PR" =~ ^[0-9]+$ ]] || { echo "::error::invalid PR number: $PR"; exit 1; } + if [ "$IS_DISPATCH" = "true" ]; then + DRY="$DISPATCH_DRY"; ACTOR="$DISPATCH_ACTOR" + else + [ "$COMMENT_BODY" = "/docgen-dryrun" ] && DRY="true" || DRY="false" + ACTOR="$COMMENT_LOGIN" + fi + ACTOR=$(printf '%s' "$ACTOR" | tr -cd 'A-Za-z0-9-') # GitHub login charset; defensive + { echo "pr=$PR"; echo "dry=$DRY"; echo "actor=$ACTOR"; } >> "$GITHUB_OUTPUT" + + - name: Dispatch the DocGen engine (o2-enterprise) via the org-admin PAT + env: + GH_TOKEN: ${{ secrets.ORG_ADMIN_TOKEN }} + PR: ${{ steps.ctx.outputs.pr }} + DRY: ${{ steps.ctx.outputs.dry }} + ACTOR: ${{ steps.ctx.outputs.actor }} + run: | + gh workflow run docgen.yml --repo openobserve/o2-enterprise \ + -f source_repo=openobserve \ + -f pr_number="$PR" \ + -f dry_run="$DRY" \ + -f actor="$ACTOR" + echo "Dispatched DocGen engine for openobserve PR #$PR (dry_run=$DRY, by @$ACTOR)." + + - name: Acknowledge on the source PR + # success() => only ack if the dispatch actually succeeded (don't mislead the author if + # the dispatch 403'd on a missing PAT permission, etc.) + if: github.event_name == 'issue_comment' && success() + env: + GH_TOKEN: ${{ github.token }} # OSS context → bot can comment on the OSS PR + PR: ${{ steps.ctx.outputs.pr }} + run: | + gh pr comment "$PR" --repo openobserve/openobserve --body \ + "### 📝 DocGen — started + + Running in o2-enterprise CI now — I'll post the documentation PR link(s) back here when ready. ([engine runs](https://github.com/openobserve/o2-enterprise/actions/workflows/docgen.yml))"