This commit is contained in:
softprops 2019-09-09 21:20:59 +09:00
parent 624fcca9a1
commit ef96a2eb52
7 changed files with 158 additions and 102 deletions

View file

@ -1,30 +1,25 @@
//import * as assert from "assert"; //import * as assert from "assert";
//const assert = require('assert'); //const assert = require('assert');
import * as assert from 'assert'; import * as assert from "assert";
import { mimeOrDefault, asset } from '../src/github'; import { mimeOrDefault, asset } from "../src/github";
describe('github', () => { describe("github", () => {
describe('mimeOrDefault', () => { describe("mimeOrDefault", () => {
it('returns a specific mime for common path', async () => { it("returns a specific mime for common path", async () => {
assert.equal(mimeOrDefault('foo.tar.gz'), 'application/gzip') assert.equal(mimeOrDefault("foo.tar.gz"), "application/gzip");
}); });
it('returns default mime for uncommon path', async () => { it("returns default mime for uncommon path", async () => {
assert.equal(mimeOrDefault('foo.uncommon'), 'application/octet-stream') assert.equal(mimeOrDefault("foo.uncommon"), "application/octet-stream");
}); });
}); });
describe('asset', () => { describe("asset", () => {
it('derives asset info from a path', async () => { it("derives asset info from a path", async () => {
const { const { name, mime, size, file } = asset("tests/data/foo/bar.txt");
name, assert.equal(name, "bar.txt");
mime, assert.equal(mime, "text/plain");
size, assert.equal(size, 10);
file assert.equal(file.toString(), "release me");
} = asset('tests/data/foo/bar.txt'); });
assert.equal(name, 'bar.txt'); });
assert.equal(mime, 'text/plain'); });
assert.equal(size, 10);
assert.equal(file.toString(), 'release me')
});
})
});

View file

@ -1,19 +1,21 @@
import { isTag, paths } from '../src/util'; import { isTag, paths } from "../src/util";
import * as assert from 'assert'; import * as assert from "assert";
describe('util', () => { describe("util", () => {
describe('isTag', () => { describe("isTag", () => {
it('returns true for tags', async () => { it("returns true for tags", async () => {
assert.equal(isTag('refs/tags/foo'), true) assert.equal(isTag("refs/tags/foo"), true);
}); });
it ('returns false for other kinds of refs', async () => { it("returns false for other kinds of refs", async () => {
assert.equal(isTag('refs/heads/master'), false) assert.equal(isTag("refs/heads/master"), false);
}) });
}) });
describe('paths', () => { describe("paths", () => {
it('resolves files given a set of paths', async () => { it("resolves files given a set of paths", async () => {
assert.deepStrictEqual(paths(["tests/data/**/*"]), ['tests/data/foo/bar.txt']) assert.deepStrictEqual(paths(["tests/data/**/*"]), [
"tests/data/foo/bar.txt"
]);
}); });
}) });
}); });

65
package-lock.json generated
View file

@ -1172,8 +1172,13 @@
"version": "2.20.0", "version": "2.20.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.0.tgz",
"integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==", "integrity": "sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ==",
"dev": true, "dev": true
"optional": true },
"commandpost": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/commandpost/-/commandpost-1.4.0.tgz",
"integrity": "sha512-aE2Y4MTFJ870NuB/+2z1cXBhSBBzRydVVjzhFC4gtenEhpnj15yu0qptWGJsO9YGrcPZ3ezX8AWb1VA391MKpQ==",
"dev": true
}, },
"component-emitter": { "component-emitter": {
"version": "1.3.0", "version": "1.3.0",
@ -1386,6 +1391,18 @@
"safer-buffer": "^2.1.0" "safer-buffer": "^2.1.0"
} }
}, },
"editorconfig": {
"version": "0.15.3",
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz",
"integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==",
"dev": true,
"requires": {
"commander": "^2.19.0",
"lru-cache": "^4.1.5",
"semver": "^5.6.0",
"sigmund": "^1.0.1"
}
},
"emoji-regex": { "emoji-regex": {
"version": "7.0.3", "version": "7.0.3",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
@ -3445,6 +3462,16 @@
"js-tokens": "^3.0.0 || ^4.0.0" "js-tokens": "^3.0.0 || ^4.0.0"
} }
}, },
"lru-cache": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"dev": true,
"requires": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
}
},
"macos-release": { "macos-release": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz", "resolved": "https://registry.npmjs.org/macos-release/-/macos-release-2.3.0.tgz",
@ -3995,6 +4022,12 @@
"integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=",
"dev": true "dev": true
}, },
"prettier": {
"version": "1.18.2",
"resolved": "https://registry.npmjs.org/prettier/-/prettier-1.18.2.tgz",
"integrity": "sha512-OeHeMc0JhFE9idD4ZdtNibzY0+TPHSpSSb9h8FqtP+YnoZZ1sl8Vc9b1sasjfymH3SonAF4QcA2+mzHPhMvIiw==",
"dev": true
},
"pretty-format": { "pretty-format": {
"version": "24.9.0", "version": "24.9.0",
"resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz", "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-24.9.0.tgz",
@ -4017,6 +4050,12 @@
"sisteransi": "^1.0.3" "sisteransi": "^1.0.3"
} }
}, },
"pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=",
"dev": true
},
"psl": { "psl": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.3.1.tgz", "resolved": "https://registry.npmjs.org/psl/-/psl-1.3.1.tgz",
@ -4334,6 +4373,12 @@
"integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==", "integrity": "sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==",
"dev": true "dev": true
}, },
"sigmund": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz",
"integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=",
"dev": true
},
"signal-exit": { "signal-exit": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
@ -4844,6 +4889,16 @@
"integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==", "integrity": "sha512-lmQ4L+J6mnu3xweP8+rOrUwzmN+MRAj7TgtJtDaXE5PMyX2kCrklhg3rvOsOIfNeAWMQWO2F1GPc1kMD2vLAfw==",
"dev": true "dev": true
}, },
"typescript-formatter": {
"version": "7.2.2",
"resolved": "https://registry.npmjs.org/typescript-formatter/-/typescript-formatter-7.2.2.tgz",
"integrity": "sha512-V7vfI9XArVhriOTYHPzMU2WUnm5IMdu9X/CPxs8mIMGxmTBFpDABlbkBka64PZJ9/xgQeRpK8KzzAG4MPzxBDQ==",
"dev": true,
"requires": {
"commandpost": "^1.0.0",
"editorconfig": "^0.15.0"
}
},
"uglify-js": { "uglify-js": {
"version": "3.6.0", "version": "3.6.0",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz", "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.6.0.tgz",
@ -5099,6 +5154,12 @@
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
"dev": true "dev": true
}, },
"yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=",
"dev": true
},
"yargs": { "yargs": {
"version": "13.3.0", "version": "13.3.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz", "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.0.tgz",

View file

@ -6,7 +6,8 @@
"main": "lib/main.js", "main": "lib/main.js",
"scripts": { "scripts": {
"build": "tsc", "build": "tsc",
"test": "jest" "test": "jest",
"fmt": "prettier --write 'src/**/*.ts' '__tests__/**/*.ts'"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -30,7 +31,9 @@
"@types/node": "^12.7.4", "@types/node": "^12.7.4",
"jest": "^24.8.0", "jest": "^24.8.0",
"jest-circus": "^24.7.1", "jest-circus": "^24.7.1",
"prettier": "1.18.2",
"ts-jest": "^24.0.2", "ts-jest": "^24.0.2",
"typescript": "^3.5.1" "typescript": "^3.5.1",
"typescript-formatter": "^7.2.2"
} }
} }

View file

@ -1,19 +1,19 @@
import { GitHub } from '@actions/github'; import { GitHub } from "@actions/github";
import { Config } from './util'; import { Config } from "./util";
import { lstatSync, readFileSync } from 'fs'; import { lstatSync, readFileSync } from "fs";
import { getType } from 'mime'; import { getType } from "mime";
import { basename } from 'path'; import { basename } from "path";
export interface ReleaseAsset { export interface ReleaseAsset {
name: string, name: string;
mime: string, mime: string;
size: number, size: number;
file: Buffer file: Buffer;
} }
export interface Release { export interface Release {
upload_url: string, upload_url: string;
html_url: string html_url: string;
} }
export const asset = (path: string): ReleaseAsset => { export const asset = (path: string): ReleaseAsset => {
@ -23,39 +23,31 @@ export const asset = (path: string): ReleaseAsset => {
size: lstatSync(path).size, size: lstatSync(path).size,
file: readFileSync(path) file: readFileSync(path)
}; };
} };
export const mimeOrDefault = (path: string): string => { export const mimeOrDefault = (path: string): string => {
return getType(path) || "application/octet-stream"; return getType(path) || "application/octet-stream";
} };
export const upload = async ( export const upload = async (
gh: GitHub, gh: GitHub,
url: string, url: string,
path: string path: string
): Promise<any> => { ): Promise<any> => {
let { let { name, size, mime, file } = asset(path);
name,
size,
mime,
file
} = asset(path);
console.log(`⬆️ Uploading ${name}...`); console.log(`⬆️ Uploading ${name}...`);
return await gh.repos.uploadReleaseAsset({ return await gh.repos.uploadReleaseAsset({
url, url,
headers: { headers: {
"content-length": size, "content-length": size,
"content-type": mime "content-type": mime
}, },
name, name,
file file
}); });
} };
export const release = async ( export const release = async (config: Config, gh: GitHub): Promise<Release> => {
config: Config,
gh: GitHub
): Promise<Release> => {
const [owner, repo] = config.github_repository.split("/"); const [owner, repo] = config.github_repository.split("/");
const tag = config.github_ref.replace("refs/tags/", ""); const tag = config.github_ref.replace("refs/tags/", "");
try { try {
@ -88,8 +80,10 @@ export const release = async (
return release(config, gh); return release(config, gh);
} }
} else { } else {
console.log(`Unexpected error fetching GitHub release for tag ${config.github_ref}: ${error}`); console.log(
`Unexpected error fetching GitHub release for tag ${config.github_ref}: ${error}`
);
throw error; throw error;
} }
} }
} };

View file

@ -1,9 +1,8 @@
import { paths, parseConfig, isTag } from "./util";
import { paths, parseConfig, isTag } from './util'; import { release, upload } from "./github";
import { release, upload } from './github'; import { setFailed } from "@actions/core";
import { setFailed } from '@actions/core'; import { GitHub } from "@actions/github";
import { GitHub } from '@actions/github'; import { env } from "process";
import { env } from 'process';
async function run() { async function run() {
try { try {
@ -14,15 +13,15 @@ async function run() {
const gh = new GitHub(config.github_token); const gh = new GitHub(config.github_token);
let rel = await release(config, gh); let rel = await release(config, gh);
if (config.input_files) { if (config.input_files) {
paths(config.input_files).forEach(async (path) => { paths(config.input_files).forEach(async path => {
await upload(gh, rel.upload_url, path) await upload(gh, rel.upload_url, path);
}); });
} }
console.log(`🎉 Release ready at ${rel.html_url}`) console.log(`🎉 Release ready at ${rel.html_url}`);
} catch (error) { } catch (error) {
console.log(`Error: ${error}`); console.log(`Error: ${error}`);
setFailed(error.message); setFailed(error.message);
} }
} }
run(); run();

View file

@ -1,16 +1,16 @@
import * as glob from 'glob'; import * as glob from "glob";
import { lstatSync } from 'fs'; import { lstatSync } from "fs";
export interface Config { export interface Config {
github_token: string, github_token: string;
github_ref: string, github_ref: string;
github_repository: string, github_repository: string;
// user provided // user provided
input_name?: string, input_name?: string;
input_body?: string, input_body?: string;
input_body_path?: string, input_body_path?: string;
input_files?: string[], input_files?: string[];
input_draft?: boolean, input_draft?: boolean;
} }
type Env = { [key: string]: string | undefined }; type Env = { [key: string]: string | undefined };
@ -18,22 +18,24 @@ type Env = { [key: string]: string | undefined };
export const parseConfig = (env: Env): Config => { export const parseConfig = (env: Env): Config => {
return { return {
github_token: env.GITHUB_TOKEN || "", github_token: env.GITHUB_TOKEN || "",
github_ref: (env.GITHUB_REF || ""), github_ref: env.GITHUB_REF || "",
github_repository: env.GITHUB_REPOSITORY || "", github_repository: env.GITHUB_REPOSITORY || "",
input_name: env.INPUT_NAME, input_name: env.INPUT_NAME,
input_body: env.INPUT_BODY, input_body: env.INPUT_BODY,
input_body_path: env.INPUT_BODY_PATH, input_body_path: env.INPUT_BODY_PATH,
input_files: (env.INPUT_FILES || "").split(","), input_files: (env.INPUT_FILES || "").split(","),
input_draft: env.INPUT_DRAFT === 'true' input_draft: env.INPUT_DRAFT === "true"
} };
} };
export const paths = (patterns: string[]): string[] => { export const paths = (patterns: string[]): string[] => {
return patterns.reduce((acc: string[], pattern: string): string[] => { return patterns.reduce((acc: string[], pattern: string): string[] => {
return acc.concat(glob.sync(pattern).filter(path => lstatSync(path).isFile())); return acc.concat(
}, []) glob.sync(pattern).filter(path => lstatSync(path).isFile())
} );
}, []);
};
export const isTag = (ref: string): boolean => { export const isTag = (ref: string): boolean => {
return ref.startsWith("refs/tags/") return ref.startsWith("refs/tags/");
} };