The founders of GitHub all had deep ties and contributions to the Ruby programming language, so we cover it more than other languages in this book.
In recent years, NodeJS (JavaScript for the server side) has grown in popularity, and JavaScript has always been an interesting language because it works on both the client side and server side. GitHub has offered several popular open source projects written in NodeJS.
For these reasons, this appendix gives a little more detail on using these two languages.
In addition, some fluency with the shell is beneficial. There are many GUI programs that hide the command line from you, but to truly dive deep into the GitHub API, it is worthwhile to use the command line inside a shell. These examples all work with bash (the Bourne Again Shell), but are careful not to use any advanced features of bash (so they should convert to other shells if you strongly favor another shell).
When the history of GitHub is documented, the Ruby language will take its place as a major character. Tom Preston Warner (one of the three founders of GitHub) built the initial libraries for using Git with Ruby, a library called Grit. You can host blogs on GitHub for free, and this tool called Jekyll is built using Ruby. Gollum, the technology that powers GitHub wikis, is built using Grit and runs on Ruby.
To understand GitHub, it is best to understand a little bit of Ruby. You can use many of the tools used at GitHub by simply installing Ruby, and not knowing any Ruby syntax. This book will not require you to become an expert in Ruby, but will ask you to read through Ruby code. We write in a literal, readable way, so that anyone with basic software developer skills and mastery of the English language should be able to understand the tools we are using. Ruby is not a perfect language, but is a useful addition to a developer’s toolkit because of its focus on developer productivity.
There are many ways to get Ruby but not all of them are created equal. As a long-time user I have experienced the pain of using a preinstalled Ruby or one from a package manager, and generally these installation methods provide a suboptimal experience. If you are not familiar with Ruby, use this appendix to get through installation with the least friction and trouble.
You might already have a version of Ruby installed. Mac OS X comes bundled with Ruby and various flavors of Linux do as well (or provide a quick and easy installation through the built-in package manager like "apt-get"). However, I recommend that you use the method of installation described here rather than using the stock installed version of Ruby you might already have on your system. Often Ruby packages require a specific version of Ruby, though they may work with other versions. The problem is that you might encounter subtle bugs that have never been seen before, and using the methods described here will make it trivial to install any version of Ruby that you need side by side with any other version. You can guarantee you are using the correct version, and the method described here will not interfere with any other previously installed version of Ruby you already have on your system.
To install Ruby, use RVM. RVM stands for Ruby Version Manager. RVM allows you to install multiple versions of Ruby on your machine and have them interoperate without conflict. You will probably only need to install a single version of Ruby to use the examples in the book. And RVM makes it so that if you choose to install another version, you will not have to reconfigure any applications that relied on the other versions installed.
Installation of Ruby using RVM depends on your operating system. If you are using Mac OS X or Linux, your installation will probably be as simple as running these commands from a shell:
$ \curl -sSL https://get.rvm.io | bash -s stable
This will install RVM and Ruby.
If you are running Windows, you can use RVM to install Ruby, but your instructions are a little more complicated. Refer to the documentation to do so. A better option is to consider installing something like VirtualBox (a virtual machine manager). If you do this, you can install RVM inside a Linux Virtual Machine (VM). Windows is, sadly, a second-class citizen with Ruby and RVM and, for this reason, it is often better to install RVM inside a host system like Linux, which has a wider community around it to support you. VirtualBox and Linux are free as in beer and as in speech, so you can try them out without cost (other than your time). There are many native gems for Ruby that don’t properly compile if the host system is Windows, so you can save yourself considerable time by just using a completely free (as in beer) option like VirtualBox and a Linux virtual machine running on Windows instead of fighting with running everything directly on Windows.
Here are a few tips when using Ruby and RVM:
- Gemfile
-
Ruby packages libraries in a format called a gem. A gemfile is a manifest that describes which gems your application needs. Gemfiles make it simple to install all the required libraries: run the
bundle
command from a shell prompt and all libraries will be installed, which can include downloading from the network and building from source if compilation is required. - .ruby-version or .rvmrc
-
These two files tell your application (or shell) which version of Ruby to use. Often applications will include this file as a part of their package. If you use RVM, it will either switch to that version of Ruby or prompt you to install that version. Imagine that you have an application that only runs on Ruby 2.1.3. You can create a file called .ruby-version, which contains the string
ruby-2.1.3
and when your application starts, it will automatically use that version of Ruby. There are other Ruby-based tools (like the zero-configuration web server Pow) that are aware of files like .ruby-version and will properly use the correct version of Ruby if they see this file. - config.ru
-
This is a file used to run Ruby applications using Rack. Rack is a web server interface, compatible with many application servers. If you see a config.ru file, you can run this application with many different servers. These can be powerful frontends used in production on many large sites on the Internet, or they can be minimal servers used just on a single laptop; Rack makes it easy to set up a server.
- Missing system tools
-
If you are running Mac OS X, you need to install Xcode and the command-line tools. If you are a software developer, you probably have these already installed. If not, review online documentation to install these. If you are running Linux, you might not have installed the compiler chain; you can install all the build tools you will ever need using this command:
sudo apt-get install build-essential
. This can take a while, but will ensure you have all the tools necessary for building RVM and any binary gems. - Missing developer libraries
-
There are some libraries that support Ruby (readline support, as an example, which allows you to use command-line history inside of an interactive Ruby shell) that are not always installed or available to the RVM tool. RVM has greatly improved in detecting the correct libraries, and there are often notes that tell you how to properly configure these libraries. Make sure to read the output printed to the screen as you install Ruby using RVM for special instructions specific to your platform.
NodeJS is the server-side version of JavaScript. JavaScript is the only ubiquitious client-side programming language for the Web. Between Ruby and JavaScript, you can build any web application you need. Tools like Hubot show the benefits of using a language like JavaScript running on the NodeJS platform, which facilitates building "fast, scalable networked applications."
The nodejs.org web page offers various binary installers. These are generally the best way to install the most recent version of NodeJS.
NVM stands for "Node Version Manager" and is a direct correlate to RVM. Like RVM, NVM allows you to install multiple versions of NodeJS on a single machine and switch between them seamlessly. This can be very useful when using a tool like NodeJS that is iterating rapidly (and whose modules are also often tested against only a very new version of NodeJS). NVM runs on OS X or Linux. To install, run these commands from a shell prompt:
$ curl -o- \
https://raw.githubusercontent.com/creationix/nvm/v0.25.3/install.sh | \
bash
This will install NVM for you. You then might need to run source
~/.bash_profile
to load the NVM scripts. Once this is completed, you
are able to run NVM commands:
$ nvm install 0.10 # Install version 0.10
$ nvm use 0.10 # Use version 0.10
There are many more commands available with NVM, all of which can be found at the repository where the tool is hosted.
Much like Ruby has a Gemfile that indicates required libraries, so
too does NodeJS have an equivalent file. In NodeJS, this file is
called package.json. To install all required libraries for any
project, use the npm
tool (installed by default when you install
NodeJS using NVM). Running npm
without any arguments will
install all libraries specified by the application if there is a
package.json file included with the project. If you want to add a
package to an existing package.json file, you can append --save
to
the npm command and npm will update package.json for you once the
installation of the package has completed.
Though most chapters have focused on a specific programming language (aside from [introduction]), all of the chapters contain command-line invocations. There are a few intricacies when using the shell you might not be familiar with that we will explain here, with an actual example of each.
If you type a hash character (#) into a shell command, the rest of the line is considered a comment. This makes it easy to document commands on the same line:
$ cat file.txt # This prints out the file "file.txt"
This command ends after the file.txt
string. We use this often
throughout the appendix to document shell commands.
When a process runs in the shell, it runs within an environment, and
this environment can be configured with key/value pairs. These are called
environment variables. A common reason for this is that you can write
a program that reads passwords from the environment variables and
then specify them at runtime rather than in the source code. You
specify environment variables either as key/value pairs joined by an
equal sign in front of a command, or by using the export
command to
persist them across commands:
$ PASSWORD=MyPwd123 myProgram # myProgram retrieves the variable PASSWORD
$ export PASSWORD=MyPwd123
$ myProgram # PASSWORD is now a persisted key value
The shell invokes commands when you hit the Enter key. But there are times when you want to break a command into multiple lines for readability. In this case, break each line up using the backslash character:
$ git log -S http
...
$ git \
log \
-S \
http
...
Though not the most compelling command to break into multiple lines, this example shows two commands that do exactly the same thing.
Shell commands were written long ago in an era when programs fulfilled upon a small set of functionality, in stark contrast to today’s monolithic GUI programs. Each program generally did a few simple things and then passed information to another program for further processing. Programs then needed an elegant way to pass data between each other, and the pipe was born. Pipes facilitate communication between processes: one command’s output becomes another command’s input.
$ cat /etc/mime.types | grep http
application/http
application/vnd.httphone
application/x-httpd-eruby rhtml
application/x-httpd-php
phtml pht php
application/x-httpd-php-source phps
This invocation uses the cat program to output the file /etc/mime.types, and then passes this information to the grep program, which looks inside the input to find all lines that contain the string http.
Similar to the pipe, shells support redirecting output to files using
the >
and >>
characters. >
will overwrite an existing file (or
create a new file if it does not exist) while the double >>
string
will append to a file:
$ cat /etc/mime.types | grep http > saved-output.txt
After running this command, the file saved-output.txt will contain the same text as was produced in the prior example for the pipe. The file will be overwritten if it existed already.