Help us measure site usage?

With your permission, we use self-hosted analytics to understand page usage. It is optional and does not affect the Service. Learn more.

ScalaadvanceddevopsAI generated

CI Pipeline Configuration Linter

Build a command-line linter in Scala for CI pipeline configuration files, similar in spirit to GitLab CI's YAML format. It reads pipeline files that define stages and jobs, where each job belongs to a stage and can depend on other jobs through needs. It then reports mistakes before they reach the CI server: unknown stages, missing required fields, jobs depending on jobs that don't exist or run in a later stage, and circular dependencies (A needs B needs C needs A). Every error points to the file and line number. You'll learn to parse YAML with SnakeYAML while keeping line information, turn it into typed case classes, collect many errors instead of stopping at the first, and detect cycles in a graph with depth-first search.

Estimate
~14.5h
Steps
7
Completed by
0
Proposed by
codeseed.app

sbt · snakeyaml

Project roadmap

  1. 01

    Set up the project and fixtures

    ~1.5h

    Create an sbt project with Scala 3, adding SnakeYAML and a test library (MUnit or ScalaTest). Define the format in the README: a top-level stages list, and jobs as top-level keys, each with stage (required), script (a required list of commands) and optional needs (a list of job names). Add example pipelines in fixtures/: one valid and several invalid ones. Done when: sbt compile works and the fixtures are in the repo.

  2. 02

    Parse YAML with line numbers

    ~3h

    Use SnakeYAML's compose method, which returns a tree of Nodes, instead of load, so every value keeps its position through getStartMark (line and column). Convert the tree into case classes: Pipeline(stages, jobs) and Job(name, stage, script, needs, line), each field keeping its line. A file that isn't valid YAML becomes one error with SnakeYAML's position. Done when: the valid fixture parses into case classes with correct line numbers.

  3. 03

    Validate structure and references

    ~2.5h

    Write rules that each return a list of errors: every job has a stage and a non-empty script, each job's stage is listed in stages, each entry in needs names an existing job, and a job never needs a job in a later stage. Collect errors from all rules instead of stopping at the first, for example with Either and ValidatedNel-style accumulation or plain lists. Done when: each invalid fixture produces exactly the expected errors.

  4. 04

    Detect circular dependencies

    ~2.5h

    Build a graph from job names to their needs and run depth-first search, marking each node unvisited, in progress or done. Reaching a node that's in progress means a cycle. Report the full cycle path (for example: build -> test -> package -> build) with the line of the first job, and report each distinct cycle once. Done when: a fixture with two separate cycles reports both, and the valid fixture reports none.

  5. 05

    Report errors clearly

    ~1.5h

    Print errors sorted by file and line, like pipelines/ci.yml:14:3: error: job test needs unknown job biuld. Exit with code 1 if there are errors and 0 otherwise. Add --format json for machine-readable output. Done when: the output is sorted, readable, and the exit code matches.

  6. 06

    Lint whole directories

    ~1.5h

    Accept any number of files and directories as arguments. Search directories for .yml and .yaml files, lint each one independently so an error in one file doesn't stop the others, and finish with a summary like 3 files checked, 2 with errors, 5 errors. Done when: running the linter on fixtures/ reports every invalid file and the summary is correct.

  7. 07

    Write tests

    ~2h

    Write tests for each rule, for cycle detection (no cycle, a self-dependency, a long cycle, two cycles), for line numbers in errors, and for invalid YAML. Run the whole CLI against the fixtures and compare its output with expected files. Done when: sbt test passes.

Ready to build this?

Get a GitHub repo and start building. Your AI reviewer checks each step as you go.

~14.5h · 7 steps

Tech stack

sbtsnakeyaml