Skip to content

Commit c913ecd

Browse files
committed
chore: add "Verify Release" workflow to automate post-release checks
1 parent 76b040a commit c913ecd

2 files changed

Lines changed: 195 additions & 16 deletions

File tree

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# When a release is published, verify that the release pipeline delivered
2+
# everything: the distributable repos, the new framework version on
3+
# Packagist, and the user guide with its ePub.
4+
#
5+
# Use "Run workflow" with the release tag to verify an existing release.
6+
name: Verify Release
7+
8+
on:
9+
release:
10+
types: [published]
11+
workflow_dispatch:
12+
inputs:
13+
version:
14+
description: The release tag to verify (e.g., v4.7.5)
15+
type: string
16+
required: true
17+
18+
permissions:
19+
contents: read
20+
21+
env:
22+
TAG: ${{ github.event.release.tag_name || inputs.version }}
23+
PUBLISHED_AT: ${{ github.event.release.published_at }}
24+
25+
jobs:
26+
wait-for-deploy:
27+
name: Wait for distributables deploy
28+
if: github.repository == 'codeigniter4/CodeIgniter4'
29+
runs-on: ubuntu-24.04
30+
timeout-minutes: 30
31+
permissions:
32+
actions: read
33+
contents: read
34+
35+
steps:
36+
- name: Wait for "Deploy Distributable Repos" to succeed
37+
env:
38+
GH_TOKEN: ${{ github.token }}
39+
run: |
40+
# On workflow_dispatch the event carries no publish time.
41+
if [ -z "${PUBLISHED_AT}" ]; then
42+
PUBLISHED_AT=$(gh api "repos/${{ github.repository }}/releases/tags/${TAG}" --jq '.published_at')
43+
echo "Resolved published_at=${PUBLISHED_AT} for ${TAG}."
44+
fi
45+
46+
query="repos/${{ github.repository }}/actions/workflows/deploy-distributables.yml/runs?event=release&per_page=1&created=>=${PUBLISHED_AT}"
47+
48+
while true; do
49+
run=$(gh api "${query}" --jq '.workflow_runs[0] | "\(.status) \(.conclusion)"' || true)
50+
status=${run% *}
51+
conclusion=${run#* }
52+
echo "Deploy Distributable Repos: status=${status:-not found} conclusion=${conclusion:-n/a}"
53+
54+
if [ "${status}" = "completed" ]; then
55+
if [ "${conclusion}" = "success" ]; then
56+
exit 0
57+
fi
58+
59+
echo "Deploy Distributable Repos did not succeed."
60+
exit 1
61+
fi
62+
63+
sleep 30
64+
done
65+
66+
appstarter:
67+
name: Install and test appstarter
68+
needs: wait-for-deploy
69+
runs-on: ubuntu-24.04
70+
timeout-minutes: 45
71+
72+
steps:
73+
- name: Setup PHP
74+
uses: shivammathur/setup-php@f3e473d116dcccaddc5834248c87452386958240 # 2.37.2
75+
with:
76+
php-version: '8.2'
77+
tools: composer
78+
extensions: intl, gd
79+
coverage: none
80+
81+
- name: Wait for Packagist to serve the new framework version
82+
run: |
83+
version="${TAG#v}"
84+
85+
for i in $(seq 1 30); do
86+
if curl -fsSL https://repo.packagist.org/p2/codeigniter4/framework.json \
87+
| jq -e --arg version "v${version}" \
88+
'.packages."codeigniter4/framework" | map(select(.version == $version)) | length > 0' > /dev/null; then
89+
echo "Packagist serves codeigniter4/framework v${version}."
90+
exit 0
91+
fi
92+
93+
echo "Attempt ${i}: v${version} is not yet on Packagist."
94+
sleep 60
95+
done
96+
97+
echo "Timed out waiting for Packagist to serve v${version}."
98+
exit 1
99+
100+
- name: Install appstarter
101+
run: composer create-project codeigniter4/appstarter release-test --no-interaction
102+
103+
- name: Verify the framework version
104+
working-directory: release-test
105+
run: |
106+
version="${TAG#v}"
107+
installed=$(composer show codeigniter4/framework --format=json | jq -r '.versions[0]')
108+
echo "Installed codeigniter4/framework: ${installed}"
109+
110+
if [ "${installed}" != "v${version}" ]; then
111+
echo "Expected v${version}."
112+
exit 1
113+
fi
114+
115+
- name: Test appstarter
116+
working-directory: release-test
117+
run: composer test
118+
119+
userguide:
120+
name: Verify user guide deployment
121+
needs: wait-for-deploy
122+
runs-on: ubuntu-24.04
123+
timeout-minutes: 30
124+
125+
steps:
126+
- name: Check that the ePub was added
127+
env:
128+
GH_TOKEN: ${{ github.token }}
129+
run: |
130+
version="${TAG#v}"
131+
132+
for i in $(seq 1 30); do
133+
if gh api "repos/codeigniter4/userguide/contents/CodeIgniter${version}.epub" --jq '.name' > /dev/null 2>&1; then
134+
echo "CodeIgniter${version}.epub is in the userguide repo."
135+
exit 0
136+
fi
137+
138+
echo "Attempt ${i}: CodeIgniter${version}.epub is not yet in the userguide repo."
139+
sleep 30
140+
done
141+
142+
echo "Timed out waiting for CodeIgniter${version}.epub."
143+
exit 1
144+
145+
- name: Check that the user guide workflows succeeded
146+
env:
147+
GH_TOKEN: ${{ github.token }}
148+
run: |
149+
# On workflow_dispatch the event carries no publish time.
150+
if [ -z "${PUBLISHED_AT}" ]; then
151+
PUBLISHED_AT=$(gh api "repos/${{ github.repository }}/releases/tags/${TAG}" --jq '.published_at')
152+
echo "Resolved published_at=${PUBLISHED_AT} for ${TAG}."
153+
fi
154+
155+
for workflow in "Deploy Production" "pages build and deployment"; do
156+
query="repos/codeigniter4/userguide/actions/runs?per_page=30&created=>=${PUBLISHED_AT}"
157+
158+
success=""
159+
160+
for _ in $(seq 1 30); do
161+
run=$(gh api "${query}" \
162+
| jq -r --arg name "${workflow}" \
163+
'[.workflow_runs[] | select(.name == $name)][0] | "\(.status) \(.conclusion)"')
164+
status=${run% *}
165+
conclusion=${run#* }
166+
echo "${workflow}: status=${status:-not found} conclusion=${conclusion:-n/a}"
167+
168+
if [ "${status}" = "completed" ]; then
169+
if [ "${conclusion}" = "success" ]; then
170+
success=1
171+
break
172+
fi
173+
174+
echo "\"${workflow}\" did not succeed."
175+
exit 1
176+
fi
177+
178+
sleep 30
179+
done
180+
181+
if [ -z "${success}" ]; then
182+
echo "Timed out waiting for \"${workflow}\"."
183+
exit 1
184+
fi
185+
done

admin/RELEASE.md

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -171,22 +171,16 @@ existing content.
171171
**Full Changelog**: https://github.com/codeigniter4/CodeIgniter4/compare/v4.x.w...v4.x.x
172172
```
173173
Click the "Generate release notes" button, and get the "New Contributors".
174-
* [ ] Watch for the "Deploy Distributable Repos" action to make sure **framework**,
175-
**appstarter**, and **userguide** get updated
176-
* [ ] Run the following commands to install and test `appstarter` and verify the new
177-
version:
178-
```console
179-
rm -rf release-test
180-
composer create-project codeigniter4/appstarter release-test
181-
cd release-test
182-
composer test && composer info codeigniter4/framework
183-
```
184-
* [ ] Verify that the user guide actions succeeded:
185-
* [ ] "[Deploy Distributable Repos](https://github.com/codeigniter4/CodeIgniter4/actions/workflows/deploy-distributables.yml)", the main repo
186-
* [ ] "[Deploy Production](https://github.com/codeigniter4/userguide/actions/workflows/deploy.yml)", UG repo
187-
* [ ] "[pages-build-deployment](https://github.com/codeigniter4/userguide/actions/workflows/pages/pages-build-deployment)", UG repo
188-
* [ ] Check if "CodeIgniter4.x.x.epub" is added to UG repo. "CodeIgniter.epub" was
189-
created when v4.3.8 was released.
174+
* [ ] Watch the "[Verify Release](https://github.com/codeigniter4/CodeIgniter4/actions/workflows/verify-release.yml)"
175+
workflow and make sure it passes. It does the following:
176+
* Wait for the "[Deploy Distributable Repos](https://github.com/codeigniter4/CodeIgniter4/actions/workflows/deploy-distributables.yml)"
177+
action to update **framework**, **appstarter**, and **userguide**
178+
* Install `appstarter` from Packagist, verify it pulls framework `v4.x.x`,
179+
and run its tests
180+
* Verify that the user guide deployments succeeded ("Deploy Production" and
181+
"pages build and deployment" in the UG repo) and that **CodeIgniter4.x.x.epub**
182+
was added
183+
* If it fails, fix the cause and re-run it via "Run workflow" with the tag `v4.x.x`.
190184
* [ ] Fast-forward `develop` branch to catch the merge commit from `master`
191185
```console
192186
git fetch upstream

0 commit comments

Comments
 (0)