diff --git a/package.json b/package.json
index 3bed5f4c70ac703eae3a684a442cbf9fbfb6ac8e..d9d9e8e1e58eb8c42bdac9b20a28b4bcf3ac91b3 100644
--- a/package.json
+++ b/package.json
@@ -26,7 +26,7 @@
     "start": "babel-node --extensions \".ts,.js\" -- lib/renovate.ts",
     "test-dirty": "git diff --exit-code",
     "test-e2e": "npm pack && cd e2e && yarn install --no-lockfile && yarn test",
-    "test-schema": "bash test/json-schema.sh",
+    "test-schema": "babel-node --extensions \".ts,.js\" -- test/json-schema.ts",
     "test": "run-s lint test-schema type-check jest",
     "type-check": "tsc --noEmit"
   },
@@ -168,6 +168,7 @@
     "@types/node": "11.13.17",
     "@types/parse-link-header": "1.0.0",
     "@types/semver": "6.0.1",
+    "@types/shelljs": "0.8.5",
     "@types/tmp": "0.1.0",
     "@typescript-eslint/eslint-plugin": "1.12.0",
     "@typescript-eslint/parser": "1.12.0",
@@ -192,6 +193,7 @@
     "pretty-quick": "1.11.1",
     "rimraf": "2.6.3",
     "semantic-release": "15.13.18",
+    "shelljs": "0.8.3",
     "tmp-promise": "2.0.2",
     "typescript": "3.5.1"
   },
diff --git a/test/json-schema.sh b/test/json-schema.sh
deleted file mode 100755
index fbc7ca781885cba3805020229efdbb28aa574bff..0000000000000000000000000000000000000000
--- a/test/json-schema.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-yarn create-json-schema
-
-CHANGED=$(git status --porcelain | grep renovate-schema.json | wc -l)
-
-if [ "$CHANGED" -eq 0 ]; then
-    echo "PASS: renovate-schema.json is up to date"
-    exit 0
-else
-    git diff renovate-schema.json
-    echo "ERROR: renovate-schema.json needs updating. Run 'yarn create-json-schema' and commit."
-    exit -1
-fi
diff --git a/test/json-schema.ts b/test/json-schema.ts
new file mode 100644
index 0000000000000000000000000000000000000000..98ab68ae0f81d3ae0e5ae542616d4103da299151
--- /dev/null
+++ b/test/json-schema.ts
@@ -0,0 +1,17 @@
+import shell from 'shelljs';
+
+shell.exec('yarn create-json-schema');
+
+const res = shell
+  .exec('git status --porcelain', { silent: true })
+  .grep('renovate-schema.json');
+
+if (res.code === 0 && !res.includes('renovate-schema.json')) {
+  shell.echo('PASS: renovate-schema.json is up to date');
+  shell.exit(0);
+} else {
+  shell.echo(
+    "ERROR: renovate-schema.json needs updating. Run 'yarn create-json-schema' and commit."
+  );
+  shell.exit(-1);
+}
diff --git a/yarn.lock b/yarn.lock
index 2f2ab2cde5b9eed2b84f8e32679fe06a11e67322..ed3527d5c7c3ae349c5838c1ac788bd5c93354c0 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1122,7 +1122,7 @@
   dependencies:
     "@types/node" "*"
 
-"@types/glob@^7.1.1":
+"@types/glob@*", "@types/glob@^7.1.1":
   version "7.1.1"
   resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575"
   integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w==
@@ -1207,6 +1207,14 @@
   resolved "https://registry.yarnpkg.com/@types/semver/-/semver-6.0.1.tgz#a984b405c702fa5a7ec6abc56b37f2ba35ef5af6"
   integrity sha512-ffCdcrEE5h8DqVxinQjo+2d1q+FV5z7iNtPofw3JsrltSoSVlOGaW0rY8XxtO9XukdTn8TaCGWmk2VFGhI70mg==
 
+"@types/shelljs@0.8.5":
+  version "0.8.5"
+  resolved "https://registry.yarnpkg.com/@types/shelljs/-/shelljs-0.8.5.tgz#1e507b2f6d1f893269bd3e851ec24419ef9beeea"
+  integrity sha512-bZgjwIWu9gHCjirKJoOlLzGi5N0QgZ5t7EXEuoqyWCHTuSddURXo3FOBYDyRPNOWzZ6NbkLvZnVkn483Y/tvcQ==
+  dependencies:
+    "@types/glob" "*"
+    "@types/node" "*"
+
 "@types/stack-utils@^1.0.1":
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e"
@@ -4092,6 +4100,11 @@ inquirer@^6.2.2:
     strip-ansi "^5.1.0"
     through "^2.3.6"
 
+interpret@^1.0.0:
+  version "1.2.0"
+  resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
+  integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
+
 into-stream@^5.0.0:
   version "5.1.0"
   resolved "https://registry.yarnpkg.com/into-stream/-/into-stream-5.1.0.tgz#b05f37d8fed05c06a0b43b556d74e53e5af23878"
@@ -7336,6 +7349,13 @@ realpath-native@^1.1.0:
   dependencies:
     util.promisify "^1.0.0"
 
+rechoir@^0.6.2:
+  version "0.6.2"
+  resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384"
+  integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=
+  dependencies:
+    resolve "^1.1.6"
+
 redent@^2.0.0:
   version "2.0.0"
   resolved "https://registry.yarnpkg.com/redent/-/redent-2.0.0.tgz#c1b2007b42d57eb1389079b3c8333639d5e1ccaa"
@@ -7618,7 +7638,7 @@ resolve@1.1.7:
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.1.7.tgz#203114d82ad2c5ed9e8e0411b3932875e889e97b"
   integrity sha1-IDEU2CrSxe2ejgQRs5ModeiJ6Xs=
 
-resolve@^1.10.0, resolve@^1.11.0, resolve@^1.3.2, resolve@^1.5.0:
+resolve@^1.1.6, resolve@^1.10.0, resolve@^1.11.0, resolve@^1.3.2, resolve@^1.5.0:
   version "1.11.1"
   resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.11.1.tgz#ea10d8110376982fef578df8fc30b9ac30a07a3e"
   integrity sha512-vIpgF6wfuJOZI7KKKSP+HmiKggadPQAdsp5HiC1mvqnfp0gF1vdwgBWZIdrVft9pgqoMFQN+R7BSWZiBxx+BBw==
@@ -7906,6 +7926,15 @@ shell-quote@^1.6.1:
     array-reduce "~0.0.0"
     jsonify "~0.0.0"
 
+shelljs@0.8.3:
+  version "0.8.3"
+  resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097"
+  integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A==
+  dependencies:
+    glob "^7.0.0"
+    interpret "^1.0.0"
+    rechoir "^0.6.2"
+
 shellwords@^0.1.1:
   version "0.1.1"
   resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"