Skip to content

Embedded Modules #600

@BSick7

Description

@BSick7

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:

  1. Create and maintain a separate module repository.
  2. Manually package, version, and publish the module to the Nullstone registry.
  3. Update the referencing workspace to point to the new version.
  4. 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 stable or latest channels.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions