Commit be052facca for woocommerce

commit be052facca419be9e9b1a14c9b1679690091395e
Author: Jorge A. Torres <jorge.torres@automattic.com>
Date:   Mon Dec 15 11:48:54 2025 +0000

    Ensure A-S/WP/PHP version bumps run automatically and are tied to releases (#62371)

    * Improve A-S maintenance workflow

    * Update PHP/WP version bump workflow

    * Improve A-S bump workflow

    * Remove unnecessary output

    * Ensure changelog doesn't exist before creating it

diff --git a/.github/workflows/maintenance-bump-as-requirement.yml b/.github/workflows/maintenance-bump-as-requirement.yml
index d33725e0e0..81cda04cf6 100644
--- a/.github/workflows/maintenance-bump-as-requirement.yml
+++ b/.github/workflows/maintenance-bump-as-requirement.yml
@@ -1,5 +1,7 @@
 name: 'Maintenance: Bump Action Scheduler version'
 on:
+  schedule:
+    - cron: '0 0 * * *' # Runs every day at midnight UTC
   workflow_dispatch:
     inputs:
       version:
@@ -8,9 +10,12 @@ on:
         default: ''

 jobs:
-  bump-version:
-    name: Bump Action Scheduler version
+  check-version:
+    name: Check Action Scheduler version
     runs-on: ubuntu-latest
+    outputs:
+      version: ${{ steps.get-as-version.outputs.version }}
+      should-update: ${{ steps.check-version.outputs.should-update }}
     steps:
     - name: Fetch Action Scheduler version
       id: get-as-version
@@ -34,52 +39,117 @@ jobs:
       uses: actions/checkout@v4
       with:
         ref: trunk
-    - name: Set up dev environment
+    - name: Check if version bump is needed
+      id: check-version
       run: |
         cd plugins/woocommerce
+        current_version=$(jq -r '.require["woocommerce/action-scheduler"]' composer.json)
+        target_version="${{ steps.get-as-version.outputs.version }}"

-        # Install dev packages. Required for changelogger use.
-        composer install --quiet
+        echo "Current Action Scheduler version: $current_version"
+        echo "Target Action Scheduler version: $target_version"

+        if [ "$current_version" = "$target_version" ]; then
+          echo "Action Scheduler is already at version $target_version. No update needed."
+          echo "should-update=false" >> $GITHUB_OUTPUT
+        else
+          echo "Action Scheduler needs to be updated from $current_version to $target_version."
+          echo "should-update=true" >> $GITHUB_OUTPUT
+        fi
+
+  bump-version:
+    name: Bump Action Scheduler version
+    needs: check-version
+    if: needs.check-version.outputs.should-update == 'true'
+    runs-on: ubuntu-latest
+    steps:
+    - name: Check out trunk
+      uses: actions/checkout@v4
+      with:
+        ref: trunk
+    - name: Set up dev environment
+      run: |
         # Configure Git.
         git config --global user.name "github-actions[bot]"
         git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
+
+        # Configure token for Composer.
+        composer config --global github-oauth.github.com "${{ secrets.GITHUB_TOKEN }}"
+
+        # Install dev packages. Required for changelogger use.
+        cd plugins/woocommerce
+        composer install --quiet
     - name: Bump Action Scheduler requirement
+      id: create-pr
       env:
         GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
       run: |
+        # Fetch all branches from origin.
+        git fetch origin
+
+        # Branch name hardcoded to avoid conflicts.
+        branch_name="update-action-scheduler-via-automation"
+
+        # Delete local branch if it exists and create fresh from trunk.
+        git branch -D "$branch_name" 2>/dev/null || true
+        git checkout -b "$branch_name" origin/trunk
+
         cd plugins/woocommerce

         # Update A-S version.
-        jq --tab -r ".require[\"woocommerce/action-scheduler\"] |= \"${{ steps.get-as-version.outputs.version }}\"" composer.json > composer.json.new
+        jq --tab -r ".require[\"woocommerce/action-scheduler\"] |= \"${{ needs.check-version.outputs.version }}\"" composer.json > composer.json.new
         mv composer.json.new composer.json

         if git diff --quiet; then
-          echo "::error::No changes to commit."
-          exit 1
+          echo "No changes to commit."
+          exit 0
         fi

         composer update woocommerce/action-scheduler --no-scripts

-        branch_name="update/action-scheduler-${{ steps.get-as-version.outputs.version }}"
-        git checkout -b ${branch_name}
-
+        rm -f changelog/update-action-scheduler-via-automation
         composer exec -- changelogger add \
           --significance minor \
           --type update \
-          --entry "Update the Action Scheduler package to version ${{ steps.get-as-version.outputs.version }}." \
+          --entry "Update the Action Scheduler package to version ${{ needs.check-version.outputs.version }}." \
           --no-interaction

-        # Push changes.
+        # Commit changes.
         git add composer.lock composer.json changelog/
         git commit \
-          --message "Update Action Scheduler to '${{ steps.get-as-version.outputs.version }}'."
-        git push origin ${branch_name}
-
-        # Open PR.
-        gh pr create \
-          --title 'Bump Action Scheduler version to ${{ steps.get-as-version.outputs.version }}' \
-          --body 'This PR updates the Action Scheduler package requirement for WooCommerce core.' \
-          --base trunk \
-          --head ${branch_name} \
-          --reviewer "${{ github.actor }}"
+          --message "Update Action Scheduler to '${{ needs.check-version.outputs.version }}'."
+
+        # Push only if remote branch doesn't exist or differs from our changes.
+        if ! git ls-remote --exit-code --heads origin "$branch_name" >/dev/null 2>&1 || ! git diff --quiet HEAD origin/"$branch_name"; then
+          echo "Pushing changes to remote branch."
+          git push --force origin "$branch_name"
+        else
+          echo "No changes compared to remote branch. Skipping push."
+        fi
+
+        # Prepare PR content.
+        pr_title="Bump Action Scheduler version to ${{ needs.check-version.outputs.version }}"
+        pr_body="This PR updates the Action Scheduler package requirement for WooCommerce core."
+
+        # Check if PR already exists.
+        pr_number=$(gh pr list --head "$branch_name" --json number --jq '.[0].number' 2>/dev/null || echo "")
+
+        if [[ -n "$pr_number" ]]; then
+          echo "PR #$pr_number already exists. Updating title, body, and milestone."
+
+          gh pr edit "$pr_number" \
+            --title "$pr_title" \
+            --body "$pr_body"
+        else
+          # Get WooCommerce version for milestone from trunk.
+          milestone=$( git show origin/trunk:plugins/woocommerce/woocommerce.php | grep -oP '(?<=Version: )(.+)' | head -n1 | sed 's/\.[0-9]\+\(-dev\)\?$/.0/' )
+
+          echo "Creating new PR."
+          gh pr create \
+            --title "$pr_title" \
+            --body "$pr_body" \
+            --base trunk \
+            --head "$branch_name" \
+            --label 'Release' \
+            --milestone "$milestone"
+        fi
diff --git a/.github/workflows/maintenance-update-version-requirements.yml b/.github/workflows/maintenance-update-version-requirements.yml
index 741adf35f0..b1a7c99883 100644
--- a/.github/workflows/maintenance-update-version-requirements.yml
+++ b/.github/workflows/maintenance-update-version-requirements.yml
@@ -10,88 +10,84 @@ jobs:
     name: Update WordPress and PHP version requirements
     runs-on: ubuntu-latest
     steps:
-      - name: Install SVN
-        run: sudo apt-get -qq install -y subversion
+      - name: Check out trunk
+        uses: actions/checkout@v4
+        with:
+          ref: trunk

-      - name: Get current WordPress version
-        id: wp-version
+      - name: Compute WordPress and PHP versions
+        id: compute-env-versions
         run: |
-          WP_VERSION=$(svn ls https://core.svn.wordpress.org/tags | sort -V | tail -n 1 | tr -d '/')
-          if [[ -z "$WP_VERSION" ]]; then
+          # Fetch latest WP version.
+          wp_version=$(curl -s https://api.wordpress.org/core/version-check/1.7/ | jq -r '.offers[0].current' | sed -E 's/^([0-9]+\.[0-9]+).*/\1/' )
+          if [[ -z "$wp_version" ]]; then
             echo "Failed to get WordPress version"
             exit 1
           fi
-
-          echo "wp_version=$WP_VERSION" >> $GITHUB_OUTPUT
-          echo "Latest WordPress version is $WP_VERSION"

-      - name: Calculate L-1 WordPress version
-        id: wp-previous-version
-        uses: actions/github-script@v7
-        env:
-          WP_VERSION: ${{ steps.wp-version.outputs.wp_version }}
-        with:
-          script: |
-            const version = process.env.WP_VERSION;
-
-            const parts = version.split('.').map(Number);
-            const [major, minor] = parts;
-
-            let previousVersion;
-            if (minor > 0) {
-              previousVersion = `${major}.${minor - 1}`;
-            } else {
-              previousVersion = `${major - 1}.9`;
-            }
-
-            core.info(`Previous WordPress version is ${previousVersion}`);
-            core.setOutput('wp_prev_version', previousVersion);
+          echo "wp_version=$wp_version" >> $GITHUB_OUTPUT
+          echo "Latest WordPress version is $wp_version."

-      - name: Check out trunk
-        uses: actions/checkout@v4
-        with:
-          ref: trunk
+          # Calculate L-1 version.
+          wp_required_version=$(echo "$wp_version - 0.1" | bc)
+          echo "wp_required_version=$wp_required_version" >> $GITHUB_OUTPUT
+          echo "L-1 WordPress version is $wp_required_version."

-      - name: Get minimum PHP version from composer.json
-        id: php-version
-        run: |
-          REQUIRED_PHP=$(jq -r '.config.platform.php' plugins/woocommerce/composer.json)
-          if [[ -z "$REQUIRED_PHP" ]]; then
+          # Get required PHP version.
+          php_version=$(jq -r '.config.platform.php' plugins/woocommerce/composer.json)
+          if [[ -z "$php_version" ]]; then
             echo "Failed to get PHP version from composer.json"
             exit 1
           fi
-
-          echo "required_php_version=$REQUIRED_PHP" >> $GITHUB_OUTPUT
-          echo "Required PHP version from composer.json: $REQUIRED_PHP"
+
+          echo "php_version=$php_version" >> $GITHUB_OUTPUT
+          echo "Required PHP version from composer.json: $php_version"

       - name: Set up dev environment
         run: |
+          # Configure Git.
+          git config --global user.name "github-actions[bot]"
+          git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
+
+          # Configure token for Composer.
+          composer config --global github-oauth.github.com "${{ secrets.GITHUB_TOKEN }}"
+
           cd plugins/woocommerce

           # Install dev packages. Required for changelogger use.
           composer install --quiet

-          # Configure Git.
-          git config --global user.name "github-actions[bot]"
-          git config --global user.email "41898282+github-actions[bot]@users.noreply.github.com"
-
-      - name: Update version requirements and create PR
-        id: update-pr
+      - name: Update version requirements
+        id: update-versions
         env:
-          WP_PREV_VERSION: ${{ steps.wp-previous-version.outputs.wp_prev_version }}
-          PHP_VERSION: ${{ steps.php-version.outputs.required_php_version }}
+          PHP_VERSION: ${{ steps.compute-env-versions.outputs.php_version }}
+          WP_VERSION: ${{ steps.compute-env-versions.outputs.wp_version }}
+          WP_REQUIRED_VERSION: ${{ steps.compute-env-versions.outputs.wp_required_version }}
           GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
         run: |
+          # Fetch all branches from origin.
+          git fetch origin
+
+          # Branch name hardcoded to avoid conflicts.
+          branch_name="update-version-requirements-wp-and-php-via-automation"
+
+          # Delete local branch if it exists and create fresh from trunk.
+          git branch -D "$branch_name" 2>/dev/null || true
+          git checkout -b "$branch_name" origin/trunk
+
+          cd plugins/woocommerce
+
           # Update the version requirements in woocommerce.php
-          WOOCOMMERCE_FILE="plugins/woocommerce/woocommerce.php"
-          sed -i "s/\* Requires at least: [0-9.]*/\* Requires at least: $WP_PREV_VERSION/" "$WOOCOMMERCE_FILE"
+          WOOCOMMERCE_FILE="woocommerce.php"
+          sed -i "s/\* Requires at least: [0-9.]*/\* Requires at least: $WP_REQUIRED_VERSION/" "$WOOCOMMERCE_FILE"
           sed -i "s/\* Requires PHP: [0-9.]*/\* Requires PHP: $PHP_VERSION/" "$WOOCOMMERCE_FILE"

           # Update the version requirements in readme.txt
-          README_FILE="plugins/woocommerce/readme.txt"
-          sed -i "s/Requires at least: [0-9.]*/Requires at least: $WP_PREV_VERSION/" "$README_FILE"
+          README_FILE="readme.txt"
+          sed -i "s/Requires at least: [0-9.]*/Requires at least: $WP_REQUIRED_VERSION/" "$README_FILE"
+          sed -i "s/Tested up to: [0-9.]*/Tested up to: $WP_VERSION/" "$README_FILE"
           sed -i "s/Requires PHP: [0-9.]*/Requires PHP: $PHP_VERSION/" "$README_FILE"
-          sed -i "s/WordPress [0-9.]\+/WordPress $WP_PREV_VERSION/" "$README_FILE"
+          sed -i "s/WordPress [0-9.]\+/WordPress $WP_REQUIRED_VERSION/" "$README_FILE"
           sed -i "s/PHP [0-9.]\+ or greater is required/PHP $PHP_VERSION or greater is required/" "$README_FILE"

           # Check for changes and exit early if none
@@ -100,53 +96,70 @@ jobs:
             exit 0
           fi

-          # Create new branch with timestamp
-          BRANCH_NAME="update-version-requirements-$(date +%s)"
-          git checkout -b "$BRANCH_NAME"
-
-          cd plugins/woocommerce
+          # Add changelog entry.
+          rm -f changelog/update-version-requirements-wp-and-php-via-automation
           composer exec -- changelogger add \
             --significance minor \
             --type update \
-            --entry "Update version requirements to WordPress $WP_PREV_VERSION and PHP $PHP_VERSION in readme.txt and woocommerce.php." \
+            --entry "Update version requirements to WordPress $WP_REQUIRED_VERSION and PHP $PHP_VERSION in readme.txt and woocommerce.php." \
             --no-interaction

+          # Commit changes.
           git add .
-          git commit -m "Update version requirements to WP $WP_PREV_VERSION / PHP $PHP_VERSION"
-
-          git push origin "$BRANCH_NAME"
+          git commit -m "Update version requirements to WP $WP_REQUIRED_VERSION / PHP $PHP_VERSION"
+
+          # Push only if remote branch doesn't exist or differs from our changes.
+          if ! git ls-remote --exit-code --heads origin "$branch_name" >/dev/null 2>&1 || ! git diff --quiet HEAD origin/"$branch_name"; then
+            echo "Pushing changes to remote branch."
+            git push --force origin "$branch_name"
+          else
+            echo "No changes compared to remote branch. Skipping push."
+          fi

-          PR_URL=$(gh pr create \
-            --title "Update version requirements to WP $WP_PREV_VERSION / PHP $PHP_VERSION" \
-            --body "This PR automatically updates the version requirements in \`$WOOCOMMERCE_FILE\` and \`$README_FILE\`:
+          # Prepare PR content.
+          pr_title="Update version requirements to WP $WP_REQUIRED_VERSION / PHP $PHP_VERSION"
+          pr_body="This PR automatically updates the version requirements in \`$WOOCOMMERCE_FILE\` and \`$README_FILE\`:

           ## Changes
-          - **WordPress requirement**: $WP_PREV_VERSION
+          - **WordPress requirement**: $WP_REQUIRED_VERSION
           - **PHP requirement**: $PHP_VERSION
+          - **Tested up to**: $WP_VERSION

-          Auto-generated by the \`maintenance-update-version-requirements.yml\` workflow." \
-            --head "$BRANCH_NAME" \
-            --base trunk)
-
-          echo "PR created successfully: $PR_URL"
-          echo "pr_url=$PR_URL" >> $GITHUB_OUTPUT
+          ### ⚠️ Before merging

-      - name: Send Slack notification
-        if: steps.update-pr.outputs.pr_url != ''
-        uses: archive/github-actions-slack@v2.10.0
-        with:
-          slack-bot-user-oauth-access-token: ${{ secrets.CODE_FREEZE_BOT_TOKEN }}
-          slack-channel: ${{ secrets.WOO_DOCS_SLACK_CHANNEL }}
-          slack-optional-unfurl_links: false
-          slack-text: |
-            :woo: *WooCommerce Versions Requirements Updated*
+          Ensure that:
+
+          - [ ] **WordPress $WP_VERSION compatibility** has been tested and verified.
+          - [ ] **PHP $PHP_VERSION compatibility** has been tested and verified.
+
+          ## ⚠️ After merging

-            Version requirements for :woo: have been automatically updated and a PR has been created.
+          Please check with the Woo Docs team in \`#woo-docs\` to ensure the following documentation pages are updated:

-            *WordPress Requirement:* ${{ steps.wp-previous-version.outputs.wp_prev_version }}
-            *PHP Requirement:* ${{ steps.php-version.outputs.required_php_version }}
-            *Pull Request:* <${{ steps.update-pr.outputs.pr_url }}|${{ steps.update-pr.outputs.pr_url }}>
+          - [ ] [Update PHP and WordPress](https://woocommerce.com/document/update-php-wordpress/)
+          - [ ] [WooCommerce Server Requirements](https://woocommerce.com/document/server-requirements/)

-            <!subteam^S011VV34JTX> Please also update these documentation pages:
-            • <https://woocommerce.com/document/update-php-wordpress/|Update PHP and WordPress>
-            • <https://woocommerce.com/document/server-requirements/|WooCommerce Server Recommendations>
+          ---
+          _Auto-generated by the \`maintenance-update-version-requirements.yml\` workflow._"
+
+          # Check if PR already exists.
+          pr_number=$(gh pr list --head "$branch_name" --json number --jq '.[0].number' 2>/dev/null || echo "")
+
+          if [[ -n "$pr_number" ]]; then
+            echo "PR #$pr_number already exists. Updating title, body, and milestone."
+            gh pr edit "$pr_number" \
+              --title "$pr_title" \
+              --body "$pr_body"
+          else
+            # Get WooCommerce version for milestone from trunk.
+            wc_milestone=$( git show origin/trunk:plugins/woocommerce/woocommerce.php | grep -oP '(?<=Version: )(.+)' | head -n1 | sed 's/\.[0-9]\+\(-dev\)\?$/.0/' )
+
+            echo "Creating new PR."
+            gh pr create \
+              --title "$pr_title" \
+              --body "$pr_body" \
+              --head "$branch_name" \
+              --base trunk \
+              --label "Release" \
+              --milestone "$wc_milestone"
+          fi