Skip to content

Commit c6a59b6

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 c6a59b6

6 files changed

Lines changed: 237 additions & 0 deletions

File tree

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