Compare commits
177 Commits
Author | SHA1 | Date | |
---|---|---|---|
aa666d7acf | |||
|
28bcc1d54b | ||
|
9faded8d50 | ||
|
fccab39b87 | ||
|
6be228070f | ||
|
518b47d030 | ||
|
c6c01aa1ae | ||
|
ee4f99f0cf | ||
|
9b9c9b76c3 | ||
|
211704d102 | ||
|
01779f4efa | ||
|
95ea5ef9b7 | ||
|
2fd9685bff | ||
|
c85cde96f2 | ||
|
ac5fdeaf05 | ||
|
4044e7a932 | ||
|
440d0661eb | ||
|
6e57047eca | ||
|
58b338bc9b | ||
|
4692834087 | ||
|
2c04f32744 | ||
|
c5071df260 | ||
|
2096d44b0c | ||
|
2c0b371f7b | ||
|
a2de1057b7 | ||
|
58e21774cb | ||
|
8066b7fd54 | ||
|
f31d43c429 | ||
|
13f980149a | ||
|
020ea7d7d5 | ||
|
6d2a6f1aa6 | ||
|
ce580be16d | ||
|
d4b7c9a23d | ||
|
7983c57300 | ||
|
50ad70f229 | ||
|
90513bbc0a | ||
|
b07ddfaaf9 | ||
|
acd6f05dad | ||
|
5a7fa82309 | ||
|
81346ff687 | ||
|
a8e0d6d611 | ||
|
afc7518c50 | ||
|
ee110291b2 | ||
|
f021f25ad2 | ||
|
fd2c179131 | ||
|
ad8f5b2608 | ||
|
0d0ed9d08a | ||
|
2904832967 | ||
|
abf8ddd978 | ||
|
07dde042bb | ||
|
2557e9e8f1 | ||
|
786b48f886 | ||
|
f6f1bf167c | ||
|
b38cd2e44e | ||
|
3722204510 | ||
|
1fd1ce85eb | ||
|
00e7ca8d2e | ||
|
9912d34b8d | ||
|
f72e493d69 | ||
|
e8d3b2eede | ||
|
88efeadac9 | ||
|
3a2acce01f | ||
|
8b0dbd2805 | ||
|
5aa56da694 | ||
|
c516d59bf0 | ||
|
67995485c3 | ||
|
14a5755ef1 | ||
|
f6fb0fc130 | ||
|
5ca3d78c63 | ||
|
cac1dbb121 | ||
|
29aefa4b87 | ||
|
3d8c7154b2 | ||
|
ea446a4ea4 | ||
|
0d06f62411 | ||
|
26df1d2aa1 | ||
|
b3a87bfa8f | ||
|
b36036e920 | ||
|
c084008274 | ||
|
9fd162b3bc | ||
|
c129474e93 | ||
|
02f2cb1c8b | ||
|
b1683a7b4d | ||
|
f09e55f39f | ||
|
9e41b43294 | ||
|
6900865324 | ||
|
250e7ae2c5 | ||
|
50a789638c | ||
|
305674d1db | ||
|
bef62a26b0 | ||
|
4711a38196 | ||
|
6726543295 | ||
|
9504ea8706 | ||
|
1c980143d1 | ||
|
d1120546b5 | ||
|
164697ccd3 | ||
|
cad08804e6 | ||
|
bfd2506f5b | ||
|
3c4137198d | ||
|
40b359784d | ||
|
2baab7f78a | ||
|
fabdf9b1c6 | ||
|
46fd8102ed | ||
|
c8895edef6 | ||
|
6ed3fa5a1e | ||
|
eb881d5721 | ||
|
c119263f00 | ||
|
382edf1c7d | ||
|
e247cca3c7 | ||
|
bd664bdf6a | ||
|
bdfb5296f2 | ||
|
f5d2d7ee05 | ||
|
3773a682a7 | ||
|
4445caeb70 | ||
|
f1e0892c02 | ||
|
50cf1aacbe | ||
|
d8e16a055f | ||
|
579259c578 | ||
|
842c0eb8bc | ||
|
b5d80411ea | ||
|
0586f55164 | ||
|
473925187a | ||
|
aaed2f4a6f | ||
|
65aea33182 | ||
|
a8d863834a | ||
|
de413899fe | ||
|
c6c39d67f7 | ||
|
dac69c981a | ||
|
4d3c394522 | ||
|
125d41ebbc | ||
|
b178c18fde | ||
|
cff501a083 | ||
|
8e6295e214 | ||
|
a92afa2a7a | ||
|
e759493e07 | ||
|
7bbf1e804a | ||
|
84f2ee9374 | ||
|
6070bf61fc | ||
|
8a7befe96b | ||
|
993bf59af9 | ||
|
561e2d648d | ||
|
94d50ed934 | ||
|
bd4725b041 | ||
|
041e4f7e37 | ||
|
1c8d848a4f | ||
|
2822fbee5d | ||
|
2a67c65328 | ||
|
87f0c12cf6 | ||
|
11788ed5dc | ||
|
b93bef4eea | ||
|
6604153812 | ||
|
e623cc642a | ||
|
42f7b8269e | ||
|
1017e1aac2 | ||
|
a23b71890b | ||
|
fb850ff26d | ||
|
b9f294d179 | ||
|
03a687b3ea | ||
|
86a639dee9 | ||
|
da5620171e | ||
|
89d51e7db7 | ||
|
de8e4e05e9 | ||
|
0fd3bb8b3a | ||
|
c39513f24d | ||
|
6a5d96102d | ||
|
19c09653fe | ||
|
32a248077f | ||
|
72ab317bb0 | ||
|
07a79ea7e9 | ||
|
0d92579e13 | ||
|
cb6613e2ee | ||
|
9e10e44fed | ||
|
d3c1338eac | ||
|
01cb041e1d | ||
|
4c95c97d8f | ||
|
5e08c4d95a | ||
|
c84d5d39e5 | ||
|
e40eecdce0 |
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@ -18,8 +18,8 @@ jobs:
|
|||||||
name: release
|
name: release
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
|
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
- uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
|
- uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
|
||||||
with:
|
with:
|
||||||
cache: npm
|
cache: npm
|
||||||
node-version: lts/*
|
node-version: lts/*
|
||||||
|
8
.github/workflows/scorecard.yml
vendored
8
.github/workflows/scorecard.yml
vendored
@ -15,22 +15,22 @@ jobs:
|
|||||||
id-token: write
|
id-token: write
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3
|
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
with:
|
with:
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
- name: Run analysis
|
- name: Run analysis
|
||||||
uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0
|
uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736 # v2.3.1
|
||||||
with:
|
with:
|
||||||
results_file: results.sarif
|
results_file: results.sarif
|
||||||
results_format: sarif
|
results_format: sarif
|
||||||
publish_results: true
|
publish_results: true
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2
|
uses: actions/upload-artifact@26f96dfa697d77e81fd5907df203aa23a56210a8 # v4.3.0
|
||||||
with:
|
with:
|
||||||
name: SARIF file
|
name: SARIF file
|
||||||
path: results.sarif
|
path: results.sarif
|
||||||
retention-days: 5
|
retention-days: 5
|
||||||
- name: Upload to code-scanning
|
- name: Upload to code-scanning
|
||||||
uses: github/codeql-action/upload-sarif@a09933a12a80f87b87005513f0abb1494c27a716 # v2.21.4
|
uses: github/codeql-action/upload-sarif@e8893c57a1f3a2b659b6b55564fdfdbbd2982911 # v3.24.0
|
||||||
with:
|
with:
|
||||||
sarif_file: results.sarif
|
sarif_file: results.sarif
|
||||||
|
58
.github/workflows/test.yml
vendored
58
.github/workflows/test.yml
vendored
@ -15,42 +15,66 @@ on:
|
|||||||
permissions:
|
permissions:
|
||||||
contents: read # to fetch code (actions/checkout)
|
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:
|
||||||
- 18.0.0
|
- 20.8.1
|
||||||
- 19
|
- 20
|
||||||
|
- 21
|
||||||
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
timeout-minutes: 10
|
timeout-minutes: 5
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
|
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
|
||||||
- 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@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
|
uses: actions/setup-node@b39b52d1213e96004bfcb1c61a8a6fa8ab84f3e8 # v4.0.1
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
cache: npm
|
cache: npm
|
||||||
- run: npm clean-install
|
- run: npm clean-install
|
||||||
- name: Ensure dependencies are compatible with the version of node
|
- run: npm audit signatures
|
||||||
run: npx ls-engines
|
- run: npm test
|
||||||
- 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: test_matrix
|
needs:
|
||||||
|
- test_dev
|
||||||
|
- test_matrix
|
||||||
|
if: ${{ !cancelled() }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3
|
- name: All matrix versions passed
|
||||||
- uses: actions/setup-node@5e21ff4d9bc1a8cf6de233a3057d20ec6b3fb69d # v3
|
if: ${{ !(contains(needs.*.result, 'failure')) }}
|
||||||
with:
|
run: exit 0
|
||||||
node-version: lts/*
|
- name: Some matrix version failed
|
||||||
cache: npm
|
if: ${{ contains(needs.*.result, 'failure') }}
|
||||||
- run: npm clean-install
|
run: exit 1
|
||||||
- run: npm audit signatures
|
|
||||||
- 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 with documentation etc...)
|
- a commit should not create an inconsistent state (such as test errors, linting errors, partial fix, feature without 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,42 +241,82 @@ $ 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
|
||||||
```
|
```
|
||||||
|
|
||||||
### Lint
|
### Verification
|
||||||
|
|
||||||
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.
|
The `test` script is structured to execute as much of the verification for the project as possible.
|
||||||
Prettier formatting will be automatically verified and fixed by XO.
|
Ensuring that the `test` script fully passes in the node version defined as the development version in the `.nvmrc`
|
||||||
|
minimizes the chances of the test workflow failing after pushing your changes.
|
||||||
|
|
||||||
Before pushing your code changes make sure there are no linting errors with `npm run lint`.
|
> [!IMPORTANT]
|
||||||
|
> Before pushing your code changes, be sure to run the verification for the project with `npm test`.
|
||||||
|
|
||||||
**Tips**:
|
[npm-run-all2](https://www.npmjs.com/package/npm-run-all2) is used to enable running multiple independent lint and test
|
||||||
|
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.
|
||||||
|
|
||||||
- Most linting errors can be automatically fixed with `npm run lint -- --fix`.
|
When a failure occurs with the `test`, the output can be a bit confusing because there may be output from multiple parallel
|
||||||
- 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.
|
scripts mixed together.
|
||||||
|
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
|
||||||
|
|
||||||
### Tests
|
```shell
|
||||||
|
$ npm run <script-name>
|
||||||
|
```
|
||||||
|
|
||||||
Running the integration test requires you to install [Docker](https://docs.docker.com/engine/installation) on your machine.
|
#### Lint
|
||||||
|
|
||||||
|
##### 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.
|
||||||
|
|
||||||
Before pushing your code changes make sure all **tests pass** and the **coverage is 100%**:
|
During development, you can:
|
||||||
|
|
||||||
```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).
|
||||||
|
|
||||||
After staging your changes with `git add`, run `npm run cm` to start the interactive commit message CLI.
|
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.
|
||||||
|
@ -69,7 +69,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](http://sentimentalversioning.org).
|
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).
|
||||||
|
|
||||||
### Triggering a release
|
### Triggering a release
|
||||||
|
|
||||||
@ -110,9 +110,9 @@ In order to use **semantic-release** you need:
|
|||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
- Usage
|
- Usage
|
||||||
- [Getting started](docs/usage/getting-started.md#getting-started)
|
- [Getting started](docs/usage/getting-started.md)
|
||||||
- [Installation](docs/usage/installation.md#installation)
|
- [Installation](docs/usage/installation.md)
|
||||||
- [CI Configuration](docs/usage/ci-configuration.md#ci-configuration)
|
- [CI Configuration](docs/usage/ci-configuration.md)
|
||||||
- [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,7 +2,7 @@
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
- [Getting started](docs/usage/getting-started.md#getting-started)
|
- [Getting started](docs/usage/getting-started.md)
|
||||||
- [Installation](docs/usage/installation.md)
|
- [Installation](docs/usage/installation.md)
|
||||||
- [CI Configuration](docs/usage/ci-configuration.md)
|
- [CI Configuration](docs/usage/ci-configuration.md)
|
||||||
- [Configuration](docs/usage/configuration.md)
|
- [Configuration](docs/usage/configuration.md)
|
||||||
|
@ -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>
|
||||||
|
|
||||||
And object with [`lastRelease`](#lastrelease), [`nextRelease`](#nextrelease), [`commits`](#commits) and [`releases`](#releases) if a release is published or `false` if no release was published.
|
An 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
|
||||||
|
|
||||||
@ -159,7 +159,7 @@ Example:
|
|||||||
|
|
||||||
Type: `Array<Object>`
|
Type: `Array<Object>`
|
||||||
|
|
||||||
The list of commit included in the new release.<br>
|
The list of commit(s) 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,6 +84,11 @@
|
|||||||
- `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)
|
||||||
@ -174,6 +179,9 @@
|
|||||||
- [semantic-release-coralogix](https://github.com/adobe/semantic-release-coralogix)
|
- [semantic-release-coralogix](https://github.com/adobe/semantic-release-coralogix)
|
||||||
- `verifyConditions` Verified that required credentials are provided and API is accessible
|
- `verifyConditions` Verified that required credentials are provided and API is accessible
|
||||||
- `publish` add a release tag to Coralogix
|
- `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)
|
- [semantic-release-major-tag](https://github.com/doteric/semantic-release-major-tag)
|
||||||
- `success` Create major version tag, for example `v1`.
|
- `success` Create major version tag, for example `v1`.
|
||||||
- [semantic-release-yarn](https://github.com/hongaar/semantic-release-yarn)
|
- [semantic-release-yarn](https://github.com/hongaar/semantic-release-yarn)
|
||||||
@ -182,3 +190,7 @@
|
|||||||
- `prepare` Update the `package.json` version and create the package tarball.
|
- `prepare` Update the `package.json` version and create the package tarball.
|
||||||
- `addChannel` Add a tag for the release.
|
- `addChannel` Add a tag for the release.
|
||||||
- `publish` Publish to the npm registry.
|
- `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,6 +6,11 @@ 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.
|
||||||
|
@ -195,7 +195,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** as it's not considered a good practice, mostly because [Semantic Versioning](https://semver.org) rules applies differently to major version zero.
|
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.
|
||||||
|
|
||||||
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 18.0.0 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 20.8.1 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.
|
||||||
|
@ -40,6 +40,17 @@ 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,16 +6,3 @@ 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`.
|
|
||||||
|
11
index.js
11
index.js
@ -123,12 +123,15 @@ 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.gitHead, {
|
await addNote({ channels: [...currentRelease.channels, nextRelease.channel] }, nextRelease.gitTag, {
|
||||||
cwd,
|
cwd,
|
||||||
env,
|
env,
|
||||||
});
|
});
|
||||||
await push(options.repositoryUrl, { cwd, env });
|
await push(options.repositoryUrl, { cwd, env });
|
||||||
await pushNotes(options.repositoryUrl, { cwd, env });
|
await pushNotes(options.repositoryUrl, nextRelease.gitTag, {
|
||||||
|
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
|
||||||
@ -203,9 +206,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.gitHead, { cwd, env });
|
await addNote({ channels: [nextRelease.channel] }, nextRelease.gitTag, { cwd, env });
|
||||||
await push(options.repositoryUrl, { cwd, env });
|
await push(options.repositoryUrl, { cwd, env });
|
||||||
await pushNotes(options.repositoryUrl, { cwd, env });
|
await pushNotes(options.repositoryUrl, nextRelease.gitTag, { 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 intial lastVersion is the last release from the base branch of `FIRST_RELEASE` (1.0.0)
|
// The initial 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,11 +1,10 @@
|
|||||||
import { dirname, resolve } from "node:path";
|
import { dirname } 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 resolveFrom from "resolve-from";
|
import importFrom from "import-from-esm";
|
||||||
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";
|
||||||
@ -14,7 +13,6 @@ 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";
|
||||||
|
|
||||||
@ -35,7 +33,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 = require(resolveFrom.silent(__dirname, extendPath) || resolveFrom(cwd, extendPath));
|
const extendsOptions = (await importFrom.silent(__dirname, extendPath)) || (await importFrom(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
|
||||||
@ -76,8 +74,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 successfull, null otherwise
|
* @return {String} The authUrl as is if the connection was successful, null otherwise
|
||||||
*/
|
*/
|
||||||
async function ensureValidAuthUrl({ cwd, env, branch }, authUrl) {
|
async function ensureValidAuthUrl({ cwd, env, branch }, authUrl) {
|
||||||
try {
|
try {
|
||||||
|
49
lib/git.js
49
lib/git.js
@ -2,6 +2,7 @@ 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");
|
||||||
@ -141,13 +142,9 @@ export async function fetch(repositoryUrl, branch, ciBranch, execaOptions) {
|
|||||||
*/
|
*/
|
||||||
export async function fetchNotes(repositoryUrl, execaOptions) {
|
export async function fetchNotes(repositoryUrl, execaOptions) {
|
||||||
try {
|
try {
|
||||||
await execa(
|
await execa("git", ["fetch", "--unshallow", repositoryUrl, `+refs/notes/*:refs/notes/*`], execaOptions);
|
||||||
"git",
|
|
||||||
["fetch", "--unshallow", repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`],
|
|
||||||
execaOptions
|
|
||||||
);
|
|
||||||
} catch {
|
} catch {
|
||||||
await execa("git", ["fetch", repositoryUrl, `+refs/notes/${GIT_NOTE_REF}:refs/notes/${GIT_NOTE_REF}`], {
|
await execa("git", ["fetch", repositoryUrl, `+refs/notes/*:refs/notes/*`], {
|
||||||
...execaOptions,
|
...execaOptions,
|
||||||
reject: false,
|
reject: false,
|
||||||
});
|
});
|
||||||
@ -246,8 +243,8 @@ export async function push(repositoryUrl, execaOptions) {
|
|||||||
*
|
*
|
||||||
* @throws {Error} if the push failed.
|
* @throws {Error} if the push failed.
|
||||||
*/
|
*/
|
||||||
export async function pushNotes(repositoryUrl, execaOptions) {
|
export async function pushNotes(repositoryUrl, ref, execaOptions) {
|
||||||
await execa("git", ["push", repositoryUrl, `refs/notes/${GIT_NOTE_REF}`], execaOptions);
|
await execa("git", ["push", repositoryUrl, `refs/notes/${GIT_NOTE_REF}-${ref}`], execaOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -307,8 +304,26 @@ 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 JSON.parse((await execa("git", ["notes", "--ref", GIT_NOTE_REF, "show", ref], execaOptions)).stdout);
|
return merge(
|
||||||
|
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 {};
|
||||||
@ -327,5 +342,19 @@ 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("git", ["notes", "--ref", GIT_NOTE_REF, "add", "-f", "-m", JSON.stringify(note), ref], execaOptions);
|
await execa(
|
||||||
|
"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;
|
||||||
}
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 65 KiB |
10926
package-lock.json
generated
10926
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
82
package.json
82
package.json
@ -6,7 +6,8 @@
|
|||||||
"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",
|
||||||
@ -26,29 +27,30 @@
|
|||||||
"Matt Travi <npm@travi.org> (https://matt.travi.org/)"
|
"Matt Travi <npm@travi.org> (https://matt.travi.org/)"
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@semantic-release/commit-analyzer": "^10.0.0",
|
"@semantic-release/commit-analyzer": "^11.0.0",
|
||||||
"@semantic-release/error": "^4.0.0",
|
"@semantic-release/error": "^4.0.0",
|
||||||
"@semantic-release/github": "^9.0.0",
|
"@semantic-release/github": "^9.0.0",
|
||||||
"@semantic-release/npm": "^10.0.2",
|
"@semantic-release/npm": "^11.0.0",
|
||||||
"@semantic-release/release-notes-generator": "^11.0.0",
|
"@semantic-release/release-notes-generator": "^12.0.0",
|
||||||
"aggregate-error": "^4.0.1",
|
"aggregate-error": "^5.0.0",
|
||||||
"cosmiconfig": "^8.0.0",
|
"cosmiconfig": "^9.0.0",
|
||||||
"debug": "^4.0.0",
|
"debug": "^4.0.0",
|
||||||
"env-ci": "^9.0.0",
|
"env-ci": "^11.0.0",
|
||||||
"execa": "^8.0.0",
|
"execa": "^8.0.0",
|
||||||
"figures": "^5.0.0",
|
"figures": "^6.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": "^7.0.0",
|
||||||
|
"import-from-esm": "^1.3.1",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"marked": "^5.0.0",
|
"marked": "^11.0.0",
|
||||||
"marked-terminal": "^5.1.1",
|
"marked-terminal": "^7.0.0",
|
||||||
"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": "^10.0.0",
|
"read-pkg-up": "^11.0.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",
|
||||||
@ -56,31 +58,37 @@
|
|||||||
"yargs": "^17.5.1"
|
"yargs": "^17.5.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"ava": "5.3.1",
|
"ava": "6.1.1",
|
||||||
"c8": "8.0.1",
|
"c8": "9.1.0",
|
||||||
"clear-module": "4.1.2",
|
"clear-module": "4.1.2",
|
||||||
"codecov": "3.8.3",
|
"codecov": "3.8.3",
|
||||||
"dockerode": "3.3.5",
|
"cz-conventional-changelog": "3.3.0",
|
||||||
|
"dockerode": "4.0.2",
|
||||||
"file-url": "4.0.0",
|
"file-url": "4.0.0",
|
||||||
"fs-extra": "11.1.1",
|
"fs-extra": "11.2.0",
|
||||||
"got": "13.0.0",
|
"got": "14.2.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.3.3",
|
"nock": "13.5.1",
|
||||||
"p-retry": "5.1.2",
|
"npm-run-all2": "6.1.2",
|
||||||
"prettier": "3.0.2",
|
"p-retry": "6.2.0",
|
||||||
"sinon": "15.2.0",
|
"prettier": "3.2.5",
|
||||||
|
"publint": "0.2.7",
|
||||||
|
"sinon": "17.0.1",
|
||||||
"stream-buffers": "3.0.2",
|
"stream-buffers": "3.0.2",
|
||||||
"tempy": "3.1.0",
|
"tempy": "3.1.0",
|
||||||
"testdouble": "3.18.0"
|
"testdouble": "3.20.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=20.8.1"
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"bin",
|
"bin",
|
||||||
"docs",
|
"docs",
|
||||||
"lib",
|
"lib",
|
||||||
|
"index.d.ts",
|
||||||
"index.js",
|
"index.js",
|
||||||
"cli.js"
|
"cli.js"
|
||||||
],
|
],
|
||||||
@ -97,7 +105,7 @@
|
|||||||
"version"
|
"version"
|
||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "index.js",
|
"main": "./index.js",
|
||||||
"types": "index.d.ts",
|
"types": "index.d.ts",
|
||||||
"c8": {
|
"c8": {
|
||||||
"include": [
|
"include": [
|
||||||
@ -112,6 +120,14 @@
|
|||||||
],
|
],
|
||||||
"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"
|
||||||
@ -124,18 +140,26 @@
|
|||||||
"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 --check \"*.{js,json,md}\" \".github/**/*.{md,yml}\" \"docs/**/*.md\" \"{bin,lib,test}/**/*.js\"",
|
"lint:prettier": "prettier --check \"*.{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:prettier:fix": "prettier --write \"*.{js,json,md}\" \".github/**/*.{md,yml}\" \"docs/**/*.md\" \"{bin,lib,test}/**/*.js\"",
|
||||||
"pretest": "npm run lint",
|
"lint:lockfile": "lockfile-lint",
|
||||||
|
"lint:engines": "ls-engines",
|
||||||
|
"lint:publish": "publint --strict",
|
||||||
"semantic-release": "./bin/semantic-release.js",
|
"semantic-release": "./bin/semantic-release.js",
|
||||||
"test": "c8 ava --verbose",
|
"test": "npm-run-all --print-label --parallel lint:* --parallel test:*",
|
||||||
"test:ci": "c8 ava --verbose"
|
"test:unit": "c8 ava --verbose",
|
||||||
|
"test:integration": "ava --verbose test/integration.test.js"
|
||||||
},
|
},
|
||||||
"renovate": {
|
"renovate": {
|
||||||
"extends": [
|
"extends": [
|
||||||
"github>semantic-release/.github"
|
"github>semantic-release/.github:renovate-config"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -389,6 +389,92 @@ 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,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 {String} The path of the clone if `withRemote` is `true`, the path of the repository otherwise.
|
* @return {Promise<Object>} 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);
|
||||||
@ -98,7 +98,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 seach commits.
|
* @param {String} [from] Git reference from which to search 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 +240,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 seach for.
|
* @param {String} tagName The tag name to search 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 +315,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, "add", "-m", note, ref], execaOptions);
|
await execa("git", ["notes", "--ref", `${GIT_NOTE_REF}-${ref}`, "add", "-m", note, ref], execaOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -325,5 +325,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, "show", ref], execaOptions)).stdout;
|
return (await execa("git", ["notes", "--ref", `${GIT_NOTE_REF}-${ref}`, "show", ref], execaOptions)).stdout;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ test("Replace multiple sensitive environment variable values", (t) => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Replace multiple occurences of sensitive environment variable values", (t) => {
|
test("Replace multiple occurrences 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}`),
|
||||||
|
@ -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 = {
|
||||||
...process.env,
|
...processEnvWithoutGitHubActionsVariables,
|
||||||
...npmRegistry.authEnv(),
|
...npmRegistry.authEnv(),
|
||||||
npm_config_registry: npmRegistry.url,
|
npm_config_registry: npmRegistry.url,
|
||||||
};
|
};
|
||||||
@ -516,8 +516,8 @@ test("Pass options via CLI arguments", async (t) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test("Run via JS API", async (t) => {
|
test("Run via JS API", async (t) => {
|
||||||
td.replace("../lib/logger", { log: () => {}, error: () => {}, stdout: () => {} });
|
await td.replaceEsm("../lib/logger", null, { log: () => {}, error: () => {}, stdout: () => {} });
|
||||||
td.replace("env-ci", () => ({ 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 packageName = "test-js-api";
|
const packageName = "test-js-api";
|
||||||
const owner = "git";
|
const owner = "git";
|
||||||
|
@ -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 retuns multiple functions", async (t) => {
|
test("Normalize and load plugin that returns 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 muliple plugin type
|
// Considered as an Array of 2 definitions and not as one Array definition in case of a multiple 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 muliple plugin type
|
// Considered as an Array of 2 definitions and not as one Array definition in the case of a multiple 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