Skip to content

Commit c2e42b2

Browse files
committed
enhance sitemap parity check workflow with improved deployment handling
Signed-off-by: Jessie Ssebuliba <jessiessebuliba@gmail.com>
1 parent 7c86bcc commit c2e42b2

1 file changed

Lines changed: 95 additions & 21 deletions

File tree

.github/workflows/sitemap-parity.yml

Lines changed: 95 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,51 +1,125 @@
11
name: Sitemap Parity
22

3-
# Fires whenever a deployment status changes on any commit — Netlify posts one
4-
# of these every time it finishes a build (both PR previews and prod).
5-
# We only act on successful `deploy-preview` deployments and check every URL
6-
# listed in the current production sitemap against the freshly-deployed
7-
# preview. If a page in prod has become unreachable on the preview, the check
8-
# fails and blocks the PR.
3+
# Ensures every URL currently listed in the production sitemap is still
4+
# reachable on the deployment that will be produced by this branch. Runs on:
5+
# - pull_request -> waits for the Netlify deploy-preview, then checks
6+
# - push to main -> waits for the Netlify production deploy, then checks
7+
#
8+
# In both cases the job blocks until the Netlify deployment for the exact
9+
# commit under test reports success (via GitHub's Deployments API), then runs
10+
# the check against that deploy's target URL. If any prod URL is unreachable
11+
# on the new deploy, the check fails and blocks the merge.
12+
913
on:
10-
deployment_status:
14+
pull_request:
15+
branches: ['main']
16+
push:
17+
branches: ['main']
1118

1219
permissions:
1320
contents: read
14-
# Needed so failed check runs show up on the PR conversation timeline.
15-
statuses: read
21+
deployments: read
1622

1723
concurrency:
18-
group: sitemap-parity-${{ github.event.deployment.sha }}
24+
group: sitemap-parity-${{ github.event.pull_request.head.sha || github.sha }}
1925
cancel-in-progress: true
2026

2127
jobs:
2228
check:
23-
# Only run when a Netlify deploy preview has just succeeded.
24-
if: >-
25-
github.event.deployment_status.state == 'success' &&
26-
startsWith(github.event.deployment.environment, 'deploy-preview')
2729
runs-on: ubuntu-latest
28-
timeout-minutes: 10
30+
timeout-minutes: 20
2931

3032
steps:
31-
- name: Checkout code at the deployed commit
33+
- name: Checkout repository
3234
uses: actions/checkout@v4
3335
with:
34-
ref: ${{ github.event.deployment.sha }}
36+
# For PRs, check out the PR head commit so the script matches what
37+
# Netlify actually deployed. For pushes, this is the pushed commit.
38+
ref: ${{ github.event.pull_request.head.sha || github.sha }}
3539

3640
- name: Setup Node.js
3741
uses: actions/setup-node@v4
3842
with:
3943
node-version: '20'
4044

41-
- name: Check sitemap parity
45+
- name: Determine expected Netlify environment
46+
id: env
47+
run: |
48+
if [ "${{ github.event_name }}" = "pull_request" ]; then
49+
echo "expected=deploy-preview" >> "$GITHUB_OUTPUT"
50+
echo "sha=${{ github.event.pull_request.head.sha }}" >> "$GITHUB_OUTPUT"
51+
else
52+
echo "expected=production" >> "$GITHUB_OUTPUT"
53+
echo "sha=${{ github.sha }}" >> "$GITHUB_OUTPUT"
54+
fi
55+
56+
- name: Wait for Netlify deployment
57+
id: wait
4258
env:
43-
PREVIEW_URL: ${{ github.event.deployment_status.target_url }}
59+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
60+
SHA: ${{ steps.env.outputs.sha }}
61+
EXPECTED_ENV_PREFIX: ${{ steps.env.outputs.expected }}
62+
# Total wait budget in seconds (default 15 min) and poll interval.
63+
WAIT_TIMEOUT: '900'
64+
WAIT_INTERVAL: '15'
4465
run: |
45-
if [ -z "$PREVIEW_URL" ]; then
46-
echo "::error::No preview URL available on this deployment_status event."
66+
set -euo pipefail
67+
echo "Waiting for a successful Netlify deployment on commit $SHA ..."
68+
echo "Expected environment prefix: $EXPECTED_ENV_PREFIX"
69+
70+
deadline=$(( $(date +%s) + WAIT_TIMEOUT ))
71+
preview_url=""
72+
73+
while [ "$(date +%s)" -lt "$deadline" ]; do
74+
# List deployments GitHub knows about for this SHA. Netlify posts
75+
# one per build (deploy-preview-<PR#> for PRs, production for main).
76+
deployments_json=$(gh api \
77+
"repos/${{ github.repository }}/deployments?sha=$SHA&per_page=100")
78+
79+
ids=$(printf '%s' "$deployments_json" \
80+
| jq -r --arg prefix "$EXPECTED_ENV_PREFIX" \
81+
'.[] | select(.environment | startswith($prefix)) | .id')
82+
83+
for id in $ids; do
84+
status_json=$(gh api \
85+
"repos/${{ github.repository }}/deployments/$id/statuses?per_page=100")
86+
latest_state=$(printf '%s' "$status_json" | jq -r '.[0].state // ""')
87+
latest_target=$(printf '%s' "$status_json" | jq -r '.[0].target_url // ""')
88+
latest_env_url=$(printf '%s' "$status_json" | jq -r '.[0].environment_url // ""')
89+
90+
if [ "$latest_state" = "success" ]; then
91+
# Prefer environment_url (canonical site URL) over target_url
92+
# (which Netlify sometimes sets to the deploy log page).
93+
if [ -n "$latest_env_url" ] && [ "$latest_env_url" != "null" ]; then
94+
preview_url="$latest_env_url"
95+
else
96+
preview_url="$latest_target"
97+
fi
98+
if [ -n "$preview_url" ] && [ "$preview_url" != "null" ]; then
99+
echo "Found successful deployment: $id -> $preview_url"
100+
break 2
101+
fi
102+
elif [ "$latest_state" = "failure" ] || [ "$latest_state" = "error" ]; then
103+
echo "::error::Netlify deployment $id reported state=$latest_state for commit $SHA."
104+
exit 1
105+
fi
106+
done
107+
108+
echo "No successful deployment yet, sleeping ${WAIT_INTERVAL}s ..."
109+
sleep "$WAIT_INTERVAL"
110+
done
111+
112+
if [ -z "$preview_url" ]; then
113+
echo "::error::Timed out after ${WAIT_TIMEOUT}s waiting for a Netlify deployment on $SHA."
47114
exit 1
48115
fi
116+
117+
echo "preview_url=$preview_url" >> "$GITHUB_OUTPUT"
118+
119+
- name: Check sitemap parity
120+
env:
121+
PREVIEW_URL: ${{ steps.wait.outputs.preview_url }}
122+
run: |
49123
echo "Preview URL: $PREVIEW_URL"
50124
node scripts/check-sitemap-parity.mjs \
51125
--prod-base=https://open-elements.com \

0 commit comments

Comments
 (0)