Compare commits

...
15 Commits
Author SHA1 Message Date
Gregor MartynusandGitHub b8fb35c7e1 feat: throw an Error if package.json has duplicate "repository" key (#1656) 2020-10-11 14:59:51 -07:00
Graeme CasselsandGitHub 18e35b28ad docs: reorder default plugins list (#1650)
Reorder the list default plugins from alphabetical to order of execution.
2020-10-04 11:52:17 -07:00
Micael JarniacandGitHub e35e5bb73f docs(contributing): fix commit message examples (#1648)
It had the backticks (`\``) around the messages, but I think they were unintentional, probably a leftover from copy-pasting.
2020-10-02 15:12:20 -07:00
Gregor MartynusandGitHub 311c46580f docs(README): welcome @travi, add alumni section 2020-09-25 15:31:11 -07:00
b4c5d0a436 fix: add logging for when ssh falls back to http (#1639)
Co-authored-by: thomas williams <thomas.williams@thetradedesk.com>
2020-09-17 10:15:04 -07:00
Micael JarniacandGitHub c982249f87 docs(contributing): typo fix (#1638) 2020-09-16 11:39:04 -07:00
Joep KockelkornandGitHub 9635f50da6 docs: improve github actions recipe on git plugin (#1626) 2020-09-06 10:38:29 -07:00
ylemkimonandGitHub d036a899d5 ci(docs): use actions/checkout@v2 (#1620) 2020-08-17 16:26:13 -07:00
AbdelRahman WahdanandGitHub 9303d1dba0 docs(resources.md): added more sematnic release article (#1610) 2020-07-30 17:17:36 -07:00
kopalandGitHub b72cdb331b docs(configuration.md): Updated documentation for dry-run feature of semantic Release (#1607) 2020-07-29 15:25:32 -07:00
Ahmed HassaneinandGitHub ee44ee80c8 docs(github-actions): suggest action_dispatch as trigger (#1605) 2020-07-28 06:57:05 -07:00
Rylan CollinsandGitHub b24d2474b1 docs: add semantic-release-rubygem to community plugins (#1602) 2020-07-22 16:35:05 -07:00
Gavin StaniforthandGitHub 6d118c6c14 docs: be clear about what module of semantic-release handles updating the package.json (#1601) 2020-07-12 12:31:40 -07:00
Shun KakinokiandMatt Travi b5c9dea215 docs: update github documentation to docs.github.com 2020-07-09 22:44:15 -05:00
kopalandGitHub 1405b94296 docs: added recipe for Jenkins CI configuration (#1) (#1591) 2020-06-30 14:54:33 -07:00
15 changed files with 161 additions and 23 deletions
+6 -6
View File
@@ -107,11 +107,11 @@ To ensure consistency and quality, all documentation modifications must:
- a third-party product/brand/service, i.e. Integrate with [GitHub](https://github.com)
- an external concept or feature, i.e. Create a [GitHub release](https://help.github.com/articles/creating-releases)
- a package or module, i.e. The [`@semantic-release/github`](https://github.com/semantic-release/github) module
- Use the the [single backtick `code` quoting](https://help.github.com/articles/basic-writing-and-formatting-syntax/#quoting-code) for:
- Use the [single backtick `code` quoting](https://help.github.com/articles/basic-writing-and-formatting-syntax/#quoting-code) for:
- commands inside sentences, i.e. the `semantic-release` command
- programming language keywords, i.e. `function`, `async`, `String`
- packages or modules, i.e. The [`@semantic-release/github`](https://github.com/semantic-release/github) module
- Use the the [triple backtick `code` formatting](https://help.github.com/articles/creating-and-highlighting-code-blocks) for:
- Use the [triple backtick `code` formatting](https://help.github.com/articles/creating-and-highlighting-code-blocks) for:
- code examples
- configuration examples
- sequence of command lines
@@ -183,17 +183,17 @@ The footer should contain any information about **Breaking Changes** and is also
#### Examples
```commit
`fix(pencil): stop graphite breaking when too much pressure applied`
fix(pencil): stop graphite breaking when too much pressure applied
```
```commit
`feat(pencil): add 'graphiteWidth' option`
feat(pencil): add 'graphiteWidth' option
Fix #42
```
```commit
perf(pencil): remove graphiteWidth option`
perf(pencil): remove graphiteWidth option
BREAKING CHANGE: The graphiteWidth option has been removed.
@@ -229,7 +229,7 @@ Before pushing your code changes make sure there are no linting errors with `npm
### Tests
Running the integration test requires you to install [Docker](https://docs.docker.com/engine/installation) on your machine.
Running the integration test requires you to install [Docker](https://docs.docker.com/engine/installation) on your machine. Note: the tests assume that running `git init` will create a `master` branch by default. If your local `git` is configured differently (see [`init.defaultBranch`](https://github.blog/2020-07-27-highlights-from-git-2-28/#introducing-init-defaultbranch)), change it temporarily when running the tests.
All the [semantic-release](https://github.com/semantic-release) repositories use [AVA](https://github.com/avajs/ava) for writing and running tests.
+10 -3
View File
@@ -150,9 +150,16 @@ Let people know that your package is published using **semantic-release** by inc
## Team
| [![Stephan Bönnemann](https://github.com/boennemann.png?size=100)](https://github.com/boennemann) | [![Rolf Erik Lekang](https://github.com/relekang.png?size=100)](https://github.com/relekang) | [![Johannes Jörg Schmidt](https://github.com/jo.png?size=100)](https://github.com/jo) | [![Gregor Martynus](https://github.com/gr2m.png?size=100)](https://github.com/gr2m) | [![Pierre Vanduynslager](https://github.com/finnp.png?size=100)](https://github.com/finnp) | [![Pierre Vanduynslager](https://github.com/pvdlg.png?size=100)](https://github.com/pvdlg) | [![Christoph Witzko](https://github.com/christophwitzko.png?size=100)](https://github.com/christophwitzko) |
|---------------------------------------------------------------------------------------------------|----------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------|
| [Stephan Bönnemann](https://github.com/boennemann) | [Rolf Erik Lekang](https://github.com/relekang) | [Johannes Jörg Schmidt](https://github.com/jo) | [Gregor Martynus](https://github.com/gr2m) | [Finn Pauls](https://github.com/finnp) | [Pierre Vanduynslager](https://github.com/pvdlg) | [Christoph Witzko](https://github.com/christophwitzko) |
| [![Gregor Martynus](https://github.com/gr2m.png?size=100)](https://github.com/gr2m) | [![Pierre Vanduynslager](https://github.com/pvdlg.png?size=100)](https://github.com/pvdlg) | [![Matt Travi](https://github.com/travi.png?size=100)](https://github.com/travi) |
| ----------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------- |
| [Gregor Martynus](https://github.com/gr2m) | [Pierre Vanduynslager](https://github.com/pvdlg) | [Matt Travi](https://github.com/travi) |
## Alumni
| [![Stephan Bönnemann](https://github.com/boennemann.png?size=100)](https://github.com/boennemann) | [![Rolf Erik Lekang](https://github.com/relekang.png?size=100)](https://github.com/relekang) | [![Johannes Jörg Schmidt](https://github.com/jo.png?size=100)](https://github.com/jo) | [![Finn Pauls](https://github.com/finnp.png?size=100)](https://github.com/finnp) | [![Christoph Witzko](https://github.com/christophwitzko.png?size=100)](https://github.com/christophwitzko) |
| ------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- |
| [Stephan Bönnemann](https://github.com/boennemann) | [Rolf Erik Lekang](https://github.com/relekang) | [Johannes Jörg Schmidt](https://github.com/jo) | [Finn Pauls](https://github.com/finnp) | [Christoph Witzko](https://github.com/christophwitzko) |
<p align="center">
<img alt="Kill all humans" src="media/bender.png">
+4
View File
@@ -101,3 +101,7 @@
- `addChannel`: Update a Gitea release's pre-release field.
- [@google/semantic-release-replace-plugin](https://github.com/google/semantic-release-replace-plugin)
- `prepare`: Replace version strings in files using regex and glob.
- [semantic-release-rubygem](https://github.com/Gusto/semantic-release-rubygem)
- `verifyConditions`: Locate and validate a `.gemspec` file, locate and validate a `lib/**/version.rb` file, verify the presence of the `GEM_HOST_API_KEY` environment variable, and create a credentials file with the API key.
- `prepare`: Update the version in the `lib/**/version.rb` version file and [build](https://guides.rubygems.org/command-reference/#gem-build) the gem.
- `publish`: [Push the Ruby gem](https://guides.rubygems.org/command-reference/#gem-push) to the gem server.
+1
View File
@@ -5,6 +5,7 @@
- [Travis CI](travis.md)
- [GitLab CI](gitlab-ci.md)
- [GitHub Actions](github-actions.md)
- [Jenkins CI](jenkins-ci.md)
## Git hosted services
- [Git authentication with SSH keys](git-auth-ssh-keys.md)
+19 -2
View File
@@ -28,7 +28,9 @@ jobs:
runs-on: ubuntu-18.04
steps:
- name: Checkout
uses: actions/checkout@v1
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup Node.js
uses: actions/setup-node@v1
with:
@@ -48,9 +50,23 @@ To keep `package.json` updated in the `master` branch, [`@semantic-release/git`]
**Note**: Automatically populated `GITHUB_TOKEN` cannot be used if branch protection is enabled for the target branch. It is **not** advised to mitigate this limitation by overriding an automatically populated `GITHUB_TOKEN` variable with a [Personal Access Tokens](https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line), as it poses a security risk. Since Secret Variables are available for Workflows triggered by any branch, it becomes a potential vector of attack, where a Workflow triggered from a non-protected branch can expose and use a token with elevated permissions, yielding branch protection insignificant. One can use Personal Access Tokens in trusted environments, where all developers should have the ability to perform administrative actions in the given repository and branch protection is enabled solely for convenience purposes, to remind about required reviews or CI checks.
If the risk is acceptible, some extra configuration is needed. The [actions/checkout `persist-credentials`](https://github.com/marketplace/actions/checkout#usage) option needs to be `false`, otherwise the generated `GITHUB_TOKEN` will interfere with the custom one. Example:
```yaml
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
persist-credentials: false # <--- this
```
## Trigger semantic-release on demand
There is a way to trigger semantic-relase on demand. Use [`repository_dispatch`](https://help.github.com/en/articles/events-that-trigger-workflows#external-events-repository_dispatch) event to have control on when to generate a release by making an HTTP request, e.g.:
### Using GUI:
You can use [Manual Triggers](https://github.blog/changelog/2020-07-06-github-actions-manual-triggers-with-workflow_dispatch/) for GitHub Actions.
### Using HTTP:
Use [`repository_dispatch`](https://docs.github.com/en/actions/reference/events-that-trigger-workflows#repository_dispatch) event to have control on when to generate a release by making an HTTP request, e.g.:
```yaml
name: Release
@@ -67,6 +83,7 @@ To trigger a release, call (with a [Personal Access Tokens](https://help.github.
$ curl -v -H "Accept: application/vnd.github.everest-preview+json" -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/[org-name-or-username]/[repository]/dispatches -d '{ "event_type": "semantic-release" }'
```
### Using 3rd party apps:
If you'd like to use a GitHub app to manage this instead of creating a personal access token, you could consider using a project like:
* [Actions Panel](https://www.actionspanel.app/) - A declaratively configured way for triggering GitHub Actions
+61
View File
@@ -0,0 +1,61 @@
# Using semantic-release with [Jenkins CI](https://www.jenkins.io/doc/book/pipeline/)
## Environment variables
The [Authentication](../usage/ci-configuration.md#authentication) environment variables can be configured in [Jenkins Project Settings](https://www.jenkins.io/doc/pipeline/tour/environment/)..
Alternatively, the default `NPM_TOKEN` and `GH_TOKEN` can be easily [setup with semantic-release-cli](../usage/getting-started.md#getting-started).
## Node.js project configuration
### `Jenkinsfile (Declarative Pipeline)` configuration for a Node.js job
**Note**: The publish pipeline must run a [Node >= 10.18 version](../support/FAQ.md#why-does-semantic-release-require-node-version--1018).
This example is a minimal configuration for **semantic-release** with a build running Node 10.18. See [Jenkins documentation](https://www.jenkins.io/doc/) for additional configuration options.
The`semantic-release` execution command varies depending if you are using a [local](../usage/installation.md#local-installation) or [global](../usage/installation.md#global-installation) **semantic-release** installation.
```yaml
// The release stage in the pipeline will run only if the test stage in the pipeline is successful
pipeline {
agent any
environment {
GH_TOKEN = credentials('some-id')
}
stages {
stage('Test') {
steps {
sh '''
# Configure your test steps here (checkout, npm install, tests etc)
npm install
npm test
'''
}
}
stage('Release') {
tools {
nodejs "node 10.18"
}
steps {
sh '''
# Run optional required steps before releasing
npx semantic-release
'''
}
}
}
}
```
### `package.json` configuration for a Node job
A `package.json` is required only for [local](../usage/installation.md#local-installation) **semantic-release** installation.
```json
{
"devDependencies": {
"semantic-release": "^15.0.0"
}
}
```
+3 -1
View File
@@ -2,12 +2,14 @@
## Why is the `package.json`s version not updated in my repository?
**semantic-release** takes care of updating the `package.json`s version before publishing to [npm](https://www.npmjs.com).
[`@semantic-release/npm`](https://github.com/semantic-release/npm) takes care of updating the `package.json`s version before publishing to [npm](https://www.npmjs.com).
By default, only the published package will contain the version, which is the only place where it is *really* required, but the updated `package.json` will not be pushed to the Git repository
However, the [`@semantic-release/git`](https://github.com/semantic-release/git) plugin can be used to push the updated `package.json` as well as other files to the Git repository.
If you wish to only update the `package.json` and push via Git you can set the project to `"private": true,` within your `package.json` to prevent publishing to [npm](https://www.npmjs.com). This can be useful for using **semantic-release** with a non-node project.
## How can I use a npm build script that requires the `package.json`s version ?
The `package.json`s version will be updated by the `semantic-release` command just before publishing to [npm](https://www.npmjs.com), therefore it won't be available for scripts ran before the `semantic-release` command.
+1
View File
@@ -14,6 +14,7 @@
- ["Introduction to SemVer" - Irina Gebauer](https://blog.greenkeeper.io/introduction-to-semver-d272990c44f2)
- ["Introduction to Semantic Release" - liv](https://blog.greenkeeper.io/introduction-to-semantic-release-33f73b117c8)
- ["Series - Semantic Release Automation" - Abdelrahman Wahdan](https://dev.to/abdelrahmanahmed/semantic-release-and-how-to-automate-it-part-1-4pa2)
## Tutorials
+4 -2
View File
@@ -74,7 +74,7 @@ The branches on which releases should happen. By default **semantic-release** wi
**Note**: If your repository does not have a release branch, then **semantic-release** will fail with an `ERELEASEBRANCHES` error message. If you are using the default configuration, you can fix this error by pushing a `master` branch.
**Note**: Once **semantic-release** is configured, any user with the permission to push commits on one of those branches will be able to publish a release. It is recommended to protect those branches, for example with [GitHub protected branches](https://help.github.com/articles/about-protected-branches).
**Note**: Once **semantic-release** is configured, any user with the permission to push commits on one of those branches will be able to publish a release. It is recommended to protect those branches, for example with [GitHub protected branches](https://docs.github.com/github/administering-a-repository/about-protected-branches).
See [Workflow configuration](workflow-configuration.md#workflow-configuration) for more details.
@@ -116,7 +116,9 @@ Type: `Boolean`<br>
Default: `false` if running in a CI environment, `true` otherwise<br>
CLI arguments: `-d`, `--dry-run`
Dry-run mode, skip publishing, print next version and release notes.
The objective of the dry-run mode is to get a preview of the pending release. Dry-run mode skips the following steps: prepare, publish, success and fail. In addition to this it prints the next version and release notes to the console.
**Note**: The Dry-run mode verifies the repository push permission, even though nothing will be pushed. The verification is done to help user to figure out potential configuration issues.
### ci
+3 -3
View File
@@ -21,12 +21,12 @@ A plugin is a npm module that can implement one or more of the following steps:
### Default plugins
These four plugins are already part of **semantic-release** and don't have to be installed separately:
These four plugins are already part of **semantic-release** and are listed in order of execution. They do not have to be installed separately:
```
"@semantic-release/commit-analyzer"
"@semantic-release/github"
"@semantic-release/npm"
"@semantic-release/release-notes-generator"
"@semantic-release/npm"
"@semantic-release/github"
```
### Additional plugins
+4
View File
@@ -29,6 +29,10 @@ Please make sure to add the \`repositoryUrl\` to the [semantic-release configura
'docs/usage/configuration.md'
)}).`,
}),
EDUPLICATEREPOSITORYKEY: ({packageJsonPath}) => ({
message: 'Duplicate `"repository"` key in package.json.',
details: `Your package.json file at ${packageJsonPath} has more than one "repository" keys.`,
}),
EGITNOPERMISSION: ({options: {repositoryUrl}, branch: {name}}) => ({
message: 'Cannot push to the Git repository.',
details: `**semantic-release** cannot push the version tag to the branch \`${name}\` on the remote Git repository with URL \`${repositoryUrl}\`.
+19 -4
View File
@@ -1,12 +1,15 @@
const {readFile} = require('fs').promises;
const {castArray, pickBy, isNil, isString, isPlainObject} = require('lodash');
const readPkgUp = require('read-pkg-up');
const findPkgUp = require('pkg-up');
const {cosmiconfig} = require('cosmiconfig');
const resolveFrom = require('resolve-from');
const findDuplicatedPropertyKeys = require('find-duplicated-property-keys');
const debug = require('debug')('semantic-release:config');
const {repoUrl} = require('./git');
const PLUGINS_DEFINITIONS = require('./definitions/plugins');
const plugins = require('./plugins');
const {validatePlugin, parseConfig} = require('./plugins/utils');
const getError = require('./get-error');
const CONFIG_NAME = 'release';
const CONFIG_FILES = [
@@ -74,7 +77,7 @@ module.exports = async (context, cliOptions) => {
{name: 'beta', prerelease: true},
{name: 'alpha', prerelease: true},
],
repositoryUrl: (await pkgRepoUrl({normalize: false, cwd})) || (await repoUrl({cwd, env})),
repositoryUrl: (await pkgRepoUrl({cwd})) || (await repoUrl({cwd, env})),
tagFormat: `v\${version}`,
plugins: [
'@semantic-release/commit-analyzer',
@@ -93,6 +96,18 @@ module.exports = async (context, cliOptions) => {
};
async function pkgRepoUrl(options) {
const {packageJson} = (await readPkgUp(options)) || {};
return packageJson && (isPlainObject(packageJson.repository) ? packageJson.repository.url : packageJson.repository);
const packageJsonPath = await findPkgUp(options);
if (!packageJsonPath) return;
const packageJsonString = await readFile(packageJsonPath, 'utf-8');
const result = findDuplicatedPropertyKeys(packageJsonString);
if (result.length > 0) {
throw getError('EDUPLICATEREPOSITORYKEY', {packageJsonPath});
}
const {repository} = require(packageJsonPath);
if (!repository) return;
return isPlainObject(repository) ? repository.url : repository;
}
+4
View File
@@ -2,6 +2,7 @@ const {parse, format} = require('url'); // eslint-disable-line node/no-deprecate
const {isNil} = require('lodash');
const hostedGitInfo = require('hosted-git-info');
const {verifyAuth} = require('./git');
const debug = require('debug')('semantic-release:get-git-auth-url');
/**
* Determine the the git repository URL to use to push, either:
@@ -42,8 +43,11 @@ module.exports = async ({cwd, env, branch, options: {repositoryUrl}}) => {
// Test if push is allowed without transforming the URL (e.g. is ssh keys are set up)
try {
debug('Verifying ssh auth by attempting to push to %s', repositoryUrl);
await verifyAuth(repositoryUrl, branch.name, {cwd, env});
} catch (_) {
debug('SSH key auth failed, falling back to https.');
const envVar = Object.keys(GIT_TOKENS).find((envVar) => !isNil(env[envVar]));
const gitCredentials = `${GIT_TOKENS[envVar] || ''}${env[envVar] || ''}`;
+4 -2
View File
@@ -31,6 +31,7 @@
"env-ci": "^5.0.0",
"execa": "^4.0.0",
"figures": "^3.0.0",
"find-duplicated-property-keys": "^1.2.2",
"find-versions": "^3.0.0",
"get-stream": "^5.0.0",
"git-log-parser": "^1.2.0",
@@ -42,7 +43,7 @@
"micromatch": "^4.0.2",
"p-each-series": "^2.1.0",
"p-reduce": "^2.0.0",
"read-pkg-up": "^7.0.0",
"pkg-up": "^3.1.0",
"resolve-from": "^5.0.0",
"semver": "^7.3.2",
"semver-diff": "^3.1.1",
@@ -128,7 +129,8 @@
"prettier": true,
"space": true,
"rules": {
"unicorn/string-content": "off"
"unicorn/string-content": "off",
"node/no-unsupported-features/node-builtins": "off"
}
}
}
+18
View File
@@ -516,3 +516,21 @@ test('Throw an Error if one of the shareable config cannot be found', async (t)
code: 'MODULE_NOT_FOUND',
});
});
test('Throw an Error if package.json has duplicate "repository" key', async (t) => {
// Create a git repository, set the current working directory at the root of the repo
const {cwd} = await gitRepo();
// Create package.json with duplicate "repository" key
await writeFile(
path.resolve(cwd, 'package.json'),
`{
"repository": "https://github.com/octocat/repository",
"repository": "https://github.com/octocat/repository"
}`
);
const error = await t.throwsAsync(t.context.getConfig({cwd}));
t.is(error.code, 'EDUPLICATEREPOSITORYKEY');
t.is(error.message, 'Duplicate `"repository"` key in package.json.');
});