diff --git a/README.md b/README.md index e66e45cb..7bf6de1f 100644 --- a/README.md +++ b/README.md @@ -3,54 +3,35 @@

+## Toolkit +The toolkit provides a set of packages to make creating actions easier and drive consistency. ## Packages +The toolkit provides four separate packages. Since actions are run by pulling actions from the github graph, dependencies including the packages are vendored into your action. + | Package | Description | | ------- | ----------- | -| [@actions/core](packages/core) | Core functions for setting results, logging, secrets and environment variables | +| [@actions/core](packages/core) | Core functions for getting inputs, setting outputs, setting results, logging, secrets and environment variables | | [@actions/exec](packages/exec) | Functions necessary for running tools on the command line | | [@actions/io](packages/io) | Core functions for CLI filesystem scenarios | | [@actions/tool-cache](packages/tool-cache) | Functions necessary for downloading and caching tools | -## Development +## Creating an Action with the Toolkit -This repository uses [Lerna](https://github.com/lerna/lerna#readme) to manage multiple packages. Read the documentation there to begin contributing. +Actions are units of work which can either run in a container or on the host machine. -Note that before a PR will be accepted, you must ensure: -- all tests are passing -- `npm run format` reports no issues -- `npm run lint` reports no issues +[Choosing an action type](docs/action-types.md): Outlines the differences and why you would want to create a host or a container based action. -### Useful Scripts +[JavaScript Action Walthrough](docs/node12-action.md): Create an action which runs on the host using the toolkit -- `npm run bootstrap` This runs `lerna bootstrap` which will install dependencies in this repository's packages and cross-link packages where necessary. -- `npm run build` This compiles TypeScript code in each package (this is especially important if one package relies on changes in another when you're running tests). This is just an alias for `lerna run tsc`. -- `npm run format` This checks that formatting has been applied with Prettier. -- `npm test` This runs all Jest tests in all packages in this repository. - - If you need to run tests for only one package, you can pass normal Jest CLI options: - ```console - $ npm test -- packages/toolkit - ``` -- `npm run create-package [name]` This runs a script that automates a couple of parts of creating a new package. +[Docker Action Walkthrough](docs/container-action.md): Create an action that is delivered as a container and run with docker. -### Creating a Package +[Docker Action Walkthrough with Octokit](docs/container-action-toolkit.md): Create an action that is delivered as a container which uses the toolkit. This example uses the GitHub context to construct an Octokit client. -1. In a new branch, create a new Lerna package: +[Versioning](docs/action-versioning.md): Recommendations on versioning, releases and tagging your action. -```console -$ npm run create-package new-package -``` +## Contributing -This will ask you some questions about the new package. Start with `0.0.0` as the first version (look generally at some of the other packages for how the package.json is structured). - -2. Add `tsc` script to the new package's package.json file: - -```json -"scripts": { - "tsc": "tsc" -} -``` - -3. Start developing 😄 and open a pull request. +We welcome contributions. See [how to contribute](docs/contribute.md). \ No newline at end of file diff --git a/docs/action-types.md b/docs/action-types.md new file mode 100644 index 00000000..d5036c57 --- /dev/null +++ b/docs/action-types.md @@ -0,0 +1,45 @@ +# Action Types + +There are two types of actions. JavaScript and Docker actions. + +- **JavaScript Actions**: JavaScript actions run on the host machine. The unit of work is decoupled from the environment. +- **Docker Actions**: A container action is a container which carries both the unit of work along with the environment and it's dependencies packaged up as a container. + +Both have access to the workspace and the github event payload and context. + +## Why would I choose a Docker action? + +Docker actions carry both the unit of work and the environment. + +This creates a more consistent and reliable unit of work where the consumer of the action does not need to worry about the toolsets and it's dependencies. + +Docker actions are currently limited to Linux only. + +## Why would I choose a host action? + +JavaScript actions decouple the unit of work from the environment and run directly on the host machine or VM. + +Consider a simple example of testing a node lib on node 8, 10 and running a custom action. Each job will setup a node version on the host and custom-action will run it's unit of work on each environment (node8+ubunut16, node8+windows-2019, etc.) + +```yaml +on: push + +jobs: + build: + strategy: + matrix: + node: [8.x, 10.x] + os: [ubuntu-16.04, windows-2019] + runs-on: ${{matrix.os}} + actions: + - uses: actions/setup-node@master + with: + version: ${{matrix.node}} + - run: | + npm install + - run: | + npm test + - uses: actions/custom-action@master +``` + +JavaScript actions work on any environment that host action runtime is supported on which is currently node 12. However, a host action that runs a toolset expects the environment that it's running on to have that toolset in it's PATH or using a setup-* action to acquire it on demand. \ No newline at end of file diff --git a/docs/action-versioning.md b/docs/action-versioning.md new file mode 100644 index 00000000..534a1b19 --- /dev/null +++ b/docs/action-versioning.md @@ -0,0 +1,29 @@ +# Versioning + +Actions are downloaded and run from the GitHub graph of repos. The workflow references an action use a ref. + +Examples: + +```yaml +steps: + - use: actions/setup-node@74bc508 + - user: actions/setup-node@v1 + - uses: actions/setup-node@master +``` + +Binding to the immutable sha1 of a released version is the safest for stability and security. + +Binding to a specific major version allows for receiving critical fixes and security patches while still mainting compatibility and the assurance your workflow should still work. + +Binding to master is convenient but if a new major version is release which breaks compatilibility, your workflow could break. + +# Recommendations + +1. **Create a release**: use sematic versioning for the release (v1.0.9) +2. **Update the major version tag**: move the major version tag (v1, v2, etc.) to point to the ref of the current release. +3. **Compaitbility Breaks**: introduce a new major version tag (v2) if changes will break existing workflows. For example, changing inputs. + +See [Git-Basics-Tagging](https://git-scm.com/book/en/v2/Git-Basics-Tagging) + + + diff --git a/docs/assets/node12-template.png b/docs/assets/node12-template.png new file mode 100644 index 00000000..ba8cba17 Binary files /dev/null and b/docs/assets/node12-template.png differ diff --git a/docs/container-action-toolkit.md b/docs/container-action-toolkit.md new file mode 100644 index 00000000..fb274d1f --- /dev/null +++ b/docs/container-action-toolkit.md @@ -0,0 +1,3 @@ +# Creating a Container Action Using the Toolkit + +In progress. \ No newline at end of file diff --git a/docs/container-action.md b/docs/container-action.md new file mode 100644 index 00000000..417035f4 --- /dev/null +++ b/docs/container-action.md @@ -0,0 +1,71 @@ +# Creating a Docker Action + +The [container-template](https://github.com/actions/container-template) repo contains the base files to create a Docker action. + +# Create a Repo from the Template + +Navigate to https://github.com/actions/container-template + +Click on `Use this template` to create the repo for your action. + +![template](assets/node12-template.png) + +Complete creating your repo and clone the repo. + +> NOTE: The location of the repo will be how users will reference your action in their workflow file with the using keyword. + +e.g. To use https://github.com/actions/setup-node, user's will author: + +```yaml +steps: + using: actions/setup-node@master +``` + +# Define Metadata + +Your action has a name and a description. Update the author. + +Create inputs that your unit of work will need. These will be what workflow authors set with the `with:` keyword. + +```yaml +name: 'My Container Action' +description: 'Get started with Container actions' +author: 'GitHub' +inputs: + myInput: + description: 'Input to use' + default: 'world' +runs: + using: 'docker' + image: 'Dockerfile' + args: + - ${{ inputs.myInput }} +``` + +It will be run with docker and the input is mapped into the args + +# Change Code + +The entry point is in entrypoint.sh + +```bash +#!/bin/sh -l + +echo "hello $1" +``` + +# Publish + +Simply push your action to publish. + +```bash +$ git push +``` + +The runner will download the action and build the docker container on the fly at runtime. + +> Consider versioning your actions with tags. See [versioning](docs/action-versioning.md) + + + + diff --git a/docs/contribute.md b/docs/contribute.md new file mode 100644 index 00000000..a27741c1 --- /dev/null +++ b/docs/contribute.md @@ -0,0 +1,40 @@ +## Development + +This repository uses [Lerna](https://github.com/lerna/lerna#readme) to manage multiple packages. Read the documentation there to begin contributing. + +Note that before a PR will be accepted, you must ensure: +- all tests are passing +- `npm run format` reports no issues +- `npm run lint` reports no issues + +### Useful Scripts + +- `npm run bootstrap` This runs `lerna bootstrap` which will install dependencies in this repository's packages and cross-link packages where necessary. +- `npm run build` This compiles TypeScript code in each package (this is especially important if one package relies on changes in another when you're running tests). This is just an alias for `lerna run tsc`. +- `npm run format` This checks that formatting has been applied with Prettier. +- `npm test` This runs all Jest tests in all packages in this repository. + - If you need to run tests for only one package, you can pass normal Jest CLI options: + ```console + $ npm test -- packages/toolkit + ``` +- `npm run create-package [name]` This runs a script that automates a couple of parts of creating a new package. + +### Creating a Package + +1. In a new branch, create a new Lerna package: + +```console +$ npm run create-package new-package +``` + +This will ask you some questions about the new package. Start with `0.0.0` as the first version (look generally at some of the other packages for how the package.json is structured). + +2. Add `tsc` script to the new package's package.json file: + +```json +"scripts": { + "tsc": "tsc" +} +``` + +3. Start developing 😄 and open a pull request. diff --git a/docs/node12-action.md b/docs/node12-action.md new file mode 100644 index 00000000..d8a2273c --- /dev/null +++ b/docs/node12-action.md @@ -0,0 +1,124 @@ +# Creating a JavaScript Action + +The [node12-template](https://github.com/actions/node12-template) repo contains everything you need to get started. + +# Create a Repo from the Template + +Navigate to https://github.com/actions/node12-template + +Click on `Use this template` to create the repo for your action. + +![template](assets/node12-template.png) + +Complete creating your repo and clone the repo. + +> NOTE: The location of the repo will be how users will reference your action in their workflow file with the using keyword. + +e.g. To use https://github.com/actions/setup-node, user's will author: + +```yaml +steps: + using: actions/setup-node@master +``` + +# Install Dependencies + +This will install the toolkit and other dependencies + +```bash +$ npm install +``` + +The production dependencies are vendored into your action. At runtime, the self contained action will be downloaded, extracted and run. + +# Define Metadata + +Your action has a name and a description. Update the author. + +Create inputs that your unit of work will need. These will be what workflow authors set with the `with:` keyword. + +```yaml +name: 'My new action' +description: 'A test action' +author: 'GitHub' +inputs: + myInput: + description: 'Input to use' + default: 'world' +runs: + using: 'node12' + main: 'lib/main.js' + +``` + +Note that the action will be run with node 12 (carried by the runner) and the entry point is specified with `main:` + +# Change Code and Add Tests + +The entry point is in main.ts + +```typescript +import * as core from '@actions/core'; + +async function run() { + try { + const myInput = core.getInput('myInput'); + core.debug(`Hello ${myInput}!`); + } catch (error) { + core.setFailed(error.message); + } +} + +run(); +``` + +Modify tests in `__tests__\main.test.ts`. The template uses [jest](https://github.com/facebook/jest). + +# Format the Code + +```bash +$ npm run format +``` + +# Build and Test + +```bash +$ npm run build + +> node12-template-action@0.0.0 build /Users/user/Projects/testnode12 +> tsc + +$ npm test + +> jest + + PASS __tests__/main.test.ts + TODO - Add a test suite + ✓ TODO - Add a test (1ms) + +Test Suites: 1 passed, 1 total +... +``` + +# Commit and Push Changes + +```bash +$ git add +$ git commit -m "Message" +``` + +> husky will add/vendor node_modules and prune dev dependencies. See husky in package.json for details. There is no need for you to add node_modules. + +# Publish Action + +Simply push your action to publish. + +```bash +$ git push +``` + +> NOTE: Consider versioning your actions with tags. See [versioning](docs/action-versioning.md) + + + +