Compare commits
7 Commits
master
...
npm-plugin
Author | SHA1 | Date | |
---|---|---|---|
|
86e8f013a7 | ||
|
f6c978cd9e | ||
|
0ff4dee493 | ||
|
e36f0278f6 | ||
|
b06c9bbe4c | ||
|
12a981c020 | ||
|
01c9caee0b |
@ -1,4 +1,2 @@
|
|||||||
# style: prettier (#2670)
|
# style: prettier (#2670)
|
||||||
b06c9bbe4c6be121c5561b356d8c465c1cadffba
|
b06c9bbe4c6be121c5561b356d8c465c1cadffba
|
||||||
# style: upgraded prettier to v3 (#2863)
|
|
||||||
272af210523804de782b3076f05e56bcb4aeeb8f
|
|
18
.github/workflows/release.yml
vendored
18
.github/workflows/release.yml
vendored
@ -6,28 +6,18 @@ name: Release
|
|||||||
- next
|
- next
|
||||||
- beta
|
- beta
|
||||||
- "*.x"
|
- "*.x"
|
||||||
permissions:
|
|
||||||
contents: read # for checkout
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
permissions:
|
|
||||||
contents: write # to be able to publish a GitHub release
|
|
||||||
issues: write # to be able to comment on released issues
|
|
||||||
pull-requests: write # to be able to comment on released pull requests
|
|
||||||
id-token: write # to enable use of OIDC for npm provenance
|
|
||||||
name: release
|
name: release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@v3
|
||||||
- uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
|
- uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
cache: npm
|
cache: npm
|
||||||
node-version: lts/*
|
node-version: lts/*
|
||||||
- run: npm clean-install
|
- run: npm ci
|
||||||
- run: npm audit signatures
|
- run: npx semantic-release
|
||||||
# pinned version updated automatically by Renovate.
|
|
||||||
# details at https://semantic-release.gitbook.io/semantic-release/usage/installation#global-installation
|
|
||||||
- run: npx semantic-release@21.0.2
|
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_BOT_NPM_TOKEN }}
|
NPM_TOKEN: ${{ secrets.SEMANTIC_RELEASE_BOT_NPM_TOKEN }}
|
||||||
|
36
.github/workflows/scorecard.yml
vendored
36
.github/workflows/scorecard.yml
vendored
@ -1,36 +0,0 @@
|
|||||||
name: OpenSSF Scorecard
|
|
||||||
"on":
|
|
||||||
schedule:
|
|
||||||
- cron: 31 2 * * 1
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
permissions: read-all
|
|
||||||
jobs:
|
|
||||||
analysis:
|
|
||||||
name: Scorecard analysis
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
security-events: write
|
|
||||||
id-token: write
|
|
||||||
steps:
|
|
||||||
- name: Checkout code
|
|
||||||
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
|
||||||
with:
|
|
||||||
persist-credentials: false
|
|
||||||
- name: Run analysis
|
|
||||||
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
|
|
||||||
with:
|
|
||||||
results_file: results.sarif
|
|
||||||
results_format: sarif
|
|
||||||
publish_results: true
|
|
||||||
- name: Upload artifact
|
|
||||||
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
|
||||||
with:
|
|
||||||
name: SARIF file
|
|
||||||
path: results.sarif
|
|
||||||
retention-days: 5
|
|
||||||
- name: Upload to code-scanning
|
|
||||||
uses: github/codeql-action/upload-sarif@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0
|
|
||||||
with:
|
|
||||||
sarif_file: results.sarif
|
|
59
.github/workflows/test.yml
vendored
59
.github/workflows/test.yml
vendored
@ -12,69 +12,40 @@ on:
|
|||||||
- opened
|
- opened
|
||||||
- synchronize
|
- synchronize
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read # to fetch code (actions/checkout)
|
|
||||||
|
|
||||||
env:
|
|
||||||
FORCE_COLOR: 1
|
|
||||||
NPM_CONFIG_COLOR: always
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
# verify against ranges defined as supported in engines.node
|
|
||||||
test_matrix:
|
test_matrix:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version:
|
node-version:
|
||||||
- 20.8.1
|
- 18.0.0
|
||||||
- 20
|
- 19
|
||||||
- 21
|
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 5
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
- uses: actions/checkout@v3
|
||||||
- run: git config --global user.name github-actions
|
- run: git config --global user.name github-actions
|
||||||
- run: git config --global user.email github-actions@github.com
|
- run: git config --global user.email github-actions@github.com
|
||||||
- name: Use Node.js ${{ matrix.node-version }}
|
- name: Use Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: npm
|
cache: npm
|
||||||
- run: npm clean-install
|
- run: npm clean-install
|
||||||
- run: npm audit signatures
|
- name: Ensure dependencies are compatible with the version of node
|
||||||
- run: npm test
|
run: npx ls-engines
|
||||||
|
- run: npm run test:ci
|
||||||
# verify against the node version defined for development in the .nvmrc
|
|
||||||
test_dev:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
timeout-minutes: 5
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
|
||||||
- run: git config --global user.name github-actions
|
|
||||||
- run: git config --global user.email github-actions@github.com
|
|
||||||
- name: Use Node.js from .nvmrc
|
|
||||||
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
|
|
||||||
with:
|
|
||||||
node-version-file: .nvmrc
|
|
||||||
cache: npm
|
|
||||||
- run: npm clean-install
|
|
||||||
- run: npm audit signatures
|
|
||||||
- run: npm test
|
|
||||||
|
|
||||||
# separate job to set as required in branch protection,
|
# separate job to set as required in branch protection,
|
||||||
# as the build names above change each time Node versions change
|
# as the build names above change each time Node versions change
|
||||||
test:
|
test:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs: test_matrix
|
||||||
- test_dev
|
|
||||||
- test_matrix
|
|
||||||
if: ${{ !cancelled() }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: All matrix versions passed
|
- uses: actions/checkout@v3
|
||||||
if: ${{ !(contains(needs.*.result, 'failure')) }}
|
- uses: actions/setup-node@v3
|
||||||
run: exit 0
|
with:
|
||||||
- name: Some matrix version failed
|
node-version: lts/*
|
||||||
if: ${{ contains(needs.*.result, 'failure') }}
|
cache: npm
|
||||||
run: exit 1
|
- run: npm clean-install
|
||||||
|
- run: npm run lint
|
||||||
|
@ -146,7 +146,7 @@ If possible, make [atomic commits](https://en.wikipedia.org/wiki/Atomic_commit),
|
|||||||
|
|
||||||
- a commit should contain exactly one self-contained functional change
|
- a commit should contain exactly one self-contained functional change
|
||||||
- a functional change should be contained in exactly one commit
|
- a functional change should be contained in exactly one commit
|
||||||
- a commit should not create an inconsistent state (such as test errors, linting errors, partial fix, feature without documentation, etc...)
|
- a commit should not create an inconsistent state (such as test errors, linting errors, partial fix, feature with documentation etc...)
|
||||||
|
|
||||||
A complex feature can be broken down into multiple commits as long as each one maintains a consistent state and consists of a self-contained change.
|
A complex feature can be broken down into multiple commits as long as each one maintains a consistent state and consists of a self-contained change.
|
||||||
|
|
||||||
@ -241,82 +241,42 @@ $ git clone https://github.com/semantic-release/<repo-name>
|
|||||||
$ cd <repo-name>
|
$ cd <repo-name>
|
||||||
# Assign the original repo to a remote called "upstream"
|
# Assign the original repo to a remote called "upstream"
|
||||||
$ git remote add upstream https://github.com/semantic-release/<repo-name>
|
$ git remote add upstream https://github.com/semantic-release/<repo-name>
|
||||||
# Switch your node version to the version defined by the project as the development version
|
|
||||||
# This step assumes you have already installed and configured https://github.com/nvm-sh/nvm
|
|
||||||
# You may need to run `nvm install` if you have not already installed the development node version
|
|
||||||
$ nvm use
|
|
||||||
# Install the dependencies
|
# Install the dependencies
|
||||||
$ npm install
|
$ npm install
|
||||||
```
|
```
|
||||||
|
|
||||||
### Verification
|
### Lint
|
||||||
|
|
||||||
The `test` script is structured to execute as much of the verification for the project as possible.
|
All the [semantic-release](https://github.com/semantic-release) repositories use [XO](https://github.com/sindresorhus/xo) for linting and [Prettier](https://prettier.io) for formatting.
|
||||||
Ensuring that the `test` script fully passes in the node version defined as the development version in the `.nvmrc`
|
Prettier formatting will be automatically verified and fixed by XO.
|
||||||
minimizes the chances of the test workflow failing after pushing your changes.
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
Before pushing your code changes make sure there are no linting errors with `npm run lint`.
|
||||||
> Before pushing your code changes, be sure to run the verification for the project with `npm test`.
|
|
||||||
|
|
||||||
[npm-run-all2](https://www.npmjs.com/package/npm-run-all2) is used to enable running multiple independent lint and test
|
**Tips**:
|
||||||
scripts together from the `test` script.
|
|
||||||
This enables the test script to not only run all scripts, but also parallelize some of the scripts to optimize the overall
|
|
||||||
time required for verification.
|
|
||||||
|
|
||||||
When a failure occurs with the `test`, the output can be a bit confusing because there may be output from multiple parallel
|
- Most linting errors can be automatically fixed with `npm run lint -- --fix`.
|
||||||
scripts mixed together.
|
- Install the [XO plugin](https://github.com/sindresorhus/xo#editor-plugins) for your editor to see linting errors directly in your editor and automatically fix them on save.
|
||||||
To investigate the failure with cleaner output, re-run the problematic script directly using the script name from the label
|
|
||||||
included on the left side of the output
|
|
||||||
|
|
||||||
```shell
|
### Tests
|
||||||
$ npm run <script-name>
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Lint
|
Running the integration test requires you to install [Docker](https://docs.docker.com/engine/installation) on your machine.
|
||||||
|
|
||||||
##### Prettier
|
|
||||||
|
|
||||||
All the [semantic-release](https://github.com/semantic-release) repositories use [Prettier](https://prettier.io) for formatting.
|
|
||||||
Prettier formatting will be automatically verified by the `lint:prettier` script, included in the `test` script.
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> Most linting errors can be automatically fixed with `npm run lint:prettier:fix`.
|
|
||||||
|
|
||||||
##### Other Lint Tools
|
|
||||||
|
|
||||||
Other tools are used for specific compatibility concerns, but are less likely to result in failures in common contributions.
|
|
||||||
Please follow the guidance of these tools if failures are encountered.
|
|
||||||
|
|
||||||
#### Tests
|
|
||||||
|
|
||||||
> [!NOTE]
|
|
||||||
> Before pushing your code changes make sure all **tests pass** and the unit test **coverage is 100%**:
|
|
||||||
|
|
||||||
All the [semantic-release](https://github.com/semantic-release) repositories use [AVA](https://github.com/avajs/ava) for writing and running tests.
|
All the [semantic-release](https://github.com/semantic-release) repositories use [AVA](https://github.com/avajs/ava) for writing and running tests.
|
||||||
|
|
||||||
During development, you can:
|
Before pushing your code changes make sure all **tests pass** and the **coverage is 100%**:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
$ npm run test
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tips:** During development you can:
|
||||||
|
|
||||||
- run only a subset of test files with `ava <glob>`, for example `ava test/mytestfile.test.js`
|
- run only a subset of test files with `ava <glob>`, for example `ava test/mytestfile.test.js`
|
||||||
- run in watch mode with `ava -w` to automatically run a test file when you modify it
|
- run in watch mode with `ava -w` to automatically run a test file when you modify it
|
||||||
- run only the test you are working on by adding [`.only` to the test definition](https://github.com/avajs/ava#running-specific-tests)
|
- run only the test you are working on by adding [`.only` to the test definition](https://github.com/avajs/ava#running-specific-tests)
|
||||||
|
|
||||||
##### Unit Tests
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm run test:unit
|
|
||||||
```
|
|
||||||
|
|
||||||
##### Integration Tests
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> Running the integration test requires you to install [Docker](https://docs.docker.com/engine/installation) on your machine.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
$ npm run test:integration
|
|
||||||
```
|
|
||||||
|
|
||||||
### Commits
|
### Commits
|
||||||
|
|
||||||
All the [semantic-release](https://github.com/semantic-release) repositories use [Commitizen](https://github.com/commitizen/cz-cli) to help you create [valid commit messages](#commit-message-guidelines).
|
All the [semantic-release](https://github.com/semantic-release) repositories use [Commitizen](https://github.com/commitizen/cz-cli) to help you create [valid commit messages](#commit-message-guidelines).
|
||||||
|
|
||||||
Assuming you have [installed Commitizen](https://github.com/commitizen/cz-cli#installing-the-command-line-tool), run `git cz` to start the interactive commit message CLI rather than `git commit` when committing.
|
After staging your changes with `git add`, run `npm run cm` to start the interactive commit message CLI.
|
||||||
|
4
LICENSE
4
LICENSE
@ -9,8 +9,8 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|||||||
copies of the Software, and to permit persons to whom the Software is
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
furnished to do so, subject to the following conditions:
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
The above copyright notice and this permission notice shall be included in all
|
||||||
all copies or substantial portions of the Software.
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
12
README.md
12
README.md
@ -7,9 +7,6 @@
|
|||||||
<a href="https://github.com/semantic-release/semantic-release/actions?query=workflow%3ATest+branch%3Amaster">
|
<a href="https://github.com/semantic-release/semantic-release/actions?query=workflow%3ATest+branch%3Amaster">
|
||||||
<img alt="Build states" src="https://github.com/semantic-release/semantic-release/workflows/Test/badge.svg">
|
<img alt="Build states" src="https://github.com/semantic-release/semantic-release/workflows/Test/badge.svg">
|
||||||
</a>
|
</a>
|
||||||
<a href="https://securityscorecards.dev/viewer/?uri=github.com/semantic-release/semantic-release">
|
|
||||||
<img alt="OpenSSF Scorecard" src="https://api.securityscorecards.dev/projects/github.com/semantic-release/semantic-release/badge">
|
|
||||||
</a>
|
|
||||||
<a href="#badge">
|
<a href="#badge">
|
||||||
<img alt="semantic-release: angular" src="https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release">
|
<img alt="semantic-release: angular" src="https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release">
|
||||||
</a>
|
</a>
|
||||||
@ -44,7 +41,6 @@ This removes the immediate connection between human emotions and version numbers
|
|||||||
- Avoid potential errors associated with manual releases
|
- Avoid potential errors associated with manual releases
|
||||||
- Support any [package managers and languages](docs/recipes/release-workflow/README.md#package-managers-and-languages) via [plugins](docs/usage/plugins.md)
|
- Support any [package managers and languages](docs/recipes/release-workflow/README.md#package-managers-and-languages) via [plugins](docs/usage/plugins.md)
|
||||||
- Simple and reusable configuration via [shareable configurations](docs/usage/shareable-configurations.md)
|
- Simple and reusable configuration via [shareable configurations](docs/usage/shareable-configurations.md)
|
||||||
- Support for [npm package provenance](https://github.com/semantic-release/npm#npm-provenance) that promotes increased supply-chain security via signed attestations on GitHub Actions
|
|
||||||
|
|
||||||
## How does it work?
|
## How does it work?
|
||||||
|
|
||||||
@ -69,7 +65,7 @@ The table below shows which commit message gets you which release type when `sem
|
|||||||
### Automation with CI
|
### Automation with CI
|
||||||
|
|
||||||
**semantic-release** is meant to be executed on the CI environment after every successful build on the release branch.
|
**semantic-release** is meant to be executed on the CI environment after every successful build on the release branch.
|
||||||
This way no human is directly involved in the release process and the releases are guaranteed to be [unromantic and unsentimental](https://github.com/dominictarr/sentimental-versioning#readme).
|
This way no human is directly involved in the release process and the releases are guaranteed to be [unromantic and unsentimental](http://sentimentalversioning.org).
|
||||||
|
|
||||||
### Triggering a release
|
### Triggering a release
|
||||||
|
|
||||||
@ -110,9 +106,9 @@ In order to use **semantic-release** you need:
|
|||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- Usage
|
- Usage
|
||||||
- [Getting started](docs/usage/getting-started.md)
|
- [Getting started](docs/usage/getting-started.md#getting-started)
|
||||||
- [Installation](docs/usage/installation.md)
|
- [Installation](docs/usage/installation.md#installation)
|
||||||
- [CI Configuration](docs/usage/ci-configuration.md)
|
- [CI Configuration](docs/usage/ci-configuration.md#ci-configuration)
|
||||||
- [Configuration](docs/usage/configuration.md#configuration)
|
- [Configuration](docs/usage/configuration.md#configuration)
|
||||||
- [Plugins](docs/usage/plugins.md)
|
- [Plugins](docs/usage/plugins.md)
|
||||||
- [Workflow configuration](docs/usage/workflow-configuration.md)
|
- [Workflow configuration](docs/usage/workflow-configuration.md)
|
||||||
|
@ -2,10 +2,10 @@
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
- [Getting started](docs/usage/getting-started.md)
|
- [Getting started](docs/usage/getting-started.md#getting-started)
|
||||||
- [Installation](docs/usage/installation.md)
|
- [Installation](docs/usage/installation.md#installation)
|
||||||
- [CI Configuration](docs/usage/ci-configuration.md)
|
- [CI Configuration](docs/usage/ci-configuration.md#ci-configuration)
|
||||||
- [Configuration](docs/usage/configuration.md)
|
- [Configuration](docs/usage/configuration.md#configuration)
|
||||||
- [Plugins](docs/usage/plugins.md)
|
- [Plugins](docs/usage/plugins.md)
|
||||||
- [Workflow configuration](docs/usage/workflow-configuration.md)
|
- [Workflow configuration](docs/usage/workflow-configuration.md)
|
||||||
- [Shareable configurations](docs/usage/shareable-configurations.md)
|
- [Shareable configurations](docs/usage/shareable-configurations.md)
|
||||||
|
@ -25,7 +25,7 @@ See https://github.com/semantic-release/semantic-release/blob/master/docs/suppor
|
|||||||
|
|
||||||
execa("git", ["--version"])
|
execa("git", ["--version"])
|
||||||
.then(({ stdout }) => {
|
.then(({ stdout }) => {
|
||||||
const gitVersion = findVersions(stdout, { loose: true })[0];
|
const gitVersion = findVersions(stdout)[0];
|
||||||
if (lt(gitVersion, MIN_GIT_VERSION)) {
|
if (lt(gitVersion, MIN_GIT_VERSION)) {
|
||||||
console.error(`[semantic-release]: Git version ${MIN_GIT_VERSION} is required. Found ${gitVersion}.`);
|
console.error(`[semantic-release]: Git version ${MIN_GIT_VERSION} is required. Found ${gitVersion}.`);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
const semanticRelease = require("semantic-release");
|
const semanticRelease = require("semantic-release");
|
||||||
const { WritableStreamBuffer } = require("stream-buffers");
|
const { WritableStreamBuffer } = require("stream-buffers");
|
||||||
|
|
||||||
const stdoutBuffer = new WritableStreamBuffer();
|
const stdoutBuffer = WritableStreamBuffer();
|
||||||
const stderrBuffer = new WritableStreamBuffer();
|
const stderrBuffer = WritableStreamBuffer();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await semanticRelease(
|
const result = await semanticRelease(
|
||||||
@ -127,7 +127,7 @@ It allows to configure **semantic-release** to write errors to a specific stream
|
|||||||
|
|
||||||
Type: `Object` `Boolean`<br>
|
Type: `Object` `Boolean`<br>
|
||||||
|
|
||||||
An object with [`lastRelease`](#lastrelease), [`nextRelease`](#nextrelease), [`commits`](#commits) and [`releases`](#releases) if a release is published or `false` if no release was published.
|
And object with [`lastRelease`](#lastrelease), [`nextRelease`](#nextrelease), [`commits`](#commits) and [`releases`](#releases) if a release is published or `false` if no release was published.
|
||||||
|
|
||||||
#### lastRelease
|
#### lastRelease
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ Information related to the last release found:
|
|||||||
| gitTag | `String` | The [Git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) associated with the last release. |
|
| gitTag | `String` | The [Git tag](https://git-scm.com/book/en/v2/Git-Basics-Tagging) associated with the last release. |
|
||||||
| channel | `String` | The distribution channel on which the last release was initially made available (`undefined` for the default distribution channel). |
|
| channel | `String` | The distribution channel on which the last release was initially made available (`undefined` for the default distribution channel). |
|
||||||
|
|
||||||
**Note**: If no previous release is found, `lastRelease` will be an empty `Object`.
|
**Notes**: If no previous release is found, `lastRelease` will be an empty `Object`.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ Example:
|
|||||||
|
|
||||||
Type: `Array<Object>`
|
Type: `Array<Object>`
|
||||||
|
|
||||||
The list of commit(s) included in the new release.<br>
|
The list of commit included in the new release.<br>
|
||||||
Each commit object has the following properties:
|
Each commit object has the following properties:
|
||||||
|
|
||||||
| Name | Type | Description |
|
| Name | Type | Description |
|
||||||
|
@ -84,11 +84,6 @@
|
|||||||
- `verifyRelease`: Checks and warns (does not error by default) if the version numbers found on maven central and within the Git project differ by quite a bit
|
- `verifyRelease`: Checks and warns (does not error by default) if the version numbers found on maven central and within the Git project differ by quite a bit
|
||||||
- `prepare`: Changes the version number in the `pom.xml` (or all `pom.xml` files in maven projects with multiple `pom.xml` files) and optionally creates a commit with this version number and pushes it to `master`
|
- `prepare`: Changes the version number in the `pom.xml` (or all `pom.xml` files in maven projects with multiple `pom.xml` files) and optionally creates a commit with this version number and pushes it to `master`
|
||||||
- `publish`: Runs `mvn deploy` to deploy to maven central and optionally will update to next snapshot version and merge changes to development branch
|
- `publish`: Runs `mvn deploy` to deploy to maven central and optionally will update to next snapshot version and merge changes to development branch
|
||||||
- [maven-semantic-release](https://github.com/terrestris/maven-semantic-release) (alternative version)
|
|
||||||
- `verifyConditions`: Verifies that the `mvn` command exists.
|
|
||||||
- `prepare`: Changes version number in `pom.xml` and optionally in all child modules.
|
|
||||||
- `publish`: Runs one of the mvn targets `deploy`, `package jib:build` or `deploy jib:build`.
|
|
||||||
- `success`: Optionally sets new snapshot version and commits it.
|
|
||||||
- [semantic-release-ado](https://github.com/lluchmk/semantic-release-ado)
|
- [semantic-release-ado](https://github.com/lluchmk/semantic-release-ado)
|
||||||
- `prepare`: Stores the version number as an Azure DevOps pipeline variable available to downstream steps on the job
|
- `prepare`: Stores the version number as an Azure DevOps pipeline variable available to downstream steps on the job
|
||||||
- [gradle-semantic-release](https://github.com/KengoTODA/gradle-semantic-release-plugin)
|
- [gradle-semantic-release](https://github.com/KengoTODA/gradle-semantic-release-plugin)
|
||||||
@ -112,7 +107,7 @@
|
|||||||
- `verifyConditions`: Verify the presence and the validity of the authentication and the assets option configuration.
|
- `verifyConditions`: Verify the presence and the validity of the authentication and the assets option configuration.
|
||||||
- `publish`: Publish a Gitea release, optionally uploading file assets.
|
- `publish`: Publish a Gitea release, optionally uploading file assets.
|
||||||
- `addChannel`: Update a Gitea release's pre-release field.
|
- `addChannel`: Update a Gitea release's pre-release field.
|
||||||
- [semantic-release-replace-plugin](https://github.com/jpoehnelt/semantic-release-replace-plugin)
|
- [@google/semantic-release-replace-plugin](https://github.com/google/semantic-release-replace-plugin)
|
||||||
- `prepare`: Replace version strings in files using regex and glob.
|
- `prepare`: Replace version strings in files using regex and glob.
|
||||||
- [semantic-release-rubygem](https://github.com/Gusto/semantic-release-rubygem)
|
- [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.
|
- `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.
|
||||||
@ -176,21 +171,3 @@
|
|||||||
- `verifyConditions` Validate configuration, `Cargo.toml`, and local cargo executable. Also, logs in into `crates.io`.
|
- `verifyConditions` Validate configuration, `Cargo.toml`, and local cargo executable. Also, logs in into `crates.io`.
|
||||||
- `prepare` Write the new version number into `Cargo.toml` file and perform `cargo check` if configured.
|
- `prepare` Write the new version number into `Cargo.toml` file and perform `cargo check` if configured.
|
||||||
- `publish` Publish the Rust crate to `crates.io`
|
- `publish` Publish the Rust crate to `crates.io`
|
||||||
- [semantic-release-coralogix](https://github.com/adobe/semantic-release-coralogix)
|
|
||||||
- `verifyConditions` Verified that required credentials are provided and API is accessible
|
|
||||||
- `publish` add a release tag to Coralogix
|
|
||||||
- [semantic-release-jira-notes](https://github.com/iamludal/semantic-release-jira-notes)
|
|
||||||
- `verifyConditions`: Validate the config options.
|
|
||||||
- `generateNotes`: Generate the release notes with links to JIRA issues.
|
|
||||||
- [semantic-release-major-tag](https://github.com/doteric/semantic-release-major-tag)
|
|
||||||
- `success` Create major version tag, for example `v1`.
|
|
||||||
- [semantic-release-yarn](https://github.com/hongaar/semantic-release-yarn)
|
|
||||||
- **Note**: this is an alternative to the default `@semantic-release/npm` plugin and adds support for monorepos.
|
|
||||||
- `verifyConditions` Verify Yarn 2 or higher is installed, verify the presence of a NPM auth token (either in an environment variable or a `.yarnrc.yml` file) and verify the authentication method is valid.
|
|
||||||
- `prepare` Update the `package.json` version and create the package tarball.
|
|
||||||
- `addChannel` Add a tag for the release.
|
|
||||||
- `publish` Publish to the npm registry.
|
|
||||||
- [semantic-release-pub](https://github.com/zeshuaro/semantic-release-pub)
|
|
||||||
- `verifyConditions`: Verify the presence of the `pub.dev` authentication and release configuration
|
|
||||||
- `prepare`: Update the `pubspec.yaml` version
|
|
||||||
- `publish`: Publish the package onto the `pub.dev` registry
|
|
||||||
|
@ -6,11 +6,6 @@ The [Authentication](../../usage/ci-configuration.md#authentication) environment
|
|||||||
|
|
||||||
In this example a publish type [`NPM_TOKEN`](https://docs.npmjs.com/creating-and-viewing-authentication-tokens) is required to publish a package to the npm registry. GitHub Actions [automatically populate](https://help.github.com/en/articles/virtual-environments-for-github-actions#github_token-secret) a [`GITHUB_TOKEN`](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) environment variable which can be used in Workflows.
|
In this example a publish type [`NPM_TOKEN`](https://docs.npmjs.com/creating-and-viewing-authentication-tokens) is required to publish a package to the npm registry. GitHub Actions [automatically populate](https://help.github.com/en/articles/virtual-environments-for-github-actions#github_token-secret) a [`GITHUB_TOKEN`](https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line) environment variable which can be used in Workflows.
|
||||||
|
|
||||||
## npm provenance
|
|
||||||
|
|
||||||
Since GitHub Actions is a [supported provider](https://docs.npmjs.com/generating-provenance-statements#provenance-limitations) for [npm provenance](https://docs.npmjs.com/generating-provenance-statements), it is recommended to enable this to increase supply-chain security for your npm packages.
|
|
||||||
Find more detail about configuring npm to publish with provenance through semantic-release [in the documentation for our npm plugin](https://github.com/semantic-release/npm#npm-provenance).
|
|
||||||
|
|
||||||
## Node project configuration
|
## Node project configuration
|
||||||
|
|
||||||
[GitHub Actions](https://github.com/features/actions) support [Workflows](https://help.github.com/en/articles/configuring-workflows), allowing to run tests on multiple Node versions and publish a release only when all test pass.
|
[GitHub Actions](https://github.com/features/actions) support [Workflows](https://help.github.com/en/articles/configuring-workflows), allowing to run tests on multiple Node versions and publish a release only when all test pass.
|
||||||
@ -28,19 +23,10 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: read # for checkout
|
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
name: Release
|
name: Release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
|
||||||
contents: write # to be able to publish a GitHub release
|
|
||||||
issues: write # to be able to comment on released issues
|
|
||||||
pull-requests: write # to be able to comment on released pull requests
|
|
||||||
id-token: write # to enable use of OIDC for npm provenance
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v3
|
||||||
@ -51,9 +37,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
node-version: "lts/*"
|
node-version: "lts/*"
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm clean-install
|
run: npm ci
|
||||||
- name: Verify the integrity of provenance attestations and registry signatures for installed dependencies
|
|
||||||
run: npm audit signatures
|
|
||||||
- name: Release
|
- name: Release
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
@ -6,11 +6,6 @@ The [Authentication](../../usage/ci-configuration.md#authentication) environment
|
|||||||
|
|
||||||
**Note**: Make sure to configure your release branch as [protected](https://docs.gitlab.com/ce/user/project/protected_branches.html) in order for the CI/CD build to access the protected variables.
|
**Note**: Make sure to configure your release branch as [protected](https://docs.gitlab.com/ce/user/project/protected_branches.html) in order for the CI/CD build to access the protected variables.
|
||||||
|
|
||||||
## npm provenance
|
|
||||||
|
|
||||||
Since GitLab CI is a [supported provider](https://docs.npmjs.com/generating-provenance-statements#provenance-limitations) for [npm provenance](https://docs.npmjs.com/generating-provenance-statements), it is recommended to enable this to increase supply-chain security for your npm packages.
|
|
||||||
Find more detail about configuring npm to publish with provenance through semantic-release [in the documentation for our npm plugin](https://github.com/semantic-release/npm#npm-provenance).
|
|
||||||
|
|
||||||
## Node project configuration
|
## Node project configuration
|
||||||
|
|
||||||
GitLab CI supports [Pipelines](https://docs.gitlab.com/ee/ci/pipelines.html) allowing to test on multiple Node versions and publishing a release only when all test pass.
|
GitLab CI supports [Pipelines](https://docs.gitlab.com/ee/ci/pipelines.html) allowing to test on multiple Node versions and publishing a release only when all test pass.
|
||||||
|
@ -62,7 +62,7 @@ The Git history of the repository is now:
|
|||||||
|
|
||||||
We now decide to work on another future major release, in parallel of the beta one, which will also be composed of multiple features, some of them being breaking changes.
|
We now decide to work on another future major release, in parallel of the beta one, which will also be composed of multiple features, some of them being breaking changes.
|
||||||
|
|
||||||
To implement that workflow we can create the branch `alpha` from the branch `beta` and commit our first feature there. When pushing that commit, **semantic-release** will publish the pre-release version `3.0.0-alpha.1` on the dist-tag `@alpha`. That allow us to run integration tests by installing our module with `npm install example-module@alpha`. Other users installing with `npm install example-module` will still receive the version `1.0.1`.
|
To implement that workflow we can create the branch `alpha` from the branch `beta` and commit our first feature there. When pushing that commit, **semantic-release** will publish the pre-release version `3.0.0-alpha.1` on the dist-tag `@alpha`. That allow us to run integration tests by installing our module with `npm install example-module@alpha`. Other users installing with `npm install example-module` will still receive the version `1.0.0`.
|
||||||
|
|
||||||
The Git history of the repository is now:
|
The Git history of the repository is now:
|
||||||
|
|
||||||
|
@ -158,6 +158,14 @@ Or with the `publishConfig.access` key in your project's `package.json`:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Can I use semantic-release to publish a package on Artifactory?
|
||||||
|
|
||||||
|
Any npm compatible registry is supported with the [`@semantic-release/npm`](https://github.com/semantic-release/npm) plugin. For Artifactory versions prior to 5.4, the legacy authentication has to be used (with `NPM_USERNAME`, `NPM_PASSWORD` and `NPM_EMAIL` [environment variables](https://github.com/semantic-release/npm#environment-variables)).
|
||||||
|
|
||||||
|
See [npm registry authentication](https://github.com/semantic-release/npm#npm-registry-authentication) for more details.
|
||||||
|
|
||||||
|
See [Artifactory - npm Registry](https://www.jfrog.com/confluence/display/RTF/Npm+Registry#NpmRegistry-AuthenticatingthenpmClient) documentation for Artifactory configuration.
|
||||||
|
|
||||||
## Can I manually trigger the release of a specific version?
|
## Can I manually trigger the release of a specific version?
|
||||||
|
|
||||||
You can trigger a release by pushing to your Git repository. You deliberately cannot trigger a _specific_ version release, because this is the whole point of semantic-release.
|
You can trigger a release by pushing to your Git repository. You deliberately cannot trigger a _specific_ version release, because this is the whole point of semantic-release.
|
||||||
@ -195,7 +203,7 @@ If you need more control over the timing of releases, see [Triggering a release]
|
|||||||
|
|
||||||
## Can I set the initial release version of my package to `0.0.1`?
|
## Can I set the initial release version of my package to `0.0.1`?
|
||||||
|
|
||||||
This is not supported by semantic-release. [Semantic Versioning](https://semver.org/) rules apply differently to major version zero and supporting those differences is out of scope and not one of the goals of the semantic-release project.
|
This is not supported by **semantic-release** as it's not considered a good practice, mostly because [Semantic Versioning](https://semver.org) rules applies differently to major version zero.
|
||||||
|
|
||||||
If your project is under heavy development, with frequent breaking changes, and is not production ready yet we recommend [publishing pre-releases](../recipes/release-workflow/pre-releases.md#publishing-pre-releases).
|
If your project is under heavy development, with frequent breaking changes, and is not production ready yet we recommend [publishing pre-releases](../recipes/release-workflow/pre-releases.md#publishing-pre-releases).
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
# Node version requirement
|
# Node version requirement
|
||||||
|
|
||||||
**semantic-release** is written using the latest [ECMAScript 2017](https://www.ecma-international.org/publications/standards/Ecma-262.htm) features, without transpilation which **requires Node version 20.8.1 or higher**.
|
**semantic-release** is written using the latest [ECMAScript 2017](https://www.ecma-international.org/publications/standards/Ecma-262.htm) features, without transpilation which **requires Node version 18.0.0 or higher**.
|
||||||
|
|
||||||
**semantic-release** is meant to be used in a CI environment as a development support tool, not as a production dependency.
|
**semantic-release** is meant to be used in a CI environment as a development support tool, not as a production dependency.
|
||||||
Therefore, the only constraint is to run the `semantic-release` in a CI environment providing version of Node that meets our version requirement.
|
Therefore, the only constraint is to run the `semantic-release` in a CI environment providing version of Node that meets our version requirement.
|
||||||
@ -14,7 +14,7 @@ See our [Node Support Policy](node-support-policy.md) for our long-term promise
|
|||||||
The recommended approach is to run the `semantic-release` command from a CI job running on the latest available LTS version of node.
|
The recommended approach is to run the `semantic-release` command from a CI job running on the latest available LTS version of node.
|
||||||
This can either be a job used by your project to test on the latest Node LTS version or a dedicated job for the release steps.
|
This can either be a job used by your project to test on the latest Node LTS version or a dedicated job for the release steps.
|
||||||
|
|
||||||
See [CI configuration](../usage/ci-configuration.md) and [CI configuration recipes](../recipes/ci-configurations/README.md#ci-configurations) for more details.
|
See [CI configuration](../usage/ci-configuration.md) and [CI configuration recipes](../recipes/release-workflow/README.md#ci-configurations) for more details.
|
||||||
|
|
||||||
## Alternative solutions
|
## Alternative solutions
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ Here are a few examples of the CI services that can be used to achieve this:
|
|||||||
- [Wercker Workflows](http://devcenter.wercker.com/docs/workflows)
|
- [Wercker Workflows](http://devcenter.wercker.com/docs/workflows)
|
||||||
- [GoCD Pipelines](https://docs.gocd.org/current/introduction/concepts_in_go.html#pipeline).
|
- [GoCD Pipelines](https://docs.gocd.org/current/introduction/concepts_in_go.html#pipeline).
|
||||||
|
|
||||||
See [CI configuration recipes](../recipes/ci-configurations/README.md) for more details.
|
See [CI configuration recipes](../recipes/ci-configurations#ci-configurations) for more details.
|
||||||
|
|
||||||
## Authentication
|
## Authentication
|
||||||
|
|
||||||
@ -45,6 +45,6 @@ See each plugin's documentation for the environment variables required.
|
|||||||
|
|
||||||
The authentication token/credentials have to be made available in the CI service via environment variables.
|
The authentication token/credentials have to be made available in the CI service via environment variables.
|
||||||
|
|
||||||
See [CI configuration recipes](../recipes/ci-configurations/README.md) for more details on how to configure environment variables in your CI service.
|
See [CI configuration recipes](../recipes/ci-configurations#ci-configurations) for more details on how to configure environment variables in your CI service.
|
||||||
|
|
||||||
**Note**: The environment variables `GH_TOKEN`, `GITHUB_TOKEN`, `GL_TOKEN` and `GITLAB_TOKEN` can be used for both the Git authentication and the API authentication required by [@semantic-release/github](https://github.com/semantic-release/github) and [@semantic-release/gitlab](https://github.com/semantic-release/gitlab).
|
**Note**: The environment variables `GH_TOKEN`, `GITHUB_TOKEN`, `GL_TOKEN` and `GITLAB_TOKEN` can be used for both the Git authentication and the API authentication required by [@semantic-release/github](https://github.com/semantic-release/github) and [@semantic-release/gitlab](https://github.com/semantic-release/gitlab).
|
||||||
|
@ -40,17 +40,6 @@ The following three examples are the same.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- Via `release.config.cjs` file:
|
|
||||||
|
|
||||||
```js
|
|
||||||
/**
|
|
||||||
* @type {import('semantic-release').GlobalConfig}
|
|
||||||
*/
|
|
||||||
module.exports = {
|
|
||||||
branches: ["master", "next"],
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
- Via CLI argument:
|
- Via CLI argument:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -6,3 +6,16 @@ In order to use **semantic-release** you must follow these steps:
|
|||||||
2. Configure your Continuous Integration service to [run **semantic-release**](./ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded)
|
2. Configure your Continuous Integration service to [run **semantic-release**](./ci-configuration.md#run-semantic-release-only-after-all-tests-succeeded)
|
||||||
3. Configure your Git repository and package manager repository [authentication](ci-configuration.md#authentication) in your Continuous Integration service
|
3. Configure your Git repository and package manager repository [authentication](ci-configuration.md#authentication) in your Continuous Integration service
|
||||||
4. Configure **semantic-release** [options and plugins](./configuration.md#configuration)
|
4. Configure **semantic-release** [options and plugins](./configuration.md#configuration)
|
||||||
|
|
||||||
|
Alternatively those steps can be easily done with the [**semantic-release** interactive CLI](https://github.com/semantic-release/cli):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd your-module
|
||||||
|
npx semantic-release-cli setup
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
See the [semantic-release-cli](https://github.com/semantic-release/cli#what-it-does) documentation for more details.
|
||||||
|
|
||||||
|
**Note**: only a limited number of options, CI services and plugins are currently supported by `semantic-release-cli`.
|
||||||
|
@ -24,28 +24,9 @@ For other type of projects we recommend installing **semantic-release** directly
|
|||||||
$ npx semantic-release
|
$ npx semantic-release
|
||||||
```
|
```
|
||||||
|
|
||||||
### Notes
|
**Note**: For a global installation, it's recommended to specify the major **semantic-release** version to install (for example with `npx semantic-release@18`).
|
||||||
|
This way your build will not automatically use the next major **semantic-release** release that could possibly break your build.
|
||||||
|
You will have to upgrade manually when a new major version is released.
|
||||||
|
|
||||||
1. If you've globally installed **semantic-release** then we recommend that you set the major **semantic-release** version to install.
|
**Note**: `npx` is a tool bundled with `npm@>=5.2.0`. It is used to conveniently install the semantic-release binary and to execute it.
|
||||||
For example, by using `npx semantic-release@18`.
|
See [What is npx](../support/FAQ.md#what-is-npx) for more details.
|
||||||
This way you control which major version of **semantic-release** is used by your build, and thus avoid breaking the build when there's a new major version of **semantic-release**.
|
|
||||||
This also means you, or a bot, must upgrade **semantic-release** when a new major version is released.
|
|
||||||
2. Pinning **semantic-release** to an exact version makes your releases even more deterministic.
|
|
||||||
But pinning also means you, or a bot, must update to newer versions of **semantic-release** more often.
|
|
||||||
3. You can use [Renovate's regex manager](https://docs.renovatebot.com/modules/manager/regex/) to get automatic updates for **semantic-release** in either of the above scenarios.
|
|
||||||
Put this in your Renovate configuration file:
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"regexManagers": [
|
|
||||||
{
|
|
||||||
"description": "Update semantic-release version used by npx",
|
|
||||||
"fileMatch": ["^\\.github/workflows/[^/]+\\.ya?ml$"],
|
|
||||||
"matchStrings": ["\\srun: npx semantic-release@(?<currentValue>.*?)\\s"],
|
|
||||||
"datasourceTemplate": "npm",
|
|
||||||
"depNameTemplate": "semantic-release"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
```
|
|
||||||
4. `npx` is a tool bundled with `npm@>=5.2.0`. You can use it to install (and run) the **semantic-release** binary.
|
|
||||||
See [What is npx](../support/FAQ.md#what-is-npx) for more details.
|
|
||||||
|
@ -12,7 +12,7 @@ See [Release workflow recipes](../recipes/release-workflow/README.md#release-wor
|
|||||||
The release workflow is configured via the [branches option](./configuration.md#branches) which accepts a single or an array of branch definitions.
|
The release workflow is configured via the [branches option](./configuration.md#branches) which accepts a single or an array of branch definitions.
|
||||||
Each branch can be defined either as a string, a [glob](https://github.com/micromatch/micromatch#matching-features) or an object. For string and glob definitions each [property](#branches-properties) will be defaulted.
|
Each branch can be defined either as a string, a [glob](https://github.com/micromatch/micromatch#matching-features) or an object. For string and glob definitions each [property](#branches-properties) will be defaulted.
|
||||||
|
|
||||||
A branch can be defined as one of three types:
|
A branch can defined as one of three types:
|
||||||
|
|
||||||
- [release](#release-branches): to make releases on top of the last version released
|
- [release](#release-branches): to make releases on top of the last version released
|
||||||
- [maintenance](#maintenance-branches): to make releases on top of an old release
|
- [maintenance](#maintenance-branches): to make releases on top of an old release
|
||||||
|
711
index.d.ts
vendored
711
index.d.ts
vendored
@ -1,711 +0,0 @@
|
|||||||
declare interface AggregateError extends Error {
|
|
||||||
errors: any[];
|
|
||||||
}
|
|
||||||
|
|
||||||
declare module "semantic-release" {
|
|
||||||
import { Signale } from "signale";
|
|
||||||
export interface EnvCi {
|
|
||||||
/**
|
|
||||||
* Boolean, true if the environment is a CI environment
|
|
||||||
*/
|
|
||||||
isCi: boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Commit hash
|
|
||||||
*/
|
|
||||||
commit: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Current branch name
|
|
||||||
*/
|
|
||||||
branch: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Base context used in every semantic release step.
|
|
||||||
*/
|
|
||||||
export interface BaseContext {
|
|
||||||
/**
|
|
||||||
* stdout for semantic-release process
|
|
||||||
*/
|
|
||||||
stdout: NodeJS.WriteStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* stderr for semantic-release process
|
|
||||||
*/
|
|
||||||
stderr: NodeJS.WriteStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signale console loger instance.
|
|
||||||
*
|
|
||||||
* Has error, log and success methods.
|
|
||||||
*/
|
|
||||||
logger: Signale<"error" | "log" | "success">;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context used for the verify conditions step.
|
|
||||||
*/
|
|
||||||
export interface VerifyConditionsContext extends BaseContext {
|
|
||||||
/**
|
|
||||||
* The current working directory to use. It should be configured to
|
|
||||||
* the root of the Git repository to release from.
|
|
||||||
*
|
|
||||||
* It allows to run semantic-release from a specific path without
|
|
||||||
* having to change the local process cwd with process.chdir().
|
|
||||||
*
|
|
||||||
* @default process.cwd
|
|
||||||
*/
|
|
||||||
cwd?: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The environment variables to use.
|
|
||||||
*
|
|
||||||
* It allows to run semantic-release with specific environment
|
|
||||||
* variables without having to modify the local process.env.
|
|
||||||
*
|
|
||||||
* @default process.env
|
|
||||||
*/
|
|
||||||
env: Record<string, string>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information about the CI environment.
|
|
||||||
*/
|
|
||||||
envCi: EnvCi;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information of the current branch
|
|
||||||
*/
|
|
||||||
branch: BranchObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information on branches
|
|
||||||
*/
|
|
||||||
branches: ReadonlyArray<BranchObject>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context used for the analyze commits step.
|
|
||||||
*/
|
|
||||||
export interface AnalyzeCommitsContext extends VerifyConditionsContext {
|
|
||||||
/**
|
|
||||||
* List of commits taken into account when determining the new version.
|
|
||||||
*/
|
|
||||||
commits: ReadonlyArray<Commit>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of releases
|
|
||||||
*/
|
|
||||||
releases: ReadonlyArray<Release>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Last release
|
|
||||||
*/
|
|
||||||
lastRelease: LastRelease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context used for the verify release step.
|
|
||||||
*/
|
|
||||||
export interface VerifyReleaseContext extends AnalyzeCommitsContext {
|
|
||||||
/**
|
|
||||||
* The next release.
|
|
||||||
*/
|
|
||||||
nextRelease: NextRelease;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context used for the generate notes step.
|
|
||||||
*/
|
|
||||||
export type GenerateNotesContext = VerifyReleaseContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context used for the add channel step.
|
|
||||||
*/
|
|
||||||
export type AddChannelContext = VerifyReleaseContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context used for the prepare step.
|
|
||||||
*/
|
|
||||||
export type PrepareContext = VerifyReleaseContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context used for the publish step.
|
|
||||||
*/
|
|
||||||
export type PublishContext = VerifyReleaseContext;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Context used for the success step.
|
|
||||||
*/
|
|
||||||
export type SuccessContext = VerifyReleaseContext;
|
|
||||||
|
|
||||||
export interface FailContext extends BaseContext {
|
|
||||||
/**
|
|
||||||
* Errors that occurred during the release process.
|
|
||||||
*/
|
|
||||||
errors: AggregateError;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Commit {
|
|
||||||
/**
|
|
||||||
* The commit abbreviated and full hash.
|
|
||||||
*/
|
|
||||||
commit: {
|
|
||||||
/**
|
|
||||||
* The commit hash.
|
|
||||||
*/
|
|
||||||
long: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The commit abbreviated hash.
|
|
||||||
*/
|
|
||||||
short: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The commit abbreviated and full tree hash.
|
|
||||||
*/
|
|
||||||
tree: {
|
|
||||||
/**
|
|
||||||
* The commit tree hash.
|
|
||||||
*/
|
|
||||||
long: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The commit abbreviated tree hash.
|
|
||||||
*/
|
|
||||||
short: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The commit author information.
|
|
||||||
*/
|
|
||||||
author: {
|
|
||||||
/**
|
|
||||||
* The commit author name.
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The commit author email.
|
|
||||||
*/
|
|
||||||
email: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The commit author date.
|
|
||||||
*/
|
|
||||||
short: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The committer information.
|
|
||||||
*/
|
|
||||||
committer: {
|
|
||||||
/**
|
|
||||||
* The committer name.
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The committer email.
|
|
||||||
*/
|
|
||||||
email: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The committer date.
|
|
||||||
*/
|
|
||||||
short: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The commit subject.
|
|
||||||
*/
|
|
||||||
subject: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The commit body.
|
|
||||||
*/
|
|
||||||
body: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The commit full message (subject and body).
|
|
||||||
*/
|
|
||||||
message: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The commit hash.
|
|
||||||
*/
|
|
||||||
hash: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The committer date.
|
|
||||||
*/
|
|
||||||
committerDate: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BranchObject {
|
|
||||||
/**
|
|
||||||
* The name of git branch.
|
|
||||||
*
|
|
||||||
* A `name` is required for all types of branch. It can be defined as a
|
|
||||||
* [glob](https://github.com/micromatch/micromatch#matching-features)
|
|
||||||
* in which case the definition will be expanded to one per matching
|
|
||||||
* branch existing in the repository.
|
|
||||||
*
|
|
||||||
* If `name` doesn't match any branch existing in the repository, the
|
|
||||||
* definition will be ignored. For example, the default configuration
|
|
||||||
* includes the definition `next` and `next-major` which will become
|
|
||||||
* active only when the branches `next` and/or `next-major` are
|
|
||||||
* created in the repository.
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The distribution channel on which to publish releases from this
|
|
||||||
* branch.
|
|
||||||
*
|
|
||||||
* If this field is set to `false`, then the branch will be released
|
|
||||||
* on the default distribution channel (for example the `@latest`
|
|
||||||
* [dist-tag](https://docs.npmjs.com/cli/dist-tag) for npm). This is
|
|
||||||
* also the default behavior for the first
|
|
||||||
* [release branch](https://semantic-release.gitbook.io/semantic-release/usage/workflow-configuration#release-branches)
|
|
||||||
* if the channel property is not set.
|
|
||||||
*
|
|
||||||
* For all other branches, if the channel property is not set, then the
|
|
||||||
* channel name will be the same as the branch name.
|
|
||||||
*
|
|
||||||
* The value of `channel`, if defined as a string, is generated with
|
|
||||||
* [Lodash template](https://lodash.com/docs#template) with the
|
|
||||||
* variable `name` set to the branch name.
|
|
||||||
*
|
|
||||||
* For example `{name: 'next', channel: 'channel-${name}'}` will be
|
|
||||||
* expanded to `{name: 'next', channel: 'channel-next'}`.
|
|
||||||
*/
|
|
||||||
channel?: string | false | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The range of [semantic versions](https://semver.org/) to support on
|
|
||||||
* this branch.
|
|
||||||
*
|
|
||||||
* A `range` only applies to maintenance branches and must be formatted
|
|
||||||
* like `N.N.x` or `N.x` (`N` is a number). If no range is specified
|
|
||||||
* but the `name` is formatted as a range, then the branch will be
|
|
||||||
* considered a maintenance branch and the `name` value will be used
|
|
||||||
* for the `range`.
|
|
||||||
*
|
|
||||||
* Required for maintenance branches, unless `name` is formatted like
|
|
||||||
* `N.N.x` or `N.x` (`N` is a number).
|
|
||||||
*/
|
|
||||||
range?: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The pre-release identifier to append to [semantic versions](https://semver.org/)
|
|
||||||
* released from this branch.
|
|
||||||
*
|
|
||||||
* 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 will be formatted like `2.0.0-beta.1`,
|
|
||||||
* `2.0.0-beta.2`, etc.
|
|
||||||
*
|
|
||||||
* The value of `prerelease`, if defined as a string, is generated with
|
|
||||||
* [Lodash template](https://lodash.com/docs#template) with the
|
|
||||||
* variable `name` set to the name of the branch.
|
|
||||||
*
|
|
||||||
* If the `prerelease property is set to `true` then the name of the
|
|
||||||
* branch is used as the pre-release identifier.
|
|
||||||
*
|
|
||||||
* Required for pre-release branches.
|
|
||||||
*/
|
|
||||||
prerelease?: string | boolean | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies a git branch holding commits to analyze and code to release.
|
|
||||||
*
|
|
||||||
* Each branch may be defined either by a string or an object. Specifying
|
|
||||||
* a string is a shortcut for specifying that string as the `name` field,
|
|
||||||
* for example `"master"` expands to `{name: "master"}`.
|
|
||||||
*/
|
|
||||||
export type BranchSpec = string | BranchObject;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A semver release type.
|
|
||||||
* See https://github.com/semantic-release/commit-analyzer/blob/master/lib/default-release-types.js
|
|
||||||
*/
|
|
||||||
export type ReleaseType = "prerelease" | "prepatch" | "patch" | "preminor" | "minor" | "premajor" | "major";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Details of a release published by a publish plugin.
|
|
||||||
*/
|
|
||||||
export interface Release {
|
|
||||||
/**
|
|
||||||
* The release name, only if set by the corresponding publish plugin.
|
|
||||||
*/
|
|
||||||
name?: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The release URL, only if set by the corresponding publish plugin.
|
|
||||||
*/
|
|
||||||
url?: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The semver export type of the release.
|
|
||||||
*/
|
|
||||||
type: ReleaseType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The version of the release.
|
|
||||||
*/
|
|
||||||
version: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The sha of the last commit being part of the release.
|
|
||||||
*/
|
|
||||||
gitHead: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Git tag associated with the release.
|
|
||||||
*/
|
|
||||||
gitTag: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The release notes for the release.
|
|
||||||
*/
|
|
||||||
notes: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The name of the plugin that published the release.
|
|
||||||
*/
|
|
||||||
pluginName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface LastRelease {
|
|
||||||
/**
|
|
||||||
* The version name of the release.
|
|
||||||
*/
|
|
||||||
version: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Git tag of the release.
|
|
||||||
*/
|
|
||||||
gitTag: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* List of channels the release was published to.
|
|
||||||
*/
|
|
||||||
channels: string[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Git checksum of the last commit of the release.
|
|
||||||
*/
|
|
||||||
gitHead: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The Release name
|
|
||||||
*/
|
|
||||||
name: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface NextRelease extends Omit<LastRelease, "channels"> {
|
|
||||||
/**
|
|
||||||
* The semver export type of the release.
|
|
||||||
*/
|
|
||||||
type: ReleaseType;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The release channel of the release.
|
|
||||||
*/
|
|
||||||
channel: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The release notes of the next release.
|
|
||||||
*/
|
|
||||||
notes?: string | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Specifies a plugin to use.
|
|
||||||
*
|
|
||||||
* The plugin is specified by its module name.
|
|
||||||
*
|
|
||||||
* To pass options to a plugin, specify an array containing the plugin module
|
|
||||||
* name and an options object.
|
|
||||||
*/
|
|
||||||
export type PluginSpec<T = any> = string | [string, T];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* semantic-release options, after normalization and defaults have been
|
|
||||||
* applied.
|
|
||||||
*/
|
|
||||||
export interface GlobalConfig extends Options {
|
|
||||||
/**
|
|
||||||
* The branches on which releases should happen. By default
|
|
||||||
* **semantic-release** will release:
|
|
||||||
*
|
|
||||||
* * regular releases to the default distribution channel from the
|
|
||||||
* branch `master`
|
|
||||||
* * regular releases to a distribution channel matching the branch
|
|
||||||
* name from any existing branch with a name matching a maintenance
|
|
||||||
* release range (`N.N.x` or `N.x.x` or `N.x` with `N` being a
|
|
||||||
* number)
|
|
||||||
* * regular releases to the `next` distribution channel from the
|
|
||||||
* branch `next` if it exists
|
|
||||||
* * regular releases to the `next-major` distribution channel from
|
|
||||||
* the branch `next-major` if it exists.
|
|
||||||
* * prereleases to the `beta` distribution channel from the branch
|
|
||||||
* `beta` if it exists
|
|
||||||
* * prereleases to the `alpha` distribution channel from the branch
|
|
||||||
* `alpha` if it exists
|
|
||||||
*
|
|
||||||
* **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).
|
|
||||||
*
|
|
||||||
* See [Workflow configuration](https://semantic-release.gitbook.io/semantic-release/usage/workflow-configuration#workflow-configuration)
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
branches: ReadonlyArray<BranchSpec> | BranchSpec;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The git repository URL.
|
|
||||||
*
|
|
||||||
* Any valid git url format is supported (see
|
|
||||||
* [git protocols](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols))
|
|
||||||
*
|
|
||||||
* Default: `repository` property in `package.json`, or git origin url.
|
|
||||||
*/
|
|
||||||
repositoryUrl: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The git tag format used by **semantic-release** to identify
|
|
||||||
* releases. The tag name is generated with [Lodash template](https://lodash.com/docs#template)
|
|
||||||
* and will be compiled with the `version` variable.
|
|
||||||
*
|
|
||||||
* **Note**: The `tagFormat` must contain the `version` variable
|
|
||||||
* exactly once and compile to a
|
|
||||||
* [valid git reference](https://git-scm.com/docs/git-check-ref-format#_description).
|
|
||||||
*/
|
|
||||||
tagFormat: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the list of plugins to use. Plugins will run in series, in
|
|
||||||
* the order defined, for each [step](https://semantic-release.gitbook.io/semantic-release/#release-steps)
|
|
||||||
* if they implement it.
|
|
||||||
*
|
|
||||||
* Plugins configuration can be defined by wrapping the name and an
|
|
||||||
* options object in an array.
|
|
||||||
*
|
|
||||||
* See [Plugins configuration](https://semantic-release.gitbook.io/semantic-release/usage/plugins#plugins)
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* Default: `[
|
|
||||||
* "@semantic-release/commit-analyzer",
|
|
||||||
* "@semantic-release/release-notes-generator",
|
|
||||||
* "@semantic-release/npm",
|
|
||||||
* "@semantic-release/github"
|
|
||||||
* ]`
|
|
||||||
*/
|
|
||||||
plugins: ReadonlyArray<PluginSpec>;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** semantic-release configuration specific for API usage. */
|
|
||||||
export interface Config {
|
|
||||||
/**
|
|
||||||
* The current working directory to use. It should be configured to
|
|
||||||
* the root of the Git repository to release from.
|
|
||||||
*
|
|
||||||
* It allows to run semantic-release from a specific path without
|
|
||||||
* having to change the local process cwd with process.chdir().
|
|
||||||
*
|
|
||||||
* @default process.cwd
|
|
||||||
*/
|
|
||||||
cwd?: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The environment variables to use.
|
|
||||||
*
|
|
||||||
* It allows to run semantic-release with specific environment
|
|
||||||
* variables without having to modify the local process.env.
|
|
||||||
*
|
|
||||||
* @default process.env
|
|
||||||
*/
|
|
||||||
env?: Record<string, any> | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The writable stream used to log information.
|
|
||||||
*
|
|
||||||
* It allows to configure semantic-release to write logs to a specific
|
|
||||||
* stream rather than the local process.stdout.
|
|
||||||
*
|
|
||||||
* @default process.stdout
|
|
||||||
*/
|
|
||||||
stdout?: NodeJS.WriteStream | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The writable stream used to log errors.
|
|
||||||
*
|
|
||||||
* It allows to configure semantic-release to write errors to a
|
|
||||||
* specific stream rather than the local process.stderr.
|
|
||||||
*
|
|
||||||
* @default process.stderr
|
|
||||||
*/
|
|
||||||
stderr?: NodeJS.WriteStream | undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* semantic-release options.
|
|
||||||
*
|
|
||||||
* Can be used to set any core option or plugin options.
|
|
||||||
* Each option will take precedence over options configured in the
|
|
||||||
* configuration file and shareable configurations.
|
|
||||||
*/
|
|
||||||
export interface Options {
|
|
||||||
/**
|
|
||||||
* List of modules or file paths containing a
|
|
||||||
* [shareable configuration](https://semantic-release.gitbook.io/semantic-release/usage/shareable-configurations).
|
|
||||||
* If multiple shareable configurations are set, they will be imported
|
|
||||||
* in the order defined with each configuration option taking
|
|
||||||
* precedence over the options defined in a previous shareable
|
|
||||||
* configuration.
|
|
||||||
*
|
|
||||||
* **Note**: Options defined via CLI arguments or in the configuration
|
|
||||||
* file will take precedence over the ones defined in any shareable
|
|
||||||
* configuration.
|
|
||||||
*/
|
|
||||||
extends?: ReadonlyArray<string> | string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The branches on which releases should happen. By default
|
|
||||||
* **semantic-release** will release:
|
|
||||||
*
|
|
||||||
* * regular releases to the default distribution channel from the
|
|
||||||
* branch `master`
|
|
||||||
* * regular releases to a distribution channel matching the branch
|
|
||||||
* name from any existing branch with a name matching a maintenance
|
|
||||||
* release range (`N.N.x` or `N.x.x` or `N.x` with `N` being a
|
|
||||||
* number)
|
|
||||||
* * regular releases to the `next` distribution channel from the
|
|
||||||
* branch `next` if it exists
|
|
||||||
* * regular releases to the `next-major` distribution channel from
|
|
||||||
* the branch `next-major` if it exists.
|
|
||||||
* * prereleases to the `beta` distribution channel from the branch
|
|
||||||
* `beta` if it exists
|
|
||||||
* * prereleases to the `alpha` distribution channel from the branch
|
|
||||||
* `alpha` if it exists
|
|
||||||
*
|
|
||||||
* **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).
|
|
||||||
*
|
|
||||||
* See [Workflow configuration](https://semantic-release.gitbook.io/semantic-release/usage/workflow-configuration#workflow-configuration)
|
|
||||||
* for more details.
|
|
||||||
*/
|
|
||||||
branches?: ReadonlyArray<BranchSpec> | BranchSpec | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The git repository URL.
|
|
||||||
*
|
|
||||||
* Any valid git url format is supported (see
|
|
||||||
* [git protocols](https://git-scm.com/book/en/v2/Git-on-the-Server-The-Protocols))
|
|
||||||
*
|
|
||||||
* Default: `repository` property in `package.json`, or git origin url.
|
|
||||||
*/
|
|
||||||
repositoryUrl?: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The git tag format used by **semantic-release** to identify
|
|
||||||
* releases. The tag name is generated with [Lodash template](https://lodash.com/docs#template)
|
|
||||||
* and will be compiled with the `version` variable.
|
|
||||||
*
|
|
||||||
* **Note**: The `tagFormat` must contain the `version` variable
|
|
||||||
* exactly once and compile to a
|
|
||||||
* [valid git reference](https://git-scm.com/docs/git-check-ref-format#_description).
|
|
||||||
*/
|
|
||||||
tagFormat?: string | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Define the list of plugins to use. Plugins will run in series, in
|
|
||||||
* the order defined, for each [step](https://semantic-release.gitbook.io/semantic-release/#release-steps)
|
|
||||||
* if they implement it.
|
|
||||||
*
|
|
||||||
* Plugins configuration can be defined by wrapping the name and an
|
|
||||||
* options object in an array.
|
|
||||||
*
|
|
||||||
* See [Plugins configuration](https://semantic-release.gitbook.io/semantic-release/usage/plugins#plugins)
|
|
||||||
* for more details.
|
|
||||||
*
|
|
||||||
* Default: `[
|
|
||||||
* "@semantic-release/commit-analyzer",
|
|
||||||
* "@semantic-release/release-notes-generator",
|
|
||||||
* "@semantic-release/npm",
|
|
||||||
* "@semantic-release/github"
|
|
||||||
* ]`
|
|
||||||
*/
|
|
||||||
plugins?: ReadonlyArray<PluginSpec> | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Dry-run mode, skip publishing, print next version and release notes.
|
|
||||||
*/
|
|
||||||
dryRun?: boolean | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set to false to skip Continuous Integration environment verifications.
|
|
||||||
* This allows for making releases from a local machine.
|
|
||||||
*/
|
|
||||||
ci?: boolean | undefined;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Any other options supported by plugins.
|
|
||||||
*/
|
|
||||||
[name: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An object with details of the release if a release was published, or
|
|
||||||
* false if no release was published.
|
|
||||||
*/
|
|
||||||
export type Result =
|
|
||||||
| false
|
|
||||||
| {
|
|
||||||
/**
|
|
||||||
* Information related to the last release found.
|
|
||||||
*/
|
|
||||||
lastRelease: LastRelease;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The list of commits included in the new release.
|
|
||||||
*/
|
|
||||||
commits: Commit[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information related to the newly published release.
|
|
||||||
*/
|
|
||||||
nextRelease: NextRelease;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The list of releases published, one release per publish plugin.
|
|
||||||
*/
|
|
||||||
releases: Release[];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Run semantic-release and returns a Promise that resolves to a Result
|
|
||||||
* object.
|
|
||||||
* @async
|
|
||||||
*/
|
|
||||||
export default function (options: Options, environment?: Config): Promise<Result>;
|
|
||||||
}
|
|
11
index.js
11
index.js
@ -123,15 +123,12 @@ async function run(context, plugins) {
|
|||||||
if (options.dryRun) {
|
if (options.dryRun) {
|
||||||
logger.warn(`Skip ${nextRelease.gitTag} tag creation in dry-run mode`);
|
logger.warn(`Skip ${nextRelease.gitTag} tag creation in dry-run mode`);
|
||||||
} else {
|
} else {
|
||||||
await addNote({ channels: [...currentRelease.channels, nextRelease.channel] }, nextRelease.gitTag, {
|
await addNote({ channels: [...currentRelease.channels, nextRelease.channel] }, nextRelease.gitHead, {
|
||||||
cwd,
|
cwd,
|
||||||
env,
|
env,
|
||||||
});
|
});
|
||||||
await push(options.repositoryUrl, { cwd, env });
|
await push(options.repositoryUrl, { cwd, env });
|
||||||
await pushNotes(options.repositoryUrl, nextRelease.gitTag, {
|
await pushNotes(options.repositoryUrl, { cwd, env });
|
||||||
cwd,
|
|
||||||
env,
|
|
||||||
});
|
|
||||||
logger.success(
|
logger.success(
|
||||||
`Add ${nextRelease.channel ? `channel ${nextRelease.channel}` : "default channel"} to tag ${
|
`Add ${nextRelease.channel ? `channel ${nextRelease.channel}` : "default channel"} to tag ${
|
||||||
nextRelease.gitTag
|
nextRelease.gitTag
|
||||||
@ -206,9 +203,9 @@ async function run(context, plugins) {
|
|||||||
} else {
|
} else {
|
||||||
// Create the tag before calling the publish plugins as some require the tag to exists
|
// Create the tag before calling the publish plugins as some require the tag to exists
|
||||||
await tag(nextRelease.gitTag, nextRelease.gitHead, { cwd, env });
|
await tag(nextRelease.gitTag, nextRelease.gitHead, { cwd, env });
|
||||||
await addNote({ channels: [nextRelease.channel] }, nextRelease.gitTag, { cwd, env });
|
await addNote({ channels: [nextRelease.channel] }, nextRelease.gitHead, { cwd, env });
|
||||||
await push(options.repositoryUrl, { cwd, env });
|
await push(options.repositoryUrl, { cwd, env });
|
||||||
await pushNotes(options.repositoryUrl, nextRelease.gitTag, { cwd, env });
|
await pushNotes(options.repositoryUrl, { cwd, env });
|
||||||
logger.success(`Created tag ${nextRelease.gitTag}`);
|
logger.success(`Created tag ${nextRelease.gitTag}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ export function release({ release }) {
|
|||||||
return release;
|
return release;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The initial lastVersion is the last release from the base branch of `FIRST_RELEASE` (1.0.0)
|
// The intial lastVersion is the last release from the base branch of `FIRST_RELEASE` (1.0.0)
|
||||||
let lastVersion = getLatestVersion(tagsToVersions(release[0].tags)) || FIRST_RELEASE;
|
let lastVersion = getLatestVersion(tagsToVersions(release[0].tags)) || FIRST_RELEASE;
|
||||||
|
|
||||||
return release.map(({ name, tags, channel, ...rest }, idx) => {
|
return release.map(({ name, tags, channel, ...rest }, idx) => {
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { dirname } from "node:path";
|
import { dirname, resolve } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
import { createRequire } from "node:module";
|
||||||
|
|
||||||
import { castArray, isNil, isPlainObject, isString, pickBy } from "lodash-es";
|
import { castArray, isNil, isPlainObject, isString, pickBy } from "lodash-es";
|
||||||
import { readPackageUp } from "read-pkg-up";
|
import { readPackageUp } from "read-pkg-up";
|
||||||
import { cosmiconfig } from "cosmiconfig";
|
import { cosmiconfig } from "cosmiconfig";
|
||||||
import importFrom from "import-from-esm";
|
import resolveFrom from "resolve-from";
|
||||||
import debugConfig from "debug";
|
import debugConfig from "debug";
|
||||||
import { repoUrl } from "./git.js";
|
import { repoUrl } from "./git.js";
|
||||||
import PLUGINS_DEFINITIONS from "./definitions/plugins.js";
|
import PLUGINS_DEFINITIONS from "./definitions/plugins.js";
|
||||||
@ -13,6 +14,7 @@ import { parseConfig, validatePlugin } from "./plugins/utils.js";
|
|||||||
|
|
||||||
const debug = debugConfig("semantic-release:config");
|
const debug = debugConfig("semantic-release:config");
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
const require = createRequire(import.meta.url);
|
||||||
|
|
||||||
const CONFIG_NAME = "release";
|
const CONFIG_NAME = "release";
|
||||||
|
|
||||||
@ -33,7 +35,7 @@ export default async (context, cliOptions) => {
|
|||||||
options = {
|
options = {
|
||||||
...(await castArray(extendPaths).reduce(async (eventualResult, extendPath) => {
|
...(await castArray(extendPaths).reduce(async (eventualResult, extendPath) => {
|
||||||
const result = await eventualResult;
|
const result = await eventualResult;
|
||||||
const extendsOptions = (await importFrom.silent(__dirname, extendPath)) || (await importFrom(cwd, extendPath));
|
const extendsOptions = require(resolveFrom.silent(__dirname, extendPath) || resolveFrom(cwd, extendPath));
|
||||||
|
|
||||||
// For each plugin defined in a shareable config, save in `pluginsPath` the extendable config path,
|
// For each plugin defined in a shareable config, save in `pluginsPath` the extendable config path,
|
||||||
// so those plugin will be loaded relative to the config file
|
// so those plugin will be loaded relative to the config file
|
||||||
@ -74,8 +76,8 @@ export default async (context, cliOptions) => {
|
|||||||
plugins: [
|
plugins: [
|
||||||
"@semantic-release/commit-analyzer",
|
"@semantic-release/commit-analyzer",
|
||||||
"@semantic-release/release-notes-generator",
|
"@semantic-release/release-notes-generator",
|
||||||
//"@semantic-release/npm",
|
"@semantic-release/npm",
|
||||||
//"@semantic-release/github",
|
"@semantic-release/github",
|
||||||
],
|
],
|
||||||
// Remove `null` and `undefined` options, so they can be replaced with default ones
|
// Remove `null` and `undefined` options, so they can be replaced with default ones
|
||||||
...pickBy(options, (option) => !isNil(option)),
|
...pickBy(options, (option) => !isNil(option)),
|
||||||
|
@ -36,7 +36,7 @@ function formatAuthUrl(protocol, repositoryUrl, gitCredentials) {
|
|||||||
* @param {Object} context semantic-release context.
|
* @param {Object} context semantic-release context.
|
||||||
* @param {String} authUrl Repository URL to verify
|
* @param {String} authUrl Repository URL to verify
|
||||||
*
|
*
|
||||||
* @return {String} The authUrl as is if the connection was successful, null otherwise
|
* @return {String} The authUrl as is if the connection was successfull, null otherwise
|
||||||
*/
|
*/
|
||||||
async function ensureValidAuthUrl({ cwd, env, branch }, authUrl) {
|
async function ensureValidAuthUrl({ cwd, env, branch }, authUrl) {
|
||||||
try {
|
try {
|
||||||
|
@ -30,11 +30,7 @@ export default ({ branch, options: { tagFormat } }, { before } = {}) => {
|
|||||||
const [{ version, gitTag, channels } = {}] = branch.tags
|
const [{ version, gitTag, channels } = {}] = branch.tags
|
||||||
.filter(
|
.filter(
|
||||||
(tag) =>
|
(tag) =>
|
||||||
((branch.type === "prerelease" &&
|
((branch.type === "prerelease" && tag.channels.some((channel) => isSameChannel(branch.channel, channel))) ||
|
||||||
tag.channels.some((channel) => isSameChannel(branch.channel, channel)) &&
|
|
||||||
semver
|
|
||||||
.parse(tag.version)
|
|
||||||
.prerelease.includes(branch.prerelease === true ? branch.name : branch.prerelease)) ||
|
|
||||||
!semver.prerelease(tag.version)) &&
|
!semver.prerelease(tag.version)) &&
|
||||||
(isUndefined(before) || semver.lt(tag.version, before))
|
(isUndefined(before) || semver.lt(tag.version, before))
|
||||||
)
|
)
|
||||||
|
49
lib/git.js
49
lib/git.js
@ -2,7 +2,6 @@ import gitLogParser from "git-log-parser";
|
|||||||
import getStream from "get-stream";
|
import getStream from "get-stream";
|
||||||
import { execa } from "execa";
|
import { execa } from "execa";
|
||||||
import debugGit from "debug";
|
import debugGit from "debug";
|
||||||
import { merge } from "lodash-es";
|
|
||||||
import { GIT_NOTE_REF } from "./definitions/constants.js";
|
import { GIT_NOTE_REF } from "./definitions/constants.js";
|
||||||
|
|
||||||
const debug = debugGit("semantic-release:git");
|
const debug = debugGit("semantic-release:git");
|
||||||
@ -142,9 +141,13 @@ export async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
|
|||||||
*/
|
*/
|
||||||
export async function fetchNotes(repositoryUrl, execaOptions) {
|
export async function fetchNotes(repositoryUrl, execaOptions) {
|
||||||
try {
|
try {
|
||||||
await execa("git", ["fetch", "--unshallow", repositoryUrl, `+refs/notes/*:refs/notes/*`], execaOptions);
|
await execa(
|
||||||
|
"git",
|
||||||
|
["fetch", "--unshallow", repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`],
|
||||||
|
execaOptions
|
||||||
|
);
|
||||||
} catch {
|
} catch {
|
||||||
await execa("git", ["fetch", repositoryUrl, `+refs/notes/*:refs/notes/*`], {
|
await execa("git", ["fetch", repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`], {
|
||||||
...execaOptions,
|
...execaOptions,
|
||||||
reject: false,
|
reject: false,
|
||||||
});
|
});
|
||||||
@ -243,8 +246,8 @@ export async function push(repositoryUrl, execaOptions) {
|
|||||||
*
|
*
|
||||||
* @throws {Error} if the push failed.
|
* @throws {Error} if the push failed.
|
||||||
*/
|
*/
|
||||||
export async function pushNotes(repositoryUrl, ref, execaOptions) {
|
export async function pushNotes(repositoryUrl, execaOptions) {
|
||||||
await execa("git", ["push", repositoryUrl, `refs/notes/${GIT_NOTE_REF}-${ref}`], execaOptions);
|
await execa("git", ["push", repositoryUrl, `refs/notes/${GIT_NOTE_REF}`], execaOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -304,26 +307,8 @@ export async function isBranchUpToDate(repositoryUrl, branch, execaOptions) {
|
|||||||
* @return {Object} the parsed JSON note if there is one, an empty object otherwise.
|
* @return {Object} the parsed JSON note if there is one, an empty object otherwise.
|
||||||
*/
|
*/
|
||||||
export async function getNote(ref, execaOptions) {
|
export async function getNote(ref, execaOptions) {
|
||||||
const handleError = (error) => {
|
|
||||||
if (error.exitCode === 1) {
|
|
||||||
return { stdout: "{}" };
|
|
||||||
}
|
|
||||||
|
|
||||||
debug(error);
|
|
||||||
throw error;
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return merge(
|
return JSON.parse((await execa("git", ["notes", "--ref", GIT_NOTE_REF, "show", ref], execaOptions)).stdout);
|
||||||
JSON.parse(
|
|
||||||
// Used for retro-compatibility
|
|
||||||
(await execa("git", ["notes", "--ref", GIT_NOTE_REF, "show", ref], execaOptions).catch(handleError)).stdout
|
|
||||||
),
|
|
||||||
JSON.parse(
|
|
||||||
(await execa("git", ["notes", "--ref", `${GIT_NOTE_REF}-${ref}`, "show", ref], execaOptions).catch(handleError))
|
|
||||||
.stdout
|
|
||||||
)
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.exitCode === 1) {
|
if (error.exitCode === 1) {
|
||||||
return {};
|
return {};
|
||||||
@ -342,19 +327,5 @@ export async function getNote(ref, execaOptions) {
|
|||||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||||
*/
|
*/
|
||||||
export async function addNote(note, ref, execaOptions) {
|
export async function addNote(note, ref, execaOptions) {
|
||||||
await execa(
|
await execa("git", ["notes", "--ref", GIT_NOTE_REF, "add", "-f", "-m", JSON.stringify(note), ref], execaOptions);
|
||||||
"git",
|
|
||||||
["notes", "--ref", `${GIT_NOTE_REF}-${ref}`, "add", "-f", "-m", JSON.stringify(note), ref],
|
|
||||||
execaOptions
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the reference of a tag
|
|
||||||
*
|
|
||||||
* @param {String} tag The tag name to get the reference of.
|
|
||||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
|
||||||
**/
|
|
||||||
export async function getTagRef(tag, execaOptions) {
|
|
||||||
return (await execa("git", ["show-ref", tag, "--hash"], execaOptions)).stdout;
|
|
||||||
}
|
}
|
||||||
|
@ -52,12 +52,14 @@ export async function loadPlugin({ cwd }, name, pluginsPath) {
|
|||||||
? dirname(resolveFrom.silent(__dirname, pluginsPath[name]) || resolveFrom(cwd, pluginsPath[name]))
|
? dirname(resolveFrom.silent(__dirname, pluginsPath[name]) || resolveFrom(cwd, pluginsPath[name]))
|
||||||
: __dirname;
|
: __dirname;
|
||||||
|
|
||||||
|
// See https://github.com/mysticatea/eslint-plugin-node/issues/250
|
||||||
if (isFunction(name)) {
|
if (isFunction(name)) {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
const file = resolveFrom.silent(basePath, name) || resolveFrom(cwd, name);
|
const { default: cjsExport, ...esmNamedExports } = await import(
|
||||||
const { default: cjsExport, ...esmNamedExports } = await import(`file://${file}`);
|
resolveFrom.silent(basePath, name) || resolveFrom(cwd, name)
|
||||||
|
);
|
||||||
|
|
||||||
if (cjsExport) {
|
if (cjsExport) {
|
||||||
return cjsExport;
|
return cjsExport;
|
||||||
|
BIN
media/semantic-release-cli.png
Normal file
BIN
media/semantic-release-cli.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 65 KiB |
20963
package-lock.json
generated
20963
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
99
package.json
99
package.json
@ -6,8 +6,7 @@
|
|||||||
"author": "Stephan Bönnemann <stephan@boennemann.me> (http://boennemann.me)",
|
"author": "Stephan Bönnemann <stephan@boennemann.me> (http://boennemann.me)",
|
||||||
"ava": {
|
"ava": {
|
||||||
"files": [
|
"files": [
|
||||||
"test/**/*.test.js",
|
"test/**/*.test.js"
|
||||||
"!test/integration.test.js"
|
|
||||||
],
|
],
|
||||||
"nodeArguments": [
|
"nodeArguments": [
|
||||||
"--loader=testdouble",
|
"--loader=testdouble",
|
||||||
@ -27,30 +26,29 @@
|
|||||||
"Matt Travi <npm@travi.org> (https://matt.travi.org/)"
|
"Matt Travi <npm@travi.org> (https://matt.travi.org/)"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@semantic-release/commit-analyzer": "^11.0.0",
|
"@semantic-release/commit-analyzer": "^9.0.2",
|
||||||
"@semantic-release/error": "^4.0.0",
|
"@semantic-release/error": "^3.0.0",
|
||||||
"@semantic-release/github": "^9.0.0",
|
"@semantic-release/github": "^8.0.0",
|
||||||
"@semantic-release/npm": "^11.0.0",
|
"@semantic-release/npm": "^10.0.0-beta.1",
|
||||||
"@semantic-release/release-notes-generator": "^12.0.0",
|
"@semantic-release/release-notes-generator": "^10.0.0",
|
||||||
"aggregate-error": "^5.0.0",
|
"aggregate-error": "^4.0.1",
|
||||||
"cosmiconfig": "^9.0.0",
|
"cosmiconfig": "^8.0.0",
|
||||||
"debug": "^4.0.0",
|
"debug": "^4.0.0",
|
||||||
"env-ci": "^11.0.0",
|
"env-ci": "^8.0.0",
|
||||||
"execa": "^8.0.0",
|
"execa": "^6.1.0",
|
||||||
"figures": "^6.0.0",
|
"figures": "^5.0.0",
|
||||||
"find-versions": "^5.1.0",
|
"find-versions": "^5.1.0",
|
||||||
"get-stream": "^6.0.0",
|
"get-stream": "^6.0.0",
|
||||||
"git-log-parser": "^1.2.0",
|
"git-log-parser": "^1.2.0",
|
||||||
"hook-std": "^3.0.0",
|
"hook-std": "^3.0.0",
|
||||||
"hosted-git-info": "^7.0.0",
|
"hosted-git-info": "^6.0.0",
|
||||||
"import-from-esm": "^1.3.1",
|
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"marked": "^11.0.0",
|
"marked": "^4.1.0",
|
||||||
"marked-terminal": "^7.0.0",
|
"marked-terminal": "^5.1.1",
|
||||||
"micromatch": "^4.0.2",
|
"micromatch": "^4.0.2",
|
||||||
"p-each-series": "^3.0.0",
|
"p-each-series": "^3.0.0",
|
||||||
"p-reduce": "^3.0.0",
|
"p-reduce": "^3.0.0",
|
||||||
"read-pkg-up": "^11.0.0",
|
"read-pkg-up": "^9.1.0",
|
||||||
"resolve-from": "^5.0.0",
|
"resolve-from": "^5.0.0",
|
||||||
"semver": "^7.3.2",
|
"semver": "^7.3.2",
|
||||||
"semver-diff": "^4.0.0",
|
"semver-diff": "^4.0.0",
|
||||||
@ -58,37 +56,32 @@
|
|||||||
"yargs": "^17.5.1"
|
"yargs": "^17.5.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ava": "6.1.1",
|
"ava": "5.1.0",
|
||||||
"c8": "9.1.0",
|
"c8": "7.12.0",
|
||||||
"clear-module": "4.1.2",
|
"clear-module": "4.1.2",
|
||||||
"codecov": "3.8.3",
|
"codecov": "3.8.3",
|
||||||
"cz-conventional-changelog": "3.3.0",
|
"delay": "5.0.0",
|
||||||
"dockerode": "4.0.2",
|
"dockerode": "3.3.4",
|
||||||
"file-url": "4.0.0",
|
"file-url": "^4.0.0",
|
||||||
"fs-extra": "11.2.0",
|
"fs-extra": "^11.0.0",
|
||||||
"got": "14.2.0",
|
"got": "^12.5.0",
|
||||||
"js-yaml": "4.1.0",
|
"js-yaml": "4.1.0",
|
||||||
"lockfile-lint": "4.12.1",
|
|
||||||
"ls-engines": "0.9.1",
|
|
||||||
"mockserver-client": "5.15.0",
|
"mockserver-client": "5.15.0",
|
||||||
"nock": "13.5.1",
|
"nock": "13.3.0",
|
||||||
"npm-run-all2": "6.1.2",
|
"p-retry": "^5.1.1",
|
||||||
"p-retry": "6.2.0",
|
"prettier": "^2.7.1",
|
||||||
"prettier": "3.2.5",
|
"sinon": "15.0.1",
|
||||||
"publint": "0.2.7",
|
|
||||||
"sinon": "17.0.1",
|
|
||||||
"stream-buffers": "3.0.2",
|
"stream-buffers": "3.0.2",
|
||||||
"tempy": "3.1.0",
|
"tempy": "^3.0.0",
|
||||||
"testdouble": "3.20.1"
|
"testdouble": "3.16.8"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=20.8.1"
|
"node": ">=18"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"bin",
|
"bin",
|
||||||
"docs",
|
"docs",
|
||||||
"lib",
|
"lib",
|
||||||
"index.d.ts",
|
|
||||||
"index.js",
|
"index.js",
|
||||||
"cli.js"
|
"cli.js"
|
||||||
],
|
],
|
||||||
@ -105,8 +98,7 @@
|
|||||||
"version"
|
"version"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "./index.js",
|
"main": "index.js",
|
||||||
"types": "index.d.ts",
|
|
||||||
"c8": {
|
"c8": {
|
||||||
"include": [
|
"include": [
|
||||||
"lib/**/*.js",
|
"lib/**/*.js",
|
||||||
@ -120,46 +112,29 @@
|
|||||||
],
|
],
|
||||||
"all": true
|
"all": true
|
||||||
},
|
},
|
||||||
"lockfile-lint": {
|
|
||||||
"path": "package-lock.json",
|
|
||||||
"type": "npm",
|
|
||||||
"validate-https": true,
|
|
||||||
"allowed-hosts": [
|
|
||||||
"npm"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"prettier": {
|
"prettier": {
|
||||||
"printWidth": 120,
|
"printWidth": 120,
|
||||||
"trailingComma": "es5"
|
"trailingComma": "es5"
|
||||||
},
|
},
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public",
|
"access": "public"
|
||||||
"provenance": true
|
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/semantic-release/semantic-release.git"
|
"url": "git+https://github.com/semantic-release/semantic-release.git"
|
||||||
},
|
},
|
||||||
"config": {
|
|
||||||
"commitizen": {
|
|
||||||
"path": "./node_modules/cz-conventional-changelog"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"codecov": "codecov -f coverage/coverage-final.json",
|
"codecov": "codecov -f coverage/coverage-final.json",
|
||||||
"lint:prettier": "prettier --check \"*.{js,json,md}\" \".github/**/*.{md,yml}\" \"docs/**/*.md\" \"{bin,lib,test}/**/*.js\"",
|
"lint": "prettier --check \"*.{js,json,md}\" \".github/**/*.{md,yml}\" \"docs/**/*.md\" \"{bin,lib,test}/**/*.js\"",
|
||||||
"lint:prettier:fix": "prettier --write \"*.{js,json,md}\" \".github/**/*.{md,yml}\" \"docs/**/*.md\" \"{bin,lib,test}/**/*.js\"",
|
"lint:fix": "prettier --write \"*.{js,json,md}\" \".github/**/*.{md,yml}\" \"docs/**/*.md\" \"{bin,lib,test}/**/*.js\"",
|
||||||
"lint:lockfile": "lockfile-lint",
|
"pretest": "npm run lint",
|
||||||
"lint:engines": "ls-engines",
|
|
||||||
"lint:publish": "publint --strict",
|
|
||||||
"semantic-release": "./bin/semantic-release.js",
|
"semantic-release": "./bin/semantic-release.js",
|
||||||
"test": "npm-run-all --print-label --parallel lint:* --parallel test:*",
|
"test": "c8 ava --verbose",
|
||||||
"test:unit": "c8 ava --verbose",
|
"test:ci": "c8 ava --verbose"
|
||||||
"test:integration": "ava --verbose test/integration.test.js"
|
|
||||||
},
|
},
|
||||||
"renovate": {
|
"renovate": {
|
||||||
"extends": [
|
"extends": [
|
||||||
"github>semantic-release/.github:renovate-config"
|
"github>semantic-release/.github"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -389,92 +389,6 @@ test.serial('Read configuration from an array of paths in "extends"', async (t)
|
|||||||
t.deepEqual(result, { options: expectedOptions, plugins: pluginsConfig });
|
t.deepEqual(result, { options: expectedOptions, plugins: pluginsConfig });
|
||||||
});
|
});
|
||||||
|
|
||||||
test.serial('Read configuration from an array of CJS files in "extends"', async (t) => {
|
|
||||||
// Create a git repository, set the current working directory at the root of the repo
|
|
||||||
const { cwd } = await gitRepo();
|
|
||||||
const pkgOptions = { extends: ["./shareable1.cjs", "./shareable2.cjs"] };
|
|
||||||
const options1 = {
|
|
||||||
verifyRelease: "verifyRelease1",
|
|
||||||
analyzeCommits: { path: "analyzeCommits1", param: "analyzeCommits_param1" },
|
|
||||||
branches: ["test_branch"],
|
|
||||||
repositoryUrl: "https://host.null/owner/module.git",
|
|
||||||
};
|
|
||||||
const options2 = {
|
|
||||||
verifyRelease: "verifyRelease2",
|
|
||||||
generateNotes: "generateNotes2",
|
|
||||||
analyzeCommits: { path: "analyzeCommits2", param: "analyzeCommits_param2" },
|
|
||||||
branches: ["test_branch"],
|
|
||||||
tagFormat: `v\${version}`,
|
|
||||||
plugins: false,
|
|
||||||
};
|
|
||||||
// Create package.json and shareable.json in repository root
|
|
||||||
await outputJson(path.resolve(cwd, "package.json"), { release: pkgOptions });
|
|
||||||
await writeFile(path.resolve(cwd, "shareable1.cjs"), `module.exports = ${JSON.stringify(options1)}`);
|
|
||||||
await writeFile(path.resolve(cwd, "shareable2.cjs"), `module.exports = ${JSON.stringify(options2)}`);
|
|
||||||
const expectedOptions = { ...options1, ...options2, branches: ["test_branch"] };
|
|
||||||
// Verify the plugins module is called with the plugin options from shareable1.mjs and shareable2.mjs
|
|
||||||
td.when(
|
|
||||||
plugins(
|
|
||||||
{ options: expectedOptions, cwd },
|
|
||||||
{
|
|
||||||
verifyRelease1: "./shareable1.cjs",
|
|
||||||
verifyRelease2: "./shareable2.cjs",
|
|
||||||
generateNotes2: "./shareable2.cjs",
|
|
||||||
analyzeCommits1: "./shareable1.cjs",
|
|
||||||
analyzeCommits2: "./shareable2.cjs",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
).thenResolve(pluginsConfig);
|
|
||||||
|
|
||||||
const result = await t.context.getConfig({ cwd });
|
|
||||||
|
|
||||||
// Verify the options contains the plugin config from shareable1.json and shareable2.json
|
|
||||||
t.deepEqual(result, { options: expectedOptions, plugins: pluginsConfig });
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('Read configuration from an array of ESM files in "extends"', async (t) => {
|
|
||||||
// Create a git repository, set the current working directory at the root of the repo
|
|
||||||
const { cwd } = await gitRepo();
|
|
||||||
const pkgOptions = { extends: ["./shareable1.mjs", "./shareable2.mjs"] };
|
|
||||||
const options1 = {
|
|
||||||
verifyRelease: "verifyRelease1",
|
|
||||||
analyzeCommits: { path: "analyzeCommits1", param: "analyzeCommits_param1" },
|
|
||||||
branches: ["test_branch"],
|
|
||||||
repositoryUrl: "https://host.null/owner/module.git",
|
|
||||||
};
|
|
||||||
const options2 = {
|
|
||||||
verifyRelease: "verifyRelease2",
|
|
||||||
generateNotes: "generateNotes2",
|
|
||||||
analyzeCommits: { path: "analyzeCommits2", param: "analyzeCommits_param2" },
|
|
||||||
branches: ["test_branch"],
|
|
||||||
tagFormat: `v\${version}`,
|
|
||||||
plugins: false,
|
|
||||||
};
|
|
||||||
// Create package.json and shareable.json in repository root
|
|
||||||
await outputJson(path.resolve(cwd, "package.json"), { release: pkgOptions });
|
|
||||||
await writeFile(path.resolve(cwd, "shareable1.mjs"), `export default ${JSON.stringify(options1)}`);
|
|
||||||
await writeFile(path.resolve(cwd, "shareable2.mjs"), `export default ${JSON.stringify(options2)}`);
|
|
||||||
const expectedOptions = { ...options1, ...options2, branches: ["test_branch"] };
|
|
||||||
// Verify the plugins module is called with the plugin options from shareable1.mjs and shareable2.mjs
|
|
||||||
td.when(
|
|
||||||
plugins(
|
|
||||||
{ options: expectedOptions, cwd },
|
|
||||||
{
|
|
||||||
verifyRelease1: "./shareable1.mjs",
|
|
||||||
verifyRelease2: "./shareable2.mjs",
|
|
||||||
generateNotes2: "./shareable2.mjs",
|
|
||||||
analyzeCommits1: "./shareable1.mjs",
|
|
||||||
analyzeCommits2: "./shareable2.mjs",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
).thenResolve(pluginsConfig);
|
|
||||||
|
|
||||||
const result = await t.context.getConfig({ cwd });
|
|
||||||
|
|
||||||
// Verify the options contains the plugin config from shareable1.json and shareable2.json
|
|
||||||
t.deepEqual(result, { options: expectedOptions, plugins: pluginsConfig });
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial('Prioritize configuration from config file over "extends"', async (t) => {
|
test.serial('Prioritize configuration from config file over "extends"', 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
|
||||||
const { cwd } = await gitRepo();
|
const { cwd } = await gitRepo();
|
||||||
|
@ -43,43 +43,6 @@ test("Get the highest prerelease valid tag, ignoring other tags from other prere
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Get the correct prerelease tag, when other prereleases share the same git HEAD", (t) => {
|
|
||||||
const testConfig = {
|
|
||||||
branch: {
|
|
||||||
name: "alpha",
|
|
||||||
prerelease: "alpha",
|
|
||||||
channel: "alpha",
|
|
||||||
tags: [
|
|
||||||
{ version: "1.0.0-beta.1", gitTag: "v1.0.0-beta.1", gitHead: "v1.0.0-beta.1", channels: ["beta"] },
|
|
||||||
{ version: "1.0.0-beta.2", gitTag: "v1.0.0-beta.2", gitHead: "v1.0.0-alpha.1", channels: ["alpha", "beta"] },
|
|
||||||
{ version: "1.0.0-alpha.1", gitTag: "v1.0.0-alpha.1", gitHead: "v1.0.0-alpha.1", channels: ["alpha", "beta"] },
|
|
||||||
],
|
|
||||||
type: "prerelease",
|
|
||||||
},
|
|
||||||
options: { tagFormat: `v\${version}`, debug: true },
|
|
||||||
};
|
|
||||||
const firstResult = getLastRelease(testConfig);
|
|
||||||
|
|
||||||
t.deepEqual(firstResult, {
|
|
||||||
version: "1.0.0-alpha.1",
|
|
||||||
gitTag: "v1.0.0-alpha.1",
|
|
||||||
name: "v1.0.0-alpha.1",
|
|
||||||
gitHead: "v1.0.0-alpha.1",
|
|
||||||
channels: ["alpha", "beta"],
|
|
||||||
});
|
|
||||||
|
|
||||||
testConfig.branch.prerelease = true;
|
|
||||||
const secondResult = getLastRelease(testConfig);
|
|
||||||
|
|
||||||
t.deepEqual(secondResult, {
|
|
||||||
version: "1.0.0-alpha.1",
|
|
||||||
gitTag: "v1.0.0-alpha.1",
|
|
||||||
name: "v1.0.0-alpha.1",
|
|
||||||
gitHead: "v1.0.0-alpha.1",
|
|
||||||
channels: ["alpha", "beta"],
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test("Return empty object if no valid tag is found", (t) => {
|
test("Return empty object if no valid tag is found", (t) => {
|
||||||
const result = getLastRelease({
|
const result = getLastRelease({
|
||||||
branch: {
|
branch: {
|
||||||
|
@ -275,24 +275,3 @@ test("Increase version for release on prerelease branch when there is no regular
|
|||||||
"1.0.0-beta.2"
|
"1.0.0-beta.2"
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Increase patch when previous version shares HEAD with other releases", (t) => {
|
|
||||||
t.is(
|
|
||||||
getNextVersion({
|
|
||||||
branch: {
|
|
||||||
name: "alpha",
|
|
||||||
type: "prerelease",
|
|
||||||
prerelease: "alpha",
|
|
||||||
tags: [
|
|
||||||
{ gitTag: "v1.0.0-beta.1", version: "1.0.0-beta.1", channels: ["beta"] },
|
|
||||||
{ gitTag: "v1.0.0-beta.2", version: "1.0.0-beta.2", channels: ["alpha", "beta"] },
|
|
||||||
{ gitTag: "v1.0.0-alpha.1", version: "1.0.0-alpha.1", channels: ["alpha", "beta"] },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
nextRelease: { type: "patch", channel: "alpha" },
|
|
||||||
lastRelease: { version: "v1.0.0-alpha.1", channels: ["alpha", "beta"] },
|
|
||||||
logger: t.context.logger,
|
|
||||||
}),
|
|
||||||
"1.0.0-alpha.2"
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
@ -43,7 +43,7 @@ export async function initGit(withRemote) {
|
|||||||
*
|
*
|
||||||
* @param {Boolean} withRemote `true` to create a shallow clone of a bare repository.
|
* @param {Boolean} withRemote `true` to create a shallow clone of a bare repository.
|
||||||
* @param {String} [branch='master'] The branch to initialize.
|
* @param {String} [branch='master'] The branch to initialize.
|
||||||
* @return {Promise<Object>} The path of the clone if `withRemote` is `true`, the path of the repository otherwise.
|
* @return {String} The path of the clone if `withRemote` is `true`, the path of the repository otherwise.
|
||||||
*/
|
*/
|
||||||
export async function gitRepo(withRemote, branch = "master") {
|
export async function gitRepo(withRemote, branch = "master") {
|
||||||
let { cwd, repositoryUrl } = await initGit(withRemote);
|
let { cwd, repositoryUrl } = await initGit(withRemote);
|
||||||
@ -90,7 +90,9 @@ export async function gitCommits(messages, execaOptions) {
|
|||||||
await pEachSeries(
|
await pEachSeries(
|
||||||
messages,
|
messages,
|
||||||
async (message) =>
|
async (message) =>
|
||||||
(await execa("git", ["commit", "-m", message, "--allow-empty", "--no-gpg-sign"], execaOptions)).stdout
|
(
|
||||||
|
await execa("git", ["commit", "-m", message, "--allow-empty", "--no-gpg-sign"], execaOptions)
|
||||||
|
).stdout
|
||||||
);
|
);
|
||||||
return (await gitGetCommits(undefined, execaOptions)).slice(0, messages.length);
|
return (await gitGetCommits(undefined, execaOptions)).slice(0, messages.length);
|
||||||
}
|
}
|
||||||
@ -98,7 +100,7 @@ export async function gitCommits(messages, execaOptions) {
|
|||||||
/**
|
/**
|
||||||
* Get the list of parsed commits since a git reference.
|
* Get the list of parsed commits since a git reference.
|
||||||
*
|
*
|
||||||
* @param {String} [from] Git reference from which to search commits.
|
* @param {String} [from] Git reference from which to seach commits.
|
||||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||||
*
|
*
|
||||||
* @return {Array<Object>} The list of parsed commits.
|
* @return {Array<Object>} The list of parsed commits.
|
||||||
@ -240,7 +242,7 @@ export async function gitTagHead(tagName, execaOptions) {
|
|||||||
* Get the first commit sha referenced by the tag `tagName` in the remote repository.
|
* Get the first commit sha referenced by the tag `tagName` in the remote repository.
|
||||||
*
|
*
|
||||||
* @param {String} repositoryUrl The repository remote URL.
|
* @param {String} repositoryUrl The repository remote URL.
|
||||||
* @param {String} tagName The tag name to search for.
|
* @param {String} tagName The tag name to seach for.
|
||||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||||
*
|
*
|
||||||
* @return {String} The sha of the commit associated with `tagName` on the remote repository.
|
* @return {String} The sha of the commit associated with `tagName` on the remote repository.
|
||||||
@ -315,7 +317,7 @@ export async function rebase(ref, execaOptions) {
|
|||||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||||
*/
|
*/
|
||||||
export async function gitAddNote(note, ref, execaOptions) {
|
export async function gitAddNote(note, ref, execaOptions) {
|
||||||
await execa("git", ["notes", "--ref", `${GIT_NOTE_REF}-${ref}`, "add", "-m", note, ref], execaOptions);
|
await execa("git", ["notes", "--ref", GIT_NOTE_REF, "add", "-m", note, ref], execaOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -325,5 +327,5 @@ export async function gitAddNote(note, ref, execaOptions) {
|
|||||||
* @param {Object} [execaOpts] Options to pass to `execa`.
|
* @param {Object} [execaOpts] Options to pass to `execa`.
|
||||||
*/
|
*/
|
||||||
export async function gitGetNote(ref, execaOptions) {
|
export async function gitGetNote(ref, execaOptions) {
|
||||||
return (await execa("git", ["notes", "--ref", `${GIT_NOTE_REF}-${ref}`, "show", ref], execaOptions)).stdout;
|
return (await execa("git", ["notes", "--ref", GIT_NOTE_REF, "show", ref], execaOptions)).stdout;
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import Docker from "dockerode";
|
import Docker from "dockerode";
|
||||||
|
import getStream from "get-stream";
|
||||||
import pRetry from "p-retry";
|
import pRetry from "p-retry";
|
||||||
import { gitShallowClone, initBareRepo } from "./git-utils.js";
|
import { gitShallowClone, initBareRepo } from "./git-utils.js";
|
||||||
|
|
||||||
@ -14,27 +15,15 @@ let container;
|
|||||||
export const gitCredential = `${GIT_USERNAME}:${GIT_PASSWORD}`;
|
export const gitCredential = `${GIT_USERNAME}:${GIT_PASSWORD}`;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download the `gitbox` Docker image
|
* Download the `gitbox` Docker image, create a new container and start it.
|
||||||
*/
|
|
||||||
export function pull() {
|
|
||||||
return docker.pull(IMAGE).then((stream) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
docker.modem.followProgress(stream, (err, res) => (err ? reject(err) : resolve(res)));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create a new container and start it.
|
|
||||||
*/
|
*/
|
||||||
export async function start() {
|
export async function start() {
|
||||||
|
await getStream(await docker.pull(IMAGE));
|
||||||
|
|
||||||
container = await docker.createContainer({
|
container = await docker.createContainer({
|
||||||
Tty: true,
|
Tty: true,
|
||||||
Image: IMAGE,
|
Image: IMAGE,
|
||||||
HostConfig: {
|
PortBindings: { [`${SERVER_PORT}/tcp`]: [{ HostPort: `${HOST_PORT}` }] },
|
||||||
PortBindings: { [`${SERVER_PORT}/tcp`]: [{ HostPort: `${HOST_PORT}` }] },
|
|
||||||
},
|
|
||||||
ExposedPorts: { [`${SERVER_PORT}/tcp`]: {} },
|
|
||||||
});
|
});
|
||||||
await container.start();
|
await container.start();
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import Docker from "dockerode";
|
import Docker from "dockerode";
|
||||||
|
import getStream from "get-stream";
|
||||||
import got from "got";
|
import got from "got";
|
||||||
import pRetry from "p-retry";
|
import pRetry from "p-retry";
|
||||||
import { mockServerClient } from "mockserver-client";
|
import { mockServerClient } from "mockserver-client";
|
||||||
@ -10,27 +11,15 @@ const docker = new Docker();
|
|||||||
let container;
|
let container;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download the `mockserver` Docker image,
|
* Download the `mockserver` Docker image, create a new container and start it.
|
||||||
*/
|
|
||||||
export function pull() {
|
|
||||||
return docker.pull(IMAGE).then((stream) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
docker.modem.followProgress(stream, (err, res) => (err ? reject(err) : resolve(res)));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create a new container and start it.
|
|
||||||
*/
|
*/
|
||||||
export async function start() {
|
export async function start() {
|
||||||
|
await getStream(await docker.pull(IMAGE));
|
||||||
|
|
||||||
container = await docker.createContainer({
|
container = await docker.createContainer({
|
||||||
Tty: true,
|
Tty: true,
|
||||||
Image: IMAGE,
|
Image: IMAGE,
|
||||||
HostConfig: {
|
PortBindings: { [`${MOCK_SERVER_PORT}/tcp`]: [{ HostPort: `${MOCK_SERVER_PORT}` }] },
|
||||||
PortBindings: { [`${MOCK_SERVER_PORT}/tcp`]: [{ HostPort: `${MOCK_SERVER_PORT}` }] },
|
|
||||||
},
|
|
||||||
ExposedPorts: { [`${MOCK_SERVER_PORT}/tcp`]: {} },
|
|
||||||
});
|
});
|
||||||
await container.start();
|
await container.start();
|
||||||
|
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
import path, { dirname } from "node:path";
|
import path, { dirname } from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
import { setTimeout } from "node:timers/promises";
|
|
||||||
import Docker from "dockerode";
|
import Docker from "dockerode";
|
||||||
|
import getStream from "get-stream";
|
||||||
import got from "got";
|
import got from "got";
|
||||||
|
import delay from "delay";
|
||||||
import pRetry from "p-retry";
|
import pRetry from "p-retry";
|
||||||
|
|
||||||
const IMAGE = "verdaccio/verdaccio:5";
|
const IMAGE = "verdaccio/verdaccio:5";
|
||||||
@ -16,32 +17,20 @@ const __dirname = dirname(fileURLToPath(import.meta.url));
|
|||||||
let container, npmToken;
|
let container, npmToken;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Download the `npm-registry-docker` Docker image
|
* Download the `npm-registry-docker` Docker image, create a new container and start it.
|
||||||
*/
|
|
||||||
export function pull() {
|
|
||||||
return docker.pull(IMAGE).then((stream) => {
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
docker.modem.followProgress(stream, (err, res) => (err ? reject(err) : resolve(res)));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* create a new container and start it.
|
|
||||||
*/
|
*/
|
||||||
export async function start() {
|
export async function start() {
|
||||||
|
await getStream(await docker.pull(IMAGE));
|
||||||
|
|
||||||
container = await docker.createContainer({
|
container = await docker.createContainer({
|
||||||
Tty: true,
|
Tty: true,
|
||||||
Image: IMAGE,
|
Image: IMAGE,
|
||||||
HostConfig: {
|
PortBindings: { [`${REGISTRY_PORT}/tcp`]: [{ HostPort: `${REGISTRY_PORT}` }] },
|
||||||
PortBindings: { [`${REGISTRY_PORT}/tcp`]: [{ HostPort: `${REGISTRY_PORT}` }] },
|
Binds: [`${path.join(__dirname, "config.yaml")}:/verdaccio/conf/config.yaml`],
|
||||||
Binds: [`${path.join(__dirname, "config.yaml")}:/verdaccio/conf/config.yaml`],
|
|
||||||
},
|
|
||||||
ExposedPorts: { [`${REGISTRY_PORT}/tcp`]: {} },
|
|
||||||
});
|
});
|
||||||
|
|
||||||
await container.start();
|
await container.start();
|
||||||
await setTimeout(4000);
|
await delay(4000);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Wait for the registry to be ready
|
// Wait for the registry to be ready
|
||||||
|
@ -11,7 +11,7 @@ test("Replace multiple sensitive environment variable values", (t) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Replace multiple occurrences of sensitive environment variable values", (t) => {
|
test("Replace multiple occurences of sensitive environment variable values", (t) => {
|
||||||
const env = { secretKey: "secret" };
|
const env = { secretKey: "secret" };
|
||||||
t.is(
|
t.is(
|
||||||
hideSensitive(env)(`https://user:${env.secretKey}@host.com?token=${env.secretKey}`),
|
hideSensitive(env)(`https://user:${env.secretKey}@host.com?token=${env.secretKey}`),
|
||||||
|
@ -39,11 +39,7 @@ test.beforeEach((t) => {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
test.afterEach.always((t) => {
|
test("Plugins are called with expected values", async (t) => {
|
||||||
td.reset();
|
|
||||||
});
|
|
||||||
|
|
||||||
test.serial("Plugins are called with expected values", 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
|
||||||
const { cwd, repositoryUrl } = await gitRepo(true);
|
const { cwd, repositoryUrl } = await gitRepo(true);
|
||||||
// Add commits to the master branch
|
// Add commits to the master branch
|
||||||
@ -1853,19 +1849,10 @@ test.serial("Throw an Error if plugin returns an unexpected value", async (t) =>
|
|||||||
await td.replaceEsm("../lib/get-logger.js", null, () => t.context.logger);
|
await td.replaceEsm("../lib/get-logger.js", null, () => t.context.logger);
|
||||||
await td.replaceEsm("env-ci", null, () => ({ isCi: true, branch: "master", isPr: false }));
|
await td.replaceEsm("env-ci", null, () => ({ isCi: true, branch: "master", isPr: false }));
|
||||||
const semanticRelease = (await import("../index.js")).default;
|
const semanticRelease = (await import("../index.js")).default;
|
||||||
|
const error = await t.throwsAsync(
|
||||||
let error;
|
semanticRelease(options, { cwd, env: {}, stdout: new WritableStreamBuffer(), stderr: new WritableStreamBuffer() }),
|
||||||
try {
|
{ instanceOf: SemanticReleaseError }
|
||||||
await semanticRelease(options, {
|
);
|
||||||
cwd,
|
|
||||||
env: {},
|
|
||||||
stdout: new WritableStreamBuffer(),
|
|
||||||
stderr: new WritableStreamBuffer(),
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
error = e;
|
|
||||||
}
|
|
||||||
t.is(error.code, "EANALYZECOMMITSOUTPUT");
|
|
||||||
t.regex(error.details, /string/);
|
t.regex(error.details, /string/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import path from "node:path";
|
import path from "path";
|
||||||
import { setTimeout } from "node:timers/promises";
|
|
||||||
import test from "ava";
|
import test from "ava";
|
||||||
import * as td from "testdouble";
|
import * as td from "testdouble";
|
||||||
import { escapeRegExp } from "lodash-es";
|
import { escapeRegExp } from "lodash-es";
|
||||||
import fsExtra from "fs-extra";
|
import fsExtra from "fs-extra";
|
||||||
import { execa } from "execa";
|
import { execa } from "execa";
|
||||||
import { WritableStreamBuffer } from "stream-buffers";
|
import { WritableStreamBuffer } from "stream-buffers";
|
||||||
|
import delay from "delay";
|
||||||
|
|
||||||
import getAuthUrl from "../lib/get-git-auth-url.js";
|
import getAuthUrl from "../lib/get-git-auth-url.js";
|
||||||
import { SECRET_REPLACEMENT } from "../lib/definitions/constants.js";
|
import { SECRET_REPLACEMENT } from "../lib/definitions/constants.js";
|
||||||
@ -35,7 +35,7 @@ let env;
|
|||||||
|
|
||||||
// Environment variables used only for the local npm command used to do verification
|
// Environment variables used only for the local npm command used to do verification
|
||||||
const npmTestEnv = {
|
const npmTestEnv = {
|
||||||
...processEnvWithoutGitHubActionsVariables,
|
...process.env,
|
||||||
...npmRegistry.authEnv(),
|
...npmRegistry.authEnv(),
|
||||||
npm_config_registry: npmRegistry.url,
|
npm_config_registry: npmRegistry.url,
|
||||||
};
|
};
|
||||||
@ -47,7 +47,6 @@ const pluginLogEnv = path.resolve("./test/fixtures/plugin-log-env");
|
|||||||
const pluginEsmNamedExports = path.resolve("./test/fixtures/plugin-esm-named-exports");
|
const pluginEsmNamedExports = path.resolve("./test/fixtures/plugin-esm-named-exports");
|
||||||
|
|
||||||
test.before(async () => {
|
test.before(async () => {
|
||||||
await Promise.all([gitbox.pull(), npmRegistry.pull(), mockServer.pull()]);
|
|
||||||
await Promise.all([gitbox.start(), npmRegistry.start(), mockServer.start()]);
|
await Promise.all([gitbox.start(), npmRegistry.start(), mockServer.start()]);
|
||||||
|
|
||||||
env = {
|
env = {
|
||||||
@ -296,7 +295,7 @@ test("Release patch, minor and major versions", async (t) => {
|
|||||||
t.is(exitCode, 0);
|
t.is(exitCode, 0);
|
||||||
|
|
||||||
// Wait for 3s as the change of dist-tag takes time to be reflected in the registry
|
// Wait for 3s as the change of dist-tag takes time to be reflected in the registry
|
||||||
await setTimeout(3000);
|
await delay(3000);
|
||||||
// Retrieve the published package from the registry and check version and gitHead
|
// Retrieve the published package from the registry and check version and gitHead
|
||||||
({
|
({
|
||||||
"dist-tags": { latest: releasedVersion },
|
"dist-tags": { latest: releasedVersion },
|
||||||
@ -516,8 +515,8 @@ test("Pass options via CLI arguments", async (t) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("Run via JS API", async (t) => {
|
test("Run via JS API", async (t) => {
|
||||||
await td.replaceEsm("../lib/logger", null, { log: () => {}, error: () => {}, stdout: () => {} });
|
td.replace("../lib/logger", { log: () => {}, error: () => {}, stdout: () => {} });
|
||||||
await td.replaceEsm("env-ci", null, () => ({ isCi: true, branch: "master", isPr: false }));
|
td.replace("env-ci", () => ({ isCi: true, branch: "master", isPr: false }));
|
||||||
const semanticRelease = (await import("../index.js")).default;
|
const semanticRelease = (await import("../index.js")).default;
|
||||||
const packageName = "test-js-api";
|
const packageName = "test-js-api";
|
||||||
const owner = "git";
|
const owner = "git";
|
||||||
@ -599,7 +598,7 @@ test("Log unexpected errors from plugins and exit with 1", async (t) => {
|
|||||||
// Verify the type and message are logged
|
// Verify the type and message are logged
|
||||||
t.regex(stderr, /Error: a/);
|
t.regex(stderr, /Error: a/);
|
||||||
// Verify the the stacktrace is logged
|
// Verify the the stacktrace is logged
|
||||||
t.regex(stderr, new RegExp(process.platform === "win32" ? pluginError.replace(/\\/g, "\\\\") : pluginError));
|
t.regex(stderr, new RegExp(pluginError));
|
||||||
// Verify the Error properties are logged
|
// Verify the Error properties are logged
|
||||||
t.regex(stderr, /errorProperty: 'errorProperty'/);
|
t.regex(stderr, /errorProperty: 'errorProperty'/);
|
||||||
t.is(exitCode, 1);
|
t.is(exitCode, 1);
|
||||||
@ -688,7 +687,6 @@ test("Use the valid git credentials when multiple are provided", async (t) => {
|
|||||||
BB_TOKEN_BASIC_AUTH: gitbox.gitCredential,
|
BB_TOKEN_BASIC_AUTH: gitbox.gitCredential,
|
||||||
GIT_ASKPASS: "echo",
|
GIT_ASKPASS: "echo",
|
||||||
GIT_TERMINAL_PROMPT: 0,
|
GIT_TERMINAL_PROMPT: 0,
|
||||||
GIT_CONFIG_PARAMETERS: "'credential.helper='",
|
|
||||||
},
|
},
|
||||||
branch: { name: "master" },
|
branch: { name: "master" },
|
||||||
options: { repositoryUrl: "http://toto@localhost:2080/git/test-auth.git" },
|
options: { repositoryUrl: "http://toto@localhost:2080/git/test-auth.git" },
|
||||||
@ -709,7 +707,6 @@ test("Use the repository URL as is if none of the given git credentials are vali
|
|||||||
GITLAB_TOKEN: "trash",
|
GITLAB_TOKEN: "trash",
|
||||||
GIT_ASKPASS: "echo",
|
GIT_ASKPASS: "echo",
|
||||||
GIT_TERMINAL_PROMPT: 0,
|
GIT_TERMINAL_PROMPT: 0,
|
||||||
GIT_CONFIG_PARAMETERS: "'credential.helper='",
|
|
||||||
},
|
},
|
||||||
branch: { name: "master" },
|
branch: { name: "master" },
|
||||||
options: { repositoryUrl: dummyUrl },
|
options: { repositoryUrl: dummyUrl },
|
||||||
@ -719,7 +716,7 @@ test("Use the repository URL as is if none of the given git credentials are vali
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("ESM Plugin with named exports", async (t) => {
|
test("ESM Plugin with named exports", async (t) => {
|
||||||
const packageName = "plugin-exports";
|
const packageName = "log-secret";
|
||||||
// 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
|
||||||
t.log("Create git repository");
|
t.log("Create git repository");
|
||||||
const { cwd, repositoryUrl } = await gitbox.createRepo(packageName);
|
const { cwd, repositoryUrl } = await gitbox.createRepo(packageName);
|
||||||
|
@ -96,7 +96,7 @@ test("Normalize and load plugin from function", async (t) => {
|
|||||||
t.is(typeof plugin, "function");
|
t.is(typeof plugin, "function");
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Normalize and load plugin that returns multiple functions", async (t) => {
|
test("Normalize and load plugin that retuns multiple functions", async (t) => {
|
||||||
const plugin = await normalize(
|
const plugin = await normalize(
|
||||||
{ cwd, options: {}, logger: t.context.logger },
|
{ cwd, options: {}, logger: t.context.logger },
|
||||||
"verifyConditions",
|
"verifyConditions",
|
||||||
|
@ -52,7 +52,7 @@ test("validateStep: optional plugin configuration", (t) => {
|
|||||||
t.true(validateStep(type, { path: () => {}, options: "value" }));
|
t.true(validateStep(type, { path: () => {}, options: "value" }));
|
||||||
t.false(validateStep(type, { path: null }));
|
t.false(validateStep(type, { path: null }));
|
||||||
|
|
||||||
// Considered as an Array of 2 definitions and not as one Array definition in case of a multiple plugin type
|
// Considered as an Array of 2 definitions and not as one Array definition in case of a muliple plugin type
|
||||||
t.false(validateStep(type, [() => {}, { options: "value" }]));
|
t.false(validateStep(type, [() => {}, { options: "value" }]));
|
||||||
t.false(validateStep(type, ["plugin-path.js", { options: "value" }]));
|
t.false(validateStep(type, ["plugin-path.js", { options: "value" }]));
|
||||||
|
|
||||||
@ -134,7 +134,7 @@ test("validateStep: required plugin configuration", (t) => {
|
|||||||
t.true(validateStep(type, { path: () => {}, options: "value" }));
|
t.true(validateStep(type, { path: () => {}, options: "value" }));
|
||||||
t.false(validateStep(type, { path: null }));
|
t.false(validateStep(type, { path: null }));
|
||||||
|
|
||||||
// Considered as an Array of 2 definitions and not as one Array definition in the case of a multiple plugin type
|
// Considered as an Array of 2 definitions and not as one Array definition in the case of a muliple plugin type
|
||||||
t.false(validateStep(type, [() => {}, { options: "value" }]));
|
t.false(validateStep(type, [() => {}, { options: "value" }]));
|
||||||
t.false(validateStep(type, ["plugin-path.js", { options: "value" }]));
|
t.false(validateStep(type, ["plugin-path.js", { options: "value" }]));
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user