house9

random code and what not

CircleCI: Could not get cache stat, action npm install failed

| Comments

Our builds started to randomly fail on CircleCI when executing npm install:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
npm install
npm ERR! Could not get cache stat 
npm ERR! Could not get cache stat 
npm ERR! Could not get cache stat 
npm ERR! Linux 3.14.28-031428-generic
npm ERR! argv "node" "/home/ubuntu/nvm/v0.10.32/bin/npm" "install"
npm ERR! node v0.10.32
npm ERR! npm  v2.1.16
npm ERR! path /home/ubuntu/.npm/_git-remotes/git-github-com-SOMEPATH-ON-GITHUB-2799bac7/objects/pack/pack-ba6de98838bb215ca34b4ebaac78c6dbad04a80b.keep
npm ERR! code ENOENT
npm ERR! errno 34

npm ERR! enoent ENOENT, chown '/home/ubuntu/.npm/_git-remotes/git-github-com-SOMEPATH-ON-GITHUB-2799bac7/objects/pack/pack-ba6de98838bb215ca34b4ebaac78c6dbad04a80b.keep'
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent 

npm ERR! Please include the following file with any support request:
npm ERR!     /home/ubuntu/PROJECT-NAME/npm-debug.log

npm install returned exit code 34
action npm install failed

Sometimes it would take re-running the build 3 or 4 times before going green.

Each failure was always due to installing via Git URL.

Adding ~/.npm/_git-remotes/ to the cache_directories of the circle configuration fixed the majority of these issues:

1
2
3
4
5
6
7
8
9
10
11
machine:
  node:
    version: 0.10.32
dependencies:
  cache_directories:
    - "node_modules"
    - "~/.npm/_git-remotes/"
  override:
    - npm prune && npm install
  post:
    - bower install

upgrading from rspec 2 to rspec 3

| Comments

I’ve spent the last few days upgrading a rails application from 4.1 to 4.2 and as part of the upgrade going from rspec 2.99 to 3.2.

The rspec upgrade was much easier than I had anticipated thanks to the transpec gem.

  • added the rspec-its gem to my Gemfile
  • then ran the transpec migration
1
2
3
4
gem install transpec
transpec --keep its --negative-form to_not
rspec spec
git commit -aeF .git/COMMIT_EDITMSG

Only a few minor tweaks were needed to my specs after the migration – the transpec is brilliant!

ember-cli broccoli fingerprinting

| Comments

ember-cli uses broccoli for asset compilation and fingerprinting of asset file names.

When the environment is production, the addon will automatically fingerprint your js, css, png, jpg, and gif assets …

No fingerprinting occurs in the development environment. These are great defaults, but what if you have a staging environment and want to fingerprint those assets? You can override the fingerprint setting when the ember application is created.

1
2
3
4
5
var app = new EmberApp({
  fingerprint: {
    enabled: true
  }
});

Now all environments will fingerprint assets, but we really don’t want that in development. Since the ember application has not booted up yet we do not have access to the configuration object directly – lucky for us it is available on the process object before the ember application is created.

1
2
3
4
5
6
7
8
// Brocfile.js
var emberEnvironment = process.env.EMBER_ENV;
var fingerprint = (emberEnvironment === 'production' || emberEnvironment === 'staging');
var app = new EmberApp({
  fingerprint: {
    enabled: fingerprint
  }
});

AWS IAM policy for uploading SSL certificates

| Comments

The following IAM policy can be used to upload SSL certificates to AWS for use by cloudfront or ELB.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "iam:DeleteServerCertificate",
        "iam:UploadServerCertificate",
        "iam:ListServerCertificates",
        "iam:GetServerCertificate"
      ],
      "Resource": "*"
    }
  ]
}

This policy gives full access to certificate management and nothing else.

Resources

rbenv and Your user account isn’t allowed to install to the system Rubygems

| Comments

This happened to me after re-installing my OS and using a fresh install of rbenv. I cloned my application repository and went to execute a bundle install and received the following error:

1
2
3
4
5
6
7
8
9
10
11
12
Fetching source index from http://rubygems.org/


Your user account isn't allowed to install to the system Rubygems.
You can cancel this installation and run:

    bundle install --path vendor/bundle

to install the gems into ./vendor/bundle/, or you can enter your password
and install the bundled gems to Rubygems using sudo.

Password:

What? rbenv should not be prompting me to use sudo, it was trying to install gems on the system version of ruby. Running rbenv local returned 2.1.4 as expected, what the heck was going on?

gem list | grep bundler returned nothing – doh! I didn’t have bundler installed via rbenv so it was falling back to the system ruby. I was not expecting it to use a different version of bundler.

1
2
3
4
rbenv local
gem install bundler
rbenv rehash
bundle

And all was right with the world again!

Setup Mac OS X for rails development

| Comments

Whenever I get new machine or re-install my OS I like to use pivotals sprout-wrap for the setup. I have been through the process many times and finally documented it back in October.

From the app store install XCode

  • open XCode and accept the terms, then close app
  • from the terminal run: xcode-select --install
  • copy ssh keys from old machine via airdrop
  • then install sprout-wrap dependencies using the built in version of Ruby that ships with Mac OS X:
1
2
3
4
5
6
7
sudo gem install soloist
sudo gem install bundler
mkdir installs
cd installs
git clone https://github.com/pivotal-sprout/sprout-wrap.git
cd sprout-wrap
sudo bundle

Modify the soloistrc file if desired; for me that means adding ‘sourcetree’, ‘hipchat’ and a few others to the casks section.

The full list of available casks are here: https://github.com/pivotal-sprout/sprout-osx-apps/tree/master/recipes

You probably want to change the ‘Energy Saver’ settings to never while the installs are running.

bundle exec soloist

Enter your password after prompted and then watch the magic happen…

A few hours later, after sprout-wrap is done; time for a few more ‘manual’ installs

  • janus for vim configuration (i dont’ use vim much but occasionally pair with people who do)
  • Clone personal dotfiles
  • install some firefox add ons
  • For chrome once I login to Google all of my add ons will auto install
  • Install SublimeText3 and Package Control
    • If you prefer SublimeText2 it is available as a cask and can be installed via soloist

then Encrypt your hard drive using FileVault2

Done! :)


NOTE: if you install sprout-wrap with defaults it will configure many os-x settings which you may or may not like; I personally do like them, especially the ‘Fast Key Repeat Rate’.

This post originally appeared on the private discussion board Ruby Rogues Parley.

Rails, timezones, javascript and moment.js

| Comments

So you need to display some datetimes in your new ember.js/angular/backbone UI and the times must be displayed for a timezone which is different from the logged on user.

Let us say we have an Event class in our rails application with the following attributes:

1
2
3
4
5
6
create_table :events do |t|
  t.string :event_name, null: false
  t.text :description
  t.datetime :start_at, null: false
  t.string :time_zone, null: false, default: 'UTC'
end

Rails uses the timezone format: Eastern Time (US & Canada)

Javascript (and therefore the moment-timezone library) use the format: America/New_York

Rails can easily convert this for you and return the proper js format in your json:

1
2
3
4
5
6
7
8
class Event < ActiveRecord::Base
  # ...

  def time_zone_mapping
    # time_zone => Eastern Time (US & Canada)
    ActiveSupport::TimeZone::MAPPING[self.time_zone] # => America/New_York
  end
end

and with moment.js and moment-timezone

1
2
// where 'event' is the js representation of your rails model
moment(event.startAt).tz(event.timeZoneMapping).format('dddd, MMMM Do YYYY h:mm a z');

You will want to ensure that all json is being rendered with UTC as the configured timezone in rails, i.e. config.time_zone = 'UTC' in your application config and/or Time.zone = 'UTC' in your api controller.

See also

rubocop script for your modified files

| Comments

Our CI server is setup to run rubocop (ruby linter) after every checkin. On my local development machine I prefer to lint files that have recently changed and not the entire code base.

Add this code to a shell script and it will lint all files that have been staged. Note it uses the autofix rubocop option, optionally you could run it on non-staged files without the autofix flag.

1
git diff --name-only --cached | grep '\.rb' | xargs rubocop -a

Don’t forget to git add . after rubocop finds/fixes any code style violations in your staged files.

Protractor - promises all the way down

| Comments

Expected undefined to equal 7.

We recently started using Protractor for end to end testing of an angular application. Protractor returns promises when locating elements on the page, in some cases you may need to do your assertions inside of callback functions.

For example:

1
2
3
4
5
6
7
8
9
10
// this works just fine
expect(element(by.id('email')).getText()).toEqual('x@x.com');

// this will fail
expect(element(by.id('email')).getText().length).toEqual(7);

// getText retuns a promise and not a string, instead...
element(by.id('email')).getText().then(function (data) {
  expect(data.length).toEqual(7);
});

You can use the elementexplorer to debug your locators, but be aware that even non-matched elements will return an ‘Element Finder’ object.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
node node_modules/protractor/bin/elementexplorer.js

Getting page at: about:blank
> browser.get('http://www.angularjs.org');
null
> element(by.model('xxxx'))
{ click: [Function],
  sendKeys: [Function],
  getTagName: [Function],
  getCssValue: [Function],
  getAttribute: [Function],
  getText: [Function],
  getSize: [Function],
  getLocation: [Function],
  isEnabled: [Function],
  isSelected: [Function],
  submit: [Function],
  clear: [Function],
  isDisplayed: [Function],
  getOuterHtml: [Function],
  getInnerHtml: [Function],
  toWireValue: [Function],
  findElements: [Function],
  isElementPresent: [Function],
  evaluate: [Function],
  findElement: [Function],
  find: [Function],
  isPresent: [Function],
  element: { [Function] all: [Function] },
  '$': [Function],
  '$$': [Function] }

However, invoking one of the methods on an unmatched element will raise a NoSuchElementError.

Resources:

stub paperclip s3 uploads in rspec

| Comments

I was searching around stackoverflow trying to figure how to stub out s3 uploads with paperclip when running unit tests; came across a few that looked promising, along the lines of:

1
Model.any_instance.stubs(:save_attached_files).returns(true)

But that was not working with paperclip version 4, a quick look at the stacktrace reveled the method I wanted to mock.

Failure/Error: report.save
AWS::S3::Errors::InvalidAccessKeyId:
  The AWS Access Key Id you provided does not exist in our records.
/Users/me/.rvm/gems/ruby-2.1.0/gems/aws-sdk-1.33.0/lib/aws/core/client.rb:374:in `return_or_raise'
/Users/me/.rvm/gems/ruby-2.1.0/gems/aws-sdk-1.33.0/lib/aws/core/client.rb:475:in `client_request'
(eval):3:in `put_object'
/Users/me/.rvm/gems/ruby-2.1.0/gems/aws-sdk-1.33.0/lib/aws/s3/s3_object.rb:1751:in `write_with_put_object'
/Users/me/.rvm/gems/ruby-2.1.0/gems/aws-sdk-1.33.0/lib/aws/s3/s3_object.rb:607:in `write'
/Users/me/.rvm/gems/ruby-2.1.0/gems/paperclip-4.0.0/lib/paperclip/storage/s3.rb:337:in `block in flush_writes'
/Users/me/.rvm/gems/ruby-2.1.0/gems/paperclip-4.0.0/lib/paperclip/storage/s3.rb:314:in `each'
/Users/me/.rvm/gems/ruby-2.1.0/gems/paperclip-4.0.0/lib/paperclip/storage/s3.rb:314:in `flush_writes'
/Users/me/.rvm/gems/ruby-2.1.0/gems/paperclip-4.0.0/lib/paperclip/attachment.rb:239:in `save'
/Users/me/.rvm/gems/ruby-2.1.0/gems/paperclip-4.0.0/lib/paperclip/has_attached_file.rb:87:in `block in add_active_record_callbacks'
/Users/me/.rvm/gems/ruby-2.1.0/gems/activesupport-3.2.16/lib/active_support/callbacks.rb:460:in `_run__2863894366922569793__save__4567171711544756900__callbacks'
/Users/me/.rvm/gems/ruby-2.1.0/gems/activesupport-3.2.16/lib/active_support/callbacks.rb:405:in `__run_callback'
/Users/me/.rvm/gems/ruby-2.1.0/gems/activesupport-3.2.16/lib/active_support/callbacks.rb:385:in `_run_save_callbacks'
# ...

after double checking the code on github, a working stub:

1
Paperclip::Attachment.any_instance.stub(:save).and_return(true)