From 6c610e7a05a49fc2530c9ef23c5c5f6933838f0b Mon Sep 17 00:00:00 2001 From: Renuka Fernando Date: Tue, 25 Aug 2026 15:51:38 +0530 Subject: [PATCH 1/2] ci: send azure webhook signature as x-webhook-checksum The Azure DevOps Incoming WebHook service connection reads the HMAC signature from the `x-webhook-checksum` header and expects the bare hex digest, not GitHub's `X-Hub-Signature: sha1=` format. The mismatched header name caused the webhook to reject requests with `RequiredHeaderSignatureNotFound` (HTTP 500). Send the checksum under the correct header and drop the `sha1=` prefix so Azure can verify the payload. Signed-off-by: Renuka Fernando --- .github/workflows/platform-api-cloud-release.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/platform-api-cloud-release.yml b/.github/workflows/platform-api-cloud-release.yml index c19d4f2eb0..8dbe5ec380 100644 --- a/.github/workflows/platform-api-cloud-release.yml +++ b/.github/workflows/platform-api-cloud-release.yml @@ -67,13 +67,13 @@ jobs: echo "Payload:"; cat payload.json - # Azure verifies HMAC-SHA1(secret, body) against the X-Hub-Signature header, - # formatted as "sha1=". - SIG="sha1=$(openssl dgst -sha1 -hmac "$AZURE_WEBHOOK_SECRET" payload.json | awk '{print $NF}')" + # Azure verifies HMAC-SHA1(secret, body) against the x-webhook-checksum + # header. The value is the bare hex digest (no "sha1=" prefix). + CHECKSUM="$(openssl dgst -sha1 -hmac "$AZURE_WEBHOOK_SECRET" payload.json | awk '{print $NF}')" HTTP_CODE=$(curl -sS --connect-timeout 10 --max-time 60 -o response.txt -w '%{http_code}' -X POST "$AZURE_WEBHOOK_URL" \ -H "Content-Type: application/json" \ - -H "X-Hub-Signature: $SIG" \ + -H "x-webhook-checksum: $CHECKSUM" \ --data-binary @payload.json) echo "Azure webhook responded with HTTP ${HTTP_CODE}" From cd56b8e49510b67b80b3e0754b4e246a57832904 Mon Sep 17 00:00:00 2001 From: Renuka Fernando Date: Tue, 25 Aug 2026 15:56:50 +0530 Subject: [PATCH 2/2] ci: trigger cloud release on push instead of pull_request Switch the Platform API cloud-release trigger from `pull_request: [closed]` to `push` on the release branches. A pull_request run for a PR opened from a fork gets no repository secrets, so merges of fork PRs failed with the webhook secrets unset. A push (which a merge produces) runs with full secret access and executes the workflow version on the pushed branch. Drop the now-unneeded merged-PR `if:` guard and the pull_request-specific BRANCH/COMMIT expressions in favour of github.ref_name / github.sha. Signed-off-by: Renuka Fernando --- .../workflows/platform-api-cloud-release.yml | 29 +++++++++---------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/.github/workflows/platform-api-cloud-release.yml b/.github/workflows/platform-api-cloud-release.yml index 8dbe5ec380..19b333b83f 100644 --- a/.github/workflows/platform-api-cloud-release.yml +++ b/.github/workflows/platform-api-cloud-release.yml @@ -1,22 +1,22 @@ name: Platform API Cloud Release # The cloud image is built and pushed to ACR by an Azure DevOps pipeline. This -# workflow no longer builds anything: on a merge into a release branch (main or -# platform-api/v0.10.x) it just calls the Azure pipeline's incoming webhook, -# passing the repo + branch to build. The payload is authenticated with an -# HMAC-SHA1 signature. +# workflow no longer builds anything: on a push to a release branch (main or +# platform-api/v0.10.x) — which a merge produces — it just calls the Azure +# pipeline's incoming webhook, passing the repo + branch to build. The payload +# is authenticated with an HMAC-SHA1 signature. # -# NOTE: pull_request runs the workflow from the PR's base branch, so this file -# must be kept identical on every branch listed under `branches:` below. +# Using `push` (not `pull_request: closed`) means the run has access to secrets +# even when merging a PR opened from a fork, and the workflow that runs is the +# version on the pushed branch. # # Required GitHub secrets: -# AZURE_WEBHOOK_URL - https://dev.azure.com//_apis/public/distributedtask/webhooks/platform-api-cloud-release?api-version=6.0-preview +# AZURE_WEBHOOK_URL - https://dev.azure.com//_apis/public/distributedtask/webhooks/PlatformApiCloudReleaseWebhook?api-version=6.0-preview # AZURE_WEBHOOK_SECRET - the shared secret configured on the Incoming WebHook service connection on: - # Fire when a PR is merged into a release branch... - pull_request: - types: [closed] + # Fire on a push to a release branch (merging a PR produces such a push)... + push: branches: - main - platform-api/v0.10.x @@ -38,17 +38,16 @@ concurrency: jobs: trigger-azure-build: runs-on: ubuntu-latest - # On pull_request only run for actual merges (not closed-without-merge). - if: github.event_name == 'workflow_dispatch' || github.event.pull_request.merged == true steps: - name: Trigger Azure DevOps pipeline webhook env: AZURE_WEBHOOK_URL: ${{ secrets.AZURE_WEBHOOK_URL }} AZURE_WEBHOOK_SECRET: ${{ secrets.AZURE_WEBHOOK_SECRET }} REPO_URL: ${{ github.server_url }}/${{ github.repository }} - # base.ref/merge_commit_sha for merges; ref_name/sha for manual runs. - BRANCH: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.ref || github.ref_name }} - COMMIT: ${{ github.event_name == 'pull_request' && github.event.pull_request.merge_commit_sha || github.sha }} + # push and workflow_dispatch both expose the branch as ref_name and + # its HEAD (the merge commit, for a PR merge) as sha. + BRANCH: ${{ github.ref_name }} + COMMIT: ${{ github.sha }} run: | set -euo pipefail if [ -z "${AZURE_WEBHOOK_URL:-}" ] || [ -z "${AZURE_WEBHOOK_SECRET:-}" ]; then