Skip to content

devx-cafe/gh-insitu

Repository files navigation

gh-insitu

A self-contained parallel task runner for the GitHub CLI.

InSitu brings parity between local development and CI by letting you define checks once in .insitu.yml and run them identically on your machine and inside GitHub Actions workflows.

Latest release Release workflow


Installation

Requires the GitHub CLI (gh) to be installed.

gh extension install devx-cafe/gh-insitu

Verify:

gh insitu --help

Quick start

# Bootstrap a starter .insitu.yml and a pre-commit hook
gh insitu init

# Validate the config and preview the execution plan
gh insitu plan

# Run all waves
gh insitu run

# Run a specific wave
gh insitu run static

# Apply a boilerplate commit from another repo
gh insitu boilerplate --repo lakruzz/boilerplates --ref cspell

.insitu.yml syntax

The configuration file uses three top-level sections:

# .insitu.yml

# 1. Global defaults – inherited by all checks
defaults:
  die-on-error: true # stop after the first failing wave
  timeout: 5m # default per-check timeout (Go duration string)
  verbose: false # print command output for every check (not just failures)

# 2. Inventory – the library of named checks
inventory:
  - id: "build"
    name: "Build" # human-readable label (optional; falls back to id)
    command: "make build"
    timeout: 10m # per-check timeout override (optional)
    die-on-error: false # per-check die-on-error override (optional)

  - id: "coverage"
    name: "Unit Test with Coverage"
    command: "make coverage"

# 3. Waves – ordered execution groups that reference inventory ids
waves:
  - id: "static"
    name: "Static Analysis & Build"
    parallel: true # run all checks in this wave concurrently
    checks:
      - "build"

  - id: "test"
    name: "Post-Build Validation"
    parallel: true
    checks:
      - "coverage"

Field reference

Field Required Description
defaults.die-on-error no Stop after the first wave that has a failure. Default: false.
defaults.timeout no Fallback timeout for every check. Go duration string (e.g. 5m, 30s). Default: 5m.
defaults.verbose no Print full command output for all checks. Default: false (CI: true).
inventory[].id yes Unique identifier, referenced by waves.
inventory[].name no Display name shown in output.
inventory[].command yes Shell command to execute.
inventory[].timeout no Override defaults.timeout for this check.
inventory[].die-on-error no Override defaults.die-on-error for this check.
waves[].id yes Unique wave identifier.
waves[].name no Display name for the wave.
waves[].parallel no When true, all checks in the wave run concurrently. Default: false.
waves[].checks yes List of inventory id values to execute.

Config file discovery

By default every command looks for .insitu.yml in the current working directory. You can override this with the --config / -c flag on any command:

gh insitu run --config path/to/custom.yml
gh insitu plan -c ci/checks.yml

Commands

insitu init

Creates a starter .insitu.yml and installs a .git/hooks/pre-commit hook that runs insitu run before every commit.

gh insitu init               # create .insitu.yml + pre-commit hook
gh insitu init --force       # overwrite an existing .insitu.yml
gh insitu init -c custom.yml # write config to a custom path

insitu plan

Validates the configuration and prints the resolved execution plan (timeouts, commands, die-on-error settings). No checks are actually run.

gh insitu plan
gh insitu plan --config custom.yml

insitu run

Executes one or more waves. Without arguments all waves run in order.

gh insitu run                            # run all waves
gh insitu run static                     # run only the 'static' wave
gh insitu run static test                # run 'static' then 'test'
gh insitu run --verbose                  # always print all command output
gh insitu run --mark-pending             # mark all checks as 'pending' (CI only)
gh insitu run trunk-worthy --mark-pending

Inside a GitHub Actions workflow (GITHUB_ACTIONS=true):

  • Each check result is automatically reported as a GitHub commit status.
  • Output is wrapped in ::group:: / ::endgroup:: for collapsible log sections.
  • Use --mark-pending as an early step to show checks as pending while the workflow runs.

insitu boilerplate

Fetch the files changed by the tip commit of a branch (or any ref) from a remote GitHub repository and apply them to the current working tree.

For each file in the boilerplate commit:

  • File does not exist locally → written directly (parent directories are created as needed).
  • File already exists → merged according to --strategy (see below).
  • File is removed by the commit → skipped.

--strategy merge (default)

Non-destructive apply. The template is used as BOTH the common ancestor and the "other" side; the local file is "current". Because base == other, git sees no incoming changes from the template — only local additions and modifications survive. All existing local content is preserved; template-only lines are not forced in.

--strategy combine

Full union. Uses an empty common ancestor and --union, so both the local file and the template contribute all their lines. The result contains every line from both sides in order. Zero conflict markers are ever produced.

--strategy inject

Programmatic deep-merge: for each key or array item in the template, add/update it in the existing file. Supported formats: .json, .jsonc (comments are stripped on write), .yml, .yaml. Other file types fall back to combine. Never produces conflict markers.

By default the command refuses to run on a dirty working tree. Use --allow-dirty to skip that guard.

gh insitu boilerplate --repo lakruzz/boilerplates --ref cspell
gh insitu boilerplate --repo org/templates --ref main --allow-dirty
gh insitu boilerplate --repo org/templates --ref cspell --strategy combine
gh insitu boilerplate --repo org/templates --ref cspell --strategy inject
Flag Required Description
--repo yes Source repository in owner/repo format.
--ref no Branch, tag, or commit SHA to fetch. Default: HEAD.
--strategy no merge (default), combine, or inject. See description above.
--allow-dirty no Skip the clean working-tree check before applying.

A GitHub token must be available via GH_TOKEN or GITHUB_TOKEN.


GitHub Actions example

- name: Mark checks pending
  run: gh insitu run --mark-pending
  env:
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- name: Run all checks
  run: gh insitu run
  env:
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Releases

See the Releases page for all published versions and release notes. Releases are built and published automatically by the Release workflow.


Contributing

See CONTRIBUTING.md for development guidelines, testing practices, and how to set up the local development environment.

About

A strategi for shift-left development. Define you checks and workflows as self-contained in-repo configurations that can run outside GitHubs Workflows — in situ🎯

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors