Skip to content

fix: initialize git submodules and freeze the lockfile in the web session setup hook - #10348

Open
dgarros wants to merge 2 commits into
stablefrom
claude/sweet-clarke-cgqq2a
Open

fix: initialize git submodules and freeze the lockfile in the web session setup hook#10348
dgarros wants to merge 2 commits into
stablefrom
claude/sweet-clarke-cgqq2a

Conversation

@dgarros

@dgarros dgarros commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

Why

Two independent defects in dev/setup-environment.sh, the SessionStart hook for Claude Code on the web. One is new, one is a backport of a fix already on develop.

1. Submodules are never initialized. The web container clones without --recurse-submodules, so python_sdk and frontend/packages/schema-visualizer are empty when the hook runs. Both are consumed as local paths rather than published packages, and neither installer treats an empty directory as an error — so setup reports success while producing a broken environment.

2. The lockfile churns on every session. A plain pnpm install re-resolves the caret ranges in package.json and picks up whatever transitive versions have been published since the lockfile was committed, rewriting pnpm-lock.yaml. Observed on a real session: oxlint 1.74→1.77, @oxc-parser 0.141→0.143, a new @astrojs/compiler — a 780-line diff nobody asked for. This was fixed on develop in #9972 but never reached stable.

Goal: every web session starts with both submodules populated and a clean working tree, or setup stops with a clear error.

Non-goals: no change to how submodules are pinned or updated, and no change to the Python install command.

What changed

Two commits against stable:

  • fix: initialize git submodules in the web session setup hook (new) — runs git submodule update --init --recursive above the Python and frontend installers, then asserts the two expected manifests exist so a partial fetch stops setup instead of silently degrading it. The command is already the canonical one documented in dev/guidelines/git-workflow.md.
  • fix(setup): use --frozen-lockfile in setup hook to stop lockfile churn (#9972) — cherry-picked from develop (65efe7bf, provenance recorded via cherry-pick -x). One line, unmodified from the original.

Net: +23 / -1 in one file. No dependency, lockfile, schema, or CI changes. The script still runs exclusively in the claude-code-web environment — the existing SUPPORTED_ENVIRONMENTS gate is untouched, so local and CI runs exit early exactly as before. uv.lock and pnpm-lock.yaml are unmodified.

Why the submodule failures are silent

python_sdk/infrahub_sdk is vendored into the infrahub-server distribution via [tool.hatch.build.targets.wheel.sources], not installed as a separate dependency. With the directory empty, uv sync succeeds and builds a wheel containing no infrahub_sdkimport infrahub works while import infrahub_sdk raises ModuleNotFoundError. 317 backend modules import infrahub_sdk, so anything touching the SDK was broken in every web session.

frontend/packages/schema-visualizer is a pnpm workspace package; with the directory empty pnpm resolves it to a link with no dependency graph and installs 43 fewer packages.

How to review

The submodule block is ordering-sensitive — it must stay above the Python section, which is the entire point of that commit. The second commit is a verbatim cherry-pick; reviewing it against #9972 is enough.

How to test

# Reproduce the broken state a fresh web session starts in
git submodule deinit -f --all

# Run the hook exactly as SessionStart does
CLAUDE_ENV_FILE=1 bash dev/setup-environment.sh

# Verify
uv run --no-sync python -c "import infrahub_sdk, infrahub, infrahub_testcontainers"
git submodule status   # both at pinned commits, no +/- prefix
git status --porcelain # clean -- no lockfile churn

Observed on this branch with both commits applied: exit 0, both submodules checked out at the pinned commits, all three imports succeed, pnpm reports all 5 workspace projects in scope, and the working tree stays clean. Re-running is idempotent. The manifest guard was exercised separately against an empty directory and exits 1 with the expected message.

shellcheck on the file reports only a pre-existing SC2064 at the gh install trap, which this PR leaves alone.

Impact & rollout

  • Backward compatibility: none affected. CI already checks out with submodules: true, so CI behavior is unchanged.
  • Performance: roughly 4s of submodule cloning per web session; --frozen-lockfile makes the frontend install faster by skipping resolution.
  • Config/env changes: none.
  • Deployment notes: safe to deploy; takes effect on the next web session.

Checklist

  • Tests added/updated — n/a, this is an environment bootstrap script with no test harness; validated by the reproduction above.
  • Changelog entry added — deliberately skipped: dev tooling only, no user-facing or ops-facing behavior, so it does not belong in release notes.
  • External docs updated — n/a, not user-facing.
  • Internal .md docs updated — no change needed; dev/guidelines/git-workflow.md already documents the submodule command, and the change makes the setup script follow it.
  • I have reviewed AI generated content

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 1 file

Confidence score: 3/5

  • In dev/setup-environment.sh, a successful uv sync can still leave infrahub_sdk unimportable while setup reports success, causing downstream failures that are harder to diagnose — re-run the import check after rebuilding and fail setup if it still fails.
  • dev/setup-environment.sh has no automated regression coverage for the new manifest-failure and poisoned-venv rebuild paths, so future changes could silently break recovery behavior — add focused tests for both paths.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="dev/setup-environment.sh">

<violation number="1" location="dev/setup-environment.sh:98">
P2: Custom agent: **Flag AI Slop and Fabricated Changes**

This behavior change has no automated regression test: the new manifest failure path and poisoned-venv rebuild path rely only on manual verification. Add a focused shell/Bats test that asserts missing manifests fail and the recovery path is invoked.</violation>

<violation number="2" location="dev/setup-environment.sh:120">
P1: When the initial import check fails, this rebuild is the only subsequent validation; a successful `uv sync` can still leave `infrahub_sdk` unimportable, after which setup reports success. Re-run the import check after rebuilding and exit nonzero if it still fails.</violation>
</file>

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

Comment thread dev/setup-environment.sh Outdated
# Force the rebuild when the import is broken.
if ! uv run --no-sync python -c "import infrahub_sdk" &> /dev/null; then
echo "infrahub_sdk is not importable, rebuilding infrahub-server..."
uv sync --all-groups --reinstall-package infrahub-server

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When the initial import check fails, this rebuild is the only subsequent validation; a successful uv sync can still leave infrahub_sdk unimportable, after which setup reports success. Re-run the import check after rebuilding and exit nonzero if it still fails.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At dev/setup-environment.sh, line 120:

<comment>When the initial import check fails, this rebuild is the only subsequent validation; a successful `uv sync` can still leave `infrahub_sdk` unimportable, after which setup reports success. Re-run the import check after rebuilding and exit nonzero if it still fails.</comment>

<file context>
@@ -73,13 +73,53 @@ echo "Project directory: $PROJECT_DIR"
+    # Force the rebuild when the import is broken.
+    if ! uv run --no-sync python -c "import infrahub_sdk" &> /dev/null; then
+        echo "infrahub_sdk is not importable, rebuilding infrahub-server..."
+        uv sync --all-groups --reinstall-package infrahub-server
+    fi
+
</file context>
Suggested change
uv sync --all-groups --reinstall-package infrahub-server
uv sync --all-groups --reinstall-package infrahub-server
if ! uv run --no-sync python -c "import infrahub_sdk" &> /dev/null; then
echo "Error: infrahub_sdk is still not importable after rebuilding infrahub-server" >&2
exit 1
fi

Comment thread dev/setup-environment.sh
exit 1
fi

for manifest in "python_sdk/pyproject.toml" "frontend/packages/schema-visualizer/package.json"; do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: Custom agent: Flag AI Slop and Fabricated Changes

This behavior change has no automated regression test: the new manifest failure path and poisoned-venv rebuild path rely only on manual verification. Add a focused shell/Bats test that asserts missing manifests fail and the recovery path is invoked.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At dev/setup-environment.sh, line 98:

<comment>This behavior change has no automated regression test: the new manifest failure path and poisoned-venv rebuild path rely only on manual verification. Add a focused shell/Bats test that asserts missing manifests fail and the recovery path is invoked.</comment>

<file context>
@@ -73,13 +73,53 @@ echo "Project directory: $PROJECT_DIR"
+    exit 1
+fi
+
+for manifest in "python_sdk/pyproject.toml" "frontend/packages/schema-visualizer/package.json"; do
+    if [ ! -f "$PROJECT_DIR/$manifest" ]; then
+        echo "Error: $manifest is missing after submodule initialization" >&2
</file context>

Claude Code on the web clones the repository without --recurse-submodules, so
python_sdk and frontend/packages/schema-visualizer are empty when the
SessionStart hook runs dev/setup-environment.sh. Both are consumed as local
paths rather than published packages, and neither installer treats an empty
directory as an error:

  - python_sdk/infrahub_sdk is vendored into the infrahub-server distribution
    via [tool.hatch.build.targets.wheel.sources], so uv builds a wheel with no
    infrahub_sdk in it. `import infrahub` works while `import infrahub_sdk`
    raises ModuleNotFoundError, breaking the 317 backend modules that use it.
  - frontend/packages/schema-visualizer is a pnpm workspace package, which pnpm
    resolves to a link with no dependency graph.

Both failures are silent, so the session looks correctly provisioned. Initialize
the submodules before the installers run and verify the expected manifests
exist, so a partial fetch stops setup instead of degrading it.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Ppx4cTBD3xq76fvRu1joqm
@dgarros
dgarros force-pushed the claude/sweet-clarke-cgqq2a branch from 4afb42e to 41cf861 Compare August 20, 2026 17:07
@dgarros
dgarros requested a review from a team as a code owner August 20, 2026 17:07
@dgarros
dgarros changed the base branch from develop to stable August 20, 2026 17:07
@codspeed-hq

codspeed-hq Bot commented Aug 20, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 13 untouched benchmarks


Comparing claude/sweet-clarke-cgqq2a (41cf861) with stable (efe6cad)

Open in CodSpeed

@dgarros dgarros changed the title fix: initialize git submodules in the web session setup hook fix: initialize git submodules and freeze the lockfile in the web session setup hook Aug 20, 2026

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 1 file (changes from recent commits).

Confidence score: 3/5

  • dev/setup-environment.sh can swallow a pnpm install failure and still report success, leaving development environments partially broken and making diagnosis harder; propagate the install failure or verify the command result before printing success.
Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="dev/setup-environment.sh">

<violation number="1" location="dev/setup-environment.sh:118">
P2: This swallows a pnpm install failure and then unconditionally prints "Frontend dependencies installed", so a failed frontend install leaves the environment partially broken while the script reports success. The PR's stated goal is to "fail clearly" and "prevent silent, partially-working environments," but this change does the opposite: with `set -e` active, `cmd || echo ... (continuing)` makes the compound command exit 0, then execution continues and `exit 0` reports success. `--frozen-lockfile` makes failure more likely (any lockfile drift aborts), so the failure path is not rare. This is also a regression from the prior `pnpm install` line, which would abort on failure. Drop the `|| echo ...(continuing)` guard (and the unconditional success echo) so a frontend install failure aborts setup, consistent with the submodule manifest guard which exits 1.</violation>
</file>

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

Comment thread dev/setup-environment.sh
Comment on lines +118 to 119
pnpm install --frozen-lockfile || echo "Warning: pnpm install failed (continuing)"
echo "Frontend dependencies installed"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This swallows a pnpm install failure and then unconditionally prints "Frontend dependencies installed", so a failed frontend install leaves the environment partially broken while the script reports success. The PR's stated goal is to "fail clearly" and "prevent silent, partially-working environments," but this change does the opposite: with set -e active, cmd || echo ... (continuing) makes the compound command exit 0, then execution continues and exit 0 reports success. --frozen-lockfile makes failure more likely (any lockfile drift aborts), so the failure path is not rare. This is also a regression from the prior pnpm install line, which would abort on failure. Drop the || echo ...(continuing) guard (and the unconditional success echo) so a frontend install failure aborts setup, consistent with the submodule manifest guard which exits 1.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At dev/setup-environment.sh, line 118:

<comment>This swallows a pnpm install failure and then unconditionally prints "Frontend dependencies installed", so a failed frontend install leaves the environment partially broken while the script reports success. The PR's stated goal is to "fail clearly" and "prevent silent, partially-working environments," but this change does the opposite: with `set -e` active, `cmd || echo ... (continuing)` makes the compound command exit 0, then execution continues and `exit 0` reports success. `--frozen-lockfile` makes failure more likely (any lockfile drift aborts), so the failure path is not rare. This is also a regression from the prior `pnpm install` line, which would abort on failure. Drop the `|| echo ...(continuing)` guard (and the unconditional success echo) so a frontend install failure aborts setup, consistent with the submodule manifest guard which exits 1.</comment>

<file context>
@@ -115,7 +115,7 @@ echo "Installing frontend dependencies with pnpm..."
     if [ -d "$PROJECT_DIR/frontend/app" ]; then
         cd "$PROJECT_DIR/frontend/app"
-        pnpm install
+        pnpm install --frozen-lockfile || echo "Warning: pnpm install failed (continuing)"
         echo "Frontend dependencies installed"
         cd "$PROJECT_DIR"
</file context>
Suggested change
pnpm install --frozen-lockfile || echo "Warning: pnpm install failed (continuing)"
echo "Frontend dependencies installed"
pnpm install --frozen-lockfile
echo "Frontend dependencies installed"

Comment thread dev/setup-environment.sh
exit 1
fi

for manifest in "python_sdk/pyproject.toml" "frontend/packages/schema-visualizer/package.json"; do

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this like a healthcheck, that submodules were cloned successfully?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes exactly .. not sure if this is really required .. Claude came up with it

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something with git submodule status?

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.

4 participants