Docs PR AI menu #2657
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Docs PR AI menu | |
| on: | |
| workflow_run: | |
| workflows: ["Docs PR AI menu (collect)"] | |
| types: [completed] | |
| issue_comment: | |
| types: [edited] | |
| workflow_dispatch: | |
| inputs: | |
| pull_request_number: | |
| description: Pull request number to post or refresh the AI PR menu on. | |
| required: true | |
| type: string | |
| permissions: | |
| actions: read | |
| checks: read | |
| contents: read | |
| discussions: write | |
| issues: write | |
| pull-requests: write | |
| jobs: | |
| post-menu: | |
| name: Post or refresh AI PR menu | |
| if: >- | |
| (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success') || | |
| github.event_name == 'workflow_dispatch' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| checks: read | |
| contents: read | |
| issues: write | |
| pull-requests: write | |
| concurrency: | |
| group: docs-pr-ai-menu-${{ github.event.workflow_run.id || github.event.inputs.pull_request_number }} | |
| cancel-in-progress: false | |
| steps: | |
| - name: Download PR number artifact | |
| if: github.event_name == 'workflow_run' | |
| uses: actions/download-artifact@v8 | |
| with: | |
| name: pr-number | |
| run-id: ${{ github.event.workflow_run.id }} | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Resolve pull request number | |
| id: resolve-pr | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_run" ]; then | |
| echo "number=$(cat pr_number.txt)" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "number=${{ github.event.inputs.pull_request_number }}" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Checkout repository | |
| uses: actions/checkout@v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Create or update AI PR menu comment | |
| uses: actions/github-script@v9.0.0 | |
| env: | |
| PULL_REQUEST_NUMBER: ${{ steps.resolve-pr.outputs.number }} | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const menu = require(`${process.env.GITHUB_WORKSPACE}/.github/scripts/docs_pr_ai_menu.cjs`); | |
| const pullRequestNumber = Number(process.env.PULL_REQUEST_NUMBER); | |
| if (!pullRequestNumber) { | |
| core.setFailed('Pull request number is required.'); | |
| return; | |
| } | |
| await menu.upsertMenuComment({ core, github, context, pullRequestNumber }); | |
| evaluate-trigger: | |
| name: Evaluate AI PR menu trigger | |
| if: >- | |
| github.event_name == 'issue_comment' && | |
| github.event.issue.pull_request != null && | |
| github.actor != 'github-actions[bot]' && | |
| github.event.comment.user.login == 'github-actions[bot]' && | |
| contains(github.event.comment.body, '<!-- docs-pr-ai-menu:start -->') && | |
| contains(github.event.comment.body, '<!-- docs-pr-ai-menu:end -->') | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| docs_review_triggered: ${{ steps.evaluate.outputs.docs_review_triggered }} | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Parse AI PR menu transition | |
| id: evaluate | |
| uses: actions/github-script@v9.0.0 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const menu = require(`${process.env.GITHUB_WORKSPACE}/.github/scripts/docs_pr_ai_menu.cjs`); | |
| const { data: pullRequest } = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: context.payload.issue.number, | |
| }); | |
| const isForkPR = pullRequest.head.repo.full_name !== `${context.repo.owner}/${context.repo.repo}`; | |
| if (isForkPR) { | |
| let isOrgMember = false; | |
| try { | |
| const { status } = await github.rest.orgs.checkMembershipForUser({ | |
| org: context.repo.owner, | |
| username: context.actor, | |
| }); | |
| isOrgMember = status === 204; | |
| } catch { | |
| isOrgMember = false; | |
| } | |
| if (!isOrgMember) { | |
| core.setOutput('docs_review_triggered', 'false'); | |
| return; | |
| } | |
| } | |
| const body = context.payload.comment.body || ''; | |
| const previousBody = context.payload.changes?.body?.from || ''; | |
| const previousState = menu.parseMenuState(previousBody); | |
| const currentState = menu.parseMenuState(body); | |
| const docsReviewTriggered = | |
| !previousState.docsReview.selected && currentState.docsReview.selected; | |
| core.setOutput('docs_review_triggered', String(docsReviewTriggered)); | |
| refresh-menu-after-trigger: | |
| name: Refresh AI PR menu after trigger | |
| needs: [evaluate-trigger] | |
| if: needs.evaluate-trigger.outputs.docs_review_triggered == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| checks: read | |
| contents: read | |
| issues: write | |
| pull-requests: write | |
| concurrency: | |
| group: docs-pr-ai-menu-${{ github.event.issue.number }} | |
| cancel-in-progress: false | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Refresh AI PR menu status | |
| uses: actions/github-script@v9.0.0 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const menu = require(`${process.env.GITHUB_WORKSPACE}/.github/scripts/docs_pr_ai_menu.cjs`); | |
| const pullRequestNumber = context.payload.issue.number; | |
| const progressUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; | |
| await menu.upsertMenuComment({ | |
| core, | |
| createIfMissing: false, | |
| github, | |
| context, | |
| pullRequestNumber, | |
| statusOverrides: { | |
| docsReview: { | |
| detailsUrl: progressUrl, | |
| status: 'in_progress', | |
| }, | |
| }, | |
| }); | |
| run-docs-review: | |
| name: Docs AI / docs review | |
| needs: [evaluate-trigger] | |
| if: needs.evaluate-trigger.outputs.docs_review_triggered == 'true' | |
| permissions: | |
| actions: read | |
| contents: read | |
| discussions: write | |
| issues: write | |
| pull-requests: write | |
| uses: elastic/docs-actions/.github/workflows/gh-aw-docs-review.lock.yml@v1 | |
| with: | |
| review-scope: repo-wide-markdown | |
| additional-instructions: | | |
| This repository stores documentation as markdown across the repository, not only under `docs/`. | |
| Prefer concise, high-signal review comments with exact replacement text when possible. | |
| secrets: | |
| COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }} | |
| refresh-menu-after-docs-review: | |
| name: Refresh AI PR menu after docs review | |
| needs: [evaluate-trigger, run-docs-review] | |
| if: always() && needs.evaluate-trigger.outputs.docs_review_triggered == 'true' | |
| runs-on: ubuntu-latest | |
| permissions: | |
| checks: read | |
| contents: read | |
| issues: write | |
| pull-requests: write | |
| concurrency: | |
| group: docs-pr-ai-menu-${{ github.event.issue.number }} | |
| cancel-in-progress: false | |
| steps: | |
| - name: Checkout repository | |
| uses: actions/checkout@v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Refresh AI PR menu status | |
| uses: actions/github-script@v9.0.0 | |
| with: | |
| github-token: ${{ secrets.GITHUB_TOKEN }} | |
| script: | | |
| const menu = require(`${process.env.GITHUB_WORKSPACE}/.github/scripts/docs_pr_ai_menu.cjs`); | |
| const pullRequestNumber = context.payload.issue.number; | |
| const progressUrl = `${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`; | |
| const docsReviewResult = '${{ needs.run-docs-review.result }}'; | |
| const docsReviewStatus = { | |
| conclusion: docsReviewResult === 'success' | |
| ? 'success' | |
| : docsReviewResult === 'cancelled' | |
| ? 'cancelled' | |
| : 'failure', | |
| detailsUrl: progressUrl, | |
| status: 'completed', | |
| }; | |
| await menu.upsertMenuComment({ | |
| core, | |
| createIfMissing: false, | |
| github, | |
| context, | |
| pullRequestNumber, | |
| statusOverrides: { | |
| docsReview: docsReviewStatus, | |
| }, | |
| }); |