Skip to content

Commit ac5e785

Browse files
committed
Merge release/10.0.0 into trunk
2 parents a5c0c4e + 40ec2fb commit ac5e785

File tree

60 files changed

+2412
-395
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+2412
-395
lines changed

.github/actions/e2e/run-log-tests/action.yml

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: 'Run Tests'
1+
name: 'Run E2E Tests with Retry & Upload Logs'
22
description: 'Runs E2E tests with retry & upload logs and screenshots'
33

44
runs:
@@ -10,12 +10,17 @@ runs:
1010
shell: /bin/bash +e {0}
1111
run: |
1212
npm run test:e2e-ci
13-
14-
if [[ -f "$E2E_RESULT_FILEPATH" ]]; then
15-
E2E_NUM_FAILED_TEST_SUITES=$(cat "$E2E_RESULT_FILEPATH" | jq '.stats["unexpected"]')
16-
echo "FIRST_RUN_FAILED_TEST_SUITES=$(echo $E2E_NUM_FAILED_TEST_SUITES)" >> $GITHUB_OUTPUT
17-
if [[ ${E2E_NUM_FAILED_TEST_SUITES} -gt 0 ]]; then
18-
echo "::notice::${E2E_NUM_FAILED_TEST_SUITES} test suite(s) failed in the first run but we will try (it) them again in the second run."
13+
RESULTS_JSON="$E2E_RESULT_FILEPATH"
14+
if [[ -f "$RESULTS_JSON" ]]; then
15+
# Build unique list of spec files with any failed/unexpected/timedOut/interrupted result and count them.
16+
FAILED_SPECS_COUNT=$( jq -r '[ .. | objects | select(has("specs")) | .specs[]
17+
| select( ( any(.tests[]?; (.status=="unexpected") or (.status=="failed")) )
18+
or ( any(.tests[]?.results[]?; (.status=="failed") or (.status=="timedOut") or (.status=="interrupted")) ) )
19+
| .file ] | unique | length' "$RESULTS_JSON" )
20+
echo "FIRST_RUN_FAILED_TEST_SUITES=$FAILED_SPECS_COUNT" >> $GITHUB_OUTPUT
21+
echo "RESULTS_JSON=$RESULTS_JSON" >> $GITHUB_OUTPUT
22+
if [[ ${FAILED_SPECS_COUNT} -gt 0 ]]; then
23+
echo "::notice::${FAILED_SPECS_COUNT} spec file(s) failed in the first run. We will re-run only the failed specs."
1924
exit 0
2025
fi
2126
else
@@ -27,9 +32,32 @@ runs:
2732
- name: Re-try Failed E2E Files
2833
if: ${{ steps.first_run_e2e_tests.outputs.FIRST_RUN_FAILED_TEST_SUITES > 0 }}
2934
shell: bash
30-
# Filter failed E2E files from the result JSON file, and re-run them.
3135
run: |
32-
npm run test:e2e-ci $(cat $E2E_RESULT_FILEPATH | jq -r '[.suites[] | (if has("suites") then .suites[] | .specs[] else .specs[] end) | select(.tests[].status == "unexpected") | .file] | unique | .[]')
36+
set -e
37+
RESULTS_JSON="${{ steps.first_run_e2e_tests.outputs.RESULTS_JSON }}"
38+
echo "Using results file: $RESULTS_JSON"
39+
40+
# Build a unique list of spec files that had unexpected/failed outcomes.
41+
# This uses a recursive jq search to find any node with a 'specs' array, then selects specs
42+
# where any test result is marked unexpected/failed.
43+
mapfile -t FAILED_SPECS < <( jq -r '[ .. | objects | select(has("specs")) | .specs[]
44+
| select( ( any(.tests[]?; (.status=="unexpected") or (.status=="failed")) )
45+
or ( any(.tests[]?.results[]?; (.status=="failed") or (.status=="timedOut") or (.status=="interrupted")) ) )
46+
| .file ] | unique | .[]' "$RESULTS_JSON" )
47+
48+
if [[ ${#FAILED_SPECS[@]} -eq 0 ]]; then
49+
echo "::notice::No failed specs found in results file. Re-running full suite instead."
50+
npm run test:e2e-ci
51+
exit 0
52+
fi
53+
54+
echo "Retrying failed specs (${#FAILED_SPECS[@]}):"
55+
for f in "${FAILED_SPECS[@]}"; do
56+
echo " - $f"
57+
done
58+
59+
# Re-run only the failed spec files.
60+
npm run test:e2e-ci "${FAILED_SPECS[@]}"
3361
3462
# Archive screenshots if any
3563
- name: Archive e2e test screenshots & logs
@@ -41,5 +69,6 @@ runs:
4169
playwright-report/
4270
tests/e2e/test-results
4371
${{ env.E2E_RESULT_FILEPATH }}
72+
${{ steps.first_run_e2e_tests.outputs.RESULTS_JSON }}
4473
if-no-files-found: ignore
4574
retention-days: 14

.github/actions/setup-php/action.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: "Set up PHP"
2-
description: "Extracts the required PHP version from plugin file and uses it to build PHP."
2+
description: "Extracts the required PHP version from plugin file and uses it to build PHP. Can be overridden with E2E_PHP_VERSION environment variable."
33

44
runs:
55
using: composite
@@ -14,6 +14,6 @@ runs:
1414
- name: "Setup PHP"
1515
uses: shivammathur/setup-php@v2
1616
with:
17-
php-version: ${{ steps.get_min_php_version.outputs.MIN_PHP_VERSION }}
17+
php-version: ${{ env.E2E_PHP_VERSION || steps.get_min_php_version.outputs.MIN_PHP_VERSION }}
1818
tools: composer
1919
coverage: none

.github/scripts/README.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# GitHub Actions Scripts
2+
3+
This directory contains scripts used by GitHub Actions workflows for dynamic version management and matrix generation.
4+
5+
## Scripts
6+
7+
### `generate-wc-matrix.sh`
8+
9+
Generates the WooCommerce version matrix for E2E tests with dynamic version resolution and optimized PHP version strategy.
10+
11+
**Usage:**
12+
13+
```bash
14+
.github/scripts/generate-wc-matrix.sh
15+
```
16+
17+
**Output:**
18+
Single JSON object containing versions array and metadata:
19+
20+
```json
21+
{
22+
"versions": [
23+
"7.7.0",
24+
"9.9.5",
25+
"latest",
26+
"10.1.0-rc.2"
27+
],
28+
"metadata": {
29+
"l1_version": "9.9.5",
30+
"rc_version": "10.1.0-rc.2",
31+
"beta_version": null
32+
}
33+
}
34+
```
35+
36+
**Features:**
37+
38+
- Fetches latest WC version from WordPress.org API
39+
- Dynamically calculates L-1 version (latest stable in previous major branch)
40+
- Includes only L-1 and current major versions (skipping intermediate versions)
41+
- Dynamically resolves beta and RC versions from current major branch
42+
- Outputs structured JSON for easy parsing
43+
- Skips beta versions when not available
44+
- Provides debug output to stderr for troubleshooting
45+
46+
## Matrix Generation Strategy
47+
48+
### PHP Version Strategy
49+
50+
The workflow uses an optimized PHP version strategy to reduce job count while maintaining comprehensive coverage:
51+
52+
- **WC 7.7.0**: PHP 7.3 (legacy support - minimum required version)
53+
- **WC L-1**: PHP 8.3 (stable)
54+
- **WC latest**: PHP 8.3 (stable)
55+
- **WC beta**: PHP 8.3 (stable) - only when available
56+
- **WC rc**: PHP 8.4 (latest)
57+
58+
### Version Resolution
59+
60+
- **L-1 Version**: Extracted from JSON metadata
61+
- **Beta Version**: Extracted from JSON metadata, only included when available
62+
- **RC Version**: Always included - extracted from JSON metadata or falls back to string "rc"
63+
64+
## How It Works
65+
66+
### Script Execution
67+
68+
1. Fetches the latest WooCommerce version from `https://api.wordpress.org/plugins/info/1.0/woocommerce.json`
69+
2. Dynamically calculates the L-1 version by finding the latest stable version in the previous major branch
70+
3. Fetches beta and RC versions from the current major branch only
71+
4. Outputs JSON object to stdout for matrix generation
72+
73+
### Workflow Integration
74+
75+
1. Script runs and outputs structured JSON with versions and metadata
76+
2. Workflow extracts specific versions using standard JSON parsing
77+
3. Workflow builds optimized matrix with selective PHP version testing
78+
4. Matrix includes only necessary combinations to reduce job count
79+
80+
### Version Extraction
81+
82+
```bash
83+
# Get script result
84+
SCRIPT_RESULT=$( .github/scripts/generate-wc-matrix.sh )
85+
86+
# Extract versions and metadata using jq
87+
WC_VERSIONS=$(echo "$SCRIPT_RESULT" | jq -r '.versions')
88+
L1_VERSION=$(echo "$SCRIPT_RESULT" | jq -r '.metadata.l1_version')
89+
RC_VERSION=$(echo "$SCRIPT_RESULT" | jq -r '.metadata.rc_version')
90+
BETA_VERSION=$(echo "$SCRIPT_RESULT" | jq -r '.metadata.beta_version')
91+
```
92+
93+
## Dependencies
94+
95+
- `curl`: For API requests
96+
- `jq`: For JSON parsing and array generation
97+
- `bash`: For script execution
98+
99+
## Error Handling
100+
101+
- Scripts use `set -e` to exit on any error
102+
- Version extraction includes validation checks
103+
- Graceful handling of missing beta versions
104+
- If the API is unavailable or returns unexpected data, the workflow will fail gracefully
105+
106+
## Future Considerations
107+
108+
- Automatically adapts to new WooCommerce releases
109+
- Will include beta versions when they become available
110+
- Supports L-2 policy implementation if needed
111+
- Maintains business continuity with WC 7.7.0 support
Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
#!/bin/bash
2+
3+
# Script to dynamically generate WooCommerce version matrix for L-1 policy
4+
# This script fetches the latest WC version and calculates the L-1 version
5+
6+
set -e
7+
8+
# Function to get the latest WooCommerce version from WordPress.org API
9+
get_latest_wc_version() {
10+
curl -s https://api.wordpress.org/plugins/info/1.0/woocommerce.json | jq -r '.version'
11+
}
12+
13+
# Function to get the latest stable version for a specific major version
14+
get_latest_stable_for_major() {
15+
local major_version=$1
16+
curl -s https://api.wordpress.org/plugins/info/1.0/woocommerce.json | \
17+
jq -r --arg major "$major_version" '.versions | with_entries(select(.key | startswith($major + ".") and (contains("-") | not))) | keys | sort_by( . | split(".") | map(tonumber) ) | last'
18+
}
19+
20+
# Function to get the L-1 version (previous major version's latest stable)
21+
get_l1_version() {
22+
local latest_version=$1
23+
local major_version=$(echo "$latest_version" | cut -d. -f1)
24+
local l1_major=$((major_version - 1))
25+
get_latest_stable_for_major "$l1_major"
26+
}
27+
28+
# Function to get specific major versions' latest stable
29+
get_major_versions_latest() {
30+
local latest_version=$1
31+
local major_version=$(echo "$latest_version" | cut -d. -f1)
32+
local versions=()
33+
34+
# Dynamically calculate L-1 major version
35+
local l1_major=$((major_version - 1))
36+
37+
# Only get L-1 version (previous major) and current major
38+
# Skip intermediate major versions as they don't align with L-1 policy
39+
for ((i=l1_major; i<=major_version; i++)); do
40+
latest_stable=$(get_latest_stable_for_major "$i")
41+
if [[ -n "$latest_stable" && "$latest_stable" != "null" ]]; then
42+
versions+=("$latest_stable")
43+
fi
44+
done
45+
46+
echo "${versions[@]}"
47+
}
48+
49+
# Function to get the latest RC version from WordPress.org API
50+
get_latest_rc_version() {
51+
curl -s https://api.wordpress.org/plugins/info/1.0/woocommerce.json | \
52+
jq -r '.versions | with_entries(select(.key|match("rc";"i"))) | keys | sort_by( . | split("-")[0] | split(".") | map(tonumber) ) | last'
53+
}
54+
55+
# Function to get the latest beta version from WordPress.org API
56+
get_latest_beta_version() {
57+
local latest_version=$1
58+
local major_version=$(echo "$latest_version" | cut -d. -f1)
59+
curl -s https://api.wordpress.org/plugins/info/1.0/woocommerce.json | \
60+
jq -r --arg major "$major_version" '.versions | with_entries(select(.key | startswith($major + ".") and contains("beta"))) | keys | sort_by( . | split("-")[0] | split(".") | map(tonumber) ) | last'
61+
}
62+
63+
# Get the latest WooCommerce version
64+
echo "Fetching latest WooCommerce version..." >&2
65+
LATEST_WC_VERSION=$(get_latest_wc_version)
66+
echo "Latest WC version: $LATEST_WC_VERSION" >&2
67+
68+
# Get the L-1 version
69+
L1_VERSION=$(get_l1_version "$LATEST_WC_VERSION")
70+
echo "L-1 version: $L1_VERSION" >&2
71+
72+
# Get major versions latest stable
73+
MAJOR_VERSIONS=($(get_major_versions_latest "$LATEST_WC_VERSION"))
74+
echo "Major versions latest stable: ${MAJOR_VERSIONS[*]}" >&2
75+
76+
# Get latest RC and beta versions
77+
echo "Fetching latest RC and beta versions..." >&2
78+
LATEST_RC_VERSION=$(get_latest_rc_version)
79+
LATEST_BETA_VERSION=$(get_latest_beta_version "$LATEST_WC_VERSION")
80+
echo "Latest RC version: $LATEST_RC_VERSION" >&2
81+
echo "Latest beta version: $LATEST_BETA_VERSION" >&2
82+
83+
# Build the version array
84+
VERSIONS=("7.7.0") # Keep for business reasons (significant TPV)
85+
86+
# Add major versions latest stable (excluding current major since we'll use 'latest')
87+
for version in "${MAJOR_VERSIONS[@]}"; do
88+
# Skip the current major version since we'll use 'latest' instead
89+
if [[ "$version" != "$LATEST_WC_VERSION" ]]; then
90+
VERSIONS+=("$version")
91+
fi
92+
done
93+
94+
# Add latest, beta, rc (with actual versions)
95+
VERSIONS+=("latest")
96+
if [[ -n "$LATEST_BETA_VERSION" && "$LATEST_BETA_VERSION" != "null" ]]; then
97+
VERSIONS+=("$LATEST_BETA_VERSION")
98+
echo "Including beta version: $LATEST_BETA_VERSION" >&2
99+
else
100+
echo "No beta version available, skipping beta tests" >&2
101+
fi
102+
103+
# Decide whether to include RC: only include if RC base version (without suffix) is strictly greater than the latest stable.
104+
INCLUDED_RC_VERSION=""
105+
if [[ -n "$LATEST_RC_VERSION" && "$LATEST_RC_VERSION" != "null" ]]; then
106+
RC_BASE="${LATEST_RC_VERSION%%-*}"
107+
# Compare RC_BASE vs LATEST_WC_VERSION using sort -V
108+
HIGHEST=$(printf '%s\n%s\n' "$RC_BASE" "$LATEST_WC_VERSION" | sort -V | tail -n1)
109+
if [[ "$HIGHEST" == "$RC_BASE" && "$RC_BASE" != "$LATEST_WC_VERSION" ]]; then
110+
INCLUDED_RC_VERSION="$LATEST_RC_VERSION"
111+
VERSIONS+=("$LATEST_RC_VERSION")
112+
echo "Including RC version: $LATEST_RC_VERSION (base $RC_BASE > latest $LATEST_WC_VERSION)" >&2
113+
else
114+
echo "Skipping RC version $LATEST_RC_VERSION because stable $LATEST_WC_VERSION is already released for this line." >&2
115+
fi
116+
else
117+
echo "No RC version available, skipping rc tests" >&2
118+
fi
119+
120+
# Validate versions before output
121+
if [[ -z "$L1_VERSION" || "$L1_VERSION" == "null" ]]; then
122+
echo "Error: Could not extract L-1 version" >&2
123+
exit 1
124+
fi
125+
126+
if [[ ! "$L1_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
127+
echo "Error: Invalid L-1 version: $L1_VERSION" >&2
128+
exit 1
129+
fi
130+
131+
# RC is optional; do not fail if not present or skipped
132+
133+
# Only validate beta if it's available
134+
if [[ -n "$LATEST_BETA_VERSION" && "$LATEST_BETA_VERSION" != "null" ]]; then
135+
if [[ ! "$LATEST_BETA_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
136+
echo "Error: Invalid beta version: $LATEST_BETA_VERSION" >&2
137+
exit 1
138+
fi
139+
fi
140+
141+
# Convert to JSON array and output only the JSON (no extra whitespace or newlines)
142+
# Output a single JSON object with both versions and metadata
143+
RESULT=$(jq -n \
144+
--argjson versions "$(printf '%s\n' "${VERSIONS[@]}" | jq -R . | jq -s .)" \
145+
--arg l1_version "$L1_VERSION" \
146+
--arg rc_version "${INCLUDED_RC_VERSION}" \
147+
--arg beta_version "${LATEST_BETA_VERSION}" \
148+
'{
149+
versions: $versions,
150+
metadata: {
151+
l1_version: $l1_version,
152+
rc_version: (if ($rc_version // "") == "" or ($rc_version == "null") then null else $rc_version end),
153+
beta_version: (if ($beta_version // "") == "" or ($beta_version == "null") then null else $beta_version end)
154+
}
155+
}')
156+
157+
echo "$RESULT"

0 commit comments

Comments
 (0)