diff --git a/.changeset/brown-gifts-sparkle.md b/.changeset/brown-gifts-sparkle.md new file mode 100644 index 00000000..77e38177 --- /dev/null +++ b/.changeset/brown-gifts-sparkle.md @@ -0,0 +1,5 @@ +--- +"@wpengine/hwp-previews-wordpress-plugin": patch +--- + +chore: Changes to the github workflow to automate version updates. No existing changes to previews. diff --git a/.github/scripts/get-plugin-slug.sh b/.github/scripts/get_plugin_slug.sh similarity index 100% rename from .github/scripts/get-plugin-slug.sh rename to .github/scripts/get_plugin_slug.sh diff --git a/.github/scripts/update_composer_package.sh b/.github/scripts/update_composer_package.sh new file mode 100755 index 00000000..b0db1833 --- /dev/null +++ b/.github/scripts/update_composer_package.sh @@ -0,0 +1,304 @@ +#!/bin/bash + +# Composer Package Updater Script +# Usage: ./update_composer_package.sh [package_name] [description] +# 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." + + +set -e + +# Function to display usage +usage() { + echo "Usage: $0 [package_name] [description]" + echo "" + echo "Arguments:" + echo " version - Package version (e.g., 0.0.5)" + echo " release_url - Download URL for the package zip file" + echo " package_name - Optional: Package name (auto-detected from URL if not provided)" + echo " description - Optional: Package description (uses generic default if not provided)" + echo "" + echo "Examples:" + echo " $0 '0.0.2' 'https://github.com/wpengine/hwptoolkit/releases/download/%40wpengine%2Fwpgraphql-webhooks-wordpress-plugin-0.0.2/wp-graphql-webhooks.zip'" + echo "" + echo " With custom package name and description:" + echo " $0 '0.0.5' 'https://example.com/plugin.zip' 'wpengine/my-plugin' 'My custom plugin description'" + echo "" + echo "Note: Updates plugins/package.json file" + exit 1 +} + +# Check if minimum arguments provided +if [ "$#" -lt 2 ]; then + echo "Error: Missing required arguments" + usage +fi + +# Arguments +VERSION="$1" +RELEASE_URL="$2" +PACKAGE_NAME="$3" +DESCRIPTION="$4" +COMPOSER_FILE="plugins/package.json" + +# Function to extract package name from release URL +extract_package_name() { + local url="$1" + + # Extract from URL patterns like: + # https://github.com/wpengine/hwptoolkit/releases/download/%40wpengine%2F{PLUGIN}-wordpress-plugin-{VERSION}/{ZIP_NAME}.zip + + # Method 1: Extract from the release tag (between %40wpengine%2F and -wordpress-plugin) + if [[ "$url" =~ %40wpengine%2F([^-]+)-wordpress-plugin ]]; then + local plugin_name="${BASH_REMATCH[1]}" + echo "wpengine/$plugin_name" + return + fi + + # Method 2: Extract from @wpengine/ format + if [[ "$url" =~ @wpengine/([^-]+)-wordpress-plugin ]]; then + local plugin_name="${BASH_REMATCH[1]}" + echo "wpengine/$plugin_name" + return + fi + + # Method 3: Extract from the zip filename at the end of URL + local filename=$(basename "$url" .zip) + if [[ "$filename" =~ ^(.+)$ ]]; then + # Clean up common prefixes but keep the core name + local clean_name="$filename" + clean_name=$(echo "$clean_name" | sed 's/^hwp-//') + clean_name=$(echo "$clean_name" | sed 's/^wp-//') + clean_name=$(echo "$clean_name" | sed 's/^wpengine-//') + echo "wpengine/$clean_name" + return + fi + + # Method 4: Try to extract from middle part of URL path + if [[ "$url" =~ /([^/]+)\.zip$ ]]; then + local zip_name="${BASH_REMATCH[1]}" + # Remove common prefixes + zip_name=$(echo "$zip_name" | sed 's/^hwp-//') + zip_name=$(echo "$zip_name" | sed 's/^wp-//') + zip_name=$(echo "$zip_name" | sed 's/^wpengine-//') + echo "wpengine/$zip_name" + return + fi + + # Fallback + echo "wpengine/unknown-plugin" +} + +# Function to generate generic description +generate_description() { + local package_name="$1" + echo "A WordPress plugin for headless functionality." +} + +# Auto-detect package name if not provided +if [ -z "$PACKAGE_NAME" ]; then + PACKAGE_NAME=$(extract_package_name "$RELEASE_URL") + echo "Auto-detected package name: $PACKAGE_NAME" +fi + +# Auto-generate description if not provided +if [ -z "$DESCRIPTION" ]; then + DESCRIPTION=$(generate_description "$PACKAGE_NAME") + echo "Using description: $DESCRIPTION" +fi + +echo "Updating composer package:" +echo " Package: $PACKAGE_NAME" +echo " Version: $VERSION" +echo " File: $COMPOSER_FILE" +echo " URL: $RELEASE_URL" +echo " Description: $DESCRIPTION" + +# Create plugins directory if it doesn't exist +mkdir -p "$(dirname "$COMPOSER_FILE")" + +# Create initial package.json if it doesn't exist +if [ ! -f "$COMPOSER_FILE" ]; then + echo "Creating initial $COMPOSER_FILE..." + cat > "$COMPOSER_FILE" << 'EOF' +{ + "packages": {} +} +EOF +fi + +# Validate JSON structure +if ! python3 -m json.tool "$COMPOSER_FILE" >/dev/null 2>&1; then + echo "Error: '$COMPOSER_FILE' is not valid JSON" + exit 1 +fi + +# Function to update package using jq +update_package_jq() { + local package_name="$1" + local version="$2" + local release_url="$3" + local description="$4" + local composer_file="$5" + + # Create the new package version object and sort versions in descending order + jq --arg pkg "$package_name" \ + --arg ver "$version" \ + --arg url "$release_url" \ + --arg desc "$description" \ + ' + # Ensure the packages object exists + if .packages == null then .packages = {} else . end | + + # Ensure the package namespace exists + if .packages[$pkg] == null then .packages[$pkg] = {} else . end | + + # Add/update the version + .packages[$pkg][$ver] = { + "name": $pkg, + "version": $ver, + "type": "wordpress-plugin", + "description": $desc, + "homepage": "https://github.com/wpengine/hwptoolkit", + "license": "GPL-2.0", + "authors": [ + { + "name": "WP Engine Headless OSS Development Team", + "email": "headless-oss@wpengine.com", + "homepage": "https://wpengine.com/" + } + ], + "support": { + "issues": "https://github.com/wpengine/hwptoolkit/issues", + "email": "support@wpengine.com" + }, + "dist": { + "url": $url, + "type": "zip" + }, + "require": { + "composer/installers": "~1.0 || ~2.0" + } + } | + + # Sort versions in descending order (newest first) + .packages[$pkg] = (.packages[$pkg] | to_entries | sort_by(.key | [splits("[.]")] | map(tonumber)) | reverse | from_entries) + ' "$composer_file" > "${composer_file}.tmp" && mv "${composer_file}.tmp" "$composer_file" +} + +# Function to update package using Python (fallback) +update_package_python() { + local package_name="$1" + local version="$2" + local release_url="$3" + local description="$4" + local composer_file="$5" + + python3 << EOF +import json +from packaging import version as pkg_version + +# Read the composer file +with open('$composer_file', 'r') as f: + data = json.load(f) + +# Ensure packages object exists +if 'packages' not in data: + data['packages'] = {} + +# Ensure package namespace exists +if '$package_name' not in data['packages']: + data['packages']['$package_name'] = {} + +# Create the new version entry +data['packages']['$package_name']['$version'] = { + "name": "$package_name", + "version": "$version", + "type": "wordpress-plugin", + "description": "$description", + "homepage": "https://github.com/wpengine/hwptoolkit", + "license": "GPL-2.0", + "authors": [ + { + "name": "WP Engine Headless OSS Development Team", + "email": "headless-oss@wpengine.com", + "homepage": "https://wpengine.com/" + } + ], + "support": { + "issues": "https://github.com/wpengine/hwptoolkit/issues", + "email": "support@wpengine.com" + }, + "dist": { + "url": "$release_url", + "type": "zip" + }, + "require": { + "composer/installers": "~1.0 || ~2.0" + } +} + +# Sort versions in descending order (newest first) +try: + package_versions = data['packages']['$package_name'] + sorted_versions = dict(sorted( + package_versions.items(), + key=lambda x: pkg_version.parse(x[0]), + reverse=True + )) + data['packages']['$package_name'] = sorted_versions +except Exception as e: + # If sorting fails, continue with unsorted versions + print(f"Warning: Could not sort versions: {e}") + +# Write back to file with proper formatting +with open('$composer_file', 'w') as f: + json.dump(data, f, indent=4, separators=(',', ': ')) + +print(f"Successfully updated {package_name} version {version}") +EOF +} + +# Update the package +if command -v jq >/dev/null 2>&1; then + echo "Using jq for JSON manipulation..." + update_package_jq "$PACKAGE_NAME" "$VERSION" "$RELEASE_URL" "$DESCRIPTION" "$COMPOSER_FILE" +else + echo "jq not found, using Python fallback..." + update_package_python "$PACKAGE_NAME" "$VERSION" "$RELEASE_URL" "$DESCRIPTION" "$COMPOSER_FILE" +fi + +# Validate the updated JSON +if ! python3 -m json.tool "$COMPOSER_FILE" >/dev/null 2>&1; then + echo "Error: Updated JSON is invalid" + exit 1 +fi + +echo "✅ Successfully updated $PACKAGE_NAME to version $VERSION" + +# Show the updated section +echo "" +echo "Updated package entry:" +if command -v jq >/dev/null 2>&1; then + jq --arg pkg "$PACKAGE_NAME" --arg ver "$VERSION" '.packages[$pkg][$ver]' "$COMPOSER_FILE" +else + echo "Install jq to see formatted output, or check the file: $COMPOSER_FILE" +fi + +# Optional: Show package summary +echo "" +echo "📦 Package Summary:" +echo " Name: $PACKAGE_NAME" +echo " Version: $VERSION" +echo " Description: $DESCRIPTION" +echo " Download URL: $RELEASE_URL" +echo " File updated: $COMPOSER_FILE" + +# Check if this is a new package or version update +if command -v jq >/dev/null 2>&1; then + EXISTING_VERSIONS=$(jq -r --arg pkg "$PACKAGE_NAME" '.packages[$pkg] // {} | keys | length' "$COMPOSER_FILE") + if [ "$EXISTING_VERSIONS" -gt 1 ]; then + echo " Status: Updated existing package (now has $EXISTING_VERSIONS versions)" + else + echo " Status: Added new package" + fi +fi diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index 48e486cf..e656bd22 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -31,7 +31,7 @@ jobs: - name: Get changed plugin directory id: plugin run: | - bash .github/scripts/get-plugin-slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} + bash .github/scripts/get_plugin_slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} - name: Detect changed plugins with quality config id: detect diff --git a/.github/workflows/codeception.yml b/.github/workflows/codeception.yml index c91c0a3f..db4816c3 100644 --- a/.github/workflows/codeception.yml +++ b/.github/workflows/codeception.yml @@ -38,7 +38,7 @@ jobs: - name: Get changed plugin directory id: plugin run: | - bash .github/scripts/get-plugin-slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} + bash .github/scripts/get_plugin_slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} - name: Detect changed plugins with quality config id: detect diff --git a/.github/workflows/create-release-branch.yml b/.github/workflows/create-release-branch.yml index 4c1a001e..c2759e8a 100644 --- a/.github/workflows/create-release-branch.yml +++ b/.github/workflows/create-release-branch.yml @@ -45,7 +45,7 @@ jobs: - name: Get changed plugin directory id: plugin run: | - bash .github/scripts/get-plugin-slug.sh release + bash .github/scripts/get_plugin_slug.sh release - name: Validate plugin detection @@ -71,6 +71,53 @@ jobs: # Apply version bumps from changesets pnpm changeset version + # Only run if both package.json and composer.json exist for the plugin + if [ -f "plugins/${{ steps.plugin.outputs.slug }}/package.json" ] && [ -f "plugins/${{ steps.plugin.outputs.slug }}/composer.json" ]; then + echo "Both package.json and composer.json found for ${{ steps.plugin.outputs.slug }}" + + # Run version script for the plugin if it exists + if cat "plugins/${{ steps.plugin.outputs.slug }}/package.json" | grep -q '"version".*:'; then + echo "Running version script for ${{ steps.plugin.outputs.slug }}" + cd "plugins/${{ steps.plugin.outputs.slug }}" + npm run version + cd ../.. + else + echo "No version script found for ${{ steps.plugin.outputs.slug }}" + fi + + # Get new version from plugin's package.json + NEW_VERSION=$(jq -r '.version' "plugins/${{ steps.plugin.outputs.slug }}/package.json") + + # Build the download URL + # e.g. https://github.com/wpengine/hwptoolkit/releases/download/%40wpengine%2Fhwp-previews-wordpress-plugin-0.0.5/hwp-previews.zip + # Get the "name" field from plugin's package.json and URL encode it + PKG_NAME=$(jq -r '.name' "plugins/${{ steps.plugin.outputs.slug }}/package.json") + ENCODED_PKG_NAME=$(python3 -c "import urllib.parse,sys; print(urllib.parse.quote(sys.argv[1], safe=''))" "$PKG_NAME") + + # Format is [github-repository]/releases/download/[encoded-package-name]-[version]/[plugin-slug].zip + RELEASE_URL="https://github.com/wpengine/hwptoolkit/releases/download/${ENCODED_PKG_NAME}-${NEW_VERSION}/${{ steps.plugin.outputs.slug }}.zip" + + # Get plugin description from plugin's composer.json + DESCRIPTION=$(jq -r '.description // empty' "plugins/${{ steps.plugin.outputs.slug }}/composer.json") + + # Run the composer package update script + # Get the "name" field from plugin's composer.json + COMPOSER_NAME=$(jq -r '.name' "plugins/${{ steps.plugin.outputs.slug }}/composer.json") + if [ -n "$NEW_VERSION" ] && [ -n "$RELEASE_URL" ] && [ -n "$COMPOSER_NAME" ] && [ -n "$DESCRIPTION" ]; then + .github/scripts/update_composer_package.sh "$NEW_VERSION" "$RELEASE_URL" "$COMPOSER_NAME" "$DESCRIPTION" + else + echo "Error: Missing required values for update_composer_package.sh" + echo "NEW_VERSION: $NEW_VERSION" + echo "RELEASE_URL: $RELEASE_URL" + echo "COMPOSER_NAME: $COMPOSER_NAME" + echo "DESCRIPTION: $DESCRIPTION" + exit 1 + fi + + else + echo "package.json and/or composer.json not found for plugin ${{ steps.plugin.outputs.slug }}. Skipping version and composer update steps." + fi + # Configure git git config user.name "github-actions" git config user.email "github-actions@github.com" diff --git a/.github/workflows/e2e-test.yml b/.github/workflows/e2e-test.yml index 9d51bf5b..dd6c6986 100644 --- a/.github/workflows/e2e-test.yml +++ b/.github/workflows/e2e-test.yml @@ -37,7 +37,7 @@ jobs: - name: Get changed plugin directory id: plugin run: | - bash .github/scripts/get-plugin-slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} + bash .github/scripts/get_plugin_slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} - name: Detect changed plugin with E2E config id: detect diff --git a/.github/workflows/plugin-artifact-for-pr.yml b/.github/workflows/plugin-artifact-for-pr.yml index f22025bb..657dc279 100644 --- a/.github/workflows/plugin-artifact-for-pr.yml +++ b/.github/workflows/plugin-artifact-for-pr.yml @@ -20,7 +20,7 @@ jobs: - name: Get changed plugin directory id: plugin run: | - bash .github/scripts/get-plugin-slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} + bash .github/scripts/get_plugin_slug.sh ${{ github.event.pull_request.base.sha }} ${{ github.sha }} - name: Create plugin artifact uses: ./.github/actions/create-plugin-artifact diff --git a/plugins/hwp-previews/composer.json b/plugins/hwp-previews/composer.json index bbaa89fa..ad2169ac 100644 --- a/plugins/hwp-previews/composer.json +++ b/plugins/hwp-previews/composer.json @@ -3,7 +3,7 @@ "type": "wordpress-plugin", "description": "A WordPress plugin for headless previews.", "license": "GPL-2.0", - "version": "0.0.4", + "version": "0.0.5", "authors": [ { "name": "WP Engine Headless OSS Development Team", diff --git a/plugins/hwp-previews/hwp-previews.php b/plugins/hwp-previews/hwp-previews.php index d1ad3e0f..7cd11093 100644 --- a/plugins/hwp-previews/hwp-previews.php +++ b/plugins/hwp-previews/hwp-previews.php @@ -7,7 +7,7 @@ * Author: WPEngine Headless OSS Team * Author URI: https://github.com/wpengine * Update URI: https://github.com/wpengine/hwptoolkit - * Version: 0.0.4 + * Version: 0.0.5 * Text Domain: hwp-previews * Domain Path: /languages * Requires at least: 6.0 @@ -67,7 +67,7 @@ function hwp_previews_init(): void { */ function hwp_previews_constants(): void { if ( ! defined( 'HWP_PREVIEWS_VERSION' ) ) { - define( 'HWP_PREVIEWS_VERSION', '0.0.4' ); + define( 'HWP_PREVIEWS_VERSION', '0.0.5' ); } if ( ! defined( 'HWP_PREVIEWS_PLUGIN_DIR' ) ) { diff --git a/plugins/hwp-previews/package.json b/plugins/hwp-previews/package.json index 60907a81..961c121b 100644 --- a/plugins/hwp-previews/package.json +++ b/plugins/hwp-previews/package.json @@ -8,7 +8,7 @@ "test:e2e": "wp-scripts test-playwright --config tests/e2e/playwright.config.js", "test:e2e:debug": "npm run test:e2e -- --debug", "wp-env": "wp-env", - "version": "./scripts/sync-versions.sh" + "version": "./bin/sync-package-version.sh" }, "keywords": [], "author": "wpengine", diff --git a/plugins/hwp-previews/readme.txt b/plugins/hwp-previews/readme.txt index d6583eb0..c71f48f5 100644 --- a/plugins/hwp-previews/readme.txt +++ b/plugins/hwp-previews/readme.txt @@ -4,7 +4,7 @@ Tags: GraphQL, Headless, Previews, WPGraphQL, React, Rest Requires at least: 6.0 Tested up to: 6.8.1 Requires PHP: 7.4 -Stable tag: 0.0.4 +Stable tag: 0.0.5 License: GPL-2.0 License URI: https://www.gnu.org/licenses/gpl-2.0.html diff --git a/plugins/package.json b/plugins/package.json new file mode 100644 index 00000000..ec74f764 --- /dev/null +++ b/plugins/package.json @@ -0,0 +1,86 @@ +{ + "packages": { + "wpengine/previews": { + "0.0.5": { + "name": "wpengine/previews", + "version": "0.0.5", + "type": "wordpress-plugin", + "description": "A WordPress plugin for headless previews.", + "homepage": "https://github.com/wpengine/hwptoolkit", + "license": "GPL-2.0", + "authors": [ + { + "name": "WP Engine Headless OSS Development Team", + "email": "headless-oss@wpengine.com", + "homepage": "https://wpengine.com/" + } + ], + "support": { + "issues": "https://github.com/wpengine/hwptoolkit/issues", + "email": "support@wpengine.com" + }, + "dist": { + "url": "https://github.com/wpengine/hwptoolkit/releases/download/%40wpengine%2Fhwp-previews-wordpress-plugin-0.0.5/hwp-previews.zip", + "type": "zip" + }, + "require": { + "composer/installers": "~1.0 || ~2.0" + } + }, + "0.0.4": { + "name": "wpengine/previews", + "version": "0.0.4", + "type": "wordpress-plugin", + "description": "A WordPress plugin for headless previews.", + "homepage": "https://github.com/wpengine/hwptoolkit", + "license": "GPL-2.0", + "authors": [ + { + "name": "WP Engine Headless OSS Development Team", + "email": "headless-oss@wpengine.com", + "homepage": "https://wpengine.com/" + } + ], + "support": { + "issues": "https://github.com/wpengine/hwptoolkit/issues", + "email": "support@wpengine.com" + }, + "dist": { + "url": "https://github.com/wpengine/hwptoolkit/releases/download/%40wpengine%2Fhwp-previews-wordpress-plugin-0.0.4/hwp-previews.zip", + "type": "zip" + }, + "require": { + "composer/installers": "~1.0 || ~2.0" + } + } + }, + "wpengine/wp-graphql-webhooks": { + "0.0.2": { + "name": "wpengine/wp-graphql-webhooks", + "version": "0.0.2", + "type": "wordpress-plugin", + "description": "Headless webhooks for WPGraphQL", + "homepage": "https://github.com/wpengine/hwptoolkit", + "license": "GPL-2.0", + "authors": [ + { + "name": "WP Engine Headless OSS Development Team", + "email": "headless-oss@wpengine.com", + "homepage": "https://wpengine.com/" + } + ], + "support": { + "issues": "https://github.com/wpengine/hwptoolkit/issues", + "email": "support@wpengine.com" + }, + "dist": { + "url": "https://github.com/wpengine/hwptoolkit/releases/download/%40wpengine%2Fwpgraphql-webhooks-wordpress-plugin-0.0.2/wp-graphql-webhooks.zip", + "type": "zip" + }, + "require": { + "composer/installers": "~1.0 || ~2.0" + } + } + } + } +} diff --git a/plugins/wp-graphql-webhooks/package.json b/plugins/wp-graphql-webhooks/package.json index dd9a9972..b6920e9c 100644 --- a/plugins/wp-graphql-webhooks/package.json +++ b/plugins/wp-graphql-webhooks/package.json @@ -5,7 +5,7 @@ "description": "Webhooks solution for WordPress", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", - "version": "./scripts/sync-versions.sh" + "version": "./bin/sync-package-version.sh" }, "keywords": [], "author": "wpengine",