Jekyll2018-05-15T03:47:57+00:00/Andrew Amesburysoftware engineer, agilist, photographer, traveller and recovering caffeine addictPort 22 is blocked, how can I push to Git with SSH?2018-05-15T01:00:00+00:002018-05-15T01:00:00+00:00/git/github/2018/05/15/port22-blocked-github<h1 id="problem">Problem</h1>
<p>You know the drill, you’re working on a network and you push/pull from git.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push -u origin master
ssh: connect to host github.com port 22: Operation timed out
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
</code></pre></div></div>
<p>You see the dreaded timeout and realise…</p>
<blockquote>
<p>They’ve blocked port 22?</p>
</blockquote>
<p>Fear not.</p>
<h1 id="solution">Solution</h1>
<p>Use port 443 instead. <em>for ssh?</em> Yes!</p>
<p>edit <code class="highlighter-rouge">~/.ssh/config</code> and append the following</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Host github.com
Hostname ssh.github.com
Port 443
</code></pre></div></div>
<p>Save, exit and retry.</p>
<p>If port 443 is blocked. Fetch coffee.</p>ProblemLearning Golang: godep unable to find srcroot2018-01-23T01:00:00+00:002018-01-23T01:00:00+00:00/golang/dependency/management/godep/2018/01/23/golang-gopath-setup<h1 id="introduction">Introduction</h1>
<p>I consider myself to be a polyglot - I enjoy learning new programming languages and I’ve recently decided to teach myself some <a href="https://golang.org">go</a> for a project where dependencies cannot be fetched from a remote artefact repository (the ‘ship one binary’ feature of Go is really useful).</p>
<p>If you’re interested in reading more about Go dependency management, <a href="https://coreos.com/blog/godep-for-end-user-go-projects.html">CoreOS</a> has some interesting reading.</p>
<h1 id="problem">Problem</h1>
<ul>
<li>You’ve decided that it’s time to get some dependency management in place for your go projects.</li>
<li>You’ve selected the popular <a href="https://github.com/tools/godep">godep</a> tool.</li>
<li>You navigate to your chosen project folder and…</li>
<li>Error: <code class="highlighter-rouge">godep unable to find srcroot</code></li>
</ul>
<h1 id="solution">Solution</h1>
<p>Filesystem location matters a lot in Go. You’re expected to be running things from a designated ‘gopath’, but don’t confuse <em>gopath</em> with the location of <code class="highlighter-rouge">go</code> (don’t just set it to where go is installed).</p>
<p>Your <em>gopath</em> should be a location that you’re happy to put your go source code for the foreseeable future. I’ve set mine to <code class="highlighter-rouge">/Users/andrew/go</code>.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cat <<END >> ~/.bashrc
export GOPATH=/Users/andrew/go
END
</code></pre></div></div>
<p>This works for <em>zsh</em> also, simply change the filename as appropriate (to <code class="highlighter-rouge">~/.zshrc</code>). Simply <code class="highlighter-rouge">source ~/.zshrc</code> or <code class="highlighter-rouge">source ~/.bashrc</code> to update your current terminal.</p>
<p>You can check this worked using <code class="highlighter-rouge">echo $GOPATH</code>.</p>
<h1 id="where-to-put-your-projects">Where to put your projects</h1>
<p>Using GOPATH as the root directory, you can now put your source code in:
<code class="highlighter-rouge">$GOPATH/src/<project name here></code>.</p>
<h1 id="now-save-your-dependencies">Now save your dependencies</h1>
<ul>
<li>Navigate to <code class="highlighter-rouge">$GOPATH/src/<your project></code> (where your <code class="highlighter-rouge">*.go</code> files are)</li>
<li>Run <code class="highlighter-rouge">godep save</code></li>
</ul>
<p>Now, when you check what’s in the directory below, you should see the following <code class="highlighter-rouge">Godeps</code> structure.</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ tree
.
├── Godeps
│ ├── Godeps.json
│ └── Readme
...
</code></pre></div></div>
<p>Don’t edit the generated files yourself, it’s normally a bad idea.</p>Introduction I consider myself to be a polyglot - I enjoy learning new programming languages and I’ve recently decided to teach myself some go for a project where dependencies cannot be fetched from a remote artefact repository (the ‘ship one binary’ feature of Go is really useful).Docker proxy config for centos 7 (or any systemd based distro)2017-11-29T08:00:00+00:002017-11-29T08:00:00+00:00/docker/container/proxy/configuration/dockerhub/hub/pull/systemd/centos/centos7/2017/11/29/docker-behind-proxy<h1 id="problem">Problem</h1>
<p>You’re running behind a corporate proxy server and you need docker to be able to pull images on CentOS 7 (or any other systemd based distro).</p>
<p>Setting the environment variable <code class="highlighter-rouge">http_proxy</code> or <code class="highlighter-rouge">https_proxy</code> isn’t working.</p>
<h1 id="solution-for-systemd-based-linux-distributions">Solution for systemd based Linux distributions</h1>
<p>CentOS changed their init system to <code class="highlighter-rouge">systemd</code> in version 7 and that means to solve this problem you need to make a new file at:
<code class="highlighter-rouge">/etc/systemd/system/docker.service.d/http-proxy.conf</code></p>
<p>The contents should contain your proxy server details. Here’s mine:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[Service]
Environment="HTTP_PROXY=http://127.0.0.1:8000/"
Environment="HTTPS_PROXY=https://127.0.0.1:8000/"
</code></pre></div></div>
<h1 id="more">More</h1>
<p>Full docs from Docker are currently available at <a href="https://docs.docker.com/engine/admin/systemd/">https://docs.docker.com/engine/admin/systemd/</a></p>Problem You’re running behind a corporate proxy server and you need docker to be able to pull images on CentOS 7 (or any other systemd based distro).Huge files are eating my disk, where are they?2017-11-27T08:00:00+00:002017-11-27T08:00:00+00:00/du/disk/software/file/size/2017/11/27/find-huge-files<h1 id="problem">Problem</h1>
<p>Recently I have had some concerns about the amount of disk being used by my macbook pro; at times it’ll range from 40Gb total disk used to 100Gb total disk used.</p>
<p>I’m not keen on investing in a proprietary tool to do something fairly straightforward, so I decided to use a built-in function: <code class="highlighter-rouge">du</code>.</p>
<h1 id="finding-all-large-files-for-a-given-directory">Finding all large files for a given directory</h1>
<p>This solution uses <code class="highlighter-rouge">du</code>, a disk usage utility packaged with macos.</p>
<p>Example for finding all files greater than 1G: <code class="highlighter-rouge">du -h ~/ | grep 'G '</code></p>
<p>If the above command doesn’t limit your results to only files greater than 1G and instead gives all results with G in the file path, simply change the amount of space after G (it could be variable depending on your OS).</p>
<h1 id="find-all-files-in-a-tree-structure-greater-than-a-certain-size">Find all files in a tree structure greater than a certain size</h1>
<p>You can also use <code class="highlighter-rouge">tree</code> (on macos just <code class="highlighter-rouge">brew install tree</code>), with a <code class="highlighter-rouge">-h</code> flag to show file sizes in a tree structure.</p>
<p>Example for finding all files greater than 1G: <code class="highlighter-rouge">tree -h | grep G]</code></p>
<h1 id="more">More</h1>
<p>Need to find smaller files? Use B, K or M instead of G.</p>
<p>Tip: <code class="highlighter-rouge">-h</code> also works for <code class="highlighter-rouge">ls</code>. For example, try: <code class="highlighter-rouge">ls -Shl</code> (<code class="highlighter-rouge">-S</code> provides order of largest at top).</p>
<p>These methods will work for linux too, but you’ll need to use your own package manager to get tree.</p>
<h1 id="finally">Finally</h1>
<p>If you were curious, here’s what was taking up so much of my disk…</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ / tree -h | grep G]
│ │ │ │ │ ├── [ 64G] Docker.raw
</code></pre></div></div>
<p>I then found its location using <code class="highlighter-rouge">find</code>:</p>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ / sudo find / -name Docker.raw -print
/Users/andrew/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/Docker.raw
</code></pre></div></div>
<p>Unfortunately this is a known problem: <a href="https://github.com/docker/for-mac/issues/371">https://github.com/docker/for-mac/issues/371</a></p>ProblemFixing the Apple pay wallet infinite loop2017-11-16T22:00:00+00:002017-11-16T22:00:00+00:00/apple/mac/software/wallet/applepay/2017/11/16/ApplePay-Reset-Mac<h1 id="problem">Problem</h1>
<p>You restored from your time machine backup and your apple pay needs to reset.</p>
<p>But it can’t! As a result, you end up in an infinite loop of requests for elevated permissions.</p>
<blockquote>
<p>Apple Pay is already configured on this disk for another Mac.</p>
</blockquote>
<h1 id="solution">Solution</h1>
<p>The solution (from Apple) after several levels of elevation to senior engineers is reported to be:</p>
<blockquote>
<p>reinstall osx and <em>don’t</em> use a time machine backup</p>
</blockquote>
<p>Unfortunately I just don’t have the time or inclination to do that, particularly when Time Machine exists to prevent that necessity!</p>
<p>Here’s how to reset your apple pay on your Mac. I’m running High Sierra, it should work for Sierra too.</p>
<p>The commands below do the following:</p>
<ol>
<li>Change to the private database directory.</li>
<li>Move the applepay folder into another folder (you could move it back later, that way).</li>
<li>Kill the seld (secure enclave) daemon process.</li>
<li>Kill the nfc daemon that apple pay uses.</li>
</ol>
<div class="highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd /private/var/db
sudo mv -i applepay applepay.old
sudo pkill seld
sudo pkill nfcd
</code></pre></div></div>
<p>No restart needed, go back to System preferences -> Wallet and you should be able to set it up now.</p>Problem You restored from your time machine backup and your apple pay needs to reset.Personal conflict in agile teams - a fictional story2017-10-19T08:00:00+00:002017-10-19T08:00:00+00:00/agile/development/teams/leadership/2017/10/19/personal_conflict<h1 id="introduction">Introduction</h1>
<p>Sometimes people just don’t get along. At the heart of agile practice is building teams that trust each other and feel safe enough to share openly, so when things go wrong it can be devastating if not controlled quickly.</p>
<h1 id="what-kinds-of-conflict-might-exist">What kinds of conflict might exist?</h1>
<p>Development teams are made of snowflakes - unique personalities with different world views and experience. Each and every person has their own point of view, but generally conflict falls into only a few categories:</p>
<ul>
<li>Sexual harassment</li>
<li>Technical (“I want things my way”)</li>
<li>Difference in values</li>
<li>Respect (lack thereof)</li>
<li>Personal or behavioral</li>
</ul>
<p>In this post we’re going to specifically focus on <strong>personal</strong> issues. When certain behaviors trigger an emotional response in another party and it leads to conflict, but it is not specifically a HR issue yet.</p>
<h1 id="how-might-it-manifest">How might it manifest?</h1>
<p>The following is an example based on real events but with fictional characters instead of real people.</p>
<p>Frank and Jenny are used to working together; they’re both new to agile but Jenny used to report to Frank when they had a hierarchical structure in place. Now, with an agile team structure in place they’re both trying to learn new skills.</p>
<p>Jenny sees that she has a lot to learn in addition to her high workload and begins taking things into her own hands, she begins arranging meetings to learn from co-workers.</p>
<p>Frank is unsure where to start, he wants someone to coach him but the team is under pressure to deliver. He sits back and waits for a few weeks, he has time to spare. When he hears that Jenny is arranging meetings without inviting him along he gets upset, he attends even though he’s not invited.</p>
<p>Jenny doesn’t understand why Frank is so upset, he could have arranged his own. Frank is upset that Jenny is doing things as he feels he out ranks Jenny. The situation escalates; Jenny tries to avoid Frank and Frank ignores Jenny when he next sees her.</p>
<p>Neither of them are happy with things now.</p>
<p>Frank tries to rally support for his cause by stirring up water cooler conversation with colleagues. They’re not interested in participating so he psychs himself up and goes to Jenny: “Can we go and talk. Right now.”</p>
<p>Jenny feels threatened, she doesn’t want to talk when Frank is visibly angry.</p>
<p>Some facts:</p>
<ul>
<li>Jenny doesn’t like the way Frank speaks to her</li>
<li>Frank thinks of Jenny as a subordinate</li>
<li>Frank believes he could make things very hard for Jenny; he could refuse to work with her</li>
</ul>
<h1 id="when-people-refuse-to-work-together">When people refuse to work together</h1>
<p>This is the <em>easy way out</em>; they’re cutting each other off essentially. You may have heard of the saying:</p>
<blockquote>
<p>an eye for an eye leaves everyone blind</p>
</blockquote>
<p>If we all refused to cooperate then nobody would benefit from the experience of others. Worse still, the person who joins another team (if it’s even possible) is joining with baggage that everyone now knows.</p>
<p>Here are my suggestions for repairing frayed relationships in the workplace:</p>
<ul>
<li>Investigate the root cause.</li>
<li>Understand the intent of both parties. Is one or both parties acting out of malice?</li>
<li>Identify common ground; what do they both want?</li>
</ul>
<h1 id="reset">Reset</h1>
<p>This is the time to revisit the foundation that the team is built upon. Create the clean sheet that’s required for both parties to feel safe.</p>
<p>First we need to let both parties be heard. Normally, if communication breakdown reaches this point - face to face interaction is too hard (read: emotionally driven) at this point so I’d suggest individual mediation in the first instance whereby the facilitator meets with both parties independently to hear their thoughts and share some third-party perspective.</p>
<p>If that isn’t enough to make both parties want to repair the relationship, have each person write down briefly how they feel and why they feel that way on a post-it note to be exchanged with the other party. The post-it note format is deliberately to keep things concise and to make sure they don’t cloud the situation with emotive language.</p>
<p>Once you’ve established a common understanding and agreement to move forward there’s an opportunity to rebuild that relationship.</p>
<h1 id="rebuild">Rebuild</h1>
<p>Go back to basics, here’s a list of places you might begin:</p>
<ol>
<li>Does the team have a working agreement? If so, now is a great time to revisit it.</li>
<li>This is an <strong>opportunity</strong> to learn; how can the team communicate more effectively in future?</li>
<li>Does everyone understand agile depends on a flat structure?</li>
<li>We all need to be T-shaped; experts and managers don’t fit well in agile teams.</li>
<li>Retrospectives matter - it’s the right place to share.</li>
</ol>
<p>The main thing you need to understand is: How will Frank and Jenny solve their issues in future?</p>
<h1 id="refocus">Refocus</h1>
<p>The team has a common purpose. Make clear that both parties are essential to delivering that result and that working together will make the team more successful.</p>
<h1 id="moving-forward">Moving forward</h1>
<p>Frank and Jenny will be ok - as long as they’re prepared to take this process seriously and they both want to resolve these issues.</p>
<h1 id="summary">Summary</h1>
<ul>
<li>Identify the type of conflict</li>
<li>Listen and hear them out; remain unbiased</li>
<li>Reset - clear the air</li>
<li>Rebuild - provide the tools to deal with conflict</li>
<li>Refocus - close the conflict by focusing on the team’s future</li>
<li>Move forward and keep observing the situation</li>
</ul>Introduction Sometimes people just don’t get along. At the heart of agile practice is building teams that trust each other and feel safe enough to share openly, so when things go wrong it can be devastating if not controlled quickly.Infinitest: You should be using it2017-09-30T08:00:00+00:002017-09-30T08:00:00+00:00/software/engineering/development/testing/unit/infinitest/ncrunch/2017/09/30/infinitest<h1 id="what-is-infinitest">What is infinitest?</h1>
<p><a href="https://infinitest.github.io/">Infinitest</a> is a tool that continually runs your unit tests in the background. No more waiting for CI. No more forgetting to run the unit tests before checking in. No more excuses!</p>
<h1 id="why">Why?</h1>
<p>Save time!</p>
<p>Waiting for CI to tell you about a problem is too late; by the time you’ve committed the code to a branch, maybe you have a PR underway and moved on to some other task.</p>
<h1 id="is-this-the-answer-to-everything">Is this the answer to everything?</h1>
<p>No.</p>
<p>You’re never going to want your integration tests (such as Spring Boot Test) to run in the background, but having your quick, concurrent unit tests telling you if you’re breaking your test code is really valuable.</p>
<h1 id="what-about-net">What about .NET?</h1>
<p>See: <a href="www.ncrunch.net">NCrunch</a></p>
<p>Let me know what you think.</p>What is infinitest? Infinitest is a tool that continually runs your unit tests in the background. No more waiting for CI. No more forgetting to run the unit tests before checking in. No more excuses!Developing your agile test strategy2017-08-25T08:00:00+00:002017-08-25T08:00:00+00:00/agile/software/development/engineering/testing/2017/08/25/agile-test-strategy<blockquote>
<p>Agile testing doesn’t need a test strategy, does it?</p>
</blockquote>
<h1 id="why-should-you">Why should you?</h1>
<p>Let’s be clear, you probably don’t need a dogmatic 300 page document describing every facet of testing for the organisation, but it is useful to have a document for reference and to enable shared understanding.</p>
<p>The alternative to documenting team goals and processes (how we work) is to have an informal policy that the team shares; however, this relies upon the team collectively governing the policy and accurately sharing the information when group members change. In my experience, informal policy also makes it increasingly hard to bring new team members up to speed.</p>
<p>Imagine joining a team and being told:</p>
<blockquote>
<p>“We have some things we do, but they’re not written anywhere… Please remember them.”</p>
</blockquote>
<p>Not an ideal start – now you have an obligation to remember and to comply with an informal policy that you can’t refer to. That doesn’t sound like a sound engineering practice, does it?</p>
<p>To be truly agile is to adapt and improve; storing this knowledge in a shared document means you can iterate and modify your goals to meet the needs of your team, even when there is a change in direction.</p>
<p>My suggestion is to include the first attempt at your agile test strategy when you’re developing team working agreements and revisit it at your first retrospective. If you start with a clear, concise outline of your intentions then you’ll have a good foundation on which you can build your organisational maturity.</p>
<p>If you’re already in a working team – introduce the idea at your next planning session and perhaps bring along a first draft that the team can review and contribute to.</p>
<h1 id="what-might-be-in-an-agile-test-strategy">What might be in an agile test strategy?</h1>
<p>There’s no strict rule here – write down whatever you need to tell a newcomer about your process. Here are some prompts that will help you to begin:</p>
<ul>
<li>An outline of your broad goals with respect to quality.</li>
<li>A description of the terms you use to describe test types.</li>
<li>Scope; how will you focus your effort?</li>
<li>Approach; how will you work?
<ul>
<li>Before the story has been started.</li>
<li>After the story has been completed.</li>
<li>How will the story be signed off (Done)?</li>
</ul>
</li>
<li>Environments:
<ul>
<li>Do you have any specific requirements?</li>
<li>Do you share it? With whom?</li>
</ul>
</li>
<li>Risks (known or perceived).</li>
<li>Clarification of any roles and responsibilities.</li>
<li>Reporting – automated? version controlled? manual? where?</li>
</ul>
<h1 id="test-process-improvement">Test process improvement</h1>
<p>This is part of shifting right (yes, there’s more than just <em>shifting left</em>); it means focusing on improving your current practice with the benefit of experience and the overarching aim is to deliver better solutions that have fewer defects and improved reliability.</p>
<p>I have no intention of dishing out hard rules here: It’s your journey, but I do have some thoughts that may help:</p>
<ul>
<li>Keep track of things that are and aren’t working for your team as you go.</li>
<li>Evaluate the impact of your testing; collect useful data from monitoring software and understand the end user.</li>
<li>Don’t underestimate the human impact.</li>
<li>Regularly question your scope and approach, if you can’t defend it then it may not be working for you.</li>
<li>Try something new and measure it so you know if it adds value.</li>
</ul>
<h1 id="making-it-easy-how-to-start">Making it easy: How to start?</h1>
<p>Figure out <strong>what you’re trying to achieve</strong> with testing</p>
<ul>
<li>Is the software correct?</li>
<li>Does it meet some standard?</li>
<li>Is it maintainable?</li>
<li>Is it bug free?</li>
<li>Formal verification is a fair goal if you’re working with safety critical systems.</li>
</ul>
<p><strong>How</strong> will you meet your goals?</p>
<p><em>What kinds of testing will you use?</em></p>
<ul>
<li>Manual?</li>
<li>Unit tests?</li>
<li>TDD?</li>
<li>Acceptance tests?</li>
</ul>
<p>…this list could continue for a long time – pick suitable choices that are reasonably achievable</p>
<p><strong>Clarify any ambiguity</strong> that could reasonably exist. Specifically, you might choose to address the following:</p>
<ul>
<li>Terminology</li>
<li>Approach</li>
<li>Scope</li>
<li>Defect management</li>
<li>Roles and responsibilities</li>
<li>Environment requirements</li>
</ul>
<h1 id="still-not-sure-where-to-begin">Still not sure where to begin?</h1>
<p>Look at the foundation levels of the TMMi model – it may not align with your goals, but I strongly believe that every organisation should be capable of operating at level 2 of the model before beginning to work on optimising its process.</p>
<h1 id="presentation-matters">Presentation matters</h1>
<p>Brevity is an art form in itself so I try to maintain a complete version of the strategy (around 3 pages, widely spaced) and a one-page version that I can throw up in a retrospective and the team can immediately see everything in short form.</p>Agile testing doesn’t need a test strategy, does it?Software production readiness2017-01-31T08:00:00+00:002017-01-31T08:00:00+00:00/software/engineering/development/production/environment/deployment/testing/release/releng/2017/01/31/software-production-readiness<p><strong>Where to start?</strong>
I’ve been asked a few times recently about how to ensure a new software component is ready to enter production.</p>
<p>Typically I suggest the developer follow whichever release guidelines are available, but sometimes there are none.</p>
<p>Here’s a list of questions in no specific order that should prompt consideration.</p>
<ul>
<li>Check the unit test coverage. Is there any? Does it give you confidence?</li>
<li>Has the code and unit test coverage been peer reviewed? Do you want it to be 100%? Did you check your coverage is non-trivial coverage?</li>
<li>Has QA signed off the component in a production-like environment? (n.b. Docker is production-like if you’re running Docker in production)</li>
<li>Have the business performed any acceptance testing (or has a demo been conducted)?</li>
<li>Is there a rollback strategy in place?</li>
<li>Is there a mechanism for raising alerts when the system encounters an error?</li>
<li>Do you have a log store? (perhaps more importantly, does it rotate?)</li>
<li>Have you documented the source code? (e.g. Javadoc or similar)</li>
<li>Have you performance tested? (note: a short Jmeter load test can give false confidence, be careful here!)</li>
<li>Do you need to communicate the change to any operations or support staff? Has documentation been prepared?</li>
<li>
<p>Do you have a tagged copy of the source code in your source code repository?</p>
<p><strong>Wait, what?</strong> You might think this one above is too easy to even mention, but more than one team I’ve worked with has been stuck with a binary and no copy of the source code due to developer error – failing to push and deleting their copy.</p>
</li>
<li>Have you integrated your component with your organisation’s CI or CD tool?</li>
<li>Did you set the configuration correctly? (Check: Environment variables, ports, hostnames, firewall rules)</li>
<li>Did you check for vulnerabilities in your software dependencies? (<strong>Yes, do scan that docker image</strong>, it’s only as good as its layers!)</li>
<li>Are there any authentication/authorisation or privacy concerns that may mean you should have your component security tested?</li>
<li>I’m certain that there are points I’ve omitted that you can think of, but this should be enough to begin forming your software production readiness checklist.</li>
</ul>
<p>If you’ve got burning questions or wish to add more to this list I’m keen to hear from you – get in touch with me on Twitter.</p>Where to start? I’ve been asked a few times recently about how to ensure a new software component is ready to enter production.Ruby with rbenv on Ubuntu 15.102016-03-13T08:00:00+00:002016-03-13T08:00:00+00:00/ruby/rbenv/development/software/environment/ubuntu/linux/2016/03/13/Ruby-with-rbenv-ubuntu-15-10<p>Hey, so you want to install Ruby with rbenv, lets jump in.</p>
<p>To follow this guide you need:</p>
<ul>
<li>Ubuntu (I’m using 15.10)</li>
<li>a user account with sudo privileges</li>
</ul>
<p>First lets update the apt packages:</p>
<p><code class="highlighter-rouge">~$ sudo apt-get update</code></p>
<p>next lets install git because we’ll be using git repositories for ruby build and rbenv</p>
<p><code class="highlighter-rouge">~$ sudo apt-get install git gitk git-gui</code></p>
<p>we’ll also need some build tools to compile the ruby versions</p>
<p><code class="highlighter-rouge">~$ sudo apt-get install gcc build-essential libpq-dev libssl-dev libreadline-dev libsqlite3-dev zlib1g-dev</code></p>
<p>now, we’ll start in the home directory of the current user</p>
<p><code class="highlighter-rouge">~$ cd</code></p>
<p>the next step is getting rbenv from github</p>
<p><code class="highlighter-rouge">~$ git clone git://github.com/sstephenson/rbenv.git .rbenv</code></p>
<p>And then we’ll add rbenv bin directory to the PATH so that we can use rbenv as a command</p>
<p><code class="highlighter-rouge">~$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc</code></p>
<p>We probably want this to take effect in our current session, so lets use the source command to reload the bash environment variables</p>
<p><code class="highlighter-rouge">~$ source ~/.bashrc</code></p>
<p>Now check it worked:</p>
<p><code class="highlighter-rouge">~$ rbenv</code></p>
<p>Note: If this step doesn’t work, you’ve missed something. Assuming you get some help output from rbenv, proceed…</p>
<p>Ok, we’ll also want some autocompletion for our rbenv… lets enable this:</p>
<p><code class="highlighter-rouge">~$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc</code></p>
<p>Now lets get ruby build from github</p>
<p><code class="highlighter-rouge">~$ git clone git://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build</code></p>
<p>and we’ll add the ruby build bin directory to the path</p>
<p><code class="highlighter-rouge">~$ echo 'export PATH="$HOME/.rbenv/plugins/ruby-build/bin:$PATH"' >> ~/.bashrc</code></p>
<p>and reload the bashrc</p>
<p><code class="highlighter-rouge">~$ source ~/.bashrc</code></p>
<p>Now we can install a ruby version.</p>
<p><code class="highlighter-rouge">~$ rbenv install -v 2.2.3</code></p>
<p><strong>Note:</strong>
This step takes a <strong>few minutes</strong> (maybe long enough to make coffee, maybe long enough to drink it too) depending on your computer.</p>
<p>It’s compiling the Ruby version from scratch so it is somewhat processor intensive. Hold tight!</p>
<p>…Finally, the last step before we can type ruby in the terminal is setting the version</p>
<p><code class="highlighter-rouge">~$ rbenv global 2.2.3</code></p>
<p>Great. Now try it:</p>
<p><code class="highlighter-rouge">~$ ruby -v</code></p>
<p>Optional final step; save yourself disk space and time by telling your gems not to generate documentation.</p>
<p><code class="highlighter-rouge">~$ echo "gem: --no-document" > ~/.gemrc</code></p>
<p>Sweet – you’re all set with Ruby installed and rbenv setup. Enjoy!</p>Hey, so you want to install Ruby with rbenv, lets jump in.