All Projects → JasonEtco → Actions Toolkit

JasonEtco / Actions Toolkit

Licence: mit
🛠 A toolkit for building GitHub Actions in Node.js

Programming Languages

typescript
32286 projects

Projects that are alternatives of or similar to Actions Toolkit

Galaxy
Data intensive science for everyone.
Stars: ✭ 812 (-4.25%)
Mutual labels:  workflow
Gitpr
Quick reference guide on fork and pull request workflow
Stars: ✭ 902 (+6.37%)
Mutual labels:  workflow
Microflow
Microservice orchestration inspired by AWS Step functions and Apache Airflow
Stars: ✭ 24 (-97.17%)
Mutual labels:  workflow
Docs
Lightweight document management system packed with all the features you can expect from big expensive solutions
Stars: ✭ 827 (-2.48%)
Mutual labels:  workflow
Cookiecutter
DEPRECIATED! Please use nf-core/tools instead
Stars: ✭ 18 (-97.88%)
Mutual labels:  workflow
Fastscape
A fast, versatile and user-friendly landscape evolution model
Stars: ✭ 22 (-97.41%)
Mutual labels:  toolkit
Ipt
Interactive Pipe To: The Node.js cli interactive workflow
Stars: ✭ 783 (-7.67%)
Mutual labels:  workflow
Gwen Nolegacy Opentk Renderer
A C# port of the GWEN GUI library, with an OpenTK renderer
Stars: ✭ 26 (-96.93%)
Mutual labels:  toolkit
Lodsve Framework
Let our development of Spring very easy!
Stars: ✭ 18 (-97.88%)
Mutual labels:  toolkit
Alfred Unicode
Preview Unicode characters and emoji in Alfred
Stars: ✭ 23 (-97.29%)
Mutual labels:  workflow
Codevar
生成可用的代码变量 (CodeVar that return u a better variable from Chinese to English . )
Stars: ✭ 834 (-1.65%)
Mutual labels:  workflow
Wf wcf samples
Windows Communication Foundation (WCF) and Windows Workflow Foundation (WF) Samples
Stars: ✭ 17 (-98%)
Mutual labels:  workflow
Perl Workflow
Simple, flexible system to implement workflows
Stars: ✭ 10 (-98.82%)
Mutual labels:  workflow
Scipipe
Robust, flexible and resource-efficient pipelines using Go and the commandline
Stars: ✭ 826 (-2.59%)
Mutual labels:  workflow
Tincture
Frontend development toolkit for ClojureScript
Stars: ✭ 24 (-97.17%)
Mutual labels:  toolkit
Ntl
Node Task List: Interactive cli to list and run package.json scripts
Stars: ✭ 800 (-5.66%)
Mutual labels:  workflow
Hzdtf.foundation.framework
基础框架系统,支持.NET和.NET Core平台,语言:C#,DB支持MySql和SqlServer,主要功能有抽象持久化、服务层,将业务基本的增删改查抽离复用;提供代码生成器从DB生成实体、持久化、服务以及MVC控制器,每层依赖接口,并需要在客户端将对应实现层用Autofac程序集依赖注入,用AOP提供日志跟踪、事务、模型验证等。对Autofac、Redis、RabbitMQ封装扩展;DB访问提供自动主从访问,Redis客户端分区。特别适合管理系统。
Stars: ✭ 22 (-97.41%)
Mutual labels:  workflow
Feflow
🚀 A command line tool aims to improve front-end engineer workflow and standard, powered by TypeScript.
Stars: ✭ 942 (+11.08%)
Mutual labels:  workflow
Xtd forms
Modern c++17 library to create native gui for Microsoft Windows, Apple macOS and Linux.
Stars: ✭ 25 (-97.05%)
Mutual labels:  toolkit
Gvanno
Generic germline variant annotation pipeline
Stars: ✭ 23 (-97.29%)
Mutual labels:  workflow

GitHub Actions Toolkit

An opinionated toolkit for building GitHub Actions in Node.js
UsageAPIHow to test your ActionFAQ

GitHub Actions status Codecov

This toolkit is an opinionated alternative to (and wrapper around) the official toolkit. actions/toolkit makes many features optional in the interest of performance, so you may prefer to use it instead of this library.

Usage

Installation

$ npm install actions-toolkit
const { Toolkit } = require('actions-toolkit')
const tools = new Toolkit()

Bootstrap a new action

$ npx actions-toolkit my-cool-action

This will create a new folder my-cool-action with the following files:

├── Dockerfile
├── action.yml
├── index.js
├── index.test.js
└── package.json

API

Toolkit options

event (optional)

An optional list of events that this action works with. If omitted, the action will run for any event - if present, the action will exit with a failing status code for any event that is not allowed.

const tools = new Toolkit({
  event: ['issues', 'pull_requests']
})

You can also pass a single string:

const tools = new Toolkit({
  event: 'issues'
})

And/or strings that include an action (what actually happened to trigger this event) for even more specificity:

const tools = new Toolkit({
  event: ['issues.opened']
})

secrets (optional)

You can choose to pass a list of secrets that must be included in the workflow that runs your Action. This ensures that your Action has the secrets it needs to function correctly:

const tools = new Toolkit({
  secrets: ['SUPER_SECRET_KEY']
})

If any of the listed secrets are missing, the Action will fail and log a message.

token (optional)

You can pass a custom token used for authenticating with the GitHub API:

const tools = new Toolkit({
  token: '1234567890abcdefghi'
})

The github_token input or process.env.GITHUB_TOKEN will be used if no token was passed.

Toolkit.run

Run an asynchronous function that receives an instance of Toolkit as its argument. If the function throws an error (or returns a rejected promise), Toolkit.run will log the error and exit the action with a failure status code.

The toolkit instance can be configured by passing Toolkit options as the second argument to Toolkit.run.

Toolkit.run(async tools => {
  // Action code
}, { event: 'push' })

tools.github

Returns an Octokit SDK client authenticated for this repository. See https://octokit.github.io/rest.js for the API.

const newIssue = await tools.github.issues.create({
  ...tools.context.repo,
  title: 'New issue!',
  body: 'Hello Universe!'
})

You can also make GraphQL requests:

const result = await tools.github.graphql(query, variables)

See https://github.com/octokit/graphql.js for more details on how to leverage the GraphQL API.

Note: To make this function, you must pass a GitHub API token to your action. You can do this in the workflow - both of these are automatically used if they exist:

uses: your/[email protected]
with:
  github_token: ${{ github.token }}
env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

tools.log

This library comes with a slightly-customized instance of Signale, a great logging utility. Check out their docs for the full list of methods. You can use those methods in your action:

tools.log('Welcome to this example!')
tools.log.info('Gonna try this...')
try {
  risky()
  tools.log.success('We did it!')
} catch (error) {
  tools.log.fatal(error)
}

In the GitHub Actions output, this is the result:

ℹ  info      Welcome to this example!
ℹ  info      Gonna try this...
✖  fatal     Error: Something bad happened!
    at Object.<anonymous> (/index.js:5:17)
    at Module._compile (internal/modules/cjs/loader.js:734:30)

tools.inputs

GitHub Actions workflows can define some "inputs" - options that can be passed to the action:

uses: JasonEtco/[email protected]
with:
  foo: bar

You can access those using tools.inputs:

console.log(tools.inputs.foo) // -> 'bar'

Note! This is not a plain object, it's an instance of Proxy, so be aware that there may be some differences.


tools.outputs

GitHub Actions workflows can define some "outputs" - options that can be passed to the next actions. You can access those using tools.outputs:

tools.outputs.foo = 'bar'

Note! This is not a plain object, it's an instance of Proxy, so be aware that there may be some differences.


tools.command(command, (args, match) => Promise)

Respond to a slash-command posted in a GitHub issue, comment, pull request, pull request review or commit comment. Arguments to the slash command are parsed by minimist. You can use a slash command in a larger comment, but the command must be at the start of the line:

Hey, let's deploy this!
/deploy --app example --container node:alpine
tools.command('deploy', async (args: ParsedArgs, match: RegExpExecArray) => {
  console.log(args)
  // -> { app: 'example', container: 'node:alpine' }
})

The handler will run multiple times for each match:

/deploy 1
/deploy 2
/deploy 3
let i = 0
await tools.command('deploy', () => { i++ })
console.log(i)
// -> 3

tools.getPackageJSON()

Get the package.json file in the project root and returns it as an object.

const pkg = tools.getPackageJSON()

tools.readFile(path, [encoding = 'utf8'])

Get the contents of a file in the repository. Should be used with actions/checkout to clone the repository in the actions workflow.

const contents = await tools.readFile('example.md')

tools.exec

Run a CLI command in the workspace. This uses @actions/exec under the hood so check there for the full usage.

const result = await tools.exec('npm audit')

tools.token

The GitHub API token being used to authenticate requests.


tools.workspace

A path to a clone of the repository.


tools.exit

A collection of methods to end the action's process and tell GitHub what status to set (success, neutral or failure). Internally, these methods call process.exit with the appropriate exit code. You can pass an optional message to each one to be logged before exiting. This can be used like an early return:

if (someCheck) tools.exit.neutral('No _action_ necessary!')
if (anError) tools.exit.failure('We failed!')
tools.exit.success('We did it team!')

tools.context

tools.context.action

The name of the action

tools.context.actor

The actor that triggered the workflow (usually a user's login)

tools.context.event

The name of the event that triggered the workflow

tools.context.payload

A JSON object of the webhook payload object that triggered the workflow

tools.context.ref

The Git ref at which the action was triggered

tools.context.sha

The Git sha at which the action was triggered

tools.context.workflow

The name of the workflow that was triggered.

tools.context.issue

The owner, repo, and issue_number params for making API requests against an issue or pull request.

tools.context.pullRequest

The owner, repo, and pull_number params for making API requests against a pull request.

tools.context.repo

The owner and repo params for making API requests against a repository. This uses the GITHUB_REPOSITORY environment variable under the hood.

How to test your GitHub Actions

Similar to building CLIs, GitHub Actions usually works by running a file with node <file>; this means that writing a complete test suite can be tricky. Here's a pattern for writing tests using actions-toolkit, by mocking Toolkit.run:

index.js
const { Toolkit } = require('actions-toolkit')
Toolkit.run(async tools => {
  tools.log.success('Yay!')
})
index.test.js
const { Toolkit } = require('actions-toolkit')
describe('tests', () => {
  let action

  beforeAll(() => {
    // Mock `Toolkit.run` to redefine `action` when its called
    Toolkit.run = fn => { action = fn }
    // Require the index.js file, after we've mocked `Toolkit.run`
    require('./index.js')
  })

  it('logs successfully', async () => {
    // Create a fake instance of `Toolkit`
    const fakeTools = new Toolkit()
    // Mock the logger, or whatever else you need
    fakeTools.log.success = jest.fn()
    await action(fakeTools)
    expect(fakeTools.log.success).toHaveBeenCalled()
  })
})

You can then mock things by tweaking environment variables and redefining tools.context.payload. You can check out this repo's tests as an example.

Motivation

actions-toolkit is a wrapper around some fantastic open source libraries, and provides some helper methods for dealing with the GitHub Actions runtime. Actions all run in Docker containers, so this library aims to help you focus on your code and not the runtime. You can learn more about building Actions in Node.js to get started!

After building a GitHub Action in Node.js, it was clear to me that I was writing code that other actions will want to use. Reading files from the repository, making requests to the GitHub API, or running arbitrary executables on the project, etc.

So, I thought it'd be useful to build those out into a library to help you build actions in Node.js 🎉

FAQ

Aren't these just wrappers around existing functions?

Yep! I just didn't want to rewrite them for my next Action, so here we are.

What's the difference between this and actions/toolkit?

This library was the inspiration for the official toolkit. Nowadays, it's an opinionated alternative. My goal for the library is to make building simple actions easy, while the official toolkit needs to support more complicated use-cases (like performance and scaling concerns).

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].