1 | # @semantic-release/git
|
2 |
|
3 | [**semantic-release**](https://github.com/semantic-release/semantic-release) plugin to commit release assets to the project's [git](https://git-scm.com/) repository.
|
4 |
|
5 | [![Travis](https://img.shields.io/travis/semantic-release/git.svg)](https://travis-ci.org/semantic-release/git)
|
6 | [![Codecov](https://img.shields.io/codecov/c/github/semantic-release/git.svg)](https://codecov.io/gh/semantic-release/git)
|
7 | [![Greenkeeper badge](https://badges.greenkeeper.io/semantic-release/git.svg)](https://greenkeeper.io/)
|
8 |
|
9 | [![npm latest version](https://img.shields.io/npm/v/@semantic-release/git/latest.svg)](https://www.npmjs.com/package/@semantic-release/git)
|
10 | [![npm next version](https://img.shields.io/npm/v/@semantic-release/git/next.svg)](https://www.npmjs.com/package/@semantic-release/git)
|
11 |
|
12 | | Step | Description |
|
13 | |--------------------|------------------------------------------------------------------------------------------------------------------------------------|
|
14 | | `verifyConditions` | Verify the access to the remote Git repository, the commit [`message`](#message) and the [`assets`](#assets) option configuration. |
|
15 | | `prepare` | Create a release commit, including configurable file assets. |
|
16 |
|
17 | ## Install
|
18 |
|
19 | ```bash
|
20 | $ npm install @semantic-release/git -D
|
21 | ```
|
22 |
|
23 | ## Usage
|
24 |
|
25 | The plugin can be configured in the [**semantic-release** configuration file](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/configuration.md#configuration):
|
26 |
|
27 | ```json
|
28 | {
|
29 | "plugins": [
|
30 | "@semantic-release/commit-analyzer",
|
31 | "@semantic-release/release-notes-generator",
|
32 | ["@semantic-release/git", {
|
33 | "assets": ["dist/**/*.{js,css}", "docs", "package.json"],
|
34 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
|
35 | }]
|
36 | ]
|
37 | }
|
38 | ```
|
39 |
|
40 | With this example, for each release a release commit will be pushed to the remote Git repository with:
|
41 | - a message formatted like `chore(release): <version> [skip ci]\n\n<release notes>`
|
42 | - the `.js` and `.css` files in the `dist` directory, the files in the `docs` directory and the `package.json`
|
43 |
|
44 | ## Configuration
|
45 |
|
46 | ### Git authentication
|
47 |
|
48 | The Git user associated with the [Git credentials](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/ci-configuration.md#authentication) has to be able to push commit to the [release branch](https://github.com/semantic-release/semantic-release/blob/master/docs/usage/configuration.md#branch).
|
49 |
|
50 | When configuring branches permission on a Git hosting service (e.g. [GitHub protected branches](https://help.github.com/articles/about-protected-branches), [GitLab protected branches](https://docs.gitlab.com/ee/user/project/protected_branches.html) or [Bitbucket branch permissions](https://confluence.atlassian.com/bitbucket/branch-permissions-385912271.html)) it might be necessary to create a specific configuration in order to allow the **semantic-release** user to bypass global restrictions. For example on GitHub you can uncheck "Include administrators" and configure **semantic-release** to use an administrator user, so the plugin can push the release commit without requiring [status checks](https://help.github.com/articles/about-required-status-checks) and [pull request reviews](https://help.github.com/articles/about-required-reviews-for-pull-requests).
|
51 |
|
52 | ### Environment variables
|
53 |
|
54 | | Variable | Description | Default |
|
55 | |-----------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------|
|
56 | | `GIT_AUTHOR_NAME` | The author name associated with the release commit. See [Git environment variables](https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables#_committing). | @semantic-release-bot. |
|
57 | | `GIT_AUTHOR_EMAIL` | The author email associated with the release commit. See [Git environment variables](https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables#_committing). | @semantic-release-bot email address. |
|
58 | | `GIT_COMMITTER_NAME` | The committer name associated with the release commit. See [Git environment variables](https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables#_committing). | @semantic-release-bot. |
|
59 | | `GIT_COMMITTER_EMAIL` | The committer email associated with the release commit. See [Git environment variables](https://git-scm.com/book/en/v2/Git-Internals-Environment-Variables#_committing). | @semantic-release-bot email address. |
|
60 |
|
61 | ### Options
|
62 |
|
63 | | Options | Description | Default |
|
64 | |-----------|------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------|
|
65 | | `message` | The message for the release commit. See [message](#message). | `chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}` |
|
66 | | `assets` | Files to include in the release commit. Set to `false` to disable adding files to the release commit. See [assets](#assets). | `['CHANGELOG.md', 'package.json', 'package-lock.json', 'npm-shrinkwrap.json']` |
|
67 |
|
68 | #### `message`
|
69 |
|
70 | The message for the release commit is generated with [Lodash template](https://lodash.com/docs#template). The following variables are available:
|
71 |
|
72 | | Parameter | Description |
|
73 | |---------------|-------------------------------------------------------------------------------------|
|
74 | | `branch` | The branch from which the release is done. |
|
75 | | `lastRelease` | `Object` with `version`, `gitTag` and `gitHead` of the last release. |
|
76 | | `nextRelease` | `Object` with `version`, `gitTag`, `gitHead` and `notes` of the release being done. |
|
77 |
|
78 | **Note**: It is recommended to include `[skip ci]` in the commit message to not trigger a new build. Some CI service support the `[skip ci]` keyword only in the subject of the message.
|
79 |
|
80 | ##### `message` examples
|
81 |
|
82 | The `message` `Release <%= nextRelease.version %> - <%= new Date().toLocaleDateString('en-US', {year: 'numeric', month: 'short', day: 'numeric', hour: 'numeric', minute: 'numeric' }) %> [skip ci]\n\n<%= nextRelease.notes %>` will generate the commit message:
|
83 |
|
84 | > Release v1.0.0 - Oct. 21, 2015 1:24 AM \[skip ci\]<br><br>## 1.0.0<br><br>### Features<br>* Generate 1.21 gigawatts of electricity<br>...
|
85 |
|
86 | #### `assets`
|
87 |
|
88 | Can be an `Array` or a single entry. Each entry can be either:
|
89 | - a [glob](https://github.com/micromatch/micromatch#matching-features)
|
90 | - or an `Object` with a `path` property containing a [glob](https://github.com/micromatch/micromatch#matching-features).
|
91 |
|
92 | Each entry in the `assets` `Array` is globbed individually. A [glob](https://github.com/micromatch/micromatch#matching-features) can be a `String` (`"dist/**/*.js"` or `"dist/mylib.js"`) or an `Array` of `String`s that will be globbed together (`["dist/**", "!**/*.css"]`).
|
93 |
|
94 | If a directory is configured, all the files under this directory and its children will be included.
|
95 |
|
96 | **Note**: If a file has a match in `assets` it will be included even if it also has a match in `.gitignore`.
|
97 |
|
98 | ##### `assets` examples
|
99 |
|
100 | `'dist/*.js'`: include all `js` files in the `dist` directory, but not in its sub-directories.
|
101 |
|
102 | `'dist/**/*.js'`: include all `js` files in the `dist` directory and its sub-directories.
|
103 |
|
104 | `[['dist', '!**/*.css']]`: include all files in the `dist` directory and its sub-directories excluding the `css` files.
|
105 |
|
106 | `[['dist', '!**/*.css'], 'package.json']`: include `package.json` and all files in the `dist` directory and its sub-directories excluding the `css` files.
|
107 |
|
108 | `[['dist/**/*.{js,css}', '!**/*.min.*']]`: include all `js` and `css` files in the `dist` directory and its sub-directories excluding the minified version.
|
109 |
|
110 | ### Examples
|
111 |
|
112 | When used with the [@semantic-release/changelog](https://github.com/semantic-release/changelog) or [@semantic-release/npm](https://github.com/semantic-release/npm) plugins:
|
113 | - The [@semantic-release/changelog](https://github.com/semantic-release/changelog) plugin must be called first in order to update the changelog file so the `@semantic-release/git` and [@semantic-release/npm](https://github.com/semantic-release/npm) plugins can include it in the release.
|
114 | - The [@semantic-release/npm](https://github.com/semantic-release/npm) plugin must be called second in order to update the `package.json` file so the `@semantic-release/git` plugin can include it in the release commit.
|
115 |
|
116 | ```json
|
117 | {
|
118 | "plugins": [
|
119 | "@semantic-release/commit-analyzer",
|
120 | "@semantic-release/release-notes-generator",
|
121 | "@semantic-release/changelog",
|
122 | "@semantic-release/npm",
|
123 | "@semantic-release/git"
|
124 | ],
|
125 | }
|
126 | ```
|
127 |
|
128 | ### GPG signature
|
129 |
|
130 | Using GPG, you can [sign and verify tags and commits](https://git-scm.com/book/id/v2/Git-Tools-Signing-Your-Work). With GPG keys, the release tags and commits made by Semantic-release are verified and other people can trust that they were really were made by your account.
|
131 |
|
132 | #### Generate the GPG keys
|
133 |
|
134 | If you already have a GPG public and private key you can skip this step and go to the [Get the GPG keys ID and the public key content](#get-the-gpg-keys-id-and-the-public-key-content) step.
|
135 |
|
136 | [Download and install the GPG command line tools](https://www.gnupg.org/download/#binary) for your operating system.
|
137 |
|
138 | Create a GPG key
|
139 |
|
140 | ```bash
|
141 | $ gpg --full-generate-key
|
142 | ```
|
143 |
|
144 | At the prompt select the `RSA and RSA` king of key, enter `4096` for the keysize, specify how long the key should be valid, enter yout name, the email associated with your Git hosted account and finally set a long and hard to guess passphrase.
|
145 |
|
146 | #### Get the GPG keys ID and the public key content
|
147 |
|
148 | Use the `gpg --list-secret-keys --keyid-format LONG` command to list your GPG keys. From the list, copy the GPG key ID you just created.
|
149 |
|
150 | ```bash
|
151 | $ gpg --list-secret-keys --keyid-format LONG
|
152 | /Users/<user_home>/.gnupg/pubring.gpg
|
153 | ---------------------------------------
|
154 | sec rsa4096/XXXXXXXXXXXXXXXX 2017-12-01 [SC]
|
155 | uid <your_name> <your_email>
|
156 | ssb rsa4096/YYYYYYYYYYYYYYYY 2017-12-01 [E]
|
157 | ```
|
158 | the GPG key ID if 16 character string, on the on the `sec` line, after `rsa4096`. In this example, the GPG key ID is `XXXXXXXXXXXXXXXX`.
|
159 |
|
160 | Export the public key (replace XXXXXXXXXXXXXXXX with your key ID):
|
161 |
|
162 | ```bash
|
163 | $ gpg --armor --export XXXXXXXXXXXXXXXX
|
164 | ```
|
165 |
|
166 | Copy your GPG key, beginning with -----BEGIN PGP PUBLIC KEY BLOCK----- and ending with -----END PGP PUBLIC KEY BLOCK-----
|
167 |
|
168 | #### Add the GPG key to your Git hosted account
|
169 |
|
170 | ##### Add the GPG key to GitHub
|
171 |
|
172 | In GitHub **Settings**, click on **SSH and GPG keys** in the sidebar, then on the **New GPG Key** button.
|
173 |
|
174 | Paste the entire GPG key export previously and click the **Add GPG Key** button.
|
175 |
|
176 | See [Adding a new GPG key to your GitHub account](https://help.github.com/articles/adding-a-new-gpg-key-to-your-github-account/) for more details.
|
177 |
|
178 | ### Use the GPG key to sign commit and tags locally
|
179 |
|
180 | If you want to use this GPG to also sign the commits and tags you create on your local machine you can follow the instruction at [Git Tools - Signing Your Work](https://git-scm.com/book/id/v2/Git-Tools-Signing-Your-Work)
|
181 | This step is optional and unrelated to Semantic-release.
|
182 |
|
183 | #### Add the GPG keys to your CI environment
|
184 |
|
185 | Make the public and private GPG key available on the CI environment. Encrypt the keys, commit it to your repository and configure the CI environment to decrypt it.
|
186 |
|
187 | ##### Add the GPG keys to Travis CI
|
188 |
|
189 | Install the [Travis CLI](https://github.com/travis-ci/travis.rb#installation):
|
190 |
|
191 | ```bash
|
192 | $ gem install travis
|
193 | ```
|
194 |
|
195 | [Login](https://github.com/travis-ci/travis.rb#login) to Travis with the CLI:
|
196 |
|
197 | ```bash
|
198 | $ travis login
|
199 | ```
|
200 |
|
201 | Add the following [environment](https://github.com/travis-ci/travis.rb#env) variables to Travis:
|
202 | - `GPG_PASSPHRASE` to Travis with the value set during the [GPG keys generation](#generate-the-gpg-keys) step
|
203 | - `GPG_KEY_ID` to Travis with the value of your GPG key ID retrieved during the [GPG keys generation](#generate-the-gpg-keys) (replace XXXXXXXXXXXXXXXX with your key ID)
|
204 | - `GIT_EMAIL` with the email address you set during the [GPG keys generation](#generate-the-gpg-keys) step
|
205 | - `GIT_USERNAME` with the name you set during the [GPG keys generation](#generate-the-gpg-keys) step
|
206 |
|
207 | ```bash
|
208 | $ travis env set GPG_PASSPHRASE <gpg_passphrase>
|
209 | $ travis env set GPG_KEY_ID XXXXXXXXXXXXXXXX
|
210 | $ travis env set GIT_EMAIL <your_email>
|
211 | $ travis env set GIT_USERNAME <your_name>
|
212 | ```
|
213 |
|
214 | From your repository root export your public and private GPG keys in the `git_gpg_keys.asc` (replace XXXXXXXXXXXXXXXX with your key ID):
|
215 |
|
216 | ```bash
|
217 | $ gpg --export -a XXXXXXXXXXXXXXXX > git_gpg_keys.asc
|
218 | $ gpg --export-secret-key -a XXXXXXXXXXXXXXXX >> git_gpg_keys.asc
|
219 | ```
|
220 |
|
221 | [Encrypt](https://github.com/travis-ci/travis.rb#encrypt) the `git_gpg_keys.asc` (public and private key) using a symmetric encryption (AES-256), and store the secret in a secure environment variable in the Travis environment:
|
222 |
|
223 | ```bash
|
224 | $ travis encrypt-file git_gpg_keys.asc
|
225 | ```
|
226 | The `travis encrypt-file` will encrypt the keys into the `git_gpg_keys.asc.enc` file and output in the console the command to add to your `.travis.yml` file. It should look like `openssl aes-256-cbc -K $encrypted_AAAAAAAAAAAA_key -iv $encrypted_BBBBBBBBBBBB_iv -in git_gpg_keys.asc.enc -out git_gpg_keys.asc -d`.
|
227 |
|
228 | Copy this command to your `.travis.yml` file in the `before_install` step. Change the output path to write the unencrypted key in `/tmp`: `-out git_gpg_keys.asc` => `/tmp/git_gpg_keys.asc`. This will avoid to commit / modify / delete the unencrypted keys by mistake on the CI. Then add the commands to decrypt the GPG keys and make it available to `git`:
|
229 |
|
230 | ```yaml
|
231 | before_install:
|
232 | # Decrypt the git_gpg_keys.asc.enc key into /tmp/git_gpg_keys.asc
|
233 | - openssl aes-256-cbc -K $encrypted_AAAAAAAAAAAA_key -iv $encrypted_BBBBBBBBBBBB_iv -in git_gpg_keys.asc.enc -out /tmp/git_gpg_keys.asc -d
|
234 | # Make sure only the current user can read the keys
|
235 | - chmod 600 /tmp/git_gpg_keys.asc
|
236 | # Import the gpg key
|
237 | - gpg --batch --yes --import /tmp/git_gpg_keys.asc
|
238 | # Create a script that pass the passphrase to the gpg CLI called by git
|
239 | - echo '/usr/bin/gpg2 --passphrase ${GPG_PASSPHRASE} --batch --no-tty "$@"' > /tmp/gpg-with-passphrase && chmod +x /tmp/gpg-with-passphrase
|
240 | # Configure git to use the script that passes the passphrase
|
241 | - git config gpg.program "/tmp/gpg-with-passphrase"
|
242 | # Configure git to sign the commits and tags
|
243 | - git config commit.gpgsign true
|
244 | # Configure git to use your GPG key
|
245 | - git config --global user.signingkey ${GPG_KEY_ID}
|
246 | ```
|
247 |
|
248 | See [Encrypting Files](https://docs.travis-ci.com/user/encrypting-files/) for more details.
|
249 |
|
250 | Delete the local keys as it won't be used anymore:
|
251 |
|
252 | ```bash
|
253 | $ rm git_gpg_keys.asc
|
254 | ```
|
255 |
|
256 | Commit the encrypted keys and the `.travis.yml` file to your repository:
|
257 |
|
258 | ```bash
|
259 | $ git add git_gpg_keys.asc.enc .travis.yml
|
260 | $ git commit -m "ci(travis): Add the encrypted GPG keys"
|
261 | $ git push
|
262 | ```
|