From 7e8f8e9c82828dda2219da4d2c162e1ef93dcdec Mon Sep 17 00:00:00 2001 From: Leonard Du Date: Thu, 30 Jul 2026 14:55:23 +1000 Subject: [PATCH 1/5] ci: trigger tf integration via /run-tf-integration comment --- .github/workflows/terraform-integration.yml | 65 ++++++++++++++++----- .github/workflows/tf-plan-comment.yml | 37 ++++++++++++ 2 files changed, 87 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/tf-plan-comment.yml diff --git a/.github/workflows/terraform-integration.yml b/.github/workflows/terraform-integration.yml index 83811e24e4..75a645c42e 100644 --- a/.github/workflows/terraform-integration.yml +++ b/.github/workflows/terraform-integration.yml @@ -1,15 +1,8 @@ name: Terraform Integration -# Privileged terraform test/plan gated by the `terraform-privileged` environment -# (required reviewers configured in repo Settings). See MSRC #127928. - on: - pull_request_target: - paths: - - '**.tf' - - '**.json' - - '**.tfvars' - - 'modules/terraform/**' + issue_comment: + types: [created] permissions: contents: read @@ -20,6 +13,9 @@ env: jobs: terraform-test: + if: | + github.event.issue.pull_request != null && + github.event.comment.body == '/run-tf-integration' environment: terraform-privileged permissions: contents: read @@ -29,8 +25,7 @@ jobs: - name: Checkout PR head uses: actions/checkout@v4 with: - repository: ${{ github.event.pull_request.head.repo.full_name }} - ref: ${{ github.event.pull_request.head.sha }} + ref: refs/pull/${{ github.event.issue.number }}/head persist-credentials: false - name: Setup Terraform @@ -60,14 +55,16 @@ jobs: ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} setup-matrix: + if: | + github.event.issue.pull_request != null && + github.event.comment.body == '/run-tf-integration' runs-on: ubuntu-latest name: Setup terraform plan matrix for test scenarios steps: - name: Checkout PR head uses: actions/checkout@v4 with: - repository: ${{ github.event.pull_request.head.repo.full_name }} - ref: ${{ github.event.pull_request.head.sha }} + ref: refs/pull/${{ github.event.issue.number }}/head fetch-depth: 0 persist-credentials: false @@ -136,8 +133,7 @@ jobs: - name: Checkout PR head uses: actions/checkout@v4 with: - repository: ${{ github.event.pull_request.head.repo.full_name }} - ref: ${{ github.event.pull_request.head.sha }} + ref: refs/pull/${{ github.event.issue.number }}/head persist-credentials: false - name: Setup Terraform @@ -175,3 +171,42 @@ jobs: env: ARM_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }} CLOUD: ${{ matrix.cloud }} + + report-status: + needs: [terraform-test, setup-matrix, terraform-plan] + if: always() + runs-on: ubuntu-latest + name: Terraform Integration Result + steps: + - name: Post status back to PR head sha + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR: ${{ github.event.issue.number }} + TEST_RESULT: ${{ needs.terraform-test.result }} + SETUP_RESULT: ${{ needs.setup-matrix.result }} + PLAN_RESULT: ${{ needs.terraform-plan.result }} + run: | + set -eu + SHA=$(gh api "/repos/${{ github.repository }}/pulls/$PR" --jq '.head.sha') + echo "PR #$PR head sha: $SHA" + echo "terraform-test: $TEST_RESULT" + echo "setup-matrix : $SETUP_RESULT" + echo "terraform-plan: $PLAN_RESULT" + + state=success + for r in "$TEST_RESULT" "$SETUP_RESULT" "$PLAN_RESULT"; do + case "$r" in + success|skipped|"") ;; + *) state=failure ;; + esac + done + + gh api -X POST "/repos/${{ github.repository }}/statuses/$SHA" \ + -f state="$state" \ + -f context="Terraform Integration Result" \ + -f description="test=$TEST_RESULT setup=$SETUP_RESULT plan=$PLAN_RESULT" \ + -f target_url="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" + + if [ "$state" != "success" ]; then + exit 1 + fi diff --git a/.github/workflows/tf-plan-comment.yml b/.github/workflows/tf-plan-comment.yml new file mode 100644 index 0000000000..8ff8b47a94 --- /dev/null +++ b/.github/workflows/tf-plan-comment.yml @@ -0,0 +1,37 @@ +name: Terraform Plan Trigger Comment + +on: + pull_request_target: + types: [opened, synchronize, reopened] + +permissions: + contents: read + pull-requests: write + +jobs: + post-comment: + runs-on: ubuntu-latest + steps: + - name: Upsert trigger comment + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR: ${{ github.event.pull_request.number }} + run: | + set -eu + marker="" + body=$(cat < /dev/null + else + gh api -X POST "/repos/${{ github.repository }}/issues/$PR/comments" \ + -f body="$body" > /dev/null + fi From 5eee4bbe66be2098f9d96b6771fadc5dea39195e Mon Sep 17 00:00:00 2001 From: Leonard Du Date: Thu, 30 Jul 2026 15:05:39 +1000 Subject: [PATCH 2/5] ci: fix report-status permissions and fetch main for diff --- .github/workflows/terraform-integration.yml | 6 ++++++ .github/workflows/tf-plan-comment.yml | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/terraform-integration.yml b/.github/workflows/terraform-integration.yml index 75a645c42e..16901a917a 100644 --- a/.github/workflows/terraform-integration.yml +++ b/.github/workflows/terraform-integration.yml @@ -68,6 +68,9 @@ jobs: fetch-depth: 0 persist-credentials: false + - name: Fetch main branch for diff + run: git fetch origin main:refs/remotes/origin/main + - name: Setup test matrix scenarios id: setup-matrix-scenarios run: | @@ -177,6 +180,9 @@ jobs: if: always() runs-on: ubuntu-latest name: Terraform Integration Result + permissions: + statuses: write + pull-requests: read steps: - name: Post status back to PR head sha env: diff --git a/.github/workflows/tf-plan-comment.yml b/.github/workflows/tf-plan-comment.yml index 8ff8b47a94..66437a9227 100644 --- a/.github/workflows/tf-plan-comment.yml +++ b/.github/workflows/tf-plan-comment.yml @@ -5,7 +5,6 @@ on: types: [opened, synchronize, reopened] permissions: - contents: read pull-requests: write jobs: From 08e97fec836647f7e57d70a4573dae3f3686c581 Mon Sep 17 00:00:00 2001 From: Leonard Du Date: Fri, 31 Jul 2026 01:01:58 +1000 Subject: [PATCH 3/5] probe: test if GITHUB_TOKEN can list team members --- .github/workflows/probe-team-api.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 .github/workflows/probe-team-api.yml diff --git a/.github/workflows/probe-team-api.yml b/.github/workflows/probe-team-api.yml new file mode 100644 index 0000000000..998c3c8621 --- /dev/null +++ b/.github/workflows/probe-team-api.yml @@ -0,0 +1,24 @@ +name: Team API Permission Probe + +on: + push: + branches: [leonarddu/merge-gate-tf-integration] + +jobs: + probe: + runs-on: ubuntu-latest + steps: + - name: Try list telescope-oncall members with default GITHUB_TOKEN + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -eu + echo "=== GET /orgs/Azure/teams/telescope-oncall/members ===" + if gh api /orgs/Azure/teams/telescope-oncall/members --paginate --jq '.[].login'; then + echo "" + echo "RESULT: OK - default GITHUB_TOKEN CAN list team members" + else + echo "" + echo "RESULT: FAIL - default GITHUB_TOKEN CANNOT list team members; PAT needed" + exit 1 + fi From 5ff621879ee91b14add431d98e142e1e36bc58b0 Mon Sep 17 00:00:00 2001 From: Leonard Du Date: Fri, 31 Jul 2026 01:04:53 +1000 Subject: [PATCH 4/5] probe: verify gh CLI + cross-check via curl --- .github/workflows/probe-team-api.yml | 43 +++++++++++++++++++++------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/.github/workflows/probe-team-api.yml b/.github/workflows/probe-team-api.yml index 998c3c8621..059b808e8b 100644 --- a/.github/workflows/probe-team-api.yml +++ b/.github/workflows/probe-team-api.yml @@ -8,17 +8,38 @@ jobs: probe: runs-on: ubuntu-latest steps: - - name: Try list telescope-oncall members with default GITHUB_TOKEN + - name: Verify gh CLI is installed + run: | + set -eu + echo "=== which gh ===" + which gh + echo "=== gh --version ===" + gh --version + + - name: Try list telescope-oncall members via gh env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - set -eu - echo "=== GET /orgs/Azure/teams/telescope-oncall/members ===" - if gh api /orgs/Azure/teams/telescope-oncall/members --paginate --jq '.[].login'; then - echo "" - echo "RESULT: OK - default GITHUB_TOKEN CAN list team members" - else - echo "" - echo "RESULT: FAIL - default GITHUB_TOKEN CANNOT list team members; PAT needed" - exit 1 - fi + echo "=== gh api /orgs/Azure/teams/telescope-oncall/members ===" + gh api /orgs/Azure/teams/telescope-oncall/members --paginate --jq '.[].login' || echo "gh exit code: $?" + + - name: Cross-check with raw curl + env: + TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "=== curl (raw response, includes HTTP status) ===" + curl -sS -w "\nHTTP_STATUS: %{http_code}\n" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/orgs/Azure/teams/telescope-oncall/members + + - name: Cross-check curl on a public endpoint (sanity check network) + env: + TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + echo "=== curl a public endpoint to prove network + auth OK ===" + curl -sS -w "\nHTTP_STATUS: %{http_code}\n" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Accept: application/vnd.github+json" \ + https://api.github.com/repos/Azure/telescope | head -20 From 4add3548a3eeefdde0f4a07bdf9f6152ff288e14 Mon Sep 17 00:00:00 2001 From: Leonard Du Date: Fri, 31 Jul 2026 01:17:31 +1000 Subject: [PATCH 5/5] probe: also test existing GH_PAT secret --- .github/workflows/probe-team-api.yml | 35 +++++++++------------------- 1 file changed, 11 insertions(+), 24 deletions(-) diff --git a/.github/workflows/probe-team-api.yml b/.github/workflows/probe-team-api.yml index 059b808e8b..920eeea1c5 100644 --- a/.github/workflows/probe-team-api.yml +++ b/.github/workflows/probe-team-api.yml @@ -10,36 +10,23 @@ jobs: steps: - name: Verify gh CLI is installed run: | - set -eu - echo "=== which gh ===" which gh - echo "=== gh --version ===" gh --version - - name: Try list telescope-oncall members via gh + - name: Test with default GITHUB_TOKEN env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - echo "=== gh api /orgs/Azure/teams/telescope-oncall/members ===" - gh api /orgs/Azure/teams/telescope-oncall/members --paginate --jq '.[].login' || echo "gh exit code: $?" + echo "=== Default GITHUB_TOKEN ===" + gh api /orgs/Azure/teams/telescope-oncall/members --paginate --jq '.[].login' || echo "GITHUB_TOKEN exit: $?" - - name: Cross-check with raw curl + - name: Test with existing GH_PAT secret env: - TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_TOKEN: ${{ secrets.GH_PAT }} run: | - echo "=== curl (raw response, includes HTTP status) ===" - curl -sS -w "\nHTTP_STATUS: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - -H "Accept: application/vnd.github+json" \ - -H "X-GitHub-Api-Version: 2022-11-28" \ - https://api.github.com/orgs/Azure/teams/telescope-oncall/members - - - name: Cross-check curl on a public endpoint (sanity check network) - env: - TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - echo "=== curl a public endpoint to prove network + auth OK ===" - curl -sS -w "\nHTTP_STATUS: %{http_code}\n" \ - -H "Authorization: Bearer $TOKEN" \ - -H "Accept: application/vnd.github+json" \ - https://api.github.com/repos/Azure/telescope | head -20 + echo "=== Existing GH_PAT secret ===" + if [ -z "$GH_TOKEN" ]; then + echo "GH_PAT is empty/unset" + exit 0 + fi + gh api /orgs/Azure/teams/telescope-oncall/members --paginate --jq '.[].login' || echo "GH_PAT exit: $?"