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:
parent
e74ff71f7d
commit
8b5823c88f
35
action.yml
35
action.yml
@ -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
19865
dist/index.js
vendored
File diff suppressed because it is too large
Load Diff
1
dist/index.js.map
vendored
Normal file
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
3910
dist/sourcemap-register.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
8
package-lock.json
generated
8
package-lock.json
generated
@ -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": {
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
60
src/main.ts
60
src/main.ts
@ -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: {
|
||||
|
@ -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"
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user