dream2nix
dream2nix copied to clipboard
[help] node project - run tests?
My node (TypeScript) project builds just fine with a minimal dream2nix-config from the examples (and I'm amazed at how easy and clutter-free it is compared to other node nixification tools!).
Now I'd like to run the flake from a git workflow using nixbuild/nix-quick-install-action@v14. The project has a common pattern for node apps:
"scripts": {
"build": "tsc",
"test": "jest"
}
The build script gets called successfully from commandline and from the git-workflow
name: Test
on: [pull_request, push]
jobs:
test-and-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: nixbuild/nix-quick-install-action@v14
with:
nix_conf: experimental-features = nix-command flakes
- name: build packages
run: nix build '.#default'
Now I'd also like to run the task test, so I can use the workflow's exit state as complete sanity check, but I can't find a way to do so.
- When modifying my build command to
npm run test; tscor adding a postbuild command, the test will fail because it can't find any test files (test files are in the./src/folder and identified by axxx.test.tssubstring). - When adding an "app" to flakes that runs the
jestexecutable from the result, it will fail due to missing dependencies, namelyts-jest not found.
I think the latter might be fixable by moving all node dev-dependencies to runtime dependencies, but this would negatively impact the distributed package's size and dependency graph.
Is there some misconception I have about the working of dream2nix? How should I go about, fixing this?
I tried running this with:
{
inputs = {
dream2nix.url = "github:nix-community/dream2nix";
nixpkgs.url = "github:nixos/nixpkgs";
nixpkgs.follows = "nixpkgs";
};
outputs = { self, dream2nix, nixpkgs }@inp:
(dream2nix.lib.makeFlakeOutputs {
systems = [ "x86_64-linux" ];
config.projectRoot = ./.;
source = ./.;
packageOverrides = {
grud-devtools = {
"build-test" = {
buildScript = ''
# Run build
npm run build
# Run tests
npm run test -- --verbose --debug
'';
};
};
};
}) // {
apps.x86_64-linux.checks = {
type = "app";
program =
"${self.packages.x86_64-linux.default}/lib/node_modules/grud-devtools/node_modules/jest/bin/jest.js";
};
};
}
I get:
> [email protected] test /nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools
> jest "--verbose" "--debug"
{
"configs": [
{
"automock": false,
"cache": true,
"cacheDirectory": "/build/jest_rs",
"clearMocks": false,
"coveragePathIgnorePatterns": [
"/node_modules/"
],
"cwd": "/nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools",
"detectLeaks": false,
"detectOpenHandles": false,
"errorOnDeprecated": false,
"extensionsToTreatAsEsm": [],
"fakeTimers": {
"enableGlobally": false
},
"forceCoverageMatch": [],
"globals": {},
"haste": {
"computeSha1": false,
"enableSymlinks": false,
"forceNodeFilesystemAPI": true,
"throwOnModuleCollision": false
},
"id": "4957166a42cdd73dc20763cac55fc75a",
"injectGlobals": true,
"moduleDirectories": [
"node_modules"
],
"moduleFileExtensions": [
"js",
"mjs",
"cjs",
"jsx",
"ts",
"tsx",
"json",
"node"
],
"moduleNameMapper": [],
"modulePathIgnorePatterns": [],
"prettierPath": "prettier",
"resetMocks": false,
"resetModules": false,
"restoreMocks": false,
"rootDir": "/nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools",
"roots": [
"/nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools"
],
"runner": "/nix/store/vpcbv8a0y2gn4mc7dyfksmcqkflqr3rn-jest-runner-28.1.3/lib/node_modules/jest-runner/build/index.js",
"sandboxInjectedGlobals": [],
"setupFiles": [],
"setupFilesAfterEnv": [],
"skipFilter": false,
"slowTestThreshold": 5,
"snapshotSerializers": [],
"testEnvironment": "/nix/store/7va0n0pc033g4lm3yyj9ycnjg2xcv12i-jest-environment-node-28.1.3/lib/node_modules/jest-environment-node/build/index.js",
"testEnvironmentOptions": {},
"testLocationInResults": false,
"testMatch": [
"**/__tests__/**/*.[jt]s?(x)",
"**/?(*.)+(spec|test).[tj]s?(x)"
],
"testPathIgnorePatterns": [
"/node_modules/"
],
"testRegex": [],
"testRunner": "/nix/store/z91jbznsf1an8nxvdmjpg90qv62k85cz-jest-circus-28.1.3/lib/node_modules/jest-circus/runner.js",
"transform": [
[
"^.+\\.tsx?$",
"/nix/store/qxx63ziqjngaz1x2p07kvgwjy42mgm0h-ts-jest-28.0.5/lib/node_modules/ts-jest/dist/index.js",
{}
]
],
"transformIgnorePatterns": [
"/node_modules/",
"\\.pnp\\.[^\\/]+$"
],
"watchPathIgnorePatterns": []
}
],
"globalConfig": {
"bail": 0,
"changedFilesWithAncestor": false,
"ci": false,
"collectCoverage": false,
"collectCoverageFrom": [],
"coverageDirectory": "/nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools/coverage",
"coverageProvider": "babel",
"coverageReporters": [
"json",
"text",
"lcov",
"clover"
],
"detectLeaks": false,
"detectOpenHandles": false,
"errorOnDeprecated": false,
"expand": false,
"findRelatedTests": false,
"forceExit": false,
"json": false,
"lastCommit": false,
"listTests": false,
"logHeapUsage": false,
"maxConcurrency": 5,
"maxWorkers": 7,
"noStackTrace": false,
"nonFlagArgs": [],
"notify": false,
"notifyMode": "failure-change",
"onlyChanged": false,
"onlyFailures": false,
"passWithNoTests": false,
"projects": [],
"rootDir": "/nix/store/d9l2lcshhh60z8md5rxvnrfzda03l8wb-grud-devtools-0.1.0/lib/node_modules/grud-devtools",
"runTestsByPath": false,
"skipFilter": false,
"testFailureExitCode": 1,
"testPathPattern": "",
"testSequencer": "/nix/store/77r6n71lgax69ryhnq1xwm9hgj02gics-__at__jest__slash__test-sequencer-28.1.3/lib/node_modules/@jest/test-sequencer/build/index.js",
"updateSnapshot": "new",
"useStderr": false,
"verbose": true,
"watch": false,
"watchAll": false,
"watchman": true
},
"version": "28.1.3"
}
Which looks quite right, so I am really not sure why jest cannot locate the test files.
I have played with this a while, and completely forgot to respond here. I'm sorry for that.
From my observation, the problem seems to be that jest excludes directories that have a node_modules somewhere in their path.
Since the dream2nix builder buidls directly in $out/lib/node_modules/$packageName, all test directories will get excluded by default.
We should find out how jest can be configured to not ignore that directory and maybe add a community override that patches it to have that option set by default.
Alternatively we could change the builder to not build inside $out/lib/node_modules. It should probably build inside /build anyways and then move the files after the build is finished
@DavHau Making jest un-ignore the node_modules package seems to be a good idea. It should be enough to set the testPathIgnorePattern to not ignore our node_module, and there's a number of places where this could be done:
- In package.json, in a top level entry:
{..."jest": {"testPathIgnorePattern": ["regex", "regex",...] }, ... } - When calling the files from CLI with
--testPathIgnorePattern='regex' - In the jest config file the project chose to use
To un-ignore only the node_modules directory of our own package, its subdirectory should be prefixed with an exclamation mark, as seen here.
I have no knowledge of dream2nix' internals, but I don't know if changing the build [directory] will fix the problem transparently. To my understanding, it would only guarantee a successful test run if the test command gets called during the build phase. If it is used as a second call, as in my example where it will allow git to determine if the build or the test did fail, the files would already be copied to the out-path and we'd be back at jest ignoring the files.
Edit: The second call will possibly never work as long as all packages required for the test run are only used as dev dependencies. A pure nix-build will only have deps, not dev-deps. Considering this, the change to the build path might be an idea requiring less fragile changes.
This should be fixed by https://github.com/nix-community/dream2nix/pull/337