Skip to content

Commit e5b0c04

Browse files
committed
feat: Add Ability to Create Pre-Releases and Releases
Closes #446
1 parent f1eaab8 commit e5b0c04

File tree

6 files changed

+73
-16
lines changed

6 files changed

+73
-16
lines changed

.idea/runConfigurations/ArtifactPublisherTest.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/builder.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { Platform, Arch, archFromString } from "./metadata"
1010
//noinspection JSUnusedLocalSymbols
1111
const __awaiter = require("./awaiter")
1212

13-
export async function createPublisher(packager: Packager, options: BuildOptions, repoSlug: InfoRetriever, isPublishOptionGuessed: boolean = false): Promise<Publisher | null> {
13+
export async function createPublisher(packager: Packager, options: PublishOptions, repoSlug: InfoRetriever, isPublishOptionGuessed: boolean = false): Promise<Publisher | null> {
1414
const info = await repoSlug.getInfo(packager)
1515
if (info == null) {
1616
if (isPublishOptionGuessed) {
@@ -22,7 +22,7 @@ export async function createPublisher(packager: Packager, options: BuildOptions,
2222
}
2323
else {
2424
log(`Creating Github Publisher — user: ${info.user}, project: ${info.project}, version: ${packager.metadata.version}`)
25-
return new GitHubPublisher(info.user, info.project, packager.metadata.version, options.githubToken!, options.publish!)
25+
return new GitHubPublisher(info.user, info.project, packager.metadata.version, options, options.publish!)
2626
}
2727
}
2828

@@ -187,6 +187,13 @@ export async function build(rawOptions?: CliOptions): Promise<void> {
187187
options.githubToken = process.env.GH_TOKEN
188188
}
189189

190+
if (options.draft === undefined && !isEmptyOrSpaces(process.env.EP_DRAFT)) {
191+
options.draft = process.env.EP_DRAFT.toLowerCase() === "true"
192+
}
193+
if (options.prerelease === undefined && !isEmptyOrSpaces(process.env.EP_PRELEASE)) {
194+
options.prerelease = process.env.EP_PRELEASE.toLowerCase() === "true"
195+
}
196+
190197
let isPublishOptionGuessed = false
191198
if (options.publish === undefined) {
192199
if (process.env.npm_lifecycle_event === "release") {

src/cliOptions.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ export function createYargs(): any {
3131
describe: `Publish artifacts (to GitHub Releases), see ${underline("https://goo.gl/WMlr4n")}`,
3232
choices: ["onTag", "onTagOrDraft", "always", "never"],
3333
})
34+
.option("draft", {
35+
describe: "Create a draft (unpublished) release",
36+
type: "boolean",
37+
default: undefined,
38+
})
39+
.option("prerelease", {
40+
describe: "Identify the release as a prerelease",
41+
type: "boolean",
42+
default: undefined,
43+
})
3444
.option("platform", {
3545
describe: "The target platform (preferred to use --osx, --win or --linux)",
3646
choices: ["osx", "win", "linux", "darwin", "win32", "all"],

src/gitHubPublisher.ts

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Release, Asset } from "gh-release"
2-
import { log, warn } from "./util"
2+
import { log, warn, isEmptyOrSpaces } from "./util"
33
import { basename } from "path"
44
import { parse as parseUrl } from "url"
55
import * as mime from "mime"
@@ -21,21 +21,28 @@ export interface Publisher {
2121
export interface PublishOptions {
2222
publish?: "onTag" | "onTagOrDraft" | "always" | "never" | null
2323
githubToken?: string | null
24+
25+
draft?: boolean
26+
prerelease?: boolean
2427
}
2528

2629
export class GitHubPublisher implements Publisher {
2730
private tag: string
2831
private _releasePromise: BluebirdPromise<Release>
2932

33+
private readonly token: string
34+
3035
get releasePromise(): Promise<Release | null> {
3136
return this._releasePromise
3237
}
3338

34-
constructor(private owner: string, private repo: string, version: string, private token: string | null, private policy: string = "always") {
35-
if (token == null || token.length === 0) {
39+
constructor(private owner: string, private repo: string, version: string, private options: PublishOptions, private policy: string = "always") {
40+
if (isEmptyOrSpaces(options.githubToken)) {
3641
throw new Error("GitHub Personal Access Token is not specified")
3742
}
3843

44+
this.token = options.githubToken!
45+
3946
this.tag = "v" + version
4047
this._releasePromise = <BluebirdPromise<Release>>this.init()
4148
}
@@ -144,20 +151,25 @@ export class GitHubPublisher implements Publisher {
144151
return gitHubRequest<Release>(`/repos/${this.owner}/${this.repo}/releases`, this.token, {
145152
tag_name: this.tag,
146153
name: this.tag,
147-
draft: true,
154+
draft: this.options.draft == null || this.options.draft,
155+
prerelease: this.options.prerelease != null && this.options.prerelease,
148156
})
149157
}
150158

159+
// test only
160+
async getRelease(): Promise<any> {
161+
return gitHubRequest<Release>(`/repos/${this.owner}/${this.repo}/releases/${this._releasePromise.value().id}`, this.token)
162+
}
163+
151164
//noinspection JSUnusedGlobalSymbols
152-
async deleteRelease(): Promise<void> {
165+
async deleteRelease(): Promise<any> {
153166
if (!this._releasePromise.isFulfilled()) {
154167
return BluebirdPromise.resolve()
155168
}
156169

157170
for (let i = 0; i < 3; i++) {
158171
try {
159-
return await
160-
gitHubRequest<void>(`/repos/${this.owner}/${this.repo}/releases/${this._releasePromise.value().id}`, this.token, null, "DELETE")
172+
return await gitHubRequest(`/repos/${this.owner}/${this.repo}/releases/${this._releasePromise.value().id}`, this.token, null, "DELETE")
161173
}
162174
catch (e) {
163175
if (e instanceof HttpError && (e.response.statusCode === 405 || e.response.statusCode === 502)) {

test/src/ArtifactPublisherTest.ts

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import test from "./helpers/avaEx"
22
import { GitHubPublisher } from "out/gitHubPublisher"
33
import { HttpError } from "out/gitHubRequest"
44
import { join } from "path"
5+
import * as assertThat from "should/as-function"
56

67
//noinspection JSUnusedLocalSymbols
78
const __awaiter = require("out/awaiter")
@@ -48,9 +49,30 @@ function testAndIgnoreApiRate(name: string, testFunction: () => Promise<any>) {
4849
}
4950

5051
testAndIgnoreApiRate("GitHub upload", async () => {
51-
const publisher = new GitHubPublisher("actperepo", "ecb2", versionNumber(), token)
52+
const publisher = new GitHubPublisher("actperepo", "ecb2", versionNumber(), {
53+
githubToken: token
54+
})
55+
try {
56+
await publisher.upload(iconPath)
57+
}
58+
finally {
59+
await publisher.deleteRelease()
60+
}
61+
})
62+
63+
testAndIgnoreApiRate("prerelease", async () => {
64+
const publisher = new GitHubPublisher("actperepo", "ecb2", versionNumber(), {
65+
githubToken: token,
66+
draft: false,
67+
prerelease: true,
68+
})
5269
try {
5370
await publisher.upload(iconPath)
71+
const r = await publisher.getRelease()
72+
assertThat(r).has.properties({
73+
prerelease: true,
74+
draft: true,
75+
})
5476
}
5577
finally {
5678
await publisher.deleteRelease()
@@ -59,7 +81,9 @@ testAndIgnoreApiRate("GitHub upload", async () => {
5981

6082
testAndIgnoreApiRate("GitHub upload org", async () => {
6183
//noinspection SpellCheckingInspection
62-
const publisher = new GitHubPublisher("builder-gh-test", "darpa", versionNumber(), token)
84+
const publisher = new GitHubPublisher("builder-gh-test", "darpa", versionNumber(), {
85+
githubToken: token
86+
})
6387
try {
6488
await publisher.upload(iconPath)
6589
}
@@ -69,7 +93,9 @@ testAndIgnoreApiRate("GitHub upload org", async () => {
6993
})
7094

7195
testAndIgnoreApiRate("GitHub overwrite on upload", async () => {
72-
const publisher = new GitHubPublisher("actperepo", "ecb2", versionNumber(), token)
96+
const publisher = new GitHubPublisher("actperepo", "ecb2", versionNumber(), {
97+
githubToken: token
98+
})
7399
try {
74100
await publisher.upload(iconPath)
75101
await publisher.upload(iconPath)

test/src/BuildTest.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { move, outputJson } from "fs-extra-p"
44
import { Promise as BluebirdPromise } from "bluebird"
55
import * as path from "path"
66
import { assertThat } from "./helpers/fileAssert"
7-
import { archFromString, BuildOptions, Platform, Arch, PackagerOptions, DIR_TARGET, createTargets } from "out"
7+
import { archFromString, BuildOptions, Platform, Arch, PackagerOptions, DIR_TARGET, createTargets, PublishOptions } from "out"
88
import { normalizeOptions } from "out/builder"
99
import { createYargs } from "out/cliOptions"
1010

@@ -14,8 +14,10 @@ const __awaiter = require("out/awaiter")
1414
test("cli", () => {
1515
const yargs = createYargs()
1616

17-
const base = {
18-
publish: <string>undefined,
17+
const base: PublishOptions = {
18+
publish: undefined,
19+
draft: undefined,
20+
prerelease: undefined,
1921
}
2022

2123
function expected(opt: PackagerOptions): any {

0 commit comments

Comments
 (0)