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