Compare commits
76 Commits
v1-release
...
2.0.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5cd3d711a | ||
|
|
f58e245343 | ||
|
|
1daf68639d | ||
|
|
3c84140b3e | ||
|
|
fa9b523f3c | ||
|
|
6bb16de6db | ||
|
|
adacb86abb | ||
|
|
fbd30418aa | ||
|
|
588487bf09 | ||
|
|
c0f4101399 | ||
|
|
30dfbfdd8d | ||
|
|
806b0b0631 | ||
|
|
fdd8502475 | ||
|
|
8277eef782 | ||
|
|
fbc34f818a | ||
|
|
38c90ed08f | ||
|
|
c7fa458e37 | ||
|
|
8c679d7487 | ||
|
|
7cac809eef | ||
|
|
d082cf3f16 | ||
|
|
9afb63d9be | ||
|
|
0c20962e0b | ||
|
|
bd83be724b | ||
|
|
5788568237 | ||
|
|
05bca815fe | ||
|
|
0faf394792 | ||
|
|
826b119adc | ||
|
|
c48071c5e8 | ||
|
|
ba09d617a8 | ||
|
|
c14556ae27 | ||
|
|
efda0e7412 | ||
|
|
3e5b1a7442 | ||
|
|
5d5ed153e8 | ||
|
|
d151157326 | ||
|
|
d59b001b39 | ||
|
|
802e00067c | ||
|
|
ffdc680f33 | ||
|
|
48ee6952fb | ||
|
|
319155ea78 | ||
|
|
ef27273521 | ||
|
|
41ca44be6f | ||
|
|
7238d4307d | ||
|
|
003f46c67a | ||
|
|
d49eb2564a | ||
|
|
179efc987d | ||
|
|
6dd75691d6 | ||
|
|
8f6457b46e | ||
|
|
842807fcaf | ||
|
|
e6466806bd | ||
|
|
623a8a1785 | ||
|
|
96917a90ee | ||
|
|
95b7f6102f | ||
|
|
ff946c0b57 | ||
|
|
646b122c81 | ||
|
|
907e5dae80 | ||
|
|
d69dec835b | ||
|
|
0e699b142b | ||
|
|
010fda07b6 | ||
|
|
0f446d9646 | ||
|
|
d7e47607f7 | ||
|
|
bf98c4413f | ||
|
|
12f7fc1a8b | ||
|
|
08e809b7ae | ||
|
|
371a3bf0be | ||
|
|
f4d050cb90 | ||
|
|
b8902a20c8 | ||
|
|
5f836e8716 | ||
|
|
223b39fc7a | ||
|
|
c571424387 | ||
|
|
a09c67074f | ||
|
|
11f6e3b5af | ||
|
|
1d082de854 | ||
|
|
387cfa6016 | ||
|
|
aa32ea81b6 | ||
|
|
48b3121e13 | ||
|
|
55755cd0bc |
3
.eslintignore
Normal file
3
.eslintignore
Normal file
@@ -0,0 +1,3 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
55
.eslintrc.json
Normal file
55
.eslintrc.json
Normal file
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"plugins": ["jest", "@typescript-eslint", "github"],
|
||||
"extends": ["plugin:github/typescript"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 9,
|
||||
"sourceType": "module",
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"eslint-comments/no-use": "off",
|
||||
"import/no-namespace": "off",
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/explicit-member-accessibility": ["error", {
|
||||
"accessibility": "no-public"
|
||||
}],
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
"@typescript-eslint/array-type": "error",
|
||||
"@typescript-eslint/await-thenable": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": ["error", {
|
||||
"allowExpressions": true
|
||||
}],
|
||||
"@typescript-eslint/func-call-spacing": ["error", "never"],
|
||||
"@typescript-eslint/no-array-constructor": "error",
|
||||
"@typescript-eslint/no-empty-interface": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-extraneous-class": "error",
|
||||
"@typescript-eslint/no-for-in-array": "error",
|
||||
"@typescript-eslint/no-inferrable-types": "error",
|
||||
"@typescript-eslint/no-misused-new": "error",
|
||||
"@typescript-eslint/no-namespace": "error",
|
||||
"@typescript-eslint/no-non-null-assertion": "warn",
|
||||
"@typescript-eslint/no-unnecessary-qualifier": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-assertion": "error",
|
||||
"@typescript-eslint/no-useless-constructor": "error",
|
||||
"@typescript-eslint/no-var-requires": "error",
|
||||
"@typescript-eslint/prefer-for-of": "warn",
|
||||
"@typescript-eslint/prefer-function-type": "warn",
|
||||
"@typescript-eslint/prefer-includes": "error",
|
||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||
"@typescript-eslint/promise-function-async": "error",
|
||||
"@typescript-eslint/require-array-sort-compare": "error",
|
||||
"@typescript-eslint/restrict-plus-operands": "error",
|
||||
"semi": "off",
|
||||
"@typescript-eslint/semi": ["error", "never"],
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
"@typescript-eslint/unbound-method": "error"
|
||||
},
|
||||
"env": {
|
||||
"node": true,
|
||||
"es6": true,
|
||||
"jest/globals": true
|
||||
}
|
||||
}
|
||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
github: svenstaro
|
||||
25
.github/workflows/checkin.yml
vendored
25
.github/workflows/checkin.yml
vendored
@@ -1,25 +0,0 @@
|
||||
name: "PR Checks"
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
check_pr:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
|
||||
- name: "npm ci"
|
||||
run: npm ci
|
||||
|
||||
- name: "npm run build"
|
||||
run: npm run build
|
||||
|
||||
- name: "npm run test"
|
||||
run: npm run test
|
||||
|
||||
- name: "check for uncommitted changes"
|
||||
# Ensure no changes, but ignore node_modules dir since dev/fresh ci deps installed.
|
||||
run: |
|
||||
git diff --exit-code --stat -- . ':!node_modules' \
|
||||
|| (echo "##[error] found changed files after build. please 'npm run build && npm run format'" \
|
||||
"and check in all changes" \
|
||||
&& exit 1)
|
||||
71
.github/workflows/ci.yml
vendored
Normal file
71
.github/workflows/ci.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
||||
name: "CI"
|
||||
on: [pull_request, push]
|
||||
|
||||
jobs:
|
||||
build: # make sure build/ci work properly
|
||||
name: CI on ${{ matrix.os }}
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- run: |
|
||||
npm install
|
||||
npm run all
|
||||
|
||||
test: # make sure the action works on a clean machine without building
|
||||
name: E2E test
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-latest, windows-latest, macos-latest]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Make test pre-release
|
||||
uses: ./
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: README.md
|
||||
asset_name: TEST.md
|
||||
tag: ci-test-${{ matrix.os }}
|
||||
overwrite: true
|
||||
prerelease: true
|
||||
body: "rofl lol test"
|
||||
- name: Check that the uploaded asset is readable
|
||||
uses: actions/github-script@v2
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const fs = require('fs')
|
||||
const child_process = require('child_process');
|
||||
const assert = require('assert').strict;
|
||||
|
||||
const expected = fs.readFileSync("README.md")
|
||||
const release = await github.repos.getReleaseByTag({
|
||||
...context.repo,
|
||||
tag: "ci-test-${{ matrix.os }}",
|
||||
})
|
||||
assert.deepStrictEqual(release.data.prerelease, true)
|
||||
assert.deepStrictEqual(release.data.body, "rofl lol test")
|
||||
assert.deepStrictEqual(release.data.assets[0].name, "TEST.md")
|
||||
const actual = child_process.execSync(`curl -Ls ${release.data.assets[0].browser_download_url}`)
|
||||
assert.deepStrictEqual(expected, actual)
|
||||
- name: Clean up
|
||||
if: ${{ always() }}
|
||||
uses: actions/github-script@v2
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const release = await github.repos.getReleaseByTag({
|
||||
...context.repo,
|
||||
tag: "ci-test-${{ matrix.os }}",
|
||||
})
|
||||
await github.repos.deleteRelease({
|
||||
...context.repo,
|
||||
release_id: release.data.id,
|
||||
})
|
||||
await github.git.deleteRef({
|
||||
...context.repo,
|
||||
ref: "tags/ci-test-${{ matrix.os }}",
|
||||
})
|
||||
15
.github/workflows/versioning.yml
vendored
Normal file
15
.github/workflows/versioning.yml
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
name: Keep the versions up-to-date
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published, edited]
|
||||
|
||||
jobs:
|
||||
actions-tagger:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: Actions-R-Us/actions-tagger@latest
|
||||
env:
|
||||
GITHUB_TOKEN: "${{secrets.GITHUB_TOKEN}}"
|
||||
with:
|
||||
publish_latest_tag: true
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
node_modules/
|
||||
__tests__/runner/*
|
||||
node_modules
|
||||
run.sh
|
||||
__tests__/runner/*
|
||||
lib/**/*
|
||||
|
||||
3
.prettierignore
Normal file
3
.prettierignore
Normal file
@@ -0,0 +1,3 @@
|
||||
dist/
|
||||
lib/
|
||||
node_modules/
|
||||
11
.prettierrc.json
Normal file
11
.prettierrc.json
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"printWidth": 80,
|
||||
"tabWidth": 2,
|
||||
"useTabs": false,
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"bracketSpacing": false,
|
||||
"arrowParens": "avoid",
|
||||
"parser": "typescript"
|
||||
}
|
||||
8
CHANGELOG.md
Normal file
8
CHANGELOG.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Changelog
|
||||
|
||||
## [2.0.0] - 2020-07-03
|
||||
- Add `prerelease` input parameter. Setting this marks the created release as a pre-release.
|
||||
- Add `release_name` input parameter. Setting this explicitly sets the title of the release.
|
||||
- Add `body` input parameter. Setting this sets the text content of the created release.
|
||||
- Add `browser_download_url` output variable. This contains the publicly accessible download URL of the uploaded artifact.
|
||||
- Allow for leaving `asset_name` unset. This will cause the asset to use the filename.
|
||||
54
README.md
54
README.md
@@ -7,15 +7,23 @@ It runs on all operating systems types offered by GitHub.
|
||||
|
||||
You must provide:
|
||||
|
||||
- `repo_token`: Usually you'll want to set this to `${{ secrets.GITHUB_TOKEN }}`
|
||||
- `repo_token`: Usually you'll want to set this to `${{ secrets.GITHUB_TOKEN }}`.
|
||||
- `file`: A local file to be uploaded as the asset.
|
||||
- `asset_name`: The name the file gets as an asset on a release.
|
||||
- `tag`: The tag to uploaded into. If you want the current event's tag, use `${{ github.ref }}`
|
||||
- `overwrite`: If an asset with the same name already exists, overwrite it.
|
||||
- `tag`: The tag to upload into. If you want the current event's tag, use `${{ github.ref }}` (the `refs/tags/` prefix will be automatically stripped).
|
||||
|
||||
Optional Arguments
|
||||
|
||||
- `file_glob`: If set to true, the file argument can be a glob pattern (`asset_name` is ignored in this case)
|
||||
- `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`.
|
||||
- `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`).
|
||||
- `prerelease`: Mark the release as a pre-release (Default: `false`).
|
||||
- `release_name`: Explicitly set a release name. (Defaults: implicitly same as `tag` via GitHub API).
|
||||
- `body`: Content of the release text (Defaut: `""`).
|
||||
|
||||
## Output variables
|
||||
|
||||
- `browser_download_url`: The publicly available URL of the asset.
|
||||
|
||||
## Usage
|
||||
|
||||
@@ -38,20 +46,18 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: hecrj/setup-rust-action@v1-release
|
||||
with:
|
||||
rust-version: stable
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: cargo build --release
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: target/release/mything
|
||||
asset_name: mything
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
body: "This is my release text"
|
||||
```
|
||||
|
||||
Complex example with more operating systems:
|
||||
@@ -82,14 +88,11 @@ jobs:
|
||||
asset_name: mything-macos-amd64
|
||||
|
||||
steps:
|
||||
- uses: hecrj/setup-rust-action@v1-release
|
||||
with:
|
||||
rust-version: stable
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: cargo build --release --locked
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: target/release/${{ matrix.artifact_name }}
|
||||
@@ -109,18 +112,27 @@ jobs:
|
||||
name: Publish binaries
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: hecrj/setup-rust-action@v1-release
|
||||
with:
|
||||
rust-version: stable
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v2
|
||||
- name: Build
|
||||
run: cargo build --release
|
||||
- name: Upload binaries to release
|
||||
uses: svenstaro/upload-release-action@v1-release
|
||||
uses: svenstaro/upload-release-action@v2
|
||||
with:
|
||||
repo_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
file: target/release/my*
|
||||
tag: ${{ github.ref }}
|
||||
overwrite: true
|
||||
file_glob: true
|
||||
```
|
||||
```
|
||||
|
||||
## Releasing
|
||||
|
||||
To release this Action:
|
||||
|
||||
- Bump version in `package.json`
|
||||
- Create `CHANGELOG.md` entry
|
||||
- `npm run all`
|
||||
- `git commit -am <version>`
|
||||
- `git tag -sm <version> <version>`
|
||||
- `git push --follow-tags`
|
||||
- Go to https://github.com/svenstaro/upload-release-action/releases and publish the new version
|
||||
|
||||
@@ -1,6 +1,25 @@
|
||||
import * as main from '../src/main';
|
||||
import * as github from '@actions/github'
|
||||
import * as main from '../src/main'
|
||||
|
||||
// Frankly, tests would be entirely useless unless we can mock GitHub somehow.
|
||||
describe('Upload Release Action', () => {
|
||||
it('', async () => {});
|
||||
});
|
||||
let spyGetOctokit: jest.SpyInstance<any>
|
||||
let mockOctokit: any
|
||||
|
||||
beforeEach(() => {
|
||||
mockOctokit = {
|
||||
repos: {
|
||||
createRelease: jest.fn(async () => ({
|
||||
data: {
|
||||
id: 'lalala',
|
||||
upload_url: 'oaoa'
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
// spyGetOctokit = jest.spyOn(github, "getOctokit").mockImplementation(() => mockOctokit
|
||||
// jest.spyOn(github, "context", "get").mockImplementation(() => "testtest");
|
||||
})
|
||||
|
||||
it('pls write actual test', async () => {})
|
||||
})
|
||||
|
||||
26
action.yml
26
action.yml
@@ -6,21 +6,29 @@ branding:
|
||||
color: orange
|
||||
inputs:
|
||||
repo_token:
|
||||
description: 'GitHub token'
|
||||
description: 'GitHub token.'
|
||||
required: true
|
||||
file:
|
||||
description: 'Local file to upload'
|
||||
required: true
|
||||
asset_name:
|
||||
description: 'Name of the asset'
|
||||
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".'
|
||||
overwrite:
|
||||
description: 'Overwrite the release in case it already exists'
|
||||
description: 'Overwrite the release in case it already exists.'
|
||||
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.'
|
||||
prerelease:
|
||||
description: 'Mark the release as a pre-release. Defaults to "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.'
|
||||
body:
|
||||
description: 'Content of the release text. Empty by default.'
|
||||
outputs:
|
||||
browser_download_url:
|
||||
description: 'The publicly available URL of the asset.'
|
||||
runs:
|
||||
using: 'node12'
|
||||
main: 'lib/main.js'
|
||||
main: 'dist/index.js'
|
||||
|
||||
12850
dist/index.js
vendored
Normal file
12850
dist/index.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
||||
# Contributors
|
||||
|
||||
### Checkin
|
||||
|
||||
- Do checkin source (src)
|
||||
- Do checkin build output (lib)
|
||||
- Do checkin runtime node_modules
|
||||
- Do not checkin devDependency node_modules (husky can help see below)
|
||||
|
||||
### devDependencies
|
||||
|
||||
In order to handle correctly checking in node_modules without devDependencies, we run [Husky](https://github.com/typicode/husky) before each commit.
|
||||
This step ensures that formatting and checkin rules are followed and that devDependencies are excluded. To make sure Husky runs correctly, please use the following workflow:
|
||||
|
||||
```
|
||||
npm install # installs all devDependencies including Husky
|
||||
git add abc.ext # Add the files you've changed. This should include files in src, lib, and node_modules (see above)
|
||||
git commit -m "Informative commit message" # Commit. This will run Husky
|
||||
```
|
||||
|
||||
During the commit step, Husky will take care of formatting all files with [Prettier](https://github.com/prettier/prettier) as well as pruning out devDependencies using `npm prune --production`.
|
||||
It will also make sure these changes are appropriately included in your commit (no further work is needed)
|
||||
111
lib/main.js
111
lib/main.js
@@ -1,111 +0,0 @@
|
||||
"use strict";
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
||||
return new (P || (P = Promise))(function (resolve, reject) {
|
||||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
||||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
||||
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
|
||||
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
||||
});
|
||||
};
|
||||
var __importStar = (this && this.__importStar) || function (mod) {
|
||||
if (mod && mod.__esModule) return mod;
|
||||
var result = {};
|
||||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k];
|
||||
result["default"] = mod;
|
||||
return result;
|
||||
};
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const fs = __importStar(require("fs"));
|
||||
const core = __importStar(require("@actions/core"));
|
||||
const github = __importStar(require("@actions/github"));
|
||||
const path = __importStar(require("path"));
|
||||
const glob = require("glob");
|
||||
function get_release_by_tag(tag, octokit, context) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
core.debug(`Getting release by tag ${tag}.`);
|
||||
return yield octokit.repos.getReleaseByTag(Object.assign({}, context.repo, { tag: tag }));
|
||||
}
|
||||
catch (error) {
|
||||
// If this returns 404, we need to create the release first.
|
||||
if (error.status === 404) {
|
||||
core.debug(`Release for tag ${tag} doesn't exist yet so we'll create it now.`);
|
||||
return yield octokit.repos.createRelease(Object.assign({}, context.repo, { tag_name: tag }));
|
||||
}
|
||||
else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function upload_to_release(release, file, asset_name, tag, overwrite, octokit, context) {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
const stat = fs.statSync(file);
|
||||
if (!stat.isFile()) {
|
||||
core.debug(`Skipping ${file}, since its not a file`);
|
||||
return;
|
||||
}
|
||||
const file_size = stat.size;
|
||||
const file_bytes = fs.readFileSync(file);
|
||||
// Check for duplicates.
|
||||
const assets = yield octokit.repos.listAssetsForRelease(Object.assign({}, context.repo, { release_id: release.data.id }));
|
||||
const duplicate_asset = assets.data.find(a => a.name === asset_name);
|
||||
if (duplicate_asset !== undefined) {
|
||||
if (overwrite === "true") {
|
||||
core.debug(`An asset called ${asset_name} already exists in release ${tag} so we'll overwrite it.`);
|
||||
yield octokit.repos.deleteReleaseAsset(Object.assign({}, context.repo, { asset_id: duplicate_asset.id }));
|
||||
}
|
||||
else {
|
||||
core.setFailed(`An asset called ${asset_name} already exists.`);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
core.debug(`No pre-existing asset called ${asset_name} found in release ${tag}. All good.`);
|
||||
}
|
||||
core.debug(`Uploading ${file} to ${asset_name} in release ${tag}.`);
|
||||
yield octokit.repos.uploadReleaseAsset({
|
||||
url: release.data.upload_url,
|
||||
name: asset_name,
|
||||
file: file_bytes,
|
||||
headers: {
|
||||
"content-type": "binary/octet-stream",
|
||||
"content-length": file_size
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
||||
function run() {
|
||||
return __awaiter(this, void 0, void 0, function* () {
|
||||
try {
|
||||
const token = core.getInput('repo_token', { required: true });
|
||||
const file = core.getInput('file', { required: true });
|
||||
const file_glob = core.getInput('file_glob');
|
||||
const tag = core.getInput('tag', { required: true }).replace("refs/tags/", "");
|
||||
const overwrite = core.getInput('overwrite');
|
||||
const octokit = new github.GitHub(token);
|
||||
const context = github.context;
|
||||
const release = yield get_release_by_tag(tag, octokit, context);
|
||||
if (file_glob === "true") {
|
||||
const files = glob.sync(file);
|
||||
if (files.length > 0) {
|
||||
for (let file of files) {
|
||||
const asset_name = path.basename(file);
|
||||
yield upload_to_release(release, file, asset_name, tag, overwrite, octokit, context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
core.setFailed("No files matching the glob pattern found.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
const asset_name = core.getInput('asset_name', { required: true });
|
||||
yield upload_to_release(release, file, asset_name, tag, overwrite, octokit, context);
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
core.setFailed(error.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
run();
|
||||
8202
package-lock.json
generated
8202
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
35
package.json
35
package.json
@@ -1,12 +1,17 @@
|
||||
{
|
||||
"name": "upload-release-action",
|
||||
"version": "1.0.1",
|
||||
"version": "2.0.0",
|
||||
"private": true,
|
||||
"description": "Upload files to a GitHub release",
|
||||
"main": "lib/main.js",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"test": "jest"
|
||||
"format": "prettier --write **/*.ts",
|
||||
"format-check": "prettier --check **/*.ts",
|
||||
"lint": "eslint src/**/*.ts",
|
||||
"pack": "ncc build",
|
||||
"test": "jest",
|
||||
"all": "npm run build && npm run format && npm run lint && npm run pack && npm test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -22,16 +27,24 @@
|
||||
"author": "Sven-Hendrik Haase",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@actions/core": "^1.0.0",
|
||||
"@actions/github": "^1.0.0",
|
||||
"glob": "^7.1.4"
|
||||
"@actions/core": "^1.2.0",
|
||||
"@actions/github": "^4.0.0",
|
||||
"@types/glob": "^7.1.2",
|
||||
"glob": "^7.1.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/jest": "^24.0.13",
|
||||
"@types/node": "^12.0.4",
|
||||
"jest": "^24.8.0",
|
||||
"jest-circus": "^24.7.1",
|
||||
"ts-jest": "^24.0.2",
|
||||
"typescript": "^3.5.1"
|
||||
"@types/jest": "^24.9.1",
|
||||
"@types/node": "^12.12.47",
|
||||
"@typescript-eslint/parser": "^3.5.0",
|
||||
"@zeit/ncc": "^0.22.3",
|
||||
"eslint": "^7.3.1",
|
||||
"eslint-plugin-github": "^4.0.1",
|
||||
"eslint-plugin-jest": "^23.17.1",
|
||||
"jest": "^26.1.0",
|
||||
"jest-circus": "^26.1.0",
|
||||
"js-yaml": "^3.14.0",
|
||||
"prettier": "^2.0.5",
|
||||
"ts-jest": "^26.1.1",
|
||||
"typescript": "^3.9.6"
|
||||
}
|
||||
}
|
||||
|
||||
246
src/main.ts
246
src/main.ts
@@ -1,104 +1,162 @@
|
||||
import * as fs from 'fs';
|
||||
import * as core from '@actions/core';
|
||||
import * as github from '@actions/github';
|
||||
import * as path from 'path';
|
||||
import * as fs from 'fs'
|
||||
import {Octokit} from '@octokit/core'
|
||||
import {Endpoints} 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'
|
||||
|
||||
const glob = require("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 UploadAssetResp = Endpoints['POST /repos/:owner/:repo/releases/:release_id/assets{?name,label}']['response']
|
||||
|
||||
async function get_release_by_tag(tag: string, octokit: any, context: any): Promise<any> {
|
||||
try {
|
||||
core.debug(`Getting release by tag ${tag}.`);
|
||||
return await octokit.repos.getReleaseByTag({
|
||||
...context.repo,
|
||||
tag: tag,
|
||||
});
|
||||
} catch (error) {
|
||||
// If this returns 404, we need to create the release first.
|
||||
if (error.status === 404) {
|
||||
core.debug(`Release for tag ${tag} doesn't exist yet so we'll create it now.`)
|
||||
return await octokit.repos.createRelease({
|
||||
...context.repo,
|
||||
tag_name: tag,
|
||||
})
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function upload_to_release(release: any, file: string, asset_name: string, tag: string, overwrite: string, octokit: any, context: any) {
|
||||
const stat = fs.statSync(file);
|
||||
if (!stat.isFile()) {
|
||||
core.debug(`Skipping ${file}, since its not a file`);
|
||||
return;
|
||||
}
|
||||
const file_size = stat.size;
|
||||
const file_bytes = fs.readFileSync(file);
|
||||
|
||||
// Check for duplicates.
|
||||
const assets = await octokit.repos.listAssetsForRelease({
|
||||
...context.repo,
|
||||
release_id: release.data.id,
|
||||
});
|
||||
const duplicate_asset = assets.data.find(a => a.name === asset_name);
|
||||
if (duplicate_asset !== undefined) {
|
||||
if (overwrite === "true") {
|
||||
core.debug(`An asset called ${asset_name} already exists in release ${tag} so we'll overwrite it.`)
|
||||
await octokit.repos.deleteReleaseAsset({
|
||||
...context.repo,
|
||||
asset_id: duplicate_asset.id
|
||||
})
|
||||
} else {
|
||||
core.setFailed(`An asset called ${asset_name} already exists.`)
|
||||
return;
|
||||
}
|
||||
async function get_release_by_tag(
|
||||
tag: string,
|
||||
prerelease: boolean,
|
||||
release_name: string,
|
||||
body: string,
|
||||
octokit: Octokit
|
||||
): Promise<ReleaseByTagResp | CreateReleaseResp> {
|
||||
try {
|
||||
core.debug(`Getting release by tag ${tag}.`)
|
||||
return await octokit.repos.getReleaseByTag({
|
||||
...github.context.repo,
|
||||
tag: tag
|
||||
})
|
||||
} catch (error) {
|
||||
// If this returns 404, we need to create the release first.
|
||||
if (error.status === 404) {
|
||||
core.debug(
|
||||
`Release for tag ${tag} doesn't exist yet so we'll create it now.`
|
||||
)
|
||||
return await octokit.repos.createRelease({
|
||||
...github.context.repo,
|
||||
tag_name: tag,
|
||||
prerelease: prerelease,
|
||||
release_name: release_name,
|
||||
body: body
|
||||
})
|
||||
} else {
|
||||
core.debug(`No pre-existing asset called ${asset_name} found in release ${tag}. All good.`);
|
||||
throw error
|
||||
}
|
||||
|
||||
core.debug(`Uploading ${file} to ${asset_name} in release ${tag}.`)
|
||||
await octokit.repos.uploadReleaseAsset({
|
||||
url: release.data.upload_url,
|
||||
name: asset_name,
|
||||
file: file_bytes,
|
||||
headers: {
|
||||
"content-type": "binary/octet-stream",
|
||||
"content-length": file_size
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function run() {
|
||||
try {
|
||||
const token = core.getInput('repo_token', { required: true });
|
||||
const file = core.getInput('file', { required: true });
|
||||
const file_glob = core.getInput('file_glob');
|
||||
const tag = core.getInput('tag', { required: true }).replace("refs/tags/", "");
|
||||
const overwrite = core.getInput('overwrite');
|
||||
async function upload_to_release(
|
||||
release: ReleaseByTagResp | CreateReleaseResp,
|
||||
file: string,
|
||||
asset_name: string,
|
||||
tag: string,
|
||||
overwrite: boolean,
|
||||
octokit: Octokit
|
||||
): Promise<undefined | string> {
|
||||
const stat = fs.statSync(file)
|
||||
if (!stat.isFile()) {
|
||||
core.debug(`Skipping ${file}, since its not a file`)
|
||||
return
|
||||
}
|
||||
const file_size = stat.size
|
||||
const file_bytes = fs.readFileSync(file)
|
||||
|
||||
const octokit = new github.GitHub(token);
|
||||
const context = github.context;
|
||||
const release = await get_release_by_tag(tag, octokit, context);
|
||||
|
||||
if (file_glob === "true") {
|
||||
const files = glob.sync(file);
|
||||
if (files.length > 0) {
|
||||
for (let file of files) {
|
||||
const asset_name = path.basename(file);
|
||||
await upload_to_release(release, file, asset_name, tag, overwrite, octokit, context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
core.setFailed("No files matching the glob pattern found.");
|
||||
}
|
||||
}
|
||||
else {
|
||||
const asset_name = core.getInput('asset_name', { required: true });
|
||||
await upload_to_release(release, file, asset_name, tag, overwrite, octokit, context);
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(error.message);
|
||||
// Check for duplicates.
|
||||
const assets: RepoAssetsResp = await octokit.repos.listReleaseAssets({
|
||||
...github.context.repo,
|
||||
release_id: release.data.id
|
||||
})
|
||||
const duplicate_asset = assets.data.find(a => a.name === asset_name)
|
||||
if (duplicate_asset !== undefined) {
|
||||
if (overwrite) {
|
||||
core.debug(
|
||||
`An asset called ${asset_name} already exists in release ${tag} so we'll overwrite it.`
|
||||
)
|
||||
await octokit.repos.deleteReleaseAsset({
|
||||
...github.context.repo,
|
||||
asset_id: duplicate_asset.id
|
||||
})
|
||||
} else {
|
||||
core.setFailed(`An asset called ${asset_name} already exists.`)
|
||||
return duplicate_asset.browser_download_url
|
||||
}
|
||||
} else {
|
||||
core.debug(
|
||||
`No pre-existing asset called ${asset_name} found in release ${tag}. All good.`
|
||||
)
|
||||
}
|
||||
|
||||
core.debug(`Uploading ${file} to ${asset_name} in release ${tag}.`)
|
||||
const uploaded_asset: UploadAssetResp = await octokit.repos.uploadReleaseAsset(
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
run();
|
||||
async function run(): Promise<void> {
|
||||
try {
|
||||
// Get the inputs from the workflow file: https://github.com/actions/toolkit/tree/master/packages/core#inputsoutputs
|
||||
const token = core.getInput('repo_token', {required: true})
|
||||
const file = core.getInput('file', {required: true})
|
||||
const tag = core.getInput('tag', {required: true}).replace('refs/tags/', '')
|
||||
|
||||
const file_glob = core.getInput('file_glob') == 'true' ? true : false
|
||||
const overwrite = core.getInput('overwrite') == 'true' ? true : false
|
||||
const prerelease = core.getInput('prerelease') == 'true' ? true : false
|
||||
const release_name = core.getInput('release_name')
|
||||
const body = core.getInput('body')
|
||||
|
||||
const octokit: Octokit = github.getOctokit(token)
|
||||
const release = await get_release_by_tag(
|
||||
tag,
|
||||
prerelease,
|
||||
release_name,
|
||||
body,
|
||||
octokit
|
||||
)
|
||||
|
||||
if (file_glob) {
|
||||
const files = glob.sync(file)
|
||||
if (files.length > 0) {
|
||||
for (const file of files) {
|
||||
const asset_name = path.basename(file)
|
||||
const asset_download_url = await upload_to_release(
|
||||
release,
|
||||
file,
|
||||
asset_name,
|
||||
tag,
|
||||
overwrite,
|
||||
octokit
|
||||
)
|
||||
core.setOutput('browser_download_url', asset_download_url)
|
||||
}
|
||||
} else {
|
||||
core.setFailed('No files matching the glob pattern found.')
|
||||
}
|
||||
} else {
|
||||
const asset_name =
|
||||
core.getInput('asset_name') !== ''
|
||||
? core.getInput('asset_name').replace(/\$tag/g, tag)
|
||||
: path.basename(file)
|
||||
const asset_download_url = await upload_to_release(
|
||||
release,
|
||||
file,
|
||||
asset_name,
|
||||
tag,
|
||||
overwrite,
|
||||
octokit
|
||||
)
|
||||
core.setOutput('browser_download_url', asset_download_url)
|
||||
}
|
||||
} catch (error) {
|
||||
core.setFailed(error.message)
|
||||
}
|
||||
}
|
||||
|
||||
run()
|
||||
|
||||
@@ -1,63 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
/* Basic Options */
|
||||
// "incremental": true, /* Enable incremental compilation */
|
||||
"target": "es6", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
|
||||
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
|
||||
// "allowJs": true, /* Allow javascript files to be compiled. */
|
||||
// "checkJs": true, /* Report errors in .js files. */
|
||||
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
|
||||
// "declaration": true, /* Generates corresponding '.d.ts' file. */
|
||||
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
|
||||
// "sourceMap": true, /* Generates corresponding '.map' file. */
|
||||
// "outFile": "./", /* Concatenate and emit output to single file. */
|
||||
"outDir": "./lib", /* Redirect output structure to the directory. */
|
||||
"rootDir": "./src", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
|
||||
// "composite": true, /* Enable project compilation */
|
||||
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
|
||||
// "removeComments": true, /* Do not emit comments to output. */
|
||||
// "noEmit": true, /* Do not emit outputs. */
|
||||
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
|
||||
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
|
||||
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
|
||||
|
||||
/* Strict Type-Checking Options */
|
||||
"strict": true, /* Enable all strict type-checking options. */
|
||||
"noImplicitAny": false, /* Raise error on expressions and declarations with an implied 'any' type. */
|
||||
// "strictNullChecks": true, /* Enable strict null checks. */
|
||||
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
|
||||
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
|
||||
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
|
||||
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
|
||||
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
|
||||
|
||||
/* Additional Checks */
|
||||
// "noUnusedLocals": true, /* Report errors on unused locals. */
|
||||
// "noUnusedParameters": true, /* Report errors on unused parameters. */
|
||||
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
|
||||
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
|
||||
|
||||
/* Module Resolution Options */
|
||||
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
|
||||
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
|
||||
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
|
||||
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
|
||||
// "typeRoots": [], /* List of folders to include type definitions from. */
|
||||
// "types": [], /* Type declaration files to be included in compilation. */
|
||||
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
|
||||
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
|
||||
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
|
||||
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
|
||||
|
||||
/* Source Map Options */
|
||||
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
|
||||
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
|
||||
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
|
||||
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
|
||||
|
||||
/* Experimental Options */
|
||||
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
|
||||
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
|
||||
"target": "es6",
|
||||
"module": "commonjs",
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"strict": true,
|
||||
"noImplicitAny": true,
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"exclude": ["node_modules", "**/*.test.ts"]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user