Skip to content

Commit

Permalink
refactor for cross platform use
Browse files Browse the repository at this point in the history
  • Loading branch information
softprops committed Sep 9, 2019
1 parent 090932e commit 18daf2c
Show file tree
Hide file tree
Showing 15 changed files with 5,626 additions and 23 deletions.
53 changes: 33 additions & 20 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name: Main

on:
push:
branches:
- 'master'
on: [pull_request, push]
# push:
# branches:
# - 'master'

jobs:
build:
Expand All @@ -14,20 +14,33 @@ jobs:
uses: actions/checkout@master
with:
fetch-depth: 1
- name: Install
run: npm ci
- name: Build
run: npm run build
- name: Test
run: npm rust 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)
# https://github.com/actions/docker/tree/master/cli
- name: Package
uses: actions/docker/cli@master
with:
args: build -t ${{ github.repository }}:latest -t ${{ github.repository }}:${{ github.sha }} .
# https://github.com/actions/docker/tree/master/login
- name: Publish Auth
uses: actions/docker/login@master
env:
# https://help.github.com/en/articles/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
# https://github.com/actions/docker/tree/master/cli
- name: Publish
uses: actions/docker/cli@master
with:
args: push ${{ github.repository }}:latest
# - name: Package
# uses: actions/docker/cli@master
# with:
# args: build -t ${{ github.repository }}:latest -t ${{ github.repository }}:${{ github.sha }} .
# # https://github.com/actions/docker/tree/master/login
# - name: Publish Auth
# uses: actions/docker/login@master
# env:
# # https://help.github.com/en/articles/virtual-environments-for-github-actions#creating-and-using-secrets-encrypted-variables
# DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
# DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
# # https://github.com/actions/docker/tree/master/cli
# - name: Publish
# uses: actions/docker/cli@master
# with:
# args: push ${{ github.repository }}:latest
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/target
**/*.rs.bk
node_modules
30 changes: 30 additions & 0 deletions __tests__/github.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
//import * as assert from "assert";
//const assert = require('assert');
import * as assert from 'assert';
import { mimeOrDefault, asset } from '../src/github';

describe('github', () => {
describe('mimeOrDefault', () => {
it('returns a specific mime for common path', async () => {
assert.equal(mimeOrDefault('foo.tar.gz'), 'application/gzip')
});
it('returns default mime for uncommon path', async () => {
assert.equal(mimeOrDefault('foo.uncommon'), 'application/octet-stream')
});
});

describe('asset', () => {
it('derives asset info from a path', async () => {
const {
name,
mime,
size,
file
} = 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')
});
})
});
19 changes: 19 additions & 0 deletions __tests__/util.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { isTag, paths } from '../src/util';
import * as assert from 'assert';

describe('util', () => {
describe('isTag', () => {
it('returns true for tags', async () => {
assert.equal(isTag('refs/tags/foo'), true)
});
it ('returns false for other kinds of refs', async () => {
assert.equal(isTag('refs/heads/master'), false)
})
})

describe('paths', () => {
it('resolves files given a set of paths', async () => {
assert.deepStrictEqual(paths(["tests/data/**/*"]), ['tests/data/foo/bar.txt'])
});
})
});
8 changes: 5 additions & 3 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,12 @@ inputs:
required: false
default: 'empty'
runs:
using: 'docker'
image: 'docker://softprops:action-gh-action'
#using: 'docker'
#image: 'docker://softprops:action-gh-action'
using: 'node12'
main: 'lib/main.js'
env:
'GITHUB_TOKEN': 'As provided by Github Actions'
branding:
color: 'green'
color: 'green'
icon: 'package'
11 changes: 11 additions & 0 deletions jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
}
69 changes: 69 additions & 0 deletions lib/github.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const fs_1 = require("fs");
const mime_1 = require("mime");
const path_1 = require("path");
exports.asset = (path) => {
return {
name: path_1.basename(path),
mime: exports.mimeOrDefault(path),
size: fs_1.lstatSync(path).size,
file: fs_1.readFileSync(path)
};
};
exports.mimeOrDefault = (path) => {
return mime_1.getType(path) || "application/octet-stream";
};
exports.upload = (gh, url, path) => __awaiter(void 0, void 0, void 0, function* () {
let { name, size, mime, file } = exports.asset(path);
console.log(`⬆️ Uploading ${name}...`);
return yield gh.repos.uploadReleaseAsset({
url,
headers: {
"content-length": size,
"content-type": mime
},
name,
file
});
});
exports.release = (config, gh) => __awaiter(void 0, void 0, void 0, function* () {
let [owner, repo] = config.github_repository.split("/");
try {
let release = yield gh.repos.getReleaseByTag({
owner,
repo,
tag: config.github_ref
});
return release.data;
}
catch (error) {
if (error.status === 404) {
const tag_name = config.github_ref.replace("refs/tags/", "");
const name = config.input_name || tag_name;
const body = config.input_body;
const draft = config.input_draft;
let release = yield gh.repos.createRelease({
owner,
repo,
tag_name,
name,
body,
draft
});
return release.data;
}
else {
throw error;
}
}
});
45 changes: 45 additions & 0 deletions lib/main.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(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 core = __importStar(require("@actions/core"));
const github_1 = require("@actions/github");
const util_1 = require("./util");
const github_2 = require("./github");
function run() {
return __awaiter(this, void 0, void 0, function* () {
try {
const config = util_1.parseConfig(process.env);
if (!util_1.isTag(config.github_ref)) {
throw new Error(`⚠️ GitHub Releases requires a tag`);
}
// todo: validate github_ref is a tag
const gh = new github_1.GitHub(config.github_token);
let rel = yield github_2.release(config, gh);
if (config.input_files) {
util_1.paths(config.input_files).forEach((path) => __awaiter(this, void 0, void 0, function* () {
yield github_2.upload(gh, rel.upload_url, path);
}));
}
console.log(`🎉 Release ready at ${rel.html_url}`);
}
catch (error) {
core.setFailed(error.message);
}
});
}
run();
31 changes: 31 additions & 0 deletions lib/util.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"use strict";
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 glob = __importStar(require("glob"));
const fs_1 = require("fs");
exports.parseConfig = (env) => {
return {
github_token: env.GITHUB_TOKEN || "",
github_ref: (env.GITHUB_REF || ""),
github_repository: env.GITHUB_REPOSITORY || "",
input_name: env.INPUT_NAME,
input_body: env.INPUT_BODY,
input_body_path: env.INPUT_BODY_PATH,
input_files: (env.INPUT_FILES || "").split(","),
input_draft: env.INPUT_DRAFT === 'true'
};
};
exports.paths = (patterns) => {
return patterns.reduce((acc, pattern) => {
return acc.concat(glob.sync(pattern).filter(path => fs_1.lstatSync(path).isFile()));
}, []);
};
exports.isTag = (ref) => {
return ref.startsWith("refs/tags/");
};
Loading

0 comments on commit 18daf2c

Please sign in to comment.