For the complete documentation index, see llms.txt. This page is also available as Markdown.

Validating your config

Validate lunar-config.yml at commit/PR time — before merge — with a Hub-less dry run that runs the same checks the Hub does, plus a generated JSON Schema.

lunar hub pull validates configuration on the Hub, but by then the change has already merged. To catch mistakes before they merge, validate the config in CI on the pull request.

There are two complementary tools:

  1. lunar hub pull --dry-run — the authoritative check, meant to run in CI on your pull requests. It runs the Hub's own load-and-validate steps against the same code (load the config, resolve every uses: plugin, validate the whole manifest, and resolve each component's default branch) and stops before applying anything — so it catches the mistakes a real hub pull would reject after merge, without a separate re-implementation that could drift.

  2. A JSON Schema — generated from the manifest definition, for editor autocomplete and inline structural feedback while you type.

The dry run needs no Hub connection. It does need GitHub access (a LUNAR_GITHUB_TOKEN, or a configured Hub used only as an auth source) to resolve uses: plugins — the same access the Hub itself uses to fetch them. This is what lets it catch plugin-resolution problems that a purely structural check would miss.

lunar hub pull --dry-run

lunar hub pull --dry-run <repo>

<repo> is the config repository ref, e.g. github://acme-corp/lunar@my-branch. The dry run clones it, loads lunar-config.yml (and any lunar-config.d/ fragments), resolves every uses: plugin, and runs the full manifest validation — required fields, enum values, hook/cron shape, on: expressions, domain references, and whether each referenced plugin actually exists and resolves. It exits non-zero and prints the failure if anything is wrong, and never contacts the Hub or applies the manifest.

It runs the Hub's own PullManifest load-and-validate code — the Fetch pipeline plus the same component default-branch resolution the Hub performs before persisting — so a component pointing at a typo'd or inaccessible repo fails the dry run too, not just a real pull.

Pre-merge validation in CI

Run the dry run on every pull request against your config repo. The example below is for GitHub Actions — it's provided as a starting point; adapt the CLI install and the invocation to whatever CI system you use. It needs a token that can read the config repo and the plugin repos it references.

It intentionally runs on all pull requests rather than only when lunar-config.yml changes: the dry run resolves and validates every referenced plugin, including local ./-path plugins in collectors/, policies/, or catalogers/, so a PR that edits one of those without touching lunar-config.yml is still checked. (A paths: filter would skip those.)

name: Validate Lunar config

on:
  pull_request:

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - name: Install Lunar CLI
        run: |
          curl -fsSL -o lunar "https://github.com/earthly/lunar-dist/releases/latest/download/lunar-linux-amd64"
          chmod +x lunar
          sudo mv lunar /usr/local/bin/lunar
      - name: Dry-run the config
        env:
          LUNAR_GITHUB_TOKEN: ${{ secrets.LUNAR_GITHUB_TOKEN }}
        run: |
          lunar hub pull --dry-run "github://${{ github.repository }}@${{ github.event.pull_request.head.sha }}"

Pin the CLI to a specific release (e.g. .../releases/download/v1.2.3/lunar-linux-amd64) instead of latest for reproducible CI. The token needs read access to the config repo and any private plugin repos it uses:.

JSON Schema (editor autocomplete)

For editor autocomplete and inline structural validation as you edit, the CLI emits a JSON Schema (draft-07 format) for lunar-config.yml, generated from the same manifest definition the Hub uses:

Commit that file and point your editor at it. In VS Code, for example:

Last updated