Release test workflow: support WooAF draft releases (#40786)

This commit is contained in:
nigeljamesstevenson 2023-10-17 14:19:46 +01:00 committed by GitHub
commit bfb47ee8aa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 393 additions and 207 deletions

View File

@ -0,0 +1,19 @@
module.exports = async ( { github, context, core } ) => {
const { ASSET_ID: asset_id } = process.env;
const { owner, repo } = context.repo;
const fs = require( 'fs' );
const path = require( 'path' );
const response = await github.rest.repos.getReleaseAsset( {
owner,
repo,
asset_id,
headers: { accept: 'application/octet-stream' },
} );
const zipPath = path.resolve( 'tmp', 'woocommerce.zip' );
fs.mkdirSync( 'tmp' );
fs.writeFileSync( zipPath, Buffer.from( response.data ) );
core.setOutput( 'zip-path', zipPath );
};

View File

@ -0,0 +1,51 @@
module.exports = async ( { github, context, core } ) => {
const { RELEASE_VERSION, GITHUB_EVENT_NAME } = process.env;
async function findRelease() {
const { owner, repo } = context.repo;
const list = await github.rest.repos.listReleases( {
owner,
repo,
per_page: 100,
} );
const match = list.data.find( ( { tag_name, name } ) =>
[ tag_name, name ].includes( RELEASE_VERSION )
);
return match;
}
async function handleWorkflowDispatch() {
const match = await findRelease();
if ( match ) {
return match;
}
throw new Error(
`"${ RELEASE_VERSION }" is not a valid release version!`
);
}
function findWooCommerceZipAsset() {
const match = release.assets.find(
( { name } ) => name === 'woocommerce.zip'
);
if ( ! match ) {
throw new Error(
`Release ${ RELEASE_VERSION } does not contain a woocommerce.zip asset!`
);
}
return match;
}
const release =
GITHUB_EVENT_NAME === 'release'
? await findRelease()
: await handleWorkflowDispatch();
const asset = findWooCommerceZipAsset();
core.setOutput( 'version', RELEASE_VERSION );
core.setOutput( 'created', release.created_at );
core.setOutput( 'asset-id', asset.id );
};

View File

@ -5,7 +5,7 @@ on:
workflow_dispatch: workflow_dispatch:
inputs: inputs:
tag: tag:
description: 'WooCommerce Release Tag' description: 'WooCommerce release version'
required: true required: true
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.event.release.tag_name || inputs.tag }} group: ${{ github.workflow }}-${{ github.event.release.tag_name || inputs.tag }}
@ -16,55 +16,33 @@ env:
E2E_UPDATE_WC_ARTIFACT: WooCommerce version update test on release smoke test site (run ${{ github.run_number }}) E2E_UPDATE_WC_ARTIFACT: WooCommerce version update test on release smoke test site (run ${{ github.run_number }})
SLACK_BLOCKS_ARTIFACT: slack-blocks SLACK_BLOCKS_ARTIFACT: slack-blocks
jobs: jobs:
get-tag: validate-version:
name: Get WooCommerce release tag name: Validate release version
permissions: permissions:
contents: read contents: read
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
outputs: outputs:
tag: ${{ steps.get-tag.outputs.tag }} version: ${{ steps.validate-version.outputs.version }}
created: ${{ steps.created-at.outputs.created }} created: ${{ steps.validate-version.outputs.created }}
asset-id: ${{ steps.validate-version.outputs.asset-id }}
steps: steps:
- name: Validate tag - uses: actions/checkout@v3
if: ${{ github.event_name == 'workflow_dispatch' }}
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: gh release view "${{ inputs.tag }}" --repo=woocommerce/woocommerce
- name: Get tag from triggered event - name: Validate release version
id: get-tag id: validate-version
uses: actions/github-script@v6
env: env:
RELEASE_TAG: ${{ github.event.release.tag_name || inputs.tag }} RELEASE_VERSION: ${{ inputs.tag }}
run: | with:
echo "Triggered event: ${{ github.event_name }}" github-token: ${{ secrets.E2E_GH_TOKEN }}
echo "Tag from event: $RELEASE_TAG" script: |
echo "tag=$RELEASE_TAG" >> $GITHUB_OUTPUT const script = require('./.github/workflows/scripts/validate-release-version.js');
await script({ github, context, core });
- name: Verify woocommerce.zip asset
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
RELEASE_TAG: ${{ steps.get-tag.outputs.tag }}
run: |
ASSET_NAMES=$(gh release view $RELEASE_TAG --repo woocommerce/woocommerce --json assets --jq ".assets[].name")
if [[ $ASSET_NAMES == *"woocommerce.zip"* ]]
then
echo "$RELEASE_TAG has a valid woocommerce.zip asset."
exit 0
fi
echo "$RELEASE_TAG does not have a valid woocommerce.zip asset."
exit 1
- name: Get 'created-at' of WooCommerce zip
id: created-at
env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
run: echo "created=$(gh release view ${{ steps.get-tag.outputs.tag }} --json assets --jq .assets[0].createdAt --repo woocommerce/woocommerce)" >> $GITHUB_OUTPUT
e2e-update-wc: e2e-update-wc:
name: Test WooCommerce update name: Test WooCommerce update
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
needs: [get-tag] needs: [validate-version]
permissions: permissions:
contents: read contents: read
env: env:
@ -94,7 +72,7 @@ jobs:
CUSTOMER_USER: ${{ secrets.RELEASE_TEST_CUSTOMER_USER }} CUSTOMER_USER: ${{ secrets.RELEASE_TEST_CUSTOMER_USER }}
DEFAULT_TIMEOUT_OVERRIDE: 120000 DEFAULT_TIMEOUT_OVERRIDE: 120000
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }} GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
UPDATE_WC: ${{ needs.get-tag.outputs.tag }} UPDATE_WC: ${{ needs.validate-version.outputs.version }}
- name: Upload Allure artifacts to bucket - name: Upload Allure artifacts to bucket
if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' ) if: success() || ( failure() && steps.run-e2e-composite-action.conclusion == 'failure' )
@ -113,10 +91,10 @@ jobs:
ENV_DESCRIPTION: wp-latest ENV_DESCRIPTION: wp-latest
run: | run: |
gh workflow run publish-test-reports-release.yml \ gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \ -f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \ -f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \ -f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \ -f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_WP_LATEST_ARTIFACT }}" \ -f artifact="${{ env.E2E_WP_LATEST_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \ -f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \ -f test_type="e2e" \
@ -132,12 +110,12 @@ jobs:
test-name: WC Update test test-name: WC Update test
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }} e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: wp-latest env-slug: wp-latest
release-version: ${{ needs.get-tag.outputs.tag }} release-version: ${{ needs.validate-version.outputs.version }}
api-wp-latest: api-wp-latest:
name: API on WP Latest name: API on WP Latest
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
needs: [get-tag, e2e-update-wc] needs: [validate-version, e2e-update-wc]
permissions: permissions:
contents: read contents: read
outputs: outputs:
@ -170,7 +148,8 @@ jobs:
API_BASE_URL: ${{ secrets.RELEASE_TEST_URL }} API_BASE_URL: ${{ secrets.RELEASE_TEST_URL }}
USER_KEY: ${{ secrets.RELEASE_TEST_ADMIN_USER }} USER_KEY: ${{ secrets.RELEASE_TEST_ADMIN_USER }}
USER_SECRET: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }} USER_SECRET: ${{ secrets.RELEASE_TEST_ADMIN_PASSWORD }}
UPDATE_WC: ${{ needs.get-tag.outputs.tag }} UPDATE_WC: ${{ needs.validate-version.outputs.version }}
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
- name: Upload Allure artifacts to bucket - name: Upload Allure artifacts to bucket
if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' ) if: success() || ( failure() && steps.run-api-composite-action.conclusion == 'failure' )
@ -189,10 +168,10 @@ jobs:
ENV_DESCRIPTION: wp-latest ENV_DESCRIPTION: wp-latest
run: | run: |
gh workflow run publish-test-reports-release.yml \ gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \ -f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \ -f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \ -f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \ -f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.API_WP_LATEST_ARTIFACT }}" \ -f artifact="${{ env.API_WP_LATEST_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \ -f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="api" \ -f test_type="api" \
@ -208,12 +187,12 @@ jobs:
test-name: WP Latest test-name: WP Latest
api-result: ${{ steps.run-api-composite-action.outputs.result }} api-result: ${{ steps.run-api-composite-action.outputs.result }}
env-slug: wp-latest env-slug: wp-latest
release-version: ${{ needs.get-tag.outputs.tag }} release-version: ${{ needs.validate-version.outputs.version }}
e2e-wp-latest: e2e-wp-latest:
name: E2E on WP Latest name: E2E on WP Latest
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
needs: [get-tag, api-wp-latest] needs: [validate-version, api-wp-latest]
permissions: permissions:
contents: read contents: read
env: env:
@ -291,10 +270,10 @@ jobs:
ENV_DESCRIPTION: wp-latest ENV_DESCRIPTION: wp-latest
run: | run: |
gh workflow run publish-test-reports-release.yml \ gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \ -f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \ -f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \ -f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \ -f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_WP_LATEST_ARTIFACT }}" \ -f artifact="${{ env.E2E_WP_LATEST_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \ -f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \ -f test_type="e2e" \
@ -311,12 +290,12 @@ jobs:
api-result: ${{ needs.api-wp-latest.outputs.result }} api-result: ${{ needs.api-wp-latest.outputs.result }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }} e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: wp-latest env-slug: wp-latest
release-version: ${{ needs.get-tag.outputs.tag }} release-version: ${{ needs.validate-version.outputs.version }}
test-wp-latest-1: test-wp-latest-1:
name: Test against WP Latest-1 name: Test against WP Latest-1
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
needs: [ get-tag ] needs: [validate-version]
env: env:
API_ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/api/allure-report API_ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/api/allure-report
API_ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/api/allure-results API_ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/test-results/api/allure-results
@ -350,12 +329,20 @@ jobs:
WP_ENV_CORE: WordPress/WordPress#${{ steps.get-wp-latest-1.outputs.version }} WP_ENV_CORE: WordPress/WordPress#${{ steps.get-wp-latest-1.outputs.version }}
- name: Download release zip - name: Download release zip
id: download-zip
uses: actions/github-script@v6
env: env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }} ASSET_ID: ${{ needs.validate-version.outputs.asset-id }}
run: gh release download ${{ steps.get-wp-latest-1.outputs.version }} --dir tmp with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/download-release-zip.js');
await script({ github, context, core });
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build - name: Replace `plugins/woocommerce` with unzipped woocommerce release build
run: unzip -d plugins -o tmp/woocommerce.zip run: unzip -d plugins -o ${{ env.ZIP_PATH }}
env:
ZIP_PATH: ${{ steps.download-zip.outputs.zip-path }}
- name: Run API tests - name: Run API tests
id: run-api-composite-action id: run-api-composite-action
@ -387,10 +374,10 @@ jobs:
ENV_DESCRIPTION: wp-latest-1 ENV_DESCRIPTION: wp-latest-1
run: | run: |
gh workflow run publish-test-reports-release.yml \ gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \ -f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \ -f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \ -f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \ -f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.API_WP_LATEST_X_ARTIFACT }}" \ -f artifact="${{ env.API_WP_LATEST_X_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \ -f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="api" \ -f test_type="api" \
@ -428,10 +415,10 @@ jobs:
ENV_DESCRIPTION: wp-latest-1 ENV_DESCRIPTION: wp-latest-1
run: | run: |
gh workflow run publish-test-reports-release.yml \ gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \ -f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \ -f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \ -f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \ -f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_WP_LATEST_X_ARTIFACT }}" \ -f artifact="${{ env.E2E_WP_LATEST_X_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \ -f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \ -f test_type="e2e" \
@ -451,12 +438,12 @@ jobs:
api-result: ${{ steps.run-api-composite-action.outputs.result }} api-result: ${{ steps.run-api-composite-action.outputs.result }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }} e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: wp-latest-1 env-slug: wp-latest-1
release-version: ${{ needs.get-tag.outputs.tag }} release-version: ${{ needs.validate-version.outputs.version }}
test-php-versions: test-php-versions:
name: Test against PHP ${{ matrix.php_version }} name: Test against PHP ${{ matrix.php_version }}
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
needs: [get-tag] needs: [validate-version]
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -490,12 +477,20 @@ jobs:
run: bash verify-php-version.sh run: bash verify-php-version.sh
- name: Download release zip - name: Download release zip
id: download-zip
uses: actions/github-script@v6
env: env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }} ASSET_ID: ${{ needs.validate-version.outputs.asset-id }}
run: gh release download ${{ needs.get-tag.outputs.tag }} --dir tmp with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/download-release-zip.js');
await script({ github, context, core });
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build - name: Replace `plugins/woocommerce` with unzipped woocommerce release build
run: unzip -d plugins -o tmp/woocommerce.zip run: unzip -d plugins -o ${{ env.ZIP_PATH }}
env:
ZIP_PATH: ${{ steps.download-zip.outputs.zip-path }}
- name: Run API tests - name: Run API tests
id: run-api-composite-action id: run-api-composite-action
@ -527,10 +522,10 @@ jobs:
ENV_DESCRIPTION: php-${{ matrix.php_version }} ENV_DESCRIPTION: php-${{ matrix.php_version }}
run: | run: |
gh workflow run publish-test-reports-release.yml \ gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \ -f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \ -f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \ -f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \ -f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.API_ARTIFACT }}" \ -f artifact="${{ env.API_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \ -f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="api" \ -f test_type="api" \
@ -568,10 +563,10 @@ jobs:
ENV_DESCRIPTION: php-${{ matrix.php_version }} ENV_DESCRIPTION: php-${{ matrix.php_version }}
run: | run: |
gh workflow run publish-test-reports-release.yml \ gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \ -f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \ -f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \ -f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \ -f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.E2E_ARTIFACT }}" \ -f artifact="${{ env.E2E_ARTIFACT }}" \
-f env_description="${{ env.ENV_DESCRIPTION }}" \ -f env_description="${{ env.ENV_DESCRIPTION }}" \
-f test_type="e2e" \ -f test_type="e2e" \
@ -591,12 +586,12 @@ jobs:
api-result: ${{ steps.run-api-composite-action.outputs.result }} api-result: ${{ steps.run-api-composite-action.outputs.result }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }} e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: php-${{ matrix.php_version }} env-slug: php-${{ matrix.php_version }}
release-version: ${{ needs.get-tag.outputs.tag }} release-version: ${{ needs.validate-version.outputs.version }}
test-plugins: test-plugins:
name: With ${{ matrix.plugin }} name: With ${{ matrix.plugin }}
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
needs: [get-tag] needs: [validate-version]
env: env:
ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-results ALLURE_RESULTS_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-results
ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-report ALLURE_REPORT_DIR: ${{ github.workspace }}/plugins/woocommerce/tests/e2e-pw/allure-report
@ -638,12 +633,20 @@ jobs:
run: pnpm run env:test run: pnpm run env:test
- name: Download release zip - name: Download release zip
id: download-zip
uses: actions/github-script@v6
env: env:
GH_TOKEN: ${{ secrets.E2E_GH_TOKEN }} ASSET_ID: ${{ needs.validate-version.outputs.asset-id }}
run: gh release download ${{ needs.get-tag.outputs.tag }} --dir tmp with:
github-token: ${{ secrets.E2E_GH_TOKEN }}
script: |
const script = require('./.github/workflows/scripts/download-release-zip.js');
await script({ github, context, core });
- name: Replace `plugins/woocommerce` with unzipped woocommerce release build - name: Replace `plugins/woocommerce` with unzipped woocommerce release build
run: unzip -d plugins -o tmp/woocommerce.zip run: unzip -d plugins -o ${{ env.ZIP_PATH }}
env:
ZIP_PATH: ${{ steps.download-zip.outputs.zip-path }}
- name: Run 'Upload plugin' test - name: Run 'Upload plugin' test
id: run-upload-test id: run-upload-test
@ -686,10 +689,10 @@ jobs:
GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }} GITHUB_TOKEN: ${{ secrets.REPORTS_TOKEN }}
run: | run: |
gh workflow run publish-test-reports-release.yml \ gh workflow run publish-test-reports-release.yml \
-f created_at="${{ needs.get-tag.outputs.created }}" \ -f created_at="${{ needs.validate-version.outputs.created }}" \
-f run_id=${{ github.run_id }} \ -f run_id=${{ github.run_id }} \
-f run_number=${{ github.run_number }} \ -f run_number=${{ github.run_number }} \
-f release_tag=${{ needs.get-tag.outputs.tag }} \ -f release_tag=${{ needs.validate-version.outputs.version }} \
-f artifact="${{ env.ARTIFACT_NAME }}" \ -f artifact="${{ env.ARTIFACT_NAME }}" \
-f env_description="${{ matrix.env_description }}" \ -f env_description="${{ matrix.env_description }}" \
-f test_type="e2e" \ -f test_type="e2e" \
@ -704,7 +707,7 @@ jobs:
test-name: With ${{ matrix.plugin }} test-name: With ${{ matrix.plugin }}
e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }} e2e-result: ${{ steps.run-e2e-composite-action.outputs.result }}
env-slug: ${{ matrix.env_description }} env-slug: ${{ matrix.env_description }}
release-version: ${{ needs.get-tag.outputs.tag }} release-version: ${{ needs.validate-version.outputs.version }}
post-slack-summary: post-slack-summary:
name: Post Slack summary name: Post Slack summary
@ -717,7 +720,7 @@ jobs:
) )
needs: needs:
- e2e-wp-latest - e2e-wp-latest
- get-tag - validate-version
- test-php-versions - test-php-versions
- test-plugins - test-plugins
- test-wp-latest-1 - test-wp-latest-1
@ -735,7 +738,7 @@ jobs:
id: run-payload-action id: run-payload-action
uses: ./.github/actions/tests/slack-summary-on-release/slack-payload uses: ./.github/actions/tests/slack-summary-on-release/slack-payload
with: with:
release-version: ${{ needs.get-tag.outputs.tag }} release-version: ${{ needs.validate-version.outputs.version }}
blocks-dir: ${{ steps.download-slack-blocks.outputs.download-path }} blocks-dir: ${{ steps.download-slack-blocks.outputs.download-path }}
- name: Send Slack message - name: Send Slack message

View File

@ -0,0 +1,4 @@
Significance: patch
Type: dev
Update release test workflow to support release drafts.

View File

@ -1,21 +1,19 @@
const { UPDATE_WC, USER_KEY, USER_SECRET } = process.env; const { UPDATE_WC, USER_KEY, USER_SECRET } = process.env;
const { test, expect } = require( '@playwright/test' ); const { test: setup, expect } = require( '@playwright/test' );
const path = require( 'path' );
const fs = require( 'fs' ); const fs = require( 'fs' );
const { downloadWooCommerceRelease } = require( './utils/plugin-utils' );
const pluginEndpoint = '/wp-json/wp/v2/plugins/woocommerce/woocommerce';
const zipPath = path.resolve( 'tmp', 'woocommerce.zip' ); let zipPath;
const downloadURL = `https://github.com/woocommerce/woocommerce/releases/download/${ UPDATE_WC }/woocommerce.zip`;
test( `Setup remote test site`, async ( { page, request } ) => { setup( `Setup remote test site`, async ( { page, request } ) => {
await test.step( `Download WooCommerce build zip`, async () => { setup.setTimeout( 5 * 60 * 1000 );
const response = await request.get( downloadURL );
expect( response.ok() ).toBeTruthy(); await setup.step( `Download WooCommerce build zip`, async () => {
const body = await response.body(); zipPath = await downloadWooCommerceRelease( { request } );
fs.mkdirSync( 'tmp', { recursive: true } );
fs.writeFileSync( zipPath, body );
} ); } );
await test.step( 'Login to wp-admin', async () => { await setup.step( 'Login to wp-admin', async () => {
const Username = 'Username or Email Address'; const Username = 'Username or Email Address';
const Password = 'Password'; const Password = 'Password';
const Log_In = 'Log In'; const Log_In = 'Log In';
@ -33,75 +31,92 @@ test( `Setup remote test site`, async ( { page, request } ) => {
).toBeVisible(); ).toBeVisible();
} ); } );
await test.step( `Deactivate currently installed WooCommerce version`, async () => { const installed = await setup.step(
const response = await request.put( `See if there's a WooCommerce plugin installed`,
'/wp-json/wp/v2/plugins/woocommerce/woocommerce', async () => {
{ const response = await request.get( pluginEndpoint );
const isOK = response.ok();
const status = response.status();
// Fast-fail if response was neither OK nor 404.
expect( isOK || status === 404 ).toEqual( true );
return isOK;
}
);
await setup.step(
`Deactivate currently installed WooCommerce version`,
async () => {
if ( ! installed ) {
return;
}
const options = {
data: { data: {
status: 'inactive', status: 'inactive',
}, },
};
const response = await request.put( pluginEndpoint, options );
expect( response.ok() ).toBeTruthy();
} }
); );
expect( response.ok() ).toBeTruthy();
} );
await test.step( `Delete currently installed WooCommerce version`, async () => { await setup.step(
const response = await request.delete( `Delete currently installed WooCommerce version`,
'/wp-json/wp/v2/plugins/woocommerce/woocommerce' async () => {
if ( ! installed ) {
return;
}
const response = await request.delete( pluginEndpoint );
expect( response.ok() ).toBeTruthy();
}
); );
expect( response.ok() ).toBeTruthy();
} );
await test.step( `Install WooCommerce ${ UPDATE_WC }`, async () => { await setup.step( `Install WooCommerce ${ UPDATE_WC }`, async () => {
const Upload_Plugin = 'Upload Plugin'; const Upload_Plugin = 'Upload Plugin';
const Plugin_zip_file = 'Plugin zip file'; const Plugin_zip_file = 'Plugin zip file';
const Install_Now = 'Install Now'; const Install_Now = 'Install Now';
const Activate_Plugin = 'Activate Plugin'; const Activate_Plugin = 'Activate Plugin';
const timeout = 3 * 60 * 1000;
await page.goto( '/wp-admin/plugin-install.php' ); await page.goto( '/wp-admin/plugin-install.php' );
await page.getByRole( 'button', { name: Upload_Plugin } ).click(); await page.getByRole( 'button', { name: Upload_Plugin } ).click();
await page.getByLabel( Plugin_zip_file ).setInputFiles( zipPath ); await page.getByLabel( Plugin_zip_file ).setInputFiles( zipPath );
await page.getByRole( 'button', { name: Install_Now } ).click(); await page.getByRole( 'button', { name: Install_Now } ).click();
const uploadResponse = await page.waitForResponse(
'**/wp-admin/update.php?action=upload-plugin'
);;
expect( uploadResponse.ok() ).toBeTruthy();
await expect( await expect(
page.getByRole( 'link', { name: Activate_Plugin } ) page.getByRole( 'link', { name: Activate_Plugin } )
).toBeVisible(); ).toBeVisible( { timeout } );
} ); } );
await test.step( `Activate WooCommerce`, async () => { await setup.step( `Activate WooCommerce`, async () => {
const response = await request.put( const options = {
'/wp-json/wp/v2/plugins/woocommerce/woocommerce',
{
data: { data: {
status: 'active', status: 'active',
}, },
} };
); const response = await request.put( pluginEndpoint, options );
expect( response.ok() ).toBeTruthy(); expect( response.ok() ).toBeTruthy();
} ); } );
await test.step( `Verify WooCommerce version was installed`, async () => { await setup.step( `Verify WooCommerce version was installed`, async () => {
const response = await request.get( const response = await request.get( pluginEndpoint );
'/wp-json/wp/v2/plugins/woocommerce/woocommerce'
);
const { status, version } = await response.json(); const { status, version } = await response.json();
expect( status ).toEqual( 'active' ); expect( status ).toEqual( 'active' );
expect( version ).toEqual( UPDATE_WC ); expect( version ).toEqual( UPDATE_WC );
} ); } );
await test.step( `Verify WooCommerce database version`, async () => { await setup.step( `Verify WooCommerce database version`, async () => {
const response = await request.get( '/wp-json/wc/v3/system_status' ); const response = await request.get( '/wp-json/wc/v3/system_status' );
const { database } = await response.json(); const { database } = await response.json();
const { wc_database_version } = database; const { wc_database_version } = database;
const [major, minor] = UPDATE_WC.split( '.' ); const [ major, minor ] = UPDATE_WC.split( '.' );
const pattern = new RegExp( `^${ major }\.${ minor }` ); const pattern = new RegExp( `^${ major }\.${ minor }` );
expect( wc_database_version ).toMatch( pattern ); expect( wc_database_version ).toMatch( pattern );
} ); } );
await test.step( `Delete zip`, async () => { await setup.step( `Delete zip`, async () => {
fs.unlinkSync( zipPath ); fs.unlinkSync( zipPath );
} ); } );
} ); } );

View File

@ -1,4 +1,5 @@
const defaultConfig = require( './playwright.config' ); const defaultConfig = require( './playwright.config' );
const { devices } = require( '@playwright/test' );
// Global setup will be done through the 'Setup' project, not through the `globalSetup` property // Global setup will be done through the 'Setup' project, not through the `globalSetup` property
delete defaultConfig[ 'globalSetup' ]; delete defaultConfig[ 'globalSetup' ];
@ -13,6 +14,7 @@ const config = {
name: 'Setup', name: 'Setup',
testDir: './', testDir: './',
testMatch: 'ci-release.global-setup.js', testMatch: 'ci-release.global-setup.js',
use: { ...devices[ 'Desktop Chrome' ] },
}, },
{ {
name: 'API tests', name: 'API tests',

View File

@ -1,10 +1,25 @@
const { APIRequest } = require( '@playwright/test' ); const { APIRequest, expect } = require( '@playwright/test' );
const axios = require( 'axios' ).default; const axios = require( 'axios' ).default;
const fs = require( 'fs' ); const fs = require( 'fs' );
const path = require( 'path' ); const path = require( 'path' );
const { promisify } = require( 'util' ); const { promisify } = require( 'util' );
const execAsync = promisify( require( 'child_process' ).exec ); const execAsync = promisify( require( 'child_process' ).exec );
/**
* GitHub [release asset](https://docs.github.com/en/rest/releases/assets?apiVersion=2022-11-28) object.
* @typedef {Object} ReleaseAsset
* @property {string} name
* @property {string} url
*/
/**
* GitHub [release](https://docs.github.com/en/rest/releases/releases?apiVersion=2022-11-28) object.
* @typedef {Object} Release
* @property {ReleaseAsset[]} assets
* @property {string} tag_name
* @property {string} name
*/
/** /**
* Encode basic auth username and password to be used in HTTP Authorization header. * Encode basic auth username and password to be used in HTTP Authorization header.
* *
@ -258,3 +273,94 @@ export const installPluginThruWpCli = async ( pluginPath ) => {
await runWpCliCommand( `wp plugin list` ); await runWpCliCommand( `wp plugin list` );
}; };
/**
* Download the WooCommerce release zip. Can download draft releases when `token` is specified.
*
* @param {Object} params
* @param {import("@playwright/test").APIRequestContext} params.request
* @param {string} params.version The version indicated in the release `tag_name` or `name` field.
* @param {string} params.token
* @param {string} params.downloadDir
*
* @throws When `version` was not found.
*
* @returns {Promise<string>} Absolute path to the downloaded WooCommerce zip.
*/
export const downloadWooCommerceRelease = async ( {
request,
version = process.env.UPDATE_WC,
token = process.env.GITHUB_TOKEN,
downloadDir = 'tmp',
} ) => {
/**
*
* @returns {Promise<Release>}
*/
const getRelease = async () => {
const url =
'https://api.github.com/repos/woocommerce/woocommerce/releases';
const options = {
params: {
per_page: 100,
},
headers: {
Authorization: token ? `Bearer ${ token }` : undefined,
},
};
const response = await request.get( url, options );
/**
* @type {Release[]}
*/
const releases = await response.json();
const match = releases.find( ( { tag_name, name } ) =>
[ tag_name, name ].includes( version )
);
if ( ! match ) {
throw new Error( `Release ${ version } not found!` );
}
return match;
};
/**
*
* @param {Release} release
* @throws When `release` does not contain a woocommerce zip.
* @returns {ReleaseAsset}
*/
const getWooCommerceZipAsset = ( release ) => {
const zipName =
version.toLowerCase() === 'nightly'
? 'woocommerce-trunk-nightly.zip'
: 'woocommerce.zip';
const asset = release.assets.find( ( { name } ) => name === zipName );
if ( ! asset ) {
throw new Error(
`Release ${ version } does not contain a WooCommerce ZIP asset`
);
}
return asset;
};
const release = await getRelease();
const asset = getWooCommerceZipAsset( release );
const downloadResponse = await request.get( asset.url, {
headers: {
Authorization: token ? `Bearer ${ token }` : undefined,
Accept: 'application/octet-stream',
},
} );
expect( downloadResponse.ok() ).toBeTruthy();
const body = await downloadResponse.body();
const zipPath = path.resolve( downloadDir, asset.name );
fs.mkdirSync( path.resolve( downloadDir ), { recursive: true } );
fs.writeFileSync( zipPath, body );
return zipPath;
};

View File

@ -63,17 +63,17 @@ const getWCDownloadURL = async () => {
throw new Error( error.message ); throw new Error( error.message );
} ); } );
const releaseWithTagName = response.data.find( const release = response.data.find( ( { tag_name, name } ) =>
( { tag_name } ) => tag_name === UPDATE_WC [ tag_name, name ].includes( UPDATE_WC )
); );
if ( ! releaseWithTagName ) { if ( ! release ) {
throw new Error( throw new Error(
`No release with tag_name="${ UPDATE_WC }" found. If "${ UPDATE_WC }" is a draft release, make sure to specify a GITHUB_TOKEN environment variable.` `Release "${ UPDATE_WC }" not found. If "${ UPDATE_WC }" is a draft release, make sure to specify a GITHUB_TOKEN environment variable.`
); );
} }
const wcZipAsset = releaseWithTagName.assets.find( ( { name } ) => const wcZipAsset = release.assets.find( ( { name } ) =>
name.match( /^woocommerce(-trunk-nightly)?\.zip$/ ) name.match( /^woocommerce(-trunk-nightly)?\.zip$/ )
); );
@ -82,7 +82,7 @@ const getWCDownloadURL = async () => {
} }
throw new Error( throw new Error(
`WooCommerce release with tag "${ UPDATE_WC }" found, but does not have a WooCommerce ZIP asset.` `Release "${ UPDATE_WC }" found, but does not have a WooCommerce ZIP asset.`
); );
}; };
@ -91,6 +91,8 @@ skipTestIfUndefined();
test.describe.serial( 'WooCommerce update', () => { test.describe.serial( 'WooCommerce update', () => {
test.use( { storageState: ADMINSTATE } ); test.use( { storageState: ADMINSTATE } );
test.setTimeout( 5 * 60 * 1000 );
test.beforeAll( async () => { test.beforeAll( async () => {
await test.step( 'Download WooCommerce zip from GitHub', async () => { await test.step( 'Download WooCommerce zip from GitHub', async () => {
const url = await getWCDownloadURL(); const url = await getWCDownloadURL();
@ -135,9 +137,7 @@ test.describe.serial( 'WooCommerce update', () => {
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
} ); } );
await test.step( await test.step( 'Choose the option "Replace current with uploaded"', async () => {
'Choose the option "Replace current with uploaded"',
async () => {
await page await page
.locator( '.button-primary.update-from-upload-overwrite' ) .locator( '.button-primary.update-from-upload-overwrite' )
.click(); .click();
@ -145,8 +145,7 @@ test.describe.serial( 'WooCommerce update', () => {
await expect( await expect(
page.getByText( 'Plugin updated successfully.' ) page.getByText( 'Plugin updated successfully.' )
).toBeVisible(); ).toBeVisible();
} } );
);
await test.step( 'Go to "Installed plugins" page', async () => { await test.step( 'Go to "Installed plugins" page', async () => {
await page.goto( 'wp-admin/plugins.php', { await page.goto( 'wp-admin/plugins.php', {
@ -154,9 +153,7 @@ test.describe.serial( 'WooCommerce update', () => {
} ); } );
} ); } );
await test.step( await test.step( 'Assert that "WooCommerce" is listed and active', async () => {
'Assert that "WooCommerce" is listed and active',
async () => {
await expect( await expect(
page.locator( '.plugin-title strong', { page.locator( '.plugin-title strong', {
hasText: /^WooCommerce$/, hasText: /^WooCommerce$/,
@ -165,13 +162,10 @@ test.describe.serial( 'WooCommerce update', () => {
await expect( await expect(
page.locator( '#deactivate-woocommerce' ) page.locator( '#deactivate-woocommerce' )
).toBeVisible(); ).toBeVisible();
} } );
);
if ( UPDATE_WC !== 'nightly' ) { if ( UPDATE_WC !== 'nightly' ) {
await test.step( await test.step( 'Verify that WooCommerce was updated to the expected version', async () => {
'Verify that WooCommerce was updated to the expected version',
async () => {
const api = new wcApi( { const api = new wcApi( {
url: baseURL, url: baseURL,
consumerKey: process.env.CONSUMER_KEY, consumerKey: process.env.CONSUMER_KEY,
@ -186,13 +180,11 @@ test.describe.serial( 'WooCommerce update', () => {
} ); } );
const wcPluginData = response.data.active_plugins.find( const wcPluginData = response.data.active_plugins.find(
( { plugin } ) => ( { plugin } ) => plugin === 'woocommerce/woocommerce.php'
plugin === 'woocommerce/woocommerce.php'
); );
expect( wcPluginData.version ).toEqual( UPDATE_WC ); expect( wcPluginData.version ).toEqual( UPDATE_WC );
} } );
);
} }
} ); } );
@ -208,24 +200,19 @@ test.describe.serial( 'WooCommerce update', () => {
} ); } );
} ); } );
await test.step( await test.step( 'Skip this test if the "Update WooCommerce Database" button did not appear', async () => {
'Skip this test if the "Update WooCommerce Database" button did not appear',
async () => {
test.skip( test.skip(
! ( await updateButton.isVisible() ), ! ( await updateButton.isVisible() ),
'The "Update WooCommerce Database" button did not appear after updating WooCommerce. Verify with the team if the WooCommerce version being tested does not really trigger a database update.' 'The "Update WooCommerce Database" button did not appear after updating WooCommerce. Verify with the team if the WooCommerce version being tested does not really trigger a database update.'
); );
} } );
);
await test.step( 'Notice appeared. Start DB update', async () => { await test.step( 'Notice appeared. Start DB update', async () => {
await updateButton.click(); await updateButton.click();
await page.waitForLoadState( 'networkidle' ); await page.waitForLoadState( 'networkidle' );
} ); } );
await test.step( await test.step( 'Assert that the notice "WooCommerce database update complete." appears', async () => {
'Assert that the notice "WooCommerce database update complete." appears',
async () => {
await expect await expect
.poll( .poll(
async () => { async () => {
@ -241,7 +228,6 @@ test.describe.serial( 'WooCommerce update', () => {
} }
) )
.toEqual( true ); .toEqual( true );
} } );
);
} ); } );
} ); } );