UNPKG

3.45 kBJavaScriptView Raw
1const {basename, extname, resolve} = require('path');
2const {stat, readFile} = require('fs-extra');
3const {isPlainObject} = require('lodash');
4const parseGithubUrl = require('parse-github-url');
5const mime = require('mime');
6const debug = require('debug')('semantic-release:github');
7const globAssets = require('./glob-assets.js');
8const resolveConfig = require('./resolve-config');
9const getClient = require('./get-client');
10
11module.exports = async (pluginConfig, context) => {
12 const {
13 cwd,
14 options: {branch, repositoryUrl},
15 nextRelease: {gitTag, notes},
16 logger,
17 } = context;
18 const {githubToken, githubUrl, githubApiPathPrefix, proxy, assets} = resolveConfig(pluginConfig, context);
19 const {name: repo, owner} = parseGithubUrl(repositoryUrl);
20 const github = getClient({githubToken, githubUrl, githubApiPathPrefix, proxy});
21
22 /* eslint-disable camelcase */
23 const releaseData = {
24 owner,
25 repo,
26 tag_name: gitTag,
27 name: gitTag,
28 target_commitish: branch,
29 body: notes,
30 };
31 /* eslint-enable */
32
33 debug('release owner: %o', owner);
34 debug('release repo: %o', repo);
35 debug('release name: %o', gitTag);
36 debug('release branch: %o', branch);
37
38 // When there are no assets, we publish a release directly
39 if (!assets || assets.length === 0) {
40 const {
41 data: {html_url: url},
42 } = await github.repos.createRelease(releaseData);
43
44 logger.log('Published GitHub release: %s', url);
45 return {url, name: 'GitHub release'};
46 }
47
48 // We'll create a draft release, append the assets to it, and then publish it.
49 // This is so that the assets are available when we get a Github release event.
50 const draftRelease = {...releaseData, draft: true};
51
52 const {
53 data: {html_url: url, upload_url: uploadUrl, id: releaseId},
54 } = await github.repos.createRelease(draftRelease);
55
56 // Append assets to the release
57 const globbedAssets = await globAssets(context, assets);
58 debug('globed assets: %o', globbedAssets);
59
60 await Promise.all(
61 globbedAssets.map(async asset => {
62 const filePath = isPlainObject(asset) ? asset.path : asset;
63 let file;
64
65 try {
66 file = await stat(resolve(cwd, filePath));
67 } catch (error) {
68 logger.error('The asset %s cannot be read, and will be ignored.', filePath);
69 return;
70 }
71
72 if (!file || !file.isFile()) {
73 logger.error('The asset %s is not a file, and will be ignored.', filePath);
74 return;
75 }
76
77 const fileName = asset.name || basename(filePath);
78 const upload = {
79 url: uploadUrl,
80 file: await readFile(resolve(cwd, filePath)),
81 name: fileName,
82 headers: {
83 'content-type': mime.getType(extname(fileName)) || 'text/plain',
84 'content-length': file.size,
85 },
86 };
87
88 debug('file path: %o', filePath);
89 debug('file name: %o', fileName);
90
91 if (isPlainObject(asset) && asset.label) {
92 upload.label = asset.label;
93 }
94
95 const {
96 data: {browser_download_url: downloadUrl},
97 } = await github.repos.uploadReleaseAsset(upload);
98 logger.log('Published file %s', downloadUrl);
99 })
100 );
101
102 /* eslint-disable camelcase */
103 const release = {
104 owner,
105 repo,
106 release_id: releaseId,
107 draft: false,
108 };
109 /* eslint-enable */
110
111 await github.repos.updateRelease(release);
112
113 logger.log('Published GitHub release: %s', url);
114 return {url, name: 'GitHub release'};
115};