From 9f9f2a3ed2e9977c4458bcb0a23be188e442e7e7 Mon Sep 17 00:00:00 2001
From: softprops <d.tangren@gmail.com>
Date: Mon, 16 Sep 2019 23:51:16 +0900
Subject: [PATCH] merge drafts workaround. fixes #14

---
 src/github.ts | 81 ++++++++++++++++++++++++++++++++++++++++++++++++---
 src/main.ts   |  4 +--
 2 files changed, 79 insertions(+), 6 deletions(-)

diff --git a/src/github.ts b/src/github.ts
index 79a853a..2c8ed71 100644
--- a/src/github.ts
+++ b/src/github.ts
@@ -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 GitHubReleaseer {
+  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 => {
@@ -47,11 +105,26 @@ 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 release of releaser.allReleases({
+        owner,
+        repo
+      })) {
+        if (tag == release.data.tag_name) {
+          return release.data;
+        }
+      }
+    }
+    let release = await releaser.getReleaseByTag({
       owner,
       repo,
       tag
@@ -65,7 +138,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,
@@ -79,7 +152,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(
diff --git a/src/main.ts b/src/main.ts
index 737571b..b26bad3 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,5 +1,5 @@
 import { paths, parseConfig, isTag } from "./util";
-import { release, upload } from "./github";
+import { release, upload, GitHubReleaseer } from "./github";
 import { setFailed } from "@actions/core";
 import { GitHub } from "@actions/github";
 import { env } from "process";
@@ -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 GitHubReleaseer(gh));
     if (config.input_files) {
       paths(config.input_files).forEach(async path => {
         await upload(gh, rel.upload_url, path);