Added upload and test functionality

This commit is contained in:
Greg 2021-12-08 15:56:42 -07:00
parent fedb5e9677
commit 473c4e5279
9 changed files with 172 additions and 17 deletions

62
.github/workflows/test-plugins.yml vendored Normal file
View File

@ -0,0 +1,62 @@
name: Build zip for PR
on: pull_request
# on:
# release:
# types: [published]
jobs:
test-plugins:
name: Smoke tests with ${{ matrix.plugins }} plugin installed
runs-on: ubuntu-18.04
strategy:
matrix:
plugins: [ 'automattic/woocommerce-payments', 'woocommerce/facebook-for-woocommerce', 'automattic/woocommerce-services', ${{ secrets.WC_SUBSCRIPTIONS_REPO }}]
pluginNames: [ 'WooCommerce Payments', 'Facebook for WooCommerce', 'WooCommerce Shipping & Tax', 'WooCommerce Subscriptions' ]
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: 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 }}
PLUGIN_REPOSITORY: ${{ matrix.plugins }}
PLUGIN_NAME: ${{ matrix.pluginNames }}
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

View File

@ -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
## Fixed

View File

@ -227,9 +227,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

View File

@ -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:

View File

@ -0,0 +1,5 @@
file_uploads = On
memory_limit = 500M
upload_max_filesize = 500M
post_max_size = 500M
max_execution_time = 600

View File

@ -9,9 +9,10 @@ const StreamZip = require( 'node-stream-zip' );
* 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 getRemotePluginZip = async ( fileUrl, authorizationToken = '' ) => {
const appPath = getAppRoot();
const savePath = path.resolve(
appPath,
@ -19,12 +20,12 @@ const getRemotePluginZip = async ( fileUrl ) => {
);
mkdirp.sync( savePath );
// Pull the filename from the end of the URL
const fileName = fileUrl.split( '/' ).pop();
// Pull the version from the end of the URL and add .zip
const fileName = fileUrl.split( '/' ).pop() + '.zip';
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 );
@ -35,24 +36,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 = {
@ -62,6 +63,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,11 +77,11 @@ const getLatestReleaseZipUrl = async (
// Loop until we find the first pre-release, then return it.
body.forEach( ( release ) => {
if ( release.prerelease ) {
resolve( release.assets[ 0 ].browser_download_url );
resolve( release.zipball_url );
}
} );
} else {
resolve( body.assets[ 0 ].browser_download_url );
resolve( body.zipball_url );
}
} );
} );
@ -110,17 +116,24 @@ const checkNestedZip = async ( zipFilePath, savePath ) => {
* @param {string} downloadPath The location where to download the zip to.
* @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
.get( options, function ( err, resp, body ) {
console.log(resp.statusCode)
if ( err ) {
reject( err );
} else {
@ -131,9 +144,32 @@ const downloadZip = async ( fileUrl, downloadPath ) => {
} );
};
/**
* Delete the downloaded plugin files.
*/
const deleteDownloadedPluginFiles = async () => {
const appPath = getAppRoot();
const pluginSavePath = path.resolve(
appPath,
'plugins/woocommerce/tests/e2e/plugins'
);
fs.readdir( pluginSavePath, ( err, files ) => {
if ( err ) throw err;
for ( const file of files ) {
fs.unlink(path.join( pluginSavePath, file ), err => {
if ( err ) throw err;
} );
}
} );
}
module.exports = {
getRemotePluginZip,
getLatestReleaseZipUrl,
checkNestedZip,
downloadZip,
deleteDownloadedPluginFiles,
};

View File

@ -1,7 +1,7 @@
const getAppRoot = require( './app-root' );
const { getAppName, getAppBase } = require( './app-name' );
const { getTestConfig, getAdminConfig, resolveLocalE2ePath } = 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' );
@ -15,6 +15,7 @@ module.exports = {
resolveLocalE2ePath,
getRemotePluginZip,
getLatestReleaseZipUrl,
deleteDownloadedPluginFiles,
takeScreenshotFor,
updateReadyPageStatus,
...consoleUtils,

View File

@ -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();
} );
});

View File

@ -0,0 +1,43 @@
/**
* Internal dependencies
*/
const { merchant } = require( '@woocommerce/e2e-utils' );
const { getRemotePluginZip, getLatestReleaseZipUrl, deleteDownloadedPluginFiles } = require( '@woocommerce/e2e-environment' );
/**
* External dependencies
*/
const {
it,
beforeAll,
} = require( '@jest/globals' );
const { PLUGIN_REPOSITORY, PLUGIN_NAME, GITHUB_TOKEN } = process.env;
let zipUrl;
let pluginPath;
describe( 'Upload and activate plugin', () => {
beforeAll( async () => {
zipUrl = await getLatestReleaseZipUrl( PLUGIN_REPOSITORY, GITHUB_TOKEN );
pluginPath = await getRemotePluginZip( zipUrl, GITHUB_TOKEN );
await merchant.login();
});
afterAll( async () => {
await merchant.logout();
await deleteDownloadedPluginFiles();
});
it( 'can upload and activate the provided plugin', async () => {
await merchant.uploadAndActivatePlugin( pluginPath, PLUGIN_NAME );
});
it( 'can remove downloaded plugin zip', async () => {
await deleteDownloadedPluginFiles();
} );
});