/
PublisherGithub.ts
111 lines (97 loc) · 3.81 KB
/
PublisherGithub.ts
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
import PublisherBase, { PublisherOptions } from '@electron-forge/publisher-base';
import { asyncOra } from '@electron-forge/async-ora';
import fs from 'fs-extra';
import mime from 'mime-types';
import path from 'path';
import GitHub from './util/github';
import { PublisherGitHubConfig } from './Config';
import { ForgeMakeResult } from '@electron-forge/shared-types';
interface GitHubRelease {
tag_name: string;
assets: {
name: string;
}[];
upload_url: string;
}
export default class PublisherGithub extends PublisherBase<PublisherGitHubConfig> {
name = 'github';
async publish({ makeResults }: PublisherOptions) {
const { config } = this;
const perReleaseArtifacts: {
[release: string]: ForgeMakeResult[];
} = {};
for (const makeResult of makeResults) {
const release = makeResult.packageJSON.version;
if (!perReleaseArtifacts[release]) {
perReleaseArtifacts[release] = [];
}
perReleaseArtifacts[release].push(makeResult);
}
if (!(config.repository && typeof config.repository === 'object' &&
config.repository.owner && config.repository.name)) {
throw 'In order to publish to github you must set the "github_repository.owner" and "github_repository.name" properties in your forge config. See the docs for more info'; // eslint-disable-line
}
const github = new GitHub(config.authToken, true, config.octokitOptions);
for (const releaseName of Object.keys(perReleaseArtifacts)) {
let release: GitHubRelease;
const artifacts = perReleaseArtifacts[releaseName];
await asyncOra(`Searching for target release: ${releaseName}`, async () => {
try {
release = (await github.getGitHub().repos.getReleases({
owner: config.repository.owner,
repo: config.repository.name,
per_page: 100,
})).data.find((testRelease: GitHubRelease) => testRelease.tag_name === `v${releaseName}`);
if (!release) {
throw { code: 404 };
}
} catch (err) {
if (err.code === 404) {
// Release does not exist, let's make it
release = (await github.getGitHub().repos.createRelease({
owner: config.repository.owner,
repo: config.repository.name,
tag_name: `v${releaseName}`,
name: `v${releaseName}`,
draft: config.draft !== false,
prerelease: config.prerelease === true,
})).data;
} else {
// Unknown error
throw err;
}
}
});
let uploaded = 0;
await asyncOra(`Uploading Artifacts ${uploaded}/${artifacts.length} to v${releaseName}`, async (uploadSpinner) => {
const updateSpinner = () => {
uploadSpinner.text = `Uploading Artifacts ${uploaded}/${artifacts.length} to v${releaseName}`; // eslint-disable-line
};
const flatArtifacts: string[] = [];
for (const artifact of artifacts) {
flatArtifacts.push(...artifact.artifacts);
}
await Promise.all(flatArtifacts.map(artifactPath =>
new Promise(async (resolve) => {
const done = () => {
uploaded += 1;
updateSpinner();
resolve();
};
if (release.assets.find(asset => asset.name === path.basename(artifactPath))) {
return done();
}
await github.getGitHub().repos.uploadAsset({
url: release.upload_url,
file: fs.createReadStream(artifactPath),
contentType: mime.lookup(artifactPath) || 'application/octet-stream',
contentLength: (await fs.stat(artifactPath)).size,
name: path.basename(artifactPath),
});
return done();
}),
));
});
}
}
}