fix: allow multiple branches with same channel
This commit is contained in:
		
							parent
							
								
									20e7a38cdb
								
							
						
					
					
						commit
						63f51ae6dd
					
				| @ -48,8 +48,10 @@ For example the configuration `['+([0-9])?(.{+([0-9]),x}).x', 'master', 'next']` | ||||
| 
 | ||||
| ### channel | ||||
| 
 | ||||
| The `channel` can be defined for any branch type. If it's not defined, releases will be done on the default distribution channel (for example the `@latest` [dist-tag](https://docs.npmjs.com/cli/dist-tag) for npm). | ||||
| The value of `channel`, if defined, is generated with [Lodash template](https://lodash.com/docs#template) with the variable `name` available. | ||||
| The `channel` can be defined for any branch type. By default releases will be done on the default distribution channel (for example the `@latest` [dist-tag](https://docs.npmjs.com/cli/dist-tag) for npm) for the first [release branch](#release-branches) and on a distribution channel named based on the branch `name` for any other branch. | ||||
| If the `channel` property is set to `false` the default channel will be used. | ||||
| 
 | ||||
| The value of `channel`, if defined as a string, is generated with [Lodash template](https://lodash.com/docs#template) with the variable `name` available. | ||||
| 
 | ||||
| For example the configuration `['master', {name: 'next', channel: 'channel-${name}'}]` will be expanded as: | ||||
| ```js | ||||
| @ -78,7 +80,7 @@ For example the configuration `['1.1.x', '1.2.x', 'master']` will be expanded as | ||||
| 
 | ||||
| ### prerelease | ||||
| 
 | ||||
| A `prerelease` property applies only to pre-release branches, is required and The `prerelease` value must be valid per the [Semantic Versioning Specification](https://semver.org/#spec-item-9). It will determine the name of versions (for example if `prerelease` is set to `beta` the version be formatted like `2.0.0-beta.1`, `2.0.0-beta.2` etc...). | ||||
| A `prerelease` property applies only to pre-release branches and the `prerelease` value must be valid per the [Semantic Versioning Specification](https://semver.org/#spec-item-9). It will determine the name of versions (for example if `prerelease` is set to `beta` the version be formatted like `2.0.0-beta.1`, `2.0.0-beta.2` etc...). | ||||
| If the `prerelease` property is set to `true` the `name` value will be used. | ||||
| 
 | ||||
| The value of `prerelease`, if defined as a string, is generated with [Lodash template](https://lodash.com/docs#template) with the variable `name` available. | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| const {isUndefined} = require('lodash'); | ||||
| const semver = require('semver'); | ||||
| const {makeTag} = require('./utils'); | ||||
| const {makeTag, isSameChannel} = require('./utils'); | ||||
| 
 | ||||
| /** | ||||
|  * Last release. | ||||
| @ -28,7 +28,10 @@ const {makeTag} = require('./utils'); | ||||
|  */ | ||||
| module.exports = ({branch, options: {tagFormat}}, {before} = {}) => { | ||||
|   const [{version, gitTag, channel} = {}] = branch.tags | ||||
|     .filter(tag => (branch.type === 'prerelease' && branch.channel === tag.channel) || !semver.prerelease(tag.version)) | ||||
|     .filter( | ||||
|       tag => | ||||
|         (branch.type === 'prerelease' && isSameChannel(branch.channel, tag.channel)) || !semver.prerelease(tag.version) | ||||
|     ) | ||||
|     .filter(tag => isUndefined(before) || semver.lt(tag.version, before)) | ||||
|     .sort((a, b) => semver.rcompare(a.version, b.version)); | ||||
| 
 | ||||
|  | ||||
| @ -1,5 +1,6 @@ | ||||
| const semver = require('semver'); | ||||
| const {FIRST_RELEASE, FIRSTPRERELEASE} = require('./definitions/constants'); | ||||
| const {isSameChannel} = require('./utils'); | ||||
| 
 | ||||
| module.exports = ({branch, nextRelease: {type, channel}, lastRelease, logger}) => { | ||||
|   let version; | ||||
| @ -7,7 +8,7 @@ module.exports = ({branch, nextRelease: {type, channel}, lastRelease, logger}) = | ||||
|     const {major, minor, patch} = semver.parse(lastRelease.version); | ||||
|     version = | ||||
|       branch.type === 'prerelease' | ||||
|         ? semver.prerelease(lastRelease.version) && lastRelease.channel === channel | ||||
|         ? semver.prerelease(lastRelease.version) && isSameChannel(lastRelease.channel, channel) | ||||
|           ? semver.inc(lastRelease.version, 'prerelease') | ||||
|           : `${semver.inc(`${major}.${minor}.${patch}`, type)}-${branch.prerelease}.${FIRSTPRERELEASE}` | ||||
|         : semver.inc(lastRelease.version, type); | ||||
|  | ||||
| @ -71,6 +71,10 @@ function makeTag(tagFormat, version, channel) { | ||||
|   return template(tagFormat)({version: `${version}${channel ? `@${channel}` : ''}`}); | ||||
| } | ||||
| 
 | ||||
| function isSameChannel(channel, otherChannel) { | ||||
|   return channel === otherChannel || (!channel && !otherChannel); | ||||
| } | ||||
| 
 | ||||
| module.exports = { | ||||
|   extractErrors, | ||||
|   hideSensitiveValues, | ||||
| @ -86,4 +90,5 @@ module.exports = { | ||||
|   getFirstVersion, | ||||
|   getRange, | ||||
|   makeTag, | ||||
|   isSameChannel, | ||||
| }; | ||||
|  | ||||
| @ -581,6 +581,117 @@ test('Publish a pre-release version', async t => { | ||||
|   t.is(releases[0].gitTag, 'v1.1.0-beta.2@beta'); | ||||
| }); | ||||
| 
 | ||||
| test('Publish releases from different branch on the same channel', async t => { | ||||
|   const {cwd, repositoryUrl} = await gitRepo(true); | ||||
|   await gitCommits(['feat: initial commit'], {cwd}); | ||||
|   await gitTagVersion('v1.0.0', undefined, {cwd}); | ||||
|   await gitPush(repositoryUrl, 'master', {cwd}); | ||||
|   await gitCheckout('next-major', true, {cwd}); | ||||
|   await gitPush(repositoryUrl, 'next-major', {cwd}); | ||||
|   await gitCheckout('next', true, {cwd}); | ||||
|   await gitCommits(['feat: a feature'], {cwd}); | ||||
|   await gitPush(repositoryUrl, 'next', {cwd}); | ||||
| 
 | ||||
|   const config = { | ||||
|     branches: ['master', {name: 'next', channel: false}, {name: 'next-major', channel: false}], | ||||
|     repositoryUrl, | ||||
|   }; | ||||
|   const addChannel = stub().resolves({}); | ||||
|   const options = { | ||||
|     ...config, | ||||
|     verifyConditions: stub().resolves(), | ||||
|     verifyRelease: stub().resolves(), | ||||
|     generateNotes: stub().resolves(''), | ||||
|     addChannel, | ||||
|     prepare: stub().resolves(), | ||||
|     publish: stub().resolves(), | ||||
|     success: stub().resolves(), | ||||
|     fail: stub().resolves(), | ||||
|   }; | ||||
| 
 | ||||
|   let semanticRelease = requireNoCache('..', { | ||||
|     './lib/get-logger': () => t.context.logger, | ||||
|     'env-ci': () => ({isCi: true, branch: 'next', isPr: false}), | ||||
|   }); | ||||
|   let {releases} = await semanticRelease(options, {cwd, env: {}, stdout: {write: () => {}}, stderr: {write: () => {}}}); | ||||
| 
 | ||||
|   t.is(releases.length, 1); | ||||
|   t.is(releases[0].version, '1.1.0'); | ||||
|   t.is(releases[0].gitTag, 'v1.1.0'); | ||||
| 
 | ||||
|   await gitCommits(['fix: a fix'], {cwd}); | ||||
|   ({releases} = await semanticRelease(options, { | ||||
|     cwd, | ||||
|     env: {}, | ||||
|     stdout: {write: () => {}}, | ||||
|     stderr: {write: () => {}}, | ||||
|   })); | ||||
| 
 | ||||
|   t.is(releases.length, 1); | ||||
|   t.is(releases[0].version, '1.1.1'); | ||||
|   t.is(releases[0].gitTag, 'v1.1.1'); | ||||
| 
 | ||||
|   await gitCheckout('master', false, {cwd}); | ||||
|   await merge('next', {cwd}); | ||||
|   await gitPush('origin', 'master', {cwd}); | ||||
| 
 | ||||
|   semanticRelease = requireNoCache('..', { | ||||
|     './lib/get-logger': () => t.context.logger, | ||||
|     'env-ci': () => ({isCi: true, branch: 'master', isPr: false}), | ||||
|   }); | ||||
| 
 | ||||
|   t.falsy(await semanticRelease(options, {cwd, env: {}, stdout: {write: () => {}}, stderr: {write: () => {}}})); | ||||
|   t.is(addChannel.callCount, 0); | ||||
| }); | ||||
| 
 | ||||
| test('Publish pre-releases the same channel as regular releases', async t => { | ||||
|   const {cwd, repositoryUrl} = await gitRepo(true); | ||||
|   await gitCommits(['feat: initial commit'], {cwd}); | ||||
|   await gitTagVersion('v1.0.0', undefined, {cwd}); | ||||
|   await gitPush(repositoryUrl, 'master', {cwd}); | ||||
|   await gitCheckout('beta', true, {cwd}); | ||||
|   await gitCommits(['feat: a feature'], {cwd}); | ||||
|   await gitPush(repositoryUrl, 'beta', {cwd}); | ||||
| 
 | ||||
|   const config = { | ||||
|     branches: ['master', {name: 'beta', channel: false, prerelease: true}], | ||||
|     repositoryUrl, | ||||
|   }; | ||||
|   const options = { | ||||
|     ...config, | ||||
|     verifyConditions: stub().resolves(), | ||||
|     verifyRelease: stub().resolves(), | ||||
|     generateNotes: stub().resolves(''), | ||||
|     addChannel: false, | ||||
|     prepare: stub().resolves(), | ||||
|     publish: stub().resolves(), | ||||
|     success: stub().resolves(), | ||||
|     fail: stub().resolves(), | ||||
|   }; | ||||
| 
 | ||||
|   const semanticRelease = requireNoCache('..', { | ||||
|     './lib/get-logger': () => t.context.logger, | ||||
|     'env-ci': () => ({isCi: true, branch: 'beta', isPr: false}), | ||||
|   }); | ||||
|   let {releases} = await semanticRelease(options, {cwd, env: {}, stdout: {write: () => {}}, stderr: {write: () => {}}}); | ||||
| 
 | ||||
|   t.is(releases.length, 1); | ||||
|   t.is(releases[0].version, '1.1.0-beta.1'); | ||||
|   t.is(releases[0].gitTag, 'v1.1.0-beta.1'); | ||||
| 
 | ||||
|   await gitCommits(['fix: a fix'], {cwd}); | ||||
|   ({releases} = await semanticRelease(options, { | ||||
|     cwd, | ||||
|     env: {}, | ||||
|     stdout: {write: () => {}}, | ||||
|     stderr: {write: () => {}}, | ||||
|   })); | ||||
| 
 | ||||
|   t.is(releases.length, 1); | ||||
|   t.is(releases[0].version, '1.1.0-beta.2'); | ||||
|   t.is(releases[0].gitTag, 'v1.1.0-beta.2'); | ||||
| }); | ||||
| 
 | ||||
| test('Do not add pre-releases to a different channel', async t => { | ||||
|   const {cwd, repositoryUrl} = await gitRepo(true); | ||||
|   const commits = await gitCommits(['feat: initial release'], {cwd}); | ||||
|  | ||||
| @ -14,6 +14,7 @@ import { | ||||
|   getFirstVersion, | ||||
|   getRange, | ||||
|   makeTag, | ||||
|   isSameChannel, | ||||
| } from '../lib/utils'; | ||||
| 
 | ||||
| test('extractErrors', t => { | ||||
| @ -178,3 +179,12 @@ test('makeTag', t => { | ||||
|   t.is(makeTag(`v\${version}`, '1.0.0', 'next'), 'v1.0.0@next'); | ||||
|   t.is(makeTag(`v\${version}@test`, '1.0.0', 'next'), 'v1.0.0@next@test'); | ||||
| }); | ||||
| 
 | ||||
| test('isSameChannel', t => { | ||||
|   t.true(isSameChannel('next', 'next')); | ||||
|   t.true(isSameChannel(null, undefined)); | ||||
|   t.true(isSameChannel(false, undefined)); | ||||
|   t.true(isSameChannel('', false)); | ||||
| 
 | ||||
|   t.false(isSameChannel('next', false)); | ||||
| }); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user