Skip to content

Contributing

Issues and pull requests are welcome on GitHub. This page covers the workspace layout, how to build and test locally, the conventions the codebase follows, and the specific steps for adding a new validation rule.

gapline is a Cargo workspace with two crates:

CratePathRole
gapline-corecore/Feed parsing, validation engine, CRUD primitives, integrity index, rules.
gaplinecli/The CLI binary — argument parsing, output rendering, config loader, .gl runner.
gapline/
├── Cargo.toml # Workspace root manifest.
├── LICENSE
├── README.md
├── core/
│ ├── src/
│ ├── benches/
│ └── tests/
└── cli/
├── src/
├── CHANGELOG.md
└── tests/
  • Rust 1.70 or later. Install with rustup.
  • A C toolchain (for the zip crate’s native dependencies).

Optional but recommended:

  • cargo-nextest for faster test runs.
  • prek for pre-commit hooks (a prek.toml is checked in).

Build both crates from the workspace root:

Terminal window
cargo build --workspace
cargo build --workspace --release

The CLI binary lands at target/release/gapline.

Run the full test suite:

Terminal window
cargo test --workspace

Or with nextest if installed:

Terminal window
cargo nextest run --workspace

Unit tests live in #[cfg(test)] modules next to the code they exercise. Integration tests are under <crate>/tests/. The core crate has benchmarks under core/benches/:

Terminal window
cargo bench -p gapline-core

clippy is configured to fail on warnings. Run both CI-equivalent checks locally before opening a PR:

Terminal window
cargo fmt --all -- --check
cargo clippy --workspace -- -D warnings

Commit subjects follow Conventional Commits (visible in the CLI changelog):

  • feat: add speed_validation rule
  • fix(cli): correct --feed help text grammar
  • perf(core): drop double alloc in required_id/optional_id

The categories used in the changelog are feat, fix, perf, and feat! (breaking).

  1. Pick a stage. Rules live under core/src/validation/<stage>/. The existing stages are file_structure, csv_formatting, field_definition, field_type, foreign_key, primary_key, schedule_time_validation, best_practices, and third_party.

  2. Implement the rule. Each rule implements a validation trait in its stage module. Return ValidationError values with rule_id, severity, message, and as much location context (file_name, line_number, field_name, value) as the rule can provide.

  3. Register the rule. Add it to the registry in core/src/validation/rules.rs so gapline rules list picks it up.

  4. Add tests. A unit test covering the positive and negative cases inside the same module. An integration test under core/tests/ if the rule cuts across multiple files.

  5. Document the rule. The rule ID will be auto-included in the validation rules catalogue once the build-time JSON generator runs (see the in-progress dump task under cli/src/bin/).

  1. Add the field to the relevant variant of Commands in cli/src/cli/parser.rs.
  2. Wire it through to the command’s runner under cli/src/cli/commands/.
  3. Update the command’s reference page under doc-site/src/content/docs/reference/cli/.
  4. If the flag has an equivalent in gapline.toml, add the key to core/src/config.rs and update doc-site/src/content/docs/reference/configuration-file.md.

The .gl runner is in cli/src/cli/runner/. Directives are parsed in parser.rs and dispatched in executor.rs. When adding a new directive:

  1. Extend DirectiveKind in parser.rs.
  2. Add the parsing function.
  3. Add the executor branch.
  4. Document the directive on .gl syntax.

Treat every contributor with respect. The repository follows the Contributor Covenant; be kind, be clear, and stay on topic.