UNPKG

vrrv-installer-builder

Version:

A complete solution to package and build a ready for distribution Electron app for MacOS, Windows and Linux with “auto update” support out of the box

157 lines (155 loc) 7.64 kB
"use strict"; const util_1 = require("../util/util"); const log_1 = require("../util/log"); const util_2 = require("../util/util"); const path_1 = require("path"); const url_1 = require("url"); const mime = require("mime"); const fs_extra_p_1 = require("fs-extra-p"); const restApiRequest_1 = require("./restApiRequest"); const bluebird_1 = require("bluebird"); const uploader_1 = require("./uploader"); //noinspection JSUnusedLocalSymbols const __awaiter = require("../util/awaiter"); class GitHubPublisher { constructor(owner, repo, version, options) { let isPublishOptionGuessed = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : false; let config = arguments[5]; this.owner = owner; this.repo = repo; this.version = version; this.options = options; this.isPublishOptionGuessed = isPublishOptionGuessed; if (util_1.isEmptyOrSpaces(options.githubToken)) { throw new Error("GitHub Personal Access Token is not specified"); } this.token = options.githubToken; this.policy = options.publish || "always"; if (version.startsWith("v")) { throw new Error(`Version must not starts with "v": ${ version }`); } this.tag = config != null && config.vPrefixedTagName === false ? version : `v${ version }`; this._releasePromise = this.token === "__test__" ? bluebird_1.Promise.resolve(null) : this.init(); } get releasePromise() { return this._releasePromise; } init() { return __awaiter(this, void 0, void 0, function* () { const createReleaseIfNotExists = this.policy !== "onTagOrDraft"; // we don't use "Get a release by tag name" because "tag name" means existing git tag, but we draft release and don't create git tag const releases = yield restApiRequest_1.githubRequest(`/repos/${ this.owner }/${ this.repo }/releases`, this.token); for (let release of releases) { if (release.tag_name === this.tag || release.tag_name === this.version) { if (release.draft) { return release; } if (!this.isPublishOptionGuessed && this.policy === "onTag") { throw new Error(`Release with tag ${ this.tag } must be a draft`); } const message = `Release with tag ${ this.tag } is not a draft, artifacts will be not published`; if (this.isPublishOptionGuessed || this.policy === "onTagOrDraft") { log_1.log(message); } else { log_1.warn(message); } return null; } } if (createReleaseIfNotExists) { log_1.log(`Release with tag ${ this.tag } doesn't exist, creating one`); return this.createRelease(); } else { log_1.log(`Release with tag ${ this.tag } doesn't exist, artifacts will be not published`); return null; } }); } upload(file, artifactName) { return __awaiter(this, void 0, void 0, function* () { const fileName = artifactName || path_1.basename(file); const release = yield this.releasePromise; if (release == null) { util_2.debug(`Release with tag ${ this.tag } doesn't exist and is not created, artifact ${ fileName } is not published`); return; } const parsedUrl = url_1.parse(release.upload_url.substring(0, release.upload_url.indexOf("{")) + "?name=" + fileName); const fileStat = yield fs_extra_p_1.stat(file); let badGatewayCount = 0; uploadAttempt: for (let i = 0; i < 3; i++) { try { return yield restApiRequest_1.doApiRequest({ hostname: parsedUrl.hostname, path: parsedUrl.path, method: "POST", headers: { Accept: "application/vnd.github.v3+json", "User-Agent": "electron-builder", "Content-Type": mime.lookup(fileName), "Content-Length": fileStat.size } }, this.token, uploader_1.uploadFile.bind(this, file, fileStat, fileName)); } catch (e) { if (e instanceof restApiRequest_1.HttpError) { if (e.response.statusCode === 422 && e.description != null && e.description.errors != null && e.description.errors[0].code === "already_exists") { // delete old artifact and re-upload log_1.log(`Artifact ${ fileName } already exists, overwrite one`); const assets = yield restApiRequest_1.githubRequest(`/repos/${ this.owner }/${ this.repo }/releases/${ release.id }/assets`, this.token); for (let asset of assets) { if (asset.name === fileName) { yield restApiRequest_1.githubRequest(`/repos/${ this.owner }/${ this.repo }/releases/assets/${ asset.id }`, this.token, null, "DELETE"); continue uploadAttempt; } } log_1.log(`Artifact ${ fileName } not found, trying to upload again`); continue; } else if (e.response.statusCode === 502 && badGatewayCount++ < 3) { continue; } } throw e; } } }); } createRelease() { return restApiRequest_1.githubRequest(`/repos/${ this.owner }/${ this.repo }/releases`, this.token, { tag_name: this.tag, name: this.version, draft: this.options.draft == null || this.options.draft, prerelease: this.options.prerelease != null && this.options.prerelease }); } // test only //noinspection JSUnusedGlobalSymbols getRelease() { return __awaiter(this, void 0, void 0, function* () { return restApiRequest_1.githubRequest(`/repos/${ this.owner }/${ this.repo }/releases/${ this._releasePromise.value().id }`, this.token); }); } //noinspection JSUnusedGlobalSymbols deleteRelease() { return __awaiter(this, void 0, void 0, function* () { if (!this._releasePromise.isFulfilled()) { return; } const release = this._releasePromise.value(); if (release == null) { return; } for (let i = 0; i < 3; i++) { try { return yield restApiRequest_1.githubRequest(`/repos/${ this.owner }/${ this.repo }/releases/${ release.id }`, this.token, null, "DELETE"); } catch (e) { if (e instanceof restApiRequest_1.HttpError && (e.response.statusCode === 405 || e.response.statusCode === 502)) { continue; } throw e; } } log_1.warn(`Cannot delete release ${ release.id }`); }); } } exports.GitHubPublisher = GitHubPublisher; //# sourceMappingURL=gitHubPublisher.js.map