Skip to content

Conversation

@ryoppippi
Copy link
Member

@ryoppippi ryoppippi commented Jan 3, 2026

Summary

Replaces uv-managed .venv with Nix-managed Python environments using uv2nix. This provides fully reproducible builds with dependencies cached in the Nix store.

What Changed

  • flake.nix: Add uv2nix, pyproject-nix, and pyproject-build-systems inputs
  • devShells: Create shells for Python 3.11 and 3.13 (default, python311, python313)
  • Build overrides: Add setuptools for pypika, editables for stackone-ai
  • CI: Update matrix to use nix develop .#pythonXXX instead of uv sync
  • setup-nix action: Simplify with gc-max-store-size: 4G for cache management
  • justfile: Add lint-fix alias

Why

  • Reproducibility: All dependencies are now managed by Nix store with hash-based caching
  • Faster CI: No need for uv sync step; dependencies are cached with other Nix derivations
  • Multi-version support: Easy to test against Python 3.11 and 3.13 via devShells
  • Backward compatible: uv run commands still work for non-Nix users

Notes

  • The .venv directory is no longer needed (can be deleted locally)
  • Use nix develop (default) or nix develop .#python313 for specific versions

Summary by cubic

Switches Python dependency management to Nix via uv2nix, replacing the uv-managed .venv. Builds are now reproducible, CI is faster with versioned, lockfile-scoped cache keys, and ty runs correctly in Nix shells via VIRTUAL_ENV.

  • New Features

    • Nix-managed envs from uv.lock using uv2nix; deps cached in the Nix store.
    • Dev shells and packages for Python 3.11 and 3.13 (default, python311, python313).
    • Build overrides: setuptools for pypika; editables for stackone-ai. CI uses nix develop .#pythonXXX with cache keys scoped by Python version and flake.lock/uv.lock; setup-nix restores per-version caches and limits store size.
  • Migration

    • Remove your local .venv. Use nix develop (or nix develop .#python313) for a specific version.
    • uv run still works for non-Nix users; commands auto-prefix uv outside Nix shells.

Written for commit 10475d3. Summary will update on new commits.

Replace uv-managed .venv with Nix-managed Python environments using
uv2nix. This provides fully reproducible builds with dependencies
cached in the Nix store, eliminating the need for uv sync in CI.

Key changes:
- Add uv2nix, pyproject-nix, and pyproject-build-systems inputs
- Create devShells for Python 3.11 and 3.13 (default, python311, python313)
- Add build system overrides for pypika (setuptools) and stackone-ai (editables)
- Update CI matrix to use nix develop .#pythonXXX instead of uv sync
- Simplify setup-nix action with gc-max-store-size for cache management
- Add lint-fix alias to justfile

The .venv directory is no longer needed as all dependencies are
managed by Nix. Both Nix and non-Nix users can still use uv run
commands which will work in either environment.
Copilot AI review requested due to automatic review settings January 3, 2026 13:25
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR replaces the uv-managed .venv approach with Nix-managed Python environments using uv2nix, providing fully reproducible builds with dependencies cached in the Nix store.

Key Changes:

  • Integration of uv2nix, pyproject-nix, and pyproject-build-systems for managing Python dependencies through Nix
  • Development shells for multiple Python versions (3.11 and 3.13) with version-specific commands
  • Simplified CI workflow by removing the uv sync step, leveraging Nix store caching instead

Reviewed changes

Copilot reviewed 4 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
flake.nix Adds uv2nix inputs, creates workspace overlay, implements multi-version devShells with Python 3.11 and 3.13, includes build system overrides for pypika and stackone-ai
flake.lock Updates dependency locks including new uv2nix-related inputs and repository ownership change for flake-compat (edolstra → NixOS)
.github/workflows/ci.yaml Updates CI matrix to use Nix devShell selectors (python311, python313) and removes uv sync installation step
.github/actions/setup-nix/action.yaml Adds gc-max-store-size: 4G for cache management and removes redundant environment loading step
justfile Adds lint-fix alias for format command and makes update-version command more explicit with python argument

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

echo "Installing MCP mock server dependencies..."
(cd vendor/stackone-ai-node && pnpm install --frozen-lockfile)
fi
fi
Copy link

Copilot AI Jan 3, 2026

Choose a reason for hiding this comment

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

The git hooks installation script is missing from the new shellHook. The previous version included ${config.pre-commit.installationScript} at the end of the shellHook, which automatically installs git hooks (gitleaks, treefmt, ty) when entering the development shell. Without this, developers will need to manually install git hooks, which may lead to inconsistent development environments and commits that fail CI checks.

Add the installation script to the end of the shellHook to restore this functionality.

Suggested change
fi
fi
# Install git hooks (pre-commit, gitleaks, treefmt, ty)
${config.pre-commit.installationScript}

Copilot uses AI. Check for mistakes.
Copy link

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

Choose a reason for hiding this comment

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

1 issue found across 5 files

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="flake.nix">

<violation number="1" location="flake.nix:172">
P1: Missing pre-commit hook installation. The shellHook no longer calls `${config.pre-commit.installationScript}`, so git hooks (gitleaks, treefmt, ty) won&#39;t be automatically installed when entering the dev shell. Add the installation script at the end of shellHook.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

(cd vendor/stackone-ai-node && pnpm install --frozen-lockfile)
fi
fi
'';
Copy link

@cubic-dev-ai cubic-dev-ai bot Jan 3, 2026

Choose a reason for hiding this comment

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

P1: Missing pre-commit hook installation. The shellHook no longer calls ${config.pre-commit.installationScript}, so git hooks (gitleaks, treefmt, ty) won't be automatically installed when entering the dev shell. Add the installation script at the end of shellHook.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At flake.nix, line 172:

<comment>Missing pre-commit hook installation. The shellHook no longer calls `${config.pre-commit.installationScript}`, so git hooks (gitleaks, treefmt, ty) won&#39;t be automatically installed when entering the dev shell. Add the installation script at the end of shellHook.</comment>

<file context>
@@ -31,8 +68,110 @@
+                    (cd vendor/stackone-ai-node &amp;&amp; pnpm install --frozen-lockfile)
+                  fi
+                fi
+              &#39;&#39;;
+            };
+        in
</file context>
Suggested change
'';
# Install git hooks
${config.pre-commit.installationScript}
'';
Fix with Cubic

Separate cache keys per Python version to prevent cache overwrites
when matrix jobs run in parallel. Default to python311 since it
matches the default devShell.
@ryoppippi ryoppippi force-pushed the feat/uv2nix-integration branch from 54f011a to d276461 Compare January 3, 2026 13:31
ty needs VIRTUAL_ENV to locate the Python environment's site-packages.
Without this, ty looks for .venv which doesn't exist in the Nix environment.

Also update justfile to conditionally use 'uv run' prefix only when
not in a Nix environment (detected via VIRTUAL_ENV). This makes
commands work for both Nix and non-Nix users.
@ryoppippi ryoppippi force-pushed the feat/uv2nix-integration branch from d276461 to c5f7aa8 Compare January 3, 2026 13:33
Add a dedicated build-cache job that runs before other CI jobs to
pre-populate the Nix store cache. This ensures that subsequent
parallel jobs (gitleaks, ci matrix, coverage) can benefit from the
cached derivations instead of each rebuilding from scratch.

The build-cache job:
- Runs as a matrix for both python311 and python313
- Builds the Nix development environment
- Saves the cache via cache-nix-action for downstream jobs

gitleaks, ci, and coverage jobs now depend on build-cache to ensure
cache is available before they run.
Add flake.lock and uv.lock hash to the cache key so that:
- Cache is saved when dependencies change (new hash = new key)
- Old cache is still restored via restore-prefixes-first-match
- Incremental updates build on previous cache

This ensures cache hits do not prevent saving updated derivations
while still benefiting from partial cache restoration.
Now that cache keys include lockfile hashes, proper invalidation
happens automatically. Each job can build and save its own cache,
making the dedicated build-cache job unnecessary.
Include pyproject.toml and src/**/*.py in the cache key hash
since source changes affect the editable install derivation.
Copy link

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

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).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name=".github/actions/setup-nix/action.yaml">

<violation number="1" location=".github/actions/setup-nix/action.yaml:19">
P2: Including `src/**/*.py` in the cache key will cause unnecessary cache invalidations on every source code change. This cache is for the Nix store (dependencies), not source code. Dependencies only change when lock files or `pyproject.toml` change, but source code changes on nearly every commit. This defeats the caching purpose and will slow CI rather than speed it up.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

- name: Load Nix development environment
shell: bash
run: nix develop --command true
primary-key: nix-${{ runner.os }}-${{ inputs.python-version }}-${{ hashFiles('flake.lock', 'uv.lock', 'pyproject.toml', 'src/**/*.py') }}
Copy link

@cubic-dev-ai cubic-dev-ai bot Jan 3, 2026

Choose a reason for hiding this comment

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

P2: Including src/**/*.py in the cache key will cause unnecessary cache invalidations on every source code change. This cache is for the Nix store (dependencies), not source code. Dependencies only change when lock files or pyproject.toml change, but source code changes on nearly every commit. This defeats the caching purpose and will slow CI rather than speed it up.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/actions/setup-nix/action.yaml, line 19:

<comment>Including `src/**/*.py` in the cache key will cause unnecessary cache invalidations on every source code change. This cache is for the Nix store (dependencies), not source code. Dependencies only change when lock files or `pyproject.toml` change, but source code changes on nearly every commit. This defeats the caching purpose and will slow CI rather than speed it up.</comment>

<file context>
@@ -16,7 +16,7 @@ runs:
       uses: nix-community/cache-nix-action@b426b118b6dc86d6952988d396aa7c6b09776d08 # v7
       with:
-        primary-key: nix-${{ runner.os }}-${{ inputs.python-version }}-${{ hashFiles(&#39;flake.lock&#39;, &#39;uv.lock&#39;) }}
+        primary-key: nix-${{ runner.os }}-${{ inputs.python-version }}-${{ hashFiles(&#39;flake.lock&#39;, &#39;uv.lock&#39;, &#39;pyproject.toml&#39;, &#39;src/**/*.py&#39;) }}
         restore-prefixes-first-match: |
           nix-${{ runner.os }}-${{ inputs.python-version }}-
</file context>
Suggested change
primary-key: nix-${{ runner.os }}-${{ inputs.python-version }}-${{ hashFiles('flake.lock', 'uv.lock', 'pyproject.toml', 'src/**/*.py') }}
primary-key: nix-${{ runner.os }}-${{ inputs.python-version }}-${{ hashFiles('flake.lock', 'uv.lock', 'pyproject.toml') }}
Fix with Cubic

@ryoppippi ryoppippi merged commit ee67062 into main Jan 3, 2026
13 checks passed
@ryoppippi ryoppippi deleted the feat/uv2nix-integration branch January 3, 2026 14:15
ryoppippi added a commit that referenced this pull request Jan 3, 2026
ryoppippi added a commit that referenced this pull request Jan 3, 2026
* Revert "ci: nix dev true (#91)"

This reverts commit 730aeba.

* Revert "chore: remove gc store (#90)"

This reverts commit 1265cae.

* Revert "feat(nix): integrate uv2nix for Python dependency management (#88)"

This reverts commit ee67062.

* Revert "chore(ci): switch to cache-nix-action for Nix store caching (#87)"

This reverts commit 0bbfd2d.
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.

2 participants