Running bower install from Puppet

In automating the deployment of an application, I needed to run bower install from a Puppet exec { } statement. I was getting the following output with a failure:

Notice: /Stage[main]/Foo/Exec[run bower]/returns: undefined
Notice: /Stage[main]/Foo/Exec[run bower]/returns:
Notice: /Stage[main]/Foo/Exec[run bower]/returns: path.js:360
Notice: /Stage[main]/Foo/Exec[run bower]/returns:         throw new TypeError('Arguments to path.join must be strings');
Notice: /Stage[main]/Foo/Exec[run bower]/returns:               ^
Notice: /Stage[main]/Foo/Exec[run bower]/returns: TypeError: Arguments to path.join must be strings
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at path.js:360:15
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at Array.filter (native)
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at Object.exports.join (path.js:358:36)
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at Object.<anonymous> (/usr/local/lib/node_modules/bower/node_modules/insight/nod
e_modules/configstore/node_modules/xdg-basedir/index.js:8:42)
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at Module._compile (module.js:456:26)
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at Object.Module._extensions..js (module.js:474:10)
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at Module.load (module.js:356:32)
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at Function.Module._load (module.js:312:12)
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at Module.require (module.js:364:17)
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at require (module.js:380:17)
Notice: /Stage[main]/Foo/Exec[run bower]/returns:     at Object.<anonymous> (/usr/local/lib/node_modules/bower/node_modules/insight/nod
e_modules/configstore/index.js:11:18)

After taking a look what has happening in the insight node module, I saw that the userHome variable was not getting set from the user-home module.

It would seem that the HOME environment variable does not get set by Puppet’s Exec resource, which is a little odd to me, but I suppose somewhat reasonable. Simply updating my exec statement to manually set it resolved the issue:

exec { 'run puppet':
  cwd         => '/home/foo/my-app',
  user        => 'foo',
  command     => 'bower install --config.interactive=false',
  environment => 'HOME=/home/foo'
}

Also note the --config.interactive=false. Without that, Bower wants to know if you’re willing to send along usage information by way of an automated script-incompatible prompt.

I’d also like to briefly mention the importance of understanding and reading through a stack trace, opening up some files, finding source code, and understanding what’s happening as a way to debug a problem. I see many junior and senior developers out there who seem to give up after a Google search fails. I cannot stress how important this skill is as a developer.