feat: allow to release from local machine
This commit is contained in:
		
							parent
							
								
									5cc62e49ee
								
							
						
					
					
						commit
						5bc46a08cf
					
				| @ -168,6 +168,7 @@ semantic-release | |||||||
| These options are currently available: | These options are currently available: | ||||||
| - `branch`: The branch on which releases should happen. Default: `'master'` | - `branch`: The branch on which releases should happen. Default: `'master'` | ||||||
| - `repositoryUrl`: The git repository URL. Default: `repository` property in `package.json` or git origin url. Any valid git url format is supported (See [Git protocols](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols)). If the [Github plugin](https://github.com/semantic-release/github) is used the URL must be a valid Github URL that include the `owner`, the `repository` name and the `host`. The Github shorthand URL is not supported. | - `repositoryUrl`: The git repository URL. Default: `repository` property in `package.json` or git origin url. Any valid git url format is supported (See [Git protocols](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols)). If the [Github plugin](https://github.com/semantic-release/github) is used the URL must be a valid Github URL that include the `owner`, the `repository` name and the `host`. The Github shorthand URL is not supported. | ||||||
|  | - `no-ci`: Skip Continuous Integration environment verifications, allowing to make releases from a local machine | ||||||
| - `dry-run`: Dry-run mode, skip publishing, print next version and release notes | - `dry-run`: Dry-run mode, skip publishing, print next version and release notes | ||||||
| - `extends`: Array of module or files path containing a shareable configuration. Options defined via CLI or in the `release` property will take precedence over the one defined in a shareable configuration. | - `extends`: Array of module or files path containing a shareable configuration. Options defined via CLI or in the `release` property will take precedence over the one defined in a shareable configuration. | ||||||
| - `debug`: Output debugging information | - `debug`: Output debugging information | ||||||
| @ -269,7 +270,8 @@ If you run `npm run semantic-release` locally a dry run gets performed, which lo | |||||||
| 
 | 
 | ||||||
| ### Can I run this on my own machine rather than on a CI server? | ### Can I run this on my own machine rather than on a CI server? | ||||||
| 
 | 
 | ||||||
| Of course you can, but this doesn’t necessarily mean you should. Running your tests on an independent machine before releasing software is a crucial part of this workflow. Also it is a pain to set this up locally, with tokens lying around and everything. That said, you can run the scripts with `--debug=false` explicitly. You have to export `GH_TOKEN=<your_token>` and `NPM_TOKEN=<your_other_token>`. | Yes, you can by explicitly setting the [`--no-ci` CLI option](#options), but this doesn’t necessarily mean you should. Running your tests on an independent machine before releasing software is a crucial part of this workflow. | ||||||
|  | You will need to set all necessary authentication token (like `GH_TOKEN` and `NPM_TOKEN`) on your local machine. | ||||||
| 
 | 
 | ||||||
| ### Can I manually trigger the release of a specific version? | ### Can I manually trigger the release of a specific version? | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										4
									
								
								cli.js
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								cli.js
									
									
									
									
									
								
							| @ -27,6 +27,10 @@ module.exports = async () => { | |||||||
|     ) |     ) | ||||||
|     .option('--generate-notes <path>', 'Path or package name for the generateNotes plugin') |     .option('--generate-notes <path>', 'Path or package name for the generateNotes plugin') | ||||||
|     .option('--publish <paths>', 'Comma separated list of paths or packages name for the publish plugin(s)', list) |     .option('--publish <paths>', 'Comma separated list of paths or packages name for the publish plugin(s)', list) | ||||||
|  |     .option( | ||||||
|  |       '--no-ci', | ||||||
|  |       'Skip Continuous Integration environment verifications, allowing to make releases from a local machine' | ||||||
|  |     ) | ||||||
|     .option('--debug', 'Output debugging information') |     .option('--debug', 'Output debugging information') | ||||||
|     .option( |     .option( | ||||||
|       '-d, --dry-run', |       '-d, --dry-run', | ||||||
|  | |||||||
							
								
								
									
										6
									
								
								index.js
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								index.js
									
									
									
									
									
								
							| @ -10,13 +10,13 @@ const {gitHead: getGitHead, isGitRepo} = require('./lib/git'); | |||||||
| module.exports = async opts => { | module.exports = async opts => { | ||||||
|   const {isCi, branch, isPr} = envCi(); |   const {isCi, branch, isPr} = envCi(); | ||||||
| 
 | 
 | ||||||
|   if (!isCi && !opts.dryRun) { |   if (!isCi && !opts.dryRun && !opts.noCi) { | ||||||
|     logger.log('This run was not triggered in a known CI environment, running in dry-run mode.'); |     logger.log('This run was not triggered in a known CI environment, running in dry-run mode.'); | ||||||
|     opts.dryRun = true; |     opts.dryRun = true; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   if (isCi && isPr) { |   if (isCi && isPr && !opts.noCi) { | ||||||
|     logger.log('This run was triggered by a pull request and therefore a new version won’t be published.'); |     logger.log("This run was triggered by a pull request and therefore a new version won't be published."); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -209,7 +209,7 @@ test.serial('Dry-run skips publish', async t => { | |||||||
|   t.is(publish.callCount, 0); |   t.is(publish.callCount, 0); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
| test.serial('Force a dry-run if not on a CI', async t => { | test.serial('Force a dry-run if not on a CI and ignore "noCi" is not explicitly set', async t => { | ||||||
|   // Create a git repository, set the current working directory at the root of the repo
 |   // Create a git repository, set the current working directory at the root of the repo
 | ||||||
|   await gitRepo(); |   await gitRepo(); | ||||||
|   // Add commits to the master branch
 |   // Add commits to the master branch
 | ||||||
| @ -257,6 +257,58 @@ test.serial('Force a dry-run if not on a CI', async t => { | |||||||
|   t.is(publish.callCount, 0); |   t.is(publish.callCount, 0); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | test.serial('Allow local releases with "noCi" option', async t => { | ||||||
|  |   // Create a git repository, set the current working directory at the root of the repo
 | ||||||
|  |   await gitRepo(); | ||||||
|  |   // Add commits to the master branch
 | ||||||
|  |   let commits = await gitCommits(['First']); | ||||||
|  |   // Create the tag corresponding to version 1.0.0
 | ||||||
|  |   await gitTagVersion('v1.0.0'); | ||||||
|  |   // Add new commits to the master branch
 | ||||||
|  |   commits = (await gitCommits(['Second'])).concat(commits); | ||||||
|  | 
 | ||||||
|  |   const lastRelease = {version: '1.0.0', gitHead: commits[commits.length - 1].hash, gitTag: 'v1.0.0'}; | ||||||
|  |   const nextRelease = {type: 'major', version: '2.0.0', gitHead: await getGitHead(), gitTag: 'v2.0.0'}; | ||||||
|  |   const notes = 'Release notes'; | ||||||
|  | 
 | ||||||
|  |   const verifyConditions = stub().resolves(); | ||||||
|  |   const getLastRelease = stub().resolves(lastRelease); | ||||||
|  |   const analyzeCommits = stub().resolves(nextRelease.type); | ||||||
|  |   const verifyRelease = stub().resolves(); | ||||||
|  |   const generateNotes = stub().resolves(notes); | ||||||
|  |   const publish = stub().resolves(); | ||||||
|  | 
 | ||||||
|  |   const options = { | ||||||
|  |     noCi: true, | ||||||
|  |     branch: 'master', | ||||||
|  |     repositoryUrl: 'git@hostname.com:owner/module.git', | ||||||
|  |     verifyConditions, | ||||||
|  |     getLastRelease, | ||||||
|  |     analyzeCommits, | ||||||
|  |     verifyRelease, | ||||||
|  |     generateNotes, | ||||||
|  |     publish, | ||||||
|  |   }; | ||||||
|  | 
 | ||||||
|  |   const semanticRelease = proxyquire('..', { | ||||||
|  |     './lib/logger': t.context.logger, | ||||||
|  |     'env-ci': () => ({isCi: false, branch: 'master', isPr: true}), | ||||||
|  |   }); | ||||||
|  |   t.truthy(await semanticRelease(options)); | ||||||
|  | 
 | ||||||
|  |   t.not(t.context.log.args[0][0], 'This run was not triggered in a known CI environment, running in dry-run mode.'); | ||||||
|  |   t.not( | ||||||
|  |     t.context.log.args[0][0], | ||||||
|  |     "This run was triggered by a pull request and therefore a new version won't be published." | ||||||
|  |   ); | ||||||
|  |   t.is(verifyConditions.callCount, 1); | ||||||
|  |   t.is(getLastRelease.callCount, 1); | ||||||
|  |   t.is(analyzeCommits.callCount, 1); | ||||||
|  |   t.is(verifyRelease.callCount, 1); | ||||||
|  |   t.is(generateNotes.callCount, 1); | ||||||
|  |   t.is(publish.callCount, 1); | ||||||
|  | }); | ||||||
|  | 
 | ||||||
| test.serial('Accept "undefined" values for the "getLastRelease" and "generateNotes" plugins', async t => { | test.serial('Accept "undefined" values for the "getLastRelease" and "generateNotes" plugins', async t => { | ||||||
|   // Create a git repository, set the current working directory at the root of the repo
 |   // Create a git repository, set the current working directory at the root of the repo
 | ||||||
|   await gitRepo(); |   await gitRepo(); | ||||||
| @ -333,7 +385,7 @@ test.serial('Returns falsy value if triggered by a PR', async t => { | |||||||
|   t.falsy(await semanticRelease({repositoryUrl: 'git@hostname.com:owner/module.git'})); |   t.falsy(await semanticRelease({repositoryUrl: 'git@hostname.com:owner/module.git'})); | ||||||
|   t.is( |   t.is( | ||||||
|     t.context.log.args[0][0], |     t.context.log.args[0][0], | ||||||
|     'This run was triggered by a pull request and therefore a new version won’t be published.' |     "This run was triggered by a pull request and therefore a new version won't be published." | ||||||
|   ); |   ); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user