forked from semantic-release/gitlab
/
publish.js
126 lines (104 loc) · 3.99 KB
/
publish.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
const {createReadStream} = require('fs');
const {resolve} = require('path');
const {stat} = require('fs-extra');
const {isPlainObject, template} = require('lodash');
const FormData = require('form-data');
const urlJoin = require('url-join');
const got = require('got');
const debug = require('debug')('semantic-release:gitlab');
const resolveConfig = require('./resolve-config');
const getRepoId = require('./get-repo-id');
const getAssets = require('./glob-assets');
const {RELEASE_NAME} = require('./definitions/constants');
module.exports = async (pluginConfig, context) => {
const {
cwd,
options: {repositoryUrl},
nextRelease: {gitTag, gitHead, notes},
logger,
} = context;
const {gitlabToken, gitlabUrl, gitlabApiUrl, assets, milestones, proxy} = resolveConfig(pluginConfig, context);
const assetsList = [];
const repoId = getRepoId(context, gitlabUrl, repositoryUrl);
const encodedRepoId = encodeURIComponent(repoId);
const encodedGitTag = encodeURIComponent(gitTag);
const apiOptions = {headers: {'PRIVATE-TOKEN': gitlabToken}};
debug('repoId: %o', repoId);
debug('release name: %o', gitTag);
debug('release ref: %o', gitHead);
debug('milestones: %o', milestones);
if (assets && assets.length > 0) {
const globbedAssets = await getAssets(context, assets);
debug('globbed assets: %o', globbedAssets);
await Promise.all(
globbedAssets.map(async asset => {
const {path, type, filepath} = isPlainObject(asset) ? asset : {path: asset};
const file = resolve(cwd, path);
const label = asset.label ? template(asset.label)(context) : undefined;
let fileStat;
try {
fileStat = await stat(file);
} catch (_) {
logger.error('The asset %s cannot be read, and will be ignored.', path);
return;
}
if (!fileStat || !fileStat.isFile()) {
logger.error('The asset %s is not a file, and will be ignored.', path);
return;
}
debug('file path: %o', path);
debug('file label: %o', label);
debug('file type: %o', type);
debug('file filepath: %o', filepath);
// Uploaded assets to the project
const form = new FormData();
form.append('file', createReadStream(file));
const uploadEndpoint = urlJoin(gitlabApiUrl, `/projects/${encodedRepoId}/uploads`);
debug('POST-ing the file %s to %s', file, uploadEndpoint);
let response;
try {
response = await got.post(uploadEndpoint, {...apiOptions, ...proxy, body: form}).json();
} catch (error) {
logger.error('An error occurred while uploading %s to the GitLab project uploads API:\n%O', file, error);
throw error;
}
const {url, alt} = response;
assetsList.push({label, alt, url, type, filepath});
logger.log('Uploaded file: %s', url);
})
);
}
debug('Create a release for git tag %o with commit %o', gitTag, gitHead);
const createReleaseEndpoint = urlJoin(gitlabApiUrl, `/projects/${encodedRepoId}/releases`);
const json = {
/* eslint-disable camelcase */
tag_name: gitTag,
description: notes && notes.trim() ? notes : gitTag,
milestones,
assets: {
links: assetsList.map(({label, alt, url, type, filepath}) => {
return {
name: label || alt,
url: urlJoin(gitlabUrl, repoId, url),
link_type: type,
filepath,
};
}),
},
/* eslint-enable camelcase */
};
debug('POST-ing the following JSON to %s:\n%s', createReleaseEndpoint, JSON.stringify(json, null, 2));
try {
await got.post(createReleaseEndpoint, {
...apiOptions,
...proxy,
json,
});
} catch (error) {
logger.error('An error occurred while making a request to the GitLab release API:\n%O', error);
throw error;
}
logger.log('Published GitLab release: %s', gitTag);
const releaseUrl = urlJoin(gitlabUrl, repoId, `/-/releases/${encodedGitTag}`);
return {name: RELEASE_NAME, url: releaseUrl};
};