chore: update next-version to handle using the next bump package.json… (#25599)

Co-authored-by: Bill Glesias <bglesias@gmail.com>
This commit is contained in:
Emily Rohrbough
2023-01-27 15:50:21 -06:00
committed by GitHub
parent b50714108d
commit 52e9dbc100
11 changed files with 254 additions and 59 deletions

View File

@@ -28,7 +28,7 @@ mainBuildFilters: &mainBuildFilters
only:
- develop
- /^release\/\d+\.\d+\.\d+$/
- 'mschile/chrome_memory_fix'
- 'emily/next-version'
# usually we don't build Mac app - it takes a long time
# but sometimes we want to really confirm we are doing the right thing
@@ -130,7 +130,7 @@ commands:
- run:
name: Check current branch to persist artifacts
command: |
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "mschile/chrome_memory_fix" ]]; then
if [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "emily/next-version" ]]; then
echo "Not uploading artifacts or posting install comment for this branch."
circleci-agent step halt
fi

View File

@@ -33,14 +33,14 @@ const clear = () => {
const prune = () => {
const cacheDir = state.getCacheDir()
const currentVersion = util.pkgVersion()
const checkedInBinaryVersion = util.pkgVersion()
let deletedBinary = false
return fs.readdirAsync(cacheDir)
.then((versions) => {
return Bluebird.all(versions.map((version) => {
if (version !== currentVersion) {
if (version !== checkedInBinaryVersion) {
deletedBinary = true
const versionDir = join(cacheDir, version)
@@ -51,7 +51,7 @@ const prune = () => {
})
.then(() => {
if (deletedBinary) {
logger.always(`Deleted all binary caches except for the ${currentVersion} binary cache.`)
logger.always(`Deleted all binary caches except for the ${checkedInBinaryVersion} binary cache.`)
} else {
logger.always(`No binary caches found to prune.`)
}

View File

@@ -136,14 +136,14 @@ describe('lib/tasks/cache', () => {
it('deletes cache binaries for all version but the current one', async () => {
await cache.prune()
const currentVersion = util.pkgVersion()
const checkedInBinaryVersion = util.pkgVersion()
const files = await fs.readdir('/.cache/Cypress')
expect(files.length).to.eq(1)
files.forEach((file) => {
expect(file).to.eq(currentVersion)
expect(file).to.eq(checkedInBinaryVersion)
})
defaultSnapshot()
@@ -155,14 +155,14 @@ describe('lib/tasks/cache', () => {
await fs.removeAsync(dir)
await cache.prune()
const currentVersion = util.pkgVersion()
const checkedInBinaryVersion = util.pkgVersion()
const files = await fs.readdirAsync('/.cache/Cypress')
expect(files.length).to.eq(1)
files.forEach((file) => {
expect(file).to.eq(currentVersion)
expect(file).to.eq(checkedInBinaryVersion)
})
defaultSnapshot()

View File

@@ -1,3 +1,4 @@
/* eslint-disable no-console */
// store the cwd
const cwd = process.cwd()
@@ -194,7 +195,7 @@ const deploy = {
return askMissingOptions(['version', 'platform'])(options)
.then(() => {
debug('building binary: platform %s version %s', options.platform, options.version)
console.log('building binary: platform %s version %s', options.platform, options.version)
return build.buildCypressApp(options)
})

View File

@@ -1,18 +1,20 @@
/* eslint-disable no-console */
// See ../guides/next-version.md for documentation.
const path = require('path')
const semver = require('semver')
const bumpCb = require('conventional-recommended-bump')
const { promisify } = require('util')
const currentVersion = require('../package.json').version
const checkedInBinaryVersion = require('../package.json').version
const { changeCatagories } = require('./semantic-commits/change-categories')
const { getCurrentReleaseData } = require('./semantic-commits/get-current-release-data')
const bump = promisify(bumpCb)
const paths = ['packages', 'cli']
const getNextVersionForPath = async (path) => {
const { version: releasedVersion } = await getCurrentReleaseData(false)
let commits
const whatBump = (foundCommits) => {
// semantic version bump: 0 - major, 1 - minor, 2 - patch
@@ -48,9 +50,20 @@ const getNextVersionForPath = async (path) => {
path,
})
let nextVersion = semver.inc(checkedInBinaryVersion, releaseType || 'patch')
const hasVersionBump = checkedInBinaryVersion !== releasedVersion
// See ../guides/next-version.md for documentation.
// for the time being, honoring this ENV -- ideally this will be deleted to remove manually overriding without a PR
if (process.env.NEXT_VERSION) {
nextVersion = process.env.NEXT_VERSION
} else if (hasVersionBump) {
nextVersion = checkedInBinaryVersion
}
return {
// allow the semantic next version to be overridden by environment
nextVersion: process.env.NEXT_VERSION || semver.inc(currentVersion, releaseType || 'patch'),
nextVersion,
commits,
}
}
@@ -93,7 +106,7 @@ if (require.main !== module) {
const { nextVersion } = await getNextVersionForBinary()
if (process.argv.includes('--npm')) {
if (process.argv.includes('--npm') && checkedInBinaryVersion !== nextVersion) {
const cmd = `npm --no-git-tag-version version ${nextVersion}`
console.log(`Running '${cmd}'...`)

View File

@@ -5,8 +5,8 @@
/* eslint-disable no-console */
const execa = require('execa')
const fs = require('fs')
const path = require('path')
const semverSortNewestFirst = require('semver/functions/rcompare')
const checkedInBinaryVersion = require('../package.json').version
const { getCurrentBranch, getPackagePath, readPackageJson, independentTagRegex } = require('./utils')
@@ -27,14 +27,6 @@ const getTags = async () => {
return stdout.split('\n')
}
const getBinaryVersion = async () => {
const { stdout: root } = await execa('git', ['rev-parse', '--show-toplevel'])
const rootPath = path.join(root, 'package.json')
const rootPackage = JSON.parse(fs.readFileSync(rootPath))
return rootPackage.version
}
const parseSemanticReleaseOutput = (output) => {
const currentVersion = (output.match(/associated with version (\d+\.\d+\.\d+-?\S*)/) || [])[1]
const nextVersion = (output.match(/next release version is (\d+\.\d+\.\d+-?\S*)/) || [])[1]
@@ -71,13 +63,11 @@ const getCurrentVersion = async (name) => {
const getPackageVersions = async (packages) => {
console.log(`Finding package versions...\n`)
const binaryVersion = await getBinaryVersion()
console.log(`Cypress binary: ${binaryVersion}`)
console.log(`Cypress binary: ${checkedInBinaryVersion}`)
const versions = {
cypress: {
currentVersion: binaryVersion,
currentVersion: checkedInBinaryVersion,
nextVersion: undefined,
},
}
@@ -232,7 +222,6 @@ if (require.main === module) {
}
module.exports = {
getBinaryVersion,
parseSemanticReleaseOutput,
readPackageJson,
releasePackages,

View File

@@ -1,32 +1,14 @@
/* eslint-disable no-console */
const execa = require('execa')
const childProcess = require('child_process')
const _ = require('lodash')
const { Octokit } = require('@octokit/core')
const { getCurrentReleaseData } = require('./get-current-release-data')
const { getNextVersionForBinary } = require('../get-next-version')
const { getLinkedIssues } = require('./get-linked-issues')
const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN })
/**
* Get the version, commit date and git sha of the latest tag published on npm.
*/
const getCurrentReleaseData = async () => {
console.log('Get Current Release Information\n')
const { stdout } = await execa('npm', ['info', 'cypress', '--json'])
const npmInfo = JSON.parse(stdout)
const latestReleaseInfo = {
version: npmInfo['dist-tags'].latest,
commitDate: npmInfo.buildInfo.commitDate,
buildSha: npmInfo.buildInfo.commitSha,
}
console.log({ latestReleaseInfo })
return latestReleaseInfo
}
/**
* Get the list of file names that have been added, deleted or changed since the git
* sha associated with the latest tag published on npm.
@@ -36,8 +18,8 @@ const getCurrentReleaseData = async () => {
* @param {string} latestReleaseInfo.commitDate - data of release
* @param {string} latestReleaseInfo.buildSha - git commit associated with published content
*/
const getChangedFilesSinceLastRelease = async (latestReleaseInfo) => {
const { stdout } = await execa('git', ['diff', `${latestReleaseInfo.buildSha}..`, '--name-only'])
const getChangedFilesSinceLastRelease = (latestReleaseInfo) => {
const stdout = childProcess.execSync(`git diff ${latestReleaseInfo.buildSha}.. --name-only`)
if (!stdout) {
console.log('no files changes since last release')
@@ -117,7 +99,6 @@ const getReleaseData = async (latestReleaseInfo) => {
if (require.main !== module) {
module.exports = {
getCurrentReleaseData,
getReleaseData,
}

View File

@@ -0,0 +1,26 @@
/* eslint-disable no-console */
const childProcess = require('child_process')
/**
* Get the version, commit date and git sha of the latest tag published on npm.
*/
const getCurrentReleaseData = (verbose = true) => {
verbose && console.log('Get Current Release Information\n')
const stdout = childProcess.execSync('npm info cypress --json')
const npmInfo = JSON.parse(stdout)
const latestReleaseInfo = {
version: npmInfo['dist-tags'].latest,
commitDate: npmInfo.buildInfo.commitDate,
buildSha: npmInfo.buildInfo.commitSha,
}
verbose && console.log({ latestReleaseInfo })
return latestReleaseInfo
}
module.exports = {
getCurrentReleaseData,
}

View File

@@ -1,19 +1,18 @@
/* eslint-disable no-console */
const { getBinaryVersion } = require('../npm-release')
const { validateChangelog } = require('./validate-changelog')
const { getCurrentReleaseData, getReleaseData } = require('./get-binary-release-data')
const { getCurrentReleaseData } = require('./get-current-release-data')
const { getReleaseData } = require('./get-binary-release-data')
const checkedInBinaryVersion = require('../../package.json').version
const changelog = async () => {
const latestReleaseInfo = await getCurrentReleaseData()
if (process.env.CIRCLECI) {
const checkedInBinaryVersion = await getBinaryVersion()
console.log({ checkedInBinaryVersion })
const hasVersionBump = checkedInBinaryVersion !== latestReleaseInfo.version
if (process.env.CIRCLE_BRANCH !== 'develop' || !/^release\/\d+\.\d+\.\d+$/.test(process.env.CIRCLE_BRANCH) || !hasVersionBump) {
if (process.env.CIRCLE_BRANCH !== 'develop' && !/^release\/\d+\.\d+\.\d+$/.test(process.env.CIRCLE_BRANCH) && !hasVersionBump) {
console.log('Only verify the entire changelog for develop, a release branch or any branch that bumped to the Cypress version in the package.json.')
return

View File

@@ -0,0 +1,183 @@
const { expect, use } = require('chai')
const proxyquire = require('proxyquire').noCallThru()
const sinon = require('sinon')
use(require('sinon-chai'))
describe('get-next-version', () => {
const releasedVersion = '12.2.0'
let getNextVersionForPath
let getNextVersionForBinary
let bumpStub
let getCurrentReleaseDataStub
afterEach(() => {
delete process.env.NEXT_VERSION
})
beforeEach(() => {
sinon.restore()
bumpStub = sinon.stub()
getCurrentReleaseDataStub = sinon.stub()
getCurrentReleaseDataStub.resolves({
version: releasedVersion,
})
const npmRelease = proxyquire('../get-next-version', {
'conventional-recommended-bump': bumpStub,
'./semantic-commits/get-current-release-data': {
getCurrentReleaseData: getCurrentReleaseDataStub,
},
'../package.json': sinon.stub({ version: releasedVersion }),
})
getNextVersionForPath = npmRelease.getNextVersionForPath
getNextVersionForBinary = npmRelease.getNextVersionForBinary
})
context('#getNextVersionForPath', () => {
it('determines next version is patch', async () => {
const semanticCommits = [
{ type: 'fix' },
]
bumpStub.callsFake(async ({ whatBump, _path }, cb) => {
const { level } = whatBump(semanticCommits)
expect(level, 'semantic bump level').to.eq(2)
return cb(undefined, { releaseType: 'patch' })
})
const { nextVersion, commits } = await getNextVersionForPath('packages')
expect(nextVersion).to.eq('12.2.1')
expect(commits).to.contain.members(semanticCommits)
})
it('determines next version is minor', async () => {
const semanticCommits = [
{ type: 'fix' },
{ type: 'feat' },
]
bumpStub.callsFake(async ({ whatBump, _path }, cb) => {
const { level } = whatBump(semanticCommits)
expect(level, 'semantic bump level').to.eq(1)
return cb(undefined, { releaseType: 'minor' })
})
const { nextVersion, commits } = await getNextVersionForPath('packages')
expect(nextVersion).to.eq('12.3.0')
expect(commits).to.contain.members(semanticCommits)
})
it('determines next version is major', async () => {
const semanticCommits = [
{ type: 'fix' },
{ type: 'feat' },
{ type: 'breaking' },
]
bumpStub.callsFake(async ({ whatBump, _path }, cb) => {
const { level } = whatBump(semanticCommits)
expect(level, 'semantic bump level').to.eq(0)
return cb(undefined, { releaseType: 'major' })
})
const { nextVersion, commits } = await getNextVersionForPath('packages')
expect(nextVersion).to.eq('13.0.0')
expect(commits).to.contain.members(semanticCommits)
})
it('honors package.json version when its been bumped', async () => {
const semanticCommits = [
{ type: 'fix' },
]
bumpStub.callsFake(async ({ whatBump, _path }, cb) => {
const { level } = whatBump(semanticCommits)
expect(level, 'semantic bump level').to.eq(2)
return cb(undefined, { releaseType: 'patch' })
})
getCurrentReleaseDataStub.resolves({
// package version !== release version assumed check in version is correct
version: '12.2.2',
})
const { nextVersion, commits } = await getNextVersionForPath('packages')
expect(nextVersion).to.eq('12.2.0')
expect(commits).to.contain.members(semanticCommits)
})
it('honors NEXT_VERSION env', async () => {
process.env.NEXT_VERSION = '15.0.0'
const semanticCommits = [
{ type: 'fix' },
]
bumpStub.callsFake(async ({ whatBump, _path }, cb) => {
const { level } = whatBump(semanticCommits)
expect(level, 'semantic bump level').to.eq(2)
return cb(undefined, { releaseType: 'patch' })
})
const { nextVersion, commits } = await getNextVersionForPath('packages', '12.2.2')
expect(nextVersion).to.eq('15.0.0')
expect(commits).to.contain.members(semanticCommits)
})
})
context('#getNextVersionForBinary', () => {
it('determines next version for all cli & packages changes', async () => {
let calls = 0
const cliSemanticCommits = [
{ type: 'fix', title: 'fix: cli' },
{ type: 'fix', title: 'fix: typescript' },
{ type: 'dependency', title: 'dependency: security update' },
]
const packagesSemanticCommits = [
{ type: 'feat', title: 'feat: add new command' },
]
bumpStub.callsFake(async ({ whatBump, _path }, cb) => {
if (calls === 0) {
const { level } = whatBump(packagesSemanticCommits)
expect(level, 'semantic bump level').to.eq(1)
calls++
return cb(undefined, { releaseType: 'minor' })
}
const { level } = whatBump(cliSemanticCommits)
expect(level, 'semantic bump level').to.eq(2)
return cb(undefined, { releaseType: 'patch' })
})
const { nextVersion, commits } = await getNextVersionForBinary('packages', releasedVersion)
expect(nextVersion).to.eq('12.3.0')
expect(commits).to.contain.members(packagesSemanticCommits)
expect(commits).to.contain.members(cliSemanticCommits)
})
})
})

View File

@@ -38,7 +38,10 @@ circleCiRootEvent.add({
// Therefore, we have each honeycomb event await this promise
// before sending itself.
let asyncInfo = Promise.all([getNextVersionForPath(path.resolve(__dirname, '../../packages')), commitInfo()])
let asyncInfo = Promise.all([
getNextVersionForPath(path.resolve(__dirname, '../../packages')),
commitInfo(),
])
.then(([{ nextVersion }, commitInformation]) => {
const ciInformation = ciProvider.commitParams() || {}