Skip to content

Commit 53d9740

Browse files
committed
Add release automation
Add GitHub Actions workflows for the release process: 1. When a draft release is created or edited on GitHub, the prepare-release workflow bumps version numbers, updates the changelog in readme.txt, builds the plugin zip, uploads it to the draft release, and creates a release PR. 2. When the release PR is merged to trunk, the publish-release workflow publishes the draft release and creates the tag. Also add a build script (bin/build-plugin-zip.sh) that assembles the plugin zip by copying the plugin package, resolving the driver symlink, and removing dev-only files.
1 parent f4a9333 commit 53d9740

6 files changed

Lines changed: 246 additions & 0 deletions

File tree

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
name: Prepare release
2+
3+
on:
4+
release:
5+
types: [created, edited]
6+
7+
concurrency:
8+
group: release-prepare-${{ github.event.release.tag_name }}
9+
cancel-in-progress: false
10+
11+
jobs:
12+
prepare-release:
13+
name: Prepare release PR and build plugin zip
14+
if: >-
15+
github.repository == 'WordPress/sqlite-database-integration'
16+
&& github.event.release.draft == true
17+
runs-on: ubuntu-latest
18+
permissions:
19+
contents: write
20+
pull-requests: write
21+
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
with:
26+
ref: trunk
27+
28+
- name: Extract version and changelog
29+
id: release_info
30+
env:
31+
RELEASE_TAG: ${{ github.event.release.tag_name }}
32+
RELEASE_BODY: ${{ github.event.release.body }}
33+
run: |
34+
# Extract version from tag (strip leading "v" if present).
35+
VERSION="${RELEASE_TAG#v}"
36+
echo "version=$VERSION" >> $GITHUB_OUTPUT
37+
38+
# Extract changelog, converting markdown list items to WP readme format.
39+
CHANGELOG=$(echo "$RELEASE_BODY" | sed 's/^- /* /' | sed 's/^[[:space:]]*- /* /')
40+
{
41+
echo "changelog<<CHANGELOG_EOF"
42+
echo "$CHANGELOG"
43+
echo "CHANGELOG_EOF"
44+
} >> $GITHUB_OUTPUT
45+
46+
# Branch name for the release PR.
47+
echo "branch=release/v$VERSION" >> $GITHUB_OUTPUT
48+
49+
- name: Create release branch
50+
env:
51+
BRANCH: ${{ steps.release_info.outputs.branch }}
52+
run: |
53+
git checkout -B "$BRANCH"
54+
55+
- name: Bump version numbers
56+
env:
57+
VERSION: ${{ steps.release_info.outputs.version }}
58+
run: |
59+
# Update version.php
60+
sed -i "s/define( 'SQLITE_DRIVER_VERSION', '.*' );/define( 'SQLITE_DRIVER_VERSION', '$VERSION' );/" \
61+
packages/wp-mysql-on-sqlite/src/version.php
62+
63+
# Update plugin header
64+
sed -i "s/^\( \* Version:\).*/\1 $VERSION/" \
65+
packages/sqlite-database-integration/load.php
66+
67+
# Update readme.txt stable tag
68+
sed -i "s/^Stable tag:.*/Stable tag: $VERSION/" \
69+
packages/sqlite-database-integration/readme.txt
70+
71+
- name: Update changelog in readme.txt
72+
env:
73+
VERSION: ${{ steps.release_info.outputs.version }}
74+
CHANGELOG: ${{ steps.release_info.outputs.changelog }}
75+
run: |
76+
README="packages/sqlite-database-integration/readme.txt"
77+
78+
# Build the new changelog entry.
79+
ENTRY=$(printf "= %s =\n\n%s\n" "$VERSION" "$CHANGELOG")
80+
81+
if grep -q "^== Changelog ==" "$README"; then
82+
# Insert the new entry after the == Changelog == header.
83+
awk -v entry="$ENTRY" '
84+
/^== Changelog ==/ { print; print ""; print entry; next }
85+
{ print }
86+
' "$README" > "$README.tmp" && mv "$README.tmp" "$README"
87+
else
88+
# Add a changelog section at the end.
89+
printf "\n== Changelog ==\n\n%s\n" "$ENTRY" >> "$README"
90+
fi
91+
92+
- name: Commit version bump
93+
env:
94+
VERSION: ${{ steps.release_info.outputs.version }}
95+
BRANCH: ${{ steps.release_info.outputs.branch }}
96+
run: |
97+
git config user.name "github-actions[bot]"
98+
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
99+
git add -A
100+
git commit -m "Bump version to $VERSION"
101+
git push -f origin "$BRANCH"
102+
103+
- name: Build plugin zip
104+
run: composer run build
105+
106+
- name: Upload zip to draft release
107+
env:
108+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
109+
RELEASE_TAG: ${{ github.event.release.tag_name }}
110+
run: |
111+
# Remove any previously uploaded zip.
112+
gh release delete-asset "$RELEASE_TAG" "sqlite-database-integration.zip" --yes 2>/dev/null || true
113+
# Upload the new zip.
114+
gh release upload "$RELEASE_TAG" "build/sqlite-database-integration.zip"
115+
116+
- name: Create or update pull request
117+
id: pr
118+
env:
119+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
120+
VERSION: ${{ steps.release_info.outputs.version }}
121+
BRANCH: ${{ steps.release_info.outputs.branch }}
122+
run: |
123+
# Check if a PR already exists for this branch.
124+
EXISTING_PR=$(gh pr list --head "$BRANCH" --base trunk --json number --jq '.[0].number // empty')
125+
126+
if [ -n "$EXISTING_PR" ]; then
127+
PR_URL=$(gh pr view "$EXISTING_PR" --json url --jq '.url')
128+
echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
129+
else
130+
PR_URL=$(gh pr create \
131+
--base trunk \
132+
--head "$BRANCH" \
133+
--title "Release $VERSION" \
134+
--body "Version bump and changelog update for release $VERSION.")
135+
echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
136+
fi
137+
138+
- name: Add PR link to draft release
139+
env:
140+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
141+
RELEASE_TAG: ${{ github.event.release.tag_name }}
142+
RELEASE_BODY: ${{ github.event.release.body }}
143+
PR_URL: ${{ steps.pr.outputs.pr_url }}
144+
run: |
145+
PR_NOTE="> To publish the release, review and merge: $PR_URL"
146+
147+
# Remove any existing PR note, then append the new one.
148+
CLEAN_BODY=$(echo "$RELEASE_BODY" | grep -v "^> To publish the release, review and merge:")
149+
NEW_BODY=$(printf "%s\n\n%s" "$CLEAN_BODY" "$PR_NOTE")
150+
151+
gh release edit "$RELEASE_TAG" --notes "$NEW_BODY"
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
name: Publish release
2+
3+
on:
4+
pull_request:
5+
types: [closed]
6+
branches: [trunk]
7+
8+
jobs:
9+
publish-release:
10+
name: Publish draft release
11+
if: >-
12+
github.repository == 'WordPress/sqlite-database-integration'
13+
&& github.event.pull_request.merged == true
14+
&& startsWith(github.event.pull_request.head.ref, 'release/')
15+
runs-on: ubuntu-latest
16+
permissions:
17+
contents: write
18+
19+
steps:
20+
- name: Checkout repository
21+
uses: actions/checkout@v4
22+
23+
- name: Extract version from branch name
24+
id: version
25+
env:
26+
BRANCH: ${{ github.event.pull_request.head.ref }}
27+
run: |
28+
# Extract version from branch name (release/v2.3.0 → 2.3.0).
29+
VERSION="${BRANCH#release/v}"
30+
echo "version=$VERSION" >> $GITHUB_OUTPUT
31+
echo "tag=v$VERSION" >> $GITHUB_OUTPUT
32+
33+
- name: Publish draft release
34+
env:
35+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36+
TAG: ${{ steps.version.outputs.tag }}
37+
MERGE_SHA: ${{ github.event.pull_request.merge_commit_sha }}
38+
run: |
39+
# Get the current release body and remove the PR note.
40+
BODY=$(gh release view "$TAG" --json body --jq '.body' 2>/dev/null || echo "")
41+
CLEAN_BODY=$(echo "$BODY" | grep -v "^> To publish the release, review and merge:")
42+
43+
# Publish the release, targeting the merge commit.
44+
gh release edit "$TAG" \
45+
--draft=false \
46+
--target "$MERGE_SHA" \
47+
--notes "$CLEAN_BODY"
48+
49+
- name: Delete release branch
50+
env:
51+
BRANCH: ${{ github.event.pull_request.head.ref }}
52+
run: git push origin --delete "$BRANCH" 2>/dev/null || true

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ composer.lock
55
._.DS_Store
66
.DS_Store
77
._*
8+
/build
89
/wordpress
910
/.claude/settings.local.json

bin/build-plugin-zip.sh

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#!/bin/bash
2+
3+
##
4+
# Build the SQLite Database Integration plugin zip.
5+
#
6+
# This script copies the plugin package into ./build/sqlite-database-integration/,
7+
# resolves the driver symlink, removes dev-only files, and creates a zip archive.
8+
##
9+
10+
set -e
11+
12+
DIR="$(cd "$(dirname "$0")/.." && pwd)"
13+
BUILD_DIR="$DIR/build"
14+
PLUGIN_DIR="$BUILD_DIR/sqlite-database-integration"
15+
ZIP_FILE="$BUILD_DIR/sqlite-database-integration.zip"
16+
17+
# Clean previous build.
18+
rm -rf "$PLUGIN_DIR"
19+
rm -f "$ZIP_FILE"
20+
mkdir -p "$BUILD_DIR"
21+
22+
# Copy the plugin package.
23+
cp -R "$DIR/packages/sqlite-database-integration" "$PLUGIN_DIR"
24+
25+
# Resolve the database symlink — replace it with a real copy of the driver.
26+
rm "$PLUGIN_DIR/wp-includes/database"
27+
cp -R "$DIR/packages/wp-mysql-on-sqlite/src" "$PLUGIN_DIR/wp-includes/database"
28+
29+
# Remove dev-only files.
30+
rm -rf "$PLUGIN_DIR/composer.json"
31+
rm -rf "$PLUGIN_DIR/vendor"
32+
rm -rf "$PLUGIN_DIR/node_modules"
33+
34+
# Create the zip archive.
35+
cd "$BUILD_DIR"
36+
zip -r "$ZIP_FILE" "sqlite-database-integration/" -x "*.DS_Store"
37+
38+
echo "Built: $ZIP_FILE"

composer.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@
3636
"fix-cs": [
3737
"@php ./vendor/bin/phpcbf"
3838
],
39+
"build": [
40+
"./bin/build-plugin-zip.sh"
41+
],
3942
"test": [
4043
"phpunit"
4144
],

phpcs.xml.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
<!-- Directories and third party library exclusions. -->
3333
<exclude-pattern>/vendor/*</exclude-pattern>
3434
<exclude-pattern>/node_modules/*</exclude-pattern>
35+
<exclude-pattern>/build/*</exclude-pattern>
3536
<exclude-pattern>/wordpress/*</exclude-pattern>
3637
<exclude-pattern>/packages/sqlite-database-integration/wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php</exclude-pattern>
3738

0 commit comments

Comments
 (0)