Skip to content

Commit cde71cf

Browse files
authored
Merge pull request #312 from wpengine/feat-add-composer-packages-for-plugins
chore: Adding composer package setup to workflow
2 parents 0b8b35b + 19b64ba commit cde71cf

File tree

14 files changed

+453
-11
lines changed

14 files changed

+453
-11
lines changed

.changeset/brown-gifts-sparkle.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@wpengine/hwp-previews-wordpress-plugin": patch
3+
---
4+
5+
chore: Changes to the github workflow to automate version updates. No existing changes to previews.
Lines changed: 304 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,304 @@
1+
#!/bin/bash
2+
3+
# Composer Package Updater Script
4+
# Usage: ./update_composer_package.sh <version> <release_url> [package_name] [description]
5+
# e.g. .github/scripts/update_composer_package.sh "0.0.5" "https://github.com/wpengine/hwptoolkit/releases/download/%40wpengine%2Fhwp-previews-wordpress-plugin-0.0.5/hwp-previews.zip" "wpengine/previews" "A WordPress plugin for headless previews."
6+
7+
8+
set -e
9+
10+
# Function to display usage
11+
usage() {
12+
echo "Usage: $0 <version> <release_url> [package_name] [description]"
13+
echo ""
14+
echo "Arguments:"
15+
echo " version - Package version (e.g., 0.0.5)"
16+
echo " release_url - Download URL for the package zip file"
17+
echo " package_name - Optional: Package name (auto-detected from URL if not provided)"
18+
echo " description - Optional: Package description (uses generic default if not provided)"
19+
echo ""
20+
echo "Examples:"
21+
echo " $0 '0.0.2' 'https://github.com/wpengine/hwptoolkit/releases/download/%40wpengine%2Fwpgraphql-webhooks-wordpress-plugin-0.0.2/wp-graphql-webhooks.zip'"
22+
echo ""
23+
echo " With custom package name and description:"
24+
echo " $0 '0.0.5' 'https://example.com/plugin.zip' 'wpengine/my-plugin' 'My custom plugin description'"
25+
echo ""
26+
echo "Note: Updates plugins/package.json file"
27+
exit 1
28+
}
29+
30+
# Check if minimum arguments provided
31+
if [ "$#" -lt 2 ]; then
32+
echo "Error: Missing required arguments"
33+
usage
34+
fi
35+
36+
# Arguments
37+
VERSION="$1"
38+
RELEASE_URL="$2"
39+
PACKAGE_NAME="$3"
40+
DESCRIPTION="$4"
41+
COMPOSER_FILE="plugins/package.json"
42+
43+
# Function to extract package name from release URL
44+
extract_package_name() {
45+
local url="$1"
46+
47+
# Extract from URL patterns like:
48+
# https://github.com/wpengine/hwptoolkit/releases/download/%40wpengine%2F{PLUGIN}-wordpress-plugin-{VERSION}/{ZIP_NAME}.zip
49+
50+
# Method 1: Extract from the release tag (between %40wpengine%2F and -wordpress-plugin)
51+
if [[ "$url" =~ %40wpengine%2F([^-]+)-wordpress-plugin ]]; then
52+
local plugin_name="${BASH_REMATCH[1]}"
53+
echo "wpengine/$plugin_name"
54+
return
55+
fi
56+
57+
# Method 2: Extract from @wpengine/ format
58+
if [[ "$url" =~ @wpengine/([^-]+)-wordpress-plugin ]]; then
59+
local plugin_name="${BASH_REMATCH[1]}"
60+
echo "wpengine/$plugin_name"
61+
return
62+
fi
63+
64+
# Method 3: Extract from the zip filename at the end of URL
65+
local filename=$(basename "$url" .zip)
66+
if [[ "$filename" =~ ^(.+)$ ]]; then
67+
# Clean up common prefixes but keep the core name
68+
local clean_name="$filename"
69+
clean_name=$(echo "$clean_name" | sed 's/^hwp-//')
70+
clean_name=$(echo "$clean_name" | sed 's/^wp-//')
71+
clean_name=$(echo "$clean_name" | sed 's/^wpengine-//')
72+
echo "wpengine/$clean_name"
73+
return
74+
fi
75+
76+
# Method 4: Try to extract from middle part of URL path
77+
if [[ "$url" =~ /([^/]+)\.zip$ ]]; then
78+
local zip_name="${BASH_REMATCH[1]}"
79+
# Remove common prefixes
80+
zip_name=$(echo "$zip_name" | sed 's/^hwp-//')
81+
zip_name=$(echo "$zip_name" | sed 's/^wp-//')
82+
zip_name=$(echo "$zip_name" | sed 's/^wpengine-//')
83+
echo "wpengine/$zip_name"
84+
return
85+
fi
86+
87+
# Fallback
88+
echo "wpengine/unknown-plugin"
89+
}
90+
91+
# Function to generate generic description
92+
generate_description() {
93+
local package_name="$1"
94+
echo "A WordPress plugin for headless functionality."
95+
}
96+
97+
# Auto-detect package name if not provided
98+
if [ -z "$PACKAGE_NAME" ]; then
99+
PACKAGE_NAME=$(extract_package_name "$RELEASE_URL")
100+
echo "Auto-detected package name: $PACKAGE_NAME"
101+
fi
102+
103+
# Auto-generate description if not provided
104+
if [ -z "$DESCRIPTION" ]; then
105+
DESCRIPTION=$(generate_description "$PACKAGE_NAME")
106+
echo "Using description: $DESCRIPTION"
107+
fi
108+
109+
echo "Updating composer package:"
110+
echo " Package: $PACKAGE_NAME"
111+
echo " Version: $VERSION"
112+
echo " File: $COMPOSER_FILE"
113+
echo " URL: $RELEASE_URL"
114+
echo " Description: $DESCRIPTION"
115+
116+
# Create plugins directory if it doesn't exist
117+
mkdir -p "$(dirname "$COMPOSER_FILE")"
118+
119+
# Create initial package.json if it doesn't exist
120+
if [ ! -f "$COMPOSER_FILE" ]; then
121+
echo "Creating initial $COMPOSER_FILE..."
122+
cat > "$COMPOSER_FILE" << 'EOF'
123+
{
124+
"packages": {}
125+
}
126+
EOF
127+
fi
128+
129+
# Validate JSON structure
130+
if ! python3 -m json.tool "$COMPOSER_FILE" >/dev/null 2>&1; then
131+
echo "Error: '$COMPOSER_FILE' is not valid JSON"
132+
exit 1
133+
fi
134+
135+
# Function to update package using jq
136+
update_package_jq() {
137+
local package_name="$1"
138+
local version="$2"
139+
local release_url="$3"
140+
local description="$4"
141+
local composer_file="$5"
142+
143+
# Create the new package version object and sort versions in descending order
144+
jq --arg pkg "$package_name" \
145+
--arg ver "$version" \
146+
--arg url "$release_url" \
147+
--arg desc "$description" \
148+
'
149+
# Ensure the packages object exists
150+
if .packages == null then .packages = {} else . end |
151+
152+
# Ensure the package namespace exists
153+
if .packages[$pkg] == null then .packages[$pkg] = {} else . end |
154+
155+
# Add/update the version
156+
.packages[$pkg][$ver] = {
157+
"name": $pkg,
158+
"version": $ver,
159+
"type": "wordpress-plugin",
160+
"description": $desc,
161+
"homepage": "https://github.com/wpengine/hwptoolkit",
162+
"license": "GPL-2.0",
163+
"authors": [
164+
{
165+
"name": "WP Engine Headless OSS Development Team",
166+
"email": "[email protected]",
167+
"homepage": "https://wpengine.com/"
168+
}
169+
],
170+
"support": {
171+
"issues": "https://github.com/wpengine/hwptoolkit/issues",
172+
"email": "[email protected]"
173+
},
174+
"dist": {
175+
"url": $url,
176+
"type": "zip"
177+
},
178+
"require": {
179+
"composer/installers": "~1.0 || ~2.0"
180+
}
181+
} |
182+
183+
# Sort versions in descending order (newest first)
184+
.packages[$pkg] = (.packages[$pkg] | to_entries | sort_by(.key | [splits("[.]")] | map(tonumber)) | reverse | from_entries)
185+
' "$composer_file" > "${composer_file}.tmp" && mv "${composer_file}.tmp" "$composer_file"
186+
}
187+
188+
# Function to update package using Python (fallback)
189+
update_package_python() {
190+
local package_name="$1"
191+
local version="$2"
192+
local release_url="$3"
193+
local description="$4"
194+
local composer_file="$5"
195+
196+
python3 << EOF
197+
import json
198+
from packaging import version as pkg_version
199+
200+
# Read the composer file
201+
with open('$composer_file', 'r') as f:
202+
data = json.load(f)
203+
204+
# Ensure packages object exists
205+
if 'packages' not in data:
206+
data['packages'] = {}
207+
208+
# Ensure package namespace exists
209+
if '$package_name' not in data['packages']:
210+
data['packages']['$package_name'] = {}
211+
212+
# Create the new version entry
213+
data['packages']['$package_name']['$version'] = {
214+
"name": "$package_name",
215+
"version": "$version",
216+
"type": "wordpress-plugin",
217+
"description": "$description",
218+
"homepage": "https://github.com/wpengine/hwptoolkit",
219+
"license": "GPL-2.0",
220+
"authors": [
221+
{
222+
"name": "WP Engine Headless OSS Development Team",
223+
"email": "[email protected]",
224+
"homepage": "https://wpengine.com/"
225+
}
226+
],
227+
"support": {
228+
"issues": "https://github.com/wpengine/hwptoolkit/issues",
229+
"email": "[email protected]"
230+
},
231+
"dist": {
232+
"url": "$release_url",
233+
"type": "zip"
234+
},
235+
"require": {
236+
"composer/installers": "~1.0 || ~2.0"
237+
}
238+
}
239+
240+
# Sort versions in descending order (newest first)
241+
try:
242+
package_versions = data['packages']['$package_name']
243+
sorted_versions = dict(sorted(
244+
package_versions.items(),
245+
key=lambda x: pkg_version.parse(x[0]),
246+
reverse=True
247+
))
248+
data['packages']['$package_name'] = sorted_versions
249+
except Exception as e:
250+
# If sorting fails, continue with unsorted versions
251+
print(f"Warning: Could not sort versions: {e}")
252+
253+
# Write back to file with proper formatting
254+
with open('$composer_file', 'w') as f:
255+
json.dump(data, f, indent=4, separators=(',', ': '))
256+
257+
print(f"Successfully updated {package_name} version {version}")
258+
EOF
259+
}
260+
261+
# Update the package
262+
if command -v jq >/dev/null 2>&1; then
263+
echo "Using jq for JSON manipulation..."
264+
update_package_jq "$PACKAGE_NAME" "$VERSION" "$RELEASE_URL" "$DESCRIPTION" "$COMPOSER_FILE"
265+
else
266+
echo "jq not found, using Python fallback..."
267+
update_package_python "$PACKAGE_NAME" "$VERSION" "$RELEASE_URL" "$DESCRIPTION" "$COMPOSER_FILE"
268+
fi
269+
270+
# Validate the updated JSON
271+
if ! python3 -m json.tool "$COMPOSER_FILE" >/dev/null 2>&1; then
272+
echo "Error: Updated JSON is invalid"
273+
exit 1
274+
fi
275+
276+
echo "✅ Successfully updated $PACKAGE_NAME to version $VERSION"
277+
278+
# Show the updated section
279+
echo ""
280+
echo "Updated package entry:"
281+
if command -v jq >/dev/null 2>&1; then
282+
jq --arg pkg "$PACKAGE_NAME" --arg ver "$VERSION" '.packages[$pkg][$ver]' "$COMPOSER_FILE"
283+
else
284+
echo "Install jq to see formatted output, or check the file: $COMPOSER_FILE"
285+
fi
286+
287+
# Optional: Show package summary
288+
echo ""
289+
echo "📦 Package Summary:"
290+
echo " Name: $PACKAGE_NAME"
291+
echo " Version: $VERSION"
292+
echo " Description: $DESCRIPTION"
293+
echo " Download URL: $RELEASE_URL"
294+
echo " File updated: $COMPOSER_FILE"
295+
296+
# Check if this is a new package or version update
297+
if command -v jq >/dev/null 2>&1; then
298+
EXISTING_VERSIONS=$(jq -r --arg pkg "$PACKAGE_NAME" '.packages[$pkg] // {} | keys | length' "$COMPOSER_FILE")
299+
if [ "$EXISTING_VERSIONS" -gt 1 ]; then
300+
echo " Status: Updated existing package (now has $EXISTING_VERSIONS versions)"
301+
else
302+
echo " Status: Added new package"
303+
fi
304+
fi

.github/workflows/code-quality.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ jobs:
3131
- name: Get changed plugin directory
3232
id: plugin
3333
run: |
34-
bash .github/scripts/get-plugin-slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }}
34+
bash .github/scripts/get_plugin_slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }}
3535
3636
- name: Detect changed plugins with quality config
3737
id: detect

.github/workflows/codeception.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
- name: Get changed plugin directory
3939
id: plugin
4040
run: |
41-
bash .github/scripts/get-plugin-slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }}
41+
bash .github/scripts/get_plugin_slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }}
4242
4343
- name: Detect changed plugins with quality config
4444
id: detect

.github/workflows/create-release-branch.yml

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ jobs:
4545
- name: Get changed plugin directory
4646
id: plugin
4747
run: |
48-
bash .github/scripts/get-plugin-slug.sh release
48+
bash .github/scripts/get_plugin_slug.sh release
4949
5050
5151
- name: Validate plugin detection
@@ -71,6 +71,53 @@ jobs:
7171
# Apply version bumps from changesets
7272
pnpm changeset version
7373
74+
# Only run if both package.json and composer.json exist for the plugin
75+
if [ -f "plugins/${{ steps.plugin.outputs.slug }}/package.json" ] && [ -f "plugins/${{ steps.plugin.outputs.slug }}/composer.json" ]; then
76+
echo "Both package.json and composer.json found for ${{ steps.plugin.outputs.slug }}"
77+
78+
# Run version script for the plugin if it exists
79+
if cat "plugins/${{ steps.plugin.outputs.slug }}/package.json" | grep -q '"version".*:'; then
80+
echo "Running version script for ${{ steps.plugin.outputs.slug }}"
81+
cd "plugins/${{ steps.plugin.outputs.slug }}"
82+
npm run version
83+
cd ../..
84+
else
85+
echo "No version script found for ${{ steps.plugin.outputs.slug }}"
86+
fi
87+
88+
# Get new version from plugin's package.json
89+
NEW_VERSION=$(jq -r '.version' "plugins/${{ steps.plugin.outputs.slug }}/package.json")
90+
91+
# Build the download URL
92+
# e.g. https://github.com/wpengine/hwptoolkit/releases/download/%40wpengine%2Fhwp-previews-wordpress-plugin-0.0.5/hwp-previews.zip
93+
# Get the "name" field from plugin's package.json and URL encode it
94+
PKG_NAME=$(jq -r '.name' "plugins/${{ steps.plugin.outputs.slug }}/package.json")
95+
ENCODED_PKG_NAME=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "$PKG_NAME")
96+
97+
# Format is [github-repository]/releases/download/[encoded-package-name]-[version]/[plugin-slug].zip
98+
RELEASE_URL="https://github.com/wpengine/hwptoolkit/releases/download/${ENCODED_PKG_NAME}-${NEW_VERSION}/${{ steps.plugin.outputs.slug }}.zip"
99+
100+
# Get plugin description from plugin's composer.json
101+
DESCRIPTION=$(jq -r '.description // empty' "plugins/${{ steps.plugin.outputs.slug }}/composer.json")
102+
103+
# Run the composer package update script
104+
# Get the "name" field from plugin's composer.json
105+
COMPOSER_NAME=$(jq -r '.name' "plugins/${{ steps.plugin.outputs.slug }}/composer.json")
106+
if [ -n "$NEW_VERSION" ] && [ -n "$RELEASE_URL" ] && [ -n "$COMPOSER_NAME" ] && [ -n "$DESCRIPTION" ]; then
107+
.github/scripts/update_composer_package.sh "$NEW_VERSION" "$RELEASE_URL" "$COMPOSER_NAME" "$DESCRIPTION"
108+
else
109+
echo "Error: Missing required values for update_composer_package.sh"
110+
echo "NEW_VERSION: $NEW_VERSION"
111+
echo "RELEASE_URL: $RELEASE_URL"
112+
echo "COMPOSER_NAME: $COMPOSER_NAME"
113+
echo "DESCRIPTION: $DESCRIPTION"
114+
exit 1
115+
fi
116+
117+
else
118+
echo "package.json and/or composer.json not found for plugin ${{ steps.plugin.outputs.slug }}. Skipping version and composer update steps."
119+
fi
120+
74121
# Configure git
75122
git config user.name "github-actions"
76123
git config user.email "[email protected]"

0 commit comments

Comments
 (0)