chore(release): prepare v2.6.0 #37
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release WordPress Plugin | |
| on: | |
| push: | |
| tags: | |
| - 'v*.*.*' | |
| permissions: | |
| contents: write | |
| jobs: | |
| build: | |
| name: Build and Release | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Setup PHP | |
| uses: shivammathur/setup-php@accd6127cb78bee3e8082180cb391013d204ef9f # v2 | |
| with: | |
| php-version: '7.4' | |
| extensions: mbstring, intl, curl | |
| tools: composer, wp-cli | |
| - name: Get the version | |
| id: get_version | |
| run: | | |
| VERSION="${GITHUB_REF#refs/tags/v}" | |
| echo "VERSION=$VERSION" >> $GITHUB_ENV | |
| case "$VERSION" in | |
| *-alpha*|*-beta*|*-rc*|*-dev*|*-preview*) | |
| echo "IS_PRERELEASE=true" >> $GITHUB_ENV | |
| ;; | |
| *) | |
| echo "IS_PRERELEASE=false" >> $GITHUB_ENV | |
| ;; | |
| esac | |
| - name: Set up Node.js | |
| uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 | |
| with: | |
| node-version: '20' | |
| cache: 'npm' | |
| - name: Install PHP dependencies | |
| run: composer install | |
| - name: Install Node dependencies | |
| run: npm ci | |
| - name: Verify version matches | |
| run: | | |
| WP_VERSION=$(grep -m 1 " \* Version:" ultimate-multisite.php | sed 's/.*Version:[[:space:]]*//') | |
| README_VERSION=$(grep -m 1 "Stable tag: " readme.txt | awk -F' ' '{print $3}') | |
| PKG_VERSION=$(node -p "require('./package.json').version") | |
| CLASS_VERSION=$(grep -oP "const VERSION = '\K[^']+" inc/class-wp-ultimo.php) | |
| echo "Tag version: ${{ env.VERSION }}" | |
| echo "Plugin header: $WP_VERSION" | |
| echo "readme.txt Stable tag: $README_VERSION" | |
| echo "package.json: $PKG_VERSION" | |
| echo "WP_Ultimo::VERSION: $CLASS_VERSION" | |
| # For pre-releases, only check plugin header, class constant, and package.json | |
| # (readme.txt Stable tag stays at the last stable version) | |
| if [ "${{ env.IS_PRERELEASE }}" = "true" ]; then | |
| if [ "$WP_VERSION" != "${{ env.VERSION }}" ] || [ "$PKG_VERSION" != "${{ env.VERSION }}" ] || [ "$CLASS_VERSION" != "${{ env.VERSION }}" ]; then | |
| echo "Error: Version mismatch detected!" | |
| exit 1 | |
| fi | |
| echo "Pre-release version numbers match: ${{ env.VERSION }}" | |
| else | |
| if [ "$WP_VERSION" != "${{ env.VERSION }}" ] || [ "$README_VERSION" != "${{ env.VERSION }}" ] || [ "$PKG_VERSION" != "${{ env.VERSION }}" ] || [ "$CLASS_VERSION" != "${{ env.VERSION }}" ]; then | |
| echo "Error: Version mismatch detected!" | |
| exit 1 | |
| fi | |
| echo "All version numbers match: ${{ env.VERSION }}" | |
| fi | |
| - name: Run build process | |
| run: npm run build | |
| env: | |
| MU_CLIENT_ID: ${{ secrets.MU_CLIENT_ID }} | |
| MU_CLIENT_SECRET: ${{ secrets.MU_CLIENT_SECRET }} | |
| - name: Rename archive for release | |
| run: | | |
| mkdir -p build | |
| mv ultimate-multisite.zip build/ultimate-multisite-${{ env.VERSION }}.zip | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7 | |
| with: | |
| name: ultimate-multisite-zip | |
| path: build/ultimate-multisite-${{ env.VERSION }}.zip | |
| retention-days: 7 | |
| - name: Create Release | |
| id: create_release | |
| uses: softprops/action-gh-release@153bb8e04406b158c6c84fc1615b65b24149a1fe # v2 | |
| env: | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true | |
| with: | |
| files: | | |
| build/ultimate-multisite-${{ env.VERSION }}.zip | |
| name: Ultimate Multisite ${{ env.VERSION }} | |
| draft: true | |
| prerelease: ${{ env.IS_PRERELEASE == 'true' }} | |
| body: | | |
| # Ultimate Multisite ${{ env.VERSION }} | |
| ## What's Changed | |
| For a complete list of changes, please refer to the [changelog](https://github.com/Multisite-Ultimate/ultimate-multisite/blob/main/readme.txt). | |
| ## Installation | |
| 1. Download the ZIP file from this release | |
| 2. Upload and activate the plugin in your WordPress Network installation | |
| 3. Follow the setup wizard to configure the plugin | |
| ## Notes | |
| - Compatible with WordPress 5.3+ | |
| - Requires PHP 7.4.30+ | |
| - Always backup your site before upgrading | |
| deploy-to-wporg: | |
| name: Deploy to WordPress.org | |
| runs-on: ubuntu-latest | |
| needs: build | |
| # Only deploy stable releases to wp.org (skip pre-releases) | |
| if: ${{ !contains(github.ref, '-alpha') && !contains(github.ref, '-beta') && !contains(github.ref, '-rc') && !contains(github.ref, '-dev') && !contains(github.ref, '-preview') }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get the version | |
| run: | | |
| VERSION="${GITHUB_REF#refs/tags/v}" | |
| echo "VERSION=$VERSION" >> $GITHUB_ENV | |
| - name: Download build artifact | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 | |
| with: | |
| name: ultimate-multisite-zip | |
| path: build/ | |
| - name: Unzip build artifact into workspace | |
| run: | | |
| unzip -o build/ultimate-multisite-${{ env.VERSION }}.zip -d . | |
| - name: Install SVN | |
| run: sudo apt-get update && sudo apt-get install -y subversion | |
| - name: Deploy trunk to WordPress.org SVN | |
| env: | |
| SVN_USERNAME: ${{ secrets.SVN_USERNAME }} | |
| SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} | |
| SLUG: ultimate-multisite | |
| VERSION: ${{ env.VERSION }} | |
| run: | | |
| set -euo pipefail | |
| SVN_URL="https://plugins.svn.wordpress.org/${SLUG}" | |
| SVN_DIR="${HOME}/svn-${SLUG}" | |
| # Step 1: Shallow checkout — only trunk (no tags, no history) | |
| svn checkout --depth=immediates "${SVN_URL}" "${SVN_DIR}" | |
| svn update --set-depth=infinity "${SVN_DIR}/trunk" | |
| # Sync build artifact into trunk | |
| rsync -rc --delete ./ultimate-multisite/ "${SVN_DIR}/trunk/" \ | |
| --exclude='.svn' --exclude='.git' --exclude='.github' | |
| # Ensure readme.txt is in trunk for wp.org metadata | |
| cp readme.txt "${SVN_DIR}/trunk/readme.txt" | |
| # Stage changes in trunk only | |
| cd "${SVN_DIR}" | |
| # Add new files in batches of 500 to avoid arg list / memory limits | |
| # Use '|| true' to prevent grep returning exit 1 (no match) from killing the script under pipefail | |
| svn status trunk | grep '^\?' | awk '{print $2}' > /tmp/svn-new-files.txt || true | |
| NEW_COUNT=$(wc -l < /tmp/svn-new-files.txt) | |
| echo "New files to add: ${NEW_COUNT}" | |
| if [ "${NEW_COUNT}" -gt 0 ]; then | |
| split -l 500 /tmp/svn-new-files.txt /tmp/svn-batch-add- | |
| for batch in /tmp/svn-batch-add-*; do | |
| echo "Adding batch: $(wc -l < "$batch") files" | |
| xargs -r svn add --parents -q < "$batch" | |
| done | |
| fi | |
| # Remove deleted files in batches | |
| svn status trunk | grep '^\!' | awk '{print $2}' > /tmp/svn-del-files.txt || true | |
| DEL_COUNT=$(wc -l < /tmp/svn-del-files.txt) | |
| echo "Deleted files to remove: ${DEL_COUNT}" | |
| if [ "${DEL_COUNT}" -gt 0 ]; then | |
| split -l 500 /tmp/svn-del-files.txt /tmp/svn-batch-del- | |
| for batch in /tmp/svn-batch-del-*; do | |
| echo "Deleting batch: $(wc -l < "$batch") files" | |
| xargs -r svn delete --force -q < "$batch" | |
| done | |
| fi | |
| echo "=== SVN Status (trunk) ===" | |
| svn status trunk > /tmp/svn-status.txt || true | |
| head -50 /tmp/svn-status.txt | |
| CHANGES=$(wc -l < /tmp/svn-status.txt) | |
| echo "Total trunk changes: ${CHANGES}" | |
| if [ "${CHANGES}" -eq 0 ]; then | |
| echo "No changes to commit to trunk" | |
| else | |
| echo "Committing ${CHANGES} changes to WordPress.org SVN..." | |
| svn commit \ | |
| --username "${SVN_USERNAME}" \ | |
| --password "${SVN_PASSWORD}" \ | |
| --no-auth-cache \ | |
| --non-interactive \ | |
| -m "Update trunk to ${VERSION}" 2>&1 || { | |
| echo "::error::SVN commit failed. Check SVN_USERNAME and SVN_PASSWORD secrets." | |
| exit 1 | |
| } | |
| echo "Trunk committed successfully" | |
| fi | |
| - name: Tag release on WordPress.org SVN (server-side copy) | |
| env: | |
| SVN_USERNAME: ${{ secrets.SVN_USERNAME }} | |
| SVN_PASSWORD: ${{ secrets.SVN_PASSWORD }} | |
| SLUG: ultimate-multisite | |
| VERSION: ${{ env.VERSION }} | |
| run: | | |
| set -euo pipefail | |
| SVN_URL="https://plugins.svn.wordpress.org/${SLUG}" | |
| # Check if tag already exists | |
| if svn info "${SVN_URL}/tags/${VERSION}" > /dev/null 2>&1; then | |
| echo "Tag ${VERSION} already exists in SVN — skipping" | |
| exit 0 | |
| fi | |
| # Server-side copy: no download/upload, runs entirely on wp.org SVN server | |
| svn copy \ | |
| "${SVN_URL}/trunk" \ | |
| "${SVN_URL}/tags/${VERSION}" \ | |
| --username "${SVN_USERNAME}" \ | |
| --password "${SVN_PASSWORD}" \ | |
| --no-auth-cache \ | |
| --non-interactive \ | |
| -m "Tag ${VERSION}" | |
| echo "Successfully tagged ${VERSION} on WordPress.org" |