diff --git a/lib/workers/branch/index.js b/lib/workers/branch/index.js
index 326ef2cfcb221531df451c5190ab5fb9ce9d671a..f208d60df6e3a9bbca46c38c8b6b83fe36c43604 100644
--- a/lib/workers/branch/index.js
+++ b/lib/workers/branch/index.js
@@ -1,3 +1,4 @@
+const path = require('path');
 const handlebars = require('handlebars');
 const packageJsonHelper = require('./package-json');
 const npm = require('./npm');
@@ -153,6 +154,7 @@ async function ensureBranch(config) {
       });
       try {
         const yarnLockFile = await yarn.getLockFile(
+          path.join(config.tmpDir.name, path.dirname(packageFile)),
           packageFile,
           packageFiles[packageFile],
           api,
@@ -164,6 +166,7 @@ async function ensureBranch(config) {
           commitFiles.push(yarnLockFile);
         }
         const packageLockFile = await npm.getLockFile(
+          path.join(config.tmpDir.name, path.dirname(packageFile)),
           packageFile,
           packageFiles[packageFile],
           api,
diff --git a/lib/workers/branch/npm.js b/lib/workers/branch/npm.js
index 78c1cf86e23678823a05201d5a0988c7917ccce5..9de0b9b52e26c09a8d8975011382b4bf752b89b1 100644
--- a/lib/workers/branch/npm.js
+++ b/lib/workers/branch/npm.js
@@ -1,6 +1,5 @@
-const fs = require('fs');
+const fs = require('fs-extra');
 const cp = require('child_process');
-const tmp = require('tmp');
 const path = require('path');
 
 module.exports = {
@@ -9,19 +8,21 @@ module.exports = {
   maintainLockFile,
 };
 
-async function generateLockFile(newPackageJson, npmrcContent, logger) {
+async function generateLockFile(tmpDir, newPackageJson, npmrcContent, logger) {
   logger.debug('Generating new package-lock.json file');
-  const tmpDir = tmp.dirSync({ unsafeCleanup: true });
   let packageLock;
   let result = {};
   try {
-    fs.writeFileSync(path.join(tmpDir.name, 'package.json'), newPackageJson);
+    await fs.outputFile(path.join(tmpDir, 'package.json'), newPackageJson);
     if (npmrcContent) {
-      fs.writeFileSync(path.join(tmpDir.name, '.npmrc'), npmrcContent);
+      await fs.outputFile(path.join(tmpDir, '.npmrc'), npmrcContent);
     }
-    logger.debug('Spawning npm install');
+    await fs.remove(path.join(tmpDir, 'package-lock.json'));
+    logger.debug(
+      `Spawning npm install to generate ${tmpDir}/package-lock.json`
+    );
     result = cp.spawnSync('npm', ['install', '--ignore-scripts'], {
-      cwd: tmpDir.name,
+      cwd: tmpDir,
       shell: true,
       env: { ...process.env, ...{ NODE_ENV: 'dev' } },
     });
@@ -29,7 +30,7 @@ async function generateLockFile(newPackageJson, npmrcContent, logger) {
       { stdout: String(result.stdout), stderr: String(result.stderr) },
       'npm install complete'
     );
-    packageLock = fs.readFileSync(path.join(tmpDir.name, 'package-lock.json'));
+    packageLock = fs.readFileSync(path.join(tmpDir, 'package-lock.json'));
   } catch (err) /* istanbul ignore next */ {
     logger.warn(
       {
@@ -41,22 +42,13 @@ async function generateLockFile(newPackageJson, npmrcContent, logger) {
       },
       'Error generating package-lock.json'
     );
-    try {
-      tmpDir.removeCallback();
-    } catch (err2) {
-      logger.warn(`Failed to remove tmpDir ${tmpDir.name}`);
-    }
     throw Error('Error generating lock file');
   }
-  try {
-    tmpDir.removeCallback();
-  } catch (err2) {
-    logger.warn(`Failed to remove tmpDir ${tmpDir.name}`);
-  }
   return packageLock;
 }
 
 async function getLockFile(
+  tmpDir,
   packageFile,
   packageContent,
   api,
@@ -86,6 +78,7 @@ async function getLockFile(
   const npmrcContent = await api.getFileContent('.npmrc');
   // Generate package-lock.json using shell command
   const newPackageLockContent = await module.exports.generateLockFile(
+    tmpDir,
     packageContent,
     npmrcContent,
     logger
@@ -117,6 +110,7 @@ async function maintainLockFile(inputConfig) {
   }
   logger.debug('Found existing package-lock.json file');
   const newPackageLock = await module.exports.getLockFile(
+    path.join(inputConfig.tmpDir.name, path.dirname(inputConfig.packageFile)),
     inputConfig.packageFile,
     packageContent,
     inputConfig.api,
diff --git a/lib/workers/branch/yarn.js b/lib/workers/branch/yarn.js
index 8bde6804efa697a99631b6259130f19c71131320..02405837c142e21a1cfe0555606d6a68c5d9f759 100644
--- a/lib/workers/branch/yarn.js
+++ b/lib/workers/branch/yarn.js
@@ -1,6 +1,5 @@
-const fs = require('fs');
+const fs = require('fs-extra');
 const cp = require('child_process');
-const tmp = require('tmp');
 const path = require('path');
 
 module.exports = {
@@ -12,28 +11,29 @@ module.exports = {
 const yarnVersion = '0.27.5';
 
 async function generateLockFile(
+  tmpDir,
   newPackageJson,
   npmrcContent,
   yarnrcContent,
   logger
 ) {
   logger.debug('Generating new yarn.lock file');
-  const tmpDir = tmp.dirSync({ unsafeCleanup: true });
   let yarnLock;
   let result = {};
   try {
-    fs.writeFileSync(path.join(tmpDir.name, 'package.json'), newPackageJson);
+    await fs.outputFile(path.join(tmpDir, 'package.json'), newPackageJson);
     if (npmrcContent) {
-      fs.writeFileSync(path.join(tmpDir.name, '.npmrc'), npmrcContent);
+      await fs.outputFile(path.join(tmpDir, '.npmrc'), npmrcContent);
     }
     if (yarnrcContent) {
       const filteredYarnrc = yarnrcContent.replace(
         '--install.pure-lockfile true',
         ''
       );
-      fs.writeFileSync(path.join(tmpDir.name, '.yarnrc'), filteredYarnrc);
+      await fs.outputFile(path.join(tmpDir, '.yarnrc'), filteredYarnrc);
     }
-    logger.debug('Spawning yarn install');
+    await fs.remove(path.join(tmpDir, 'yarn.lock'));
+    logger.debug(`Spawning yarn install to create ${tmpDir}/yarn.lock`);
     // Use an embedded yarn
     const yarnBin = path.join(
       __dirname,
@@ -42,13 +42,13 @@ async function generateLockFile(
     );
     const yarnOptions = [yarnBin, 'install', '--ignore-scripts'];
     result = cp.spawnSync('node', yarnOptions, {
-      cwd: tmpDir.name,
+      cwd: tmpDir,
       shell: true,
       env: { ...process.env, ...{ NODE_ENV: 'dev' } },
     });
     logger.debug(String(result.stdout));
     logger.debug(String(result.stderr));
-    yarnLock = fs.readFileSync(path.join(tmpDir.name, 'yarn.lock'));
+    yarnLock = fs.readFileSync(path.join(tmpDir, 'yarn.lock'));
   } catch (err) /* istanbul ignore next */ {
     logger.warn(
       {
@@ -61,22 +61,12 @@ async function generateLockFile(
       },
       'Error generating yarn.lock'
     );
-    try {
-      tmpDir.removeCallback();
-    } catch (err2) {
-      logger.warn(`Failed to remove tmpDir ${tmpDir.name}`);
-    }
     throw Error('Error generating lock file');
   }
-  try {
-    tmpDir.removeCallback();
-  } catch (err2) {
-    logger.warn(`Failed to remove tmpDir ${tmpDir.name}`);
-  }
   return yarnLock;
 }
 
-async function getLockFile(packageFile, packageContent, api, logger) {
+async function getLockFile(tmpDir, packageFile, packageContent, api, logger) {
   // Detect if a yarn.lock file is in use
   const yarnLockFileName = path.join(path.dirname(packageFile), 'yarn.lock');
   if (!await api.getFileContent(yarnLockFileName)) {
@@ -87,6 +77,7 @@ async function getLockFile(packageFile, packageContent, api, logger) {
   const yarnrcContent = await api.getFileContent('.yarnrc');
   // Generate yarn.lock using shell command
   const newYarnLockContent = await module.exports.generateLockFile(
+    tmpDir,
     packageContent,
     npmrcContent,
     yarnrcContent,
@@ -123,6 +114,7 @@ async function maintainLockFile(inputConfig) {
   }
   logger.debug('Found existing yarn.lock file');
   const newYarnLock = await module.exports.getLockFile(
+    path.join(inputConfig.tmpDir.name, path.dirname(inputConfig.packageFile)),
     inputConfig.packageFile,
     packageContent,
     inputConfig.api,
diff --git a/lib/workers/repository/index.js b/lib/workers/repository/index.js
index 72db87b59484c66c65fce8f48470cfd883001205..c1dd05a1ba7ee9bae4a525afeac1c22d3efe6ae4 100644
--- a/lib/workers/repository/index.js
+++ b/lib/workers/repository/index.js
@@ -1,3 +1,4 @@
+const tmp = require('tmp');
 const presets = require('../../config/presets');
 // Workers
 const branchWorker = require('../branch');
@@ -14,6 +15,7 @@ module.exports = {
 async function renovateRepository(repoConfig, token) {
   let config = { ...repoConfig };
   const { logger } = config;
+  config.tmpDir = tmp.dirSync({ unsafeCleanup: true });
   config.errors = [];
   config.warnings = [];
   logger.trace({ config }, 'renovateRepository');
@@ -125,4 +127,5 @@ async function renovateRepository(repoConfig, token) {
       logger.debug({ err });
     }
   }
+  config.tmpDir.removeCallback();
 }
diff --git a/package.json b/package.json
index f65608f3dd6df6c3a55e13d99bceba13a41fea8b..210830d57c73299afa5216a223c69be24e8d5be3 100644
--- a/package.json
+++ b/package.json
@@ -45,6 +45,7 @@
     "changelog": "1.4.0",
     "commander": "2.11.0",
     "conventional-commits-detector": "0.1.1",
+    "fs-extra": "4.0.1",
     "gh-got": "6.0.0",
     "github-url-from-git": "1.5.0",
     "gl-got": "7.0.0",
@@ -115,8 +116,12 @@
       ":automergeBranchPush",
       "group:monorepos"
     ],
-    "labels": ["ready"],
-    "assignees": ["rarkins"]
+    "labels": [
+      "ready"
+    ],
+    "assignees": [
+      "rarkins"
+    ]
   },
   "release": {
     "verifyConditions": "condition-circle"
diff --git a/test/workers/branch/__snapshots__/npm.spec.js.snap b/test/workers/branch/__snapshots__/npm.spec.js.snap
index d43fb2cd393e4aa20a89af17600d1b4851e9e6f2..2ab30bd6047ab3b2b1715ba253bc764122ff6cc7 100644
--- a/test/workers/branch/__snapshots__/npm.spec.js.snap
+++ b/test/workers/branch/__snapshots__/npm.spec.js.snap
@@ -1,5 +1,5 @@
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
-exports[`getLockFile(packageFile, packageContent, api, npmVersion) throws if no npm 1`] = `[Error: Need to generate package-lock.json but npm is not installed]`;
+exports[`getLockFile throws if no npm 1`] = `[Error: Need to generate package-lock.json but npm is not installed]`;
 
-exports[`getLockFile(packageFile, packageContent, api, npmVersion) throws if wrong npm version 1`] = `[Error: Need to generate package-lock.json but npm version is "4.0.0"]`;
+exports[`getLockFile throws if wrong npm version 1`] = `[Error: Need to generate package-lock.json but npm version is "4.0.0"]`;
diff --git a/test/workers/branch/index.spec.js b/test/workers/branch/index.spec.js
index b0d29ff8a6858d70e44a128e0b64b322c53d6ae2..aef038de9e393e1b64e7ca16b873e7d82c3989d1 100644
--- a/test/workers/branch/index.spec.js
+++ b/test/workers/branch/index.spec.js
@@ -121,6 +121,7 @@ describe('workers/branch', () => {
       config.api.getBranchStatus = jest.fn();
       config.api.getBranchStatusCheck = jest.fn();
       config.api.setBranchStatus = jest.fn();
+      config.tmpDir = { name: 'some-dir' };
       config.depName = 'dummy';
       config.currentVersion = '1.0.0';
       config.newVersion = '1.1.0';
diff --git a/test/workers/branch/npm.spec.js b/test/workers/branch/npm.spec.js
index 022a9767d7a8aa4c74adbae59a11f804cb4004ea..023fd67c35cff9b8bfb510bcfc9850106eab49cd 100644
--- a/test/workers/branch/npm.spec.js
+++ b/test/workers/branch/npm.spec.js
@@ -1,17 +1,16 @@
 const npmHelper = require('../../../lib/workers/branch/npm');
 const logger = require('../../_fixtures/logger');
 
-jest.mock('fs');
+jest.mock('fs-extra');
 jest.mock('child_process');
-jest.mock('tmp');
 
-const fs = require('fs');
+const fs = require('fs-extra');
 const cp = require('child_process');
-const tmp = require('tmp');
 
-describe('generateLockFile(newPackageJson, npmrcContent, logger)', () => {
-  tmp.dirSync = jest.fn(() => ({ name: 'somedir' }));
-  fs.writeFileSync = jest.fn();
+const tmpDir = { name: 'some-dir' };
+
+describe('generateLockFile', () => {
+  fs.outputFile = jest.fn();
   fs.readFileSync = jest.fn(() => 'package-lock-contents');
   cp.spawnSync = jest.fn(() => ({
     stdout: '',
@@ -19,17 +18,17 @@ describe('generateLockFile(newPackageJson, npmrcContent, logger)', () => {
   }));
   it('generates lock files', async () => {
     const packageLock = await npmHelper.generateLockFile(
-      'package-json-contents',
+      tmpDir.name,
+      {},
       'npmrc-contents',
       logger
     );
-    expect(tmp.dirSync.mock.calls.length).toEqual(1);
-    expect(fs.writeFileSync.mock.calls.length).toEqual(2);
+    expect(fs.outputFile.mock.calls.length).toEqual(2);
     expect(fs.readFileSync.mock.calls.length).toEqual(1);
     expect(packageLock).toEqual('package-lock-contents');
   });
 });
-describe('getLockFile(packageFile, packageContent, api, npmVersion)', () => {
+describe('getLockFile', () => {
   let api;
   beforeEach(() => {
     api = {
@@ -38,7 +37,9 @@ describe('getLockFile(packageFile, packageContent, api, npmVersion)', () => {
   });
   it('returns null if no existing package-lock.json', async () => {
     api.getFileContent.mockReturnValueOnce(false);
-    expect(await npmHelper.getLockFile('package.json', '', api)).toBe(null);
+    expect(await npmHelper.getLockFile(tmpDir, 'package.json', '', api)).toBe(
+      null
+    );
   });
   it('returns package-lock.json file', async () => {
     api.getFileContent.mockReturnValueOnce('Existing package-lock.json');
@@ -50,14 +51,14 @@ describe('getLockFile(packageFile, packageContent, api, npmVersion)', () => {
       contents: 'New package-lock.json',
     };
     expect(
-      await npmHelper.getLockFile('package.json', '', api, '5.0.4')
+      await npmHelper.getLockFile(tmpDir, 'package.json', '', api, '5.0.4')
     ).toMatchObject(packageLockFile);
   });
   it('throws if no npm', async () => {
     api.getFileContent.mockReturnValueOnce('Existing package-lock.json');
     let e;
     try {
-      await npmHelper.getLockFile('package.json', '', api, '');
+      await npmHelper.getLockFile(tmpDir, 'package.json', '', api, '');
     } catch (err) {
       e = err;
     }
@@ -67,7 +68,7 @@ describe('getLockFile(packageFile, packageContent, api, npmVersion)', () => {
     api.getFileContent.mockReturnValueOnce('Existing package-lock.json');
     let e;
     try {
-      await npmHelper.getLockFile('package.json', '', api, '4.0.0');
+      await npmHelper.getLockFile(tmpDir, 'package.json', '', api, '4.0.0');
     } catch (err) {
       e = err;
     }
@@ -75,7 +76,7 @@ describe('getLockFile(packageFile, packageContent, api, npmVersion)', () => {
   });
 });
 
-describe('maintainLockFile(inputConfig)', () => {
+describe('maintainLockFile', () => {
   let config;
   beforeEach(() => {
     config = { logger };
@@ -86,6 +87,7 @@ describe('maintainLockFile(inputConfig)', () => {
     config.versions = {
       npm: '5.3.0',
     };
+    config.tmpDir = tmpDir;
     config.api.getFileContent.mockReturnValueOnce('oldPackageContent');
     npmHelper.getLockFile = jest.fn();
   });
diff --git a/test/workers/branch/yarn.spec.js b/test/workers/branch/yarn.spec.js
index d05815cde5e7852eb30cc8193fc651d7ecf9360d..4877659df4e7e4bce10edce331beb142e7f69deb 100644
--- a/test/workers/branch/yarn.spec.js
+++ b/test/workers/branch/yarn.spec.js
@@ -1,17 +1,16 @@
 const yarnHelper = require('../../../lib/workers/branch/yarn');
 const logger = require('../../_fixtures/logger');
 
-jest.mock('fs');
+jest.mock('fs-extra');
 jest.mock('child_process');
-jest.mock('tmp');
 
-const fs = require('fs');
+const fs = require('fs-extra');
 const cp = require('child_process');
-const tmp = require('tmp');
 
-describe('generateLockFile(newPackageJson, npmrcContent, yarnrcContent, logger)', () => {
-  tmp.dirSync = jest.fn(() => ({ name: 'somedir' }));
-  fs.writeFileSync = jest.fn();
+const tmpDir = { name: 'some-dir' };
+
+describe('generateLockFile', () => {
+  fs.outputFile = jest.fn();
   fs.readFileSync = jest.fn(() => 'yarn-lock-contents');
   cp.spawnSync = jest.fn(() => ({
     stdout: '',
@@ -19,18 +18,18 @@ describe('generateLockFile(newPackageJson, npmrcContent, yarnrcContent, logger)'
   }));
   it('generates lock files', async () => {
     const yarnLock = await yarnHelper.generateLockFile(
-      'package-json-contents',
+      tmpDir.name,
+      {},
       'npmrc-contents',
       'yarnrc-contents',
       logger
     );
-    expect(tmp.dirSync.mock.calls.length).toEqual(1);
-    expect(fs.writeFileSync.mock.calls.length).toEqual(3);
+    expect(fs.outputFile.mock.calls.length).toEqual(3);
     expect(fs.readFileSync.mock.calls.length).toEqual(1);
     expect(yarnLock).toEqual('yarn-lock-contents');
   });
 });
-describe('getLockFile(packageJson, config)', () => {
+describe('getLockFile', () => {
   let api;
   beforeEach(() => {
     api = {
@@ -39,9 +38,9 @@ describe('getLockFile(packageJson, config)', () => {
   });
   it('returns null if no existing yarn.lock', async () => {
     api.getFileContent.mockReturnValueOnce(false);
-    expect(await yarnHelper.getLockFile('package.json', '', api, '')).toBe(
-      null
-    );
+    expect(
+      await yarnHelper.getLockFile(tmpDir, 'package.json', '', api, '')
+    ).toBe(null);
   });
   it('returns yarn.lock file', async () => {
     api.getFileContent.mockReturnValueOnce('Existing yarn.lock');
@@ -54,12 +53,12 @@ describe('getLockFile(packageJson, config)', () => {
       contents: 'New yarn.lock',
     };
     expect(
-      await yarnHelper.getLockFile('package.json', '', api, '')
+      await yarnHelper.getLockFile(tmpDir, 'package.json', '', api, '')
     ).toMatchObject(yarnLockFile);
   });
 });
 
-describe('maintainLockFile(inputConfig)', () => {
+describe('maintainLockFile', () => {
   let config;
   beforeEach(() => {
     config = { logger };
@@ -67,6 +66,7 @@ describe('maintainLockFile(inputConfig)', () => {
     config.api = {
       getFileContent: jest.fn(),
     };
+    config.tmpDir = tmpDir;
     config.api.getFileContent.mockReturnValueOnce('oldPackageContent');
     yarnHelper.getLockFile = jest.fn();
   });
diff --git a/yarn.lock b/yarn.lock
index c463d9b06f7aa692341ce37de85f40893b98609d..9f1a04757c6be62685e10d7828c09810722e5f22 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1363,6 +1363,14 @@ from@~0:
   version "0.1.7"
   resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
 
+fs-extra@4.0.1:
+  version "4.0.1"
+  resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.1.tgz#7fc0c6c8957f983f57f306a24e5b9ddd8d0dd880"
+  dependencies:
+    graceful-fs "^4.1.2"
+    jsonfile "^3.0.0"
+    universalify "^0.1.0"
+
 fs-readdir-recursive@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.0.0.tgz#8cd1745c8b4f8a29c8caec392476921ba195f560"
@@ -2317,6 +2325,12 @@ json5@^0.5.1:
   version "0.5.1"
   resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
 
+jsonfile@^3.0.0:
+  version "3.0.1"
+  resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66"
+  optionalDependencies:
+    graceful-fs "^4.1.6"
+
 jsonify@~0.0.0:
   version "0.0.0"
   resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73"
@@ -3998,6 +4012,10 @@ underscore.string@~2.2.0rc:
   version "2.2.1"
   resolved "https://registry.yarnpkg.com/underscore.string/-/underscore.string-2.2.1.tgz#d7c0fa2af5d5a1a67f4253daee98132e733f0f19"
 
+universalify@^0.1.0:
+  version "0.1.1"
+  resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.1.tgz#fa71badd4437af4c148841e3b3b165f9e9e590b7"
+
 url-parse-lax@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73"