Compare commits

..

No commits in common. "master" and "2.1.1" have entirely different histories.

10 changed files with 20009 additions and 45624 deletions

View File

@ -24,7 +24,7 @@
"@typescript-eslint/func-call-spacing": ["error", "never"], "@typescript-eslint/func-call-spacing": ["error", "never"],
"@typescript-eslint/no-array-constructor": "error", "@typescript-eslint/no-array-constructor": "error",
"@typescript-eslint/no-empty-interface": "error", "@typescript-eslint/no-empty-interface": "error",
"@typescript-eslint/no-explicit-any": "off", "@typescript-eslint/no-explicit-any": "error",
"@typescript-eslint/no-extraneous-class": "error", "@typescript-eslint/no-extraneous-class": "error",
"@typescript-eslint/no-for-in-array": "error", "@typescript-eslint/no-for-in-array": "error",
"@typescript-eslint/no-inferrable-types": "error", "@typescript-eslint/no-inferrable-types": "error",

View File

@ -9,7 +9,7 @@ jobs:
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- run: | - run: |
npm install npm install
npm run all npm run all
@ -21,7 +21,7 @@ jobs:
matrix: matrix:
os: [ubuntu-latest, windows-latest, macos-latest] os: [ubuntu-latest, windows-latest, macos-latest]
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- name: Make test pre-release - name: Make test pre-release
uses: ./ uses: ./
with: with:
@ -31,57 +31,26 @@ jobs:
tag: ci-test-${{ matrix.os }}-${{ github.run_id }} tag: ci-test-${{ matrix.os }}-${{ github.run_id }}
overwrite: true overwrite: true
prerelease: true prerelease: true
make_latest: true body: "rofl lol test"
body: "rofl lol test%0Aianal %25 fubar"
- name: Check that the uploaded asset is readable - name: Check that the uploaded asset is readable
uses: actions/github-script@v2 uses: actions/github-script@v2
with: with:
github-token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
script: | script: |
const fs = require('fs') const fs = require('fs')
const child_process = require('child_process');
const assert = require('assert').strict; const assert = require('assert').strict;
const expected = fs.readFileSync("README.md", "utf-8") const expected = fs.readFileSync("README.md")
const release = await github.repos.getReleaseByTag({ const release = await github.repos.getReleaseByTag({
...context.repo, ...context.repo,
tag: "ci-test-${{ matrix.os }}-${{ github.run_id }}", tag: "ci-test-${{ matrix.os }}-${{ github.run_id }}",
}) })
assert.deepStrictEqual(release.data.prerelease, true) assert.deepStrictEqual(release.data.prerelease, true)
assert.deepStrictEqual(release.data.body, "rofl lol test\nianal % fubar") assert.deepStrictEqual(release.data.body, "rofl lol test")
assert.deepStrictEqual(release.data.assets[0].name, "TEST.md") assert.deepStrictEqual(release.data.assets[0].name, "TEST.md")
const actual = await github.request(release.data.assets[0].browser_download_url) const actual = child_process.execSync(`curl -Ls ${release.data.assets[0].browser_download_url}`)
assert.deepStrictEqual(expected, actual.data) assert.deepStrictEqual(expected, actual)
- name: Make test promote
uses: ./
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: README.md
asset_name: TEST.md
tag: ci-test-${{ matrix.os }}-${{ github.run_id }}
overwrite: true
promote: true
prerelease: false
make_latest: true
body: "new body"
- name: Check that the release is promoted
uses: actions/github-script@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
retries: 15
script: |
const fs = require('fs')
const assert = require('assert').strict;
const expected = fs.readFileSync("README.md", "utf-8")
const release = await github.repos.getReleaseByTag({
...context.repo,
tag: "ci-test-${{ matrix.os }}-${{ github.run_id }}",
})
assert.deepStrictEqual(release.data.prerelease, false)
assert.deepStrictEqual(release.data.body, "new body")
assert.deepStrictEqual(release.data.assets[0].name, "TEST.md")
const actual = await github.request(release.data.assets[0].browser_download_url)
assert.deepStrictEqual(expected, actual.data)
- name: Clean up - name: Clean up
if: ${{ always() }} if: ${{ always() }}
uses: actions/github-script@v2 uses: actions/github-script@v2

1
.gitignore vendored
View File

@ -2,4 +2,3 @@ node_modules
run.sh run.sh
__tests__/runner/* __tests__/runner/*
lib/**/* lib/**/*
.idea

View File

@ -1,45 +1,5 @@
# Changelog # Changelog
## [2.9.0] - 2024-02-22
- Allow seeting a release as draft [#112](https://github.com/svenstaro/upload-release-action/pull/112) (thanks @ShonP40)
## [2.8.0] - 2024-02-21
- Bump all deps
- Update to node 20
## [2.7.0] - 2023-07-28
- Allow setting an explicit target_commitish [#46](https://github.com/svenstaro/upload-release-action/pull/46) (thanks @Spikatrix)
## [2.6.1] - 2023-05-31
- Do not overwrite body or name if empty [#108](https://github.com/svenstaro/upload-release-action/pull/108) (thanks @regevbr)
## [2.6.0] - 2023-05-23
- Add `make_latest` input parameter. Can be set to `false` to prevent the created release from being marked as the latest release for the repository [#100](https://github.com/svenstaro/upload-release-action/pull/100) (thanks @brandonkelly)
- Don't try to upload empty files [#102](https://github.com/svenstaro/upload-release-action/pull/102) (thanks @Loyalsoldier)
- Bump all deps [#105](https://github.com/svenstaro/upload-release-action/pull/105)
- `overwrite` option also overwrites name and body [#106](https://github.com/svenstaro/upload-release-action/pull/106) (thanks @regevbr)
- Add `promote` option to allow prereleases to be promoted [#74](https://github.com/svenstaro/upload-release-action/pull/74) (thanks @regevbr)
## [2.5.0] - 2023-02-21
- Add retry to upload release [#96](https://github.com/svenstaro/upload-release-action/pull/96) (thanks @sonphantrung)
## [2.4.1] - 2023-02-01
- Modernize octokit usage
## [2.4.0] - 2023-01-09
- Update to node 16
- Bump most dependencies
## [2.3.0] - 2022-06-05
- Now defaults `repo_token` to `${{ github.token }}` and `tag` to `${{ github.ref }}` [#69](https://github.com/svenstaro/upload-release-action/pull/69) (thanks @leighmcculloch)
## [2.2.1] - 2020-12-16
- Added support for the GitHub pagination API for repositories with many releases [#36](https://github.com/svenstaro/upload-release-action/pull/36) (thanks @djpohly)
## [2.2.0] - 2020-10-07
- Add support for ceating a new release in a foreign repository [#25](https://github.com/svenstaro/upload-release-action/pull/25) (thanks @kittaakos)
- Upgrade all deps
## [2.1.1] - 2020-09-25 ## [2.1.1] - 2020-09-25
- Fix `release_name` option [#27](https://github.com/svenstaro/upload-release-action/pull/27) (thanks @kittaakos) - Fix `release_name` option [#27](https://github.com/svenstaro/upload-release-action/pull/27) (thanks @kittaakos)

112
README.md
View File

@ -1,4 +1,4 @@
# Upload files to a GitHub release [![GitHub Actions Workflow](https://github.com/svenstaro/upload-release-action/actions/workflows/ci.yml/badge.svg)](https://github.com/svenstaro/upload-release-action/actions) # Upload files to a GitHub release [![GitHub Actions Workflow](https://github.com/svenstaro/upload-release-action/workflows/PR%20Checks/badge.svg)](https://github.com/svenstaro/upload-release-action/actions)
This action allows you to select which files to upload to the just-tagged release. This action allows you to select which files to upload to the just-tagged release.
It runs on all operating systems types offered by GitHub. It runs on all operating systems types offered by GitHub.
@ -7,24 +7,19 @@ It runs on all operating systems types offered by GitHub.
You must provide: You must provide:
- `repo_token`: Usually you'll want to set this to `${{ secrets.GITHUB_TOKEN }}`.
- `file`: A local file to be uploaded as the asset. - `file`: A local file to be uploaded as the asset.
- `tag`: The tag to upload into. If you want the current event's tag or branch name, use `${{ github.ref }}` (the `refs/tags/` and `refs/heads/` prefixes will be automatically stripped).
Optional Arguments Optional Arguments
- `repo_token`: Defaults to `github.token`.
- `tag`: The tag to upload into. If you want the current event's tag or branch name, use `${{ github.ref }}` (the `refs/tags/` and `refs/heads/` prefixes will be automatically stripped). Defaults to `github.ref`.
- `asset_name`: The name the file gets as an asset on a release. Use `$tag` to include the tag name. When not provided it will default to the filename. - `asset_name`: The name the file gets as an asset on a release. Use `$tag` to include the tag name. When not provided it will default to the filename.
This is not used if `file_glob` is set to `true`. This is not used if `file_glob` is set to `true`.
- `file_glob`: If set to true, the `file` argument can be a glob pattern (`asset_name` is ignored in this case) (Default: `false`) - `file_glob`: If set to true, the file argument can be a glob pattern (`asset_name` is ignored in this case) (Default: `false`)
- `overwrite`: If an asset with the same name already exists, overwrite it (Default: `false`). - `overwrite`: If an asset with the same name already exists, overwrite it (Default: `false`).
- `promote`: If a prerelease already exists, promote it to a release (Default: `false`).
- `draft`: Sets the release as a draft instead of publishing it, allowing you to make any edits needed before releasing (Default: `false`).
- `prerelease`: Mark the release as a pre-release (Default: `false`). - `prerelease`: Mark the release as a pre-release (Default: `false`).
- `make_latest`: Mark the release as the latest release for the repository (Default: `true`).
- `release_name`: Explicitly set a release name. (Defaults: implicitly same as `tag` via GitHub API). - `release_name`: Explicitly set a release name. (Defaults: implicitly same as `tag` via GitHub API).
- `target_commit`: Sets the commit hash or branch for the tag to be based on (Default: the default branch, usually `main`). - `body`: Content of the release text (Defaut: `""`).
- `body`: Content of the release text (Default: `""`).
- `repo_name`: 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. (Default: current repository).
## Output variables ## Output variables
@ -51,7 +46,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- name: Build - name: Build
run: cargo build --release run: cargo build --release
- name: Upload binaries to release - name: Upload binaries to release
@ -93,7 +88,7 @@ jobs:
asset_name: mything-macos-amd64 asset_name: mything-macos-amd64
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- name: Build - name: Build
run: cargo build --release --locked run: cargo build --release --locked
- name: Upload binaries to release - name: Upload binaries to release
@ -106,20 +101,18 @@ jobs:
``` ```
Example with `file_glob`: Example with `file_glob`:
```yaml ```yaml
name: Publish name: Publish
on: on:
push: push:
tags: tags:
- '*' - '*'
jobs: jobs:
build: build:
name: Publish binaries name: Publish binaries
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v2
- name: Build - name: Build
run: cargo build --release run: cargo build --release
- name: Upload binaries to release - name: Upload binaries to release
@ -132,101 +125,12 @@ jobs:
file_glob: true file_glob: true
``` ```
Example for creating a release in a foreign repository using `repo_name`:
```yaml
name: Publish
on:
push:
tags:
- '*'
jobs:
build:
name: Publish binaries
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: cargo build --release
- name: Upload binaries to release
uses: svenstaro/upload-release-action@v2
with:
repo_name: owner/repository-name
# A personal access token for the GitHub repository in which the release will be created and edited.
# It is recommended to create the access token with the following scopes: `repo, user, admin:repo_hook`.
repo_token: ${{ secrets.YOUR_PERSONAL_ACCESS_TOKEN }}
file: target/release/mything
asset_name: mything
tag: ${{ github.ref }}
overwrite: true
body: "This is my release text"
```
**Example for feeding a file from repo to the `body` tag:**
This example covers following points:
* Reading a file present on the repo. For example, `release.md` which is placed in root directory of the repo.
* Modify & push the `release.md` file before triggering this action (create tag for this example) to dynamically change the body of the release.
```yaml
name: Publish
on:
push:
tags:
- '*'
jobs:
build:
name: Publish binaries
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
# This step reads a file from repo and use it for body of the release
# This works on any self-hosted runner OS
- name: Read release.md and use it as a body of new release
id: read_release
shell: bash
run: |
r=$(cat path/to/release.md) # <--- Read release.md (Provide correct path as per your repo)
r="${r//'%'/'%25'}" # Multiline escape sequences for %
r="${r//$'\n'/'%0A'}" # Multiline escape sequences for '\n'
r="${r//$'\r'/'%0D'}" # Multiline escape sequences for '\r'
echo "RELEASE_BODY=$r" >> $GITHUB_OUTPUT # <--- Set environment variable
- name: Upload Binaries to Release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
tag: ${{ github.ref }}
body: |
${{ steps.read_release.outputs.RELEASE_BODY }} # <--- Use environment variables that was created earlier
```
### Permissions
This actions requires writes access to the release. If you are using [granular permissions](https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#permissions)
in your workflow, you will need to add the `contents: write` permission to the token:
```yaml
permissions:
contents: write
```
## Releasing ## Releasing
To release this Action: To release this Action:
- Bump version in `package.json` - Bump version in `package.json`
- Create `CHANGELOG.md` entry - Create `CHANGELOG.md` entry
- `npm update`
- `npm run all` - `npm run all`
- `git commit -am <version>` - `git commit -am <version>`
- `git tag -sm <version> <version>` - `git tag -sm <version> <version>`

View File

@ -8,39 +8,27 @@ inputs:
repo_token: repo_token:
description: 'GitHub token.' description: 'GitHub token.'
required: true required: true
default: ${{ github.token }}
file: file:
description: 'Local file to upload.' description: 'Local file to upload.'
required: true required: true
tag: tag:
description: 'Tag to use as a release.' description: 'Tag to use as a release.'
required: true required: true
default: ${{ github.ref }}
asset_name: asset_name:
description: 'Name of the asset. When not provided will use the file name. Unused if file_glob is set to "true".' description: 'Name of the asset. When not provided will use the file name. Unused if file_glob is set to "true".'
overwrite: overwrite:
description: 'Overwrite the release in case it already exists.' description: 'Overwrite the release in case it already exists.'
promote:
description: 'Promote a prerelease to release. Defaults to "false".'
file_glob: 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.'
draft:
description: 'Mark the release as a draft. Defaults to "false".'
prerelease: prerelease:
description: 'Mark the release as a pre-release. Defaults to "false".' description: 'Mark the release as a pre-release. Defaults to "false".'
make_latest:
description: 'Mark the release the latest release for the repository. Defaults to "true".'
release_name: 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.'
body: body:
description: 'Content of the release text. Empty by default.' description: 'Content of the release text. Empty by default.'
target_commit:
description: 'Specifies the commitish value that determines where the Git tag is created from. Can be any branch or commit SHA. Unused if the Git tag already exists. Default: the repository\"s default branch (usually `main`).'
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'
outputs: outputs:
browser_download_url: browser_download_url:
description: 'The publicly available URL of the asset.' description: 'The publicly available URL of the asset.'
runs: runs:
using: 'node20' using: 'node12'
main: 'dist/index.js' main: 'dist/index.js'

51115
dist/index.js vendored

File diff suppressed because one or more lines are too long

14081
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
{ {
"name": "upload-release-action", "name": "upload-release-action",
"version": "2.9.0", "version": "2.1.1",
"private": true, "private": true,
"description": "Upload files to a GitHub release", "description": "Upload files to a GitHub release",
"main": "lib/main.js", "main": "lib/main.js",
@ -27,27 +27,24 @@
"author": "Sven-Hendrik Haase", "author": "Sven-Hendrik Haase",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^1.10.1", "@actions/core": "^1.2.0",
"@actions/github": "^6.0.0", "@actions/github": "^4.0.0",
"@lifeomic/attempt": "^3.0.3", "@types/glob": "^7.1.2",
"@octokit/core": "^5.1.0", "glob": "^7.1.6"
"glob": "^10"
}, },
"devDependencies": { "devDependencies": {
"@octokit/types": "^12.5.0", "@types/jest": "^24.9.1",
"@types/jest": "^29", "@types/node": "^12.12.47",
"@types/node": "^20", "@typescript-eslint/parser": "^3.5.0",
"@typescript-eslint/eslint-plugin": "^7.0.2", "@zeit/ncc": "^0.22.3",
"@typescript-eslint/parser": "^7", "eslint": "^7.3.1",
"@vercel/ncc": "^0.38.1", "eslint-plugin-github": "^4.0.1",
"eslint": "^8", "eslint-plugin-jest": "^23.17.1",
"eslint-plugin-github": "^4.10", "jest": "^26.1.0",
"eslint-plugin-jest": "^27", "jest-circus": "^26.1.0",
"jest": "^29", "js-yaml": "^3.14.0",
"jest-circus": "^29", "prettier": "^2.0.5",
"js-yaml": "^4", "ts-jest": "^26.1.1",
"prettier": "^3.2", "typescript": "^3.9.6"
"ts-jest": "^29",
"typescript": "^5"
} }
} }

View File

@ -5,120 +5,51 @@ import * as core from '@actions/core'
import * as github from '@actions/github' import * as github from '@actions/github'
import * as path from 'path' import * as path from 'path'
import * as glob from 'glob' import * as glob from 'glob'
import {retry} from '@lifeomic/attempt'
const getRef = 'GET /repos/{owner}/{repo}/git/ref/{ref}' as const type RepoAssetsResp = Endpoints['GET /repos/:owner/:repo/releases/:release_id/assets']['response']
const releaseByTag = 'GET /repos/{owner}/{repo}/releases/tags/{tag}' as const type ReleaseByTagResp = Endpoints['GET /repos/:owner/:repo/releases/tags/:tag']['response']
const createRelease = 'POST /repos/{owner}/{repo}/releases' as const type CreateReleaseResp = Endpoints['POST /repos/:owner/:repo/releases']['response']
const updateRelease = type UploadAssetResp = Endpoints['POST /repos/:owner/:repo/releases/:release_id/assets{?name,label}']['response']
'PATCH /repos/{owner}/{repo}/releases/{release_id}' as const
const repoAssets =
'GET /repos/{owner}/{repo}/releases/{release_id}/assets' as const
const uploadAssets =
'POST {origin}/repos/{owner}/{repo}/releases/{release_id}/assets{?name,label}' as const
const deleteAssets =
'DELETE /repos/{owner}/{repo}/releases/assets/{asset_id}' as const
type ReleaseByTagResp = Endpoints[typeof releaseByTag]['response']
type CreateReleaseResp = Endpoints[typeof createRelease]['response']
type RepoAssetsResp = Endpoints[typeof repoAssets]['response']['data']
type UploadAssetResp = Endpoints[typeof uploadAssets]['response']
type UpdateReleaseResp = Endpoints[typeof updateRelease]['response']
type UpdateReleaseParams = Endpoints[typeof updateRelease]['parameters']
async function get_release_by_tag( async function get_release_by_tag(
tag: string, tag: string,
draft: boolean,
prerelease: boolean, prerelease: boolean,
make_latest: boolean,
release_name: string, release_name: string,
body: string, body: string,
octokit: Octokit, octokit: Octokit
overwrite: boolean, ): Promise<ReleaseByTagResp | CreateReleaseResp> {
promote: boolean,
target_commit: string
): Promise<ReleaseByTagResp | CreateReleaseResp | UpdateReleaseResp> {
let release: ReleaseByTagResp
try { try {
core.debug(`Getting release by tag ${tag}.`) core.debug(`Getting release by tag ${tag}.`)
release = await octokit.request(releaseByTag, { return await octokit.repos.getReleaseByTag({
...repo(), ...github.context.repo,
tag: tag tag: tag
}) })
} catch (error: any) { } catch (error) {
// If this returns 404, we need to create the release first. // If this returns 404, we need to create the release first.
if (error.status === 404) { if (error.status === 404) {
core.debug( core.debug(
`Release for tag ${tag} doesn't exist yet so we'll create it now.` `Release for tag ${tag} doesn't exist yet so we'll create it now.`
) )
if (target_commit) { return await octokit.repos.createRelease({
try { ...github.context.repo,
await octokit.request(getRef, {
...repo(),
ref: `tags/${tag}`
})
core.warning(
`Ignoring target_commit as the tag ${tag} already exists`
)
} catch (tagError: any) {
if (tagError.status !== 404) {
throw tagError
}
}
}
return await octokit.request(createRelease, {
...repo(),
tag_name: tag, tag_name: tag,
draft: draft,
prerelease: prerelease, prerelease: prerelease,
make_latest: make_latest ? 'true' : 'false',
name: release_name, name: release_name,
body: body, body: body
target_commitish: target_commit
}) })
} else { } else {
throw error throw error
} }
} }
let updateObject: Partial<UpdateReleaseParams> | undefined
if (promote && release.data.prerelease) {
core.debug(`The ${tag} is a prerelease, promoting it to a release.`)
updateObject = updateObject || {}
updateObject.prerelease = false
}
if (overwrite) {
if (release_name && release.data.name !== release_name) {
core.debug(
`The ${tag} release already exists with a different name ${release.data.name} so we'll overwrite it.`
)
updateObject = updateObject || {}
updateObject.name = release_name
}
if (body && release.data.body !== body) {
core.debug(
`The ${tag} release already exists with a different body ${release.data.body} so we'll overwrite it.`
)
updateObject = updateObject || {}
updateObject.body = body
}
}
if (updateObject) {
return octokit.request(updateRelease, {
...repo(),
...updateObject,
release_id: release.data.id
})
}
return release
} }
async function upload_to_release( async function upload_to_release(
release: ReleaseByTagResp | CreateReleaseResp | UpdateReleaseResp, release: ReleaseByTagResp | CreateReleaseResp,
file: string, file: string,
asset_name: string, asset_name: string,
tag: string, tag: string,
overwrite: boolean, overwrite: boolean,
octokit: ReturnType<(typeof github)['getOctokit']> octokit: Octokit
): Promise<undefined | string> { ): Promise<undefined | string> {
const stat = fs.statSync(file) const stat = fs.statSync(file)
if (!stat.isFile()) { if (!stat.isFile()) {
@ -126,24 +57,21 @@ async function upload_to_release(
return return
} }
const file_size = stat.size const file_size = stat.size
if (file_size === 0) { const file_bytes = fs.readFileSync(file)
core.debug(`Skipping ${file}, since its size is 0`)
return
}
// Check for duplicates. // Check for duplicates.
const assets: RepoAssetsResp = await octokit.paginate(repoAssets, { const assets: RepoAssetsResp = await octokit.repos.listReleaseAssets({
...repo(), ...github.context.repo,
release_id: release.data.id release_id: release.data.id
}) })
const duplicate_asset = assets.find(a => a.name === asset_name) const duplicate_asset = assets.data.find(a => a.name === asset_name)
if (duplicate_asset !== undefined) { if (duplicate_asset !== undefined) {
if (overwrite) { if (overwrite) {
core.debug( core.debug(
`An asset called ${asset_name} already exists in release ${tag} so we'll overwrite it.` `An asset called ${asset_name} already exists in release ${tag} so we'll overwrite it.`
) )
await octokit.request(deleteAssets, { await octokit.repos.deleteReleaseAsset({
...repo(), ...github.context.repo,
asset_id: duplicate_asset.id asset_id: duplicate_asset.id
}) })
} else { } else {
@ -157,47 +85,20 @@ async function upload_to_release(
} }
core.debug(`Uploading ${file} to ${asset_name} in release ${tag}.`) core.debug(`Uploading ${file} to ${asset_name} in release ${tag}.`)
const uploaded_asset: UploadAssetResp = await retry( const uploaded_asset: UploadAssetResp = await octokit.repos.uploadReleaseAsset(
async () => {
return octokit.request(uploadAssets, {
...repo(),
release_id: release.data.id,
url: release.data.upload_url,
name: asset_name,
data: fs.createReadStream(file) as any,
headers: {
'content-type': 'binary/octet-stream',
'content-length': file_size
}
})
},
{ {
maxAttempts: 3 url: release.data.upload_url,
name: asset_name,
data: file_bytes,
headers: {
'content-type': 'binary/octet-stream',
'content-length': file_size
}
} }
) )
return uploaded_asset.data.browser_download_url return uploaded_asset.data.browser_download_url
} }
function repo(): {owner: string; repo: string} {
const repo_name = core.getInput('repo_name')
// If we're not targeting a foreign repository, we can just return immediately and don't have to do extra work.
if (!repo_name) {
return github.context.repo
}
const owner = repo_name.substring(0, repo_name.indexOf('/'))
if (!owner) {
throw new Error(`Could not extract 'owner' from 'repo_name': ${repo_name}.`)
}
const repo_ = repo_name.substring(repo_name.indexOf('/') + 1)
if (!repo_) {
throw new Error(`Could not extract 'repo' from 'repo_name': ${repo_name}.`)
}
return {
owner,
repo: repo_
}
}
async function run(): Promise<void> { async function run(): Promise<void> {
try { try {
// Get the inputs from the workflow file: https://github.com/actions/toolkit/tree/master/packages/core#inputsoutputs // Get the inputs from the workflow file: https://github.com/actions/toolkit/tree/master/packages/core#inputsoutputs
@ -210,40 +111,27 @@ async function run(): Promise<void> {
const file_glob = core.getInput('file_glob') == 'true' ? true : false const file_glob = core.getInput('file_glob') == 'true' ? true : false
const overwrite = core.getInput('overwrite') == 'true' ? true : false const overwrite = core.getInput('overwrite') == 'true' ? true : false
const promote = core.getInput('promote') == 'true' ? true : false
const draft = core.getInput('draft') == 'true' ? true : false
const prerelease = core.getInput('prerelease') == 'true' ? true : false const prerelease = core.getInput('prerelease') == 'true' ? true : false
const make_latest = core.getInput('make_latest') != 'false' ? true : false
const release_name = core.getInput('release_name') const release_name = core.getInput('release_name')
const target_commit = core.getInput('target_commit') const body = core.getInput('body')
const body = core
.getInput('body')
.replace(/%0A/gi, '\n')
.replace(/%0D/gi, '\r')
.replace(/%25/g, '%')
const octokit = github.getOctokit(token) const octokit: Octokit = github.getOctokit(token)
const release = await get_release_by_tag( const release = await get_release_by_tag(
tag, tag,
draft,
prerelease, prerelease,
make_latest,
release_name, release_name,
body, body,
octokit, octokit
overwrite,
promote,
target_commit
) )
if (file_glob) { if (file_glob) {
const files = glob.sync(file) const files = glob.sync(file)
if (files.length > 0) { if (files.length > 0) {
for (const file_ of files) { for (const file of files) {
const asset_name = path.basename(file_) const asset_name = path.basename(file)
const asset_download_url = await upload_to_release( const asset_download_url = await upload_to_release(
release, release,
file_, file,
asset_name, asset_name,
tag, tag,
overwrite, overwrite,
@ -269,7 +157,7 @@ async function run(): Promise<void> {
) )
core.setOutput('browser_download_url', asset_download_url) core.setOutput('browser_download_url', asset_download_url)
} }
} catch (error: any) { } catch (error) {
core.setFailed(error.message) core.setFailed(error.message)
} }
} }