Commit dc09c6c3b17 for woocommerce

commit dc09c6c3b17a514c4535d66b3eee91d25ef22016
Author: Adrian Moldovan <3854374+adimoldovan@users.noreply.github.com>
Date:   Fri Aug 21 16:59:57 2026 +0300

    CI: set job-level timeout-minutes on workflow jobs (#67880)

diff --git a/.github/workflows/api-staleness.yml b/.github/workflows/api-staleness.yml
index 6cd46a460e7..f9312e2530b 100644
--- a/.github/workflows/api-staleness.yml
+++ b/.github/workflows/api-staleness.yml
@@ -25,6 +25,7 @@ jobs:
     api-staleness:
         name: 'GraphQL API Staleness Check'
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         steps:
             - uses: 'actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0' # v7.0.0
               name: 'Checkout'
diff --git a/.github/workflows/auto-milestone-release-prs.yml b/.github/workflows/auto-milestone-release-prs.yml
index 7565f338305..4f3de057dfc 100644
--- a/.github/workflows/auto-milestone-release-prs.yml
+++ b/.github/workflows/auto-milestone-release-prs.yml
@@ -10,6 +10,7 @@ jobs:
   add-milestone:
     name: Add milestone to release branch PRs
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     # Only run if PR has no milestone and targets a branch starting with 'release/'
     if: |
       github.event.pull_request.milestone == null &&
diff --git a/.github/workflows/automate-team-review-assignment.yml b/.github/workflows/automate-team-review-assignment.yml
index 79808b70860..e54919decab 100644
--- a/.github/workflows/automate-team-review-assignment.yml
+++ b/.github/workflows/automate-team-review-assignment.yml
@@ -20,6 +20,7 @@ jobs:
         name: Add community label
         if: ${{ github.event.action == 'opened' }}
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         steps:
             - name: Check if community contribution
               id: check
@@ -51,6 +52,7 @@ jobs:
       name: Assign reviewers
       if: ${{ github.event.pull_request && ( github.event.action == 'opened' || github.event.action == 'ready_for_review' ) }}
       runs-on: ubuntu-latest
+      timeout-minutes: 5
       steps:
         - name: Check if community contribution
           id: check
@@ -84,6 +86,7 @@ jobs:
       name: Remind reviewers to also review the testing instructions and test coverage
       if: ${{ github.event.pull_request && github.event.action == 'review_requested' }}
       runs-on: ubuntu-latest
+      timeout-minutes: 5
       steps:
         - name: Check if community contribution
           id: check
diff --git a/.github/workflows/build-live-branch.yml b/.github/workflows/build-live-branch.yml
index ca04e01589f..56a779d0039 100644
--- a/.github/workflows/build-live-branch.yml
+++ b/.github/workflows/build-live-branch.yml
@@ -31,6 +31,7 @@ jobs:
     build:
         if: github.repository_owner == 'woocommerce' && github.actor != 'github-actions[bot]'
         runs-on: ubuntu-latest
+        timeout-minutes: 10
         permissions:
             contents: read
         steps:
diff --git a/.github/workflows/changelog-auto-add.yml b/.github/workflows/changelog-auto-add.yml
index 576ef0ad8fe..2a191368e73 100644
--- a/.github/workflows/changelog-auto-add.yml
+++ b/.github/workflows/changelog-auto-add.yml
@@ -31,6 +31,7 @@ jobs:
         name: 'Add changelog to PR'
         if: ${{ github.event.pull_request.user.login != 'github-actions[bot]' && github.event.pull_request.user.login != 'woocommercebot' && ( github.event_name != 'pull_request_target' || contains( github.event.pull_request.body, '[x] Automatically create a changelog' ) ) }}
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             contents: write
             issues: write
diff --git a/.github/workflows/cherry-pick-milestoned-prs.yml b/.github/workflows/cherry-pick-milestoned-prs.yml
index 3309cef4fdc..a0b0aef6dc8 100644
--- a/.github/workflows/cherry-pick-milestoned-prs.yml
+++ b/.github/workflows/cherry-pick-milestoned-prs.yml
@@ -19,6 +19,7 @@ jobs:
   prepare:
     if: ${{ github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'trunk' && github.event.pull_request.milestone != null }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       milestoned_branch: ${{ steps.get-branches.outputs.milestoned_branch }}
       next_branch: ${{ steps.get-branches.outputs.next_branch }}
@@ -151,6 +152,7 @@ jobs:
     needs: [prepare, cherry-pick-milestoned]
     if: ${{ always() && needs.cherry-pick-milestoned.outputs.status == 'success' && needs.cherry-pick-milestoned.outputs.cherry_pick_pr_number }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       # Add original milestone to new PR
       - name: Add milestone
@@ -219,6 +221,7 @@ jobs:
   handle-skipped-milestoned:
     needs: [prepare, cherry-pick-milestoned]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ always() && needs.cherry-pick-milestoned.outputs.status == 'skipped' }}
     steps:
       - name: Comment on original PR about skip
@@ -243,6 +246,7 @@ jobs:
     needs: [prepare, cherry-pick-next]
     if: ${{ always() && needs.cherry-pick-next.outputs.status == 'success' && needs.cherry-pick-next.outputs.cherry_pick_pr_number }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       # Add original milestone to new PR
       - name: Add milestone
@@ -311,6 +315,7 @@ jobs:
   handle-skipped-next:
     needs: [prepare, cherry-pick-next]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ always() && needs.cherry-pick-next.outputs.status == 'skipped' }}
     steps:
       - name: Comment on original PR about skip
@@ -334,6 +339,7 @@ jobs:
   handle-failures-milestoned:
     needs: [prepare, cherry-pick-milestoned]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ always() && needs.cherry-pick-milestoned.outputs.status == 'failed' }}
     steps:
       - name: Handle failure for milestoned branch
@@ -413,6 +419,7 @@ jobs:
   handle-failures-next:
     needs: [prepare, cherry-pick-next]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ always() && needs.cherry-pick-next.outputs.status == 'failed' }}
     steps:
       - name: Handle failure for next branch
diff --git a/.github/workflows/cherry-pick-to-frozen.yml b/.github/workflows/cherry-pick-to-frozen.yml
index 9460f103c58..f4b9374229c 100644
--- a/.github/workflows/cherry-pick-to-frozen.yml
+++ b/.github/workflows/cherry-pick-to-frozen.yml
@@ -28,6 +28,7 @@ jobs:
        github.event.pull_request.merged == true &&
        github.event.label.name == 'cherry pick to frozen release')
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       pr_number: ${{ steps.set-vars.outputs.pr_number }}
       base_branch: ${{ steps.set-vars.outputs.base_branch }}
@@ -93,6 +94,7 @@ jobs:
   cherry-pick-to-trunk-check:
     needs: [prepare, cherry-pick]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       add_cp_to_trunk_nag: ${{ steps.check.outputs.add_cp_to_trunk_nag }}
     steps:
@@ -120,6 +122,7 @@ jobs:
     needs: [prepare, cherry-pick, cherry-pick-to-trunk-check]
     if: ${{ always() && needs.cherry-pick.outputs.status == 'success' && needs.cherry-pick.outputs.cherry_pick_pr_number }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:

       # We set the milestone of the new PR to the milestone of the source PR since they should all be merged in preperation for the same release.
@@ -202,6 +205,7 @@ jobs:
   handle-skipped:
     needs: [prepare, cherry-pick, cherry-pick-to-trunk-check]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ always() && needs.cherry-pick.outputs.status == 'skipped' }}
     steps:
       - name: Comment on original PR about skip
@@ -224,6 +228,7 @@ jobs:
   handle-failures:
     needs: [prepare, cherry-pick, cherry-pick-to-trunk-check]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ always() && needs.cherry-pick.outputs.status == 'failed' }}
     steps:
       - name: Add "cherry pick failed" label
diff --git a/.github/workflows/cherry-pick-to-trunk.yml b/.github/workflows/cherry-pick-to-trunk.yml
index fa7e8383462..66307bc64ed 100644
--- a/.github/workflows/cherry-pick-to-trunk.yml
+++ b/.github/workflows/cherry-pick-to-trunk.yml
@@ -23,6 +23,7 @@ jobs:
        github.event.pull_request.merged == true &&
        github.event.label.name == 'cherry pick to trunk')
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       pr_number: ${{ steps.set-vars.outputs.pr_number }}
       base_branch: ${{ steps.set-vars.outputs.base_branch }}
@@ -45,6 +46,7 @@ jobs:
   frozen-release-check:
     needs: [prepare, cherry-pick]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       add_cp_to_frozen_nag: ${{ steps.check.outputs.add_cp_to_frozen_nag }}
       next_branch: ${{ steps.check.outputs.next_branch }}
@@ -110,6 +112,7 @@ jobs:
     needs: [prepare, cherry-pick, frozen-release-check]
     if: ${{ always() && needs.cherry-pick.outputs.status == 'success' && needs.cherry-pick.outputs.cherry_pick_pr_number }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       # We set the milestone of the new PR to the milestone of the source PR since they should all be merged in preparation for the same release.
       - name: Add milestone
@@ -191,6 +194,7 @@ jobs:
   handle-skipped:
     needs: [prepare, cherry-pick, frozen-release-check]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ always() && needs.cherry-pick.outputs.status == 'skipped' }}
     steps:
       - name: Comment on original PR about skip
@@ -213,6 +217,7 @@ jobs:
   handle-failures:
     needs: [prepare, cherry-pick, frozen-release-check]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ always() && needs.cherry-pick.outputs.status == 'failed' }}
     steps:
       - name: Add "cherry pick failed" label
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 931355623b5..905b2a9989d 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -71,6 +71,7 @@ jobs:
     name: 'Analyze changes'
     if: ${{ !cancelled() && github.event_name == 'pull_request' }}
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     outputs:
       needs-code-validation: ${{ steps.target-changes.outputs.needs-code-validation }}
       needs-changelog-validation: ${{ steps.target-changes.outputs.needs-changelog-validation }}
@@ -103,6 +104,7 @@ jobs:
     if: ${{ !cancelled() }}
     needs: 'identify-jobs-to-run'
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     outputs:
       lint-jobs: ${{ steps.project-jobs.outputs.lint-jobs }}
       test-jobs: ${{ steps.project-jobs.outputs.test-jobs }}
@@ -154,6 +156,7 @@ jobs:
   project-lint-jobs:
     name: "Lint - ${{ matrix.projectName }} ${{ ( matrix.optional && ' (optional)' ) || '' }}"
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 10
     needs: [ 'identify-jobs-to-run', 'project-jobs' ]
     if: ${{ !cancelled() && github.event_name == 'pull_request' && needs.identify-jobs-to-run.outputs.needs-code-validation == 'true' && needs.project-jobs.outputs.lint-jobs != '[]' }}
     strategy:
@@ -227,6 +230,7 @@ jobs:
   woocommerce-plugin-build-artifact:
     name: "Build WooCommerce plugin artifact${{ needs.project-jobs.outputs.shared-plugin-build-has-required-consumers != 'true' && ' (optional)' || '' }}"
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 10
     needs: [ 'identify-jobs-to-run', 'project-jobs' ]
     # The `needs-code-validation` clause mirrors `project-test-jobs`: without it this job builds a
     # plugin zip for consumers that are themselves gated off, which is pure waste on docs-only PRs.
@@ -273,6 +277,7 @@ jobs:
     # While the CI_QUEUE_OVERFLOW repository variable is '1', e2e jobs route to the
     # dedicated group. Fork PRs are excluded.
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || ( vars.CI_QUEUE_OVERFLOW == '1' && matrix.testType == 'e2e' && ( github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository ) ) && fromJSON('{"group":"Woo Core Dedicated CI"}') || 'ubuntu-latest' }}
+    timeout-minutes: 35
     needs: [ 'identify-jobs-to-run', 'project-jobs', 'woocommerce-plugin-build-artifact' ]
     if: ${{ !cancelled() && ( github.event_name != 'pull_request' || needs.identify-jobs-to-run.outputs.needs-code-validation == 'true' ) && needs.project-jobs.outputs.test-jobs != '[]' && ( needs.woocommerce-plugin-build-artifact.result == 'success' || needs.woocommerce-plugin-build-artifact.result == 'skipped' || needs.project-jobs.outputs.shared-plugin-build-has-required-consumers != 'true' ) }}
     env: ${{ matrix.testEnv.envVars }}
@@ -477,6 +482,7 @@ jobs:
     # on the results of the other jobs in the workflow.
     name: 'Evaluate Project Job Statuses'
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     needs: [ 'project-jobs', 'woocommerce-plugin-build-artifact', 'project-lint-jobs', 'project-test-jobs', 'validate-changelog', 'validate-markdown', 'validate-syncpack' ]
     # This job must run for all trigger types (not just PRs) so that alert-on-failure can access its outputs
     if: ${{ !cancelled() }}
@@ -509,6 +515,7 @@ jobs:
   alert-on-failure:
     name: 'Report results on Slack'
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     needs: ['project-jobs', 'woocommerce-plugin-build-artifact', 'project-lint-jobs', 'project-test-jobs', 'evaluate-project-jobs']
     if: ${{ !cancelled() && github.event_name != 'pull_request' && github.repository == 'woocommerce/woocommerce' }}
     env:
@@ -565,6 +572,7 @@ jobs:
       matrix:
         report: ${{ fromJSON( needs.project-jobs.outputs.report-jobs ) }}
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     env:
       ARTIFACT_NAME: ${{ matrix.report }}-attempt-${{ github.run_attempt }}

@@ -647,6 +655,7 @@ jobs:
     if: ${{ !cancelled() && github.event_name == 'pull_request' && needs.identify-jobs-to-run.outputs.needs-syncpack-validation == 'true' }}
     needs: [ 'identify-jobs-to-run' ]
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     permissions:
       contents: read

@@ -684,6 +693,7 @@ jobs:
       }}
     needs: [ 'identify-jobs-to-run' ]
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     permissions:
       contents: read

@@ -740,6 +750,7 @@ jobs:
     if: ${{ !cancelled() && github.event_name == 'pull_request' && github.event.pull_request.base.ref == 'trunk' && needs.identify-jobs-to-run.outputs.needs-markdown-validation == 'true' }}
     needs: [ 'identify-jobs-to-run' ]
     runs-on: ${{ github.event.pull_request.user.login == 'woocommercebot' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     permissions:
       contents: read

diff --git a/.github/workflows/maintenance-bump-as-requirement.yml b/.github/workflows/maintenance-bump-as-requirement.yml
index 32113e630cd..f1d912f5488 100644
--- a/.github/workflows/maintenance-bump-as-requirement.yml
+++ b/.github/workflows/maintenance-bump-as-requirement.yml
@@ -13,6 +13,7 @@ jobs:
   check-version:
     name: Check Action Scheduler version
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       version: ${{ steps.get-as-version.outputs.version }}
       should-update: ${{ steps.check-version.outputs.should-update }}
@@ -62,6 +63,7 @@ jobs:
     needs: check-version
     if: needs.check-version.outputs.should-update == 'true'
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
     - name: Check out trunk
       uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
diff --git a/.github/workflows/maintenance-update-version-requirements.yml b/.github/workflows/maintenance-update-version-requirements.yml
index 91213ed73fc..5825b01a03e 100644
--- a/.github/workflows/maintenance-update-version-requirements.yml
+++ b/.github/workflows/maintenance-update-version-requirements.yml
@@ -9,6 +9,7 @@ jobs:
   preparation:
     name: Check versions and prep for update
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       current_wp_version: ${{ steps.compute-wp-versions.outputs.wp_version }}
       required_wp_version: ${{ steps.compute-wp-versions.outputs.wp_required_version }}
@@ -96,6 +97,7 @@ jobs:
   update-versions:
     needs: [preparation]
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     strategy:
       fail-fast: false
       matrix: ${{ fromJSON(needs.preparation.outputs.matrix) }}
diff --git a/.github/workflows/nightly-builds.yml b/.github/workflows/nightly-builds.yml
index a04ac9f36e7..68349c5c107 100644
--- a/.github/workflows/nightly-builds.yml
+++ b/.github/workflows/nightly-builds.yml
@@ -21,6 +21,7 @@ jobs:
     name: 'Nightly builds'

     runs-on: ubuntu-latest
+    timeout-minutes: 10
     permissions:
       contents: write
     steps:
diff --git a/.github/workflows/package-php-mirror.yml b/.github/workflows/package-php-mirror.yml
index c0c82986daa..e95459a4ffd 100644
--- a/.github/workflows/package-php-mirror.yml
+++ b/.github/workflows/package-php-mirror.yml
@@ -12,6 +12,7 @@ jobs:
     mirror:
         name: Prepare and mirror the package
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             contents: read
         steps:
diff --git a/.github/workflows/package-release.yml b/.github/workflows/package-release.yml
index d531d3bfa1f..487defb81d6 100644
--- a/.github/workflows/package-release.yml
+++ b/.github/workflows/package-release.yml
@@ -19,6 +19,7 @@ jobs:
   release:
     name: Run packages release script
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0

diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml
index 80859021ec1..a999efc0aea 100644
--- a/.github/workflows/phpstan.yml
+++ b/.github/workflows/phpstan.yml
@@ -30,6 +30,7 @@ jobs:
     phpstan:
         name: 'PHPStan Analysis'
         runs-on: ubuntu-latest
+        timeout-minutes: 15
         steps:
             - uses: 'actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0' # v7.0.0
               name: 'Checkout'
diff --git a/.github/workflows/pr-assess-bundle-size.yml b/.github/workflows/pr-assess-bundle-size.yml
index 49320dec282..6c28d6bf20e 100644
--- a/.github/workflows/pr-assess-bundle-size.yml
+++ b/.github/workflows/pr-assess-bundle-size.yml
@@ -42,6 +42,7 @@ jobs:
         name: Check Asset Sizes
         if: github.event.pull_request.draft == false && github.event.pull_request.user.login != 'github-actions[bot]'
         runs-on: ubuntu-latest
+        timeout-minutes: 15
         permissions:
             contents: read
             pull-requests: write
diff --git a/.github/workflows/pr-auto-milestone-on-merge.yml b/.github/workflows/pr-auto-milestone-on-merge.yml
index a9c546a2cc2..f39fe61a67d 100644
--- a/.github/workflows/pr-auto-milestone-on-merge.yml
+++ b/.github/workflows/pr-auto-milestone-on-merge.yml
@@ -14,6 +14,7 @@ jobs:
     name: 'Assign milestone if so instructed'
     if: github.event.pull_request.merged == true && github.event.pull_request.milestone == null
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       - name: Checkout
         uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
diff --git a/.github/workflows/pr-build-live-branch.yml b/.github/workflows/pr-build-live-branch.yml
index eaeb5c98213..d37347ae98b 100644
--- a/.github/workflows/pr-build-live-branch.yml
+++ b/.github/workflows/pr-build-live-branch.yml
@@ -39,6 +39,7 @@ jobs:
     build:
         if: github.repository_owner == 'woocommerce' && github.event.pull_request.draft == false && github.event.pull_request.user.login != 'github-actions[bot]'
         runs-on: ubuntu-latest
+        timeout-minutes: 10
         permissions:
             contents: write
             pull-requests: write
diff --git a/.github/workflows/pr-email-editor-test-reminder.yml b/.github/workflows/pr-email-editor-test-reminder.yml
index 620c564fa00..b99446bbd69 100644
--- a/.github/workflows/pr-email-editor-test-reminder.yml
+++ b/.github/workflows/pr-email-editor-test-reminder.yml
@@ -21,6 +21,7 @@ jobs:
     check-and-comment:
         name: Check and add test reminder comment
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         steps:
             - name: Checkout
               uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
diff --git a/.github/workflows/pr-highlight-changes.yml b/.github/workflows/pr-highlight-changes.yml
index 14fd68e17e7..34a91bb9c59 100644
--- a/.github/workflows/pr-highlight-changes.yml
+++ b/.github/workflows/pr-highlight-changes.yml
@@ -16,6 +16,7 @@ jobs:
   analyze:
     name: 'Analyze Branch Changes'
     runs-on: ubuntu-latest
+    timeout-minutes: 10
     outputs:
       results: ${{ steps.results.outputs.results }}
     steps:
diff --git a/.github/workflows/pr-highlight-rest-api-changes.yml b/.github/workflows/pr-highlight-rest-api-changes.yml
index 49d349675eb..ea20f91e7fd 100644
--- a/.github/workflows/pr-highlight-rest-api-changes.yml
+++ b/.github/workflows/pr-highlight-rest-api-changes.yml
@@ -13,6 +13,7 @@ jobs:
     name: Send Notification for Rest API Changes
     if: github.event.pull_request.merged == true
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       - uses: dorny/paths-filter@7b450fff21473bca461d4b92ce414b9d0420d706 # v4.0.2
         id: filter
diff --git a/.github/workflows/pr-project-label.yml b/.github/workflows/pr-project-label.yml
index 07672116d88..889de11ac04 100644
--- a/.github/workflows/pr-project-label.yml
+++ b/.github/workflows/pr-project-label.yml
@@ -12,6 +12,7 @@ permissions: {}
 jobs:
     label_project:
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             contents: read
             pull-requests: write
diff --git a/.github/workflows/pr-require-milestone.yml b/.github/workflows/pr-require-milestone.yml
index c5bba510eb8..1e6b02a9d28 100644
--- a/.github/workflows/pr-require-milestone.yml
+++ b/.github/workflows/pr-require-milestone.yml
@@ -22,6 +22,7 @@ jobs:
     name: 'Ensure milestone is or will be assigned'
     if: github.event.pull_request.draft == false
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       - name: Checkout
         uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
diff --git a/.github/workflows/prepare-package-release.yml b/.github/workflows/prepare-package-release.yml
index 40a21180739..52cb21348df 100644
--- a/.github/workflows/prepare-package-release.yml
+++ b/.github/workflows/prepare-package-release.yml
@@ -13,6 +13,7 @@ jobs:
   prepare:
     name: Run prepare script
     runs-on: ubuntu-latest
+    timeout-minutes: 10
     permissions:
       contents: write
       pull-requests: write
diff --git a/.github/workflows/pull-request-post-merge-processing.yml b/.github/workflows/pull-request-post-merge-processing.yml
index 531fb210385..b39cc183bbe 100644
--- a/.github/workflows/pull-request-post-merge-processing.yml
+++ b/.github/workflows/pull-request-post-merge-processing.yml
@@ -17,6 +17,7 @@ jobs:
         name: "Process a pull request after it's merged"
         if: github.event.pull_request.merged == true
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             pull-requests: write
         steps:
@@ -45,6 +46,7 @@ jobs:
         name: Log the merge of a Feature Freeze exception
         if: ${{ github.event.pull_request.merged && startsWith( github.event.pull_request.base.ref, 'release/' ) && ! contains( github.event.pull_request.labels.*.name, 'Release' ) }}
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             pull-requests: write
         steps:
@@ -58,6 +60,7 @@ jobs:
     process-pull-request-after-close:
         name: "Process a pull request after it's been closed"
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         steps:
             - name: 'Cleanup: GitHub caches associated with the merged branch'
               run: |
diff --git a/.github/workflows/release-assignment.yml b/.github/workflows/release-assignment.yml
index 74af844580b..2508cd78435 100644
--- a/.github/workflows/release-assignment.yml
+++ b/.github/workflows/release-assignment.yml
@@ -15,6 +15,7 @@ jobs:
   check-upcoming-release-events:
     name: Check for upcoming release events
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       should-trigger-webhook: ${{ steps.check-code-freeze-8-weeks.outputs.should-trigger-webhook }}
       version: ${{ steps.check-code-freeze-8-weeks.outputs.version }}
@@ -138,6 +139,7 @@ jobs:
     needs: [check-upcoming-release-events]
     if: ${{ needs.check-upcoming-release-events.outputs.should-trigger-webhook == 'true' }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       create-tracking-issues: ${{ steps.trigger-upcoming-code-freeze-events.outputs.create-tracking-issues }}
       post: ${{ steps.trigger-upcoming-code-freeze-events.outputs.post }}
@@ -216,6 +218,7 @@ jobs:
     needs: [trigger-upcoming-code-freeze-events, check-upcoming-release-events, create-parent-tracking-issue, create-sub-tracking-issues]
     if: ${{ needs.trigger-upcoming-code-freeze-events.outputs.create-tracking-issues == 'true' }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       - name: Send Slack notification
         uses: archive/github-actions-slack@a62d71a4ea93e68cbdc37581166b0298bea512e9 # v2.10.0
@@ -236,6 +239,7 @@ jobs:
     needs: [trigger-upcoming-code-freeze-events, check-upcoming-release-events]
     if: ${{ needs.trigger-upcoming-code-freeze-events.outputs.create-tracking-issues == 'true' }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       sub-issues-matrix: ${{ steps.build-matrix.outputs.matrix }}
       issue-url: ${{ steps.check-existing-issue.outputs.issue-url || steps.create-tracking-issue.outputs.issue-url }}
@@ -519,6 +523,7 @@ jobs:
     needs: [check-upcoming-release-events, trigger-upcoming-code-freeze-events, send-slack-notification, create-parent-tracking-issue, create-sub-tracking-issues]
     if: ${{ failure() }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       - name: Send failure notification to Slack
         uses: archive/github-actions-slack@a62d71a4ea93e68cbdc37581166b0298bea512e9 # v2.10.0
diff --git a/.github/workflows/release-build-zip-file.yml b/.github/workflows/release-build-zip-file.yml
index 4f9f1ed0043..6817b5bd113 100644
--- a/.github/workflows/release-build-zip-file.yml
+++ b/.github/workflows/release-build-zip-file.yml
@@ -40,6 +40,7 @@ jobs:
   verify:
     name: 'Pre-build verification'
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     permissions:
       contents: write # Required to fetch draft releases for some reason. See https://github.com/cli/cli/issues/9076#issuecomment-2146148572.
     outputs:
@@ -251,6 +252,7 @@ jobs:
   build:
     name: Build release zip file
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 15
     needs: [ verify ]
     outputs:
       artifact-url: ${{ steps.fetch-build-details.outputs.artifact-url }}
@@ -302,6 +304,7 @@ jobs:
   create-release:
     name: Create GitHub release
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     needs: [ verify, build ]
     if: ${{ inputs.create_github_release && needs.verify.outputs.is-release-branch == 'true' }}
     permissions:
diff --git a/.github/workflows/release-bump-version.yml b/.github/workflows/release-bump-version.yml
index 8f5f7419d64..6e75dc4bbd8 100644
--- a/.github/workflows/release-bump-version.yml
+++ b/.github/workflows/release-bump-version.yml
@@ -42,6 +42,7 @@ jobs:
   bump-version:
     name: Bump WooCommerce Version
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     steps:
       - name: Normalize branch input
         id: normalize-branch
diff --git a/.github/workflows/release-cfe-prr-issue-validation.yml b/.github/workflows/release-cfe-prr-issue-validation.yml
index e1ebad48c48..4d6d5a56382 100644
--- a/.github/workflows/release-cfe-prr-issue-validation.yml
+++ b/.github/workflows/release-cfe-prr-issue-validation.yml
@@ -12,6 +12,7 @@ jobs:
   prep:
     if: github.event.label.name == 'code freeze exception' || github.event.label.name == 'point release request' || github.event.label.name == 'Approved' || github.event.label.name == 'Rejected'
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       pr_number: ${{ steps.extract-pr.outputs.PR_NUMBER }}
     steps:
@@ -43,6 +44,7 @@ jobs:
   verify:
     if: github.event.label.name == 'code freeze exception' || github.event.label.name == 'point release request' || github.event.label.name == 'Approved'
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       release_number: ${{ steps.extract-release.outputs.RELEASE_NUMBER }}
     permissions:
@@ -193,6 +195,7 @@ jobs:
   apply-milestone:
     if: github.event.label.name == 'code freeze exception' || github.event.label.name == 'point release request' || github.event.label.name == 'Approved' || github.event.label.name == 'Rejected'
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     permissions:
       issues: write
     needs:
@@ -210,6 +213,7 @@ jobs:
   cfe-created:
     if: github.event.label.name == 'code freeze exception' || github.event.label.name == 'point release request'
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     needs:
       - verify
     permissions:
@@ -256,6 +260,7 @@ jobs:
   request-approved:
     if: ${{ github.event.label.name == 'Approved' }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     permissions:
       pull-requests: write
       issues: write
@@ -335,6 +340,7 @@ jobs:
   request-rejected:
     if: ${{ github.event.label.name == 'Rejected' }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     permissions:
       issues: write
     steps:
diff --git a/.github/workflows/release-cherry-pick-pr-check-conflicts.yml b/.github/workflows/release-cherry-pick-pr-check-conflicts.yml
index d1aaabc9101..5a471e6719e 100644
--- a/.github/workflows/release-cherry-pick-pr-check-conflicts.yml
+++ b/.github/workflows/release-cherry-pick-pr-check-conflicts.yml
@@ -22,6 +22,7 @@ jobs:
   check-conflicts-label:
     name: Check for conflicts label
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: |
       startsWith(github.head_ref, 'cherry-pick-') &&
       contains(github.event.pull_request.labels.*.name, 'cherry pick has conflicts')
diff --git a/.github/workflows/release-code-freeze.yml b/.github/workflows/release-code-freeze.yml
index 9e099eb270a..252a8a18bca 100644
--- a/.github/workflows/release-code-freeze.yml
+++ b/.github/workflows/release-code-freeze.yml
@@ -23,6 +23,7 @@ jobs:
   check-feature-freeze-event:
     name: Check for Feature Freeze events today
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       should-run: ${{ steps.check-feature-freeze-event.outputs.should-run }}
     steps:
@@ -74,6 +75,7 @@ jobs:
     needs: check-feature-freeze-event
     if: ${{ needs.check-feature-freeze-event.outputs.should-run == 'true' }}
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       nextReleaseBranch: ${{ steps.calculate-versions.outputs.nextReleaseBranch }}
       nextReleaseVersion: ${{ steps.calculate-versions.outputs.nextReleaseVersion }}
@@ -128,6 +130,7 @@ jobs:
   run-feature-freeze:
     name: Perform feature freeze
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     needs: prepare-for-feature-freeze
     steps:
       - name: Checkout trunk
@@ -168,6 +171,7 @@ jobs:
   cleanup-milestones:
     name: Clean up old and completed milestones
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     needs: [prepare-for-feature-freeze, run-feature-freeze]
     steps:
       - name: Close completed milestones
@@ -224,6 +228,7 @@ jobs:
   publish-dev-release:
     name: 'Publish -dev release'
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     needs: [prepare-for-feature-freeze, build-dev-release]
     outputs:
       release-zip: ${{ steps.publish-release.outputs.release-zip }}
@@ -243,6 +248,7 @@ jobs:
   notify-slack:
     name: Notify Slack
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     needs: [publish-dev-release, prepare-for-feature-freeze]
     outputs:
       message-ts: ${{ steps.notify-success.outputs.ts }}
@@ -324,6 +330,7 @@ jobs:
   trigger-webhook:
     name: Trigger Release Webhook
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     needs: [publish-dev-release, prepare-for-feature-freeze]
     steps:
       - name: Trigger Feature Freeze Webhook
@@ -383,6 +390,7 @@ jobs:
   notify-slack-on-failure:
     name: Notify Slack on Failure
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     needs: [ check-feature-freeze-event, prepare-for-feature-freeze, run-feature-freeze, cleanup-milestones, bump-version-in-trunk, build-dev-release, publish-dev-release, notify-slack, trigger-webhook ]
     if: always() && ((contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')))
     steps:
diff --git a/.github/workflows/release-commits-and-contributors.yml b/.github/workflows/release-commits-and-contributors.yml
index f30ab5dabe8..28b910b6ded 100644
--- a/.github/workflows/release-commits-and-contributors.yml
+++ b/.github/workflows/release-commits-and-contributors.yml
@@ -20,6 +20,7 @@ jobs:
   extract-versions:
     name: Extract release current and previous versions
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     outputs:
       current_version: ${{ steps.calculate-versions.outputs.current_version }}
       previous_version: ${{ steps.calculate-versions.outputs.previous_version }}
@@ -96,6 +97,7 @@ jobs:
     name: Count commits and contributors between releases
     needs: extract-versions
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     outputs:
       commit_count: ${{ steps.count-commits.outputs.commit_count }}
       contributor_count: ${{ steps.count-commits.outputs.contributor_count }}
@@ -132,6 +134,7 @@ jobs:
     name: Generate contributors list
     needs: extract-versions
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 10
     outputs:
       contributor_list_path: ${{ steps.generate-contributors-list.outputs.filepath }}
       artifact_url: ${{ steps.output-artifact-url.outputs.artifact_url }}
@@ -194,6 +197,7 @@ jobs:
     name: Check for database updates
     needs: extract-versions
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     outputs:
       has_updates: ${{ steps.check-db-updates.outputs.has_updates }}
       updates_list: ${{ steps.check-db-updates.outputs.updates_list }}
@@ -324,6 +328,7 @@ jobs:
     name: Send Slack Notification
     needs: [extract-versions, count-commits-and-contributors, generate-contributors-list, db-updates]
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     steps:
       - name: Send Slack message
         uses: archive/github-actions-slack@a62d71a4ea93e68cbdc37581166b0298bea512e9 # v 2.10.0
diff --git a/.github/workflows/release-compile-changelog.yml b/.github/workflows/release-compile-changelog.yml
index b3e09c69bd7..3ceac362974 100644
--- a/.github/workflows/release-compile-changelog.yml
+++ b/.github/workflows/release-compile-changelog.yml
@@ -33,6 +33,7 @@ jobs:
   build-prep:
     name: Create changelog PR
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     permissions:
       contents: write
       pull-requests: write
diff --git a/.github/workflows/release-create-tracking-issue.yml b/.github/workflows/release-create-tracking-issue.yml
index a7b9f472357..e12c4b4faa2 100644
--- a/.github/workflows/release-create-tracking-issue.yml
+++ b/.github/workflows/release-create-tracking-issue.yml
@@ -44,6 +44,7 @@ jobs:
   create-tracking-issue:
     name: Create Release Tracking Issue
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     steps:
       - name: Parse version and determine template
         id: parse-version
diff --git a/.github/workflows/release-feature-highlights-notification.yml b/.github/workflows/release-feature-highlights-notification.yml
index 39160894082..d65fd56942e 100644
--- a/.github/workflows/release-feature-highlights-notification.yml
+++ b/.github/workflows/release-feature-highlights-notification.yml
@@ -10,6 +10,7 @@ env:
 jobs:
   check-feature-freeze:
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       event-version: ${{ steps.find-feature-freeze-event.outputs.event-version }}
       event-title: ${{ steps.find-feature-freeze-event.outputs.event-title }}
@@ -71,6 +72,7 @@ jobs:
     needs: check-feature-freeze
     if: needs.check-feature-freeze.outputs.event-title != ''
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       - name: Send feature highlight reminder notification
         uses: archive/github-actions-slack@a62d71a4ea93e68cbdc37581166b0298bea512e9 # v 2.10.0
diff --git a/.github/workflows/release-new-release-published.yml b/.github/workflows/release-new-release-published.yml
index bbdad99415a..b7df7f434e0 100644
--- a/.github/workflows/release-new-release-published.yml
+++ b/.github/workflows/release-new-release-published.yml
@@ -24,6 +24,7 @@ jobs:
   notify-release-published:
     name: 'Notify in Slack when a new (pre)release is published'
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ github.event.action == 'published' && ! ( contains( inputs.release_tag_name, '-dev' ) || contains( inputs.release_tag_name, '-rc' ) ) }}
     steps:
       - name: 'Checkout repository'
@@ -84,6 +85,7 @@ jobs:
   update-global-changelog:
     name: 'Update changelog.txt after any stable release'
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     if: ${{ github.event.action == 'published' && ! ( contains( inputs.release_tag_name, '-dev' ) || contains( inputs.release_tag_name, '-beta' ) || contains( inputs.release_tag_name, '-rc' ) ) }}
     permissions:
       contents: write
diff --git a/.github/workflows/release-open-issue-warning.yml b/.github/workflows/release-open-issue-warning.yml
index 5f20aa19637..68f2495a601 100644
--- a/.github/workflows/release-open-issue-warning.yml
+++ b/.github/workflows/release-open-issue-warning.yml
@@ -15,6 +15,7 @@ jobs:
   check-upcoming-release-events:
     name: Check for upcoming release events
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     outputs:
       version: ${{ steps.check-upcoming-release-build.outputs.version }}
       milestone: ${{ steps.check-upcoming-release-build.outputs.milestone }}
@@ -80,6 +81,7 @@ jobs:
     name: Check all open milestones
     needs: check-upcoming-release-events
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       - name: Get and process open milestones
         id: process-milestones
diff --git a/.github/workflows/release-trends-analysis.yml b/.github/workflows/release-trends-analysis.yml
index 972a6460d94..5d8e978f448 100644
--- a/.github/workflows/release-trends-analysis.yml
+++ b/.github/workflows/release-trends-analysis.yml
@@ -12,6 +12,7 @@ env:
 jobs:
   analyze-trends-cfes:
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     steps:
       - name: Analyze CFEs trends
         env:
@@ -36,6 +37,7 @@ jobs:
           " > /dev/null
   analyze-trends-prrs:
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     steps:
       - name: Analyze PRRs trends
         env:
@@ -60,6 +62,7 @@ jobs:
           "
   analyze-quality:
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     steps:
       - name: Analyze quality issues
         env:
diff --git a/.github/workflows/release-update-stable-tag.yml b/.github/workflows/release-update-stable-tag.yml
index 8ba7231113d..7720c0d5ddf 100644
--- a/.github/workflows/release-update-stable-tag.yml
+++ b/.github/workflows/release-update-stable-tag.yml
@@ -30,6 +30,7 @@ env:
 jobs:
   validate-release:
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 10
     outputs:
       version: ${{ steps.extract-version.outputs.version }}
       branch: ${{ steps.extract-version.outputs.branch }}
@@ -194,6 +195,7 @@ jobs:

   update-wporg-stable-tag:
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     needs: validate-release
     steps:
       - name: Install SVN
@@ -233,6 +235,7 @@ jobs:

   update-gh-stable-tag:
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 10
     needs: [validate-release, update-wporg-stable-tag]
     strategy:
       fail-fast: false
@@ -307,6 +310,7 @@ jobs:

   notify-release:
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     needs: [validate-release, update-wporg-stable-tag, update-gh-stable-tag]
     if: ${{ github.event.inputs.allow-revert != 'true' }}
     steps:
diff --git a/.github/workflows/release-upload-to-wporg.yml b/.github/workflows/release-upload-to-wporg.yml
index dcf4e1d4077..9ec23468661 100644
--- a/.github/workflows/release-upload-to-wporg.yml
+++ b/.github/workflows/release-upload-to-wporg.yml
@@ -26,6 +26,7 @@ jobs:
   get-and-validate-release-asset:
     name: Get intended release details
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 5
     permissions:
       contents: write # Required to fetch draft releases for some reason. See https://github.com/cli/cli/issues/9076#issuecomment-2146148572.
     outputs:
@@ -161,6 +162,7 @@ jobs:
   commit:
     name: Commit release to WordPress.org
     runs-on: ${{ github.repository == 'woocommerce/woocommerce' && fromJSON('{"group":"WooCommerce Release Checks"}') || 'ubuntu-latest' }}
+    timeout-minutes: 10
     needs: [get-and-validate-release-asset]
     if: ${{ github.repository == 'woocommerce/woocommerce' }}
     permissions:
@@ -290,6 +292,7 @@ jobs:
   handle-failure:
     name: Report SVN state
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     needs: [get-and-validate-release-asset, commit]
     if: failure() && github.repository == 'woocommerce/woocommerce' && github.event.inputs.confirm-update == 'true' && needs.get-and-validate-release-asset.outputs.release_tag != ''
     permissions: {}
diff --git a/.github/workflows/release-wc-beta-tester.yml b/.github/workflows/release-wc-beta-tester.yml
index af80c02c72f..a7e7e076e28 100644
--- a/.github/workflows/release-wc-beta-tester.yml
+++ b/.github/workflows/release-wc-beta-tester.yml
@@ -15,6 +15,7 @@ jobs:
     release:
         name: Run release scripts
         runs-on: ubuntu-latest
+        timeout-minutes: 15
         permissions:
             contents: write
         steps:
diff --git a/.github/workflows/shared-cherry-pick.yml b/.github/workflows/shared-cherry-pick.yml
index 2a0f59a4595..9ae980af0f7 100644
--- a/.github/workflows/shared-cherry-pick.yml
+++ b/.github/workflows/shared-cherry-pick.yml
@@ -46,6 +46,7 @@ jobs:
   verify:
     name: Verify requirements
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     permissions:
       contents: write
       pull-requests: write
@@ -211,6 +212,7 @@ jobs:
   cherry-pick:
     name: Cherry Pick
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     needs: verify
     if: needs.verify.outputs.status == 'success'
     permissions:
@@ -490,6 +492,7 @@ jobs:
   aggregate-overall-status:
     name: Aggregate final status
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     needs: [verify, cherry-pick]
     if: always()
     outputs:
diff --git a/.github/workflows/stalebot.yml b/.github/workflows/stalebot.yml
index 60c1adc8b56..d3d29abb427 100644
--- a/.github/workflows/stalebot.yml
+++ b/.github/workflows/stalebot.yml
@@ -11,6 +11,7 @@ permissions: {}
 jobs:
     stale:
         runs-on: ubuntu-latest
+        timeout-minutes: 10
         permissions:
             contents: write
             issues: write
@@ -102,6 +103,7 @@ jobs:

     remove-draft-approvals:
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             pull-requests: write
         if: github.event_name == 'pull_request' && github.event.action == 'converted_to_draft'
diff --git a/.github/workflows/storybook-pages.yml b/.github/workflows/storybook-pages.yml
index ece6b1ddd85..9113d978aba 100644
--- a/.github/workflows/storybook-pages.yml
+++ b/.github/workflows/storybook-pages.yml
@@ -11,6 +11,7 @@ permissions:
 jobs:
     deploy:
         runs-on: ubuntu-latest
+        timeout-minutes: 10
         if: ${{ github.repository == 'woocommerce/woocommerce' }}

         steps:
diff --git a/.github/workflows/tests-canonical-extensions.yml b/.github/workflows/tests-canonical-extensions.yml
index 20cb051b70f..601450693ee 100644
--- a/.github/workflows/tests-canonical-extensions.yml
+++ b/.github/workflows/tests-canonical-extensions.yml
@@ -19,6 +19,7 @@ jobs:
   run-tests:
     name: Test canonical extensions
     runs-on: ubuntu-latest
+    timeout-minutes: 15
     steps:
       - name: Checkout monorepo
         uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
diff --git a/.github/workflows/tests-on-demand.yml b/.github/workflows/tests-on-demand.yml
index 132d214975e..811c5e80d0f 100644
--- a/.github/workflows/tests-on-demand.yml
+++ b/.github/workflows/tests-on-demand.yml
@@ -30,6 +30,7 @@ on:
 jobs:
   validate-input:
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     steps:
       - name: 'Validate input'
         env:
diff --git a/.github/workflows/triage-replies.yml b/.github/workflows/triage-replies.yml
index b7c5926eb58..cdba31b64d8 100644
--- a/.github/workflows/triage-replies.yml
+++ b/.github/workflows/triage-replies.yml
@@ -10,6 +10,7 @@ jobs:
     add-dev-comment:
         if: "github.event.label.name == 'needs: developer feedback'"
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             issues: write
         steps:
@@ -30,6 +31,7 @@ jobs:
     add-reproduction-comment:
         if: "github.event.label.name == 'status: reproduction'"
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             issues: write
         steps:
@@ -49,6 +51,7 @@ jobs:
     add-support-comment:
         if: "github.event.label.name == 'type: support request'"
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             issues: write
         steps:
@@ -88,6 +91,7 @@ jobs:
     add-votes-comment:
         if: "github.event.label.name == 'needs: votes'"
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             issues: write
         steps:
@@ -123,6 +127,7 @@ jobs:
     fill-template-comment:
         if: "github.event.label.name == 'needs: template'"
         runs-on: ubuntu-latest
+        timeout-minutes: 5
         permissions:
             issues: write
         steps:
diff --git a/.github/workflows/update-feedback-labels.yml b/.github/workflows/update-feedback-labels.yml
index c0108e1e2c5..c11a077a117 100644
--- a/.github/workflows/update-feedback-labels.yml
+++ b/.github/workflows/update-feedback-labels.yml
@@ -12,6 +12,7 @@ jobs:
       github.event.issue.state == 'open' &&
       contains(github.event.issue.labels.*.name, 'needs: author feedback')
     runs-on: ubuntu-latest
+    timeout-minutes: 5
     permissions:
       issues: write
     steps: