-
Notifications
You must be signed in to change notification settings - Fork 0
feat(nix): integrate uv2nix for Python dependency management #88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
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.
There was a problem hiding this 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 syncstep, 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 |
Copilot
AI
Jan 3, 2026
There was a problem hiding this comment.
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.
| fi | |
| fi | |
| # Install git hooks (pre-commit, gitleaks, treefmt, ty) | |
| ${config.pre-commit.installationScript} |
There was a problem hiding this 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'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 | ||
| ''; |
There was a problem hiding this comment.
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'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 && pnpm install --frozen-lockfile)
+ fi
+ fi
+ '';
+ };
+ in
</file context>
| ''; | |
| # Install git hooks | |
| ${config.pre-commit.installationScript} | |
| ''; |
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.
54f011a to
d276461
Compare
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.
d276461 to
c5f7aa8
Compare
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.
There was a problem hiding this 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') }} |
There was a problem hiding this comment.
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('flake.lock', 'uv.lock') }}
+ primary-key: nix-${{ runner.os }}-${{ inputs.python-version }}-${{ hashFiles('flake.lock', 'uv.lock', 'pyproject.toml', 'src/**/*.py') }}
restore-prefixes-first-match: |
nix-${{ runner.os }}-${{ inputs.python-version }}-
</file context>
| 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') }} |
* 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.
Summary
Replaces uv-managed
.venvwith Nix-managed Python environments using uv2nix. This provides fully reproducible builds with dependencies cached in the Nix store.What Changed
default,python311,python313)nix develop .#pythonXXXinstead ofuv syncgc-max-store-size: 4Gfor cache managementlint-fixaliasWhy
uv syncstep; dependencies are cached with other Nix derivationsuv runcommands still work for non-Nix usersNotes
.venvdirectory is no longer needed (can be deleted locally)nix develop(default) ornix develop .#python313for specific versionsSummary 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
Migration
Written for commit 10475d3. Summary will update on new commits.