feat: add support for uploading to draft releases

When we try to get a release by tag it doesn't
return draft releases. In order to get draft
releases we need to list the releases using a
token that has write access on the repo.

Signed-off-by: Harikrishnan Balagopal <harikrishmenon@gmail.com>
This commit is contained in:
Harikrishnan Balagopal 2020-12-08 19:23:13 +05:30
parent e74ff71f7d
commit 8b5823c88f
No known key found for this signature in database
GPG Key ID: 021D78C6DC6A9692
8 changed files with 13938 additions and 9960 deletions

View File

@ -1,36 +1,43 @@
name: 'Upload files to a GitHub release'
description: 'Upload files to a GitHub release (cross-platform)'
author: 'Sven-Hendrik Haase'
name: "Upload files to a GitHub release"
description: "Upload files to a GitHub release (cross-platform)"
author: "Sven-Hendrik Haase"
branding:
icon: archive
color: orange
inputs:
repo_token:
description: 'GitHub token.'
description: "GitHub token."
required: true
file:
description: 'Local file to upload.'
description: "Local file to upload."
required: true
tag:
description: 'Tag to use as a release.'
description: "Tag to use as a release."
required: true
asset_name:
description: 'Name of the asset. When not provided will use the file name. Unused if file_glob is set to "true".'
required: false
overwrite:
description: 'Overwrite the release in case it already exists.'
description: "Overwrite the release in case it already exists."
required: false
file_glob:
description: 'If true the file can be a glob pattern, asset_name is ignored if this is true.'
description: "If true the file can be a glob pattern, asset_name is ignored if this is true."
required: false
prerelease:
description: 'Mark the release as a pre-release. Defaults to "false".'
required: false
release_name:
description: 'Explicitly set a release name. Defaults to empty which will cause the release to take the tag as name on GitHub.'
description: "Explicitly set a release name. Defaults to empty which will cause the release to take the tag as name on GitHub."
required: false
body:
description: 'Content of the release text. Empty by default.'
description: "Content of the release text. Empty by default."
required: false
repo_name:
description: 'Specify the name of the GitHub repository in which the GitHub release will be created, edited, and deleted. If the repository is other than the current, it is required to create a personal access token with `repo`, `user`, `admin:repo_hook` scopes to the foreign repository and add it as a secret. Defaults to the current repository'
description: "Specify the name of the GitHub repository in which the GitHub release will be created, edited, and deleted. If the repository is other than the current, it is required to create a personal access token with `repo`, `user`, `admin:repo_hook` scopes to the foreign repository and add it as a secret. Defaults to the current repository"
required: false
outputs:
browser_download_url:
description: 'The publicly available URL of the asset.'
description: "The publicly available URL of the asset."
runs:
using: 'node12'
main: 'dist/index.js'
using: "node12"
main: "dist/index.js"

19865
dist/index.js vendored

File diff suppressed because it is too large Load Diff

1
dist/index.js.map vendored Normal file

File diff suppressed because one or more lines are too long

3910
dist/sourcemap-register.js vendored Normal file

File diff suppressed because it is too large Load Diff

8
package-lock.json generated
View File

@ -1691,10 +1691,10 @@
"eslint-visitor-keys": "^1.1.0"
}
},
"@zeit/ncc": {
"version": "0.22.3",
"resolved": "https://registry.npmjs.org/@zeit/ncc/-/ncc-0.22.3.tgz",
"integrity": "sha512-jnCLpLXWuw/PAiJiVbLjA8WBC0IJQbFeUwF4I9M+23MvIxTxk5pD4Q8byQBSPmHQjz5aBoA7AKAElQxMpjrCLQ==",
"@vercel/ncc": {
"version": "0.25.1",
"resolved": "https://registry.npmjs.org/@vercel/ncc/-/ncc-0.25.1.tgz",
"integrity": "sha512-dGecC5+1wLof1MQpey4+6i2KZv4Sfs6WfXkl9KfO32GED4ZPiKxRfvtGPjbjZv0IbqMl6CxtcV1RotXYfd5SSA==",
"dev": true
},
"abab": {

View File

@ -9,8 +9,8 @@
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"lint": "eslint src/**/*.ts",
"pack": "ncc build",
"test": "jest",
"pack": "ncc build --source-map -o dist src/main.ts",
"test": "jest --detectOpenHandles",
"all": "npm run build && npm run format && npm run lint && npm run pack && npm test"
},
"repository": {
@ -36,7 +36,7 @@
"@types/jest": "^24.9.1",
"@types/node": "^12.12.64",
"@typescript-eslint/parser": "^3.5.0",
"@zeit/ncc": "^0.22.3",
"@vercel/ncc": "^0.25.1",
"eslint": "^7.10.0",
"eslint-plugin-github": "^4.0.1",
"eslint-plugin-jest": "^23.17.1",
@ -47,4 +47,4 @@
"ts-jest": "^26.4.1",
"typescript": "^3.9.6"
}
}
}

View File

@ -1,33 +1,61 @@
import * as fs from 'fs'
import {Octokit} from '@octokit/core'
import {Endpoints} from '@octokit/types'
import {
Endpoints,
ReposGetReleaseByTagResponseData,
ReposListReleasesResponseData,
ReposCreateReleaseResponseData
} from '@octokit/types'
import * as core from '@actions/core'
import * as github from '@actions/github'
import * as path from 'path'
import * as glob from 'glob'
type RepoAssetsResp = Endpoints['GET /repos/:owner/:repo/releases/:release_id/assets']['response']
type ReleaseByTagResp = Endpoints['GET /repos/:owner/:repo/releases/tags/:tag']['response']
type CreateReleaseResp = Endpoints['POST /repos/:owner/:repo/releases']['response']
type ListReleasesResp = Endpoints['GET /repos/:owner/:repo/releases']['response']
type UploadAssetResp = Endpoints['POST /repos/:owner/:repo/releases/:release_id/assets{?name,label}']['response']
type ReleaseData =
| ReposGetReleaseByTagResponseData
| ReposListReleasesResponseData[0]
| ReposCreateReleaseResponseData
async function get_release_by_tag(
tag: string,
prerelease: boolean,
release_name: string,
body: string,
octokit: Octokit
): Promise<ReleaseByTagResp | CreateReleaseResp> {
): Promise<ReleaseData> {
try {
core.debug(`Getting release by tag ${tag}.`)
console.log(`Getting release by tag ${tag}.`)
return await octokit.repos.getReleaseByTag({
...repo(),
tag: tag
})
}).data
} catch (error) {
// If this returns 404, we need to create the release first.
if (error.status === 404) {
core.debug(
// The tag could be on a draft release
try {
const listReleasesResp: ListReleasesResp = await octokit.repos.listReleases(
repo()
)
let found = false
let draftRelease = listReleasesResp.data[0]
for (const release of listReleasesResp.data) {
if (release.tag_name === tag) {
draftRelease = release
found = true
break
}
}
if (found) {
return draftRelease
}
} catch (error) {
console.error(`Failed to list the releases. Error:`, error)
}
console.log(
`Release for tag ${tag} doesn't exist yet so we'll create it now.`
)
return await octokit.repos.createRelease({
@ -36,7 +64,7 @@ async function get_release_by_tag(
prerelease: prerelease,
name: release_name,
body: body
})
}).data
} else {
throw error
}
@ -44,7 +72,7 @@ async function get_release_by_tag(
}
async function upload_to_release(
release: ReleaseByTagResp | CreateReleaseResp,
releaseData: ReleaseData,
file: string,
asset_name: string,
tag: string,
@ -53,7 +81,7 @@ async function upload_to_release(
): Promise<undefined | string> {
const stat = fs.statSync(file)
if (!stat.isFile()) {
core.debug(`Skipping ${file}, since its not a file`)
console.log(`Skipping ${file}, since its not a file`)
return
}
const file_size = stat.size
@ -62,12 +90,12 @@ async function upload_to_release(
// Check for duplicates.
const assets: RepoAssetsResp = await octokit.repos.listReleaseAssets({
...repo(),
release_id: release.data.id
release_id: releaseData.id
})
const duplicate_asset = assets.data.find(a => a.name === asset_name)
if (duplicate_asset !== undefined) {
if (overwrite) {
core.debug(
console.log(
`An asset called ${asset_name} already exists in release ${tag} so we'll overwrite it.`
)
await octokit.repos.deleteReleaseAsset({
@ -79,15 +107,15 @@ async function upload_to_release(
return duplicate_asset.browser_download_url
}
} else {
core.debug(
console.log(
`No pre-existing asset called ${asset_name} found in release ${tag}. All good.`
)
}
core.debug(`Uploading ${file} to ${asset_name} in release ${tag}.`)
console.log(`Uploading ${file} to ${asset_name} in release ${tag}.`)
const uploaded_asset: UploadAssetResp = await octokit.repos.uploadReleaseAsset(
{
url: release.data.upload_url,
url: releaseData.upload_url,
name: asset_name,
data: file_bytes,
headers: {

View File

@ -2,11 +2,16 @@
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"moduleResolution": "node",
"outDir": "./lib",
"rootDir": "./src",
"strict": true,
"noImplicitAny": true,
"esModuleInterop": true
"esModuleInterop": true,
"sourceMap": true
},
"exclude": ["node_modules", "**/*.test.ts"]
}
"exclude": [
"node_modules",
"**/*.test.ts"
]
}