Implement module system for composable CI configuration
Summary
This MR implements a module system for gitlab.ci that enables composable CI configuration. Multiple modules can now contribute stages and jobs that are automatically merged together.
This is the first step toward the architecture described in issue #2 (closed), allowing us to extract common CI functionality (omnix, cachix, discover, etc.) into separate reusable modules.
Key Changes
- Add
gitlab.ci.modulesoption that accepts a list of modules - Each module can define
stages(list) andjobs(attrset) - Module evaluation uses
lib.evalModuleswith properspecialArgs - Stages are concatenated and deduplicated
- Jobs are merged together (later modules override earlier ones)
- Make
stagesandjobsoptions have sensible defaults
Example Usage
perSystem = { pkgs, ... }: {
gitlab.ci = {
enable = true;
modules = [
# Omnix devour module
({ pkgs, ... }: {
stages = [ "build" ];
jobs.omnix-devour = {
stage = "build";
script = [ "${pkgs.omnix}/bin/om ci run" ];
};
})
# Cachix push module
({ pkgs, ... }: {
stages = [ "publish" ];
jobs.cachix-push = {
stage = "publish";
script = [ "cachix push horizon" ];
};
})
];
};
};
Backward Compatibility
The existing direct stages and jobs options still work - they are merged with module-contributed stages and jobs.
Next Steps
This enables us to:
- Extract common patterns into standalone modules
- Allow projects to compose CI functionality as needed
- Make horizon-gen-nix and other tools ship their own CI modules
- Reduce duplication across projects