Repository: semantic-release/npm (js)

Issue:
Error: package.json requires a valid "version" field
This seems to be introduces by the patch in #22. If my `package.json` doesn't contain a `version` field, I'm not able to publish it to npm.
Using a placeholder like `0.0.0-development` as I see it in this repository solves this, but is this actually the intended usage?

Pull request:
Verify `package.json` has a `version` property
Fix #27

Patch:
diff --git a/lib/get-pkg.js b/lib/get-pkg.js
index e7a3a91..ba364a7 100644
--- a/lib/get-pkg.js
+++ b/lib/get-pkg.js
@@ -4,10 +4,15 @@ const SemanticReleaseError = require('@semantic-release/error');
 module.exports = async pkgRoot => {
   try {
     const pkg = await readPkg(pkgRoot);
+
     if (!pkg.name) {
       throw new SemanticReleaseError('No "name" found in package.json.', 'ENOPKGNAME');
     }
 
+    if (!pkg.version) {
+      throw new SemanticReleaseError('No "version" found in package.json.', 'ENOPKGVERSION');
+    }
+
     return pkg;
   } catch (err) {
     if (err.code === 'ENOENT') {


Test patch:
diff --git a/test/get-pkg.test.js b/test/get-pkg.test.js
index 4e72cd9..388f48a 100644
--- a/test/get-pkg.test.js
+++ b/test/get-pkg.test.js
@@ -16,7 +16,7 @@ test.afterEach.always(() => {
   process.chdir(cwd);
 });
 
-test.serial('Verify name and return parsed package.json', async t => {
+test.serial('Verify name and version then return parsed package.json', async t => {
   const pkg = {name: 'package', version: '0.0.0'};
   await outputJson('./package.json', pkg);
 
@@ -25,7 +25,7 @@ test.serial('Verify name and return parsed package.json', async t => {
   t.is(pkg.version, result.version);
 });
 
-test.serial('Verify name and return parsed package.json from a sub-directory', async t => {
+test.serial('Verify name and version then return parsed package.json from a sub-directory', async t => {
   const pkg = {name: 'package', version: '0.0.0'};
   await outputJson('./dist/package.json', pkg);
 
@@ -50,6 +50,15 @@ test.serial('Throw error if missing package name', async t => {
   t.is(error.code, 'ENOPKGNAME');
 });
 
+test.serial('Throw error if missing package version', async t => {
+  await outputJson('./package.json', {name: 'package'});
+
+  const error = await t.throws(getPkg());
+
+  t.is(error.name, 'SemanticReleaseError');
+  t.is(error.code, 'ENOPKGVERSION');
+});
+
 test.serial('Throw error if package.json is malformed', async t => {
   await writeFile('./package.json', "{name: 'package',}");
 
diff --git a/test/integration.test.js b/test/integration.test.js
index 85c41ba..306bf5f 100644
--- a/test/integration.test.js
+++ b/test/integration.test.js
@@ -116,7 +116,7 @@ test.serial(
 
 test.serial('Verify npm auth and package', async t => {
   Object.assign(process.env, npmRegistry.authEnv);
-  const pkg = {name: 'valid-token', publishConfig: {registry: npmRegistry.url}};
+  const pkg = {name: 'valid-token', version: '0.0.0-dev', publishConfig: {registry: npmRegistry.url}};
   await outputJson('./package.json', pkg);
   await t.notThrows(t.context.m.verifyConditions({}, {options: {}, logger: t.context.logger}));
 
@@ -127,7 +127,7 @@ test.serial('Verify npm auth and package', async t => {
 
 test.serial('Verify npm auth and package from a sub-directory', async t => {
   Object.assign(process.env, npmRegistry.authEnv);
-  const pkg = {name: 'valid-token', publishConfig: {registry: npmRegistry.url}};
+  const pkg = {name: 'valid-token', version: '0.0.0-dev', publishConfig: {registry: npmRegistry.url}};
   await outputJson('./dist/package.json', pkg);
   await t.notThrows(t.context.m.verifyConditions({pkgRoot: 'dist'}, {options: {}, logger: t.context.logger}));
 
@@ -139,7 +139,7 @@ test.serial('Verify npm auth and package from a sub-directory', async t => {
 test.serial('Verify npm auth and package with "npm_config_registry" env var set by yarn', async t => {
   Object.assign(process.env, npmRegistry.authEnv);
   process.env.npm_config_registry = 'https://registry.yarnpkg.com'; // eslint-disable-line camelcase
-  const pkg = {name: 'valid-token', publishConfig: {registry: npmRegistry.url}};
+  const pkg = {name: 'valid-token', version: '0.0.0-dev', publishConfig: {registry: npmRegistry.url}};
   await outputJson('./package.json', pkg);
   await t.notThrows(t.context.m.verifyConditions({}, {options: {}, logger: t.context.logger}));
 
@@ -150,7 +150,7 @@ test.serial('Verify npm auth and package with "npm_config_registry" env var set
 
 test.serial('Return nothing if no version if published', async t => {
   Object.assign(process.env, npmRegistry.authEnv);
-  const pkg = {name: 'not-published', publishConfig: {registry: npmRegistry.url}};
+  const pkg = {name: 'not-published', version: '0.0.0-dev', publishConfig: {registry: npmRegistry.url}};
   await outputJson('./package.json', pkg);
   const nextRelease = await t.context.m.getLastRelease({}, {options: {}, logger: t.context.logger});
 
@@ -243,7 +243,7 @@ test('Throw SemanticReleaseError if publish "pkgRoot" option in getLastRelease i
 });
 
 test('Throw SemanticReleaseError if publish "npmPublish" option in verifyConditions is not a Boolean', async t => {
-  const pkg = {name: 'invalid-npmPublish', publishConfig: {registry: npmRegistry.url}};
+  const pkg = {name: 'invalid-npmPublish', version: '0.0.0-dev', publishConfig: {registry: npmRegistry.url}};
   await outputJson('./package.json', pkg);
   const npmPublish = 42;
   const error = await t.throws(
@@ -261,7 +261,7 @@ test('Throw SemanticReleaseError if publish "npmPublish" option in verifyConditi
 });
 
 test('Throw SemanticReleaseError if publish "tarballDir" option in verifyConditions is not a String', async t => {
-  const pkg = {name: 'invalid-tarballDir', publishConfig: {registry: npmRegistry.url}};
+  const pkg = {name: 'invalid-tarballDir', version: '0.0.0-dev', publishConfig: {registry: npmRegistry.url}};
   await outputJson('./package.json', pkg);
   const tarballDir = 42;
   const error = await t.throws(
@@ -279,7 +279,7 @@ test('Throw SemanticReleaseError if publish "tarballDir" option in verifyConditi
 });
 
 test('Throw SemanticReleaseError if publish "pkgRoot" option in verifyConditions is not a String', async t => {
-  const pkg = {name: 'invalid-pkgRoot', publishConfig: {registry: npmRegistry.url}};
+  const pkg = {name: 'invalid-pkgRoot', version: '0.0.0-dev', publishConfig: {registry: npmRegistry.url}};
   await outputJson('./dist/package.json', pkg);
   const pkgRoot = 42;
   const error = await t.throws(