diff --git a/.github/workflows/opencode-review.yml b/.github/workflows/opencode-review.yml index 9cc5d93da..5e46dbcbf 100644 --- a/.github/workflows/opencode-review.yml +++ b/.github/workflows/opencode-review.yml @@ -823,11 +823,11 @@ jobs: actions: write checks: read id-token: write - contents: read + contents: write models: read statuses: read deployments: read - pull-requests: read + pull-requests: write issues: read env: FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true @@ -4905,8 +4905,10 @@ jobs: - name: Run merge scheduler after approval continue-on-error: true env: - GH_TOKEN: ${{ secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.opencode_app_token.outputs.token }} - SCHEDULER_MUTATION_TOKEN_SOURCE: ${{ secrets.PR_REVIEW_MERGE_TOKEN != '' && 'PR_REVIEW_MERGE_TOKEN' || secrets.OPENCODE_APPROVE_TOKEN != '' && 'OPENCODE_APPROVE_TOKEN' || steps.opencode_app_token.outputs.available == 'true' && 'opencode-app' || 'missing' }} + GH_TOKEN: ${{ (github.event_name == 'pull_request_target' || github.event.inputs.target_repository == '' || github.event.inputs.target_repository == github.repository) && github.token || secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.opencode_app_token.outputs.token }} + SCHEDULER_ACTIONS_TOKEN: ${{ github.token }} + SCHEDULER_READ_TOKEN: ${{ github.token }} + SCHEDULER_MUTATION_TOKEN_SOURCE: ${{ (github.event_name == 'pull_request_target' || github.event.inputs.target_repository == '' || github.event.inputs.target_repository == github.repository) && 'github-token' || secrets.PR_REVIEW_MERGE_TOKEN != '' && 'PR_REVIEW_MERGE_TOKEN' || secrets.OPENCODE_APPROVE_TOKEN != '' && 'OPENCODE_APPROVE_TOKEN' || steps.opencode_app_token.outputs.available == 'true' && 'opencode-app' || 'missing' }} GH_REPOSITORY: ${{ github.event.pull_request.base.repo.full_name || github.event.inputs.target_repository || github.repository }} PR_BASE_REF: ${{ github.event.pull_request.base.ref || github.event.inputs.pr_base_ref || '' }} PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number || '' }} diff --git a/scripts/ci/test_strix_quick_gate.sh b/scripts/ci/test_strix_quick_gate.sh index 0e4a902ee..3c979dd6f 100755 --- a/scripts/ci/test_strix_quick_gate.sh +++ b/scripts/ci/test_strix_quick_gate.sh @@ -624,6 +624,10 @@ assert_opencode_review_uses_codegraph_and_gpt5_fallback() { assert_file_contains "$workflow_file" 'PR_BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.inputs.pr_base_sha }}' "coverage evidence receives the PR base SHA for changed-file scoped measurement" assert_file_contains "$workflow_file" "Run merge scheduler after approval" "opencode approval runs the merge scheduler after current-head review publication" assert_file_contains "$workflow_file" "python3 scripts/ci/pr_review_merge_scheduler.py" "opencode approval directly executes the trusted central merge scheduler when required workflows are not repo-local dispatch targets" + assert_file_contains "$workflow_file" "pull-requests: write" "opencode approval can use github-actions[bot] for same-repository mechanical merge/update follow-up" + assert_file_contains "$workflow_file" 'SCHEDULER_ACTIONS_TOKEN: ${{ github.token }}' "opencode scheduler follow-up gives workflow-control calls the GitHub Actions token" + assert_file_contains "$workflow_file" 'SCHEDULER_READ_TOKEN: ${{ github.token }}' "opencode scheduler follow-up reads current PR state with the GitHub Actions token" + assert_file_contains "$workflow_file" "&& 'github-token' || secrets.PR_REVIEW_MERGE_TOKEN" "opencode scheduler follow-up prefers github-actions[bot] for same-repository mechanical mutations" assert_file_not_contains "$workflow_file" "gh workflow run pr-review-merge-scheduler.yml" "opencode approval must not rely on repo-local workflow dispatch for organization required workflows" assert_file_contains "$workflow_file" "gh api \"repos/\${GH_REPOSITORY}\" --jq '.default_branch // empty'" "opencode scheduler dispatch uses the target repository default branch" assert_file_contains "$workflow_file" 'base_branch="${PR_BASE_REF:-${default_branch:-main}}"' "opencode scheduler follow-up derives the target base branch instead of hard-coding main" diff --git a/tests/test_opencode_agent_contract.py b/tests/test_opencode_agent_contract.py index f92e3ced8..9b4a69095 100644 --- a/tests/test_opencode_agent_contract.py +++ b/tests/test_opencode_agent_contract.py @@ -208,7 +208,11 @@ def test_opencode_runs_merge_scheduler_after_review_without_repo_local_dispatch( assert "Run merge scheduler after approval" in workflow assert "python3 scripts/ci/pr_review_merge_scheduler.py" in workflow assert "gh workflow run pr-review-merge-scheduler.yml" not in workflow - assert "secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.opencode_app_token.outputs.token" in workflow + assert "github.event_name == 'pull_request_target'" in workflow + assert "&& github.token || secrets.PR_REVIEW_MERGE_TOKEN || secrets.OPENCODE_APPROVE_TOKEN || steps.opencode_app_token.outputs.token" in workflow + assert "SCHEDULER_ACTIONS_TOKEN: ${{ github.token }}" in workflow + assert "SCHEDULER_READ_TOKEN: ${{ github.token }}" in workflow + assert "&& 'github-token' || secrets.PR_REVIEW_MERGE_TOKEN" in workflow assert "--no-trigger-reviews" in workflow assert "--enable-auto-merge" in workflow assert "--no-update-branches" in workflow