Repository navigation
156 lines (144 loc) · 6.2 KB
/
Copy pathstaging-e2e.yml
File metadata and controls
156 lines (144 loc) · 6.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
name: Protected staging E2E
# Daily, and on demand from main. It used to follow every push to main, and
# about half of each run's billed minutes went to waiting for the staging
# sync. A frontend merge is checked live by the production canary; before a
# backend production deploy, dispatch this from main once staging runs the
# merge: `gh workflow run staging-e2e.yml --ref main`.
on:
schedule:
- cron: "11 7 * * *"
workflow_dispatch:
permissions:
# Reads the Quality runs for the main commit under test.
actions: read
contents: read
# Waits for the staging-sync commit status set by the VPS sync.
statuses: read
concurrency:
group: protected-staging-e2e-main
cancel-in-progress: false
jobs:
# Staging is one shared backend that the VPS sync (docs/staging.md) moves to
# each new main commit and marks with a staging-sync commit status. Test a
# commit only once staging runs it, and skip a commit that main has already
# moved past: staging runs the newer backend, and the newer commit's run
# tests it.
staging-sync-gate:
# A scheduled run's ref is main; a dispatch must choose main.
if: github.ref == 'refs/heads/main' && vars.STAGING_E2E_ENABLED == 'true'
runs-on: ubuntu-latest
timeout-minutes: 25
outputs:
current: ${{ steps.wait.outputs.current }}
steps:
- name: Wait for staging to sync this commit
id: wait
env:
GH_TOKEN: ${{ github.token }}
SHA: ${{ github.sha }}
shell: bash
run: |
for _ in $(seq 1 40); do
main="$(gh api "repos/${GITHUB_REPOSITORY}/commits/main" --jq .sha)"
if [ "$main" != "$SHA" ]; then
echo "::notice::main moved on to ${main}; staging runs that backend, and its own run tests it. Skipping ${SHA}."
echo "current=false" >> "$GITHUB_OUTPUT"
exit 0
fi
state="$(gh api "repos/${GITHUB_REPOSITORY}/commits/${SHA}/statuses" \
--jq '[.[] | select(.context == "staging-sync")][0].state // "missing"')"
case "$state" in
success)
echo "Staging is synced with ${SHA}."
echo "current=true" >> "$GITHUB_OUTPUT"
exit 0 ;;
failure|error)
echo "::error::Staging sync failed for ${SHA}. See the open 'Staging is out of sync with main' issue."
exit 1 ;;
esac
sleep 30
done
echo "::error::No staging-sync status for ${SHA} after 20 minutes. Is debatelab-staging-sync.timer running on the VPS? See docs/staging.md."
exit 1
staging-e2e:
needs: staging-sync-gate
if: needs.staging-sync-gate.outputs.current == 'true'
runs-on: ubuntu-latest
# Bounds how long the VPS sync holds off for this run (ops/staging-sync/run.sh).
timeout-minutes: 30
environment: staging
steps:
# "Re-run failed jobs" skips the gate, so check again on every attempt.
- name: Confirm staging still runs this commit
env:
GH_TOKEN: ${{ github.token }}
SHA: ${{ github.sha }}
shell: bash
run: |
main="$(gh api "repos/${GITHUB_REPOSITORY}/commits/main" --jq .sha)"
state="$(gh api "repos/${GITHUB_REPOSITORY}/commits/${SHA}/statuses" \
--jq '[.[] | select(.context == "staging-sync")][0].state // "missing"')"
if [ "$main" != "$SHA" ] || [ "$state" != "success" ]; then
echo "::error::Staging no longer runs ${SHA} (main is ${main}, staging-sync is ${state}). Rerun the newest main commit's run instead."
exit 1
fi
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# A commit merged just before the schedule can reach staging while its
# Quality run is still queued or running, so wait for it to finish.
- name: Verify the commit passed the quality workflow
env:
GH_TOKEN: ${{ github.token }}
shell: bash
run: |
for _ in $(seq 1 30); do
read -r status conclusion < <(gh api \
"repos/${GITHUB_REPOSITORY}/actions/workflows/deploy.yml/runs?head_sha=${GITHUB_SHA}&event=push&per_page=1" \
--jq '.workflow_runs[0] // {} | "\(.status // "missing") \(.conclusion // "none")"') || true
case "$status" in
completed)
if [ "$conclusion" = success ]; then echo "Quality passed for ${GITHUB_SHA}."; exit 0; fi
echo "::error::Quality ended in ${conclusion} for main commit ${GITHUB_SHA}"
exit 1 ;;
missing)
echo "::error::Main commit ${GITHUB_SHA} has no push run of the Quality workflow"
exit 1 ;;
esac
sleep 20
done
echo "::error::Quality did not finish for ${GITHUB_SHA} within 10 minutes"
exit 1
- name: Set up Node
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
with:
node-version: 22
- name: Install dependencies
run: npm ci
- name: Install Chromium
run: npx playwright install --with-deps chromium
- name: Verify protected variables are present
shell: bash
env:
STAGING_SUPABASE_URL: ${{ secrets.STAGING_SUPABASE_URL }}
STAGING_SUPABASE_ANON_KEY: ${{ secrets.STAGING_SUPABASE_ANON_KEY }}
STAGING_DEMO_CODE: ${{ secrets.STAGING_DEMO_CODE }}
run: |
missing=0
for name in STAGING_SUPABASE_URL STAGING_SUPABASE_ANON_KEY STAGING_DEMO_CODE; do
if [ -z "${!name}" ]; then
echo "::error::$name is not configured in the staging environment"
missing=1
fi
done
exit "$missing"
- name: Protected staging browser tests
env:
CI: 1
PORT: 18080
PLAYWRIGHT_BASE_URL: http://127.0.0.1:18080
STAGING_SUPABASE_URL: ${{ secrets.STAGING_SUPABASE_URL }}
STAGING_SUPABASE_ANON_KEY: ${{ secrets.STAGING_SUPABASE_ANON_KEY }}
STAGING_DEMO_CODE: ${{ secrets.STAGING_DEMO_CODE }}
run: npm run test:e2e:staging