-
Notifications
You must be signed in to change notification settings - Fork 4
Embedded Modules #600
Description
Overview
Nullstone is built around a philosophy of reusable, battle-tested infrastructure modules published to a shared registry. However, not every module warrants that level of ceremony. Sometimes a team needs a quick, app-specific module — one that is best iterated on directly alongside the application code it supports.
The Embedded Modules epic closes this gap by allowing users to define Terraform/OpenTofu modules directly inside an application repository (or a dedicated module monorepo), and rely on Nullstone to automatically detect changes, publish new module versions, and synchronize infrastructure — all driven by the existing GitOps pipeline.
This epic also introduces a first-class CLI command (nullstone iac apply --publish) that allows developers to publish and apply module changes manually in a single step, both locally and in CI/CD pipelines.
Problem Statement
Today, contributing a Terraform/OpenTofu module to Nullstone requires a developer to:
- Create and maintain a separate module repository.
- Manually package, version, and publish the module to the Nullstone registry.
- Update the referencing workspace to point to the new version.
- Run or wait for a GitOps-triggered apply.
This overhead is justified for shared, stable modules consumed across many teams. It is not justified when a developer simply needs a custom RDS configuration, a one-off IAM policy module, or an app-specific network rule — artifacts that change frequently and are owned by a single team.
The result is that developers either avoid using modules for these cases (duplicating IaC inline) or bypass Nullstone's module system entirely, losing auditability and GitOps integration.
Goals
- Allow modules to live inside an application repo or a dedicated module monorepo, alongside the code they support.
- Automate module publishing as part of the GitOps push/merge lifecycle.
- Ensure publish and IaC sync are properly sequenced so infrastructure always reflects the latest committed module.
- Provide a CLI path for manual publish + apply, suitable for local development and CI/CD.
- Maintain compatibility with existing GitOps and module registry behavior.
Non-Goals
- Replacing the existing registry-based module workflow for shared/stable modules.
- Supporting cross-repo version propagation in the initial release (deferred to the module monorepo feature).
- Auto-promoting embedded module versions to named release channels.
Stories
| # | Story | Description |
|---|---|---|
| 1 | Module Discovery & Configuration | Allow users to declare embedded modules in .nullstone/config.yml, with support for custom paths and monorepo layouts. |
| 2 | Auto-Publish on GitOps Push | Detect module changes on merge and automatically publish a new build version before IaC sync runs. |
| 3 | IaC Sync + Publish Sequencing | Guarantee that module publishing completes before IaC sync so the correct version is applied. |
| 4 | CLI: nullstone iac apply --publish |
Provide a single CLI command to publish a module and run a plan/apply, for local development and CI/CD use. |
| 5 | Module Monorepo Support | Support a dedicated repository of multiple modules with independent per-module change detection and publishing. |
Key Design Decisions
Module Location
Users may declare modules anywhere in the repository. A default convention of .nullstone/modules/<module-name>/ is supported out of the box. Explicit path overrides are declared in .nullstone/config.yml.
Versioning
Embedded modules are published as build versions using a git SHA-based pre-release scheme (0.0.0-<short-sha>). This is intentionally ephemeral — build versions are not promoted to release channels without explicit action.
Change Detection
Nullstone uses a two-layer strategy: a git diff of the module path for efficiency, followed by a content hash of the packaged module artifact as the source of truth. A module is only published if the content hash differs from the last published version.
Publish/Sync Ordering
Within any GitOps event, module publishing must complete before IaC sync begins. This is an engine-level constraint, not a configuration option.
Local Development
The CLI supports a --local-module override (analogous to Terraform's dev_overrides) that allows developers to test module changes locally against a sandbox environment without publishing to the registry.
Out of Scope (Future)
- PR plan previews: Running a Nullstone plan on every pull request commit (referenced in the workflow as a future step).
- Cross-repo version propagation: Notifying downstream app repos when a module monorepo publishes a new version.
- Channel promotion: Promoting embedded module build versions to
stableorlatestchannels.