1 | const {basename, extname, resolve} = require('path');
|
2 | const {stat, readFile} = require('fs-extra');
|
3 | const {isPlainObject} = require('lodash');
|
4 | const parseGithubUrl = require('parse-github-url');
|
5 | const mime = require('mime');
|
6 | const debug = require('debug')('semantic-release:github');
|
7 | const globAssets = require('./glob-assets.js');
|
8 | const resolveConfig = require('./resolve-config');
|
9 | const getClient = require('./get-client');
|
10 |
|
11 | module.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 |
|
23 | const releaseData = {
|
24 | owner,
|
25 | repo,
|
26 | tag_name: gitTag,
|
27 | name: gitTag,
|
28 | target_commitish: branch,
|
29 | body: notes,
|
30 | };
|
31 |
|
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 |
|
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 |
|
49 |
|
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 |
|
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 |
|
103 | const release = {
|
104 | owner,
|
105 | repo,
|
106 | release_id: releaseId,
|
107 | draft: false,
|
108 | };
|
109 |
|
110 |
|
111 | await github.repos.updateRelease(release);
|
112 |
|
113 | logger.log('Published GitHub release: %s', url);
|
114 | return {url, name: 'GitHub release'};
|
115 | };
|