karma-webpack icon indicating copy to clipboard operation
karma-webpack copied to clipboard

Azure devops - path for folder creation is wrong when ts emits declaration files

Open Liarus opened this issue 3 years ago • 6 comments

  • Operating System: Azure Devops pipeline
  • Node Version: user-agent = "npm/6.14.11 node/v14.15.5 win32 x64"
  • NPM Version: C:\windows\system32\cmd.exe /D /S /C ""C:\Program Files\nodejs\npm.cmd" --version" 6.14.11
  • webpack Version: 5.22.0
  • karma-webpack Version: 5.0.0

Expected Behavior

Karma runs correctly with typescript emitting declaration files on Azure Devops pipeline.

Actual Behavior

Azure Devops report for 
Generating script.
Script contents:
npx karma start karma.conf.js
========================== Starting Command Output ===========================
"C:\windows\system32\cmd.exe" /D /E:ON /V:OFF /S /C "CALL "D:\a\_temp\b209e545-cd89-4b4b-a142-8fa0d494f6fa.cmd""
Webpack bundling...
Error: EINVAL: invalid argument, mkdir 'C:\Users\VSSADM~1\AppData\Local\Temp\_karma_webpack_494403\D:\a\1\s\TestApp\dist\src'
Terminate batch job (Y/N)?

Karma webpack tries to create a folder with drive letter: mkdir 'C:\Users\VSSADM~1\AppData\Local\Temp_karma_webpack_494403\D:\a\1\s\TestApp\dist\src'. Does it have something with common with different drive for temp and actual source?

On local environment (with only c: drive) it runs perfectly. I can omit this with not emitting declaration files (separate tsconfig for karma), but I want to have ts project references and during test for sure declarations and transpilation of referenced projects will occur regardless of settings and this will be a blocker for me

Code

  // webpack.config.js
const path = require('path');
const webpack = require('webpack');
const { CleanWebpackPlugin } = require("clean-webpack-plugin");

module.exports = {
  entry: path.resolve(__dirname, './src/index.ts'),
  devtool: 'source-map',
  plugins: [
    new webpack.ProgressPlugin(),
    new CleanWebpackPlugin()
  ],
  module: {
    rules: [{
      test: /\.(ts|tsx)$/,
      loader: 'ts-loader',
      include: [path.resolve(__dirname, 'src')],
      exclude: [/node_modules/]
    }]
  },

  resolve: {
    extensions: ['.tsx', '.ts', '.js']
  },

  output: {
    filename: 'test.js',
    path: path.resolve(__dirname, 'dist'),
    library: ['Test'],
    libraryTarget: 'umd',
    globalObject: 'this',
    umdNamedDefine: true
  }
}

  // ts.config.json
{
  "compileOnSave": false,
  "compilerOptions": {
    "sourceMap": true,
    "noImplicitAny": true,
    "module": "commonjs",
    "target": "es5",
    "allowJs": true,
    "outDir": "./dist",
    "declaration": true,
    "declarationDir": "./dist",
  },
  "exclude": [
    "node_modules/*",
    "**/*.spec.ts"
  ]
}
  // karma.conf.js
const webpack = require("webpack");  

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', 'webpack'],
    files: ['test/*.spec.ts'],
    mime: {
      'text/x-typescript': ['ts','tsx'] 
    },
    preprocessors: {
        'test/*.spec.ts': ['webpack', 'sourcemap']
    },
    webpack: {
      resolve: {
          extensions: ['.js', '.ts', '.tsx']
      },
      module: {
        rules: [{
          test: /\.tsx?$/,
          use: [{
            loader: 'ts-loader'
          }],
          exclude: /node_modules/
        }]
      },
      stats: {
        colors: true,
        modules: true,
        reasons: true,
        errorDetails: true
      },
      plugins: [
        new webpack.SourceMapDevToolPlugin({
          filename: null,
          test: /\.(ts|js)($|\?)/i,
          exclude: [ /node_modules/ ]
        })
      ]
    },
    reporters: ['spec'],
    port: 9876,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: false,
    browsers: ['Chrome'],
    singleRun: true,
    concurrency: Infinity
  });
};

How Do We Reproduce?

  1. Create a repo with basic test that import some type from a declared module
import { Test } from '../../src/test';

describe('Test', () => {
    describe('create', () => {
        it('should should create', () => {
            const actual = new Test()

            expect(actual).not.toBeNull();
        });

        it ('should create with default', () => {
            const actual = new Test();

            expect(actual.code).toBe('default');
        })
      });
})
  1. Launch karma test on Azure devops pipeline with yml step:
- task: Npm@1
  displayName: 'Test - install npm packages'
  inputs:
    command: 'install'
    workingDir: '$(build.sourcesDirectory)\TestApp'

- script: |
     npx karma start karma.conf.js
  workingDirectory: '$(build.sourcesDirectory)\TestApp'
  displayName: 'TestApp - unit tests'
  
- task: Npm@1
  displayName: 'TestApp - build'
  inputs:
    command: 'custom'
    workingDir: '$(build.sourcesDirectory)\TestApp'
    customCommand: 'run-script build-dev'
  1. Error with drive letter when creating a folder in temp should occur

Liarus avatar Feb 22 '21 10:02 Liarus

I was about to write an issue for the exact same bug.

The issue might be here: image

or here: image

Windows apparently doesn't like when you have D:\ in the middle of the path. There's probably a best practices way of solving this.

Obviously the real question is my there are absolute paths in the twice in the same path. But since this only happens in GitHub CI and not my local Windows machine it's hard to investigate.

Edit: Maybe jumped the gun here. Is the output path from karma-webpack exported so other packages can access it?

Edit # 2: The issue doesn't seems to be in this repo. I've added log statement in both places above and the error is thrown before they are reached. The issue is probably in Karma or another plugin.

JonWallsten avatar Feb 22 '21 11:02 JonWallsten

The issue is that Webpack is just joining to paths without checking if it's valid: https://github.com/webpack/webpack/blob/972b7f9bd1c608a0ce8794b4bed236cfffe72b2e/lib/Compiler.js#L796

This is not the fault of karma-webpack.

JonWallsten avatar Feb 22 '21 20:02 JonWallsten

Opened a new issue for Webpack: https://github.com/webpack/webpack/issues/12759

JonWallsten avatar Feb 23 '21 07:02 JonWallsten

Something to think about though: If source files are located on the 'D:' drive, maybe the temp folder should be too. Because fixing the path issue in Webpack is only one part of the problem. The second one is that the code in the output path C:\Users\VSSADM~1\AppData\Local\Temp\_karma_webpack_494403\ will never be able to reference the files in C:\Users\VSSADM~1\AppData\Local\Temp_karma_webpack_494403\D:\a\1\s\TestApp\dist\src since that path will no longer have D: only D.

JonWallsten avatar Feb 23 '21 07:02 JonWallsten

I'll leave this open until sokra responds over here => https://github.com/webpack/webpack/issues/12759

codymikol avatar Mar 30 '21 22:03 codymikol

For anyone also running into this issue, a workaround is to set the Temp drive to D:\Temp. For example, as a first step on GitHub actions:

    steps:
      # https://github.com/ryanclark/karma-webpack/issues/494
      - name: Windows temp dir fix
        run: |
          echo TEMP="D:\Temp" >> $env:GITHUB_ENV
          echo TMP="D:\Temp" >> $env:GITHUB_ENV

hugo-vrijswijk avatar Apr 16 '21 10:04 hugo-vrijswijk

This has apparently been fixed in the latest version of webpack 5

codymikol avatar Oct 22 '23 01:10 codymikol