Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft merger #16

Merged
merged 11 commits into from Sep 17, 2019
17 changes: 14 additions & 3 deletions CHANGELOG.md
@@ -1,9 +1,20 @@
## 0.1.0
## 0.1.2

* Add support for merging draft releases [#16](https://github.com/softprops/action-gh-release/pull/16)

* Initial release
GitHub's api doesn't explicitly have a way of fetching a draft release by tag name which caused draft releases to appear as separate releases when used in a build matrix.
This is now fixed.

---

## 0.1.1

* Add support for publishing releases on all supported virtual hosts

You'll need to remove `docker://` prefix and use the `@v1` action tag
You'll need to remove `docker://` prefix and use the `@v1` action tag

---

## 0.1.0

* Initial release
5 changes: 3 additions & 2 deletions README.md
Expand Up @@ -8,8 +8,6 @@

> **⚠️ Note:** To use this action, you must have access to the [GitHub Actions](https://github.com/features/actions) feature. GitHub Actions are currently only available in public beta. You can [apply for the GitHub Actions beta here](https://github.com/features/actions/signup/).

> **⚠️ Note:** This action was previously implemented as a docker container, limiting its use to GitHub Actions Linux virtual environments only. With recent releases, we now support cross platform usage. You'll need to remove the `docker://` prefix in these versions

## 🤸 Usage

### 🚥 Limit releases to pushes to tags
Expand Down Expand Up @@ -148,4 +146,7 @@ The following are *required* as `step.env` keys
|----------------|--------------------------------------|
| `GITHUB_TOKEN` | GITHUB_TOKEN as provided by `secrets`|


> **⚠️ Note:** This action was previously implemented as a docker container, limiting its use to GitHub Actions Linux virtual environments only. With recent releases, we now support cross platform usage. You'll need to remove the `docker://` prefix in these versions

Doug Tangren (softprops) 2019
54 changes: 50 additions & 4 deletions lib/github.js
Expand Up @@ -8,10 +8,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const mime_1 = require("mime");
const path_1 = require("path");
class GitHubReleaser {
constructor(github) {
this.github = github;
}
getReleaseByTag(params) {
return this.github.repos.getReleaseByTag(params);
}
createRelease(params) {
return this.github.repos.createRelease(params);
}
allReleases(params) {
return this.github.paginate.iterator(this.github.repos.listReleases.endpoint.merge(params));
}
}
exports.GitHubReleaser = GitHubReleaser;
exports.asset = (path) => {
return {
name: path_1.basename(path),
Expand All @@ -36,11 +58,35 @@ exports.upload = (gh, url, path) => __awaiter(void 0, void 0, void 0, function*
file
});
});
exports.release = (config, gh) => __awaiter(void 0, void 0, void 0, function* () {
exports.release = (config, releaser) => __awaiter(void 0, void 0, void 0, function* () {
var e_1, _a;
const [owner, repo] = config.github_repository.split("/");
const tag = config.github_ref.replace("refs/tags/", "");
try {
let release = yield gh.repos.getReleaseByTag({
// you can't get a an existing draft by tag
// so we must find one in the list of all releases
if (config.input_draft) {
try {
for (var _b = __asyncValues(releaser.allReleases({
owner,
repo
})), _c; _c = yield _b.next(), !_c.done;) {
const response = _c.value;
let release = response.data.find(release => release.tag_name === tag);
if (release) {
return release;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b);
}
finally { if (e_1) throw e_1.error; }
}
}
let release = yield releaser.getReleaseByTag({
owner,
repo,
tag
Expand All @@ -55,7 +101,7 @@ exports.release = (config, gh) => __awaiter(void 0, void 0, void 0, function* ()
const body = config.input_body;
const draft = config.input_draft;
console.log(`👩‍🏭 Creating new GitHub release for tag ${tag_name}...`);
let release = yield gh.repos.createRelease({
let release = yield releaser.createRelease({
owner,
repo,
tag_name,
Expand All @@ -68,7 +114,7 @@ exports.release = (config, gh) => __awaiter(void 0, void 0, void 0, function* ()
catch (error) {
// presume a race with competing metrix runs
console.log(`⚠️ GitHub release failed with status: ${error.status}, retrying...`);
return exports.release(config, gh);
return exports.release(config, releaser);
}
}
else {
Expand Down
2 changes: 1 addition & 1 deletion lib/main.js
Expand Up @@ -22,7 +22,7 @@ function run() {
throw new Error(`⚠️ GitHub Releases requires a tag`);
}
const gh = new github_2.GitHub(config.github_token);
let rel = yield github_1.release(config, gh);
let rel = yield github_1.release(config, new github_1.GitHubReleaser(gh));
if (config.input_files) {
util_1.paths(config.input_files).forEach((path) => __awaiter(this, void 0, void 0, function* () {
yield github_1.upload(gh, rel.upload_url, path);
Expand Down
82 changes: 78 additions & 4 deletions src/github.ts
Expand Up @@ -14,6 +14,64 @@ export interface ReleaseAsset {
export interface Release {
upload_url: string;
html_url: string;
tag_name: string;
}

export interface Releaser {
getReleaseByTag(params: {
owner: string;
repo: string;
tag: string;
}): Promise<{ data: Release }>;

createRelease(params: {
owner: string;
repo: string;
tag_name: string;
name: string;
body: string | undefined;
draft: boolean | undefined;
}): Promise<{ data: Release }>;

allReleases(params: {
owner: string;
repo: string;
}): AsyncIterableIterator<{ data: Release[] }>;
}

export class GitHubReleaser implements Releaser {
github: GitHub;
constructor(github: GitHub) {
this.github = github;
}

getReleaseByTag(params: {
owner: string;
repo: string;
tag: string;
}): Promise<{ data: Release }> {
return this.github.repos.getReleaseByTag(params);
}

createRelease(params: {
owner: string;
repo: string;
tag_name: string;
name: string;
body: string | undefined;
draft: boolean | undefined;
}): Promise<{ data: Release }> {
return this.github.repos.createRelease(params);
}

allReleases(params: {
owner: string;
repo: string;
}): AsyncIterableIterator<{ data: Release[] }> {
return this.github.paginate.iterator(
this.github.repos.listReleases.endpoint.merge(params)
);
}
}

export const asset = (path: string): ReleaseAsset => {
Expand Down Expand Up @@ -47,11 +105,27 @@ export const upload = async (
});
};

export const release = async (config: Config, gh: GitHub): Promise<Release> => {
export const release = async (
config: Config,
releaser: Releaser
): Promise<Release> => {
const [owner, repo] = config.github_repository.split("/");
const tag = config.github_ref.replace("refs/tags/", "");
try {
let release = await gh.repos.getReleaseByTag({
// you can't get a an existing draft by tag
// so we must find one in the list of all releases
if (config.input_draft) {
for await (const response of releaser.allReleases({
owner,
repo
})) {
let release = response.data.find(release => release.tag_name === tag);
if (release) {
return release;
}
}
}
let release = await releaser.getReleaseByTag({
owner,
repo,
tag
Expand All @@ -65,7 +139,7 @@ export const release = async (config: Config, gh: GitHub): Promise<Release> => {
const body = config.input_body;
const draft = config.input_draft;
console.log(`👩‍🏭 Creating new GitHub release for tag ${tag_name}...`);
let release = await gh.repos.createRelease({
let release = await releaser.createRelease({
owner,
repo,
tag_name,
Expand All @@ -79,7 +153,7 @@ export const release = async (config: Config, gh: GitHub): Promise<Release> => {
console.log(
`⚠️ GitHub release failed with status: ${error.status}, retrying...`
);
return release(config, gh);
return release(config, releaser);
}
} else {
console.log(
Expand Down
4 changes: 2 additions & 2 deletions src/main.ts
@@ -1,5 +1,5 @@
import { paths, parseConfig, isTag } from "./util";
import { release, upload } from "./github";
import { release, upload, GitHubReleaser } from "./github";
import { setFailed } from "@actions/core";
import { GitHub } from "@actions/github";
import { env } from "process";
Expand All @@ -11,7 +11,7 @@ async function run() {
throw new Error(`⚠️ GitHub Releases requires a tag`);
}
const gh = new GitHub(config.github_token);
let rel = await release(config, gh);
let rel = await release(config, new GitHubReleaser(gh));
if (config.input_files) {
paths(config.input_files).forEach(async path => {
await upload(gh, rel.upload_url, path);
Expand Down