diff --git a/.github/workflows/checkin.yml b/.github/workflows/checkin.yml deleted file mode 100644 index cf4f0d6..0000000 --- a/.github/workflows/checkin.yml +++ /dev/null @@ -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) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..8b2ff78 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,17 @@ +name: "Test JavaScript Action" +on: + push: + branches: + - 'releases/*' # only run in release distribution branches + +jobs: + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v1 + + - run: npm ci + - run: npm test + - uses: actions/typescript-action@releases/v1 + with: + milliseconds: 1000 diff --git a/.gitignore b/.gitignore index 0ca55a6..ffdd18c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ __tests__/runner/* +# comment out in distribution branches +node_modules/ + # Rest pulled from https://github.com/github/gitignore/blob/master/Node.gitignore # Logs logs @@ -41,7 +44,6 @@ bower_components build/Release # Dependency directories -node_modules/ jspm_packages/ # TypeScript v1 declaration files diff --git a/README.md b/README.md index d19ca99..7560101 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,115 @@ # Create a JavaScript Action using TypeScript -This template offers an easy way to get started writing a JavaScript action with TypeScript compile time support, unit testing with Jest and using the GitHub Actions Toolkit. +# Create a JavaScript Action -## Getting Started +Use this template to bootstrap the creation of a JavaScript action.:rocket: -See the walkthrough located [here](https://github.com/actions/toolkit/blob/master/docs/typescript-action.md). +This template includes compilication support, tests, a validation workflow, publishing, and versioning guidance. -In addition to walking your through how to create an action, it also provides strategies for versioning, releasing and referencing your actions. +If you are new, there's also a simpler introduction. See the [Hello World JavaScript Action](https://github.com/actions/hello-world-javascript-action) + +## Create an action from this template + +Click the `Use this Template` and provide the new repo details for your action + +## Code in Master + +Install the dependencies +```bash +$ npm install +``` + +Build the typescript +```bash +$ npm run build +``` + +Run the tests :heavy_check_mark: +```bash +$ npm test + + PASS ./index.test.js + ✓ throws invalid number (3ms) + ✓ wait 500 ms (504ms) + ✓ test runs (95ms) + +... +``` + +## Change action.yml + +The action.yml contains defines the inputs and output for your action. + +Update the action.yml with your name, description, inputs and outputs for your action. + +See the [documentation](https://help.github.com/en/articles/metadata-syntax-for-github-actions) + +## Change the Code + +Most toolkit and CI/CD operations involve async operations so the action is run in an async function. + +```javascript +import * as core from '@actions/core'; +... + +async function run() { + try { + ... + } + catch (error) { + core.setFailed(error.message); + } +} + +run() +``` + +See the [toolkit documentation](https://github.com/actions/toolkit/blob/master/README.md#packages) for the various packages. + +## Publish to a distribution branch + +Actions are run from GitHub repos. We will create a releases branch and only checkin production modules (core in this case). + +Comment out node_modules in .gitignore and create a releases/v1 branch +```bash +# comment out in distribution branches +# node_modules/ +``` + +```bash +$ git checkout -b releases/v1 +$ git commit -a -m "prod dependencies" +``` + +```bash +$ npm prune --production +$ git add node_modules +$ git commit -a -m "prod dependencies" +$ git push origin releases/v1 +``` + +Your action is now published! :rocket: + +See the [versioning documentation](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) + +## Validate + +You can now validate the action by referencing the releases/v1 branch + +```yaml +uses: actions/javascript-action@releases/v1 +with: + milliseconds: 1000 +``` + +See the [actions tab](https://github.com/actions/javascript-action/actions) for runs of this action! :rocket: + +## Usage: + +After testing you can [create a v1 tag](https://github.com/actions/toolkit/blob/master/docs/action-versioning.md) to reference the stable and tested action + +```yaml +uses: actions/typescript-action@v1 +with: + milliseconds: 1000 +``` diff --git a/__tests__/main.test.ts b/__tests__/main.test.ts index 48f15ff..4c437c4 100644 --- a/__tests__/main.test.ts +++ b/__tests__/main.test.ts @@ -1,3 +1,23 @@ -describe('TODO - Add a test suite', () => { - it('TODO - Add a test', async () => {}); +import {wait} from '../src/wait' +import * as process from 'process' +import * as cp from 'child_process' +import * as path from 'path' + +test('throws invalid number', async() => { + await expect(wait('foo')).rejects.toThrow('milleseconds not a number'); }); + +test('wait 500 ms', async() => { + const start = new Date(); + await wait(500); + const end = new Date(); + var delta = Math.abs(end.getTime() - start.getTime()); + expect(delta).toBeGreaterThan(450); +}); + +// shows how the runner will run a javascript action with env / stdout protocol +test('test runs', () => { + process.env['INPUT_MILLISECONDS'] = '500'; + const ip = path.join(__dirname, '..', 'lib', 'main.js'); + console.log(cp.execSync(`node ${ip}`).toString()); +}) \ No newline at end of file diff --git a/lib/main.js b/lib/main.js new file mode 100644 index 0000000..9598b7e --- /dev/null +++ b/lib/main.js @@ -0,0 +1,35 @@ +"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 core = __importStar(require("@actions/core")); +const wait_1 = require("./wait"); +function run() { + return __awaiter(this, void 0, void 0, function* () { + try { + const ms = core.getInput('milliseconds'); + console.log(`Waiting ${ms} milliseconds ...`); + core.debug((new Date()).toTimeString()); + wait_1.wait(parseInt(ms)); + core.debug((new Date()).toTimeString()); + core.setOutput('time', new Date().toTimeString()); + } + catch (error) { + core.setFailed(error.message); + } + }); +} +run(); diff --git a/lib/wait.js b/lib/wait.js new file mode 100644 index 0000000..727df44 --- /dev/null +++ b/lib/wait.js @@ -0,0 +1,11 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +function wait(milliseconds) { + return new Promise((resolve, reject) => { + if (typeof (milliseconds) !== 'number') { + throw new Error('milleseconds not a number'); + } + setTimeout(() => resolve("done!"), milliseconds); + }); +} +exports.wait = wait; diff --git a/package.json b/package.json index ff41092..e77dbff 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ { - "name": "javascript-template-action", + "name": "typescript-action", "version": "0.0.0", "private": true, "description": "JavaScript template action", diff --git a/src/main.ts b/src/main.ts index fae8b12..ec98ef0 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,9 +1,16 @@ import * as core from '@actions/core'; +import {wait} from './wait' async function run() { try { - const myInput = core.getInput('myInput'); - core.debug(`Hello ${myInput}`); + const ms = core.getInput('milliseconds'); + console.log(`Waiting ${ms} milliseconds ...`) + + core.debug((new Date()).toTimeString()) + wait(parseInt(ms)); + core.debug((new Date()).toTimeString()) + + core.setOutput('time', new Date().toTimeString()); } catch (error) { core.setFailed(error.message); } diff --git a/src/wait.ts b/src/wait.ts new file mode 100644 index 0000000..3dcfbdb --- /dev/null +++ b/src/wait.ts @@ -0,0 +1,10 @@ +export function wait(milliseconds) { + return new Promise((resolve, reject) => { + if (typeof(milliseconds) !== 'number') { + throw new Error('milleseconds not a number'); + } + + setTimeout(() => resolve("done!"), milliseconds) + }); +} + \ No newline at end of file