Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion bin/sake.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ const args = [
]))

// fire up gulp
spawn('node', args, { cwd: process.cwd(), stdio: 'inherit' })
const child = spawn('node', args, { cwd: process.cwd(), stdio: 'inherit' })

// we need the exit code of the child process to propagate up to the main process
child.on('exit', function(code) {
process.exitCode = code
})
65 changes: 65 additions & 0 deletions helpers/arguments.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import minimist from 'minimist'

/**
* Determines if the command is being run in "non-interactive mode". If true, we should never present with prompts.
* @returns {boolean}
*/
export function isNonInteractive()
{
return process.argv.includes('--non-interactive');
}

/**
* Whether we already have a GitHub release for this deployment. If we don't, we'll be creating one.
* @returns {boolean}
*/
export function hasGitRelease()
{
return !! gitReleaseUploadUrl;
}

export const gitReleaseUploadUrl = () => {
const argv = minimist(process.argv.slice(2))

return argv['release-upload-url'] || null;
}

/**
* Gets the name of the GitHub "release tag" to deploy.
* @returns {string|null}
*/
export const gitReleaseTag = () => {
const argv = minimist(process.argv.slice(2))

return argv['release-tag'] || null;
}

/**
* Whether this is a dry run deployment. If true, the deploy will not actually happen.
* @returns {boolean}
*/
export function isDryRunDeploy()
{
return process.argv.includes('--dry-run');
}

/**
* If specified, then no changes will be made/committed to the code base during a deployment. This should be used if
* you're specifying an _exact_ release to deploy, rather than having Sake create the release for you. The expectation
* here is that prior to deployment the code has already had all the versions/min-reqs bumped.
* @returns {boolean}
*/
export function withoutCodeChanges()
{
return process.argv.includes('--without-code-changes');
}

export const skipLinting = () => {
return process.argv.includes('--skip-linting');
}

export const newPluginVersion = () => {
const argv = minimist(process.argv.slice(2))

return argv['new-version'] || null;
}
4 changes: 3 additions & 1 deletion lib/sake.js
Original file line number Diff line number Diff line change
Expand Up @@ -537,7 +537,7 @@ function initializeSake(config, options) {
}

exports.getPrereleasesPath = function () {
return this.resolvePath(process.env.SAKE_PRE_RELEASE_PATH)
return process.env.SAKE_PRE_RELEASE_PATH ? this.resolvePath(process.env.SAKE_PRE_RELEASE_PATH) : null
}

exports.normalizePath = function (p) {
Expand Down Expand Up @@ -579,6 +579,7 @@ function initializeSake(config, options) {
* Throws an error without the stack trace in gulp.
*/
exports.throwError = (message) => {
process.exitCode = 1;
let err = new Error(chalk.red(message))
err.showStack = false
throw err
Expand All @@ -591,6 +592,7 @@ function initializeSake(config, options) {
* see https://stackoverflow.com/a/30741722
*/
exports.throwDeferredError = (message) => {
process.exitCode = 1;
setTimeout(() => {
exports.throwError(message)
})
Expand Down
6 changes: 6 additions & 0 deletions tasks/clean.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import path from 'node:path';
import del from 'del';
import sake from '../lib/sake.js'
import log from 'fancy-log';

/**
* Clean dev directory from map files
Expand Down Expand Up @@ -48,6 +49,11 @@ cleanWcRepoTask.displayName = 'clean:wc_repo'
* Delete prerelease
*/
const cleanPrereleaseTask = (done) => {
if (sake.getPrereleasesPath() === null) {
log.info('No pre-release path defined -- skipping clean')
return done()
}

return del([
sake.getPrereleasesPath() + sake.config.plugin.id + '*.zip',
sake.getPrereleasesPath() + sake.config.plugin.id + '*.txt'
Expand Down
8 changes: 7 additions & 1 deletion tasks/compile.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { lintPhpTask } from './lint.js'
import { minifyImagesTask } from './imagemin.js'
import { makepotTask } from './makepot.js'
import { stylesTask } from './styles.js'
import { skipLinting } from '../helpers/arguments.js'
const sass = gulpSaas(dartSaas);

/************************** Scripts */
Expand Down Expand Up @@ -152,7 +153,12 @@ compileStyles.displayName = 'compile:styles'
// Compile all plugin assets
const compile = (done) => {
// default compile tasks
let tasks = [lintPhpTask, 'scripts', stylesTask, minifyImagesTask] // NOTE: do not import the `scripts` constant here, otherwise it creates a circular dependency
let tasks = ['scripts', stylesTask, minifyImagesTask] // NOTE: do not import the `scripts` constant here, otherwise it creates a circular dependency

// lint PHP unless told not to
if (! skipLinting()) {
tasks.push(lintPhpTask)
}

// unless exclusively told not to, generate the POT file as well
if (!sake.options.skip_pot) {
Expand Down
143 changes: 120 additions & 23 deletions tasks/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@ import replace from 'gulp-replace'
import replaceTask from 'gulp-replace-task'
import { promptDeployTask, promptTestedReleaseZipTask, promptWcUploadTask } from './prompt.js'
import { bumpMinReqsTask, bumpTask } from './bump.js'
import { cleanPrereleaseTask, cleanWcRepoTask, cleanWpAssetsTask, cleanWpTrunkTask } from './clean.js'
import { cleanBuildTask, cleanPrereleaseTask, cleanWcRepoTask, cleanWpAssetsTask, cleanWpTrunkTask } from './clean.js'
import { buildTask } from './build.js'
import {
gitHubCreateDocsIssueTask,
gitHubCreateReleaseTask,
gitHubGetReleaseIssueTask,
gitHubGetWcIssuesTask
gitHubGetWcIssuesTask, gitHubUploadZipToReleaseTask
} from './github.js'
import {
shellGitEnsureCleanWorkingCopyTask,
Expand All @@ -32,7 +32,14 @@ import {
import { zipTask } from './zip.js'
import { validateReadmeHeadersTask } from './validate.js'
import { lintScriptsTask, lintStylesTask } from './lint.js'
import { copyWcRepoTask, copyWpAssetsTask, copyWpTagTask, copyWpTrunkTask } from './copy.js'
import { copyBuildTask, copyWcRepoTask, copyWpAssetsTask, copyWpTagTask, copyWpTrunkTask } from './copy.js'
import {
gitReleaseTag,
hasGitRelease,
isDryRunDeploy,
isNonInteractive, newPluginVersion,
withoutCodeChanges
} from '../helpers/arguments.js'

let validatedEnvVariables = false

Expand All @@ -41,10 +48,10 @@ let validatedEnvVariables = false
function validateEnvVariables () {
if (validatedEnvVariables) return

let variables = ['GITHUB_API_KEY', 'GITHUB_USERNAME', 'SAKE_PRE_RELEASE_PATH']
let variables = ['GITHUB_API_KEY']

if (sake.config.deploy.type === 'wc') {
variables = variables.concat(['WC_CONSUMER_KEY', 'WC_CONSUMER_SECRET'])
variables = variables.concat(['WC_USERNAME', 'WC_APPLICATION_PASSWORD'])
}

if (sake.config.deploy.type === 'wp') {
Expand All @@ -54,13 +61,62 @@ function validateEnvVariables () {
sake.validateEnvironmentVariables(variables)
}

/**
* Deploys the plugin, using a specific Git release
* This differs from {@see deployTask()} in that this task does NOT do any code changes to your working copy.
* It simply bundles up your code as-is, zips it, uploads it to the release you provided, and deploys it.
* It's expected that the plugin is already "fully built" at the time you run this.
*/
const deployFromReleaseTask = (done) => {
validateEnvVariables()

if (! gitReleaseTag()) {
sake.throwError('Missing required GitHub release tag')
}

// indicate that we are deploying
sake.options.deploy = true

let tasks = [
// clean the build directory
cleanBuildTask,
// copy plugin files to the build directory
copyBuildTask,
// create the zip, which will be attached to the releases
zipTask,
// upload the zip to the release,
gitHubUploadZipToReleaseTask
]

if (isDryRunDeploy()) {
tasks.push(function(cb) {
log.info('Dry run deployment successful')

return cb()
})
} else {
if (sake.config.deploy.wooId && sake.config.deploy.type === 'wc') {
tasks.push(promptWcUploadTask)
}

if (sake.config.deploy.type === 'wp') {
tasks.push(deployToWpRepoTask)
}
}

return gulp.series(tasks)(done)
}
deployFromReleaseTask.displayName = 'deploy:git-release'

/**
* Deploy the plugin
*/
const deployTask = (done) => {
validateEnvVariables()

if (!sake.isDeployable()) {
// we only validate if a release hasn't been provided to us
// if we are provided a release then we have to assume version numbers, etc. have already been adjusted
if (! hasGitRelease() && ! withoutCodeChanges() && !sake.isDeployable()) {
sake.throwError('Plugin is not deployable: \n * ' + sake.getChangelogErrors().join('\n * '))
}

Expand All @@ -76,10 +132,15 @@ const deployTask = (done) => {
// ensure version is bumped
bumpTask,
// fetch the latest WP/WC versions & bump the "tested up to" values
fetchLatestWpWcVersionsTask,
bumpMinReqsTask,
fetchAndBumpLatestWpWcVersions,
// prompt for the version to deploy as
promptDeployTask,
function (cb) {
if (! isNonInteractive()) {
return promptDeployTask()
} else {
return cb()
}
},
function (cb) {
if (sake.options.version === 'skip') {
log.error(chalk.red('Deploy skipped!'))
Expand All @@ -88,7 +149,13 @@ const deployTask = (done) => {
cb()
},
// replace version number & date
replaceVersionTask,
function (cb) {
if (withoutCodeChanges()) {
return cb()
}

return replaceVersionTask()
},
// delete prerelease, if any
cleanPrereleaseTask,
// build the plugin - compiles and copies to build dir
Expand All @@ -103,19 +170,33 @@ const deployTask = (done) => {
cb()
},
// git commit & push
shellGitPushUpdateTask,
function (cb) {
if (withoutCodeChanges() || isDryRunDeploy()) {
return cb()
}

return shellGitPushUpdateTask()
},
// create the zip, which will be attached to the releases
zipTask,
// create releases, attaching the zip
deployCreateReleasesTask,
// create the release if it doesn't already exist, and attach the zip
deployCreateReleasesTask
]

if (sake.config.deploy.wooId && sake.config.deploy.type === 'wc') {
tasks.push(promptWcUploadTask)
}
if (isDryRunDeploy()) {
tasks.push(function(cb) {
log.info('Dry run deployment successful')

if (sake.config.deploy.type === 'wp') {
tasks.push(deployToWpRepoTask)
return cb()
})
} else {
if (sake.config.deploy.wooId && sake.config.deploy.type === 'wc') {
tasks.push(promptWcUploadTask)
}

if (sake.config.deploy.type === 'wp') {
tasks.push(deployToWpRepoTask)
}
}

// finally, create a docs issue, if necessary
Expand Down Expand Up @@ -179,13 +260,15 @@ searchWtUpdateKeyTask.displayName = 'search:wt_update_key'
* Internal task for replacing the version and date when deploying
*/
const replaceVersionTask = (done) => {
if (!sake.getVersionBump()) {
const bumpVersion = newPluginVersion() || sake.getVersionBump()

if (!bumpVersion) {
sake.throwError('No version replacement specified')
}

const versions = sake.getPrereleaseVersions(sake.getPluginVersion())
const versionReplacements = versions.map(version => {
return { match: version, replacement: () => sake.getVersionBump() }
return { match: version, replacement: () => bumpVersion }
})

const filterChangelog = filter('**/{readme.md,readme.txt,changelog.txt}', { restore: true })
Expand Down Expand Up @@ -270,10 +353,19 @@ const deployCreateReleasesTask = (done) => {
sake.options.repo = sake.config.deploy.dev.name
sake.options.prefix_release_tag = sake.config.multiPluginRepo
cb()
},
gitHubCreateReleaseTask
}
]

if (hasGitRelease()) {
tasks.push(gitHubUploadZipToReleaseTask)
} else if (! isDryRunDeploy()) {
tasks.push(gitHubCreateReleaseTask)
} else {
// if it wasn't a dry run we would have created a release
log.info('Dry run - skipping creation of release')
return done()
}

return gulp.series(tasks)(done)
}
deployCreateReleasesTask.displayName = 'deploy_create_releases'
Expand Down Expand Up @@ -442,7 +534,11 @@ const fetchLatestWpWcVersionsTask = (done) => {
}
fetchLatestWpWcVersionsTask.displayName = 'fetch_latest_wp_wc_versions'

const fetchAndBumpLatestWpWcVersions = gulp.series(fetchLatestWpWcVersionsTask, bumpMinReqsTask)
fetchAndBumpLatestWpWcVersions.displayName = 'fetch_and_bump_latest_wp_wc_versions'

export {
deployFromReleaseTask,
deployTask,
deployPreflightTask,
deployValidateFrameworkVersionTask,
Expand All @@ -456,5 +552,6 @@ export {
updateWcRepoTask,
deployToWpRepoTask,
copyToWpRepoTask,
fetchLatestWpWcVersionsTask
fetchLatestWpWcVersionsTask,
fetchAndBumpLatestWpWcVersions
}
Loading