Morrison-Lab/gha

Central, reusable GitHub Actions for R-package and Quarto repositories

This site documents Morrison-Lab/gha, a set of reusable GitHub Actions shared across the d-morrison, UCD-SERG, ucdavis, UCLA-PHP, and UCD-IDDRC owners. It is modeled on r-lib/actions and easystats/workflows: a repo calls a shared workflow with a tiny stub instead of carrying its own copy.

The repo is public so it can be referenced from repositories across those owners.

How it works

Each capability ships as two layers:

  • A composite action (for example check-bibliography-dois/action.yml) bundles the real steps and any helper script. It is referenced as Morrison-Lab/gha/<name>@vN (the major tag that capability currently recommends - see Versioning).
  • A reusable workflow (.github/workflows/<name>.yml, on: workflow_call) wraps the composite, declares permissions, and checks out the caller’s repo. This is what consumer repos target.

A consumer repo adds a small caller stub (see the examples/ directory):

name: Check Bibliography DOIs
on:
  push: { branches: [main] }
  pull_request:
  workflow_dispatch:
jobs:
  check:
    uses: Morrison-Lab/gha/.github/workflows/check-bibliography-dois.yml@v2

Pin to the major tag that capability currently recommends (@v2 in the example above) - it varies per capability rather than defaulting uniformly to @v1; see Versioning for the full breakdown. Do not reference @main from consumers.

Actions vs. workflows

NoteComposite action

A composite action is a list of steps. It runs inside a job that already exists - the caller’s runner and permissions are already in place. An action has no concept of jobs or triggers; it is just a named bundle of commands.

# <name>/action.yml
name: My Action
description: Does a thing
inputs:
  my-input:
    description: ...
runs:
  using: composite
  steps:
    - run: echo "hello"
      shell: bash
NoteReusable workflow

A reusable workflow is a complete pipeline. It defines its own jobs, each with its own runner (runs-on:), permissions (permissions:), and steps. A consumer calls it as a job, not as a step.

# .github/workflows/<name>.yml
on: workflow_call
jobs:
  my-job:
    runs-on: ubuntu-latest
    permissions:
      contents: read
    steps:
      - uses: actions/checkout@v4
      - run: echo "hello"
Warningshell: is required in composite actions

Every run: step in a composite action must declare shell:. Workflows have a default shell; composite actions do not.

Composite action Reusable workflow
Key top-level keys name, description, inputs, outputs, runs on, jobs
Jobs No - only steps under runs Yes - one or more jobs blocks
runs-on Absent - inherits the caller’s runner Per job
permissions Absent Yes (caller must also grant them)
Called from A job’s steps (via uses) A workflow’s jobs (via uses)

Because an action cannot declare permissions or choose its runner, this repo uses the two-layer design: the composite action holds the real logic, and the reusable workflow wraps it to handle the runner, permissions, and checkout. Consumer repos reference only the workflow layer.

Where to go next

  • Workflows catalogs every reusable workflow and what it does.
  • Permissions lists the GITHUB_TOKEN permissions and secrets each one needs.
  • Versioning explains the moving major tags (@v1/@v2, per capability) and how third-party actions are pinned.

This very site is built and shipped by the workflows it documents: quarto-publish deploys it to GitHub Pages, and the preview family renders a preview for each pull request.