Reuse GitHub Actions workflows across repositories
On first run, ghat will copy a workflow from another GitHub repo. Successive runs will update the existing workflows and preserve the env variables.
- Write workflows once, use them in any repository
- Update your workflows without copy-pasting YAML
- Preserve local envvariables
- Customize workflows before importing them
The good parts:
- ghatdoes not run every time on your CI
- ghatdoesn't have to be a dependency of your project
- ghatis node-based, but can install any type of workflows
- Workflow changes need to be committed by the user, so you don't have to worry about it suddenly breaking "because of a dependency"
Requirements:
- git
- npm or yarn (you can use npx ghat ...oryarn dlx ghat ...to run it without installing it)
- a writable ~/.degitcache folder as required by degit
ghat uses degit to fetch any repository or specific YAML file/folder within it. Below you can find some examples using the workflows in fregante/ghatemplates.
$ ghat --help
  Description
    Reuse GitHub Actions workflows across repositories
  Usage
    $ ghat <source> [options]
  Options
    --exclude        Any part of the YAML file to be removed (can be repeated)
    --set            Value to add (can be repeated). The value is interpreted as YAML/JSON. Writing JSON on the CLI is tricky, so you might want to wrap the whole flag value
    -v, --version    Displays current version
    -h, --help       Displays this message
  Examples
    $ ghat fregante/ghatemplates/node
    $ ghat fregante/ghatemplates/node --exclude jobs.Build --exclude jobs.Test
    $ ghat fregante/ghatemplates/node --set on=push
    $ ghat fregante/ghatemplates/node --set 'jobs.Test.container=node:12.15'
    $ ghat fregante/ghatemplates/node-multi --set jobs.build.strategy.matrix.node-version=\[8.x,10.x\]
    $ ghat fregante/ghatemplates/node/build.ymlIf you provide a user/repo address, ghat will fetch the repository and look for *.yml/*.yaml files at the top level. If none are found, it will assume you want to copy the repo’s active workflows from .github/workflows
npx ghat fregante/ghat
# Copies *.yml OR .github/workflows/*.ymlnpx ghat fregante/ghatemplates/node
# Copies node/*.yml into the local .github/workflows. It's NOT recursivenpx ghat fregante/ghatemplates/node/ci.yml
# Copies node/ci.yml into the local .github/workflows/ci.ymlYou can exclude any property from the template by using the --exclude <path> flag, multiple times.
- pathis parsed by dot-prop, so refer to its documentation.
--exclude on.scheduleYou can set/overwrite any value with the --set <path>=<value> flag, multiple times.
- pathis parsed by dot-prop, so refer to its documentation.
- valueis a YAML/JSON value passed directly to the YAML parser.
Note: writing JSON on the command line is a little tricky, so if you're running into errors, try wrapping the whole flag value into a string, for example:
--set 'on.schedule=[{"cron": "42 17 * * 4"}]'When you fetch a workflow that already exists locally, the local file will be overridden, except for the top-level env object. For example:
env:
  ADJECTIVE: cool
# DO NOT EDIT BELOW - use `npx ghat fregante/workflows/demo`
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - run: echo My workflow is $ADJECTIVEenv:
  ADJECTIVE: the default
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - run: echo This new workflow is "$ADJECTIVE" since it was updatedOnly the top-level env will be preserved, the rest will be updated.
env:
  ADJECTIVE: cool
# DO NOT EDIT BELOW - use `npx ghat fregante/workflows/demo`
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - run: echo This new workflow is "$ADJECTIVE" since it was updatedGitHub Actions Templating
I won’t pretend to know exactly what a Ghat is, but you should know check them out, they’re beautiful. 🇮🇳
MIT © Federico Brigante