fix(deps): preserve mixed-case materialization paths #4024
Workflow file for this run
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
| # Merge Gate -- single-authority orchestrator that aggregates ALL required | |
| # checks into one verdict for BOTH PR-time and merge-queue contexts. | |
| # Branch protection / merge-queue ruleset requires only this check; this | |
| # workflow polls the Checks API for all underlying checks. | |
| # | |
| # Why this file exists: | |
| # GitHub's required-status-checks model is name-based, not workflow-based. | |
| # Without this gate, every required check would need to be listed in the | |
| # ruleset (and listed again for the merge-queue ruleset) -- adding or | |
| # renaming a check meant editing rulesets. With this gate, the ruleset | |
| # requires only 'gate' and the gate aggregates whatever underlying checks | |
| # we declare in EXPECTED_CHECKS for each event context. | |
| # | |
| # Why both pull_request and merge_group triggers: | |
| # The merge-queue ruleset also requires 'gate'. Without a merge_group | |
| # trigger, the gate check would never fire against the merge-queue temp | |
| # branch SHA and PRs would sit in the queue with 'gate' stuck in | |
| # "Expected -- Waiting for status to be reported" indefinitely | |
| # (observed on PR #899). The merge_group trigger fires the same gate | |
| # logic against the temp branch SHA and aggregates the merge-queue-time | |
| # checks (ci.yml + ci-integration.yml). | |
| # | |
| # Why no pull_request_target dual trigger: | |
| # We tried dual-trigger redundancy in PR #865 to harden against rare | |
| # dropped 'pull_request' webhook deliveries (observed once on PR #856). | |
| # It backfired: 'concurrency: cancel-in-progress' produced TWO check-runs | |
| # per SHA -- one SUCCESS and one CANCELLED -- which poisons branch | |
| # protection's status-check rollup ('CANCELLED' counts as failure -> | |
| # PR BLOCKED). pull_request and merge_group are different event channels | |
| # that target different SHAs, so they don't collide. | |
| # | |
| # Recovery if a webhook is dropped: | |
| # pull_request context: | |
| # - Push an empty commit: git commit --allow-empty -m 'retrigger' && git push | |
| # - Or trigger manually: gh workflow run merge-gate.yml -f pr_number=NNN | |
| # - Or close + reopen the PR. | |
| # merge_group context (NB: pushing a commit will not retrigger the | |
| # merge_group event, only pull_request): | |
| # - Remove the PR from the merge queue and re-add it. | |
| name: Merge Gate | |
| on: | |
| pull_request: | |
| branches: [ main ] | |
| merge_group: | |
| branches: [ main ] | |
| types: [ checks_requested ] | |
| workflow_dispatch: | |
| inputs: | |
| pr_number: | |
| description: 'PR number to re-run the gate against' | |
| required: true | |
| type: string | |
| # Dedup pushes to the same PR / merge-queue entry: cancel any older | |
| # in-flight gate run on the same head. In merge_group context, github.ref | |
| # is refs/heads/gh-readonly-queue/main/pr-N-<sha>, which is unique per | |
| # queue entry -- so cancel-in-progress only cancels rapid push-after-push | |
| # on the same temp branch, never across PR <-> merge_group channels. | |
| concurrency: | |
| group: merge-gate-${{ github.event.pull_request.number || inputs.pr_number || github.ref }} | |
| cancel-in-progress: true | |
| permissions: | |
| contents: read | |
| checks: read | |
| pull-requests: read | |
| jobs: | |
| gate: | |
| name: gate | |
| runs-on: ubuntu-24.04 | |
| # Job timeout sized above the poll budget (TIMEOUT_MIN below) to leave | |
| # headroom for setup/teardown without false-failing the gate. | |
| timeout-minutes: 60 | |
| steps: | |
| - name: Resolve head SHA | |
| id: sha | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| case "${{ github.event_name }}" in | |
| workflow_dispatch) | |
| sha=$(gh api "repos/${{ github.repository }}/pulls/${{ inputs.pr_number }}" --jq '.head.sha') | |
| ;; | |
| merge_group) | |
| # Temp merge commit on the merge-queue temp branch; check | |
| # runs from ci.yml/ci-integration.yml are reported here, NOT | |
| # against the PR head SHA. | |
| sha="${{ github.event.merge_group.head_sha }}" | |
| ;; | |
| *) | |
| sha="${{ github.event.pull_request.head.sha }}" | |
| ;; | |
| esac | |
| if [ -z "$sha" ]; then | |
| echo "::error::Could not resolve head SHA for event ${{ github.event_name }}" | |
| exit 1 | |
| fi | |
| echo "sha=$sha" >> "$GITHUB_OUTPUT" | |
| echo "[merge-gate] event=${{ github.event_name }} resolved head SHA: $sha" | |
| - name: Checkout head | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.sha.outputs.sha }} | |
| sparse-checkout: | | |
| .github/scripts/ci | |
| - name: Wait for all required checks | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| REPO: ${{ github.repository }} | |
| SHA: ${{ steps.sha.outputs.sha }} | |
| EVENT_NAME: ${{ github.event_name }} | |
| # All required checks the gate aggregates, branched by event: | |
| # pull_request / workflow_dispatch -> only ci.yml runs at PR time | |
| # merge_group -> ci.yml AND ci-integration.yml run | |
| # Keep this in sync with the underlying workflows. | |
| # NOTE: 'gate' (this job) MUST NOT appear here -- it would | |
| # deadlock waiting for itself. | |
| # PR context: only the shard jobs gate. Coverage Combine runs | |
| # in parallel as a non-required signal so global 80% drift is | |
| # visible in the PR UI without paying ~3 min of runner- | |
| # allocation latency on the critical path. | |
| # merge_group context: Coverage Combine IS required, so the | |
| # global 80% floor blocks the actual merge. | |
| # Lifecycle Smoke (Linux) is required in BOTH contexts: it's a | |
| # hermetic, ~65-70s ci.yml job (runs on pull_request AND | |
| # merge_group, same as APM Self-Check / NOTICE Drift Check), | |
| # promoting the smallest stable subset of the real | |
| # Consume/Produce/Govern lifecycle contracts -- selected | |
| # declaratively via the `lifecycle_smoke` pytest marker, | |
| # including the direct #2226/#2240 regression tests -- onto | |
| # the PR-time critical path. | |
| # "Windows Compatibility Gate" is also required at BOTH | |
| # PR-time and merge-queue-time: it is the only Windows signal | |
| # that runs before merge (build-release.yml's full Windows | |
| # matrix only runs post-merge on push to main), so it must | |
| # gate the class of Windows-only regressions fixed in | |
| # microsoft/apm#2233 rather than surfacing only after landing | |
| # on main. | |
| EXPECTED_CHECKS: ${{ github.event_name == 'merge_group' && 'Build & Test Shard 1 (Linux),Build & Test Shard 2 (Linux),Coverage Combine (Linux),Windows Compatibility Gate,APM Self-Check,NOTICE Drift Check,Lifecycle Smoke (Linux),Build (Linux),Smoke Test (Linux),Integration Tests (Linux),Release Validation (Linux)' || 'Build & Test Shard 1 (Linux),Build & Test Shard 2 (Linux),Windows Compatibility Gate,APM Self-Check,NOTICE Drift Check,Lifecycle Smoke (Linux)' }} | |
| # Poll budget: ci-integration.yml chains Build -> Smoke -> | |
| # Integration (timeout 20m) -> Release Validation (timeout 20m). | |
| # Theoretical worst case ~50m; observed today ~5m end-to-end. | |
| # Sized at 55m to absorb growth without false-failing the gate. | |
| TIMEOUT_MIN: '55' | |
| # 5s poll keeps perceived gate latency low. With ~3 expected checks | |
| # per poll = ~36 gh API calls/min, well under the 5000/hr quota. | |
| # cancel-in-progress concurrency bounds parallel polling per PR. | |
| POLL_SEC: '5' | |
| run: | | |
| chmod +x .github/scripts/ci/merge_gate_wait.sh | |
| .github/scripts/ci/merge_gate_wait.sh | |