diff --git a/changelogs/fragments/2924-npm-fix-package-json.yml b/changelogs/fragments/2924-npm-fix-package-json.yml new file mode 100644 index 0000000000..ce4a416cf7 --- /dev/null +++ b/changelogs/fragments/2924-npm-fix-package-json.yml @@ -0,0 +1,3 @@ +bugfixes: + - npm - correctly handle cases where a dependency does not have a ``version`` property because it is either missing or invalid + (https://github.com/ansible-collections/community.general/issues/2917). diff --git a/plugins/modules/packaging/language/npm.py b/plugins/modules/packaging/language/npm.py index 5a48468970..6328768781 100644 --- a/plugins/modules/packaging/language/npm.py +++ b/plugins/modules/packaging/language/npm.py @@ -216,7 +216,6 @@ class Npm(object): self.module.fail_json(msg="Failed to parse NPM output with error %s" % to_native(e)) if 'dependencies' in data: for dep, props in data['dependencies'].items(): - dep_version = dep + '@' + str(props['version']) if 'missing' in props and props['missing']: missing.append(dep) @@ -224,7 +223,9 @@ class Npm(object): missing.append(dep) else: installed.append(dep) - installed.append(dep_version) + if 'version' in props and props['version']: + dep_version = dep + '@' + str(props['version']) + installed.append(dep_version) if self.name_version and self.name_version not in installed: missing.append(self.name) # Named dependency not installed diff --git a/tests/unit/plugins/modules/packaging/language/test_npm.py b/tests/unit/plugins/modules/packaging/language/test_npm.py index abdacc6aef..89de549915 100644 --- a/tests/unit/plugins/modules/packaging/language/test_npm.py +++ b/tests/unit/plugins/modules/packaging/language/test_npm.py @@ -52,6 +52,25 @@ class NPMModuleTestCase(ModuleTestCase): call(['/testbin/npm', 'install', '--global', 'coffee-script'], check_rc=True, cwd=None), ]) + def test_present_missing(self): + set_module_args({ + 'name': 'coffee-script', + 'global': 'true', + 'state': 'present', + }) + self.module_main_command.side_effect = [ + (0, '{"dependencies": {"coffee-script": {"missing" : true}}}', ''), + (0, '{}', ''), + ] + + result = self.module_main(AnsibleExitJson) + + self.assertTrue(result['changed']) + self.module_main_command.assert_has_calls([ + call(['/testbin/npm', 'list', '--json', '--long', '--global'], check_rc=False, cwd=None), + call(['/testbin/npm', 'install', '--global', 'coffee-script'], check_rc=True, cwd=None), + ]) + def test_present_version(self): set_module_args({ 'name': 'coffee-script',