Lunar Collector Skill
Create collector plugins for Earthly Lunar—Bash scripts that gather SDLC metadata and write it to the Component JSON for policy evaluation.
Quick Start
- •Read about-lunar.md for platform overview
- •Read core-concepts.md for architecture and key entities
- •Read collector-reference.md for comprehensive collector documentation
Collector Basics
A collector is a Bash script that:
- •Gathers data (from files, CI artifacts, external APIs)
- •Writes to the Component JSON using
lunar collect
#!/bin/bash
set -e
if [ -f ./README.md ]; then
lunar collect -j ".repo.readme_exists" true \
".repo.readme_num_lines" "$(wc -l < ./README.md)"
else
lunar collect -j ".repo.readme_exists" false
fi
Plugin Structure
my-collector/ ├── lunar-collector.yml # Required: plugin config ├── main.sh # Main script ├── Dockerfile # Optional: for containerization ├── README.md # Documentation └── install.sh # Optional: install dependencies
lunar-collector.yml:
version: 0
name: my-collector
description: Collects X data
author: team@example.com
default_image: earthly/lunar-scripts:1.0.0
collectors:
- name: my-collector
mainBash: main.sh
hook:
type: code # or: cron, ci-after-command, ci-after-job, etc.
inputs:
threshold:
description: Minimum threshold
default: "10"
Hook Types
| Hook | Trigger | Use Case |
|---|---|---|
code | Git push | File analysis, config parsing |
cron | Schedule | External API queries |
ci-after-command | After CI command | Capture test coverage, scan results |
ci-after-job | After CI job | Job-level artifact collection |
The lunar collect Command
# String value lunar collect ".repo.language" "go" # JSON values (use -j) lunar collect -j ".repo.readme_exists" true lunar collect -j ".coverage.percentage" 85.5 # Multiple values lunar collect -j ".repo.readme_exists" true ".repo.readme_lines" 150 # Pipe JSON from stdin cat results.json | lunar collect -j ".test.results" -
Environment Variables
| Variable | Description |
|---|---|
LUNAR_COMPONENT_ID | Component identifier |
LUNAR_COMPONENT_PR | PR number (if in PR context) |
LUNAR_COMPONENT_GIT_SHA | Git SHA being evaluated |
LUNAR_PLUGIN_ROOT | Plugin root directory |
LUNAR_SECRET_<NAME> | Secrets |
Inputs are available as uppercase environment variables (e.g., THRESHOLD for input threshold).
Reference Documentation
For detailed information, read these files in the references/ directory:
| File | Content |
|---|---|
| about-lunar.md | Platform overview, why Lunar exists |
| core-concepts.md | Architecture, Component JSON, hooks, enforcement levels |
| collector-reference.md | Complete collector guide - hooks, environment variables, patterns |
| component-json/conventions.md | Component JSON schema design principles, presence detection, source metadata |
| component-json/structure.md | Component JSON schema categories (.repo, .k8s, .sca, etc.) with examples |
| strategies.md | Implementation strategies (CI detection, file parsing, API integration) |
| collector-README-template.md | README template for collector plugins |
Full Lunar Documentation
For the complete Lunar platform documentation including installation, configuration, CLI reference, and SDK details, see docs/SUMMARY.md.
Local Development & Testing
Run collectors locally to test before deploying. Commands must be run from a directory containing lunar-config.yml.
Prerequisites:
- •Set
LUNAR_HUB_TOKENenvironment variable for authentication - •Be in a directory with a valid
lunar-config.yml
Run a collector against a remote component:
lunar collector dev <collector-name> --verbose --component github.com/org/repo
Run a collector against a local directory:
lunar collector dev <collector-name> --verbose --component-dir ../path/to/local/repo
Test a CI collector with a fake command:
lunar collector dev <collector-name> --fake-ci-cmd "npm test" --component github.com/org/repo
Collector names are dot-separated (e.g., k8s.yaml-collection, dockerfile.base-images).
The command outputs the resulting Component JSON to stdout, which can be piped to lunar policy dev for end-to-end testing:
lunar collector dev my-collector --component github.com/org/repo | \ lunar policy dev my-policy --component-json -
Best Practices
- •Always use
set -e- Exit on errors - •Use structured JSON - Group related data together
- •Include source metadata - Tool name, version, integration type
- •Document Component JSON paths - In README.md
- •Use
earthly/lunar-scripts:1.0.0- Official base image for containerized collectors - •Handle missing data gracefully - Check file existence before processing
Common Patterns
File parsing with find command input:
inputs:
find_command:
description: Command to find files
default: "find . -type f -name '*.yaml'"
CI artifact collection:
# Hook: ci-after-command with pattern: ^go test.*
if [ -f coverage.out ]; then
COVERAGE=$(go tool cover -func=coverage.out | grep total | awk '{print $3}' | tr -d '%')
lunar collect -j ".testing.coverage.percentage" "$COVERAGE"
fi
External API query:
RESPONSE=$(curl -fsS -H "Authorization: Bearer $LUNAR_SECRET_API_TOKEN" \ "https://api.example.com/repos/$LUNAR_COMPONENT_ID/status") echo "$RESPONSE" | lunar collect -j ".external.status" -