Skip to content

Replace pull_request_target with pull_request in CI workflow #790

Replace pull_request_target with pull_request in CI workflow

Replace pull_request_target with pull_request in CI workflow #790

Workflow file for this run

name: TestBench Validation
on:
pull_request:
branches:
- main
types: [opened, synchronize, reopened, edited]
workflow_dispatch:
permissions:
contents: read
concurrency:
group: ${{ github.head_ref || github.ref_name }}
cancel-in-progress: true
env:
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true
HEAD_REF: ${{ github.head_ref }}
REF_NAME: ${{ github.ref_name }}
BASE_REF: ${{ github.event.pull_request.base.ref }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
PR_NUMBER: ${{ github.event.number }}
JAVA_VERSION: 21
jobs:
format-check:
name: Format Check
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
ref: ${{ env.HEAD_SHA }}
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "temurin"
- name: Cache Maven dependencies
uses: actions/cache@v5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-
- name: Run spotless validation
run: mvn spotless:check --batch-mode --no-transfer-progress
build:
name: Build Project
needs: format-check
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
ref: ${{ env.HEAD_SHA }}
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "temurin"
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "20"
- name: Cache Maven dependencies
uses: actions/cache@v5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-maven-
- name: Clean Maven cache (if needed)
if: github.event_name == 'workflow_dispatch'
run: |
echo "---> Clean maven cache"
rm -rf ~/.m2/repository ~/.npm* ~/.pnpm*
- name: Build with Maven and Generate Javadoc
run: mvn clean install javadoc:javadoc -DskipTests -Dtestbench.javadocs -B
unit-tests:
name: Unit Tests
needs: build
if: ${{ !github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest
timeout-minutes: 15
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
ref: ${{ env.HEAD_SHA }}
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "temurin"
- name: Restore Maven cache
uses: actions/cache/restore@v5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
- name: Set TB License
run: |
TB_LICENSE=${{secrets.TB_LICENSE}}
mkdir -p ~/.vaadin/
echo '{"username":"'`echo $TB_LICENSE | cut -d / -f1`'","proKey":"'`echo $TB_LICENSE | cut -d / -f2`'"}' > ~/.vaadin/proKey
- name: Run unit tests
run: |
mvn test -B
- name: Upload test results
if: always()
uses: actions/upload-artifact@v5
with:
name: unit-test-results
path: |
**/target/surefire-reports/TEST-*.xml
retention-days: 7
integration-tests:
name: Integration Tests (${{ matrix.name }})
needs: build
if: ${{ !github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest
timeout-minutes: 45
concurrency:
group: saucelabs-testbench # Global queue for SauceLabs tests only
cancel-in-progress: false
strategy:
max-parallel: 1 # Only one JUnit version at a time to stay within SauceLabs limit
matrix:
include:
- name: JUnit 4
module: vaadin-testbench-integration-tests
- name: JUnit 5
module: vaadin-testbench-integration-tests-junit5
- name: JUnit 6
module: vaadin-testbench-integration-tests-junit6
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
ref: ${{ env.HEAD_SHA }}
fetch-depth: 0
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "temurin"
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "20"
- name: Restore Maven cache
uses: actions/cache/restore@v5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
- name: Set up Sauce Labs tunnel
uses: saucelabs/sauce-connect-action@v3.0.0
with:
username: ${{ secrets.SAUCE_USERNAME }}
accessKey: ${{ secrets.SAUCE_ACCESS_KEY }}
tunnelName: ${{ github.run_id }}-${{ github.run_number }}
region: us-west-1
retryTimeout: 300
proxyLocalhost: allow
- name: Wait for Sauce Labs tunnel to be ready
env:
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
SAUCE_TUNNEL_ID: ${{ github.run_id }}-${{ github.run_number }}
run: |
# sauce-connect-action returns once the local process is up, but the tunnel
# can still be propagating on the Sauce side — poll the REST API until it
# actually shows as running before launching 25 parallel sessions.
# ?full=1 returns tunnel objects (not just IDs). sauce-connect-action@v3 uses
# Sauce Connect 5 which stores the name in `tunnel_name`; fall back to
# `tunnel_identifier` for SC4-era responses just in case.
URL="https://api.us-west-1.saucelabs.com/rest/v1/${SAUCE_USERNAME}/tunnels?full=1&filter=running"
echo "Probing Sauce Labs for tunnel ${SAUCE_TUNNEL_ID}..."
LAST_RESPONSE=""
for i in $(seq 1 30); do
if RESPONSE=$(curl -sSf -u "${SAUCE_USERNAME}:${SAUCE_ACCESS_KEY}" "$URL"); then
LAST_RESPONSE="$RESPONSE"
if echo "$RESPONSE" | jq -e --arg id "$SAUCE_TUNNEL_ID" \
'any(.[]; (.tunnel_name // .tunnel_identifier) == $id and (.status // "running") == "running")' > /dev/null; then
echo "Tunnel ${SAUCE_TUNNEL_ID} is running (attempt $i)."
# Grace period to let the tunnel fully stabilize before 25 parallel sessions hit it
sleep 10
exit 0
fi
echo "Tunnel not listed yet (attempt $i/30), sleeping 5s..."
else
echo "Sauce API request failed (attempt $i/30), sleeping 5s..." >&2
fi
sleep 5
done
echo "Tunnel ${SAUCE_TUNNEL_ID} did not become ready in time" >&2
echo "Last response from Sauce API:" >&2
echo "$LAST_RESPONSE" | jq '.' >&2 || echo "$LAST_RESPONSE" >&2
exit 1
- name: Set TB License
run: |
TB_LICENSE=${{secrets.TB_LICENSE}}
mkdir -p ~/.vaadin/
echo '{"username":"'`echo $TB_LICENSE | cut -d / -f1`'","proKey":"'`echo $TB_LICENSE | cut -d / -f2`'"}' > ~/.vaadin/proKey
- name: Run Integration Tests
env:
SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }}
SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }}
SAUCE_TUNNEL_ID: ${{ github.run_id }}-${{ github.run_number }}
run: |
mvn verify \
-pl ${{ matrix.module }} -am \
-P validation \
-DskipUnitTests \
-Dsystem.com.vaadin.testbench.Parameters.testsInParallel=5 \
-Dsystem.com.vaadin.testbench.Parameters.maxAttempts=2 \
-Dcom.vaadin.testbench.Parameters.hubHostname=localhost \
-Dsauce.tunnelId=${SAUCE_TUNNEL_ID} \
-Dfailsafe.forkCount=5 \
-Dsystem.sauce.user=${SAUCE_USERNAME} \
-Dsystem.sauce.sauceAccessKey=${SAUCE_ACCESS_KEY} \
-B
- name: Upload error screenshots
if: failure()
uses: actions/upload-artifact@v5
with:
name: error-screenshots-${{ matrix.name }}
path: |
**/error-screenshots/**
retention-days: 7
- name: Upload test results
if: always()
uses: actions/upload-artifact@v5
with:
name: integration-test-results-${{ matrix.name }}
path: |
**/target/failsafe-reports/TEST-*.xml
retention-days: 7
loadtest-converter-tests:
name: Load Test Converter Plugin ITs
needs: build
if: ${{ !github.event.pull_request.head.repo.fork }}
runs-on: ubuntu-latest
timeout-minutes: 30
steps:
- name: Checkout repository
uses: actions/checkout@v5
with:
ref: ${{ env.HEAD_SHA }}
- name: Set up JDK ${{ env.JAVA_VERSION }}
uses: actions/setup-java@v5
with:
java-version: ${{ env.JAVA_VERSION }}
distribution: "temurin"
- name: Set up Node.js
uses: actions/setup-node@v5
with:
node-version: "20"
- name: Restore Maven cache
uses: actions/cache/restore@v5
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}-${{ github.run_id }}
- name: Set TB License
run: |
TB_LICENSE=${{secrets.TB_LICENSE}}
mkdir -p ~/.vaadin/
echo '{"username":"'`echo $TB_LICENSE | cut -d / -f1`'","proKey":"'`echo $TB_LICENSE | cut -d / -f2`'"}' > ~/.vaadin/proKey
- name: Run Maven Invoker Tests
run: |
mvn verify \
-pl vaadin-testbench-loadtest/testbench-converter-plugin -am \
-P maven-invoker-it \
-DskipUnitTests \
-B
- name: Upload invoker logs
if: always()
uses: actions/upload-artifact@v5
with:
name: loadtest-converter-invoker-logs
path: |
vaadin-testbench-loadtest/testbench-converter-plugin/target/its/**/build.log
vaadin-testbench-loadtest/testbench-converter-plugin/target/invoker-reports/**
retention-days: 7
validation-status:
name: Validation Status
permissions:
actions: write
issues: read
checks: write
pull-requests: write
if: ${{ always() && !github.event.pull_request.head.repo.fork }}
needs: [format-check, build, unit-tests, integration-tests, loadtest-converter-tests]
runs-on: ubuntu-latest
steps:
- name: Merge test result artifacts
uses: actions/upload-artifact/merge@v5
with:
name: test-results
pattern: '{unit-test-results,integration-test-results-*}'
delete-merged: true
- name: Download merged test results
uses: actions/download-artifact@v5
with:
name: test-results
- name: Publish test results
uses: EnricoMi/publish-unit-test-result-action@v2
with:
files: '**/TEST-*.xml'
check_name: Test Results
comment_mode: failures
- name: Check all jobs status
run: |
echo "format-check: ${{ needs.format-check.result }}"
echo "build: ${{ needs.build.result }}"
echo "unit-tests: ${{ needs.unit-tests.result }}"
echo "integration-tests: ${{ needs.integration-tests.result }}"
echo "loadtest-converter-tests: ${{ needs.loadtest-converter-tests.result }}"
if [ "${{ needs.format-check.result }}" != "success" ] || \
[ "${{ needs.build.result }}" != "success" ] || \
[ "${{ needs.unit-tests.result }}" != "success" ] || \
[ "${{ needs.integration-tests.result }}" != "success" ] || \
[ "${{ needs.loadtest-converter-tests.result }}" != "success" ]; then
echo "One or more validation jobs failed"
exit 1
fi
echo "All validation jobs completed successfully"