Merge pull request #31400 from woocommerce/add/plugin-upload-test-functionality
Added plugin upload and test functionality
This commit is contained in:
commit
fe5d4d6c2e
|
@ -52,3 +52,103 @@ jobs:
|
|||
pnpx wc-e2e test:e2e plugins/woocommerce/tests/e2e/specs/smoke-tests/update-woocommerce.js
|
||||
pnpx wc-e2e test:e2e
|
||||
pnpx wc-api-tests test api
|
||||
|
||||
build:
|
||||
name: Build zip for PR
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Build
|
||||
id: build
|
||||
uses: woocommerce/action-build@trunk
|
||||
env:
|
||||
BUILD_ENV: e2e
|
||||
|
||||
- name: Upload PR zip
|
||||
uses: actions/upload-artifact@v2
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
name: woocommerce
|
||||
path: ${{ steps.build.outputs.zip_path }}
|
||||
retention-days: 7
|
||||
|
||||
test-plugins:
|
||||
name: Smoke tests with ${{ matrix.plugin }} plugin installed
|
||||
runs-on: ubuntu-18.04
|
||||
needs: [build]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- plugin: 'WooCommerce Payments'
|
||||
repo: 'automattic/woocommerce-payments'
|
||||
- plugin: 'WooCommerce PayPal Payments'
|
||||
repo: 'woocommerce/woocommerce-paypal-payments'
|
||||
- plugin: 'WooCommerce Shipping & Tax'
|
||||
repo: 'woocommerce/woocommerce-services'
|
||||
- plugin: 'WooCommerce Subscriptions'
|
||||
repo: WC_SUBSCRIPTIONS_REPO
|
||||
private: true
|
||||
- plugin: 'WordPress SEO' # Yoast SEO in the UI, but the slug is wordpress-seo
|
||||
repo: 'Yoast/wordpress-seo'
|
||||
- plugin: 'Contact Form 7'
|
||||
repo: 'takayukister/contact-form-7'
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: package/woocommerce
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
run: pnpx wc-e2e docker:up
|
||||
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
|
||||
- name: Download WooCommerce ZIP.
|
||||
uses: actions/download-artifact@v2
|
||||
with:
|
||||
name: woocommerce
|
||||
path: tmp
|
||||
|
||||
- name: Extract and replace WooCommerce zip.
|
||||
working-directory: tmp
|
||||
run: |
|
||||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
|
||||
- name: Install dependencies again
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
|
||||
- name: Run tests command.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||
GITHUB_REPOSITORY: ${{ matrix.private && secrets[matrix.repo] || matrix.repo }}
|
||||
PLUGIN_NAME: ${{ matrix.plugin }}
|
||||
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||
run: |
|
||||
pnpx wc-e2e test:e2e plugins/woocommerce/tests/e2e/specs/smoke-tests/upload-plugin.js
|
||||
pnpm nx test-e2e woocommerce
|
||||
|
|
|
@ -105,3 +105,74 @@ jobs:
|
|||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||
run: pnpm nx test-e2e woocommerce
|
||||
|
||||
test-plugins:
|
||||
name: Smoke tests with ${{ matrix.plugin }} plugin installed
|
||||
runs-on: ubuntu-18.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- plugin: 'WooCommerce Payments'
|
||||
repo: 'automattic/woocommerce-payments'
|
||||
- plugin: 'WooCommerce PayPal Payments'
|
||||
repo: 'woocommerce/woocommerce-paypal-payments'
|
||||
- plugin: 'WooCommerce Shipping & Tax'
|
||||
repo: 'woocommerce/woocommerce-services'
|
||||
- plugin: 'WooCommerce Subscriptions'
|
||||
repo: WC_SUBSCRIPTIONS_REPO
|
||||
private: true
|
||||
- plugin: 'WordPress SEO' # Yoast SEO in the UI, but the slug is wordpress-seo
|
||||
repo: 'Yoast/wordpress-seo'
|
||||
- plugin: 'Contact Form 7'
|
||||
repo: 'takayukister/contact-form-7'
|
||||
steps:
|
||||
- name: Create dirs.
|
||||
run: |
|
||||
mkdir -p code/woocommerce
|
||||
mkdir -p package/woocommerce
|
||||
mkdir -p tmp/woocommerce
|
||||
mkdir -p node_modules
|
||||
|
||||
- name: Checkout code.
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: package/woocommerce
|
||||
|
||||
- name: Install PNPM and install dependencies
|
||||
working-directory: package/woocommerce
|
||||
run: |
|
||||
npm install -g pnpm
|
||||
pnpm install
|
||||
|
||||
- name: Load docker images and start containers.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
LATEST_WP_VERSION_MINUS: ${{ matrix.wp }}
|
||||
run: pnpm nx docker-up woocommerce
|
||||
|
||||
- name: Move current directory to code. We will install zip file in this dir later.
|
||||
run: mv ./package/woocommerce/plugins/woocommerce/* ./code/woocommerce
|
||||
|
||||
- name: Download WooCommerce release zip
|
||||
working-directory: tmp
|
||||
run: |
|
||||
ASSET_ID=$(jq ".release.assets[0].id" $GITHUB_EVENT_PATH)
|
||||
|
||||
curl https://api.github.com/repos/woocommerce/woocommerce/releases/assets/${ASSET_ID} -LJOH 'Accept: application/octet-stream'
|
||||
|
||||
unzip woocommerce.zip -d woocommerce
|
||||
mv woocommerce/woocommerce/* ../package/woocommerce/plugins/woocommerce/
|
||||
|
||||
- name: Run tests command.
|
||||
working-directory: package/woocommerce/plugins/woocommerce
|
||||
env:
|
||||
WC_E2E_SCREENSHOTS: 1
|
||||
E2E_SLACK_TOKEN: ${{ secrets.SMOKE_TEST_SLACK_TOKEN }}
|
||||
E2E_SLACK_CHANNEL: ${{ secrets.RELEASE_TEST_SLACK_CHANNEL }}
|
||||
GITHUB_REPOSITORY: ${{ matrix.private && secrets[matrix.repo] || matrix.repo }}
|
||||
PLUGIN_NAME: ${{ matrix.plugin }}
|
||||
GITHUB_TOKEN: ${{ secrets.E2E_GH_TOKEN }}
|
||||
run: |
|
||||
pnpx wc-e2e test:e2e plugins/woocommerce/tests/e2e/specs/smoke-tests/upload-plugin.js
|
||||
pnpm nx test-e2e woocommerce
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
## Added
|
||||
|
||||
- Added `await` for every call to `shopper.logout`
|
||||
- Updated `getLatestReleaseZipUrl()` to allow passing in an authorization token and simplified arguments to just the repository name
|
||||
- Added `upload.ini` which increases the limits for uploading files (such as for plugins) in the Docker environment
|
||||
- Test setup, scaffolding, and removal via `wc-e2e install` and `wc-e2e uninstall`
|
||||
|
||||
## Fixed
|
||||
|
|
|
@ -254,9 +254,9 @@ The above method also makes use of the following utility methods which can also
|
|||
|
||||
If you would like to get the latest release zip URL, which can be used in the methods mentioned above, you can use the following helper function to do so:
|
||||
|
||||
`getLatestReleaseZipUrl( owner, repository, getPrerelease, perPage )`
|
||||
`getLatestReleaseZipUrl( repository, authorizationToken, getPrerelease, perPage )`
|
||||
|
||||
This will return a string with the latest release URL. Optionally, you can use the `getPrerelease` boolean flag, which defaults to false, on whether or not to get a prerelease instead. The `perPage` flag can be used to return more results when getting the list of releases. The default value is 3.
|
||||
This will return a string with the latest release URL. Optionally, you can use the `getPrerelease` boolean flag, which defaults to false, on whether or not to get a prerelease instead. The `perPage` flag can be used to return more results when getting the list of releases. The default value is 3. If the repository requires authorization to access, the authorization token can be passed in to the `authorizationToken` argument.
|
||||
|
||||
## Additional information
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ services:
|
|||
WORDPRESS_DEBUG: 1
|
||||
volumes:
|
||||
- wordpress:/var/www/html
|
||||
- ./upload.ini:/usr/local/etc/php/conf.d/uploads.ini
|
||||
- "../../../${WC_E2E_FOLDER}:${WC_E2E_FOLDER_MAPPING}"
|
||||
|
||||
wordpress-cli:
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
file_uploads = On
|
||||
memory_limit = 500M
|
||||
upload_max_filesize = 500M
|
||||
post_max_size = 500M
|
||||
max_execution_time = 600
|
|
@ -1,27 +1,27 @@
|
|||
const path = require( 'path' );
|
||||
const getAppRoot = require( './app-root' );
|
||||
const fs = require( 'fs' );
|
||||
const mkdirp = require( 'mkdirp' );
|
||||
const request = require( 'request' );
|
||||
const StreamZip = require( 'node-stream-zip' );
|
||||
const { resolveLocalE2ePath } = require( './test-config' );
|
||||
|
||||
/**
|
||||
* Upload a plugin zip from a remote location, such as a GitHub URL or other hosted location.
|
||||
*
|
||||
* @param {string} fileUrl The URL where the zip file is located.
|
||||
* @param {string} authorizationToken Authorization token used to authenticate with the GitHub API if required.
|
||||
* @return {string} The path where the zip file is located.
|
||||
*/
|
||||
const getRemotePluginZip = async ( fileUrl ) => {
|
||||
const appPath = getAppRoot();
|
||||
const getRemotePluginZip = async ( fileUrl, authorizationToken = '' ) => {
|
||||
const savePath = resolveLocalE2ePath( 'plugins' );
|
||||
mkdirp.sync( savePath );
|
||||
|
||||
// Pull the filename from the end of the URL
|
||||
// Pull the version from the end of the URL
|
||||
const fileName = fileUrl.split( '/' ).pop();
|
||||
let filePath = path.join( savePath, fileName );
|
||||
|
||||
// First, download the zip file
|
||||
await downloadZip( fileUrl, filePath );
|
||||
await downloadZip( fileUrl, filePath, authorizationToken );
|
||||
|
||||
// Check for a nested zip and update the filepath
|
||||
filePath = await checkNestedZip( filePath, savePath );
|
||||
|
@ -32,24 +32,24 @@ const getRemotePluginZip = async ( fileUrl ) => {
|
|||
/**
|
||||
* Get the latest release zip for a plugin from a GiHub repository.
|
||||
*
|
||||
* @param {string} owner The owner of the plugin repository.
|
||||
* @param {string} repository The repository name.
|
||||
* @param {string} repository The repository owner and name. For example: `woocommerce/woocommerce`.
|
||||
* @param {string} authorizationToken Authorization token used to authenticate with the GitHub API if required.
|
||||
* @param {boolean} getPrerelease Flag on whether to get a prelease or not.
|
||||
* @param {number} perPage Limit of entries returned from the latest releases list, defaults to 3.
|
||||
* @return {Promise<string>}} Returns the URL for the release zip file.
|
||||
*/
|
||||
const getLatestReleaseZipUrl = async (
|
||||
owner,
|
||||
repository,
|
||||
authorizationToken = '',
|
||||
getPrerelease = false,
|
||||
perPage = 3
|
||||
) => {
|
||||
let requesturl;
|
||||
|
||||
if ( getPrerelease ) {
|
||||
requesturl = `https://api.github.com/repos/${ owner }/${ repository }/releases?per_page=${ perPage }`;
|
||||
requesturl = `https://api.github.com/repos/${ repository }/releases?per_page=${ perPage }`;
|
||||
} else {
|
||||
requesturl = `https://api.github.com/repos/${ owner }/${ repository }/releases/latest`;
|
||||
requesturl = `https://api.github.com/repos/${ repository }/releases/latest`;
|
||||
}
|
||||
|
||||
const options = {
|
||||
|
@ -59,6 +59,11 @@ const getLatestReleaseZipUrl = async (
|
|||
headers: { 'user-agent': 'node.js' },
|
||||
};
|
||||
|
||||
// If provided with a token, use it for authorization
|
||||
if ( authorizationToken ) {
|
||||
options.headers.Authorization = `token ${ authorizationToken }`;
|
||||
}
|
||||
|
||||
// Wrap in a promise to make the request async
|
||||
return new Promise( function ( resolve, reject ) {
|
||||
request.get( options, function ( err, resp, body ) {
|
||||
|
@ -71,6 +76,12 @@ const getLatestReleaseZipUrl = async (
|
|||
resolve( release.assets[ 0 ].browser_download_url );
|
||||
}
|
||||
} );
|
||||
} else if ( authorizationToken ) {
|
||||
// If it's a private repo, we need to download the archive this way
|
||||
const tagName = body.tag_name;
|
||||
resolve(
|
||||
`https://github.com/${ repository }/archive/${ tagName }.zip`
|
||||
);
|
||||
} else {
|
||||
resolve( body.assets[ 0 ].browser_download_url );
|
||||
}
|
||||
|
@ -90,7 +101,7 @@ const checkNestedZip = async ( zipFilePath, savePath ) => {
|
|||
const entries = await zip.entries();
|
||||
|
||||
for ( const entry of Object.values( entries ) ) {
|
||||
if ( entry.name.match( /.zip/ ) ) {
|
||||
if ( entry.name.match( /\.zip/ ) ) {
|
||||
await zip.extract( null, savePath );
|
||||
await zip.close();
|
||||
return path.join( savePath, entry.name );
|
||||
|
@ -105,15 +116,22 @@ const checkNestedZip = async ( zipFilePath, savePath ) => {
|
|||
*
|
||||
* @param {string} fileUrl The URL where the zip file is located.
|
||||
* @param {string} downloadPath The location where to download the zip to.
|
||||
* @param {string} authorizationToken Authorization token used to authenticate with the GitHub API if required.
|
||||
* @return {Promise<void>}
|
||||
*/
|
||||
const downloadZip = async ( fileUrl, downloadPath ) => {
|
||||
const downloadZip = async ( fileUrl, downloadPath, authorizationToken ) => {
|
||||
const options = {
|
||||
url: fileUrl,
|
||||
method: 'GET',
|
||||
encoding: null,
|
||||
headers: { 'user-agent': 'node.js' },
|
||||
};
|
||||
|
||||
// If provided with a token, use it for authorization
|
||||
if ( authorizationToken ) {
|
||||
options.headers.Authorization = `token ${ authorizationToken }`;
|
||||
}
|
||||
|
||||
// Wrap in a promise to make the request async
|
||||
return new Promise( function ( resolve, reject ) {
|
||||
request
|
||||
|
@ -128,9 +146,27 @@ const downloadZip = async ( fileUrl, downloadPath ) => {
|
|||
} );
|
||||
};
|
||||
|
||||
/**
|
||||
* Delete the downloaded plugin files.
|
||||
*/
|
||||
const deleteDownloadedPluginFiles = async () => {
|
||||
const pluginSavePath = resolveLocalE2ePath( 'plugins' );
|
||||
|
||||
fs.readdir( pluginSavePath, ( err, files ) => {
|
||||
if ( err ) throw err;
|
||||
|
||||
for ( const file of files ) {
|
||||
fs.unlink( path.join( pluginSavePath, file ), ( error ) => {
|
||||
if ( error ) throw error;
|
||||
} );
|
||||
}
|
||||
} );
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
getRemotePluginZip,
|
||||
getLatestReleaseZipUrl,
|
||||
checkNestedZip,
|
||||
downloadZip,
|
||||
deleteDownloadedPluginFiles,
|
||||
};
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
const getAppRoot = require( './app-root' );
|
||||
const { getAppName, getAppBase } = require( './app-name' );
|
||||
const testConfig = require( './test-config' );
|
||||
const { getRemotePluginZip, getLatestReleaseZipUrl } = require('./get-plugin-zip');
|
||||
const {
|
||||
getRemotePluginZip,
|
||||
getLatestReleaseZipUrl,
|
||||
deleteDownloadedPluginFiles,
|
||||
} = require( './get-plugin-zip' );
|
||||
const takeScreenshotFor = require( './take-screenshot' );
|
||||
const updateReadyPageStatus = require( './update-ready-page' );
|
||||
const consoleUtils = require( './filter-console' );
|
||||
|
@ -12,6 +16,7 @@ module.exports = {
|
|||
getAppName,
|
||||
getRemotePluginZip,
|
||||
getLatestReleaseZipUrl,
|
||||
deleteDownloadedPluginFiles,
|
||||
takeScreenshotFor,
|
||||
updateReadyPageStatus,
|
||||
...testConfig,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*/
|
||||
const { merchant, utils } = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
const { getRemotePluginZip, getLatestReleaseZipUrl } = require( '@woocommerce/e2e-environment' );
|
||||
const { getRemotePluginZip, getLatestReleaseZipUrl, deleteDownloadedPluginFiles } = require( '@woocommerce/e2e-environment' );
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
|
@ -24,7 +24,7 @@ utils.describeIf( UPDATE_WC )( 'WooCommerce plugin can be uploaded and activated
|
|||
beforeAll( async () => {
|
||||
|
||||
if ( TEST_RELEASE ) {
|
||||
zipUrl = await getLatestReleaseZipUrl( 'woocommerce', 'woocommerce' );
|
||||
zipUrl = await getLatestReleaseZipUrl( 'woocommerce/woocommerce' );
|
||||
} else {
|
||||
zipUrl = 'https://github.com/woocommerce/woocommerce/releases/download/nightly/woocommerce-trunk-nightly.zip';
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ utils.describeIf( UPDATE_WC )( 'WooCommerce plugin can be uploaded and activated
|
|||
|
||||
afterAll( async () => {
|
||||
await merchant.logout();
|
||||
await deleteDownloadedPluginFiles();
|
||||
});
|
||||
|
||||
it( 'can upload and activate the WooCommerce plugin', async () => {
|
||||
|
@ -46,4 +47,8 @@ utils.describeIf( UPDATE_WC )( 'WooCommerce plugin can be uploaded and activated
|
|||
await merchant.runDatabaseUpdate();
|
||||
});
|
||||
|
||||
it( 'can remove downloaded plugin zip', async () => {
|
||||
await deleteDownloadedPluginFiles();
|
||||
} );
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
const { merchant, utils } = require( '@woocommerce/e2e-utils' );
|
||||
|
||||
const { getRemotePluginZip, getLatestReleaseZipUrl, deleteDownloadedPluginFiles } = require( '@woocommerce/e2e-environment' );
|
||||
|
||||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
const {
|
||||
it,
|
||||
beforeAll,
|
||||
} = require( '@jest/globals' );
|
||||
|
||||
const { GITHUB_REPOSITORY, PLUGIN_NAME, GITHUB_TOKEN } = process.env;
|
||||
|
||||
let zipUrl;
|
||||
let pluginPath;
|
||||
|
||||
utils.describeIf( GITHUB_REPOSITORY )( 'Upload and activate plugin', () => {
|
||||
beforeAll( async () => {
|
||||
zipUrl = await getLatestReleaseZipUrl( GITHUB_REPOSITORY, GITHUB_TOKEN );
|
||||
|
||||
pluginPath = await getRemotePluginZip( zipUrl, GITHUB_TOKEN );
|
||||
|
||||
await merchant.login();
|
||||
});
|
||||
|
||||
afterAll( async () => {
|
||||
await merchant.logout();
|
||||
});
|
||||
|
||||
it( 'can upload and activate the provided plugin', async () => {
|
||||
await merchant.uploadAndActivatePlugin( pluginPath, PLUGIN_NAME );
|
||||
});
|
||||
|
||||
it( 'can remove downloaded plugin zip', async () => {
|
||||
await deleteDownloadedPluginFiles();
|
||||
} );
|
||||
|
||||
});
|
Loading…
Reference in New Issue