Mastodon

Keeping credentials out of your code with environmental vars

I have a project that is up on Github and deployed to Heroku. As I was adding the user credentials file to my project it dawned on me: my application needs these credentials when I run it on Heroku but I don’t want them to be part of my project and therefore visible to everyone on Github.

Turning to the great minds at Stackoverflow, I was advised to use environmental variables.
Since my application is connecting to another site via SFTP I have a hash of all the usual stuff; username password and hostname. It turns out you can just reference environmental variables like this:

@sftp_credentials = {Rails.env.to_sym => {
:sftp_host => ENV[‘SFTP_HOST’],
:sftp_user => ENV[‘SFTP_USER’],
:sftp_password => ENV[‘SFTP_PASSWORD’]
}}

And then make sure you have the environment vars set in your .bashrc so they are available during local development:

export SFTP_HOST=’somesite.com’
export SFTP_USER=’someuser’
export SFTP_PASSWORD=’somepassword’

And then set those variables on Heroku so they are available when your app runs there:

mike@sleepycat:~/projects/myapp$ heroku config:add SFTP_HOST=somesite.com SFTP_USER=someuser SFTP_PASSWORD=somepassword
Adding config vars:
SFTP_HOST => somesite.com
SFTP_PASSWORD => somepassword
SFTP_USER => someuser
Restarting app…done.

Git: Not a valid object name?

I have been using branches in my general development workflow for while but a lot of my development has just been local. Recently I have been moving between computers and pushing my project up to github. This works well but introduces a minor twist on branching; creating local tracking branches for remote branches.
I have been using git branch –track and life has been good. Well today I must have done something different:

mike@sleepycat:~/projects/my_app$ git branch –track haml_val origin/haml_val
fatal: Not a valid object name: ‘origin/haml_val’.

A fatality huh? I checked my syntax and it really was fine. Curious I checked my remotes:

mike@sleepycat:~/projects/myapp$ git remote show origin

haml_val new (next fetch will store in remotes/origin)

From that I decide that a quick git pull (which I believe runs git fetch and then get merge) should do the trick but I get the same error. After some head scratching it turns out that the solution really is fetch:

mike@sleepycat:~/projects/myapp$ git fetch origin
From github.com:sleepycat/myapp
* [new branch] haml_val -> origin/haml_val
bf4ba85..83f687f master -> origin/master
mike@sleepycat:~/projects/myapp$ git branch –track haml_val origin/haml_val
Branch haml_val set up to track remote branch haml_val from origin.

Success! I still don’t know why that would work and git pull wouldn’t but either way its a lesson learned.

My Git cheatsheet

“Good judgement comes from experience, and often experience comes from bad judgement.”

~Rita Mae Brown

I am pretty sure Rita Mae was talking about Git when she said that. Git is complicated and I don’t think you can really feel comfortable with it until you have created a few disasters with it and hopefully recovered from them using it. I’m no git guru, but I am starting to know a thing or two and I thought I would write down a few of the things that have come up a few times for me. I’ll be adding to this as new ones come up for me. Corrections or suggestions are welcome.

Seeing uncommitted modifications.

Quite a few times I have seen a file listed in git status as modified and thought “What changed in there?”. Essentialy what you are asking is whats the difference between the file pointed to by HEAD and the file.

mike@sleepycat:~/projects/myapp$ git diff — HEAD app/controllers/ceo_controller.rb

diff –git a/app/controllers/ceo_controller.rb b/app/controllers/ceo_controller.rb

index 927112d..3efc1fa 100755

— a/app/controllers/ceo_controller.rb

+++ b/app/controllers/ceo_controller.rb

@@ -26,6 +26,11 @@ class CeoController < ApplicationController

+

+ def claimed_reward

+ @claimed_reward = @member.claimed_rewards.find(params[:id])

+ show_image @claimed_reward.coupon.id

+ end

def gm_preferences

if request.post?

git diff will show all changes in all files.

Adding something to your last commit.

Inevitably after triumphantly committing a piece of code there will end up being some other thing you need to do. Perhaps its suddenly realizing the debugger statement is still in there, or realising that some comments would be a good idea.

…make changes…

git add -u

git commit

Oops! Forgot something

…make changes…

git add -u

git commit –amend

Undoing a commit –amend

Sometimes my last commit doesn’t end up being what I thought it was. Accidentally tacking a minor bug fix onto a merge commit with –amend is kind of goofy, so to undo it:

git reset –soft HEAD@{1}

For more info on the HEAD@{1} or related syntax like HEAD^, you want to look up treeishes.

Step back one commit.

git reset –hard HEAD^

The command above moves the head pointer back one commit and gets rid of the changes.

git reset –soft HEAD^

This would also move the head pointer back one commit but the files you changed would be visible as “modified” when you run git status.

If you are using Heroku to host your project there is an additional consideration. Stepping back one commit means that your remote master on the server at Heroku is further ahead than your local repo. When you try to push you are going to get this:

! [rejected] master -> master (non-fast forward)

The answer is; force it.

git push heroku master –force

Deleting merged branches.

Working with branches is great but it won’t take long before you end up with a pretty long list of branches. Prune your branches with

git branch -d name_of_branch

This will only delete the branch if it has been merged into the current branch. So:

git checkout master

git branch -d facebook_stuff

would only delete the facebook_stuff branch if it had been merged into the master branch already.

Adding a remote.

Out of a general sense of paranoia I periodically have a need to clone the main repository. I’ll try some experiment, fix something… whatever. and then ocaisionally I will want to send the results to staging which I have set up as a remote. The problem is that my staging remote is set up on the original project not the clone so I have to create it again. Since I have had to look this up a few times. This command will show the details for the repo I have titled “staging”:

git remote show staging

Doing that on my original project shows me the address of the repo which I copy to the clipboard and, switching to the newly cloned copy repo, can recreate my link to staging there. This will create a new remote titled staging pointing to an app on heroku.com:

git remote add staging git@heroku.com:<my_app_name>.git

Ignoring files and directories with .gitignore

Create a file in the root of your project called .gitignore. Add whatever rules you need. What you see below will ignore everything in the log directory and the tmp/sass-cache/ directory as well as any file with a .orig extension.

log/
tmp/sass-cache/
*.orig

Somewhat counter-intuitively you need to add the .gitignore file to your repo. For some reason my instinct is that is should somehow be ignored as well but my understanding is that you want it under revision control as well so add it and away you go.