Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
439 changes: 328 additions & 111 deletions .github/workflows/ci.yml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion e2e/docs-e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "",
"author": "",
"devDependencies": {
"@playwright/test": "1.57.0",
"@playwright/test": "1.59.1",
"@types/node": "24.10.0"
},
"keywords": [],
Expand Down
2 changes: 1 addition & 1 deletion e2e/qwik-cli-e2e/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.0",
"dependencies": {
"kleur": "^4.1.5",
"playwright": "^1.57.0"
"playwright": "^1.59.1"
},
"private": true,
"scripts": {
Expand Down
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

188 changes: 156 additions & 32 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -17,51 +17,175 @@
outputs = { self, rust-overlay, nixpkgs }:
let
b = builtins;
devShell = system: _pkgs:
perSystem = system: _pkgs:
let
overlays = [ (import rust-overlay) ];
pkgs = import nixpkgs {
inherit system overlays;
};
in
{
default = pkgs.mkShell {
lib = pkgs.lib;
pnpm = pkgs.pnpm_10.override { nodejs-slim = pkgs.nodejs-slim_24; };
pnpmDependencySource = lib.cleanSourceWith {
name = "qwik-pnpm-dependency-source";
src = ./.;
filter = path: type:
let
root = toString ./.;
rel = lib.removePrefix "${root}/" (toString path);
isWorkspaceConfig = builtins.elem rel [
".npmrc"
"package.json"
"pnpm-lock.yaml"
"pnpm-workspace.yaml"
];
isWorkspacePackageConfig =
builtins.match "(packages|e2e)/[^/]+/(package\\.json|\\.npmrc)" rel != null;
in
type == "directory"
|| isWorkspaceConfig
|| isWorkspacePackageConfig
|| lib.hasPrefix "patches/" rel;
};
pnpmDependencySourceId = b.substring 0 12 (b.hashString "sha256" (toString pnpmDependencySource));
# CI prints the replacement hash when a platform hash is missing or stale.
pnpmDepsHash = {
aarch64-darwin = "sha256-kpjBxC8qiyv+ozqXqixTgRc14lijAhKf2PpovSrUUx8=";
x86_64-linux = "sha256-kpjBxC8qiyv+ozqXqixTgRc14lijAhKf2PpovSrUUx8=";
}.${system} or lib.fakeHash;
pnpmDeps = pkgs.fetchPnpmDeps {
pname = "qwik-${pnpmDependencySourceId}";
version = "0.0.0";
src = pnpmDependencySource;
inherit pnpm;
fetcherVersion = 4;
hash = pnpmDepsHash;
};
nodeModules = pkgs.stdenvNoCC.mkDerivation {
pname = "qwik-${pnpmDependencySourceId}-node-modules";
version = "0.0.0";
src = pnpmDependencySource;
nativeBuildInputs = with pkgs; [
bashInteractive
gitMinimal

coreutils
gnutar
nodejs_24
corepack_24
pnpm
zstd
];
dontConfigure = true;
dontBuild = true;
installPhase = ''
runHook preInstall

# Playwright for the end-to-end tests
playwright-driver.browsers
export HOME="$TMPDIR/home"
export npm_config_cache="$TMPDIR/npm-cache"
export PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD=1
export PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1
export PUPPETEER_SKIP_DOWNLOAD=1
export npm_config_manage_package_manager_versions=false

# Qwik optimizer deps
wasm-pack
# Provides rustc and cargo
((rust-bin.fromRustupToolchainFile
./rust-toolchain).override {
# For rust-analyzer
extensions = [ "rust-src" ];
# For building wasm
targets = [ "wasm32-unknown-unknown" ];
})
];
# https://github.com/microsoft/playwright/issues/5501
shellHook = ''
export PATH=$PWD/node_modules/.bin:$PATH
export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers}
export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true
pwNixVersion=${pkgs.playwright-driver.version}
pwNpmVersion=$(${pkgs.jq}/bin/jq -r .version node_modules/@playwright/test/package.json 2>/dev/null)
if [ -n "$pwNpmVersion" ] && [ "$pwNpmVersion" != "$pwNixVersion" ]; then
echo "!!! Playwright version mismatch: $pwNpmVersion (nodejs) != $pwNixVersion (nix). Please fix." >&2
fi
mkdir -p "$HOME" "$TMPDIR/pnpm-store"
tar --zstd -xf ${pnpmDeps}/pnpm-store.tar.zst -C "$TMPDIR/pnpm-store"
chmod -R u+w "$TMPDIR/pnpm-store"

pnpm config set store-dir "$TMPDIR/pnpm-store"
pnpm config set package-import-method copy
pnpm install --offline --frozen-lockfile --ignore-scripts

mkdir -p "$out"
find node_modules packages e2e -name node_modules -prune -print \
| LC_ALL=C sort \
| tar --zstd --sort=name --mtime='@1' --owner=0 --group=0 --numeric-owner \
-cf "$out/node_modules.tar.zst" --files-from=-

runHook postInstall
'';
};
rustToolchain = (pkgs.rust-bin.fromRustupToolchainFile
./rust-toolchain).override {
# For rust-analyzer
extensions = [ "rust-src" ];
# For building wasm
targets = [ "wasm32-unknown-unknown" ];
};
localNodeEnv = ''
export PATH=$PWD/node_modules/.bin:$PATH
unset PLAYWRIGHT_BROWSERS_PATH
unset PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS
'';
playwrightEnv = localNodeEnv + ''
export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers}
export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true
pwNixVersion=${pkgs.playwright-driver.version}
pwNpmVersion=$(${pkgs.jq}/bin/jq -r .version node_modules/@playwright/test/package.json 2>/dev/null)
if [ -n "$pwNpmVersion" ] && [ "$pwNpmVersion" != "$pwNixVersion" ]; then
echo "!!! Playwright version mismatch: $pwNpmVersion (nodejs) != $pwNixVersion (nix). Please fix." >&2
fi
'';
mkNodeShell = { nodejs, corepack, withPlaywright ? false, extraInputs ? [ ] }:
pkgs.mkShell {
nativeBuildInputs = with pkgs; [
bashInteractive
gitMinimal
gnutar
jq
tree
zstd

nodejs
corepack
] ++ pkgs.lib.optionals withPlaywright [
# Playwright for the end-to-end tests
pkgs.playwright-driver.browsers
] ++ extraInputs;
shellHook = if withPlaywright then playwrightEnv else localNodeEnv;
};
in
{
packages = {
pnpm-deps = pnpmDeps;
node-modules = nodeModules;
};
devShells = {
default = mkNodeShell {
nodejs = pkgs.nodejs_24;
corepack = pkgs.corepack_24;
withPlaywright = true;
extraInputs = with pkgs; [
# Qwik optimizer deps
wasm-pack
# Provides rustc and cargo
rustToolchain
];
};
ci-node24 = mkNodeShell {
nodejs = pkgs.nodejs_24;
corepack = pkgs.corepack_24;
};
ci-node24-e2e = mkNodeShell {
nodejs = pkgs.nodejs_24;
corepack = pkgs.corepack_24;
withPlaywright = true;
};
ci-node22-e2e = mkNodeShell {
nodejs = pkgs.nodejs_22;
corepack = pkgs.corepack_22;
withPlaywright = true;
};
ci-rust = mkNodeShell {
nodejs = pkgs.nodejs_24;
corepack = pkgs.corepack_24;
extraInputs = with pkgs; [
# Qwik optimizer deps
wasm-pack
# Provides rustc and cargo
rustToolchain
];
};
};
};
in
{
devShells = b.mapAttrs (devShell) nixpkgs.legacyPackages;
packages = b.mapAttrs (system: pkgs: (perSystem system pkgs).packages) nixpkgs.legacyPackages;
devShells = b.mapAttrs (system: pkgs: (perSystem system pkgs).devShells) nixpkgs.legacyPackages;
};
}
39 changes: 39 additions & 0 deletions nix-flakehub-ci-todo.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Nix + FlakeHub CI TODO

## Current state

- Unix CI uses `nix develop` for tool prerequisites.
- FlakeHub Cache is optional and must not block CI when unavailable.
- Windows CI stays non-Nix and consumes the same GitHub artifacts as before.
- Build outputs are still cached with the existing GitHub Actions cache/artifact flow.

## Next steps

1. Package pnpm dependency materialization.
- Create a Nix derivation keyed by `pnpm-lock.yaml`, package manifests, patches, and pnpm workspace config.
- Store `node_modules/.pnpm` in a Nix store output.
- Generate a manifest of top-level and workspace package links needed to reconstruct `node_modules`.
- Add a cross-platform relink script that can rebuild the workspace `node_modules` layout from that store output.
- Keep `pnpm install --frozen-lockfile` as the fallback path for non-Nix local development and Windows CI.

2. Package build outputs incrementally.
- Start with `packages/optimizer` and `packages/qwik/dist`.
- Add `packages/qwik-router/lib`, `packages/qwik-react/lib`, `packages/eslint-plugin-qwik/dist`, and `packages/create-qwik/dist`.
- Use filtered Nix sources that mirror the current CI cache-key boundaries so unrelated source changes do not invalidate every package.
- Copy or link Nix outputs back into the existing workspace paths so downstream tests and release jobs do not need to change immediately.

3. Replace branch-scoped cache skips carefully.
- For each Nix-packaged output, prefer `nix build` substitution checks over `actions/cache` lookup-only keys.
- Keep GitHub artifact upload/download for job fanout and Windows consumers.
- Keep GitHub cache fallbacks until FlakeHub hit rates and failure behavior are known in real PR traffic.

4. Validate cache safety.
- Only allow trusted upstream workflows to publish to FlakeHub Cache.
- Ensure fork PRs run correctly without cache write access.
- Confirm all Nix derivations are network-free after dependency materialization.
- Keep `cache.nixos.org` and local build fallback enabled for all Nix commands.

5. Measure before removing old paths.
- Track `pnpm install` time, Nix substitution time, package build time, and artifact transfer time.
- Compare PRs with warm FlakeHub Cache, FlakeHub miss, and FlakeHub unavailable.
- Remove old GitHub cache branches only when replacement paths are measurably stable.
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"dependencyTypes": [
"dev"
],
"pinVersion": "1.57.0"
"pinVersion": "1.59.1"
}
],
"semverGroups": [
Expand Down Expand Up @@ -114,7 +114,7 @@
"@napi-rs/triples": "1.2.0",
"@node-rs/helper": "1.6.0",
"@octokit/action": "6.1.0",
"@playwright/test": "1.57.0",
"@playwright/test": "1.59.1",
"@qwik.dev/core": "workspace:*",
"@qwik.dev/optimizer": "workspace:*",
"@qwik.dev/partytown": "0.13.2",
Expand Down Expand Up @@ -214,6 +214,7 @@
"build.watch": "node --require ./scripts/runBefore.ts scripts/index.ts --qwik --qwikworker --qwikrouter --watch --dev --platform-binding",
"change": "changeset",
"ci.restore-artifacts": "node --require ./scripts/runBefore.ts scripts/ci-restore-artifacts.ts",
"ci.restore-node-modules": "bash scripts/ci-restore-node-modules.sh",
"cli": "pnpm build.cli && node packages/create-qwik/create-qwik.mjs && node --require ./scripts/runBefore.ts scripts/validate-cli.ts --copy-local-qwik-dist",
"cli.qwik": "pnpm build.cli && node packages/qwik/qwik-cli.mjs",
"cli.validate": "node --require ./scripts/runBefore.ts scripts/validate-cli.ts",
Expand Down
2 changes: 1 addition & 1 deletion packages/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
"gray-matter": "4.0.3",
"leaflet": "1.9.4",
"magic-string": "0.30.21",
"playwright": "1.57.0",
"playwright": "1.59.1",
"pagefind": "1.4.0",
"prettier": "3.7.4",
"prism-themes": "1.9.0",
Expand Down
Loading
Loading