<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.4.3">Jekyll</generator><link href="https://starefossen.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://starefossen.github.io/" rel="alternate" type="text/html" /><updated>2017-05-07T20:24:30+00:00</updated><id>https://starefossen.github.io/</id><title type="html">/dev/random</title><subtitle>Random thoughts on development and stuff</subtitle><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><entry><title type="html">Making a Status Page</title><link href="https://starefossen.github.io/post/2016/03/11/making-a-status-page/" rel="alternate" type="text/html" title="Making a Status Page" /><published>2016-03-11T00:00:00+00:00</published><updated>2016-03-11T00:00:00+00:00</updated><id>https://starefossen.github.io/post/2016/03/11/making-a-status-page</id><content type="html" xml:base="https://starefossen.github.io/post/2016/03/11/making-a-status-page/">&lt;p&gt;We recently had (another) a major outage from one of our payment providers. I
decided to make a simple status page that we could direct customers to when
something like this happened next time.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2016/03/11/system-status.gif&quot; alt=&quot;System Status Page&quot; /&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;vision&quot;&gt;Vision&lt;/h2&gt;

&lt;p&gt;The status page should use existing monitoring infrastructure - we don’t want to
duplicate the monitoring effort already in place. The status page itself should
be statically hosted, to minimize the risk of the status page itself going down,
and fetch service status dynamically - client side - so it does not need to be
updated manually.&lt;/p&gt;

&lt;p&gt;Status page is not a new thing, in fact there quite a few alternatives out
there. &lt;a href=&quot;https://github.com/pyupio/statuspage&quot;&gt;pyupio/statuspage&lt;/a&gt; and &lt;a href=&quot;https://github.com/CachetHQ/Cachet&quot;&gt;CachetHQ/Cachet&lt;/a&gt; are two open source
alternatives; while &lt;a href=&quot;https://status.io/&quot;&gt;Status.io&lt;/a&gt; and &lt;a href=&quot;https://www.statuspage.io/&quot;&gt;StatusPage.io&lt;/a&gt; are two commercial
proprietary options. As a hacker for a non-profit organization the proprietary
ones were out of the question :wink:&lt;/p&gt;

&lt;p&gt;I ended up borrowing layout, and concepts, from &lt;a href=&quot;https://github.com/pyupio/statuspage&quot;&gt;pyupio/statuspage&lt;/a&gt; - a shout
out goes to @pyupio for sharing such a solid piece of work with the community
:tada:&lt;/p&gt;

&lt;h2 id=&quot;service-status&quot;&gt;Service Status&lt;/h2&gt;

&lt;p&gt;As I mentioned, we already had extensive monitoring of applications, internal-
and external services set up through Pingdom. All outages are posted directly to
a Slack channel in real time. If left unresolved for enough time alerts are sent
out through push notifications and SMS.&lt;/p&gt;

&lt;p&gt;The &lt;a href=&quot;https://www.pingdom.com/resources/api&quot;&gt;Pingdom API&lt;/a&gt; requires user authentication - of course - in order to get out
any status data. This would be a problem for the client side status page vision.
In order to overcome this restriction I made a simple API proxy (written in
Node.js :rocket:) dubbed &lt;a href=&quot;https://github.com/Starefossen/status-api&quot;&gt;Starefossen/status-api&lt;/a&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;GET /api/v1/checks HTTP/1.1
Host: status.app.dnt.no

HTTP/1.1 200 OK
Access-Control-Allow-Origin: *
Content-Type: application/json; charset=utf-8

{
    &quot;checks&quot;: [ ... ]
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;We had more checks than we would like, or should, expose on the status page -
they needed to be organized. Pingdom had the solution – organization by tags. We
tagged all checks we would like to show up on the status page with &lt;code class=&quot;highlighter-rouge&quot;&gt;public&lt;/code&gt;.
From the API we could now filter using &lt;code class=&quot;highlighter-rouge&quot;&gt;?tags=public&lt;/code&gt;. We also created service
type tags to group different checks together; &lt;code class=&quot;highlighter-rouge&quot;&gt;app&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;service&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;payment&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2016/03/11/tags.gif&quot; alt=&quot;Pingdom Check Tags&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;incident-messages&quot;&gt;Incident Messages&lt;/h2&gt;

&lt;p&gt;The next thing we would like for our status page was the ability to post
messages about various incidents. We wanted to reuse existing infrastructure as
much as possible and we know GitHub had an awesome API, that could even be used
without any user authentication.&lt;/p&gt;

&lt;p&gt;We could simply create issues directly in the &lt;a href=&quot;https://github.com/Turistforeningen/status&quot;&gt;Turistforeningen/status&lt;/a&gt; issue
tracker on GitHub and fetch them using the &lt;a href=&quot;https://developer.github.com/v3/&quot;&gt;GitHub API&lt;/a&gt;. This was just what we
needed! We added some labels to indicate outage status levels and others to
indicate the various systems that could be affected.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2016/03/11/labels.png&quot; alt=&quot;GitHub Issue Labels&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Closing the issues would resolve the incident and return the status page to it’s
normal green status. This way we would only need to log incidents to GitHub and
not worry about some other tool or system to manage this.&lt;/p&gt;

&lt;h2 id=&quot;gluing-it-all-together&quot;&gt;Gluing it all together&lt;/h2&gt;

&lt;p&gt;Now that we have both the individual status checks and incident messages we can
start writing some pseudocode for how the status page should work. As you can
see from the code below, the whole page is fairly comprehensible.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;# get checks and messages
checks = http.get(&quot;https://status.app.dnt.no/api/v1/checks&quot;)
messages = http.get(&quot;https://api.github.com/repos/Turistforeningen/status/issues&quot;)

alert = null

# add messages to page
for message in messages
  if message.status is not &quot;resolved&quot;
    alert = message.title

  addMessage(message.title, message.body, message.status)

# add status checks to page
for check in checks
  if check.status is not &quot;up&quot; and alert is null
    alert = check.name + &quot;is down&quot;

  addCheck(check.name, check.status, check.tag)

# show alert header message
showAlertMessage(alert)
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The client side implementation for the status page can be found in &lt;a href=&quot;https://github.com/Turistforeningen/status/blob/gh-pages/assets/js/script.js&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;script.js&lt;/code&gt;&lt;/a&gt;
in the repository up on GitHub. Except from the asynchronous nature of JavaScript
as well as the DOM manipulation necessary for adding new elements to a HTML
page; you should be able to see the familiarity with the above pseudocode.&lt;/p&gt;

&lt;p&gt;If you open up your dev tools on the status page you will see the two XHR
request happening before the checks and messages are displayed on the page.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2016/03/11/http-xhr.gif&quot; alt=&quot;HTTP XHR&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-power-of-github-pages&quot;&gt;The Power of GitHub Pages&lt;/h2&gt;

&lt;p&gt;The last piece of the puzzle was a reliable place to host the static files
necessary for the status page to function. An &lt;code class=&quot;highlighter-rouge&quot;&gt;index.html&lt;/code&gt;, some JavaScript, and
little bit of CSS. Since the source code was already hosted on GitHub, and we
have had good experience with using &lt;a href=&quot;https://help.github.com/articles/what-are-github-pages/&quot;&gt;GitHub Pages&lt;/a&gt; in the past it was the
obvious decision. This very blog you are reading is hosted on GitHub Pages as
well.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Also read:&lt;/strong&gt; &lt;a href=&quot;/post/2016/02/11/jekyll-3-on-github-pages/&quot;&gt;Jekyll 3 and GitHub Pages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just push the code to a branch named &lt;code class=&quot;highlighter-rouge&quot;&gt;gh-pages&lt;/code&gt; and let GitHub do the rest! We
even could customize the domain name simply by adding a &lt;code class=&quot;highlighter-rouge&quot;&gt;CNAME&lt;/code&gt; file with the
desired domain name – &lt;a href=&quot;http://status.dnt.no&quot;&gt;status.dnt.no&lt;/a&gt;. The complete source code for our new
status page is up at &lt;a href=&quot;https://github.com/Turistforeningen/status&quot;&gt;Turistforeningen/status&lt;/a&gt; and licensed under the &lt;a href=&quot;https://github.com/Turistforeningen/status/blob/gh-pages/LICENSE&quot;&gt;MIT
license&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;future-work&quot;&gt;Future Work&lt;/h2&gt;

&lt;p&gt;As any other project, the Status Page is not done done - there is always more
features that could be implemented. Here are some of my thoughts for future
improvements.&lt;/p&gt;

&lt;h3 id=&quot;response-time&quot;&gt;Response Time&lt;/h3&gt;

&lt;p&gt;Service response time is currently not considered. Service status could be based
on a threshold with regards to the average response time over x amount of time
in addition to the downtime.&lt;/p&gt;

&lt;p&gt;Response time graphs would also be a nice addition to the &lt;code class=&quot;highlighter-rouge&quot;&gt;operational&lt;/code&gt; and
&lt;code class=&quot;highlighter-rouge&quot;&gt;major outage&lt;/code&gt; labels.&lt;/p&gt;

&lt;h3 id=&quot;downtime&quot;&gt;Downtime&lt;/h3&gt;

&lt;p&gt;Currently the Status Page only checks how long since last reported downtime.
This is because the Pingdom API only returns this when listing all the checks.
A natural thing to do would be to fetch the duration from the &lt;code class=&quot;highlighter-rouge&quot;&gt;summary&lt;/code&gt; API
endpoint for services with downtime within some amount of time.&lt;/p&gt;</content><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><category term="devops" /><category term="uptime" /><category term="monitoring" /><summary type="html">We recently had (another) a major outage from one of our payment providers. I decided to make a simple status page that we could direct customers to when something like this happened next time.</summary></entry><entry><title type="html">Spaghetti, Notebooks, and Modeling</title><link href="https://starefossen.github.io/post/2016/03/09/spaghetti-notebook-modeling/" rel="alternate" type="text/html" title="Spaghetti, Notebooks, and Modeling" /><published>2016-03-09T00:00:00+00:00</published><updated>2016-03-09T00:00:00+00:00</updated><id>https://starefossen.github.io/post/2016/03/09/spaghetti-notebook-modeling</id><content type="html" xml:base="https://starefossen.github.io/post/2016/03/09/spaghetti-notebook-modeling/">&lt;p&gt;Microservices dependency spaghetti, the concept of an engineering notebook, and
the importance of software modeling was three main topics discussed at this
meeting with &lt;a href=&quot;http://www.meetup.com/Lean-Coffee-Bergen/&quot;&gt;Lean Coffee Bergen&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2016/03/09/lean-coffee.jpg&quot; alt=&quot;Lean Coffee Kanban board in action&quot; /&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;microservice-spaghetti&quot;&gt;Microservice Spaghetti&lt;/h2&gt;

&lt;p&gt;The microservice oriented approach is not a new concept in the world of software
engineering, and is more traditionally known as service oriented architecture&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; -
or SOA for short. Such a services should be unassociated, loosely coupled units
of functionality that are self-contained.&lt;/p&gt;

&lt;p&gt;In reality, however, many of the services had in fact hard dependencies such the
ability for inter process communication; programming language and version. Even
though they appeared unassociated there ware in fact tightly coupled with one
another.&lt;/p&gt;

&lt;p&gt;A more modern definition of microservices are web services. They implement the
same functionality as their SOA counterpart over standard Internet protocols
independent of platforms and programming languages. This allows services to be
moved around, switched out, rebuilt, and scaled without having to worry about
other their dependents (in theory at last).&lt;/p&gt;

&lt;h2 id=&quot;the-engineering-notebook&quot;&gt;The Engineering Notebook&lt;/h2&gt;

&lt;p&gt;The concept of an Engineering Notebook is the method of to precisely record all
work, from concept to prototype - preferably in a notebook by hand. Should
software engineers adopt more of this mindset too?&lt;/p&gt;

&lt;p&gt;The notebook is always on and it comes with no distracting notifications. You
will be able to have one canonical source of history - instead of sifting
through multiple git repositories or issue trackers. The notebook also has an
infinite amount of different drawings and support for complex notations without
installing any special tool or ad-on.&lt;/p&gt;

&lt;p&gt;On the other hand, notebooks are not easily searchable and depending on your
handwriting may not be easily readable after some amount of time. Some attempts
has been made to use digital notebooks (tablets) with handwriting recognition
software with varied amount of success.&lt;/p&gt;

&lt;p&gt;A notebook can be quite useful for personal planning. Project management tools
like &lt;a href=&quot;https://www.atlassian.com/software/jira/&quot;&gt;JIRA&lt;/a&gt; are often better for information sharing than personal task
management. Simply making a list in your notebook and crossing them out as you
go during the day may be a good solution for keeping track of your day to day
activities.&lt;/p&gt;

&lt;h2 id=&quot;software-modeling&quot;&gt;Software Modeling&lt;/h2&gt;

&lt;p&gt;Many software engineers have a formal understanding of software modeling through
UML diagrams&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; from their university education and the formal waterfall
software development process&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. But what role does software modeling play in
today’s world of agile software development?&lt;/p&gt;

&lt;p&gt;With Agile development there is less design up front, however, this is not an
excuse for not making proper models and diagrams of the system(s) in question.
This is a good practice that all engineers must restrain and remember to use.&lt;/p&gt;

&lt;p&gt;Diagrams are useful for modeling entities and their relations or dependencies.
Some diagram can be thrown away when the implementation is done, while others
can be kept as reference or documentation for later. Be mindful if the diagram
is one or the other.&lt;/p&gt;

&lt;p&gt;If you are using JIRA it might be worth to take a look at &lt;a href=&quot;https://www.gliffy.com/&quot;&gt;Gliffy&lt;/a&gt; - a digital
tool to create and manage flowcharts, wireframes, UML diagrams directly from
issues and wiki pages.&lt;/p&gt;

&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Service-oriented_architecture&quot;&gt;Service-oriented architecture&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Unified_Modeling_Language&quot;&gt;Unified Modeling Language&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Waterfall_model&quot;&gt;Waterfall model&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><category term="agile" /><category term="lean coffee" /><summary type="html">Microservices dependency spaghetti, the concept of an engineering notebook, and the importance of software modeling was three main topics discussed at this meeting with Lean Coffee Bergen.</summary></entry><entry><title type="html">Node.js Drama of 2016: Express.js</title><link href="https://starefossen.github.io/post/2016/02/13/nodejs-drama-express/" rel="alternate" type="text/html" title="Node.js Drama of 2016: Express.js" /><published>2016-02-13T00:00:00+00:00</published><updated>2016-02-13T00:00:00+00:00</updated><id>https://starefossen.github.io/post/2016/02/13/nodejs-drama-express</id><content type="html" xml:base="https://starefossen.github.io/post/2016/02/13/nodejs-drama-express/">&lt;p&gt;&lt;a href=&quot;http://expressjs.com/&quot;&gt;Express&lt;/a&gt; was originally created by TJ Holowaychuk (@tj) in 2009, under the the
slogan «&lt;em&gt;Insanely fast (and small) server-side JavaScript web development
framework&lt;/em&gt;». It has since grown to become one of the most widely installed
package from the npm registry with over 4.5 million monthly downloads. Now, it
may be facing a new beginning!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2016/02/13/techcrunch.png&quot; alt=&quot;Screenshot of IBM's acquisition of StrongLoop in TechCrunch&quot; /&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;transferred-to-strongloop&quot;&gt;Transferred to StrongLoop&lt;/h2&gt;

&lt;p&gt;To understand the drama surrounding Express you need to know some of the history
of the Express project. Lets rewind to the spring of 2014. Node.js is growing
rapidly much thanked to modules like Express which makes it super easy for
anyone to spin up websites and services using Node.js.&lt;/p&gt;

&lt;p&gt;Since 2013 TJ had greatly reduced his involvement in Epxress development, and by
May of 2014 Douglas Wilson (@dougwilson) had more or less taken over the role as
lead maintainer of Express. Then, shortly thereafter, TJ announced he was
leaving the Node.js community&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; and the Express project would find a new home
at StrongLoop&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://strongloop.com/&quot;&gt;StrongLoop&lt;/a&gt; is the author of the &lt;a href=&quot;http://loopback.io/&quot;&gt;LoopBack&lt;/a&gt;, a framework for creating APIs
built on top of, you might have already guessed it, Express. The transfer of
Express to StrongLoop came as a shock to the maintainers&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;. They had not been
informed, and they had lost access to the main repository during the transfer.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[…] TJ has not been the one maintaining express day to day for a long time
and I think this move came as a surprise to all of the current maintainers.&lt;/p&gt;

  &lt;p&gt;–@defunctzombie (&lt;a href=&quot;https://github.com/expressjs/express/issues/2264#issuecomment-50509818&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The maintainers were upset and they felt this was a move in the wrong direction.
Rumors of StrongLoop purchasing Express from TJ did not exactly help. TJ even
did a follow up post in an attempt to defuse the situation&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; but to little or
no avail. StrongLoop co-founder Bert Belder (@piscisaureus) promised Express
would remain an open source project.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[…] express will remain a community open source project; that’s what makes it
interesting in the first place.&lt;/p&gt;

  &lt;p&gt;-@piscisaureus (&lt;a href=&quot;https://github.com/expressjs/express/issues/2264#issuecomment-50685504&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2016/02/13/contributors.png&quot; alt=&quot;Contributors graph for the Express project&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;acquired-by-ibm&quot;&gt;Acquired by IBM&lt;/h2&gt;

&lt;p&gt;Fast forward to September 10Th, 2015. The dust over the transfer to StrongLoop
had settled, and the development of Express had slowly declined. IBM announced
they had acquired StrongLoop&lt;sup id=&quot;fnref:5&quot;&gt;&lt;a href=&quot;#fn:5&quot; class=&quot;footnote&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; and a prophecy from a year earlier may be about
to come true.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Strongloop may not be a thing in 1 year or 2 years […]&lt;/p&gt;

  &lt;p&gt;–@defunctzombie (&lt;a href=&quot;https://github.com/expressjs/express/issues/2264#issuecomment-50509818&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This leads to a very special situation where the new owner of Express, IBM, and
the employer of the lead maintainer for Express, Sencha Labs, are competing
companies.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[…] @dougwilson (who has maintained express for two years) can no longer
contribute to the Express project because IBM is a direct competitor to his
employer.&lt;/p&gt;

  &lt;p&gt;–@chipersoft (&lt;a href=&quot;https://github.com/nodejs/TSC/pull/39#issuecomment-178216742&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Whats left of the maintainers, and other concerned user, makes another attempt
to have Express moved to it’s own organization on GitHub - under the banner of
«returning Express back to the community». Several attempts was made with IBM
during the fall of 2015 but the situation looked more deadlocked than ever. This
was apparently the last drop for Doug Wilson in a growing frustration with
corporate overlords.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I did not voluntarily give up on Express, IBM forced me out of this
repository.&lt;/p&gt;

  &lt;p&gt;-@dougwilson (&lt;a href=&quot;https://github.com/expressjs/express/issues/2844#issuecomment-171430278&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;By January of 2016 IBM was still figuring out what to do with the sticky
situation they had inherited from StrongLoop acquisition. While more and more
disgruntled users piled on the discussion about what should happen with Express
next, James M Snell (@jasnell) from IBM and Ritchie Martori (@ritch) from
StrongLoop was working with various stakeholders within IBM to conclude a
solution&lt;sup id=&quot;fnref:7&quot;&gt;&lt;a href=&quot;#fn:7&quot; class=&quot;footnote&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The express project is applying to become an incubating top level project.&lt;/p&gt;

  &lt;p&gt;–@jasnell (&lt;a href=&quot;https://github.com/nodejs/TSC/pull/39#issue-129621635&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This stirred up the discussion again, and after a lengthy (and heated)
discussion back and forth, the incubating application was merged. This means, if
everything goes as planned, that Express will become an official Node.js project
outside of what is known as Node.js core.&lt;/p&gt;

&lt;h2 id=&quot;epilogue&quot;&gt;Epilogue&lt;/h2&gt;

&lt;p&gt;Express has now been transferred to it’s new home at &lt;a href=&quot;https://github.com/expressjs/express/&quot;&gt;expressjs/express&lt;/a&gt;, and
Doug Wilson also transferred the ownership of his modules that Express depends
on, either directly or indirectly, to the Node.js foundation.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;I am donating all of my Node.js modules to the Node.js foundation, to go along
with Express.&lt;/p&gt;

  &lt;p&gt;–@dougwilson (&lt;a href=&quot;https://github.com/expressjs/express/issues/2844#issuecomment-177043519&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The intellectual property of Express, however, is still owned by IBM and will
probably remain so for a long time. The API documentation, a blog post worthy in
and of itself, will be pulled into the main repository&lt;sup id=&quot;fnref:8&quot;&gt;&lt;a href=&quot;#fn:8&quot; class=&quot;footnote&quot;&gt;7&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;[…] currently there is no IP transfer indicated. The question over the
 expressjs.com domain name will need to be looked at again a bit later but it
 will not be included in this initial proposal.&lt;/p&gt;

  &lt;p&gt;–@jasnell (&lt;a href=&quot;https://github.com/nodejs/TSC/pull/39#issuecomment-181944178&quot;&gt;source&lt;/a&gt;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;:sparkles: Stay tuned for more drama! :sparkles:&lt;/p&gt;

&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://medium.com/@tjholowaychuk/farewell-node-js-4ba9e7f3e52b#.kta3541lp&quot;&gt;Farewell Node.js - Leaving node.js land&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://strongloop.com/strongblog/tj-holowaychuk-sponsorship-of-express/&quot;&gt;TJ Holowaychuk Passes Sponsorship of Express to StrongLoop&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/strongloop/express/issues/2264&quot;&gt;This repo needs to belong in the expressjs org&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://medium.com/@tjholowaychuk/strongloop-express-40b8bcb8e5af#.vsa9sx3zs&quot;&gt;StrongLoop &amp;amp; Express&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:5&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://www-03.ibm.com/press/us/en/pressrelease/47577.wss&quot;&gt;IBM Acquires StrongLoop to Extend Enterprise Reach using IBM Cloud&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:5&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:7&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/nodejs/TSC/pull/39&quot;&gt;Add initial TLP application for express&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:7&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:8&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/expressjs/express/issues/2887&quot;&gt;Move API doc source from expressjs.com repo&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:8&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><category term="nodejs" /><category term="drama" /><category term="express" /><summary type="html">Express was originally created by TJ Holowaychuk (@tj) in 2009, under the the slogan «Insanely fast (and small) server-side JavaScript web development framework». It has since grown to become one of the most widely installed package from the npm registry with over 4.5 million monthly downloads. Now, it may be facing a new beginning!</summary></entry><entry><title type="html">Jekyll 3 and GitHub Pages</title><link href="https://starefossen.github.io/post/2016/02/11/jekyll-3-on-github-pages/" rel="alternate" type="text/html" title="Jekyll 3 and GitHub Pages" /><published>2016-02-11T00:00:00+00:00</published><updated>2016-02-11T00:00:00+00:00</updated><id>https://starefossen.github.io/post/2016/02/11/jekyll-3-on-github-pages</id><content type="html" xml:base="https://starefossen.github.io/post/2016/02/11/jekyll-3-on-github-pages/">&lt;p&gt;Jekyll, the static site generator used by GitHub Pages, recently released their
third major version 💯 🌟 and GitHub Pages just announced their support. Here is a
list of all the new cool stuff and what &lt;em&gt;you&lt;/em&gt; need to change!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2016/02/11/jekyll.png&quot; alt=&quot;Jekyll Static Site Generator&quot; /&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;h2 id=&quot;what-is-a-static-site-generator&quot;&gt;What is a static site generator?&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://jekyllrb.com/&quot;&gt;Jekyll&lt;/a&gt; is one of many static site generators perfect for making for personal,
project, or organization sites. Think of it like a file-based CMS, but without
all the complexity. A static site generator takes your content, often written in
some sort of Markdown flavor, and out comes a complete, static website ready to
be served by Apache, Nginx or another web server.&lt;/p&gt;

&lt;p&gt;Because the output it is just bunch of static files it does not require any
database, it can be cached and served extremely efficient over HTTP. Jekyll is
the engine behind GitHub Pages, which you can use to host sites right from your
GitHub repositories for free.&lt;/p&gt;

&lt;h2 id=&quot;what-is-new-in-jekyll-30&quot;&gt;What is new in Jekyll 3.0?&lt;/h2&gt;

&lt;p&gt;Many of the important changes in Jekyll 3.0 are under the hood. The two most
prominent new features are related to performance and profiling.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;--incremental&lt;/code&gt; regeneration of changes makes local builds significantly
faster. This is especially important for large sites, and you will be able to
preview changes instantly.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;--profile&lt;/code&gt; option tells Jekyll to analyze your site’s build time. This
enables you to find exactly the spots where you can speed things up if compile
time is an issue.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt; jekyll build --profile
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;table class=&quot;table table-striped table-bordered table-hover&quot; rules=&quot;groups&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th style=&quot;text-align: left&quot;&gt;Filename&lt;/th&gt;
      &lt;th style=&quot;text-align: center&quot;&gt;Count&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Bytes&lt;/th&gt;
      &lt;th style=&quot;text-align: right&quot;&gt;Time&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;feed.xml&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;58.48K&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.200&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_layouts/default.html&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;120.54K&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.088&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;sitemap.xml&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;3.06K&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.054&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_includes/side.html&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;11.59K&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.007&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_layouts/post.html&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;9&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;53.38K&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.006&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_includes/head.html&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;18.30K&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.003&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;index.html&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;9.02K&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.003&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_includes/header.html&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;1.05K&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.002&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;timeline.html&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;1&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;6.42K&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.001&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td style=&quot;text-align: left&quot;&gt;_includes/footer.html&lt;/td&gt;
      &lt;td style=&quot;text-align: center&quot;&gt;12&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;10.09K&lt;/td&gt;
      &lt;td style=&quot;text-align: right&quot;&gt;0.001&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;The default highlighter has been changed from &lt;a href=&quot;http://pygments.org/&quot;&gt;Pygments&lt;/a&gt; to &lt;a href=&quot;http://rouge.jneen.net/&quot;&gt;Rouge&lt;/a&gt; - a
pure-ruby code highlighter that is compatible with Pygments. The change should
be seamless for most users of Jekyll and GitHub Pages.&lt;/p&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;site.collections&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;&lt;/code&gt; is now array of collections
and &lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;site.posts&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;&lt;/code&gt; is now a part of all the collections
and not a special array. Read more about &lt;a href=&quot;http://jekyllrb.com/docs/collections/&quot;&gt;Jekyll Collections&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;new-filters&quot;&gt;New Filters&lt;/h3&gt;

&lt;p&gt;Also new is &lt;a href=&quot;https://github.com/Shopify/liquid&quot;&gt;Liquid&lt;/a&gt; 3.0. Liquid is the templating engine which makes all the
&lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt; magic work. As
with Jekyll, many of the changes in Liquid 3.0 are under the hood, but this
release also includes some new &lt;a href=&quot;https://github.com/Shopify/liquid/wiki/Liquid-for-Designers#standard-filters&quot;&gt;Liquid Filters&lt;/a&gt;.&lt;/p&gt;

&lt;table class=&quot;table table-striped table-bordered table-hover&quot; rules=&quot;groups&quot;&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Filter&lt;/th&gt;
      &lt;th&gt;Example&lt;/th&gt;
      &lt;th&gt;Output&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;uniq&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;[1,1,3,2,3,1,4,3,2,1]&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;uniq&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;[1,3,2,4]&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;url_encode&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;Jackô &amp;amp; Jones&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;url_encode&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}}&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;Jack%C3%B4%20%26%20Jones&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;strip&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&quot;\tab c  \n \t&quot;&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}}&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;ab c&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;default&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;first_name&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;default:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;'User'&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;User&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;h2 id=&quot;what-is-new-in-github-pages&quot;&gt;What is new in GitHub Pages?&lt;/h2&gt;

&lt;p&gt;As you might have guessed, GitHub Pages now uses Jekyll 3&lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; class=&quot;footnote&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; with all of the
new stuff mentioned above. However, there are some other changes as well, and
the most important is the change of Markdown parsing engine to &lt;a href=&quot;http://kramdown.gettalong.org/&quot;&gt;Kramdown&lt;/a&gt;. If
you are using &lt;a href=&quot;https://github.com/davidfstr/rdiscount&quot;&gt;Rediscount&lt;/a&gt; or &lt;a href=&quot;https://github.com/vmg/redcarpet&quot;&gt;Redcarpet&lt;/a&gt; for rendering your Markdown (like I
did) you should read on!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2016/02/11/incremental.png&quot; alt=&quot;Jekyll Site Generating&quot; /&gt;&lt;/p&gt;

&lt;p&gt;When working with the new changes locally I immediately ran into problems. First
of all there were some minor inconsistencies in how Jekyll was rendering
Markdown. Fenced code blocks using three or more backticks did not evaluate to
syntax highlighted code. This was solved by setting &lt;code class=&quot;highlighter-rouge&quot;&gt;input: GFM&lt;/code&gt;&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; class=&quot;footnote&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Setting this suddenly all my articles had very strange line breaks, after some
googling around I found a post on StackOverflow which suggested setting
&lt;code class=&quot;highlighter-rouge&quot;&gt;hard_wrap: false&lt;/code&gt; which solved the line break problem&lt;sup id=&quot;fnref:3&quot;&gt;&lt;a href=&quot;#fn:3&quot; class=&quot;footnote&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Still, syntax highlighting was not working correctly and after even more
googling I found a blog post which explained how to get Jekyll working with
Rouge syntax highlighter by explicitly setting &lt;code class=&quot;highlighter-rouge&quot;&gt;syntax_highlighter: rouge&lt;/code&gt;&lt;sup id=&quot;fnref:4&quot;&gt;&lt;a href=&quot;#fn:4&quot; class=&quot;footnote&quot;&gt;4&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Your final &lt;code class=&quot;highlighter-rouge&quot;&gt;_config.yml&lt;/code&gt; should include the following:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-Yaml&quot;&gt;markdown: kramdown
highlighter: rouge

kramdown:
    input: GFM
    hard_wrap: false
    syntax_highlighter: rouge
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;running-locally&quot;&gt;Running Locally&lt;/h2&gt;

&lt;p&gt;The easiest way to run your Jekyll site locally is to use the &lt;a href=&quot;https://hub.docker.com/r/starefossen/github-pages/&quot;&gt;GitHub Pages
Docker Image&lt;/a&gt; .&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-command&quot;&gt;&amp;gt; docker pull starefossen/github-pages
&amp;gt; docker run -v &quot;$PWD&quot;:/usr/src/app -p &quot;4000:4000&quot; starefossen/github-pages
&lt;/code&gt;&lt;/pre&gt;

&lt;h2 id=&quot;footnotes&quot;&gt;Footnotes&lt;/h2&gt;

&lt;div class=&quot;footnotes&quot;&gt;
  &lt;ol&gt;
    &lt;li id=&quot;fn:1&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://github.com/blog/2100-github-pages-now-faster-and-simpler-with-jekyll-3-0&quot;&gt;GitHub Pages now faster and simpler with Jekyll 3.0&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:1&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:2&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://kramdown.gettalong.org/parser/gfm.html&quot;&gt;Github Flavored Markdown Parser&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:2&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:3&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;http://stackoverflow.com/questions/25418399/jekyll-converting-every-newline-as-line-break&quot;&gt;Jekyll converting every newline as line break&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:3&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
    &lt;li id=&quot;fn:4&quot;&gt;
      &lt;p&gt;&lt;a href=&quot;https://sacha.me/articles/jekyll-rouge/&quot;&gt;Syntax Highlighting in Jekyll With Rouge&lt;/a&gt;&amp;nbsp;&lt;a href=&quot;#fnref:4&quot; class=&quot;reversefootnote&quot;&gt;&amp;#8617;&lt;/a&gt;&lt;/p&gt;
    &lt;/li&gt;
  &lt;/ol&gt;
&lt;/div&gt;</content><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><category term="github" /><category term="jekyll" /><summary type="html">Jekyll, the static site generator used by GitHub Pages, recently released their third major version 💯 🌟 and GitHub Pages just announced their support. Here is a list of all the new cool stuff and what you need to change!</summary></entry><entry><title type="html">Automatic Publishing of npm Packages</title><link href="https://starefossen.github.io/post/2015/09/20/automatic-publishing-to-npm/" rel="alternate" type="text/html" title="Automatic Publishing of npm Packages" /><published>2015-09-20T00:00:00+00:00</published><updated>2015-09-20T00:00:00+00:00</updated><id>https://starefossen.github.io/post/2015/09/20/automatic-publishing-to-npm</id><content type="html" xml:base="https://starefossen.github.io/post/2015/09/20/automatic-publishing-to-npm/">&lt;p&gt;If you are actively maintaining more than a couple of packages in the npm
registry this will be a life saver for you; automatically publish new versions of
your packages directly from your CI server 📡&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/09/20/auto-publish.gif&quot; alt=&quot;Automatic publish successfull builds&quot; /&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;As the &lt;em&gt;only&lt;/em&gt; package maintainer at &lt;a href=&quot;http://english.turistforeningen.no&quot;&gt;the Norwegian Trekking
Association&lt;/a&gt;, and currently maintaining &lt;a href=&quot;https://www.npmjs.com/~turistforeningen&quot;&gt;16
packages&lt;/a&gt; in the public npm registry,
time is of essence. Anything that can ease the burden of maintaining all the
packages is a welcomed addition 😅&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Also read:&lt;/strong&gt; &lt;a href=&quot;/post/2015/04/06/git--tagging-releases/&quot;&gt;Tagging software releases with git and
GitHub&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;the-problem&quot;&gt;The problem&lt;/h2&gt;

&lt;p&gt;So what exactly is the problem we are trying to solve? The &lt;code class=&quot;highlighter-rouge&quot;&gt;npm publish&lt;/code&gt; command
requires the user to be authenticated before they can publish. If you publish
from multiple machines and/or have multiple maintainers you will need to make
sure that all of those are authenticated with npm.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/09/20/npm-publish.gif&quot; alt=&quot;npm publish command output&quot; /&gt;&lt;/p&gt;

&lt;p&gt;By “manually” having to publish to npm you introduce the risk of publishing
versions that do not pass the tests (you do have tests right?!), and introduce
the possibility of inconsistencies between published versions.&lt;/p&gt;

&lt;h2 id=&quot;npm-publish&quot;&gt;npm publish&lt;/h2&gt;

&lt;p&gt;The  &lt;code class=&quot;highlighter-rouge&quot;&gt;npm publish&lt;/code&gt; (and more recently &lt;code class=&quot;highlighter-rouge&quot;&gt;npm adduser&lt;/code&gt;) commands requires some user
interaction to type in user credentials. This makes it problematic for use on
servers since there is no user there to type in the username and password.&lt;/p&gt;

&lt;p&gt;Because of this limitation some CI servers offers plugins or addons to make the
integration with npm easier for maintainers.&lt;/p&gt;

&lt;h3 id=&quot;npm-publish-for-travis-ci&quot;&gt;npm publish for Travis CI&lt;/h3&gt;

&lt;p&gt;Travis CI can automatically release your npm package to the npm registry after
a successful build. All you need to do is add the following to your
&lt;code class=&quot;highlighter-rouge&quot;&gt;.travis.yml&lt;/code&gt; configuration:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;deploy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;provider&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;npm&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;api_key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;YOUR&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;API&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;KEY&quot;&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;tags&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Also Read:&lt;/strong&gt; &lt;a href=&quot;http://docs.travis-ci.com/user/deployment/npm/&quot;&gt;npm Releasing - Travis
CI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;npm-publish-for-wercker-ci&quot;&gt;npm publish for Wercker CI&lt;/h3&gt;

&lt;p&gt;Wercker CI can automatically release your npm package to the npm registry after
a successful build. All you need to do is add the following to your
&lt;code class=&quot;highlighter-rouge&quot;&gt;wercker.yml&lt;/code&gt; configuration and add the &lt;code class=&quot;highlighter-rouge&quot;&gt;NPM_TOKEN&lt;/code&gt; environment variable:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;deploy&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;turistforeningen/npm-publish&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;You also need to add your &lt;code class=&quot;highlighter-rouge&quot;&gt;NPM_TOKEN&lt;/code&gt; as an Environment Variable to your Deploy
Pipeline in the Wercker settings page for your project.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;Also checkout:&lt;/strong&gt;
&lt;a href=&quot;https://github.com/Turistforeningen/wercker-npm-publish&quot;&gt;turistforeningen/wercker-npm-publish&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/09/20/wercker-deploy-target.png&quot; alt=&quot;Publish to npm&quot; /&gt;&lt;/p&gt;</content><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><category term="node" /><category term="npm" /><category term="jenkins" /><category term="travis" /><category term="wercker" /><summary type="html">If you are actively maintaining more than a couple of packages in the npm registry this will be a life saver for you; automatically publish new versions of your packages directly from your CI server 📡</summary></entry><entry><title type="html">Atom (RSS) feeds for GitHub Pages</title><link href="https://starefossen.github.io/post/2015/09/16/github-pages-atom-feed/" rel="alternate" type="text/html" title="Atom (RSS) feeds for GitHub Pages" /><published>2015-09-16T00:00:00+00:00</published><updated>2015-09-16T00:00:00+00:00</updated><id>https://starefossen.github.io/post/2015/09/16/github-pages-atom-feed</id><content type="html" xml:base="https://starefossen.github.io/post/2015/09/16/github-pages-atom-feed/">&lt;p&gt;GitHub recently rolled out support for automatic ATOM (RSS) feed generation for
their GitHub Pages platform. It literally only take seconds to set up and get
going!&lt;/p&gt;

&lt;!--more--&gt;

&lt;h3 id=&quot;_configyml&quot;&gt;_config.yml&lt;/h3&gt;

&lt;p&gt;Add the &lt;a href=&quot;https://github.com/jekyll/jekyll-feed&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;jekyll-feed&lt;/code&gt; gem&lt;/a&gt; to the list
of installed gems for your Jekyll blog. Make sure you have filled out &lt;code class=&quot;highlighter-rouge&quot;&gt;name&lt;/code&gt;,
&lt;code class=&quot;highlighter-rouge&quot;&gt;description&lt;/code&gt;, and &lt;code class=&quot;highlighter-rouge&quot;&gt;author&lt;/code&gt; information too.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Blog&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Name&quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Blog&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Description&quot;&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;author&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Your&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;Name&quot;&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;email&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;you@email.com&quot;&lt;/span&gt;

&lt;span class=&quot;nn&quot;&gt;...&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;gems&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;jekyll-feed&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;head&quot;&gt;&amp;lt;head&amp;gt;&lt;/h3&gt;

&lt;p&gt;Inside the &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;head&amp;gt;&lt;/code&gt; tag, add the &lt;code class=&quot;highlighter-rouge&quot;&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;feed_meta&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;err&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt; tag to
automatically add a link to your ATOM feed. This makes you ATOM feed visible to
users visiting your blog with a capable feed reader.&lt;/p&gt;

&lt;div class=&quot;language-html highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;cp&quot;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;charset=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;utf-8&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;meta&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;description&quot;&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;content=&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;{{ site.description }}&quot;&lt;/span&gt;&lt;span class=&quot;nt&quot;&gt;&amp;gt;&lt;/span&gt;

    &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- jekyll-feed link --&amp;gt;&lt;/span&gt;
    {% feed_meta %}
  &lt;span class=&quot;nt&quot;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;--testing-locally&quot;&gt;🐳  Testing Locally&lt;/h3&gt;

&lt;p&gt;You are running Docker right?! If so, just pull the &lt;a href=&quot;https://github.com/Starefossen/docker-github-pages&quot;&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;starefossen/github-pages&lt;/code&gt;
Docker Image&lt;/a&gt; and your blog
is up and running locally without having to install a single thing!&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ docker pull starefossen/github-pages
$ docker run --rm -it -v &quot;$PWD&quot;:/usr/src/app -p &quot;4000:4000&quot; starefossen/github-pages
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;ProTip™&lt;/strong&gt; Changes reloads automatically as you go when using the Docker Image!&lt;/p&gt;

&lt;h3 id=&quot;--profit&quot;&gt;💰  Profit&lt;/h3&gt;

&lt;p&gt;Commit and push you changes to GitHub and your ATOM feed is up and running in
under a minute!&lt;/p&gt;</content><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><category term="GitHub Pages" /><summary type="html">GitHub recently rolled out support for automatic ATOM (RSS) feed generation for their GitHub Pages platform. It literally only take seconds to set up and get going!</summary></entry><entry><title type="html">Recording H.264 Streams</title><link href="https://starefossen.github.io/post/2015/08/19/recording-h264-streams/" rel="alternate" type="text/html" title="Recording H.264 Streams" /><published>2015-08-19T00:00:00+00:00</published><updated>2015-08-19T00:00:00+00:00</updated><id>https://starefossen.github.io/post/2015/08/19/recording-h264-streams</id><content type="html" xml:base="https://starefossen.github.io/post/2015/08/19/recording-h264-streams/">&lt;p&gt;This is a project I did a while a go, but I never got a round to write a post
about it 😩  So here it is.  It was a ☔️ wet and cold spring in Norway (like most
of them are).  We were going on a 🚙 trip for the weekend, and I wanted to bring
some 📺 TV shows my son could watch on the way.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/08/24/trail.jpg&quot; alt=&quot;Summer marked trails in Norway&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Summer marked trails in Norway by Hans Kristian Flaatten.  Licensed under &lt;a href=&quot;https://creativecommons.org/licenses/by-sa/4.0/&quot;&gt;CC
BY-SA 4.0&lt;/a&gt;.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Here in Norway we have a public broadcasting company - the Norwegian
Broadcasting Corporation (NRK). I have had the opportunity to work with them on
UT.no - Norway’s Trip Planner - but more on that later.  NRK makes available all
of their shows through their online media player &lt;a href=&quot;https://tv.nrk.no&quot;&gt;tv.nrk.no&lt;/a&gt;
for a period of 6 to 12 months before they are taken offline.&lt;/p&gt;

&lt;p&gt;All this is well and good, except for the disability to save shows for offline
viewing.  Since we have so spotty cellular connection because of all the high
mountains and deep fjords, and streaming 200 episodes of Sesame Street is not an
economically viable option anyways, I opted for making my own offline copies.
&lt;a href=&quot;http://ffmpeg.org&quot;&gt;ffmpeg&lt;/a&gt; 🎥 to the rescue!&lt;/p&gt;

&lt;h2 id=&quot;m3u-to-mp4&quot;&gt;m3u-to-mp4&lt;/h2&gt;

&lt;p&gt;Getting the &lt;code class=&quot;highlighter-rouge&quot;&gt;m3u&lt;/code&gt;-steam was just a matter of right clicking on it in Safari and
saving to disk. Once I had the &lt;code class=&quot;highlighter-rouge&quot;&gt;m3u&lt;/code&gt; playlist file it was time to fire up
&lt;code class=&quot;highlighter-rouge&quot;&gt;ffmpeg&lt;/code&gt;, and by the way, there’s a &lt;a href=&quot;https://hub.docker.com/r/nachochip/ffmpeg/&quot;&gt;Docker Image for
that&lt;/a&gt; 😅&lt;/p&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;m3u&lt;/code&gt; is not the actual video stream itself. It is just a playlist composed of
links to several small videos that are downloaded and played in rapid succession.
ffmpeg has built in support for downloading and concatenate into one video file.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ffmpeg -i playlist.m3u -c copy -bsf:a aac_adtstoasc recording.mp4
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Here is a rundown of what the different &lt;a href=&quot;http://ffmpeg.org/ffmpeg.html&quot;&gt;cli
flags&lt;/a&gt; do:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-i playlist.m3u&lt;/code&gt; is location of the playlist file we want to record.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-c copy&lt;/code&gt; do not re-encoding the video stream since it is already the desired
format of H.264.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;-bsf:a aac_adtstoasc&lt;/code&gt; converts the audio such that it is compatible with the
&lt;code class=&quot;highlighter-rouge&quot;&gt;mp4&lt;/code&gt; container.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;recording.mp4&lt;/code&gt; is the location of the outputted recording.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;-docker-all-things&quot;&gt;🐳 Docker All Things&lt;/h3&gt;

&lt;p&gt;Since I do not install program directly on my computer any more I of course had
to run this too in a Docker container. You can check out the project on
&lt;a href=&quot;https://github.com/Starefossen/m3u-to-mp4&quot;&gt;github.com/Starefossen/m3u-to-mp4&lt;/a&gt; 🚀&lt;/p&gt;

&lt;div class=&quot;language-bash highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;docker run --rm
  -v &lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;/playlists:/playlists
  -v &lt;span class=&quot;k&quot;&gt;$(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;pwd&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;)&lt;/span&gt;/recordings:/recordings
  nachochip/ffmpeg
    -i /playlists/episode1.m3u
    -c copy
    -bsf:a aac_adtstoasc
    /recordings/episode1.mp4
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;</content><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><category term="media" /><category term="h.264" /><category term="ffmpeg" /><summary type="html">This is a project I did a while a go, but I never got a round to write a post about it 😩 So here it is. It was a ☔️ wet and cold spring in Norway (like most of them are). We were going on a 🚙 trip for the weekend, and I wanted to bring some 📺 TV shows my son could watch on the way. Summer marked trails in Norway by Hans Kristian Flaatten. Licensed under CC BY-SA 4.0.</summary></entry><entry><title type="html">Building Docker Images from remote repositories</title><link href="https://starefossen.github.io/post/2015/08/16/docker-build-remote-repo/" rel="alternate" type="text/html" title="Building Docker Images from remote repositories" /><published>2015-08-16T00:00:00+00:00</published><updated>2015-08-16T00:00:00+00:00</updated><id>https://starefossen.github.io/post/2015/08/16/docker-build-remote-repo</id><content type="html" xml:base="https://starefossen.github.io/post/2015/08/16/docker-build-remote-repo/">&lt;p&gt;I recently wanted to build a Docker Image directly form a source repository
without having to clone the repository locally &lt;em&gt;before&lt;/em&gt; building it. This turned
out to be such a neat little trick that I thought it was worth sharing.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;Inspecting what the &lt;code class=&quot;highlighter-rouge&quot;&gt;docker build&lt;/code&gt; command had to offer with regards to building
repote repositories yield an interesting parameter named &lt;code class=&quot;highlighter-rouge&quot;&gt;URL&lt;/code&gt;.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ docker build --help
&amp;gt; Usage: docker build [OPTIONS] PATH | &amp;gt;&amp;gt;&amp;gt; URL &amp;lt;&amp;lt;&amp;lt; | -
&amp;gt; Build a new image from the source code at PATH
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Consulting the &lt;a href=&quot;http://docs.docker.com/reference/commandline/build/&quot;&gt;online build
documentation&lt;/a&gt; confirmed my
suspicion that this was in fact an option to build a Docker Image directly form
a remote repository.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;The URL parameter can specify the location of a Git repository; the repository
acts as the build context.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The URL parameter also has the optional possibilities to specify a which branch,
tag, or commit sha to build, as well as the location (directory) of the
Dockerfile you want to build.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;$ docker build https://github.com/docker-library/hello-world.git#master:/
&amp;gt; Sending build context to Docker daemon 132.1 k
&amp;gt; Sending build context to Docker daemon
&amp;gt; Step 0 : FROM scratch
&amp;gt;  ---&amp;gt;
&amp;gt; Step 1 : COPY hello /
&amp;gt;  ---&amp;gt; a1e6124c9115
&amp;gt; Removing intermediate container b27bf9c2271f
&amp;gt; Step 2 : CMD /hello
&amp;gt;  ---&amp;gt; Running in 80cd51769b8e
&amp;gt;  ---&amp;gt; 3ec9c8c47f66
&amp;gt; Removing intermediate container 80cd51769b8e
&amp;gt; Successfully built 3ec9c8c47f66
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h3 id=&quot;epilogue&quot;&gt;Epilogue&lt;/h3&gt;

&lt;p&gt;I later realized that the repository is cloned locally behind the scenes which
makes that sense when you think about authentication, vpn etc to private
repositories.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;This command runs in a temporary directory on your local host. After the
command succeeds, the directory is sent to the Docker daemon as the context.
Local clones give you the ability to access private repositories using local
user credentials, VPNs, and so forth.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3 id=&quot;a-nodejs-example&quot;&gt;A Node.JS Example&lt;/h3&gt;

&lt;p&gt;If you are interested in how to build a remote repository using the Docker Remote
API with the &lt;a href=&quot;https://github.com/apocas/dockerode&quot;&gt;dockerode&lt;/a&gt; Docker client
library for Node.JS, this is how you do it:&lt;/p&gt;

&lt;p&gt;```javascript
const options = {
  t: ‘docker-library/hello-world’,
  remote: ‘https://github.com/docker-library/hello-world.git’,
};&lt;/p&gt;

&lt;p&gt;docker.buildImage(null, options, function(err, res) {
  if (err) { throw err; }&lt;/p&gt;

&lt;p&gt;res.on(‘data’, function(data) {
    console.log(data.toString());
  });
});&lt;/p&gt;</content><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><category term="docker" /><summary type="html">I recently wanted to build a Docker Image directly form a source repository without having to clone the repository locally before building it. This turned out to be such a neat little trick that I thought it was worth sharing.</summary></entry><entry><title type="html">Django Performance: POSTGIS_VERSION</title><link href="https://starefossen.github.io/post/2015/05/21/django-performance-postgis-version/" rel="alternate" type="text/html" title="Django Performance: POSTGIS_VERSION" /><published>2015-05-21T00:00:00+00:00</published><updated>2015-05-21T00:00:00+00:00</updated><id>https://starefossen.github.io/post/2015/05/21/django-performance-postgis-version</id><content type="html" xml:base="https://starefossen.github.io/post/2015/05/21/django-performance-postgis-version/">&lt;p&gt;This is the first post in a series of posts about boosting performance in the
main Django application for the &lt;a href=&quot;http://english.turistforeningen.no&quot;&gt;Norwegian Trekking
Association&lt;/a&gt; (DNT).  The application is
scheduled to serve all of DNTs 200+ official web sites with a total of 1.5
million monthly page views by the end of 2015.&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/turistforeningen/sherpa&quot;&gt;Sherpa&lt;/a&gt; is a fairly typical Django
application.  It uses Django 1.7 served through Gunicorn 1.8 via Nginx 1.9 using
memcachd 1.4 for caching and Postgres 9.3 with Postgis 2.1 as its main database.
I will try to get a another post out outlining the technical details of our
production setup soon.&lt;/p&gt;

&lt;h2 id=&quot;step-1---gathering-data&quot;&gt;Step 1 - Gathering Data&lt;/h2&gt;

&lt;p&gt;We have been measuring the response time of some key pages through our Pingdom
monitoring checks for years, and they all yielded the same average of 730ms
(originating from Europe since our servers are located in the eu-west-1 aws
region).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/05/21/response_pre.png&quot; alt=&quot;Pre Response Time&quot; title=&quot;Pre Response Time&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Other than that we had fairly little data to work with so we decided to log all
Postgres queries &lt;del&gt;longer than 300 ms&lt;/del&gt; over the weekend using the &lt;a href=&quot;http://www.postgresql.org/docs/current/static/runtime-config-logging.html#GUC-LOG-STATEMENT&quot;&gt;
log_min_duration_statement&lt;/a&gt;
method as suggested in &lt;a href=&quot;https://wiki.postgresql.org/wiki/Logging_Difficult_Queries&quot;&gt;this Postgres wiki
page&lt;/a&gt; on logging
difficult queries. &lt;strong&gt;Update:&lt;/strong&gt; We later learned that our configuration was not
entirely correct, and subsequently &lt;em&gt;all&lt;/em&gt; queries were logged. 😁  Oops!&lt;/p&gt;

&lt;h2 id=&quot;step-2---analyze&quot;&gt;Step 2 - Analyze&lt;/h2&gt;

&lt;p&gt;When we returned to work next Monday we had 10 GB of query logs to sift through.
😥.  A few days later the log file had doubled in size!  &lt;a href=&quot;https://bucardo.org/wiki/Pgsi&quot;&gt;Postgres System Impact
report (pgsi)&lt;/a&gt; to the rescue!&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;perl pgsi.pl --file=postgresql-head.log &amp;gt; pg_analyze.html
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Now we had a nicely formatted html page with all the different queries ordered
by type (SELECT, INSERT, UPDATE, etc) and system impact.  The first entry
immediately stood out as a big surprise! 😮&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;System Impact:    3.43
Mean Duration:    9.69 ms
Median Duration:  5.34 ms
Total Count:      624439
Mean Interval:    282.11 ms
Std. Deviation:   208.81 ms

SELECT postgis_lib_version()
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;The query with the most system impact of all the logged queries was a simple
call to retrieve the version of the installed PostGIS library.  How could this
be? The total count for this query indicated that it had to be executed for each
request to the application.&lt;/p&gt;

&lt;p&gt;Searching the &lt;a href=&quot;https://github.com/django/django&quot;&gt;django/django&lt;/a&gt; repository on
GitHub returned one result for a test, and one in what appeared to be the
PostGIS driver for Django / GeoDjango – no issues 😕.&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;postgis_lib_version&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;&quot;Returns the version number of the PostGIS library used with PostgreSQL.&quot;&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_get_postgis_func&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'postgis_lib_version'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Upon further inspection of &lt;a href=&quot;https://github.com/django/django/blob/master/django/contrib/gis/db/backends/postgis/operations.py#L297&quot;&gt;the
driver&lt;/a&gt;
we reviled the following function call chain: &lt;code class=&quot;highlighter-rouge&quot;&gt;postgis_lib_version()&lt;/code&gt; &amp;lt;=
&lt;code class=&quot;highlighter-rouge&quot;&gt;postgis_version_tuple()&lt;/code&gt; &amp;lt;= &lt;code class=&quot;highlighter-rouge&quot;&gt;spatial_version()&lt;/code&gt;.  In the &lt;code class=&quot;highlighter-rouge&quot;&gt;spatial_version()&lt;/code&gt;
function definition there where this comment:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Trying to get the PostGIS version because the function signatures will depend
on the version used.  The cost here is a database query to determine the
version, which can be mitigated by setting &lt;code class=&quot;highlighter-rouge&quot;&gt;POSTGIS_VERSION&lt;/code&gt; with a 3-tuple
comprising user-supplied values for the major, minor, and subminor revision of
PostGIS.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And there we had it! For each connection to the Postgres database Django’s
PostGIS driver would try to determine what version of PostGIS was installed in
order for it to communicate correctly.  This is done by executing the
&lt;code class=&quot;highlighter-rouge&quot;&gt;postgis_lib_version&lt;/code&gt; function &lt;strong&gt;unless&lt;/strong&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;POSTGIS_VERSION&lt;/code&gt; setting is set.&lt;/p&gt;

&lt;h2 id=&quot;step-3---act&quot;&gt;Step 3 - Act&lt;/h2&gt;

&lt;p&gt;We quickly added &lt;code class=&quot;highlighter-rouge&quot;&gt;POSTGIS_VERSION&lt;/code&gt; based on an environment variable to our
Django settings, and deployed to production.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;if 'POSTGIS_VERSION' in os.environ:
    POSTGIS_VERSION = os.environ['POSTGIS_VERSION']
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;step-4---profit&quot;&gt;Step 4 - Profit&lt;/h2&gt;

&lt;p&gt;Response time immediately dropped by 45%, from 730ms to 400ms. We would never
have expected these two lines of code to impact the overall performance of the
system in such a way!&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/05/21/response_post.png&quot; alt=&quot;Post Response Time&quot; title=&quot;Post Response Time&quot; /&gt;&lt;/p&gt;</content><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><category term="django" /><category term="performance" /><category term="postgis" /><category term="geodjango" /><summary type="html">This is the first post in a series of posts about boosting performance in the main Django application for the Norwegian Trekking Association (DNT). The application is scheduled to serve all of DNTs 200+ official web sites with a total of 1.5 million monthly page views by the end of 2015.</summary></entry><entry><title type="html">Testing Docker apps with Wercker</title><link href="https://starefossen.github.io/post/2015/05/19/testing-docker-apps-with-wercker/" rel="alternate" type="text/html" title="Testing Docker apps with Wercker" /><published>2015-05-19T00:00:00+00:00</published><updated>2015-05-19T00:00:00+00:00</updated><id>https://starefossen.github.io/post/2015/05/19/testing-docker-apps-with-wercker</id><content type="html" xml:base="https://starefossen.github.io/post/2015/05/19/testing-docker-apps-with-wercker/">&lt;p&gt;Wercker is a free and hosted continuous delivery platform with a lot of
flexibility.  Wercker offers everything you would expect from a modern CI
service, and they recently announced full support for the Docker container
runtime.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/uploads/2015/05/19/wercker.png&quot; alt=&quot;Wercker Promo&quot; title=&quot;Wercker Promo&quot; /&gt;&lt;/p&gt;

&lt;!--more--&gt;

&lt;p&gt;The Wercker platform has two modes (known as stacks) to run applications;
&lt;code class=&quot;highlighter-rouge&quot;&gt;Classic&lt;/code&gt; using custom made pre-built containers, and &lt;code class=&quot;highlighter-rouge&quot;&gt;Ewok&lt;/code&gt; using the Docker
container runtime.  If you don’t know what Docker is, I suggest you read &lt;a href=&quot;http://docs.docker.com/introduction/understanding-docker/&quot;&gt;this
article&lt;/a&gt; in order to
get a basic understanding of Docker.&lt;/p&gt;

&lt;p&gt;With the &lt;code class=&quot;highlighter-rouge&quot;&gt;Ewok&lt;/code&gt; stack your application is run using Docker containers from
Docker Hub - linked together just as you would have locally or in production.
Yay for identical environments!!&lt;/p&gt;

&lt;h2 id=&quot;boxes&quot;&gt;Boxes&lt;/h2&gt;

&lt;p&gt;You application code is run in a primary container (known as a &lt;code class=&quot;highlighter-rouge&quot;&gt;box&lt;/code&gt;).  In Ewok
the name this &lt;code class=&quot;highlighter-rouge&quot;&gt;box&lt;/code&gt; is the name of a &lt;a href=&quot;http://docs.docker.com/terms/container/&quot;&gt;Docker
image&lt;/a&gt; from &lt;a href=&quot;https://hub.docker.com/&quot;&gt;Docker
Hub&lt;/a&gt; + an optional image tag.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;box&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;node:0.10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;services&quot;&gt;Services&lt;/h2&gt;

&lt;p&gt;Adhering to the &lt;a href=&quot;https://docs.docker.com/articles/dockerfile_best-practices/&quot;&gt;Docker best
practices&lt;/a&gt; you
should only run a single process per container.  If your application depends on
another service (such as a database or a cache) you can link multiple containers
together using &lt;code class=&quot;highlighter-rouge&quot;&gt;services&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The services directive looks just like a box, but you can define as many of them
as you like.  They will automatically be linked together with your box before your
application starts.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mongo:2.6&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis:2.8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;When Wercker starts, any service you have defined will be started and &lt;a href=&quot;http://docs.docker.com/userguide/dockerlinks/&quot;&gt;linked
together&lt;/a&gt; with your box
automatically.  The IP-address of a given service will be available as a
hostname corresponding to the name of the image.  Any ports exposed by the
container can be used as they are.&lt;/p&gt;

&lt;p&gt;Wercker also has support for &lt;a href=&quot;http://devcenter.wercker.com/docs/services/advanced-services.html&quot;&gt;advanced service
configurations&lt;/a&gt;,
such as injecting custom environment variables and altering the startup command.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;id&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mariadb&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;env&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
          &lt;span class=&quot;s&quot;&gt;MYSQL_ROOT_USERNAME&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;myusername&lt;/span&gt;
          &lt;span class=&quot;s&quot;&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mysecretpassword&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;build-steps&quot;&gt;Build Steps&lt;/h2&gt;

&lt;p&gt;Your containers are started and linked together, and it is time to run the
build. This is done with one, or many, build steps. Wercker has an
astonishingly amount of pre-defined build steps for every language in their
step registry.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;build:
    steps:
        - npm-install
        - npm-test
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;You can also submit your own build steps to the step registry, or script them in
your build configuration using the &lt;code class=&quot;highlighter-rouge&quot;&gt;script&lt;/code&gt; build step like this.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;build:
    steps:
        - script:
            name: my custom script
            code: |
                # some command
                # more command
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;putting-it-all-togheter&quot;&gt;Putting it all togheter&lt;/h2&gt;

&lt;p&gt;And there you have it; &lt;code class=&quot;highlighter-rouge&quot;&gt;box&lt;/code&gt;, &lt;code class=&quot;highlighter-rouge&quot;&gt;services&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;build steps&lt;/code&gt; all go into one file
in your project repository named &lt;code class=&quot;highlighter-rouge&quot;&gt;wercker.yml&lt;/code&gt;.  This is your Wercker build
configuration file.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;box&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;node:0.10&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;services&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;mongo:2.6&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;redis:2.8&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;build&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;steps&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;npm-install&lt;/span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;npm-test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;

&lt;h2 id=&quot;getting-started&quot;&gt;Getting Started&lt;/h2&gt;

&lt;p&gt;You can read more about the Wercker platform at
&lt;a href=&quot;http://devcenter.wercker.com&quot;&gt;devcenter.wercker.com&lt;/a&gt;, or check out their GitHub
repo &lt;a href=&quot;https://github.com/wercker/docs&quot;&gt;werkcer/docs&lt;/a&gt; where you can search
through all of their documentation which is nicely formatted in Markdown.&lt;/p&gt;

&lt;p&gt;Wercker also provides a lot of example projects to get you started.  Check them
out as well:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/wercker/getting-started-python&quot;&gt;Python Wercker Example&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/wercker/getting-started-golang&quot;&gt;Go Wercker Example&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/wercker/getting-started-nodejs&quot;&gt;Node.JS Wercker Example&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/wercker/getting-started-ruby&quot;&gt;Ruby Wercker Example&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Hans Kristian Flaatten</name><email>hans@starefossen.com</email></author><category term="docker" /><category term="testing" /><category term="ci" /><summary type="html">Wercker is a free and hosted continuous delivery platform with a lot of flexibility. Wercker offers everything you would expect from a modern CI service, and they recently announced full support for the Docker container runtime.</summary></entry></feed>