diff --git a/.github/workflows/upload-release-to-plugin-repo.yml b/.github/workflows/upload-release-to-plugin-repo.yml new file mode 100644 index 00000000000000..57df6897e9553c --- /dev/null +++ b/.github/workflows/upload-release-to-plugin-repo.yml @@ -0,0 +1,64 @@ +on: + release: + types: [released] + +name: Upload Gutenberg plugin to WordPress.org plugin repo + +jobs: + upload: + name: Upload Gutenberg Plugin + runs-on: ubuntu-latest + environment: wp.org plugin + if: github.event.release.assets[0] + env: + PLUGIN_REPO_URL: 'https://plugins.svn.wordpress.org/gutenberg' + STABLE_TAG_REGEX: 'Stable tag: [0-9]\+\.[0-9]\+\.[0-9]\+\s*' + SVN_USERNAME: ${{ secrets.svn_username }} + SVN_PASSWORD: ${{ secrets.svn_password }} + VERSION: ${{ github.event.release.name }} + steps: + - name: Check out Gutenberg trunk from WP.org plugin repo + run: svn checkout "$PLUGIN_REPO_URL/trunk" + + - name: Get previous stable tag + id: get_previous_stable_tag + run: echo ::set-output name=stable_tag::$(grep "$STABLE_TAG_REGEX" ./trunk/readme.txt) + + - name: Delete everything + working-directory: ./trunk + run: find . -maxdepth 1 -not -name ".svn" -not -name "." -not -name ".." -exec rm -rf {} + + + - name: Download and unzip Gutenberg plugin asset into trunk folder + env: + PLUGIN_URL: ${{ github.event.release.assets[0].browser_download_url }} + run: | + curl -L -o gutenberg.zip $PLUGIN_URL + unzip gutenberg.zip -d trunk + rm gutenberg.zip + + - name: Replace the stable tag placeholder with the existing stable tag on the SVN repository + env: + STABLE_TAG_PLACEHOLDER: 'Stable tag: V\.V\.V' + STABLE_TAG: ${{ steps.get_previous_stable_tag.outputs.stable_tag }} + run: sed -i "s/${STABLE_TAG_PLACEHOLDER}/${STABLE_TAG}/g" ./trunk/readme.txt + + - name: Commit the content changes + working-directory: ./trunk + run: | + svn st | grep '^?' | awk '{print $2}' | xargs -r svn add + svn st | grep '^!' | awk '{print $2}' | xargs -r svn rm + svn commit -m "Committing version $VERSION" \ + --no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD" + + - name: Create the SVN tag + working-directory: ./trunk + run: | + svn copy "$PLUGIN_REPO_URL/trunk" "$PLUGIN_REPO_URL/tags/$VERSION" -m "Tagging version $VERSION" \ + --no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD" + + - name: Update the plugin's stable version + working-directory: ./trunk + run: | + sed -i "s/${STABLE_TAG_REGEX}/Stable tag: ${VERSION}/g" ./readme.txt + svn commit -m "Releasing version $VERSION" \ + --no-auth-cache --non-interactive --username "$SVN_USERNAME" --password "$SVN_PASSWORD" diff --git a/bin/plugin/commands/release.js b/bin/plugin/commands/release.js index 16f8f8796e9033..cf40654be9d57f 100644 --- a/bin/plugin/commands/release.js +++ b/bin/plugin/commands/release.js @@ -6,7 +6,6 @@ const fs = require( 'fs' ); const semver = require( 'semver' ); const Octokit = require( '@octokit/rest' ); const { sprintf } = require( 'sprintf-js' ); -const os = require( 'os' ); /** * Internal dependencies @@ -19,7 +18,6 @@ const { runShellScript, } = require( '../lib/utils' ); const git = require( '../lib/git' ); -const svn = require( '../lib/svn' ); const { getNextMajorVersion } = require( '../lib/version' ); const { getIssuesByMilestone, @@ -32,31 +30,6 @@ const { findReleaseBranchName, } = require( './common' ); -const STABLE_TAG_REGEX = /Stable tag: [0-9]+\.[0-9]+\.[0-9]+\s*\n/; -const STABLE_TAG_PLACEHOLDER = 'Stable tag: V.V.V\n'; - -/** - * Fetching the SVN repository to the working directory. - * - * @param {string} abortMessage Abort message. - * - * @return {Promise} Repository local path. - */ -async function runSvnRepositoryCheckoutStep( abortMessage ) { - // Cloning the repository - let svnWorkingDirectoryPath; - await runStep( 'Fetching the SVN repository', abortMessage, async () => { - log( '>> Fetching the SVN repository' ); - svnWorkingDirectoryPath = svn.checkout( config.svnRepositoryURL ); - log( - '>> The SVN repository has been successfully fetched in the following temporary folder: ' + - formats.success( svnWorkingDirectoryPath ) - ); - } ); - - return svnWorkingDirectoryPath; -} - /** * Creates a new release branch based on the last package.json version * and chooses the next version number. @@ -478,149 +451,6 @@ async function runGithubReleaseStep( return release; } -/** - * Updates and commits the content of the SVN repo using the new plugin ZIP. - * - * @param {string} svnWorkingDirectoryPath SVN Working Directory Path. - * @param {string} zipPath Plugin zip path. - * @param {string} version Version. - * @param {string} abortMessage Abort Message. - */ -async function runUpdateTrunkContentStep( - svnWorkingDirectoryPath, - zipPath, - version, - abortMessage -) { - // Updating the content of the svn - await runStep( 'Updating trunk content', abortMessage, async () => { - log( '>> Replacing trunk content using the new plugin ZIP' ); - - const readmePath = svnWorkingDirectoryPath + '/readme.txt'; - - const previousReadmeFileContent = fs.readFileSync( readmePath, 'utf8' ); - const stableTag = previousReadmeFileContent.match( - STABLE_TAG_REGEX - )[ 0 ]; - - // Delete everything - runShellScript( - 'find . -maxdepth 1 -not -name ".svn" -not -name "." -not -name ".." -exec rm -rf {} +', - svnWorkingDirectoryPath - ); - - // Update the content using the plugin ZIP - runShellScript( 'unzip ' + zipPath + ' -d ' + svnWorkingDirectoryPath ); - - // Replace the stable tag placeholder with the existing stable tag on the SVN repository. - const newReadmeFileContent = fs.readFileSync( readmePath, 'utf8' ); - fs.writeFileSync( - readmePath, - newReadmeFileContent.replace( STABLE_TAG_PLACEHOLDER, stableTag ) - ); - - let xargsOpts = ''; - if ( os.platform === 'linux' ) { - // When xargs receives no arguments, it behaves differently in macOS and linux: - // - macOS: doesn't run - // - linux: run without arguments - // - // In linux, the -r option teaches xargs not to run if it receives no arguments. - xargsOpts = '-r'; - } - - // Commit the content changes - runShellScript( - "svn st | grep '^?' | awk '{print $2}' | xargs " + - xargsOpts + - ' svn add', - svnWorkingDirectoryPath - ); - runShellScript( - "svn st | grep '^!' | awk '{print $2}' | xargs " + - xargsOpts + - ' svn rm', - svnWorkingDirectoryPath - ); - await askForConfirmation( - 'Trunk content has been updated, please check the SVN diff. Commit the changes?', - true, - abortMessage - ); - - svn.commit( svnWorkingDirectoryPath, 'Committing version ' + version ); - log( '>> Trunk has been successfully updated' ); - } ); -} - -/** - * Creates a new SVN Tag - * - * @param {string} version Version. - * @param {string} abortMessage Abort Message. - */ -async function runSvnTagStep( version, abortMessage ) { - await runStep( 'Creating the SVN Tag', abortMessage, async () => { - await askForConfirmation( - 'Proceed with the creation of the SVN Tag?', - true, - abortMessage - ); - svn.tagTrunk( - config.svnRepositoryURL, - version, - 'Tagging version ' + version - ); - log( - '>> The SVN ' + - formats.success( version ) + - ' tag has been successfully created' - ); - } ); -} - -/** - * Updates the stable version of the plugin in the SVN repository. - * - * @param {string} svnWorkingDirectoryPath SVN working directory. - * @param {string} version Version. - * @param {string} abortMessage Abort Message. - */ -async function updateThePluginStableVersion( - svnWorkingDirectoryPath, - version, - abortMessage -) { - // Updating the content of the svn - await runStep( - "Updating the plugin's stable version", - abortMessage, - async () => { - const readmePath = svnWorkingDirectoryPath + '/readme.txt'; - const readmeFileContent = fs.readFileSync( readmePath, 'utf8' ); - const newReadmeContent = readmeFileContent.replace( - STABLE_TAG_REGEX, - 'Stable tag: ' + version + '\n' - ); - fs.writeFileSync( readmePath, newReadmeContent ); - - // Commit the content changes - await askForConfirmation( - 'The stable version is updated in the readme.txt file. Commit the changes?', - true, - abortMessage - ); - - svn.commit( - svnWorkingDirectoryPath, - 'Releasing version ' + version - ); - - log( '>> Stable version updated successfully' ); - } - ); -} - /** * Checks whether the milestone associated with the release has open issues or * pull requests. Returns a promise resolving to true if there are no open issue @@ -796,10 +626,6 @@ async function releasePlugin( isRC = true ) { 'Aborting! Make sure to manually cherry-pick the ' + formats.success( commitHash ) + ' commit to the master branch.'; - if ( ! isRC ) { - abortMessage += - ' Make sure to perform the SVN release manually as well.'; - } // Cherry-picking the bump commit into master await runCherrypickBumpCommitIntoMasterStep( @@ -808,43 +634,6 @@ async function releasePlugin( isRC = true ) { abortMessage ); - if ( ! isRC ) { - abortMessage = - 'Aborting! The GitHub release is done. Make sure to perform the SVN release manually.'; - - await askForConfirmation( - 'The GitHub release is complete. Proceed with the SVN release? ', - true, - abortMessage - ); - - // Fetching the SVN repository - const svnWorkingDirectory = await runSvnRepositoryCheckoutStep( - abortMessage - ); - temporaryFolders.push( svnWorkingDirectory ); - - // Updating the SVN trunk content - await runUpdateTrunkContentStep( - svnWorkingDirectory, - zipPath, - version, - abortMessage - ); - - abortMessage = - 'Aborting! The GitHub release is done, SVN trunk updated. Make sure to create the SVN tag and update the stable version manually.'; - await runSvnTagStep( version, abortMessage ); - - abortMessage = - 'Aborting! The GitHub release is done, SVN tagged. Make sure to update the stable version manually.'; - await updateThePluginStableVersion( - svnWorkingDirectory, - version, - abortMessage - ); - } - abortMessage = 'Aborting! The release is finished though.'; await runCleanLocalFoldersStep( temporaryFolders, abortMessage ); diff --git a/bin/plugin/lib/svn.js b/bin/plugin/lib/svn.js deleted file mode 100644 index 533d7b7f0e2a0f..00000000000000 --- a/bin/plugin/lib/svn.js +++ /dev/null @@ -1,40 +0,0 @@ -/** - * Internal dependencies - */ -const { getRandomTemporaryPath, runShellScript } = require( './utils' ); - -function checkout( repositoryUrl ) { - const svnWorkingDirectoryPath = getRandomTemporaryPath(); - runShellScript( - 'svn checkout ' + repositoryUrl + '/trunk ' + svnWorkingDirectoryPath - ); - - return svnWorkingDirectoryPath; -} - -function commit( svnWorkingDirectoryPath, message ) { - runShellScript( - 'svn commit -m "' + message + '"', - svnWorkingDirectoryPath - ); -} - -function tagTrunk( repositoryUrl, tagName, message ) { - runShellScript( - 'svn cp ' + - repositoryUrl + - '/trunk ' + - repositoryUrl + - '/tags/' + - tagName + - ' -m "' + - message + - '"' - ); -} - -module.exports = { - checkout, - commit, - tagTrunk, -};