Skip to content

Instantly share code, notes, and snippets.

@digitaljhelms
Last active December 23, 2015 05:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save digitaljhelms/6589916 to your computer and use it in GitHub Desktop.
Save digitaljhelms/6589916 to your computer and use it in GitHub Desktop.
Boilerplate files for a client-side JavaScript project, inherently using Node for Grunt to manage build tasks and Bower to manage script dependencies, with the option of Vagrant.
# .gems gem export file.
compass
#!/usr/bin/env bash
# Used by Vagrant to provision the virtual machine
function msg {
echo -e "\033[0m\033[1m\033[44m\033[97m>>> $@ \033[0m"
}
function err {
echo -e "\033[0m\033[1m\033[41m\033[97m>>> $@ \033[0m"
}
msg "Running bootstrap script with with the following options: $@"
if [ "$1" = "vagrant" ]; then
INIT="vagrant"
shift
fi
# if last line is `mesg n`, replace with conditional
if [ "`sudo tail -n 1 /root/.profile`" = "mesg n" ]; then
msg 'Patching basebox to prevent future `stdin: is not a tty` errors...'
sudo sed -i '$d' /root/.profile
sudo cat << 'EOH' >> /root/.profile
# "stdin: is not a tty"
if `tty -s`; then
mesg n
fi
EOH
fi
# http://www.thomas-krenn.com/en/wiki/Perl_warning_Setting_locale_failed_in_Debian
if [ "`head -n 1 /vagrant/.env-facility`" != "vagrant" ]; then
# only do this on first run; takes forever!
export LANGUAGE=en_US.UTF-8
export LANG=en_US.UTF-8
export LC_ALL=en_US.UTF-8
locale-gen en_US.UTF-8
dpkg-reconfigure locales
fi
msg 'Updating all Apt repositories'
apt-get update
if [ "$1" = "git" ]; then
msg 'Installing Git'
apt-get install -y git
shift
fi
if [ "$1" = "curl" ]; then
msg 'Installing cURL'
apt-get install -y curl
shift
fi
if [ "$1" = "node" ]; then
msg 'Adding software PPA repository for Node to Apt'
apt-get install -y python-software-properties
add-apt-repository ppa:chris-lea/node.js
apt-get update
msg 'Installing Node'
apt-get install -y nodejs
msg 'Installing Grunt and Bower'
npm install -g grunt-cli bower
shift
fi
if [ "$1" = "phantomjs" ]; then
msg 'Installing PhantomJS'
apt-get install -y phantomjs
shift
fi
if [ "$1" = "rvm" ]; then
msg 'Installing RVM'
curl -L https://get.rvm.io | bash -s stable
# the rvm script creates an rvm group the vagrant user needs to belong to
sudo usermod -a -G rvm vagrant
# trust the .rvmrc project file & ignore .rvmrc warnings
su -l vagrant -c "source /usr/local/rvm/scripts/rvm; rvm rvmrc trust /vagrant/.rvmrc; rvm rvmrc warning ignore all.rvmrcs"
shift
fi
if [ "$1" = "init" ]; then
# run project initialization scripts
su -l vagrant -c "/vagrant/init.sh $INIT"
fi
source 'https://rubygems.org'
gem 'compass'
#!/usr/bin/env bash
# Project initialization script
function msg {
echo -e "\033[0m\033[1m\033[44m\033[97m>>> $@ \033[0m"
}
function err {
echo -e "\033[0m\033[1m\033[41m\033[97mERR: $@ \033[0m"
}
function import_gems {
if [ "$1" = "rvm" ]; then
msg 'Importing gems listed in .gems file into RVM gemset'
rvm gemset import
else
# check for bundler
command -v bundle >/dev/null 2>&1 && { BUNDLER=true; }
# install bundler
if [ -z $BUNDLER ]; then
echo 'Tried using Bundler to install Ruby gems, but could not locate it.'
read -p "Would you like to install Bundler now? [y/N] " -r
if [[ $REPLY =~ ^[Yy]$ ]]; then
# install bundler
sudo gem install bundler
# test the bundle command
command -v bundle >/dev/null 2>&1 || { err 'Bundler installation unsuccessful, please refer to README. Aborting.' >&2; exit 1; }
BUNDLER=true
fi
fi
# install gems using bundler if installed
if [ $BUNDLER ]; then
msg 'Installing gems using Bundler'
bundle install
fi
fi
}
function envlog {
# inform script(s) of chosen environment
if [ "$1" = "vagrant" ]; then
ENVFILE="/vagrant/.env-facility"
RUNFILE="/vagrant/.env-runcount"
else
ENVFILE=".env-facility"
RUNFILE=".env-runcount"
fi
if [ ! -f $ENVFILE ] || [ "`head -n 1 $ENVFILE`" != "$1" ]; then
# if first line != env chosen, [re]write envfile
echo "$1" > $ENVFILE
# increment runcount by 1
RUNCOUNT=1
else
# first line matches env chosen, just increment count
RUNCOUNT=$(head -n 1 "$RUNFILE")
if [[ $RUNCOUNT != *[!0-9]* ]]; then
# if last line of envfile is an int, increment runcount by 1
RUNCOUNT=$(( $RUNCOUNT + 1 ))
else
# last line of envfile is NOT an int, [re]set runcount to 1
RUNCOUNT=1
fi
fi
# write runcount to runfile
echo $RUNCOUNT > $RUNFILE
}
if [ "$1" = "vagrant" ]; then
msg 'Running project initialization script for Vagrant'
# log chosen env and increment run count
envlog vagrant
source /usr/local/rvm/scripts/rvm
# upon cd of vagrant directory, rvm will install ruby
cd /vagrant
# install gems
import_gems rvm
else
msg 'Running project initialization script'
# log chosen env and increment run count
envlog local
# check for node
command -v npm >/dev/null 2>&1 || { err 'Node (>=0.8.0) is required but not installed. Aborting.' >&2; exit 1; }
# check for a ruby version manager
command -v rvm >/dev/null 2>&1 && { RVM=true; }
command -v rbenv >/dev/null 2>&1 && { RBENV=true; }
# install a ruby version manager if one isn't found
if [[ -z $RVM && -z $RBENV ]]; then
# rbenv and rvm are missing
echo 'A Ruby version manager is suggested, ideally RVM (>=1.22.0) or rbenv (>=0.4.0).'
read -p "Would you like to install RVM now? [y/N] " -r
if [[ $REPLY =~ ^[Yy]$ ]]; then
msg 'Installing RVM'
curl -L https://get.rvm.io | bash -s stable
# reload the shell configuration
source ~/.bash_profile
# test the rvm command
command -v rvm >/dev/null 2>&1 || { err 'RVM installation unsuccessful, please install RVM manually. Aborting.' >&2; exit 1; }
# trust the .rvmrc project file
rvm rvmrc trust .rvmrc
msg 'Installing Ruby'
rvm install ruby-$(head -n 1 .ruby-version)
RVM=true
fi
fi
# install ruby gems
if [ $RVM ]; then
# rvm exists, make sure we have the latest stable
rvm get stable
# install gems
import_gems rvm
else
# if ruby is installed, try installing gems using bundler
command -v ruby >/dev/null 2>&1 && { import_gems; }
fi
# ensure bower & grunt are globally installed (and install if they aren't)
command -v bower >/dev/null 2>&1 && { msg 'Ensuring latest Bower'; sudo npm update -g bower; } || { msg 'Trying to install Bower'; sudo npm install -g bower; }
command -v grunt >/dev/null 2>&1 && { msg 'Ensuring latest Grunt'; sudo npm update -g grunt-cli; } || { msg 'Trying to install Grunt'; sudo npm install -g grunt-cli; }
fi
# install npm and bower packages
msg 'Performing local NPM and Bower package install'
npm install
bower install
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# All Vagrant configuration is done here. The most common configuration
# options are documented and commented below. For a complete reference,
# please see the online documentation at vagrantup.com.
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "precise32"
# The url from where the 'config.vm.box' box will be fetched if it
# doesn't already exist on the user's system.
config.vm.box_url = "http://files.vagrantup.com/precise32.box"
# Create a forwarded port mapping which allows access to a specific port
# within the machine from a port on the host machine. In the example below,
# accessing "localhost:8080" will access port 80 on the guest machine.
config.vm.network :forwarded_port, guest: 9000, host: 9000
# Create a private network, which allows host-only access to the machine
# using a specific IP.
# config.vm.network :private_network, ip: "192.168.33.10"
# Create a public network, which generally matched to bridged network.
# Bridged networks make the machine appear as another physical device on
# your network.
# config.vm.network :public_network
# If true, then any SSH connections made will enable agent forwarding.
# Default value: false
# config.ssh.forward_agent = true
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
# config.vm.synced_folder "../data", "/vagrant_data"
# Provider-specific configuration so you can fine-tune various
# backing providers for Vagrant. These expose provider-specific options.
# Example for VirtualBox:
#
# config.vm.provider :virtualbox do |vb|
# # Don't boot with headless mode
# vb.gui = true
#
# # Use VBoxManage to customize the VM. For example to change memory:
# vb.customize ["modifyvm", :id, "--memory", "1024"]
# end
#
# View the documentation for the provider you're using for more
# information on available options.
# Enable provisioning with Puppet stand alone. Puppet manifests
# are contained in a directory path relative to this Vagrantfile.
# You will need to create the manifests directory and a manifest in
# the file base.pp in the manifests_path directory.
#
# An example Puppet manifest to provision the message of the day:
#
# # group { "puppet":
# # ensure => "present",
# # }
# #
# # File { owner => 0, group => 0, mode => 0644 }
# #
# # file { '/etc/motd':
# # content => "Welcome to your Vagrant-built virtual machine!
# # Managed by Puppet.\n"
# # }
#
# config.vm.provision :puppet do |puppet|
# puppet.manifests_path = "manifests"
# puppet.manifest_file = "site.pp"
# end
# Enable provisioning with chef solo, specifying a cookbooks path, roles
# path, and data_bags path (all relative to this Vagrantfile), and adding
# some recipes and/or roles.
#
# config.vm.provision :chef_solo do |chef|
# chef.cookbooks_path = "../my-recipes/cookbooks"
# chef.roles_path = "../my-recipes/roles"
# chef.data_bags_path = "../my-recipes/data_bags"
# chef.add_recipe "mysql"
# chef.add_role "web"
#
# # You may also specify custom JSON attributes:
# chef.json = { :mysql_password => "foo" }
# end
# Enable provisioning with chef server, specifying the chef server URL,
# and the path to the validation key (relative to this Vagrantfile).
#
# The Opscode Platform uses HTTPS. Substitute your organization for
# ORGNAME in the URL and validation key.
#
# If you have your own Chef Server, use the appropriate URL, which may be
# HTTP instead of HTTPS depending on your configuration. Also change the
# validation key to validation.pem.
#
# config.vm.provision :chef_client do |chef|
# chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
# chef.validation_key_path = "ORGNAME-validator.pem"
# end
#
# If you're using the Opscode platform, your validator client is
# ORGNAME-validator, replacing ORGNAME with your organization name.
#
# If you have your own Chef Server, the default validation client name is
# chef-validator, unless you changed the configuration.
#
# chef.validation_client_name = "ORGNAME-validator"
# Enable provisioning with shell, useful when a full configuration
# management system such as Chef or Puppet is not necessary.
#
# $script = <<SCRIPT
# echo I am provisioning...
# date > vagrant_provisioned_at
# SCRIPT
#
# config.vm.provision :shell do |s|
# s.inline = $script
# s.args = "'arg1, arg2'"
# s.path = "bootstrap.sh"
# end
config.vm.provision :shell, :path => "bootstrap.sh", :args => "vagrant git curl node phantomjs rvm init"
end
@digitaljhelms
Copy link
Author

TODO: work this into a reusable Yeoman generator

@digitaljhelms
Copy link
Author

Run rvm --create use ruby-2.0.0@gemset --rvmrc to generate the .rvmrc file.

@digitaljhelms
Copy link
Author

Prerequisites for local install:

  • RVM
  • None

Simply run ./init.sh to bootstrap your local environment.

Prerequisites for Vagrant install:

  • VirtualBox
  • Vagrant

As usual, run vagrant up to build and provision the Vagrant box; uses the Ubuntu precise 32 VirtualBox.

@digitaljhelms
Copy link
Author

RVM is no longer a prerequisite. If it is not installed, the initialization script will attempt to install it [upon request]. If it is not installed (or the option to install is declined) the script will attempt to install Bundler and use it (and the Gemfile) to install required gems.

The .ruby-version and .ruby-gemset files are compatible with RVM and other Ruby version managers, and are referenced by the .rvmrc file for cross-compatibility.

Instructions remain the same, place these files in your project directory and run ./init.sh for a local install or vagrant up to use Vagrant.

Optionally, change the Ruby version number in the .ruby-version file to a version more amicable to the project.

The arguments specified in Vagrantfile to the bootstrap.sh script can be adjusted for testing/troubleshooting, but should always be in the order shown (with exception of being absent entirely):

  • vagrant tells the project initialization script that a Vagrant install is being performed; aka, don't do anything that the Vagrant bootstrap has already done (install Node, Bower, Grunt, RVM, etc).
  • node is used only by the Vagrant bootstrap and instructs the provisioner to install Node.
  • rvm is used only by the Vagrant bootstrap and instructs the provisioner to install RVM.
  • init is used only by the Vagrant bootstrap and instructs the provisioner to run the project initialization script after provisioning completes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment