Set `process.env.commit` on Heroku push - node.js

I'm using NPM's scripts.postinstall to build our application using GulpJS when we push it to Heroku:
"postinstall": "./node_modules/.bin/gulp build --require coffee-script/register"
I want to be able to set an environment variable at this time with the value of the commit hash. This will then be referenced in files as a cachebuster, e.g.:
<script type="text/javascript" src="/index.{{ process.env.commit }}.js"></script>
I can use git-rev to easily get this value asynchronously but I want it stored on an environment level. How can I set a custom Node environment variable?
If I'm going about this the wrong way and there's a better solution please let me know (I can only find methods to set NODE_ENV and not the process.env object itself).

You cannot do this via a postinstall script: the heroku command won't be available in the build environment. You can create your own lightweight deployment script that runs the command on your machine when a successful build occurs however:
#!/bin/sh
git push heroku master && heroku config:set COMMIT=$(git rev-parse --short HEAD)
To note, I got confirmation of this from Heroku support directly. This was their response:
There isn't an installation of heroku toolbelt on the slug compiler. If you need to set an environment variable as part of the push then you'll have to do it on your machine rather than the Heroku compiler.

Solution I've found is to use the heroku config system to set custom environment variables:
git = require "git-rev"
exec = require "exec-sync"
gulp.task "commit", ->
git.long (hash) ->
exec "heroku config:set COMMIT=#{ hash }"
Needs further testing but for now it works (also, because the command is run on the server there's no need to use heroku config:push).

You can now add this metadata with this labs feature from heroku !
heroku labs:enable runtime-dyno-metadata -a <app name>

Related

Heroku: How to deploy a NodeJS app with a private repo dependency?

I want to deploy a NodeJS app on Heroku that has a private repository listed as a dependency in package.json.
How do I grant Heroku read-only access to this single repository, without exposing any credentials unnecessarily?
This question has been asked repeatedly in various forms, but I was unable to get any of the answers working.
Here is what finally did the trick — Note that I am on Windows 10:
Generate key in git bash with the command ssh-keygen -t ssh-rsa -C "myusername#protonmail.com" (empty password)
Copy & paste the *.pub file (created by the above command) contents as a deploy key here: https://github.com/myusername/my-private-repo/settings/keys
my-private-repo above refers to the dependency, not the repo you are deploying
On Heroku, add https://github.com/heroku/heroku-buildpack-ssh-key.git as a buildpack — ABOVE — the heroku/nodejs buildpack
Set your Heroku app's environment variable BUILDPACK_SSH_KEY to the — ENTIRE — contents of the other file (not the one ending with .pub) including the NEWLINE at the end (not sure if that's optional)
Set dependency URL in package.json like so:
"dependencies": {
"my-private-repo": "git+ssh://github.com/myusername/my-private-repo.git"
}
Happy deploying 🙂

Elastic Beanstalk Environment Variables Missing When In SSH

I'm trying to run some commands on my NodeJS app that need to be run via SSH (Sequelize seeding for instance), however when I do so, I noticed that the expected env vars were missing.
If I run eb printenv on my local machine I see the expected environment variables that were set in my EB Dashboard
If I SSH in, and run printenv, all of those variables I expect are missing.
So what happens, is when I run my seeds, I get an error:
node_modules/.bin/sequelize db:seed:all
ERROR: connect ECONNREFUSED 127.0.0.1:3306
I noticed that the port was wrong, it should be 5432. I checked to see if my environment variables were set with printenv and they are not there. This leads me to suspect that the proper env variables are not loaded in my ssh session, and NodeJS is falling back to the default values I provided in my config.
I found some solutions online, like running the following to load the env variables:
/opt/python/current/env
But the python directory doesn't exist. All that's inside /opt/ is elasticbeanstalk and aws directories.
I had some success so I could at least see that the env variables exist somewhere on the server by running the following:
sudo /opt/elasticbeanstalk/bin/get-config environment --output YAML
But simply running this command does not fix the problem. All it does is output the expected env variables to the screen. That's something! At least I know they are definitely there! But the env variables are still not there when I run printenv
So how do I fix this problem? Sequelize and NodeJS are clearly not seeing the env variables either, and it's trying to use the fallback default values that are set in my config file.
I know my answer is late, but I had the same problem and after some attempts with bash script I found a way to store it in your env vars.
you can simply run the following command:
export env=`/opt/elasticbeanstalk/bin/get-config environment -k <your-variable-name>`
now you will be able to easily access this variable:
echo $your-variable-name
afterward, you can utilize the env var to do what ever you like. in my case, I use it to decide which version of my code to build in a file called build-script.sh and its content is as follows:
# get env variable to know in which environment this code is running in
export env=`/opt/elasticbeanstalk/bin/get-config environment -k environment`
# building the code based on the current environment
if [ $env = "production" ]
then
echo "building for production"
npm --prefix /var/app/current run build-prod
else
echo "building for non production"
npm --prefix /var/app/current run build-prod
fi
hope this helps anyone facing the same issue 🤟🏻

(remote rejected) master -> master (pre-receive hook declined), Push rejected, failed to compile Node.js app

I know that there's couple posts like this one, but solution of any of them works for me.
Here is what I receive when I go for git push heroku master:
Please support. Ignoring node_modules is not working.
Docpad app - package.json file is updated according to docpad's manual.
I also have Procfile set up as in the link above.
PS. I have tried to deploy docpad app via openshift, but while Im going with manual from http://docpad.org/docs/deploy/ I receive error at step 5.
The application 'appname' is configured for git reference deployments but the
artifact provided ('https://github.com/myusername/appname#master') is a url.
Please provide a git reference to deploy (branch, tag or commit SHA1) or
configure your app to deploy from binaries with 'rhc configure-app appname
--deployment-type binary'.
If I configure myapp to deployment-type binary it isnt working neither.
The plugin which heroku tries to install returned 404 and the installation fails due to that.
Verify that the plugin is indeed public and not something you have wrote or used locally.
There is no package with this name hosted on the registry you use.
Remove the line with "docpad-plugin-blah": "2" from your package.json file. That line was provided in the docs simply to show you how to install plugins, but there's no such plugin as blah.
"dependencies": {
"docpad": "6"
},
I strongly recommend that you read through the Getting Started on OpenShift to get an overview of the development workflow using Git.
That being said, and if you really meant to use git reference deployments and you know why you are using them, then read through the Managing Deployments section on the developers page of OpenShift and find out how to properly set up git reference deployments. For instance, 'https://github.com/myusername/appname#master' is not a valid git url and therefore it cannot be cloned.

How can I run script after deploy to heroku

I have an application in node.js which depends on env variables. I made some changes in code and now one of this vars should be changed after deploy. I don't want to do this manually. What is the best practise to do this automatically.
I guess that running some script after deploy could be solution, but I want to run this script only once (with this one particular change).
My only idea is that I should have script that will be checking (after each deploy) some directory if there is another script to run and then run it and remove it. But how can I achieve that?
The best way to approach this is to use the Heroku Toolbelt to set your environment variables as described here:
heroku config:set GITHUB_USERNAME=joesmith
You can then refer to these variables in your Node.js application by using the following syntax:
var dbUsername = process.env.DB_USERNAME;
Assuming you set a DB_USERNAME variable like this:
heroku config:set DB_USERNAME=myAppUserName
I like to ensure there's a fallback if the environment variable is not set, you can achieve that like this:
var dbUsername = process.env.DB_USERNAME || 'fallbackUsername';
// The string after || will be used if the process.env.DB_USERNAME variable is undefined (not set)

Heroku reports "no app specified" on Windows command line

I have a node.js application running on Heroku. I've used the (Windows) command line to initialize the app with heroku create, and I can hit the production website and see that it's running correctly. All's good.
But when I try to run simple commands, like heroku ps, from the directory in which the app lives, Heroku responds with a "no app specified" error:
C:\dev\iq>heroku ps
! No app specified.
! Run this command from an app folder or specify which app to use with --app APP.
I've read in other posts that you can avoid having to use the --app APP syntax with every command if you configure git like so:
git config heroku.remote heroku
However, after doing so, Heroku still complains that the app wasn't specified for simple command line requests. I've verified that .git/config has been updated appropriately:
C:\dev\iq>type .git\config
[core]
repositoryformatversion = 0
filemode = false
bare = false
logallrefupdates = true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
[remote "heroku"]
url = git#heroku.com:aqueous-mountain-xxxx.git
fetch = +refs/heads/*:refs/remotes/heroku/*
[heroku]
remote = heroku
I've just reinstalled the latest version of Heroku:
C:\dev\iq>heroku --version
heroku/toolbelt/3.2.2 (i386-mingw32) ruby/1.9.3
What am I missing?
The 'heroku' command requires the '--app' parameter to target a given application, unless you run it from a application folder (clone of the Git repo containing your application).
From my experience, this error occurs when the code is not pushed to heroku (git push heroku master) before running heroku ps.

Resources