Skip to content

feat(module): pin module version (version field, ?ref=, --ref)#39

Open
rickliujh wants to merge 2 commits into
mainfrom
feat/module-version
Open

feat(module): pin module version (version field, ?ref=, --ref)#39
rickliujh wants to merge 2 commits into
mainfrom
feat/module-version

Conversation

@rickliujh

@rickliujh rickliujh commented Jul 25, 2026

Copy link
Copy Markdown
Owner

What

A git module previously always cloned its source's default branch, so a run tracked whatever was on main at the time. This adds a way to pin a module to an exact branch, tag, or commit so runs are reproducible.

Three ways to set it, one for each place a module is named:

  • Child modules — a visible version: field alongside name/source/params (the preferred form), templatable:
    modules:
      - name: networking
        source: https://github.com/org/modules.git//networking
        version: v1.4.0            # or "{{ .modVersion }}"
  • CLI / root module — a short --ref flag on loom run / loom diff:
    loom run https://github.com/org/modules.git//onboard --ref v1.4.0 -p serviceName=payments
  • ?ref= suffix on any git source (Terraform convention), for the root or a child source:
    loom run 'https://github.com/org/modules.git//onboard?ref=v1.4.0'

Precedence: --ref flag → version field → ?ref= suffix. Pinning a local source is an error (already fixed on disk).

How

  • config.ModuleRef gains a templatable Version field, validated like other templatable fields.
  • module.ResolveSource(source, version, parentDir, logger) takes an explicit version and merges it with any ?ref= suffix (explicit wins), clones in full, then checks out the ref.
  • New git.Checkout — go-git ResolveRevision + checkout, with a git checkout CLI fallback (resolves refs go-git can't, e.g. remote-tracking branches). No Repository interface change.
  • The executor renders modules[].version with the parent's params and passes it down.
  • --ref flag added to loom run and loom diff, threaded to ResolveSource (flag beats a ?ref= suffix).

Spec & docs

  • New behavioral rule M5 (Version pinning) in specs/module.md, plus updates to the child-module inputs table, source-pattern table, the T4 templatable list, the run/diff flag tables, and the execution flow.
  • Guide + reference docs updated (README, module-composition, loom-yaml, cli-run, cli-diff).

Tests

  • git.Checkout tag checkout (go-git and CLI paths) + unknown-ref error.
  • version-field resolution, field-overrides-?ref= precedence, and local-source rejection for both spellings.
  • CLI --ref pins the root source (cmd test).
  • Full suite + spectrace guard green; go vet clean.

Verified end-to-end against a real repo: child version: default → v1 content; -p modVersion=v2 → v2 content; --ref v1 on the root → v1 content; --ref overrides ?ref=; bogus version → pinning module "..." to version "v9": git checkout v9: exit status 1.

🤖 Generated with Claude Code

rickliujh and others added 2 commits July 25, 2026 23:35
A git module previously always cloned its source's default branch, so a
run tracked whatever was on main. Add version pinning to a branch, tag,
or commit:

- spec.modules[].version — a visible, templatable field on child module
  references (the preferred form).
- ?ref=<version> — a Terraform-style suffix on the source string, for the
  CLI/root source (which has no modules[] entry to hold a field). Also
  accepted in a child source; the version field takes precedence.

ResolveSource takes an explicit version and combines it with any ?ref=
suffix, then clones in full and checks out the ref via a new git.Checkout
(go-git ResolveRevision with git-CLI fallback). Pinning a local source is
an error. Documented as spec rule M5 with referencing tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The version field covers child modules, but the root module is named on
the command line and had no field. Add a short --ref flag to `loom run`
and `loom diff` that pins the root source to a git branch, tag, or commit.
It threads through the same ResolveSource path and takes precedence over a
?ref= suffix on the source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@rickliujh rickliujh changed the title feat(module): pin module version via version field and ?ref= feat(module): pin module version (version field, ?ref=, --ref) Jul 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant