diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 7f8af2017..2b1144b80 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,49 +1,54 @@ name: Plugin Build -on: pull_request +on: + - pull_request jobs: - build: - name: Plugin Build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Get npm cache directory - id: npm-cache - run: | - echo "::set-output name=dir::$(npm config get cache)" - - uses: actions/cache@v2 - with: - path: ${{ steps.npm-cache.outputs.dir }} - key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} - restore-keys: | - ${{ runner.os }}-node- - - uses: shivammathur/setup-php@v2 - with: - php-version: '7.4' - tools: composer - coverage: none - - name: Get composer cache directory - id: composer-cache - run: echo "::set-output name=dir::$(composer config cache-files-dir)" - - uses: actions/cache@v2 - with: - path: ${{ steps.composer-cache.outputs.dir }} - key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} - restore-keys: | - ${{ runner.os }}-composer- - - name: Install JS dependencies - run: npm ci - - name: Install PHP dependencies - run: composer install --no-ansi --no-interaction --prefer-dist --no-progress - - name: Build Plugin - run: npm run build - - name: Decompress plugin - run: unzip wp-job-manager.zip -d wp-job-manager - - name: Store Artifact - uses: actions/upload-artifact@v2 - with: - name: wp-job-manager-${{ github.event.pull_request.head.sha }} - path: ${{ github.workspace }}/wp-job-manager/ - retention-days: 7 - + build: + name: Plugin Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Get npm cache directory + id: npm-cache + run: | + echo "::set-output name=dir::$(npm config get cache)" + - uses: actions/cache@v2 + with: + path: ${{ steps.npm-cache.outputs.dir }} + key: ${{ runner.os }}-node-${{ hashFiles('package-lock.json') }} + restore-keys: | + ${{ runner.os }}-node- + - uses: shivammathur/setup-php@v2 + with: + php-version: '7.4' + tools: composer + coverage: none + - name: Get composer cache directory + id: composer-cache + run: echo "::set-output name=dir::$(composer config cache-files-dir)" + - uses: actions/cache@v2 + with: + path: ${{ steps.composer-cache.outputs.dir }} + key: ${{ runner.os }}-composer-${{ hashFiles('composer.lock') }} + restore-keys: | + ${{ runner.os }}-composer- + - name: Install JS dependencies + run: npm ci + - name: Install PHP dependencies + run: composer install --no-ansi --no-interaction --prefer-dist --no-progress + - name: Build Plugin + run: npm run build + - name: Decompress plugin + run: unzip wp-job-manager.zip -d wp-job-manager + - name: Store Artifact + uses: actions/upload-artifact@v2 + with: + name: wp-job-manager-${{ github.event.pull_request.head.sha }} + path: ${{ github.workspace }}/wp-job-manager/ + retention-days: 7 + - name: Save plugin zip and add link to the PR description + env: + WPJMCOM_API_LOGIN: ${{ secrets.WPJMCOM_API_LOGIN }} + GH_TOKEN: ${{ github.token }} + run: node scripts/upload-and-link-plugin-zip.mjs --pr ${{ github.event.number }} --commit ${{ github.event.pull_request.head.sha }} ${{ github.event.pull_request.merged && '--merged' || '' }} diff --git a/scripts/upload-and-link-plugin-zip.mjs b/scripts/upload-and-link-plugin-zip.mjs new file mode 100644 index 000000000..028248c8e --- /dev/null +++ b/scripts/upload-and-link-plugin-zip.mjs @@ -0,0 +1,120 @@ +import chalk from 'chalk'; +import { execSync } from "node:child_process"; +import process from "node:process"; +import { parseArgs } from "node:util"; + +const { env } = process; + +const { values: { pr, commit, merged } } = parseArgs( { + options: { + pr: { type: "string" }, + commit: { type: "string" }, + merged: { type: "boolean", default: false }, + }, +} ); + +const MEDIA_LIBRARY_ENDPOINT = "https://wpjobmanager.com/wp-json/wp/v2/media" + +const login = env.WPJMCOM_API_LOGIN; + +( function main() { + + if ( ! login ) { + console.log( 'WPJobManager.com secrets not available, exiting.' ); + process.exit( 0 ); + } + + try { + deleteOldZips(); + } catch ( error ) { + console.log( 'Failed to delete old plugin zips.' ); + console.log( error.message ); + console.log( error.stack ); + process.exit( 1 ); + } + + if ( merged ) { + return; + } + + try { + const zip = uploadZip(); + addLinksToPR( zip ); + } catch ( error ) { + console.log( 'Failed to upload plugin zip.' ); + console.log( error.message ); + console.log( error.stack ); + process.exit( 1 ); + } + +} )(); + +/** + * Remove previously uploaded plugin zip files for the PR. + */ +function deleteOldZips() { + + const oldZips = JSON.parse( execSync( `curl -s -u "${ login }" "${ MEDIA_LIBRARY_ENDPOINT }?mime_type=application/zip&_fields=id,date,title,source_url"` ).toString() ); + if ( oldZips?.code || ! Array.isArray( oldZips ) ) { + console.log( `[${ oldZips.code }]`, oldZips.message ); + return; + } + oldZips?.forEach( ( zip ) => { + const + title = zip.title.rendered; + if ( title.startsWith( `wp-job-manager-zip-${pr}-` ) ) { + console.log( `Deleting old plugin build ${ title }.zip` ); + execSync( `curl -s -u "${ login }" -X DELETE "${ MEDIA_LIBRARY_ENDPOINT }/${ zip.id }?force=true"` ); + } + } ) +} + +/** + * Upload plugin zip to media library. + * + * @returns {string} URL to plugin zip file. + */ +function uploadZip() { + + const id = `${ pr }-${ commit.substring( 0, 8 ) }`; + + const response = execSync( `curl -u "${ login }" --http1.1 --data-binary @wp-job-manager.zip -H "Content-Disposition: attachment; filename=\"wp-job-manager-zip-${ id }.zip\"" ${ MEDIA_LIBRARY_ENDPOINT }?title=wp-job-manager-zip-${ id }` ).toString(); + + const zip = JSON.parse( response )?.source_url?.replaceAll( '"', '' ).trim(); + if ( ! zip ) { + throw new Error( response ); + } + console.log( chalk.green( '✓' ), `Plugin file uploaded to ${ zip }` ) + + return zip; +} + +/** + * Add a link to the plugin zip and the playground to the PR description. + * + * @param {string} zip URL to plugin zip file. + */ +function addLinksToPR( zip ) { + + const [ , path, id ] = zip.match( 'wp-content/uploads/(.*)/wp-job-manager-zip-(.*).zip' ); + const playgroundLink = `https://wpjobmanager.com/playground/?core=${ path }/${ id }` + + const links = ` + +---- + +| Plugin build for ${ commit } | +| ------------------------------------------------------------ | +| 📦 [Download plugin zip](${ zip }) | +| ▶️ [Open in playground](${ playgroundLink }) | + + +`; + + let body = execSync( `gh pr view ${ pr } --json body --jq .body` ).toString(); + + body = body.replace( /((([\s\S]*))|$)/, links ); + + execSync( `gh pr edit ${ pr } --body "${ body.replaceAll( '"', '\\"' ) }"`, { stdio: 'inherit' } ) + console.log( chalk.green( '✓' ), 'Plugin build links added to PR.' ); +}