@semantic-release/github 2.1.0 → 2.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,68 +8,86 @@ Set of [semantic-release](https://github.com/semantic-release/semantic-release)
8
8
 
9
9
  ## verifyConditions
10
10
 
11
- Verify the presence and the validity of the `githubToken` (set via option or environment variable).
11
+ Verify the presence and the validity of the `githubToken` (set via option or environment variable) and the `assets` option configuration.
12
12
 
13
- ### Options
13
+ ## publish
14
14
 
15
- | Option | Description | Default |
16
- | --------------------- | --------------------------------------------------------- | ------------------------------------------------------ |
17
- | `githubToken` | **Required.** The token used to authenticate with GitHub. | `process.env.GH_TOKEN` or `process.env.GITHUB_TOKEN` |
18
- | `githubUrl` | The GitHub Enterprise endpoint. | `process.env.GH_URL` or `process.env.GITHUB_URL` |
19
- | `githubApiPathPrefix` | The GitHub Enterprise API prefix. | `process.env.GH_PREFIX` or `process.env.GITHUB_PREFIX` |
15
+ Publish a [Github release](https://help.github.com/articles/about-releases), optionnaly uploading files.
20
16
 
21
- ## publish
17
+ ## Configuration
18
+
19
+ ### Github Repository authentication
20
+
21
+ The `Github` authentication configuration is **required** and can be set via [environment variables](#environment-variables).
22
+
23
+ Only the [personal token](https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line) authentication is supported.
22
24
 
23
- Publish a [Github release](https://help.github.com/articles/about-releases).
25
+ ### Environment variables
26
+
27
+ | Variable | Description |
28
+ | ------------------------------ | ----------------------------------------------------------|
29
+ | `GH_TOKEN` or `GITHUB_TOKEN` | **Required.** The token used to authenticate with GitHub. |
30
+ | `GH_URL` or `GITHUB_URL` | The GitHub Enterprise endpoint. |
31
+ | `GH_PREFIX` or `GITHUB_PREFIX` | The GitHub Enterprise API prefix. |
24
32
 
25
33
  ### Options
26
34
 
27
- | Option | Description | Default |
28
- | --------------------- | --------------------------------------------------------- | ------------------------------------------------------ |
29
- | `githubToken` | **Required.** The token used to authenticate with GitHub. | `process.env.GH_TOKEN` or `process.env.GITHUB_TOKEN` |
30
- | `githubUrl` | The GitHub Enterprise endpoint. | `process.env.GH_URL` or `process.env.GITHUB_URL` |
31
- | `githubApiPathPrefix` | The GitHub Enterprise API prefix. | `process.env.GH_PREFIX` or `process.env.GITHUB_PREFIX` |
32
- | `assets` | An array of files to upload to the release. | -
35
+ | Option | Description | Default |
36
+ | --------------------- | ------------------------------------------------------------------ | ---------------------------------------------------- |
37
+ | `githubToken` | **Required.** The token used to authenticate with GitHub. | `GH_TOKEN` or `GITHUB_TOKEN` environment variable. |
38
+ | `githubUrl` | The GitHub Enterprise endpoint. | `GH_URL` or `GITHUB_URL` environment variable. |
39
+ | `githubApiPathPrefix` | The GitHub Enterprise API prefix. | `GH_PREFIX` or `GITHUB_PREFIX` environment variable. |
40
+ | `assets` | An array of files to upload to the release. See [assets](#assets). | - |
33
41
 
34
- #### assets option
42
+ #### `assets`
35
43
 
36
- Each element of the array can be a path to the file or an `object` with the properties:
44
+ Can be a [glob](https://github.com/isaacs/node-glob#glob-primer) or and `Array` of [globs](https://github.com/isaacs/node-glob#glob-primer) and `Object`s with the following properties
37
45
 
38
- | Property | Description | Default |
39
- | -------- | ------------------------------------------------------------------------ | ------------------------------------ |
40
- | `path` | **Required.** The file path to upload relative to the project directory. | - |
41
- | `name` | The name of the downloadable file on the Github release. | File name extracted from the `path`. |
42
- | `label` | Short description of the file displayed on the Github release. | - |
46
+ | Property | Description | Default |
47
+ | -------- | -------------------------------------------------------------------------------------------------------- | ------------------------------------ |
48
+ | `path` | **Required.** A [glob](https://github.com/isaacs/node-glob#glob-primer) to identify the files to upload. | - |
49
+ | `name` | The name of the downloadable file on the Github release. | File name extracted from the `path`. |
50
+ | `label` | Short description of the file displayed on the Github release. | - |
43
51
 
44
- ## Configuration
52
+ Each entry in the `assets` `Array` is globbed individually. A [glob](https://github.com/isaacs/node-glob#glob-primer) can be a `String` (`"dist/**/*.js"` or `"dist/mylib.js"`) or an `Array` of `String`s that will be globbed together (`["dist/**", "!**/*.css"]`).
53
+
54
+ If a directory is configured, all the files under this directory and its children will be included.
55
+
56
+ Files can be included enven if they have a match in `.gitignore`.
57
+
58
+ ##### `assets` examples
59
+
60
+ `'dist/*.js'`: include all the `js` files in the `dist` directory, but not in its sub-directories.
61
+
62
+ `[['dist', '!**/*.css']]`: include all the files in the `dist` directory and its sub-directories excluding the `css` files.
63
+
64
+ `[{path: 'dist/MyLibrary.js', label: 'MyLibrary JS distribution'}, {path: 'dist/MyLibrary.css', label: 'MyLibrary CSS distribution'}]`: include the `dist/MyLibrary.js` and `dist/MyLibrary.css` files, and label them `MyLibrary JS distribution` and `MyLibrary CSS distribution` in the Github release.
65
+
66
+ `[['dist/**/*.{js,css}', '!**/*.min.*'], {path: 'build/MyLibrary.zip', label: 'MyLibrary'}]`: include all the `js` and `css` files in the `dist` directory and its sub-directories excluding the minified version, plus the `build/MyLibrary.zip` file and label it `MyLibrary` in the Github release.
67
+
68
+ ### Usage
45
69
 
46
70
  The plugins are used by default by [semantic-release](https://github.com/semantic-release/semantic-release) so no specific configuration is requiered if `githubToken`, `githubUrl` and `githubApiPathPrefix` are set via environment variable.
47
71
 
48
72
  Each individual plugin can be disabled, replaced or used with other plugins in the `package.json`:
73
+
49
74
  ```json
50
75
  {
51
76
  "release": {
52
- "verifyConditions": ["@semantic-release/github", "verify-other-condition"],
53
- "getLastRelease": "custom-get-last-release",
54
- "publish": [
55
- "custom-publish",
56
- {
57
- "path": "@semantic-release/github",
58
- "assets": [
59
- {"path": "dist/asset.min.css", "label": "CSS distribution"},
60
- {"path": "dist/asset.min.js", "label": "JS distribution"}
61
- ]
62
- }
63
- ]
77
+ "verifyConditions": ["@semantic-release/github", "@semantic-release/npm", "verify-other-condition"],
78
+ "getLastRelease": "@semantic-release/npm",
79
+ "publish": ["@semantic-release/npm", "@semantic-release/github", "other-publish"]
64
80
  }
65
81
  }
66
82
  ```
67
83
 
68
- The same configuration for Github Enterprise:
84
+ Options can be set within the plugin definition in the `semantic-release` configuration file:
85
+
69
86
  ```json
70
87
  {
71
88
  "release": {
72
89
  "verifyConditions": [
90
+ "@semantic-release/npm",
73
91
  {
74
92
  "path": "@semantic-release/github",
75
93
  "githubUrl": "https://my-ghe.com",
@@ -77,9 +95,8 @@ The same configuration for Github Enterprise:
77
95
  },
78
96
  "verify-other-condition"
79
97
  ],
80
- "getLastRelease": "custom-get-last-release",
81
98
  "publish": [
82
- "custom-publish",
99
+ "@semantic-release/npm",
83
100
  {
84
101
  "path": "@semantic-release/github",
85
102
  "githubUrl": "https://my-ghe.com",
package/index.js CHANGED
@@ -3,7 +3,7 @@ const publishGithub = require('./lib/publish');
3
3
 
4
4
  let verified;
5
5
 
6
- async function verifyConditions(pluginConfig, {options}) {
6
+ async function verifyConditions(pluginConfig, {options, logger}) {
7
7
  // If the Github publish plugin is used and has `assets` configured, validate it now in order to prevent any release if the configuration is wrong
8
8
  if (options.publish) {
9
9
  const publishPlugin = (Array.isArray(options.publish) ? options.publish : [options.publish]).find(
@@ -14,13 +14,13 @@ async function verifyConditions(pluginConfig, {options}) {
14
14
  }
15
15
  }
16
16
 
17
- await verifyGithub(pluginConfig, options);
17
+ await verifyGithub(pluginConfig, options, logger);
18
18
  verified = true;
19
19
  }
20
20
 
21
21
  async function publish(pluginConfig, {nextRelease, options, logger}) {
22
22
  if (!verified) {
23
- await verifyGithub(pluginConfig, options);
23
+ await verifyGithub(pluginConfig, options, logger);
24
24
  verified = true;
25
25
  }
26
26
  await publishGithub(pluginConfig, options, nextRelease, logger);
@@ -0,0 +1,14 @@
1
+ const url = require('url');
2
+ const GitHubApi = require('github');
3
+
4
+ module.exports = (githubToken, githubUrl, githubApiPathPrefix) => {
5
+ const {port, protocol, hostname} = githubUrl ? url.parse(githubUrl) : {};
6
+ const github = new GitHubApi({
7
+ port,
8
+ protocol: (protocol || '').split(':')[0] || null,
9
+ host: hostname,
10
+ pathPrefix: githubApiPathPrefix,
11
+ });
12
+ github.authenticate({type: 'token', token: githubToken});
13
+ return github;
14
+ };
@@ -0,0 +1,49 @@
1
+ const {basename} = require('path');
2
+ const {isPlainObject, castArray, uniqWith} = require('lodash');
3
+ const pReduce = require('p-reduce');
4
+ const globby = require('globby');
5
+ const debug = require('debug')('semantic-release:github');
6
+
7
+ module.exports = async assets =>
8
+ uniqWith(
9
+ (await pReduce(
10
+ assets,
11
+ async (result, asset) => {
12
+ // Wrap single glob definition in Array
13
+ const glob = castArray(isPlainObject(asset) ? asset.path : asset);
14
+ // Skip solo negated pattern (avoid to include every non js file with `!**/*.js`)
15
+ if (glob.length <= 1 && glob[0].startsWith('!')) {
16
+ debug(
17
+ 'skipping the negated glob %o as its alone in its group and would retrieve a large amount of files ',
18
+ glob[0]
19
+ );
20
+ return result;
21
+ }
22
+ const globbed = await globby(glob, {expandDirectories: true, gitignore: false, dot: true});
23
+ if (isPlainObject(asset)) {
24
+ if (globbed.length > 1) {
25
+ // If asset is an Object with a glob the `path` property that resolve to multiple files,
26
+ // Output an Object definition for each file matched and set each one with:
27
+ // - `path` of the matched file
28
+ // - `name` based on the actual file name (to avoid assets with duplicate `name`)
29
+ // - other properties of the original asset definition
30
+ return [...result, ...globbed.map(file => Object.assign({}, asset, {path: file, name: basename(file)}))];
31
+ }
32
+ // If asset is an Object, output an Object definition with:
33
+ // - `path` of the matched file if there is one, or the original `path` definition (will be considered as a missing file)
34
+ // - other properties of the original asset definition
35
+ return [...result, Object.assign({}, asset, {path: globbed[0] || asset.path})];
36
+ }
37
+ if (globbed.length > 0) {
38
+ // If asset is a String definition, output each files matched
39
+ return [...result, ...globbed];
40
+ }
41
+ // If asset is a String definition but no match is found, output the elements of the original glob (each one will be considered as a missing file)
42
+ return [...result, ...glob];
43
+ },
44
+ []
45
+ // Sort with Object first, to prioritize Object definition over Strings in dedup
46
+ )).sort(asset => !isPlainObject(asset)),
47
+ // Compare `path` property if Object definition, value itself if String
48
+ (a, b) => (isPlainObject(a) ? a.path : a) === (isPlainObject(b) ? b.path : b)
49
+ );
package/lib/publish.js CHANGED
@@ -1,48 +1,51 @@
1
- const {basename} = require('path');
2
- const {parse} = require('url');
3
- const {stat} = require('fs-extra');
1
+ const {basename, extname} = require('path');
2
+ const {stat, readFile} = require('fs-extra');
3
+ const {isPlainObject} = require('lodash');
4
4
  const parseGithubUrl = require('parse-github-url');
5
- const GitHubApi = require('github');
6
- const pEachSeries = require('p-each-series');
7
- const debug = require('debug')('semantic-release:publish-github');
5
+ const pReduce = require('p-reduce');
6
+ const mime = require('mime');
7
+ const debug = require('debug')('semantic-release:github');
8
+ const globAssets = require('./glob-assets.js');
8
9
  const resolveConfig = require('./resolve-config');
10
+ const getClient = require('./get-client');
9
11
 
10
12
  module.exports = async (pluginConfig, {branch, repositoryUrl}, {version, gitHead, gitTag, notes}, logger) => {
11
13
  const {githubToken, githubUrl, githubApiPathPrefix, assets} = resolveConfig(pluginConfig);
12
14
  const {name: repo, owner} = parseGithubUrl(repositoryUrl);
13
- let {port, protocol, hostname: host} = githubUrl ? parse(githubUrl) : {};
14
- protocol = (protocol || '').split(':')[0] || null;
15
-
16
- const github = new GitHubApi({port, protocol, host, pathPrefix: githubApiPathPrefix});
17
- github.authenticate({type: 'token', token: githubToken});
18
-
15
+ const github = getClient(githubToken, githubUrl, githubApiPathPrefix);
19
16
  const release = {owner, repo, tag_name: gitTag, name: gitTag, target_commitish: branch, body: notes}; // eslint-disable-line camelcase
17
+
20
18
  debug('release owner: %o', owner);
21
19
  debug('release repo: %o', repo);
22
20
  debug('release name: %o', gitTag);
23
21
  debug('release branch: %o', branch);
22
+
24
23
  const ref = `refs/tags/${gitTag}`;
25
24
 
26
25
  try {
27
26
  // Test if the tag already exists
28
27
  await github.gitdata.getReference({owner, repo, ref: `tags/${gitTag}`});
28
+ debug('The git tag %o already exists', gitTag);
29
29
  } catch (err) {
30
30
  // If the error is 404, the tag doesn't exist, otherwise it's an error
31
31
  if (err.code !== 404) {
32
32
  throw err;
33
33
  }
34
- debug('Create git tag %o with commit %o', ref, gitHead);
34
+ debug('Create git tag %o with commit %o', gitTag, gitHead);
35
35
  await github.gitdata.createReference({owner, repo, ref, sha: gitHead});
36
36
  }
37
37
 
38
- const {data: {id, html_url}} = await github.repos.createRelease(release); // eslint-disable-line camelcase
39
- logger.log('Published Github release: %s', html_url);
38
+ const {data: {html_url: htmlUrl, upload_url: uploadUrl}} = await github.repos.createRelease(release);
39
+ logger.log('Published Github release: %s', htmlUrl);
40
40
 
41
41
  if (assets && assets.length > 0) {
42
+ const globbedAssets = await globAssets(assets);
43
+ debug('globed assets: %o', globbedAssets);
42
44
  // Make requests serially to avoid hitting the rate limit (https://developer.github.com/v3/guides/best-practices-for-integrators/#dealing-with-abuse-rate-limits)
43
- await pEachSeries(assets, async asset => {
44
- const filePath = typeof asset === 'object' ? asset.path : asset;
45
+ await pReduce(globbedAssets, async (_, asset) => {
46
+ const filePath = isPlainObject(asset) ? asset.path : asset;
45
47
  let file;
48
+
46
49
  try {
47
50
  file = await stat(filePath);
48
51
  } catch (err) {
@@ -53,16 +56,27 @@ module.exports = async (pluginConfig, {branch, repositoryUrl}, {version, gitHead
53
56
  logger.error('The asset %s is not a file, and will be ignored.', filePath);
54
57
  return;
55
58
  }
59
+
56
60
  const fileName = asset.name || basename(filePath);
57
- const upload = {owner, repo, id, filePath, name: fileName};
61
+ const upload = {
62
+ owner,
63
+ repo,
64
+ url: uploadUrl,
65
+ file: await readFile(filePath),
66
+ contentType: mime.getType(extname(fileName)) || 'text/plain',
67
+ contentLength: file.size,
68
+ name: fileName,
69
+ };
70
+
58
71
  debug('file path: %o', filePath);
59
72
  debug('file name: %o', fileName);
60
- if (asset.label) {
73
+
74
+ if (isPlainObject(asset) && asset.label) {
61
75
  upload.label = asset.label;
62
76
  }
63
77
 
64
- const {data: {browser_download_url}} = await github.repos.uploadAsset(upload); // eslint-disable-line camelcase
65
- logger.log('Published file %s', browser_download_url);
78
+ const {data: {browser_download_url: downloadUrl}} = await github.repos.uploadAsset(upload);
79
+ logger.log('Published file %s', downloadUrl);
66
80
  });
67
81
  }
68
82
  };
@@ -1,6 +1,8 @@
1
+ const {castArray} = require('lodash');
2
+
1
3
  module.exports = ({githubToken, githubUrl, githubApiPathPrefix, assets}) => ({
2
4
  githubToken: githubToken || process.env.GH_TOKEN || process.env.GITHUB_TOKEN,
3
5
  githubUrl: githubUrl || process.env.GH_URL || process.env.GITHUB_URL,
4
6
  githubApiPathPrefix: githubApiPathPrefix || process.env.GH_PREFIX || process.env.GITHUB_PREFIX,
5
- assets: assets ? (Array.isArray(assets) ? assets : [assets]) : assets,
7
+ assets: assets ? castArray(assets) : assets,
6
8
  });
package/lib/verify.js CHANGED
@@ -1,24 +1,29 @@
1
- const {parse} = require('url');
1
+ const {isString, isPlainObject, isUndefined, isArray} = require('lodash');
2
2
  const parseGithubUrl = require('parse-github-url');
3
- const GitHubApi = require('github');
3
+ const urlJoin = require('url-join');
4
4
  const SemanticReleaseError = require('@semantic-release/error');
5
5
  const resolveConfig = require('./resolve-config');
6
+ const getClient = require('./get-client');
6
7
 
7
- module.exports = async (pluginConfig, {repositoryUrl}) => {
8
+ module.exports = async (pluginConfig, {repositoryUrl}, logger) => {
8
9
  const {githubToken, githubUrl, githubApiPathPrefix, assets} = resolveConfig(pluginConfig);
9
10
 
10
11
  if (!githubToken) {
11
12
  throw new SemanticReleaseError('No github token specified.', 'ENOGHTOKEN');
12
13
  }
13
14
 
14
- if (assets && assets.length > 0) {
15
- // Verify that every asset is either a string or an object with path attribute defined
16
- if (!assets.every(asset => typeof asset === 'string' || (typeof asset === 'object' && Boolean(asset.path)))) {
17
- throw new SemanticReleaseError(
18
- 'The "assets" options must be an Array of strings or objects with a path property.',
19
- 'EINVALIDASSETS'
20
- );
21
- }
15
+ if (
16
+ !isUndefined(assets) &&
17
+ assets !== false &&
18
+ !(
19
+ isArray(assets) &&
20
+ assets.every(asset => isStringOrStringArray(asset) || (isPlainObject(asset) && isStringOrStringArray(asset.path)))
21
+ )
22
+ ) {
23
+ throw new SemanticReleaseError(
24
+ 'The "assets" options must be an Array of Strings or Objects with a path property.',
25
+ 'EINVALIDASSETS'
26
+ );
22
27
  }
23
28
 
24
29
  const {name: repo, owner} = parseGithubUrl(repositoryUrl);
@@ -29,13 +34,15 @@ module.exports = async (pluginConfig, {repositoryUrl}) => {
29
34
  );
30
35
  }
31
36
 
32
- let {port, protocol, hostname: host} = githubUrl ? parse(githubUrl) : {};
33
- protocol = (protocol || '').split(':')[0] || null;
34
-
35
- const github = new GitHubApi({port, protocol, host, pathPrefix: githubApiPathPrefix});
36
- github.authenticate({type: 'token', token: githubToken});
37
+ if (githubUrl) {
38
+ logger.log('Verify Github authentication (%s)', urlJoin(githubUrl, githubApiPathPrefix));
39
+ } else {
40
+ logger.log('Verify Github authentication');
41
+ }
37
42
 
43
+ const github = getClient(githubToken, githubUrl, githubApiPathPrefix);
38
44
  let push;
45
+
39
46
  try {
40
47
  ({data: {permissions: {push}}} = await github.repos.get({repo, owner}));
41
48
  } catch (err) {
@@ -53,3 +60,7 @@ module.exports = async (pluginConfig, {repositoryUrl}) => {
53
60
  );
54
61
  }
55
62
  };
63
+
64
+ function isStringOrStringArray(value) {
65
+ return isString(value) || (isArray(value) && value.every(isString));
66
+ }
package/package.json CHANGED
@@ -1 +1 @@
1
- {"name":"@semantic-release/github","description":"Set of semantic-release plugins for publishing a Github release","version":"2.1.0","author":"Pierre Vanduynslager (https://twitter.com/@pvdlg_)","bugs":{"url":"https://github.com/semantic-release/github/issues"},"config":{"commitizen":{"path":"cz-conventional-changelog"}},"contributors":["Stephan Bönnemann <stephan@boennemann.me> (http://boennemann.me)","Gregor Martynus (https://twitter.com/gr2m)"],"dependencies":{"@semantic-release/error":"^2.1.0","debug":"^3.1.0","fs-extra":"^4.0.2","github":"^12.0.5","p-each-series":"^1.0.0","parse-github-url":"^1.0.1"},"devDependencies":{"ava":"^0.24.0","clear-module":"^2.1.0","codecov":"^3.0.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint-config-prettier":"^2.8.0","eslint-plugin-prettier":"^2.3.0","nock":"^9.1.0","nyc":"^11.2.1","prettier":"~1.8.2","semantic-release":"^10.0.0","sinon":"^4.0.0","xo":"^0.18.2"},"engines":{"node":">=4"},"files":["lib","index.js"],"homepage":"https://github.com/semantic-release/github#readme","keywords":["git","github","publish","release","semantic-release","version"],"license":"MIT","main":"index.js","nyc":{"include":["lib/**/*.js","index.js"],"reporter":["json","text","html"],"all":true},"prettier":{"printWidth":120,"singleQuote":true,"bracketSpacing":false,"trailingComma":"es5"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"https://github.com/semantic-release/github.git"},"scripts":{"cm":"git-cz","codecov":"codecov -f coverage/coverage-final.json","lint":"xo","pretest":"npm run lint","semantic-release":"semantic-release","test":"nyc ava -v"},"xo":{"extends":["prettier"],"plugins":["prettier"],"rules":{"prettier/prettier":2}}}
1
+ {"name":"@semantic-release/github","description":"Set of semantic-release plugins for publishing a Github release","version":"2.2.3","author":"Pierre Vanduynslager (https://twitter.com/@pvdlg_)","bugs":{"url":"https://github.com/semantic-release/github/issues"},"config":{"commitizen":{"path":"cz-conventional-changelog"}},"contributors":["Stephan Bönnemann <stephan@boennemann.me> (http://boennemann.me)","Gregor Martynus (https://twitter.com/gr2m)"],"dependencies":{"@semantic-release/error":"^2.1.0","debug":"^3.1.0","fs-extra":"^5.0.0","github":"^13.0.0","globby":"^7.1.1","lodash":"^4.17.4","mime":"^2.0.3","p-reduce":"^1.0.0","parse-github-url":"^1.0.1","url-join":"^2.0.2"},"devDependencies":{"ava":"^0.24.0","clear-module":"^2.1.0","codecov":"^3.0.0","commitizen":"^2.9.6","cz-conventional-changelog":"^2.0.0","eslint-config-prettier":"^2.8.0","eslint-plugin-prettier":"^2.3.0","nock":"^9.1.0","nyc":"^11.2.1","prettier":"~1.9.2","semantic-release":"^10.0.0","sinon":"^4.0.0","tempy":"^0.2.1","xo":"^0.18.2"},"engines":{"node":">=4"},"files":["lib","index.js"],"homepage":"https://github.com/semantic-release/github#readme","keywords":["git","github","publish","release","semantic-release","version"],"license":"MIT","main":"index.js","nyc":{"include":["lib/**/*.js","index.js"],"reporter":["json","text","html"],"all":true},"prettier":{"printWidth":120,"singleQuote":true,"bracketSpacing":false,"trailingComma":"es5"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"https://github.com/semantic-release/github.git"},"scripts":{"cm":"git-cz","codecov":"codecov -f coverage/coverage-final.json","lint":"xo","pretest":"npm run lint","semantic-release":"semantic-release","test":"nyc ava -v"},"xo":{"extends":["prettier"],"plugins":["prettier"],"rules":{"prettier/prettier":2}}}