<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>GitLab</title>
  <id>https://about.gitlab.com/blog/</id>
  <link href="https://about.gitlab.com/blog/"/>
  <updated>2017-01-10T00:00:00+00:00</updated>
  <author>
    <name>Blog Author</name>
  </author>
  <entry>
    <title>GitLab 8.15.4, 8.14.6, and 8.13.11 Released</title>
    <link rel="alternate" href="https://about.gitlab.com/2017/01/10/gitlab-8-dot-15-dot-4-released/"/>
    <id>https://about.gitlab.com/2017/01/10/gitlab-8-dot-15-dot-4-released/</id>
    <published>2017-01-10T00:00:00+00:00</published>
    <updated>2017-01-10T00:00:00+00:00</updated>
    <author>
      <name>Douglas Barbosa Alexandre</name>
    </author>
    <content type="html">
&lt;p&gt;Today we are releasing versions 8.15.4, 8.14.6, and 8.13.11 for GitLab Community
Edition (CE) and Enterprise Edition (EE).&lt;&#x2F;p&gt;

&lt;p&gt;These versions contain important security fixes, and we recommend that all
affected GitLab installations be upgraded to one of these versions.
Additionally, the 8.15.4 version resolves a number of regressions and bugs in
last month&#x27;s &lt;a href=&quot;&#x2F;2016&#x2F;12&#x2F;22&#x2F;gitlab-8-15-released&quot;&gt;8.15 release&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;



&lt;h2 id=&quot;security-fixes-in-8154-8146-and-81311&quot;&gt;Security fixes in 8.15.4, 8.14.6 and 8.13.11&lt;&#x2F;h2&gt;

&lt;h3 id=&quot;cross-site-scripting-vulnerability-in-turbolinks&quot;&gt;Cross-Site Scripting Vulnerability in Turbolinks&lt;&#x2F;h3&gt;

&lt;p&gt;These releases include a &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;25842&quot;&gt;patch&lt;&#x2F;a&gt; for a cross-site scripting vulnerability in the
Ruby gem Turbolinks. Versions 2.5.4 and earlier of Turbolinks are vulnerable to
cross-site scripting attacks when loading attachments with HTML content types.
We&#x27;ve released a temporary GitLab fork of Turbolinks while we make a decision
on migrating to Turbolinks version 5 or abandoning Turbolinks.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;cross-site-scripting-vulnerability-in-gitlab-markup&quot;&gt;Cross-Site Scripting Vulnerability in GitLab-Markup&lt;&#x2F;h3&gt;

&lt;p&gt;Also included with these releases is a &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;26411&quot;&gt;patch&lt;&#x2F;a&gt; for a cross-site scripting
vulnerability in the GitLab Markup gem, forked from the GitHub Markup gem.
This vulnerability can be exploited by tricking users into clicking on
ReStructuredText files that specify a raw HTML format. Thanks to Jason Ritzke
(@Rtzq0) for reporting this vulnerability.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;additional-changes-in-8154&quot;&gt;Additional changes in 8.15.4&lt;&#x2F;h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Use #parts instead of #part to read all the parts of the Message. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8507&quot;&gt;!8507&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Re-add Google Cloud Storage as a backup strategy (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8481&quot;&gt;!8481&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Don&#x27;t instrument 405 Grape calls (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8445&quot;&gt;!8445&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Speed up group milestone index by passing group_id to IssuesFinder (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8363&quot;&gt;!8363&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; With Gitea v1.0.0, notes are imported (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8298&quot;&gt;!8298&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Make successful pipeline emails off for watchers (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8176&quot;&gt;!8176&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;Omnibus GitLab:&lt;&#x2F;strong&gt; Switch to using gitlab-psql for query against db (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;omnibus-gitlab&#x2F;merge_requests&#x2F;1197&quot;&gt;!1197&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;Omnibus GitLab:&lt;&#x2F;strong&gt; Adding &#x2F;bin&#x2F;sh to command for analyze_new_cluster.sh call (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;omnibus-gitlab&#x2F;merge_requests&#x2F;1194&quot;&gt;!1194&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;upgrade-barometer&quot;&gt;Upgrade barometer&lt;&#x2F;h2&gt;

&lt;p&gt;These versions have no migrations and should not require any downtime.&lt;&#x2F;p&gt;

&lt;p&gt;Please be aware that by default the Omnibus packages will stop, run migrations,
and start again, no matter how “big” or “small” the upgrade is. This behavior
can be changed by adding a &lt;a href=&quot;http:&#x2F;&#x2F;doc.gitlab.com&#x2F;omnibus&#x2F;update&#x2F;README.html&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;gitlab&#x2F;skip-auto-migrations&lt;&#x2F;code&gt;
file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;updating&quot;&gt;Updating&lt;&#x2F;h2&gt;

&lt;p&gt;To update, check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;update&#x2F;&quot;&gt;update page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;enterprise-edition&quot;&gt;Enterprise Edition&lt;&#x2F;h2&gt;

&lt;p&gt;Interested in GitLab Enterprise Edition? Check out the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;features&#x2F;#enterprise&quot;&gt;features exclusive to
EE&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Access to GitLab Enterprise Edition is included with a &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;pricing&#x2F;&quot;&gt;subscription&lt;&#x2F;a&gt;.
No time to upgrade GitLab yourself? Subscribers receive upgrade and installation
services.&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;default-blog-image.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>Why We Use Personas in Product Development</title>
    <link rel="alternate" href="https://about.gitlab.com/2017/01/09/the-importance-of-ux-personas/"/>
    <id>https://about.gitlab.com/2017/01/09/the-importance-of-ux-personas/</id>
    <published>2017-01-09T00:00:00+00:00</published>
    <updated>2017-01-09T00:00:00+00:00</updated>
    <author>
      <name>Sarah O’Donnell</name>
    </author>
    <content type="html">
&lt;p class=&quot;alert alert-orange&quot; style=&quot;background-color: rgba(252,163,38,.3); border-color: rgba(252,163,38,.3); color: rgb(226,67,41) !important; text-align: center;&quot;&gt;Catch our upcoming webcast &amp;nbsp;&amp;nbsp;&lt;i class=&quot;fa fa-gitlab&quot; style=&quot;color:rgb(107,79,187); font-size:.85em&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;i&gt; &amp;nbsp;&amp;nbsp;&lt;strong&gt;Designing For the Modern Developer&lt;&#x2F;strong&gt; &amp;nbsp;&amp;nbsp;&lt;i class=&quot;fa fa-gitlab&quot; style=&quot;color:rgb(107,79,187); font-size:.85em&quot; aria-hidden=&quot;true&quot;&gt;&lt;&#x2F;i&gt;
&amp;nbsp;&amp;nbsp;on January 19. &lt;a style=&quot;color: rgb(107,79,187);&quot; href=&quot;https:&#x2F;&#x2F;page.gitlab.com&#x2F;uxlivestream_landingpage.html?utm_medium=blog&amp;amp;utm_source=blog&amp;amp;utm_campaign=ux+webcast&amp;amp;utm_content=register+now+button&quot;&gt;Register here&lt;&#x2F;a&gt;!&lt;&#x2F;p&gt;

&lt;p&gt;When developing a product, it’s easy to assume that users are just like ourselves. If we rely on our assumptions to lead what and how we develop, there is a risk of creating a product that may only work for a segment of users. A more analytical approach is necessary for understanding the needs of all users, which is paramount to successful user experience (UX).&lt;&#x2F;p&gt;



&lt;p&gt;Every month, we piece together the jigsaw of new features and design tweaks, and all the tools that ship with GitLab, ensuring that each change fits within our vision and understanding of user needs. To help with this task, we&#x27;re &lt;a href=&quot;https:&#x2F;&#x2F;www.surveymonkey.co.uk&#x2F;r&#x2F;GitLab&quot;&gt;developing&lt;&#x2F;a&gt; personas that will allow us to relate to different types of users and subsequently predict their behavior. This is essential for our key challenge of creating a unified experience for teams big and small, so they can stay focused on their own goals. In this post, I&#x27;ll explore some of the reasons to use personas in product development.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;what-is-a-persona&quot;&gt;What is a persona?&lt;&#x2F;h2&gt;

&lt;p&gt;Personas are fictional characters created to represent the major needs and expectations of the different types of users that use a website, product or service. A persona typically has a name, a picture, and a background, along with demographic information such as age, highest level of education and work experience.&lt;&#x2F;p&gt;

&lt;p&gt;Imagine the last time you were engrossed in a television series. It’s likely that you connected with one or more of the leading characters because you could understand - and on some level, relate to - their emotions, responses and actions in a given situation. You probably discussed the television series with a friend and together, you may have guessed at future plot lines based on the events that had occurred so far in the series. Personas work in a similar way.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;what-can-personas-reveal&quot;&gt;What can personas reveal?&lt;&#x2F;h2&gt;

&lt;p&gt;A good persona generates empathy for users by putting a “human face” on data. Its aim is to summarize and share research findings with anybody contributing towards the success of the product. It’s easier for an individual (regardless of their job title) to understand a persona that collectively represents the motivations, frustrations and goals of thousands of users, than it is to trawl through days, or even months&#x27; worth, of research findings.&lt;&#x2F;p&gt;

&lt;p&gt;Personas provide a clear understanding of why and how a person is using your product, and documents any pain points they experience, both in the context of using the product and the environment in which the product is used. Finally, it summarizes their goals: what do they hope to solve or achieve by using your product? This information is normally collected by using both qualitative (surveys, user interviews, etc.) and quantitative research techniques (web analytics). While a persona itself is fictional, it is formed using factual data to provide a realistic model of user needs.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;how-do-personas-change-the-way-teams-work&quot;&gt;How do personas change the way teams work?&lt;&#x2F;h2&gt;

&lt;p&gt;Personas promote further discussions within a team about how a user would interact with a proposed idea. By internalizing the user, we adopt their mentality and form solutions based on what’s best for the user and their given situation.&lt;&#x2F;p&gt;

&lt;p&gt;By defining personas, there is a well-documented, clear focus on who the product is for, which stops users’ needs from being altered to suit an idea or concept. A product manager may use personas to validate and prioritize features, whereas a designer may use them to determine the overall visual style of a product. When everybody within a team has a shared understanding of users, disagreements surrounding product development are reduced, as there is greater consensus about what is right for users.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;what-is-the-state-of-personas-at-gitlab&quot;&gt;What is the state of personas at GitLab?&lt;&#x2F;h2&gt;

&lt;p&gt;At GitLab, we are in the early stages of discovering who our personas are. If you want to make sure that your needs and expectations as a user are met, then you can help us by &lt;a href=&quot;https:&#x2F;&#x2F;www.surveymonkey.co.uk&#x2F;r&#x2F;GitLab&quot;&gt;completing our survey&lt;&#x2F;a&gt; and sharing your views.&lt;&#x2F;p&gt;

&lt;p&gt;The qualitative data from this survey will be analyzed and categorized by coding similar responses. A code is a word or short phrase that describes a respondent’s answer, and serves to condense the information collected into key themes and topics. We&#x27;ll use statistical analysis to summarize and describe the quantitative data (close-ended questions) in the survey, and we can interpret the collective findings to form a basis for our personas.&lt;&#x2F;p&gt;

&lt;p&gt;Because it has some limitations, we interpret survey data alongside user interviews and web analytics. This helps us compare findings and make the strongest conclusions possible. We&#x27;re looking forward to learning about how you use GitLab!&lt;&#x2F;p&gt;

&lt;p&gt;&lt;em&gt;Tweet &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gitlab&quot;&gt;@GitLab&lt;&#x2F;a&gt; and check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;jobs&#x2F;&quot;&gt;job openings&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;p&gt;Image: &quot;&lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;sidneiensis&#x2F;14109676698&#x2F;in&#x2F;photolist-nuPMiU-ryzBme-aBf95E-bhuWaX-dWMhVA-9hrsBU-cwgKsS-dWFxBg-6HobWf-9s5y2P-fuV8He-eAEQoD-fvRBo6-ftDY1D-97v8g5-MxynM-3fawkY-nuJMy8-97s9px-fuVaex-qYfefX-bAojmQ-fyrNcH-aCR5c2-7XA7iP-cyqD8N-49HGS-8oVQhu-pt2tn1-74753h-2zT9w3-7PqwNc-7476K7-dN1rGL-fsXKRX-kUua-746WoE-8fabaP-oJPHDc-a6TGaF-eDSoXL-5bJjta-g6njp8-ftDXdV-8XKrHW-g2H8EV-dMUTPp-9s5xpn-ftd733-brt87D&quot;&gt;Curves&lt;&#x2F;a&gt;&quot; by &lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;sidneiensis&#x2F;&quot;&gt;Jason Tong&lt;&#x2F;a&gt; is licensed under &lt;a href=&quot;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by&#x2F;2.0&#x2F;legalcode&quot;&gt;CC BY 2.0&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;!-- Identifiers, in alphabetical order --&gt;

&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;blogimages&#x2F;the-importance-of-ux-personas.jpg&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>GitLab 8.15.3 released</title>
    <link rel="alternate" href="https://about.gitlab.com/2017/01/06/gitlab-8-dot-15-dot-3-released/"/>
    <id>https://about.gitlab.com/2017/01/06/gitlab-8-dot-15-dot-3-released/</id>
    <published>2017-01-06T00:00:00+00:00</published>
    <updated>2017-01-06T00:00:00+00:00</updated>
    <author>
      <name>Douglas Barbosa Alexandre</name>
    </author>
    <content type="html">
&lt;p&gt;Today we are releasing version 8.15.3 for GitLab Community Edition (CE) and
Enterprise Edition (EE).&lt;&#x2F;p&gt;

&lt;p&gt;This version resolves a number of regressions and bugs in the &lt;a href=&quot;&#x2F;2016&#x2F;12&#x2F;22&#x2F;gitlab-8-15-released&quot;&gt;recent 8.15
release&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;This version includes a migration which will &lt;strong&gt;rename projects&lt;&#x2F;strong&gt; that became
inaccessible in version 8.15 due to reserved names. We would have preferred
to do this in the monthly release rather than a patch release, but weighed
against inaccessible projects we believe it&#x27;s a reasonable tradeoff.&lt;&#x2F;p&gt;



&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Rename projects with reserved path names (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8234&quot;&gt;!8234&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Whitelist next project names: assets, profile, public (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8470&quot;&gt;!8470&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix 500 error when visit group from admin area if group name contains dot (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8342&quot;&gt;!8342&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix GFM dropdown not showing at beginning of new lines (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8338&quot;&gt;!8338&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix error 500 renaming group. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8201&quot;&gt;!8201&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Pipeline stylesheets changes (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8224&quot;&gt;!8224&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix cross-project references copy to include the project reference (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8232&quot;&gt;!8232&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Revert MattermostNotificationService and SlackNotificationService (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8240&quot;&gt;!8240&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Use stable icon for Mattermost integration (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8252&quot;&gt;!8252&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Resolve &quot;Labels are not consistent on all pages&quot; (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8256&quot;&gt;!8256&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix 500 errors when creating a user with identity via API (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8442&quot;&gt;!8442&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Remove bottom border from Issuable titles (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8278&quot;&gt;!8278&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix project hooks params (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8425&quot;&gt;!8425&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Gitlab::LDAP::Person uses LDAP attributes configuration (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8418&quot;&gt;!8418&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; LDAP attributes needs default values (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8465&quot;&gt;!8465&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Removes invalid HTML and unneeded CSS to prevent shaking in the pipelines tab (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8411&quot;&gt;!8411&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; API: extern_uid is a string (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8404&quot;&gt;!8404&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Increases pipeline graph drowdown width in order to prevent strange position (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8399&quot;&gt;!8399&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Copy, don&#x27;t move uploaded avatar files (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8396&quot;&gt;!8396&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Add API route slack slash commands (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8362&quot;&gt;!8362&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fixed regression of note-headline-light where it was always placed on 2 lines (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8348&quot;&gt;!8348&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix left border in session tabs (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8346&quot;&gt;!8346&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix unclear closing issue behaviour on Merge Request show page (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8345&quot;&gt;!8345&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix grammar error in text about mentioned issues (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8337&quot;&gt;!8337&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Only limit container width on issues &amp;amp; MRs within fixed-width container (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8330&quot;&gt;!8330&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Cache project authorizations even when user has access to zero projects (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8327&quot;&gt;!8327&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;EE:&lt;&#x2F;strong&gt; Only fetch repo once on secondary after push (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ee&#x2F;merge_requests&#x2F;1015&quot;&gt;!1015&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;EE:&lt;&#x2F;strong&gt; Disable LDAP permission override in project members edit list (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ee&#x2F;merge_requests&#x2F;1018&quot;&gt;!1018&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;upgrade-barometer&quot;&gt;Upgrade barometer&lt;&#x2F;h2&gt;

&lt;p&gt;This version includes a post-deploy migration and should not require
any downtime.&lt;&#x2F;p&gt;

&lt;p&gt;We recommend clearing the GitLab cache (&lt;code&gt;gitlab-rake cache:clear&lt;&#x2F;code&gt;) after
upgrading to 8.15.3 due to the renamed projects.&lt;&#x2F;p&gt;

&lt;p&gt;Please be aware that by default the Omnibus packages will stop, run migrations,
and start again, no matter how “big” or “small” the upgrade is. This behavior
can be changed by adding a &lt;a href=&quot;http:&#x2F;&#x2F;doc.gitlab.com&#x2F;omnibus&#x2F;update&#x2F;README.html&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;gitlab&#x2F;skip-auto-migrations&lt;&#x2F;code&gt;
file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;updating&quot;&gt;Updating&lt;&#x2F;h2&gt;

&lt;p&gt;To update, check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;update&#x2F;&quot;&gt;update page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;enterprise-edition&quot;&gt;Enterprise Edition&lt;&#x2F;h2&gt;

&lt;p&gt;Interested in GitLab Enterprise Edition? Check out the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;features&#x2F;#enterprise&quot;&gt;features exclusive to
EE&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Access to GitLab Enterprise Edition is included with a &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;pricing&#x2F;&quot;&gt;subscription&lt;&#x2F;a&gt;.
No time to upgrade GitLab yourself? Subscribers receive upgrade and installation
services.&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;default-blog-image.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>Prometheus and GitLab</title>
    <link rel="alternate" href="https://about.gitlab.com/2017/01/05/prometheus-and-gitlab/"/>
    <id>https://about.gitlab.com/2017/01/05/prometheus-and-gitlab/</id>
    <published>2017-01-05T00:00:00+00:00</published>
    <updated>2017-01-05T00:00:00+00:00</updated>
    <author>
      <name>Mark Pundsack</name>
    </author>
    <content type="html">
&lt;p&gt;A little while ago, we presented a first draft of our vision for monitoring within GitLab. We &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;handbook&#x2F;#values&quot;&gt;value transparency&lt;&#x2F;a&gt;, so see below for the recorded video and transcript of the presentation, or view the &lt;a href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;presentation&#x2F;d&#x2F;12SDArWFfr8fGOZEOqUOwn7NMwfuGKBeS1KLJxtBVyMM&#x2F;edit?usp=sharing&quot;&gt;slides&lt;&#x2F;a&gt; directly. Please do give us your feedback on any of the linked issues!&lt;&#x2F;p&gt;



&lt;figure class=&quot;video_container&quot;&gt;
  &lt;iframe src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;NFPGtbQfL1A&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt; &lt;&#x2F;iframe&gt;
&lt;&#x2F;figure&gt;

&lt;h2 id=&quot;gitlab-monitoring-vision-01&quot;&gt;GitLab Monitoring Vision 0.1&lt;&#x2F;h2&gt;

&lt;p&gt;Thanks everyone for joining. Just to level set: This call is to go over a first draft of our vision for monitoring within GitLab. A version 0.1 of the vision, if you will. I’m presenting it so Sid and others can ask questions and critique it, and to share more broadly. If you’re looking for a polished presentation about a well-defined product, this is the wrong place. :)&lt;&#x2F;p&gt;

&lt;p&gt;I’ll start by talking about a potential minimum viable product (MVP), and then discuss future directions, and finally open it up to Q&amp;amp;A.&lt;&#x2F;p&gt;

&lt;p&gt;And if you want to play along at home, here’s a link to your personalized &lt;a href=&quot;http:&#x2F;&#x2F;bit.ly&#x2F;2hP4xTn&quot;&gt;buzzword bingo card&lt;&#x2F;a&gt; for the presentation.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;minimum-viable-product-mvp&quot;&gt;Minimum Viable Product (MVP)&lt;&#x2F;h2&gt;
&lt;h3 id=&quot;use-prometheus-to-monitor-gitlab-installation&quot;&gt;Use Prometheus to Monitor GitLab Installation&lt;&#x2F;h3&gt;

&lt;p&gt;So the first step is to add &lt;a href=&quot;https:&#x2F;&#x2F;prometheus.io&#x2F;&quot;&gt;Prometheus&lt;&#x2F;a&gt; to monitor GitLab installations themselves. I won’t go into details here; and I believe &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-com&#x2F;marketing&#x2F;issues&#x2F;594&quot;&gt;Pablo will be giving a talk about how we’re using it&lt;&#x2F;a&gt;. But in short, Prometheus is an open source monitoring solution. We’ve been using it internally here, and we’re going to bundle it up with GitLab CE so you can use it to monitor your own instances of GitLab.&lt;&#x2F;p&gt;

&lt;p&gt;Meta issue: &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-com&#x2F;infrastructure&#x2F;issues&#x2F;589&quot;&gt;gitlab-com&#x2F;infrastructure&#x2F;issues&#x2F;589&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

&lt;p&gt;Related issues:&lt;&#x2F;p&gt;
&lt;ol&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-workhorse&#x2F;issues&#x2F;61&quot;&gt;Expose service metrics via Prometheus&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-com&#x2F;infrastructure&#x2F;issues&#x2F;543&quot;&gt;Monitor CI end to end with prometheus&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-com&#x2F;infrastructure&#x2F;issues&#x2F;414&quot;&gt;Build public monitoring infrastructure&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;omnibus-gitlab&#x2F;issues&#x2F;1481&quot;&gt;Bundle Prometheus with GitLab CE&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-com&#x2F;infrastructure&#x2F;issues&#x2F;760&quot;&gt;Build High Available (Federated) prometheus monitoring solution&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;

&lt;p&gt;Here’s a couple screenshots I cribbed from some of those issues. Again, I’m not going to go into detail here. These are fairly traditional, if not ugly, dashboards using Prometheus and Grafana.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;monitoring&#x2F;sidekiq-stats.png&quot; alt=&quot;Sidekiq stats&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;monitoring&#x2F;cpu-usage.png&quot; alt=&quot;CPU Usage&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;mvp3&quot;&gt;MVP+3&lt;&#x2F;h2&gt;

&lt;h3 id=&quot;web-application-monitoring&quot;&gt;Web Application Monitoring&lt;&#x2F;h3&gt;

&lt;p&gt;I kind of tongue-in-cheek called this MVP+3, but after some number of iterations, the next &lt;strong&gt;major&lt;&#x2F;strong&gt; step is to &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;23841&quot;&gt;use Prometheus to monitor end-user applications&lt;&#x2F;a&gt;. Ideally, providing a &lt;a href=&quot;https:&#x2F;&#x2F;newrelic.com&#x2F;&quot;&gt;New Relic&lt;&#x2F;a&gt;-like experience. Maybe it’s more accurate to say &lt;a href=&quot;https:&#x2F;&#x2F;devcenter.heroku.com&#x2F;articles&#x2F;metrics&quot;&gt;Heroku-like monitoring&lt;&#x2F;a&gt; experience. New Relic does TONS of things we won’t touch for a long time, if ever. I believe there’s always a place for dedicated monitoring solutions that go deep. Our unique value won’t be in the deepness of the monitoring, it’ll be in the integration of monitoring into the rest of the experience. That may not be apparent in the initial release, but will show up later.&lt;&#x2F;p&gt;

&lt;p&gt;MVP focuses on:&lt;&#x2F;p&gt;
&lt;ul&gt;
  &lt;li&gt;Limit to applications on Kubernetes&lt;&#x2F;li&gt;
  &lt;li&gt;Response: Throughput, latency, errors&lt;&#x2F;li&gt;
  &lt;li&gt;Resource: CPU, Memory, I&#x2F;O&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;Initially we’ll focus on Kubernetes because that’s where we’re placing a few bets and installing Prometheus into every permutation of hardware is just too much to tackle. So to keep scope smaller, we’ll focus on Kubernetes.&lt;&#x2F;p&gt;

&lt;p&gt;We’ll start by measuring throughput, latency (or response time), and error rates. I’m calling this response monitoring, and it’s the highest value we can deliver that works for monitoring any web stack.&lt;&#x2F;p&gt;

&lt;p&gt;But measuring resources such as CPU, memory, and I&#x2F;O might be easier for an MVP, so I’m keeping that open. Kubernetes may make some parts of that easier, but others harder. I don’t believe we should do all of this for an MVP, so my preference would be the web response side of things. The thinking goes: if one of the resources are constrained, say memory is entering swap too much, then that will show up as latency in the system. So I’d rather observe the material impact to the user directly. Unfortunately that means you don’t see anything until it’s already an impact. And knowing that latency is bad or error rates are up doesn’t help you debug the situation. That’s where resource monitoring can be useful. But still, as a first step, I want to know how my users are impacted and THEN find a way to debug it, at which point I may very well fire up New Relic to do more powerful analysis.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;monitoring-alert-on-merge-request&quot;&gt;Monitoring Alert on Merge Request&lt;&#x2F;h3&gt;

&lt;p&gt;So to show how we’re thinking of integrating monitoring, here’s a merge request, that has already been merged and deployed to production. Because we’ve got monitoring, GitLab noticed that memory usage increased right after the deploy, so we get a message right on the merge request.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;monitoring&#x2F;merge-request__performance--inline-v03.png&quot; alt=&quot;Monitoring alert on merge request&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;Let’s zoom in a little more. We see the alert, plus some summary information, telling you the memory usage increased from 114MB to 127MB, and a little spark line so you can see it graphically. Maybe we’d add a percent increase to make it more concrete. Of course, we’d also send an email notification of this alert, to the author of the actual changes about the impact. That way, this isn’t just an ops problem, the person or people most likely to be be able to deal with it know as soon as possible.
Now let’s click through and see more details.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;monitoring-dashboard&quot;&gt;Monitoring Dashboard&lt;&#x2F;h3&gt;

&lt;p&gt;So now we see something a little more traditional. This is an early mockup of how a monitoring dashboard could appear. Note even in this early stage, we’ve got lines showing when deploys happened, to help identify code changes that impacted performance. Maybe hovering over them would show a list of merge requests that were included in that deploy.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;monitoring&#x2F;environments__monitoring.png&quot; alt=&quot;Monitoring dashboard&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;This dashboard would be available for all of your environments: production, staging, and review apps. Or maybe you’d only want to install it for production environments. I’m not sure yet.
The point is that monitoring is an essential part of environments, deployments, and MRs.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;deployment-history&quot;&gt;Deployment History&lt;&#x2F;h3&gt;

&lt;p&gt;This is a screenshot cribbed from New Relic, but I could imagine some of this information show up on our deployment history pages.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;monitoring&#x2F;deploy-history-e747cf6fa6b33dd414e8099294091dca.png&quot; alt=&quot;Deployment history&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;future&quot;&gt;Future&lt;&#x2F;h2&gt;

&lt;h3 id=&quot;monitoring&quot;&gt;Monitoring++&lt;&#x2F;h3&gt;
&lt;ul&gt;
  &lt;li&gt;Response monitoring (throughput, latency, errors)&lt;&#x2F;li&gt;
  &lt;li&gt;Resource monitoring (CPU, memory, IO)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;25555&quot;&gt;Status monitoring&lt;&#x2F;a&gt; (e.g. Pingdom, up&#x2F;down&#x2F;uptime, bad MR)&lt;&#x2F;li&gt;
  &lt;li&gt;Application performance monitoring (APM) (stack-aware, endpoint-aware, code-aware, db-aware)&lt;&#x2F;li&gt;
  &lt;li&gt;End-user experience monitoring (measured at the browser)&lt;&#x2F;li&gt;
  &lt;li&gt;User metrics&#x2F;analytics (e.g. clicks, flows, funnels, a&#x2F;b testing)&lt;&#x2F;li&gt;
  &lt;li&gt;User-defined &#x2F; business metrics (signups, conversions, revenue)&lt;&#x2F;li&gt;
  &lt;li&gt;Integrated deeply, across the developer experience&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;So the future holds an infinite set of possibilities, but I’ll talk about a few directions I’d like to consider moving into.&lt;&#x2F;p&gt;

&lt;p&gt;First, there’s more to flesh out in response and resource monitoring, covering whatever we don’t ship in the MVP, and going beyond.&lt;&#x2F;p&gt;

&lt;p&gt;Then there’s status monitoring. Think &lt;a href=&quot;https:&#x2F;&#x2F;www.pingdom.com&#x2F;&quot;&gt;Pingdom&lt;&#x2F;a&gt;, which tracks whether your app is responding to a certain HTTP request to know if it’s “up” or “down”, and then alerting on that, and reporting uptime. The linked issue describes an MVP that just checks a URL after each deploy to see if your merge request borked the server or not. I have no idea yet what role Prometheus may play here.&lt;&#x2F;p&gt;

&lt;p&gt;Then there’s the broader application performance monitoring, which really is a superset of these other pieces, but I’m breaking it out to differentiate monitoring that usually requires your code to be instrumented with a client library installed in your application; like a Gem file or an npm module. Generally, it’s language, framework, and stack aware, can analyze code paths, and even profile database SQL queries.&lt;&#x2F;p&gt;

&lt;p&gt;The next level most APM companies go to is end-user experience monitoring; measuring latency at the browser so it includes the entire trip over the interwebs, and including the time to finish asynchronously loading all Javascript and actually rendering the web page. This gives a truer, and often much scarier, view of the performance of your app.&lt;&#x2F;p&gt;

&lt;p&gt;Then there’s user metrics&#x2F;analytics. Clicks, flows, and funnels.&lt;&#x2F;p&gt;

&lt;p&gt;Lastly, we’ve got user-defined or business metrics like signups, conversions, revenue, or really any action that you determine is important for your business success, or just fun to watch.&lt;&#x2F;p&gt;

&lt;p&gt;Now, I’ve pretty much just defined the entirety of several monitoring industries. Obviously we’re unlikely to be best-of-breed in all of these. At least not in the next release or two. So again, the focus really is how we can provide the biggest bang-for-buck, the 20% effort that delivers 80% of the value, and really leverage our unique value, and that’s in our deep integration; making everything easier to use because it’s already there, and more impactful because it’s integrated across the experience. Anyone can show a graph of performance, where you can see that deploy 123 of merge request XYZ caused a problem, but alerting right on the merge request itself, right after deploying it, and emailing the authors of the actual changes about their impact, well, that’s just the tip of the iceberg of how monitoring could permeate the developer experience.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;deploy-monitoring&quot;&gt;Deploy Monitoring&lt;&#x2F;h3&gt;
&lt;ul&gt;
  &lt;li&gt;Track status of deploy from start to finish&lt;&#x2F;li&gt;
  &lt;li&gt;Finer state detail (ready, preparing, waiting, deploying, finished, failed)&lt;&#x2F;li&gt;
  &lt;li&gt;Aware of rollout across multiple containers&#x2F;servers&lt;&#x2F;li&gt;
  &lt;li&gt;Ability to abort a deploy&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;Now let’s go in a different direction and talk about something I’m calling &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;21413&quot;&gt;deploy monitoring&lt;&#x2F;a&gt;.
Deploys aren’t just binary pass&#x2F;fail, and they’re not instantaneous, but we currently kinda treat them as if they’re both. Deploys can take significant time, going through many different states, and across many containers or servers. Being able to track and debug that complexity is pretty important, especially for larger organizations.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;deployboard&quot;&gt;Deployboard&lt;&#x2F;h3&gt;

&lt;p&gt;So here’s an early mockup of how we could integrate this information into our environment view.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;monitoring&#x2F;environments__deploy-graphic.png&quot; alt=&quot;Deployboard&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;On staging, you see that the last deployment finished, but production has a deployment that is ongoing. Each square represents a container, managed by Kubernetes. Hovering over each one shows the server name and it’s current status. Clicking through might show more details about that container. Since this is the environment list, we also see our review apps, but we’ve hidden the deploy status by default since it’s less important for review apps. For any of these environments, you can click through to the monitoring dashboard I already showed.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;deploy-monitoring-1&quot;&gt;Deploy Monitoring++&lt;&#x2F;h3&gt;
&lt;ul&gt;
  &lt;li&gt;Notify authors of MRs that their changes are now live or in staging&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;Now deploy monitoring is a rich area with lots of opportunities for growth. Here’s an image from someone else’s Deployboard that shows a Slack notification of a staging deploy, and @ mentioning everyone with code in that change.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;monitoring&#x2F;deployboard_notification.png&quot; alt=&quot;Deployboard notification&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;Here are some other ideas I want to explore:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;Incremental rollouts (deploy to 10 containers at a time)&lt;&#x2F;li&gt;
  &lt;li&gt;Canary deploys (deploy 10 containers, then wait for stats or manual tests)&lt;&#x2F;li&gt;
  &lt;li&gt;Blue&#x2F;green deploys&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;First is incremental rollouts where you deploy new code in batches. Say if you’ve got 100 containers to roll, you’d deploy 10 containers at a time, in 10 batches, until all 100 are done.&lt;&#x2F;p&gt;

&lt;p&gt;Closely related to that is a canary deploy, where you deploy to a few containers, and then stop while you wait some period of time for performance statistics to prove that there are no problems. Maybe even do some manual tests on those containers, although really that should have been done in staging.&lt;&#x2F;p&gt;

&lt;p&gt;And then there’s blue&#x2F;green deploy, which has a few definitions, but the one I’m using here is where you have all your traffic going to one fleet of containers or servers, call that the blue fleet. Then you start deploying new code to a green fleet, but don’t send any traffic to it. When the green fleet is up and ready, then you cut over the router to suddenly send all traffic to the green fleet and the blue fleet goes idle. You could leave that blue fleet running in case you need to immediately revert. It’s much faster to switch a router over rather than wait for all servers to deploy again. If you’re using physical servers, these fleets may be permanent, meaning you’ve got to have twice the computing capacity at any time. If they’re containers, you can bring down the idle fleet after some time and then just spin it up again when you do the next deploy.&lt;&#x2F;p&gt;

&lt;p&gt;But again, these are standard deploy strategies that companies already use. Of course we want to support these best practices, but our challenge will be to integrate these closely into GitLab to deliver even more value from the integrated whole. Integrating deploy strategies with monitoring and our knowledge of the codebase, merge requests, and issues. Maybe an alert of a performance problem automatically generates a new issue labeled appropriately and assigned to the right person so it shows up in their todos.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;feature-flags&quot;&gt;Feature Flags&lt;&#x2F;h3&gt;
&lt;ul&gt;
  &lt;li&gt;Decouple deployment from delivery&lt;&#x2F;li&gt;
  &lt;li&gt;In-code flag to execute one path or another based on externally controllable settings&lt;&#x2F;li&gt;
  &lt;li&gt;Binary switch&lt;&#x2F;li&gt;
  &lt;li&gt;Incremental (%) rollout&lt;&#x2F;li&gt;
  &lt;li&gt;Named group (internal, beta)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;I’m going to go off on a tangent for a moment and talk about &lt;a href=&quot;http:&#x2F;&#x2F;martinfowler.com&#x2F;bliki&#x2F;FeatureToggle.html&quot;&gt;Feature Flags&lt;&#x2F;a&gt;.
Feature flags allow developers to decouple deployment from delivery while reducing risk. It’s usually an in-code mechanism, like an if statement, to conditionally execute one path or another based on externally controllable settings such as a simple all-or-nothing binary switch, or a more complex incremental rollout based on percentages, like turning it on for 10% of your users, or involving named groups like company internal, or a &quot;beta” group.
With feature flags, code can be deployed into production while the feature is still turned off.&lt;&#x2F;p&gt;

&lt;p&gt;My ideal rollout is something like:&lt;&#x2F;p&gt;
&lt;ul&gt;
  &lt;li&gt;Dev team that created it -&amp;gt;&lt;&#x2F;li&gt;
  &lt;li&gt;internal alpha (all employees minus those giving customer-facing demos) -&amp;gt;&lt;&#x2F;li&gt;
  &lt;li&gt;select beta (~200 people that signed up for this specific feature) -&amp;gt;&lt;&#x2F;li&gt;
  &lt;li&gt;private beta (~1000 people that signed up for general beta) -&amp;gt;&lt;&#x2F;li&gt;
  &lt;li&gt;public beta -&amp;gt;&lt;&#x2F;li&gt;
  &lt;li&gt;10% rollout -&amp;gt;&lt;&#x2F;li&gt;
  &lt;li&gt;GA&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;Features can then be rolled out to internal users, beta users, a percentage of production users, and then to everyone in ever-increases spheres.
This help facilitate healthy real-world testing, restricting risk to affect only beta customers rather than everyone, for example, so that you get feedback earlier in the development cycle. Validate your ideas quickly.
It also helps stay true to the premise of continuous integration which is that everything is checked into master often and deployed right away. This reduces deployment risk.&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;Feature Flags as first-class citizens&lt;&#x2F;li&gt;
  &lt;li&gt;Compare flag states across environments (e.g. staging has X, which is not yet enabled on production)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;I&#x27;d like to see us work &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ee&#x2F;issues&#x2F;779&quot;&gt;feature flags into GitLab&lt;&#x2F;a&gt; in a first-class way. To be honest, I really don’t know how to do that. But I know I’d like to visually see, at a glance, which features are in private beta, for example. If a product manager tries to turn a feature on for general availability, they’ll be subtly reminded that they should consider going through private beta first. Companies should be able to set a rollout policy of what percentages things should go through at each stage.
If done right, it’ll encourage a good rollout process, and make it trivially easy for users to follow the flow, every time.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;monitoring&#x2F;user-flags.png&quot; alt=&quot;User flags&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h3 id=&quot;feature-monitoring&quot;&gt;Feature Monitoring&lt;&#x2F;h3&gt;
&lt;p&gt;Now to bring this back to monitoring, feature flags are another rollout mechanism, similar to some of the deployment strategies. So we should be able to &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;24254&quot;&gt;monitor these&lt;&#x2F;a&gt;, showing some analysis&#x2F;graphing on them.
Perhaps it’s a simple list of features and summary statistics about them indicating if they&#x27;re performing as expected. Like:&lt;&#x2F;p&gt;
&lt;ul&gt;
  &lt;li&gt;Feature X, rolled out to beta, decreased response time by 5%&lt;&#x2F;li&gt;
  &lt;li&gt;Feature Y, rolled out to 10%, increased conversion by 25%&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;The good thing is that since feature flags often run in parallel, so you’ve got some users with the flag and some users without, you can more accurately determine the performance or other impact. You don’t have to rely on point-in-time changes, like looking at memory before and after a deploy.&lt;&#x2F;p&gt;

&lt;p&gt;And it’s quite possible to have multiple flags at the same time, all at different rollout stages. With a deploy, which ships everything in master at once, if there’s a problem with one merge request 25 commits ago, you’ve got to rollback the entire stack until that change is gone. But feature flags are decoupled so if there’s a problem in an individual feature, you can just scale it down to zero without affecting any other feature, and without requiring a lengthy deploy process.&lt;&#x2F;p&gt;

&lt;p&gt;Another side note, since deployment strategies and feature flags are somewhat advanced topics that currently take quite a commitment to implement, most companies only focus on one of these strategies. If you work on feature flags, you’re not likely to bother with canary deploys, for example. But each tool has their sweet spot of value. Memory problems aren’t likely to show up using feature flags since memory is a system resource that’s really hard to pin down to a specific user. But error rates or conversion metrics are great for this. If we do a great job here, maybe people won’t have to be so stingy on their choice of tools.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;qa&quot;&gt;Q&amp;amp;A&lt;&#x2F;h3&gt;

&lt;p&gt;And with that, I’d like to thank you all for listening, and open it up to questions.&lt;&#x2F;p&gt;

&lt;hr &#x2F;&gt;

&lt;p&gt;&lt;em&gt;P.S. I really love being able to work out in the open like this, publicly sharing our vision long before it&#x27;s a reality. If you love the same, please check out or &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;jobs&#x2F;&quot;&gt;jobs page&lt;&#x2F;a&gt;. We&#x27;re looking for more &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;jobs&#x2F;prometheus-engineer&#x2F;&quot;&gt;Prometheus Engineers&lt;&#x2F;a&gt; (and many other positions)! Tweet us &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gitlab&quot;&gt;@GitLab&lt;&#x2F;a&gt;, add your questions below, and add suggestions to our &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&quot;&gt;issue tracker&lt;&#x2F;a&gt;!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;unsplash&#x2F;data.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>Behind the scenes: How we built Review Apps</title>
    <link rel="alternate" href="https://about.gitlab.com/2017/01/04/behind-the-scenes-how-we-built-review-apps/"/>
    <id>https://about.gitlab.com/2017/01/04/behind-the-scenes-how-we-built-review-apps/</id>
    <published>2017-01-04T00:00:00+00:00</published>
    <updated>2017-01-04T00:00:00+00:00</updated>
    <author>
      <name>Mark Pundsack</name>
    </author>
    <content type="html">
&lt;p&gt;A bunch of us on the GitLab team have known for a while just how important review apps are. Even though this wasn’t something that a lot of customers asked for, we knew we had to tackle it because of how we&#x27;d seen it transform a developer&#x27;s flow. We also knew that tightly integrating it into GitLab would make it even better. Although our aspirations for the feature started out gigantic and magical, we ultimately constrained them to the practical and concrete. Here&#x27;s a behind-the-scenes look at how we iterated and shipped &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;features&#x2F;review-apps&#x2F;&quot;&gt;Review Apps&lt;&#x2F;a&gt; over the last 3 releases.&lt;&#x2F;p&gt;



&lt;p&gt;Full disclosure: I used to work at Heroku on the team that shipped &lt;a href=&quot;https:&#x2F;&#x2F;devcenter.heroku.com&#x2F;articles&#x2F;github-integration-review-apps&quot;&gt;Heroku Review Apps&lt;&#x2F;a&gt;, and some of that work was inspired by a tool called &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;rainforestapp&#x2F;fourchette&quot;&gt;Fourchette&lt;&#x2F;a&gt;, which was created by the great folks at &lt;a href=&quot;https:&#x2F;&#x2F;www.rainforestqa.com&#x2F;&quot;&gt;Rainforest QA&lt;&#x2F;a&gt;. Even outside of my personal bias, our CEO, CI Lead and others had seen things like this elsewhere and saw how transformative it could be.&lt;&#x2F;p&gt;

&lt;figure class=&quot;video_container&quot;&gt;
  &lt;iframe src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;CteZol_7pxo?start=1713&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt; &lt;&#x2F;iframe&gt;
&lt;&#x2F;figure&gt;

&lt;p&gt;There are a ton of different ways we could have shipped it. We started months ago, mostly discussing asynchronously on GitLab issues, with big ideas that made Review Apps seem kind of daunting. We had ideas for black magic to detect Kubernetes settings, configure all the review app stuff for you, make them work only for merge requests rather than for every branch, etc. It felt like something that might not ship for months, if not years, because of all the complexity and dependencies.&lt;&#x2F;p&gt;

&lt;p&gt;But then a few of us got together to see how we could simplify, starting with a written proposal, then collaborating in a Google Doc, then a live chat over Google Hangouts, and we came up with what we felt would be the smallest thing we could do to enable the functionality. We shared that proposal back on the public issue. After a couple days, we pushed it even further and really cut the scope.&lt;&#x2F;p&gt;

&lt;p&gt;Here are a few links to some of the issues we went through, starting with a large meta issue, down to a concrete proposal and then counterproposal, until finally, the winning proposal emerged:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;3286&quot;&gt;#3286&lt;&#x2F;a&gt; - [Epic] GitLab Deploy, &lt;em&gt;opened 1 year ago&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;14698&quot;&gt;#14698&lt;&#x2F;a&gt; - Container scheduler for 4 use cases, &lt;em&gt;9 months ago&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;20255&quot;&gt;#20255&lt;&#x2F;a&gt; - [Meta] Review Apps, &lt;em&gt;5 months ago&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;20054&quot;&gt;#20054&lt;&#x2F;a&gt; - Review Apps as Runner job, &lt;em&gt;5 months ago&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;21411&quot;&gt;#21411&lt;&#x2F;a&gt; - How do we do deploys, &lt;em&gt;4 months ago&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;21971&quot;&gt;#21971&lt;&#x2F;a&gt; - Dynamic environments aka Review Apps, &lt;em&gt;3 months ago&lt;&#x2F;em&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;812&quot;&gt;8.12&lt;&#x2F;h2&gt;

&lt;p&gt;We initially offered experimental support for Review Apps in GitLab 8.12. At that point, we had reduced it to just one or two seemingly small changes to the &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt; format. Specifically, we let you specify the URL of an environment in &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt; (rather than just in the web UI), and we let you use variables within the environment name and URL. Trivial, right? One extra keyword and another small change enabled environments to now be “dynamic,” which is the core of Review Apps.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;review_apps&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;environment&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;review&#x2F;$CI_BUILD_REF_NAME&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;http:&#x2F;&#x2F;$CI_BUILD_REF_NAME.review.gitlab.com&#x2F;&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;813&quot;&gt;8.13&lt;&#x2F;h2&gt;

&lt;p&gt;Then in 8.13 we implemented another key piece: the ability to delete or stop apps. Again, there were all sorts of complex ideas for how to solve this, but we settled on the smallest change possible that enabled the feature. In this case, that was reusing our existing concept of manual actions, or jobs that run in a pipeline only when a user triggers them manually from the web UI. So we said, if you can script how to delete your app, just create a manual action job for it. Then we added a new keyword in &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt; so you could identify which of these jobs stopped the environment, and we displayed a different UI for that - now you get a little square stop button instead of the triangle play button. Again, pretty trivial.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;review&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;environment&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;review&#x2F;$app&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;on_stop&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;stop_review&lt;&#x2F;span&gt;

&lt;span class=&quot;na&quot;&gt;stop_review&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;echo Delete My App&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;when&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;manual&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;environment&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;review&#x2F;$app&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;action&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;stop&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;814&quot;&gt;8.14&lt;&#x2F;h2&gt;

&lt;p&gt;Most recently, in the 8.14 release, we made it so that we automatically detect when a branch is deleted, and run that manual action automatically for you. We also realized that with tons of Review Apps, your environments list might get unmanageable. To mitigate this, we came up with the convention that if you named your review app starting with a common name and then a slash, we’d treat that like a folder by which to group your apps, so the interface can show a bunch of Review Apps behind a collapsed folder. Once again, these are relatively small changes.&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;Auto-stop on branch delete&lt;&#x2F;li&gt;
  &lt;li&gt;Folders in environment list&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;wrap-up&quot;&gt;Wrap up&lt;&#x2F;h2&gt;

&lt;p&gt;Ultimately this really complex, life changing feature was broken down into 3 releases of the minimal viable change.&lt;&#x2F;p&gt;

&lt;p&gt;While we say Review Apps is now complete, it’s not finished. In fact, we have a saying that nothing is ever finished because we’re always looking for the minimal change, and then iterating. By shipping smaller pieces, we not only deliver faster, but we learn from what’s been shipped, and then iterate smarter.&lt;&#x2F;p&gt;

&lt;p&gt;We’ve now got follow-on issues to look at simplifying the &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt; syntax for Review Apps, and even adding back some of that magic we originally envisioned. We’ll continue to iterate, and your feedback is key to us shipping better.&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;25138&quot;&gt;#25138&lt;&#x2F;a&gt; - Simplify &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt; syntax for stopping Review Apps&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;24197&quot;&gt;#24197&lt;&#x2F;a&gt; - Smart deploy&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;23580&quot;&gt;#23580&lt;&#x2F;a&gt; - Auto deploy&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;&lt;em&gt;Tweet us &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gitlab&quot;&gt;@GitLab&lt;&#x2F;a&gt;, check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;jobs&#x2F;&quot;&gt;job openings&lt;&#x2F;a&gt;, or add your questions and suggestions to our &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&quot;&gt;issue tracker&lt;&#x2F;a&gt;!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;blogimages&#x2F;code-gitlab-tanuki.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>How to prepare for a virtual interview at GitLab</title>
    <link rel="alternate" href="https://about.gitlab.com/2017/01/03/how-to-prepare-for-a-virtual-interview/"/>
    <id>https://about.gitlab.com/2017/01/03/how-to-prepare-for-a-virtual-interview/</id>
    <published>2017-01-03T00:00:00+00:00</published>
    <updated>2017-01-03T00:00:00+00:00</updated>
    <author>
      <name>Sasha Bannister</name>
    </author>
    <content type="html">
&lt;p&gt;The GitLab interview process, like our company, is remote first. As a result, our recruiting team and hiring managers spend lots of time meeting candidates via &lt;a href=&quot;&#x2F;handbook&#x2F;#videocalls&quot;&gt;video calls&lt;&#x2F;a&gt;. Video chats are an important part
of our daily culture and a great way to connect with our teammates, but they can also be a confusing, uncomfortable, and stress-inducing component of an interview.&lt;&#x2F;p&gt;



&lt;p&gt;More and more organizations are conducting interviews and meetings using video platforms. At GitLab we use Google Hangouts or Appear.in for most of our &lt;a href=&quot;&#x2F;handbook&#x2F;#video-calls&quot;&gt;one-on-one calls&lt;&#x2F;a&gt;. Whatever platform you’re using, these simple guidelines will help you have a productive web interview and allow you to focus on the role.&lt;&#x2F;p&gt;

&lt;p&gt;Read on for our tips on how to avoid video chat nerves!&lt;&#x2F;p&gt;

&lt;h2 id=&quot;stage-your-interview-spot&quot;&gt;Stage Your Interview Spot&lt;&#x2F;h2&gt;

&lt;p&gt;It’s nice to be in a neutral environment that is a quiet and comfortable for you. That way neither you nor the interviewer gets too distracted by your environment. We encourage you to display your &lt;a href=&quot;&#x2F;handbook&#x2F;#values&quot;&gt;quirkiness&lt;&#x2F;a&gt; and personality, but for the interview it&#x27;s best to avoid chaos. For example, we wouldn&#x27;t suggest taking your interview call in a loud crowded cafe, in a car, or from your bed! These examples may sound extreme, but we have seen it all.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;practice-your-positioning&quot;&gt;Practice Your Positioning&lt;&#x2F;h2&gt;

&lt;p&gt;During the interview, you can’t exactly make eye contact with the interviewer, so the interviewer should clearly be able to see your face. Before the interview, check your front-facing camera or webcam to make sure you are well
lit and can be seen!&lt;&#x2F;p&gt;

&lt;h2 id=&quot;test-your-tech&quot;&gt;Test Your Tech&lt;&#x2F;h2&gt;

&lt;p&gt;Nothing is worse than realizing moments before your call that you don’t have strong enough wifi, don’t know how to use the video platform, or can’t get your mic to work! Test your equipment and the video platform before
your interview, and avoid technical snags the day of! It’s also worthwhile to make sure your computers are fully charged or plugged in, and you have earphones with a good mic (this helps minimize echo). We suggest using a webcam or your built-in camera on your laptop for the interview instead of using a phone or tablet.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;do-your-research&quot;&gt;Do Your Research&lt;&#x2F;h2&gt;

&lt;p&gt;At GitLab, we love when candidates have reviewed our &lt;a href=&quot;&#x2F;handbook&quot;&gt;handbook&lt;&#x2F;a&gt; and know our &lt;a href=&quot;&#x2F;handbook&#x2F;#values&quot;&gt;values&lt;&#x2F;a&gt;. Many of our &lt;a href=&quot;&#x2F;handbook&#x2F;hiring&#x2F;#interview-questions&quot;&gt;interview questions&lt;&#x2F;a&gt; can even be found in our &lt;a href=&quot;&#x2F;handbook&#x2F;hiring&quot;&gt;hiring process&lt;&#x2F;a&gt;, making preparation simple. Making a great first impression is not reserved for on-site interviews.&lt;&#x2F;p&gt;

&lt;p&gt;After you&#x27;ve mastered these tips, it&#x27;s important to remember that much of the traditional interviewing advice still applies; we encourage you to prepare for a virtual interview the same way you would for an in-person interview. Just because you are taking a call from home doesn’t make it the same as a casual call. Dress appropriately, do your research, and prepare good questions.&lt;&#x2F;p&gt;

&lt;p&gt;So what are you waiting for?! Now that you’re ready for your first interview with GitLab, head to our &lt;a href=&quot;&#x2F;jobs&quot;&gt;jobs page&lt;&#x2F;a&gt; to check out all of our open roles. We can’t wait to meet you!&lt;&#x2F;p&gt;

&lt;p&gt;Image: &quot;&lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;thomcochrane&#x2F;6816952248&#x2F;in&#x2F;photolist-booEps-eAd9dF-nFi1Nk-ePjC2R-irZLco-p9T8i9-hJw5BS-hJwJZv-ajfAp4-ePjM8X-mbFtpp-ePw3fy-hJvBEe-ceF17u-HHywQL-ePw19o-kYkwKf-dqEjfQ-pESWes-kYkxBf-ePw9h3-cfW6eb-HLxMw2-HHyDaj-fA43ft-dUYEGc-hVp7qj-hHfkXj-rtZnmw-nDvJzr-a8ygpG-krfaXi-edHRac-a8ygq1-aaUbmS-krfbbV-hJvB7k-dyxQZQ-a8ygqA-aaUbis-eHuQJe-h7U3mF-f29C1c-dXS8Cy-ePw58L-hVpb6J-oS8XNJ-nzD7xn-oS9qPV-hVp92f&quot;&gt;Nurturing Global Communities Of Practice via Google Plus Hangouts&lt;&#x2F;a&gt;&quot; by &lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;thomcochrane&#x2F;&quot;&gt;Thom Cochrane&lt;&#x2F;a&gt; available under &lt;a href=&quot;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by&#x2F;2.0&#x2F;legalcode&quot;&gt;CC BY 2.0&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Tweet us &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gitlab&quot;&gt;@GitLab&lt;&#x2F;a&gt;, or add your thoughts and questions to our issue tracker.&lt;&#x2F;p&gt;

&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;blogimages&#x2F;how-to-prepare-for-a-virtual-interview.jpg&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>Set Expectations, Manage Better</title>
    <link rel="alternate" href="https://about.gitlab.com/2017/01/03/set-expectations/"/>
    <id>https://about.gitlab.com/2017/01/03/set-expectations/</id>
    <published>2017-01-03T00:00:00+00:00</published>
    <updated>2017-01-03T00:00:00+00:00</updated>
    <author>
      <name>Job van der Voort</name>
    </author>
    <content type="html">
&lt;p&gt;With GitLab Inc growing to &lt;a href=&quot;&#x2F;team&quot;&gt;more than 150 people&lt;&#x2F;a&gt; working remotely and
steadily increasing, inevitably new challenges come up while building great
software.&lt;&#x2F;p&gt;



&lt;p&gt;We never shied away from &lt;a href=&quot;&#x2F;team&#x2F;structure&quot;&gt;hierarchy&lt;&#x2F;a&gt;, but recently I’ve been
noticing a trend towards more traditional people management in an effort to
maintain focus on shipping at scale.&lt;&#x2F;p&gt;

&lt;p&gt;I believe that creating overhead with meetings and reviews is a risk to the
efficiency and remote culture of organisations. It should be &lt;em&gt;actively&lt;&#x2F;em&gt; avoided
for an organisation to succeed remote at scale.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;more-people-less-productivity&quot;&gt;More people, less productivity&lt;&#x2F;h2&gt;

&lt;p&gt;When a team grows from five to 30 to 100 people, some parts of the
team will fail at some point: be that in the form of missing a deadline or not
delivering quality work.
Of course, larger organisations want to solve this permanently. If there
already is an established hierarchy, it’s likely that the managers of the
failing team will ask themselves:&lt;&#x2F;p&gt;

&lt;blockquote&gt;
  &lt;p&gt;How could we have seen this earlier?&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;p&gt;A senior manager will think back to the old days when everyone was
performing well as a small team.&lt;&#x2F;p&gt;

&lt;p&gt;Now, reader, how would you solve this? Obviously this was an oversight by
management: they should’ve seen this earlier. The suggested solution might be to improve or
create a reporting structure where management reviews the status of projects
and teams more frequently.
In addition, management should have more frequent meetings in order to review
the status of the teams and handle these if necessary.&lt;&#x2F;p&gt;

&lt;p&gt;This is where productivity goes down significantly and remote culture is in
danger.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;solution-set-clear-expectations&quot;&gt;Solution: Set clear expectations&lt;&#x2F;h2&gt;

&lt;p&gt;Reviewing work in progress both directly, and indirectly through meetings is a
waste of time.&lt;&#x2F;p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Q: But what happens if things go off the rails? How will I know? Who will handle it?&lt;&#x2F;p&gt;

  &lt;p&gt;A: Trust your people.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;p&gt;You must set clear expectations for any and all work. These expectations should
include a clear scope, time of delivery, but more importantly: communication
expectations.
Communication expectations are easily outlined:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;I expect that you will let me know immediately if you think that this deliverable will not make the deadline.&lt;&#x2F;li&gt;
  &lt;li&gt;I expect that if you have doubts about the feasibility, functionality, scope, or outline of this deliverable, you will let me know.&lt;&#x2F;li&gt;
  &lt;li&gt;I expect that if you need help from colleagues, you will contact them and ensure their collaboration. If you get stuck with this, I expect you to communicate this to me.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;Now this seems a little verbose – maybe it is, but it makes it very clear
what is expected of those responsible. It even seems very obvious, but now that
we wrote this down, do the additional reviews and reports still make sense?&lt;&#x2F;p&gt;

&lt;h2 id=&quot;doing-this-remotely&quot;&gt;Doing this remotely&lt;&#x2F;h2&gt;

&lt;p&gt;Doing all of this remotely adds a layer of complexity. We’re fighting with two
paradoxical goals: we want to maintain a single source of truth, and we want to be able to give a sense of urgency when working with deadlines, to be able to maintain a certain pace.&lt;&#x2F;p&gt;

&lt;p&gt;In practice this means that everyone is expected to over-communicate. For
example, I might say in a GitLab issue to Sytse that our rocket engine won’t
make it in time for the planned launch date, but because I know he’s way behind
on email and Todos, I’ll also send him a message in chat.&lt;&#x2F;p&gt;

&lt;p&gt;For remote teams, such as our own, I’d add another expectation:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;I expect &lt;em&gt;you&lt;&#x2F;em&gt; to make sure that other parties you communicate with are actually reached.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;This means sometimes you’ll have to ask someone else if Jane is absent or
send her another message on chat if she doesn’t reply within a reasonable
time.
From personal experience, being a little more pushy and impatient that you’d be
in everyday life is enormously beneficial to this end.&lt;&#x2F;p&gt;

&lt;p&gt;Over-communicating is a small cost to pay for the freedom of working remotely.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;at-gitlab&quot;&gt;At GitLab&lt;&#x2F;h2&gt;

&lt;p&gt;I wrote this as a response to observations I made at GitLab. That said,
it already was a company policy to look specifically for people who
manage themselves. This is &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;handbook&#x2F;leadership&#x2F;&quot;&gt;what we write in our handbook on this topic&lt;&#x2F;a&gt;:&lt;&#x2F;p&gt;

&lt;blockquote&gt;
  &lt;p&gt;We don&#x27;t have project managers. Individual contributors need to manage themselves. Not everyone will be able to do this effectively and be fit for our organization. Making someone responsible for managing others will make the job of the people who can manage themselves worse. If you manage yourself you have a much greater freedom to make decisions, and those decisions are based on deep knowledge of the situation. We want to retain the people who can handle that responsibility and therefore we can&#x27;t retain the ones that struggle. Assigning a project manager&#x2F;coordinator&#x2F;case manager&#x2F;etc. to something is an indicator that something is wrong and we are picking the wrong solution.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;p&gt;We write these and other lessons in our single source of truth,
&lt;a href=&quot;&#x2F;handbook&quot;&gt;our handbook&lt;&#x2F;a&gt;. Like (almost) everything at GitLab, our handbook is
open source and you&#x27;re welcome to read it and contribute to it.&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;default-blog-image.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>GitLab 8.15.2 released</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/28/gitlab-8-dot-15-dot-2-released/"/>
    <id>https://about.gitlab.com/2016/12/28/gitlab-8-dot-15-dot-2-released/</id>
    <published>2016-12-28T00:00:00+00:00</published>
    <updated>2016-12-28T00:00:00+00:00</updated>
    <author>
      <name>Robert Speicher</name>
    </author>
    <content type="html">
&lt;p&gt;Today we are releasing version 8.15.2 for GitLab Community Edition (CE) and
Enterprise Edition (EE).&lt;&#x2F;p&gt;

&lt;p&gt;This version resolves a number of regressions and bugs in the &lt;a href=&quot;&#x2F;2016&#x2F;12&#x2F;22&#x2F;gitlab-8-15-released&quot;&gt;recent 8.15
release&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Please read on for more details.&lt;&#x2F;p&gt;



&lt;hr &#x2F;&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix merge request list timestamp alignment. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8271&quot;&gt;!8271&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix discussion overlap text in regular screens. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8273&quot;&gt;!8273&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix timeout when MR contains large files marked as binary by &lt;code&gt;.gitattributes&lt;&#x2F;code&gt;.&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix mini-pipeline-graph dropdown animation and stage position in Chrome, Firefox and Safari. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8282&quot;&gt;!8282&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix line breaking in nodes of the pipeline graph in Firefox. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8292&quot;&gt;!8292&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix confidential warning text alignment. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8203&quot;&gt;!8203&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Hide Scroll Top button for failed build page. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8295&quot;&gt;!8295&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Rename &quot;autodeploy&quot; to &quot;auto deploy&quot;.&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Disable PostgreSQL statement timeouts when removing unneeded services. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8322&quot;&gt;!8322&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix finding the latest pipeline. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8301&quot;&gt;!8301&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fixed GFM autocomplete error when no data exists.&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Added ability to put emojis into repository name. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7420&quot;&gt;!7420&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fixed resolve discussion note button color.&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;EE:&lt;&#x2F;strong&gt; Add hover states for collapsed Issue&#x2F;Merge Request sidebar for Time tracking Icon&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;EE:&lt;&#x2F;strong&gt; Fix ElasticSearch search for non-default branches (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ee&#x2F;merge_requests&#x2F;999&quot;&gt;!999&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;Omnibus GitLab&lt;&#x2F;strong&gt; Add a delay option for pg-upgrade (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;omnibus-gitlab&#x2F;merge_requests&#x2F;1164&quot;&gt;!1164&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;upgrade-barometer&quot;&gt;Upgrade barometer&lt;&#x2F;h2&gt;

&lt;p&gt;This version has no migrations and should not require any downtime.&lt;&#x2F;p&gt;

&lt;p&gt;Please be aware that by default the Omnibus packages will stop, run migrations,
and start again, no matter how “big” or “small” the upgrade is. This behavior
can be changed by adding a &lt;a href=&quot;http:&#x2F;&#x2F;doc.gitlab.com&#x2F;omnibus&#x2F;update&#x2F;README.html&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;gitlab&#x2F;skip-auto-migrations&lt;&#x2F;code&gt;
file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;updating&quot;&gt;Updating&lt;&#x2F;h2&gt;

&lt;p&gt;To update, check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;update&#x2F;&quot;&gt;update page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;enterprise-edition&quot;&gt;Enterprise Edition&lt;&#x2F;h2&gt;

&lt;p&gt;Interested in GitLab Enterprise Edition? Check out the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;features&#x2F;#enterprise&quot;&gt;features exclusive to
EE&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Access to GitLab Enterprise Edition is included with a &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;pricing&#x2F;&quot;&gt;subscription&lt;&#x2F;a&gt;.
No time to upgrade GitLab yourself? Subscribers receive upgrade and installation
services.&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;default-blog-image.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>We’re bringing GitLab Pages to the Community Edition</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/24/were-bringing-gitlab-pages-to-community-edition/"/>
    <id>https://about.gitlab.com/2016/12/24/were-bringing-gitlab-pages-to-community-edition/</id>
    <published>2016-12-24T00:00:00+00:00</published>
    <updated>2016-12-24T00:00:00+00:00</updated>
    <author>
      <name>Job van der Voort</name>
    </author>
    <content type="html">
&lt;p&gt;The wider community asked us open source GitLab pages.
Inspired by the holiday-spirit we&#x27;re happy to bring GitLab Pages to the Community Edition (CE) of GitLab.&lt;&#x2F;p&gt;



&lt;p&gt;&lt;a href=&quot;http:&#x2F;&#x2F;pages.gitlab.io&#x2F;&quot;&gt;GitLab Pages&lt;&#x2F;a&gt; allows you to &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;04&#x2F;07&#x2F;gitlab-pages-setup&#x2F;&quot;&gt;host static websites&lt;&#x2F;a&gt; straight from GitLab, with any kind of &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;06&#x2F;17&#x2F;ssg-overview-gitlab-pages-part-3-examples-ci&#x2F;&quot;&gt;static site generator&lt;&#x2F;a&gt;.
For instance, &lt;a href=&quot;http:&#x2F;&#x2F;www.jobvandervoort.com&quot;&gt;my personal website&lt;&#x2F;a&gt; is hosted
through GitLab Pages on GitLab.com using my favorite static site generator
&lt;a href=&quot;https:&#x2F;&#x2F;middlemanapp.com&#x2F;&quot;&gt;Middleman&lt;&#x2F;a&gt; (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;JobV&#x2F;jobv.gitlab.io&quot;&gt;see the source here&lt;&#x2F;a&gt;). Even our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;12&#x2F;07&#x2F;building-a-new-gitlab-docs-site-with-nanoc-gitlab-ci-and-gitlab-pages&#x2F;&quot;&gt;documentation site&lt;&#x2F;a&gt; is
also fully built on GitLab Pages. Until today, GitLab Pages was exclusive to
the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;products&#x2F;&quot;&gt;Enterprise Edition&lt;&#x2F;a&gt; of GitLab.&lt;&#x2F;p&gt;

&lt;p&gt;When we chose to limit this functionality to EE, we did so based on the
reasoning that small teams wouldn’t be interested in this
functionality. We thought it met our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;about&#x2F;#stewardship&quot;&gt;stewardship&lt;&#x2F;a&gt; criteria that it was more relevant for organizations that have more than 100 potential users.&lt;&#x2F;p&gt;

&lt;p&gt;We thought that small teams would use the option of using GitLab.com (which runs EE) for free.
Or that they would set up only one website which is easy to do manually.&lt;&#x2F;p&gt;

&lt;p&gt;Yet, &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;14605&quot;&gt;more than a hundred people voted&lt;&#x2F;a&gt; and discussed bringing
GitLab Pages to our open-source MIT-licensed Community Edition (CE). We’re
always willing to reconsider our decisions and the passionate messages we
received were more than enough reason to do so. Of course, for GitLab Inc. this
is also a business decision. When we decide to bring a feature from EE to CE,
this lowers the relative value of EE and therefore the potential of selling
subscriptions. Subscriptions allows us to keep investing in new features, packaging, bugfixing and performance improvements.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;In this case, I’m happy to announce that we will be bringing GitLab Pages to the Community Edition.&lt;&#x2F;strong&gt; We’ll do this at the earliest convenience, most likely
with GitLab 8.16 on January 22nd.&lt;&#x2F;p&gt;

&lt;p&gt;We’re very fortunate that the wider community keeps us
sharp. It’s our hope that in the new year, you will continue to support,
guide, criticize, and contribute to GitLab.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;em&gt;Want to give Pages a try? &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;pages&#x2F;README.html&quot;&gt;Read our documentation here&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;p&gt;Happy holidays!&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;pages_gift.jpg&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>GitLab 8.15.1 released</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/23/gitlab-8-dot-15-dot-1-released/"/>
    <id>https://about.gitlab.com/2016/12/23/gitlab-8-dot-15-dot-1-released/</id>
    <published>2016-12-23T00:00:00+00:00</published>
    <updated>2016-12-23T00:00:00+00:00</updated>
    <author>
      <name>Douglas Barbosa Alexandre</name>
    </author>
    <content type="html">
&lt;p&gt;Today we are releasing version 8.15.1 for GitLab Community Edition (CE) and
Enterprise Edition (EE).&lt;&#x2F;p&gt;

&lt;p&gt;This version resolves a number of regressions and bugs in the &lt;a href=&quot;&#x2F;2016&#x2F;12&#x2F;22&#x2F;gitlab-8-15-released&quot;&gt;recent 8.15
release&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Please read on for more details.&lt;&#x2F;p&gt;



&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix viewing &quot;build failed&quot; TODOs. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8262&quot;&gt;!8262&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Do not show retried builds in pipeline stage dropdown. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8260&quot;&gt;!8260&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Don&#x27;t render inline math when dollar signs are inside markup. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8259&quot;&gt;!8259&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Do not override incoming Webhook channel for Slack&#x2F;Mattermost. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8270&quot;&gt;!8270&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix Mattermost command creation by specifying username. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8257&quot;&gt;!8257&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Improve autodeploy documentation. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8242&quot;&gt;!8242&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Add more images to issue creation from unresolved discussions. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8279&quot;&gt;!8279&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Stops GFM special characters interfering with markdown tags. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8265&quot;&gt;!8265&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix dropdown content non appearing in MR view. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8255&quot;&gt;!8255&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix &lt;code&gt;state_event&lt;&#x2F;code&gt; parameter to reopen an issue. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8246&quot;&gt;!8246&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Resolve &quot;Titles are bigger than usual&quot;. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8235&quot;&gt;!8235&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Adds background color for disabled state to merge when succeeds dropdown. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8222&quot;&gt;!8222&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Add Slack documentation. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8269&quot;&gt;!8269&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix format of Slack when result is &lt;code&gt;nil&lt;&#x2F;code&gt;. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8248&quot;&gt;!8248&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix error 500 on slash commands. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8285&quot;&gt;!8285&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Improve ProcessCommitWorker for large push payloads. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8267&quot;&gt;!8267&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Monkey-patch StrongParameters for ::UploadedFile&quot;. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8299&quot;&gt;!8299&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;EE:&lt;&#x2F;strong&gt; Fix 500 error while navigating to the &lt;code&gt;pages_domains&lt;&#x2F;code&gt; &#x27;show&#x27; page.. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ee&#x2F;merge_requests&#x2F;993&quot;&gt;!993&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;upgrade-barometer&quot;&gt;Upgrade barometer&lt;&#x2F;h2&gt;

&lt;p&gt;This version has no migrations and should not require any downtime.&lt;&#x2F;p&gt;

&lt;p&gt;Please be aware that by default the Omnibus packages will stop, run migrations,
and start again, no matter how “big” or “small” the upgrade is. This behavior
can be changed by adding a &lt;a href=&quot;http:&#x2F;&#x2F;doc.gitlab.com&#x2F;omnibus&#x2F;update&#x2F;README.html&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;gitlab&#x2F;skip-auto-migrations&lt;&#x2F;code&gt;
file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;updating&quot;&gt;Updating&lt;&#x2F;h2&gt;

&lt;p&gt;To update, check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;update&#x2F;&quot;&gt;update page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;enterprise-edition&quot;&gt;Enterprise Edition&lt;&#x2F;h2&gt;

&lt;p&gt;Interested in GitLab Enterprise Edition? Check out the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;features&#x2F;#enterprise&quot;&gt;features exclusive to
EE&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Access to GitLab Enterprise Edition is included with a &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;pricing&#x2F;&quot;&gt;subscription&lt;&#x2F;a&gt;.
No time to upgrade GitLab yourself? Subscribers receive upgrade and installation
services.&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;default-blog-image.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>GitLab 8.15 Released with Auto Deploy and Web Terminal</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/22/gitlab-8-15-released/"/>
    <id>https://about.gitlab.com/2016/12/22/gitlab-8-15-released/</id>
    <published>2016-12-22T00:00:00+00:00</published>
    <updated>2016-12-22T00:00:00+00:00</updated>
    <author>
      <name>Job van der Voort</name>
    </author>
    <content type="html">
&lt;p&gt;With this last release of the year, we&#x27;re not only completing our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;09&#x2F;14&#x2F;gitlab-live-event-recap&#x2F;&quot;&gt;Master Plan&lt;&#x2F;a&gt;, but we
want to show you something cool we&#x27;ve been working on:&lt;&#x2F;p&gt;

&lt;figure class=&quot;video_container&quot;&gt;
  &lt;iframe src=&quot;https:&#x2F;&#x2F;www.youtube.com&#x2F;embed&#x2F;m0nYHPue5RU&quot; frameborder=&quot;0&quot; allowfullscreen=&quot;true&quot;&gt; &lt;&#x2F;iframe&gt;
&lt;&#x2F;figure&gt;



&lt;p&gt;&lt;br &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;With GitLab 8.15, we&#x27;re introducing Auto Deploy (shown in the video at
&lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;m0nYHPue5RU?t=102&quot;&gt;1:42&lt;&#x2F;a&gt;), which automates setting up deploys and review apps. For a
Ruby on Rails project, this brings setup time to under a minute.&lt;&#x2F;p&gt;

&lt;p&gt;Plus, to make accessing your environments easier and faster, you can now
access them directly through a terminal in GitLab (shown in the video at &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;m0nYHPue5RU?t=318&quot;&gt;5:18&lt;&#x2F;a&gt;).&lt;&#x2F;p&gt;

&lt;p&gt;We want to give the power of containers, continuous integration and deployment,
review apps and container schedulers to everyone. With GitLab 8.15, we
take away all the hard work without hiding anything. In the demonstration we
setup and deploy a Ruby application with review apps, multiple environments,
chatops to a Kubernetes cluster in about 12 minutes. This typically takes days,
if not weeks to setup and use without GitLab.&lt;&#x2F;p&gt;

&lt;p&gt;For many people, December is a month of celebration and gift giving.
This month, GitLab was again so lucky to receive many great contributions.&lt;&#x2F;p&gt;

&lt;p&gt;The MVP of this month is &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;Munken&quot;&gt;Michael Munch&lt;&#x2F;a&gt; for bringing beautifully-typeset math
(LaTeX) to GitLab. Michael worked over a period of 6 months in merge requests
with in total more than three hundred comments to bring this to GitLab.&lt;&#x2F;p&gt;

&lt;p&gt;We&#x27;d also like to thank &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;warren.postma&quot;&gt;Warren Postma&lt;&#x2F;a&gt; for his contributions on the issue trackers, and the &lt;a href=&quot;https:&#x2F;&#x2F;forum.gitlab.com&#x2F;users&#x2F;warren.postma&#x2F;activity&quot;&gt;community forum&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;warren.postma&#x2F;gitlab-ce&#x2F;wikis&#x2F;home&quot;&gt;generally being a great advocate of the product and the company&lt;&#x2F;a&gt;.
And lastly, we want to thank &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;glensc&quot;&gt;Elan Ruusamäe&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;dirker&quot;&gt;Dirk Hörner&lt;&#x2F;a&gt; for their
contributions in technical design and implementation that have given super
powers to Git Hooks.&lt;&#x2F;p&gt;

&lt;p&gt;Thanks Warren, Michael, Elan, and Dirk!&lt;&#x2F;p&gt;

&lt;h2 id=&quot;auto-deploy&quot;&gt;Auto Deploy&lt;&#x2F;h2&gt;

&lt;p&gt;We want everyone to quickly get a fully functioning CI&#x2F;CD pipeline that deploys
to a container scheduler. It shouldn&#x27;t require any effort to get started,
but should also be scalable and not hide any of the magic.&lt;&#x2F;p&gt;

&lt;p&gt;Auto Deploy does this. Auto Deploy adds a single button to your project,
that when clicked, will create a merge request with a template that will
automatically deploy your application using Docker to your container scheduler.
The cool thing about this is that this immediately leverages Review Apps,
meaning you can see it working before even merging the merge request!&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;auto_deploy.png&quot; alt=&quot;Auto deploy in GitLab 8.15&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;This is as close as you can get to one-click deploys, while exposing what
is happening and having all this version-controlled, ready
to collaborate and iterate on.&lt;&#x2F;p&gt;

&lt;p&gt;See &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;m0nYHPue5RU?t=102&quot;&gt;1:42&lt;&#x2F;a&gt; in the video for a quick demo of
Auto Deploy, as it is available in GitLab 8.15.&lt;&#x2F;p&gt;

&lt;p&gt;For this first iteration, we ship Auto Deploy with a template for deploying to an external OpenShift cluster. We use &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;gliderlabs&#x2F;herokuish&quot;&gt;Herokuish&lt;&#x2F;a&gt; and Heroku Buildpacks to
package your application into a Docker Image that then is deployed to
Kubernetes on Openshift. We want to add support for more container
schedulers and cloud platforms later (vanilla Kubernetes cluster, Mesos, Docker
Swarm). Contributions are very welcome in &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-yml&quot;&gt;our template repository&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;blockquote&gt;
  &lt;p&gt;See &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;autodeploy&#x2F;index.html&quot;&gt;the Autodeploy documentation&lt;&#x2F;a&gt; for more information.&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;h2 id=&quot;web-terminal&quot;&gt;Web Terminal&lt;&#x2F;h2&gt;

&lt;p&gt;Working together with your container scheduler, GitLab happily spins up several
(dynamic) environments on request for your projects. Be that for review apps
or a staging or production environment.
Traditionally, getting direct access to these environments has been a little
painful. And that&#x27;s a shame: it&#x27;s very useful to quickly try something in a
live environment to debug a problem, or just to experiment.&lt;&#x2F;p&gt;

&lt;p&gt;With the web terminal, this has become extremely easy. Just visit the
environments page in your project and click on the terminal button.
GitLab will SSH into the instance for you and allow you to do anything
you would be able to do from your local instance.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;terminal_gif.gif&quot; alt=&quot;Web Terminal in GitLab 8.15&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;In the demonstration at &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;m0nYHPue5RU?t=318&quot;&gt;5:18&lt;&#x2F;a&gt; we show you
give you a quick peek at the web terminal. We can&#x27;t wait to see how you&#x27;ll
use it to speed up your workflow.&lt;&#x2F;p&gt;

&lt;blockquote&gt;
  &lt;p&gt;See the &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;administration&#x2F;integration&#x2F;terminal.html&quot;&gt;administrator&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;environments.html#terminal-support&quot;&gt;environments&lt;&#x2F;a&gt; documentation on the web terminal&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;h2 id=&quot;improved-bitbucket-importer&quot;&gt;Improved Bitbucket Importer&lt;&#x2F;h2&gt;

&lt;p&gt;Importing from Bitbucket has become even more powerful. With GitLab 8.15 we&#x27;ll
also import all pull requests as individual merge requests plus pull
request comments, milestones and the wiki from Bitbucket.
That makes the things we import from any Bitbucket project:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;Repository description&lt;&#x2F;li&gt;
  &lt;li&gt;Git repository&lt;&#x2F;li&gt;
  &lt;li&gt;Issues and their comments&lt;&#x2F;li&gt;
  &lt;li&gt;Pull Requests and their comments&lt;&#x2F;li&gt;
  &lt;li&gt;Milestones&lt;&#x2F;li&gt;
  &lt;li&gt;Wiki&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;When importing a project all references to pull requests and issues are
preserved and so is the access level (public&#x2F;private).&lt;&#x2F;p&gt;

&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;workflow&#x2F;importing&#x2F;import_projects_from_bitbucket.html&quot;&gt;Read the docs on the Bitbucket importer&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;global-git-hooks&quot;&gt;Global Git Hooks&lt;&#x2F;h2&gt;

&lt;p&gt;If you want to enforce rules and triggers based on Git pushes and their
contents, you have been able to use custom Git hooks in GitLab. But if you
want to standardize on these rules, you&#x27;d have to copy and paste them
to every new project.&lt;&#x2F;p&gt;

&lt;p&gt;With Global Git Hooks you can now create Git hooks that will be run
for each project on the GitLab instance. This should make it much easier
to set up rules that you want all incoming code to comply with.&lt;&#x2F;p&gt;

&lt;p&gt;Create the hooks in &lt;code&gt;hooks&#x2F;&amp;lt;hook_name&amp;gt;.d&#x2F;&lt;&#x2F;code&gt; directory or tell GitLab Shell where the directories are.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;administration&#x2F;custom_hooks.html&quot;&gt;See the documentation on Custom Hooks&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;chained-custom-git-hooks&quot;&gt;Chained Custom Git Hooks&lt;&#x2F;h2&gt;

&lt;p&gt;If you have set up custom Git hooks, the order might matter: when an initial
hook fails, there is no point in moving forward. With Chained Custom Hooks
hooks will execute in lexical order, failing on the first failing script.&lt;&#x2F;p&gt;

&lt;p&gt;This means you can create hooks &lt;code&gt;1-hook.sh&lt;&#x2F;code&gt; and &lt;code&gt;2-hook.sh&lt;&#x2F;code&gt; and you&#x27;ll know that
&lt;code&gt;1&lt;&#x2F;code&gt; will execute before &lt;code&gt;2&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;This gives a lot of power to your hooks and allows endless customization of
what happens when a commit is about to land in your GitLab project.&lt;&#x2F;p&gt;

&lt;p&gt;For more information, see the &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;administration&#x2F;custom_hooks.html#chained-hooks-support&quot;&gt;custom git hooks documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Thanks to both Elan Ruusamäe and Dirk Hörner for both helping to define Global Git Hooks and this feature, and providing the implementation!&lt;&#x2F;p&gt;

&lt;h2 id=&quot;ldap-group-membership-overrides-ee&quot;&gt;LDAP Group membership overrides (EE)&lt;&#x2F;h2&gt;

&lt;p&gt;In GitLab EE, you can sync any LDAP group with any GitLab group and give
everyone automatically a certain permission. For instance, you
can give everyone in the LDAP group &lt;code&gt;developers&lt;&#x2F;code&gt; the &lt;code&gt;Developer&lt;&#x2F;code&gt;
permission level. New developers just have to be added to the LDAP
group and GitLab will take care of giving them access automatically.&lt;&#x2F;p&gt;

&lt;p&gt;With GitLab 8.15, this has become even more powerful. In addition to the
automatically synced permissions, you can now override this permission
per user. This should make it easier to manage complex permissions across
groups and projects.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;ldap_overrides.gif&quot; alt=&quot;Override LDAP permissions in GitLab 8.15 EE&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;slack-chatops&quot;&gt;Slack Chatops&lt;&#x2F;h2&gt;

&lt;p&gt;After bringing Chatops to GitLab with &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;11&#x2F;22&#x2F;gitlab-8-14-released&#x2F;#chat-commands-experimental&quot;&gt;our Mattermost integration&lt;&#x2F;a&gt;,
we&#x27;re now doing the same for everyone using Slack! This
means you can create, show and search for issues straight from Slack. Super
convenient to bridge that gap from a casual conversation to an actual issue.&lt;&#x2F;p&gt;

&lt;p&gt;In addition, you can actually deploy from and to any environment.
For instance, you can do&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight plaintext&quot;&gt;&lt;code&gt;&#x2F;awesome-website deploy from staging to production
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;And GitLab will deploy the latest commit from staging onto master.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;slack.png&quot; alt=&quot;Slack Chatops in GitLab 8.15&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;Configure Chatops for Slack in your project services. As always,
we&#x27;re looking forward to see contributions to help expand the power of
chat integration with GitLab!&lt;&#x2F;p&gt;

&lt;h2 id=&quot;one-click-mattermost-configuration&quot;&gt;One-click Mattermost configuration&lt;&#x2F;h2&gt;

&lt;p&gt;Setting up the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;11&#x2F;22&#x2F;gitlab-8-14-released&#x2F;#chat-commands-experimental&quot;&gt;awesome Mattermost integration&lt;&#x2F;a&gt; with GitLab has been made
much easier. It&#x27;s a matter of a single click now, as you can see &lt;a href=&quot;https:&#x2F;&#x2F;youtu.be&#x2F;m0nYHPue5RU?t=196&quot;&gt;in the video at 3:16&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;mattermost.png&quot; alt=&quot;Super easy Mattermost configuration in GitLab 8.15&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;The Mattermost and Slack integrations allow you to do the same things:
create, show and search for issues and deploy to any environment.&lt;&#x2F;p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;help&#x2F;project_services&#x2F;mattermost_slash_commands.md&quot;&gt;Read the docs on the Mattermost Chatops integration&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;h2 id=&quot;diff-in-notification-emails&quot;&gt;Diff in Notification Emails&lt;&#x2F;h2&gt;

&lt;p&gt;When you get a notification email from a comment on a diff, GitLab will now
send along a bit of the diff, so you have the correct context immediately
available.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;diff_emails.png&quot; alt=&quot;Diffs in Notification emails in GitLab 8.15&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;interface-improvements&quot;&gt;Interface improvements&lt;&#x2F;h2&gt;

&lt;p&gt;Our amazing usability team has been working hard on making GitLab easier to use,
enhancing GitLab&#x27;s personality and improving readability. This release contains
various changes that will make using GitLab more enjoyable!&lt;&#x2F;p&gt;

&lt;h3 id=&quot;fresh-typefaces&quot;&gt;Fresh typefaces!&lt;&#x2F;h3&gt;

&lt;p&gt;To improve readability and cross-OS&#x2F;browser support in GitLab, we have
changed to using system fonts. These fonts are optimized for your platform
and should therefore provide a better experience, independent of where you&#x27;re
viewing GitLab from.&lt;&#x2F;p&gt;

&lt;p&gt;If you want to get a feel of GitLab across platforms, &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7545&quot;&gt;check out the original merge request&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;slimmed-down-widths&quot;&gt;Slimmed down widths&lt;&#x2F;h3&gt;

&lt;p&gt;We&#x27;ve reduced the max-width for issues and merge requests container in order to
provide a more readable line length. This is the first step for us to correct
the huge line lengths you see throughout GitLab.
Follow our &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;13680&quot;&gt;meta issue&lt;&#x2F;a&gt;
as we continue to improve GitLab&#x27;s line length.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;unique-labels&quot;&gt;Unique Labels&lt;&#x2F;h3&gt;

&lt;p&gt;We&#x27;ve given labels a unique look in order to differentiate them from buttons.
We are continuing work on this to make our
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;25518&quot;&gt;labels&lt;&#x2F;a&gt; and
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;25564&quot;&gt;status badges&lt;&#x2F;a&gt;
even more consistent in further iterations.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;labels.png&quot; alt=&quot;Unique Labels in GitLab 8.15&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h3 id=&quot;improved-build-scrolling-and-loading&quot;&gt;Improved Build Scrolling and Loading&lt;&#x2F;h3&gt;

&lt;p&gt;Build scrolling and loading works and looks quite a bit better now:&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;build_scroll.gif&quot; alt=&quot;Improved Build Scrolling and Loading in GitLab 8.15&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h3 id=&quot;smaller-page-size&quot;&gt;Smaller page size&lt;&#x2F;h3&gt;

&lt;p&gt;Between system fonts and improvements to autocomplete, we&#x27;ve reduced the
average page size of any page in GitLab significantly. A given merge request
in the GitLab CE project went from 1800kb to now 718kb!&lt;&#x2F;p&gt;

&lt;h3 id=&quot;improved-empty-states&quot;&gt;Improved empty states&lt;&#x2F;h3&gt;

&lt;p&gt;In order to improve our experience for users who are just getting started with
GitLab, we&#x27;ve added informative and fun empty states to many of our pages
across the application!
View our &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;15632&quot;&gt;meta issue&lt;&#x2F;a&gt; to
see where we&#x27;ve placed new empty states and feel free to suggest new ones!&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;empty.png&quot; alt=&quot;Even empty is beautiful in GitLab 8.15&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h3 id=&quot;other-changes-and-tweaks&quot;&gt;Other changes and tweaks&lt;&#x2F;h3&gt;

&lt;ul&gt;
  &lt;li&gt;Improved accessibility by adding a focus state to dropdown options&lt;&#x2F;li&gt;
  &lt;li&gt;Added hover states to our primary navigation and tabs throughout the site.&lt;&#x2F;li&gt;
  &lt;li&gt;Improved hover, focus, and active states for buttons &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7797&quot;&gt;!7797&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Added hover states to collapsed items with the issues&#x2F;mr&#x27;s sidebar &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7777&quot;&gt;!7777&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;mathematics-support-for-markdown-and-asciidoc-using-katex&quot;&gt;Mathematics support for Markdown and AsciiDoc, using KaTeX&lt;&#x2F;h2&gt;

&lt;p&gt;Comments and repository files can now contain beautifully-typeset mathematics, using the &lt;a href=&quot;https:&#x2F;&#x2F;khan.github.io&#x2F;KaTeX&#x2F;&quot;&gt;KaTeX&lt;&#x2F;a&gt; library from Khan Academy.&lt;&#x2F;p&gt;

&lt;p&gt;To render inline mathematics, use dollar signs around inline code: &lt;code&gt;$`a^2+b^2=c^2`$&lt;&#x2F;code&gt;&lt;&#x2F;p&gt;

&lt;p&gt;To render multiline mathematics, use the &lt;code&gt;math&lt;&#x2F;code&gt; language for the code block:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight plaintext&quot;&gt;&lt;code&gt;```math
a^2+b^2=c^2
```
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In addition to working for Markdown, this is also available for AsciiDoc documents. &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;user&#x2F;markdown.html#math&quot;&gt;Read the documentation on mathematics support.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;math.png&quot; alt=&quot;Beautifully rendered math in GitLab 8.15&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;Thanks to Michael Munch for this feature!&lt;&#x2F;p&gt;

&lt;h2 id=&quot;cleaner-merge-commit-messages&quot;&gt;Cleaner merge commit messages&lt;&#x2F;h2&gt;

&lt;p&gt;Previously, merge commit messages included the title and description of the
merge request, and a reference to the merge request. This didn&#x27;t read well when
using &lt;code&gt;git log&lt;&#x2F;code&gt; and similar tools, because merge request descriptions often
contain requests for review, screenshots, and other details incidental to the
code change.&lt;&#x2F;p&gt;

&lt;p&gt;Now, the default merge commit message is in the following format:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight plaintext&quot;&gt;&lt;code&gt;Merge branch &#x27;$SOURCE_BRANCH&#x27; into &#x27;$TARGET_BRANCH&#x27;

$TITLE

Closes $CLOSING_ISSUE_REFERENCES # only present if the MR closes issues

See merge request $MERGE_REQUEST_REFERENCE
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The previous default message is available as an option when customizing the
merge commit message.&lt;&#x2F;p&gt;

&lt;p&gt;Thanks to Gabriel Gizotti!&lt;&#x2F;p&gt;

&lt;h2 id=&quot;shorthand-cross-project-references-in-gitlab-flavored-markdown&quot;&gt;Shorthand cross-project references in GitLab Flavored Markdown&lt;&#x2F;h2&gt;

&lt;p&gt;Previously, a reference to something in another project always included the
namespace, even if the project was in the same namespace.&lt;&#x2F;p&gt;

&lt;p&gt;Now, shorthand references are available. So from within the
&lt;code&gt;gitlab-org&#x2F;gitlab-ce&lt;&#x2F;code&gt; project, you can refer to issue #1 in GitLab Workhorse
by writing &lt;code&gt;gitlab-workhorse#1&lt;&#x2F;code&gt; instead of &lt;code&gt;gitlab-org&#x2F;gitlab-workhorse#1&lt;&#x2F;code&gt;,
saving precious keystrokes!&lt;&#x2F;p&gt;

&lt;p&gt;For more information, see the &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;user&#x2F;markdown.html#special-gitlab-references&quot;&gt;special GitLab references&lt;&#x2F;a&gt; section of our Markdown documentation.&lt;&#x2F;p&gt;

&lt;p&gt;Thanks to Oswaldo Ferreira!&lt;&#x2F;p&gt;

&lt;h2 id=&quot;create-an-issue-with-unresolved-discussion-from-a-merge-request&quot;&gt;Create an issue with unresolved discussion from a merge request&lt;&#x2F;h2&gt;

&lt;p&gt;In 8.14, we &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;11&#x2F;22&#x2F;gitlab-8-14-released&#x2F;#prevent-merge-until-review-is-done&quot;&gt;added the ability to block a merge when there are unresolved discussions&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Now, we have added an option to &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;user&#x2F;project&#x2F;merge_requests&#x2F;merge_request_discussion_resolution.html#move-all-unresolved-discussions-in-a-merge-request-to-an-issue&quot;&gt;create a new issue from the unresolved discussions in a merge request&lt;&#x2F;a&gt;, and resolve those discussions at the same time! This is perfect for those cases where you need to merge something now, but don&#x27;t want to forget about the code review comments.&lt;&#x2F;p&gt;

&lt;p&gt;Thanks to Bob van Landuyt!&lt;&#x2F;p&gt;

&lt;h2 id=&quot;manual-actions-from-the-pipeline-graph&quot;&gt;Manual Actions from the Pipeline Graph&lt;&#x2F;h2&gt;

&lt;p&gt;Manual actions allow you to require manual interaction before moving
forward with a particular job in CI. Your entire pipeline can run
automatically, but the actual deploy to production will require a click.&lt;&#x2F;p&gt;

&lt;p&gt;You can do this straight from the pipeline graph. Just click on the play
button to execute that particular job.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;manual_actions_graph.png&quot; alt=&quot;Manual actions on the pipeline graph&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;user-activities-api&quot;&gt;User Activities API&lt;&#x2F;h2&gt;

&lt;p&gt;To quickly get an idea of when a user last interacted with GitLab,
we&#x27;ve added a special admin-only API to GitLab that allows you to get
the last activity timestamp of every user on the instance.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;api&#x2F;users.html#get-user-activities-admin-only&quot;&gt;Find the details in the docs&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;sort-project-and-group-members&quot;&gt;Sort Project and Group members&lt;&#x2F;h2&gt;

&lt;p&gt;You can now find people in projects and groups more easily by sorting them
by name, access level and date of joining.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;8_15&#x2F;sort_members.png&quot; alt=&quot;Easily find people in projects and groups in GitLab 8.15&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;api-changes&quot;&gt;API Changes&lt;&#x2F;h2&gt;

&lt;p&gt;Every month we make many additions to our API. Here are the highlights
for GitLab 8.15:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;Allow some Project API GET endpoints to be requested anonymously&lt;&#x2F;li&gt;
  &lt;li&gt;Allow Repositories &amp;amp; Files API GET endpoints to be requested anonymously&lt;&#x2F;li&gt;
  &lt;li&gt;Allow some Tag API GET endpoints to be requested anonymously&lt;&#x2F;li&gt;
  &lt;li&gt;Add scopes for personal access tokens and OAuth tokens&lt;&#x2F;li&gt;
  &lt;li&gt;Add ability to cherry pick a commit (community contribution)&lt;&#x2F;li&gt;
  &lt;li&gt;Add ability to unshare a project from a group (community contribution)&lt;&#x2F;li&gt;
  &lt;li&gt;Add ability to set &lt;code&gt;should_remove_source_branch&lt;&#x2F;code&gt; on merge requests (community contribution)&lt;&#x2F;li&gt;
  &lt;li&gt;Add simple representation of group&#x27;s projects (community contribution)&lt;&#x2F;li&gt;
  &lt;li&gt;Expose committer details for commits (community contribution)&lt;&#x2F;li&gt;
  &lt;li&gt;Expose merge status for branch API (community contribution)&lt;&#x2F;li&gt;
  &lt;li&gt;Expose personal snippets as &#x2F;snippets (community contribution)&lt;&#x2F;li&gt;
  &lt;li&gt;Expose pipeline coverage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;omnibus-gitlab-package-changes&quot;&gt;Omnibus GitLab package changes&lt;&#x2F;h2&gt;

&lt;h3 id=&quot;postgresql-version-upgrade&quot;&gt;PostgreSQL version upgrade&lt;&#x2F;h3&gt;

&lt;p&gt;Starting last month with GitLab 8.14 omnibus-gitlab package, we are providing a
way to upgrade the PostgreSQL database version.&lt;&#x2F;p&gt;

&lt;p&gt;The current version of PostgreSQL we are packaging (9.2.18) is slowly
approaching its EOL. Due to the &lt;a href=&quot;https:&#x2F;&#x2F;www.postgresql.org&#x2F;support&#x2F;versioning&#x2F;&quot;&gt;PostgreSQL versioning policy&lt;&#x2F;a&gt;,
upgrades between major releases require downtime and the use of the &lt;code&gt;pg_upgrade&lt;&#x2F;code&gt; tool.&lt;&#x2F;p&gt;

&lt;p&gt;For this purpose, we are packaging the newest available PostgreSQL version (9.6.1).
We are also introducing &lt;code&gt;gitlab-ctl pg-upgrade&lt;&#x2F;code&gt; tool which should make this
transition as painless as possible.
When upgrading to GitLab 8.15, this &lt;em&gt;action will not be run automatically&lt;&#x2F;em&gt;.
This will allow you to plan the database upgrade downtime.&lt;&#x2F;p&gt;

&lt;p&gt;After version 9.0 is released, we plan on setting the PostgreSQL version 9.6 as
default so please make sure that you plan your upgrade before that release.
We&#x27;re expecting to ship GitLab 9.0 on or after February 22nd.&lt;&#x2F;p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;omnibus&#x2F;settings&#x2F;database.html#upgrade-packaged-postgresql-server&quot;&gt;Read more about database upgrade in our docs&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;blockquote&gt;
  &lt;p&gt;Ran into issues? Create an issue at the &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;omnibus-gitlab&#x2F;issues&quot;&gt;omnibus-gitlab issue tracker&lt;&#x2F;a&gt;,
and reference it in the &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;omnibus-gitlab&#x2F;issues&#x2F;1783&quot;&gt;upgrade problems meta issue.&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;h2 id=&quot;performance-improvements&quot;&gt;Performance Improvements&lt;&#x2F;h2&gt;

&lt;p&gt;GitLab CE:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;Retrieving commit counts has been improved for certain cases: &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7668&quot;&gt;!7668&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Polling intervals have been adjusted to reduce system load: &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7762&quot;&gt;!7762&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Refreshing authorized projects is done in a smarter way to reduce database load: &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7956&quot;&gt;!7956&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;The most recent commit ID for a path is now cached: &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8098&quot;&gt;!8098&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;GitLab EE:&lt;&#x2F;p&gt;

&lt;p&gt;GitLab EE now ships with a command called &lt;code&gt;sidekiq-cluster&lt;&#x2F;code&gt;. This command can be used to start extra Sidekiq workers that process only a limited number of queues. This feature can be used to process queues that receive a lot of jobs, without it affecting other parts of Sidekiq. This was added in &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ee&#x2F;merge_requests&#x2F;922&quot;&gt;922&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;This command is not yet used by Omnibus, our goal is to add this in 8.16.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;gitlab-runner-19&quot;&gt;GitLab Runner 1.9&lt;&#x2F;h2&gt;

&lt;p&gt;We are also releasing GitLab Runner 1.9 today. Some highlights:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;Add a retry mechanism to prevent failed clones in builds &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;399&quot;&gt;!399&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Add Kubernete Node Selector &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;328&quot;&gt;!328&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Push prebuilt images to dockerhub &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;420&quot;&gt;!420&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Use prebuilt containers with Kubernetes executor &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;425&quot;&gt;!425&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Add path and share cache settings for S3 cache &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;423&quot;&gt;!423&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Split prepare stage to be: prepare, git_clone, restore_cache, download_artifacts &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;406&quot;&gt;!406&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Introduce docker.Client timeouts &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;411&quot;&gt;!411&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Allow network-sourced variables to specify that they should be files &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;413&quot;&gt;!413&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Fix docker hanging for docker-engine 1.12.4 &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;415&quot;&gt;!415&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Add pprof HTTP endpoints to metrics server &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;398&quot;&gt;!398&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;Add a multiple prometheus metrics: &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;merge_requests&#x2F;401&quot;&gt;!401&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;To see the full list of all changes please read &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ci-multi-runner&#x2F;blob&#x2F;v1.9.0&#x2F;CHANGELOG.md&quot;&gt;the Runner&#x27;s CHANGELOG file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;gitlab-mattermost-351&quot;&gt;GitLab Mattermost 3.5.1&lt;&#x2F;h2&gt;

&lt;p&gt;GitLab 8.15 includes &lt;a href=&quot;https:&#x2F;&#x2F;about.mattermost.com&#x2F;&quot;&gt;Mattermost 3.5.1&lt;&#x2F;a&gt;, an open
source Slack-alternative providing workplace messaging for web, PC and phone
with archiving and search. Improvements this month include new &lt;a href=&quot;https:&#x2F;&#x2F;about.mattermost.com&#x2F;mattermost-december-2016-update&#x2F;&quot;&gt;Xen Orchestra and Homebrew integrations, plus upgraded Desktop Apps for Windows, Mac and Linux&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;This version includes &lt;a href=&quot;http:&#x2F;&#x2F;about.mattermost.com&#x2F;security-updates&#x2F;&quot;&gt;security updates&lt;&#x2F;a&gt; and upgrade from earlier versions is recommended.&lt;&#x2F;p&gt;

&lt;p&gt;Mattermost 3.5.1 was included in GitLab 8.14.1, so anyone on GitLab 8.14.1 or
later should have the patch already.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;other-changes&quot;&gt;Other changes&lt;&#x2F;h2&gt;

&lt;p&gt;This release has more improvements. Please check out
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;blob&#x2F;master&#x2F;CHANGELOG.md&quot;&gt;the changelog&lt;&#x2F;a&gt; to see all the named changes.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;upgrade-barometer&quot;&gt;Upgrade barometer&lt;&#x2F;h2&gt;

&lt;p&gt;To upgrade to GitLab 8.15, downtime is required. Larger instances (&amp;gt;1000 users)
should expect about 15 minutes of downtime.&lt;&#x2F;p&gt;

&lt;p&gt;The specific migrations requiring downtime are described below.&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;Columns with default values are added, this process may take some time depending on the number of rows in these tables&lt;&#x2F;li&gt;
  &lt;li&gt;Some indexes are added concurrently, which does not require downtime but may take some time to complete&lt;&#x2F;li&gt;
  &lt;li&gt;The environments table is cleaned up, and a new column is added with a generated default value (this could take some time depending on the number of environments)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h3 id=&quot;note&quot;&gt;Note&lt;&#x2F;h3&gt;

&lt;p&gt;We assume you are upgrading from the latest version. If not, then also consult the upgrade barometers of any intermediate versions you are skipping.
If you are upgrading from a GitLab version prior to 8.0 &lt;em&gt;and&lt;&#x2F;em&gt; you have CI enabled, you have to upgrade to GitLab 8.0 &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2015&#x2F;09&#x2F;22&#x2F;gitlab-8-0-released&#x2F;&quot;&gt;first&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Please be aware that by default the Omnibus packages will stop, run migrations,
and start again, no matter how “big” or “small” the upgrade is. This behavior
can be changed by adding a &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;omnibus&#x2F;update&#x2F;README.html&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;gitlab&#x2F;skip-auto-migrations&lt;&#x2F;code&gt;
file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;hr &#x2F;&gt;

&lt;h2 id=&quot;installation&quot;&gt;Installation&lt;&#x2F;h2&gt;

&lt;p&gt;If you are setting up a new GitLab installation please see the
&lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;installation&#x2F;&quot;&gt;download GitLab page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;updating&quot;&gt;Updating&lt;&#x2F;h2&gt;

&lt;p&gt;Check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;update&#x2F;&quot;&gt;update page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;enterprise-edition&quot;&gt;Enterprise Edition&lt;&#x2F;h2&gt;

&lt;p&gt;The mentioned EE only features and things like LDAP group support can be found in GitLab Enterprise Edition.
For a complete overview please have a look at the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;features&#x2F;#enterprise&quot;&gt;feature list of GitLab EE&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Access to GitLab Enterprise Edition is included with a
&lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;pricing&#x2F;&quot;&gt;subscription&lt;&#x2F;a&gt;.
No time to upgrade GitLab yourself?
A subscription also entitles you to our upgrade and installation services.&lt;&#x2F;p&gt;

&lt;hr &#x2F;&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;8_15&#x2F;pic.jpg&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>How to Keep Remote (Volunteer) Teams Engaged</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/21/how-to-keep-remote-teams-engaged/"/>
    <id>https://about.gitlab.com/2016/12/21/how-to-keep-remote-teams-engaged/</id>
    <published>2016-12-21T00:00:00+00:00</published>
    <updated>2016-12-21T00:00:00+00:00</updated>
    <author>
      <name>Emily von Hoffmann</name>
    </author>
    <content type="html">
&lt;p&gt;We love hearing when people outside of GitLab read our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;handbook&#x2F;&quot;&gt;Handbook&lt;&#x2F;a&gt; – it&#x27;s totally public, after all, and it&#x27;s pretty comprehensive (or a behemoth, depending on your frame of mind). It was even more exciting to hear from James Telfer, of &lt;a href=&quot;http:&#x2F;&#x2F;ukseds.org&#x2F;&quot;&gt;UK Students for the Exploration and Development of Space&lt;&#x2F;a&gt; (UKSEDS) that he read the handbook and had further questions that we&#x27;d left unanswered. In particular – what to do when you have neither carrot nor stick when managing remote volunteers?&lt;&#x2F;p&gt;



&lt;p&gt;UKSEDS, a student-run charity that operates around the UK, offering career advice and skills support to students interested in the space industry, borrowed a lot from our handbook when making their constitution.&lt;&#x2F;p&gt;

&lt;p&gt;The internal engagement problem grew after UKSEDS experienced a growth surge and a structural change earlier this year. Specifically, James said:&lt;&#x2F;p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;Project teams are interacting okay with their direct managers but interaction with the wider organization is little to none. While this doesn&#x27;t directly impact work, we&#x27;re concerned about the longer-term impact on volunteer enjoyment and retention, both of which are really important to us.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;p&gt;Eliran Mesika, our Director of Strategic Partnerships, agreed to jump on the phone with James to learn more about UKSEDS&#x27; particular case and the challenges they faced.&lt;&#x2F;p&gt;

&lt;p&gt;Here are some highlights:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;Having individual responsibilities somewhere public (even internally) is a useful accountability tool, and helps direct team members to the correct person when they have a question.&lt;&#x2F;li&gt;
  &lt;li&gt;Functional group updates presented to the whole company make teams talk more, which results in more organic collaboration.&lt;&#x2F;li&gt;
  &lt;li&gt;Keeping communication on a specific topic within the right issue is essential for keeping everyone on the same page – especially when working asynchronously.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;Read on for Eliran&#x27;s tips.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;James:&lt;&#x2F;strong&gt; Our work involves hosting skills workshops and conducting outreach, which means traveling to schools and science fairs to tell kids that space is great and they should get involved. We recently restructured by creating a small executive group that meets every week, and allowing volunteer teams to grow larger and meet less frequently. We found that destroyed our ability to connect with the teams and we&#x27;ve started losing people; we&#x27;ve got quite a high attrition rate, which is normal for a charity. But I wondered how you approached this problem? Some of those things like the random Hangouts and the 1:1 chats work great as long as you can pay people for their work time. But with volunteers it&#x27;s a different problem entirely.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;Eliran:&lt;&#x2F;strong&gt; I&#x27;m actually working with Drupal, and I think your problem is more similar to an open source project, or an open source community behind a project. There is a major difference between volunteers and people who are being paid. Once you&#x27;re paying someone, you have their attention. Perhaps learning what open source projects do to engage their contributors may be helpful in your case. For now, I can share a bit about what we&#x27;re doing to keep people engaged and connected to the mission.&lt;&#x2F;p&gt;

&lt;p&gt;We&#x27;re an open core product, and since its inception the whole behavior and culture of the company has also been open. This extends to everything the company does: from the very technical details of a new feature that is being repaired or created, all the way to our high priorities and strategy, and the actual procedures the company follows, is documented and publicly shared. It is shared within the whole company, and is available all the time.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;James:&lt;&#x2F;strong&gt; How does that culture extend to individual responsibilities?&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;Eliran:&lt;&#x2F;strong&gt;
Expectations and responsibilities are also public. I handle strategic partnerships, and it&#x27;s pretty much just me doing this, but I can look at what anyone on our whole team is working on, without even having to ask them directly. On our team page, we have everyone&#x27;s job description linked, along with any specific responsibilities. So if you have frontend developers, maybe one is responsible for the website, and others are responsible for a particular set of features of the community edition, for example. You can understand at a glance who the right person is for what you&#x27;re interested in, and you can go into any repo and see what they&#x27;re working on. For the most part when we&#x27;re talking about procedures, we have the Handbook which describes everything about the administration and culture of the company. It goes into detail even about how to write a shared document that you work on. It also talks about what we do on a regular basis.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;James:&lt;&#x2F;strong&gt; Can you elaborate a bit on those routine things, like the daily calls?&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;Eliran:&lt;&#x2F;strong&gt; Our daily calls have worked really well for us. They&#x27;re optional, but we usually get maybe two-thirds of the company joining each day. We have functional updates, where we&#x27;ve divided teams into the various days of the week, and they give an update on what they&#x27;ve completed over the past few weeks, which gives the whole company insight into what the marketing team is doing, what the CI team is doing, and what they&#x27;re working on next. It really connects you with the whole scope, rather than just seeing your team&#x27;s goals and your individual goals in a vacuum.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;James:&lt;&#x2F;strong&gt; So that&#x27;s using what other people are doing to remind an individual person or team that the greater company exists – it&#x27;s not so much that they&#x27;d be interested in the technical details, but it reminds them they&#x27;re part of something bigger? Is that the key there?&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;Eliran:&lt;&#x2F;strong&gt; Yeah I think it&#x27;s very important to give people insight into what other teams are doing, because it&#x27;s remote. That&#x27;s really key. Otherwise, it seems like when people are working remotely it&#x27;s very easy to feel isolated. Having those functional updates forces you out of isolation and connects you with the bigger goal. And on a personal level, it connects you with other people&#x27;s work. As you said, even if you&#x27;re not a technical person, you&#x27;ll still get a high-level understanding of the product or what the objective was. That&#x27;s great for creating a more cohesive environment, and it&#x27;s remained the same since I joined.&lt;&#x2F;p&gt;

&lt;blockquote&gt;
  &lt;p&gt;It&#x27;s very important to give people insight into what other teams are doing – having funtional updates forces you out of isolation and connects you with the bigger goal&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;p&gt;We also have a second part of the call where people share what they did last weekend. So once a week you have an opportunity to talk about your personal life, we rotate so everyone shares their experiences. I think that&#x27;s a very powerful tool to connect on a social level, even if you&#x27;re not talking with people on a regular basis. Typically you&#x27;re working with a team of 5-10 people, and you&#x27;ll be part of a group that&#x27;s maybe 30 people. So at best you&#x27;ll know 30 people, and you won&#x27;t talk to them on a regular basis. You know the regular few people that you talk to, and I think that&#x27;s very narrow if you&#x27;re part of a bigger group. But the way that we do these individual stories helps make everyone feel closer.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;James&lt;&#x2F;strong&gt;: I can see one definite scope for improvement for us, because we haven&#x27;t been very good at pulling the teams together. They&#x27;re sort of sandboxed at the moment.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;Eliran;&lt;&#x2F;strong&gt; I think you&#x27;ll notice that once teams start talking about what they&#x27;re doing, obviously all teams have touch points that they&#x27;ve been speaking with others about, but you&#x27;ll have more organic collaboration. Just by talking about what they&#x27;re thinking about doing, or trying to do. That&#x27;s the best case scenario. At the most basic level, you&#x27;ll get people to be aware of what&#x27;s going on.&lt;&#x2F;p&gt;

&lt;p&gt;We also have a second type of meeting, which is an open meeting focused on a certain department or area. We have a kick-off meeting for a product, or for example we have a monthly release cycle, and anyone can come to those meetings to learn more about what&#x27;s going on. Our marketing team also has those meetings for example, to talk about new efforts and past performance.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;James:&lt;&#x2F;strong&gt; How else do people reach out to work together?&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;Eliran:&lt;&#x2F;strong&gt; We use Slack for communication, and I&#x27;m not sure how that would work in an environment like yours, without volunteers dedicating a certain amount of time every day. But we have channels for everything, and the whole team is distributed across channels. We have #general, which is the channel Emily used to ask &quot;Hey is there anyone relevant who&#x27;d like to help James and talk about remote work at his organization?&quot; We also have a #questions channel, where anyone can ask anything from the most sophisticated to the stupidest. They just throw their question to the channel and people try to help them or steer them in the right direction for who to talk to. Another channel that&#x27;s really important is the #thanks channel, and I feel that&#x27;s an important part to offer gratitude to someone for helping you, and also receive that when you&#x27;ve helped someone. Because of the remote environment it&#x27;s very powerful. Because GitLab&#x27;s culture is built on asynchronous work – people in different time zones – you&#x27;re not on Slack all the time because others will pick up your question whenever they become available.&lt;&#x2F;p&gt;

&lt;p&gt;One other thing that&#x27;s working well is centralizing a process for working asynchronously. So, we try to make all the work and communication and discussion on GitLab by using issues. Someone will create an issue with a particular task or mission, and then the whole communication is available there. So people have access to information or decisions or a process on a specific area. Even if you&#x27;re not involved, you can comment and say, &quot;Hey I&#x27;d like to suggest a, b, c.&quot; So by virtue of being in different time zones, we were forced to use asynchronous methods of work, and issues work very well for that. Having the discussion tools integrated into that, and using it to keep everything in one work space dedicated to a specific topic, is great for remote teams. If you can&#x27;t always set a time for everyone to sit down together, using issues is crucial to making work happen.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;James:&lt;&#x2F;strong&gt; We do use Slack, because, as you may recall as a student you may as well be in different time zones, waking up at 9 am one day and 1 pm the next. Are there decisions made on Slack, or do you tell people, &quot;No this is a discussion, take it to x issue&quot;?&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;Eliran:&lt;&#x2F;strong&gt; We may have those specific discussions on Slack, but for the most part, maybe 95% of the decisions are happening within the issue. But we don&#x27;t discourage people from talking, so there could be times when you have to talk to someone or a group of people, because there&#x27;s only so much you can do over text. So you may make a decision over Hangout, but that is communicated back through the issue. Someone will go back and say &quot;I had a discussion with Mark, and we decided the best way to move forward is x.&quot; That way everyone has the opportunity to get the takeaways from that meeting and give input. So some decisions happen away from the issues. But it&#x27;s important to reinforce that we try to keep communication on a specific topic within an issue. We really push that, and it&#x27;s part of the culture at GitLab. As you keep growing, the sooner you adopt changes in a working culture, the better it is for people to learn them later on.&lt;&#x2F;p&gt;

&lt;p&gt;Read more about &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;12&#x2F;05&#x2F;how-we-stay-connected-as-a-remote-company&#x2F;&quot;&gt;how we stay connected as a remote company&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;em&gt;Tweet us &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gitlab&quot;&gt;@GitLab&lt;&#x2F;a&gt; and check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;jobs&#x2F;&quot;&gt;job openings&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;!-- cover image: https:&#x2F;&#x2F;www.pexels.com&#x2F;photo&#x2F;people-coffee-meeting-team-7096&#x2F; --&gt;

&lt;!-- cover image license: CC0: https:&#x2F;&#x2F;www.pexels.com&#x2F;photo-license&#x2F; --&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;blogimages&#x2F;how-to-keep-remote-teams-engaged-cover.jpg&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>A creative agency's GitLab wishlist</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/15/a-creative-agencys-gitlab-wishlist/"/>
    <id>https://about.gitlab.com/2016/12/15/a-creative-agencys-gitlab-wishlist/</id>
    <published>2016-12-15T00:00:00+00:00</published>
    <updated>2016-12-15T00:00:00+00:00</updated>
    <author>
      <name>Emily von Hoffmann</name>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;wvkuipers&quot;&gt;Wouter van Kuipers&lt;&#x2F;a&gt; is an engineer at &lt;a href=&quot;https:&#x2F;&#x2F;www.lukkien.com&#x2F;en&#x2F;&quot;&gt;Lukkien&lt;&#x2F;a&gt;, a creative agency that produces online media, photography, film, apps, CGI, and graphic design. His team currently works on a platform aimed at parents and healthcare professionals. They&#x27;ve used a combination of Jenkins and GitLab, although they are switching to GitLab CI for testing. He told me his team tends to use the collaboration tools of GitLab the most. Before GitLab, they used SVN, and ultimately decided on GitLab instead of a competitor because they needed to host on-premises for security reasons. Our service engineer &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;leematos&quot;&gt;Lee Matos&lt;&#x2F;a&gt; sat down with Wouter to learn about how GitLab can help.&lt;&#x2F;p&gt;



&lt;p&gt;Here are some items discussed below and requested by the Lukkien team:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;A view that will let you see changes over builds, and how builds are affected over time.&lt;&#x2F;li&gt;
  &lt;li&gt;Notifications around CI builds, so if there are any related tickets, those get updated as well.&lt;&#x2F;li&gt;
  &lt;li&gt;Versioning for Photoshop and InDesign files.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;Wouter:&lt;&#x2F;strong&gt; We struggle as a team and company to find a good versioning system for our (UX) designs. Right now we create separate folders and label the versions of our InDesign and Photoshop files. We want to know the latest version, but also want to have a clear visual representation of the changes between versions. Is there any planning for tooling like that in GitLab in the (near) feature?&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;Lee:&lt;&#x2F;strong&gt; Frankly, this is on our dream feature list. I think everybody on our team wants to be able to version Photoshop and InDesign documents, but we don’t have a good solution for those files right now that&#x27;s going to work smoothly. It looks like Adobe is getting into the versioning space for files like these, so there’s a silver lining here in that once Adobe solves that problem, we’ll probably do something similar quickly thereafter.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;Wouter:&lt;&#x2F;strong&gt; My next question is that we are hosting GitLab using a Docker setup, this works quite well but we are not sure if this will create limitations in the long run, for example if we want to use Mattermost in the future? My team has 8-10 developers, but we use the setup for all our teams, we’re all in the same GitLab instance. So that’s 100-120 developers.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;Lee:&lt;&#x2F;strong&gt; That&#x27;s what I would call GitLab Small&#x2F;Medium-sized. As it stands, we think that will be fine, there are no limitations even with Mattermost and we don’t expect there to be any problems. Obviously if there are, we’ll explore that with you and figure it out. Our product team leads aren&#x27;t aware of running GitLab in Docker at a big scale (1000+) – most of those clients are running it directly in a VM or Bare Metal. We feel that obviously Docker is the future so we need to find the answer to these questions. If you run into anything, please bring it up in an issue. And the same goes for Docker in Mattermost, we don’t expect anything different.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;&lt;strong&gt;Wouter:&lt;&#x2F;strong&gt; Finally, in what way does GitLab want to position itself in the long run compared to GitHub?&lt;&#x2F;p&gt;

&lt;p&gt;&lt;strong&gt;Lee:&lt;&#x2F;strong&gt; The best way to think about it, for me, is we are actually more like Atlassian. Our end goal is to build what Atlassian ended up with by acquiring the little pieces, by instead building those parts and making them 100 percent cohesive. So it’s more about building an end-to-end development tool that allows your team to work together and converse and go. Our buzz phrase at this point is &quot;From idea to production&quot;, so we want to cover everything over that process, and make it faster, whatever you’re using GitLab for. That’s even our goal internally as well, so it excites me because we’re actually using GitLab to build it.&lt;&#x2F;p&gt;

&lt;p&gt;I think GitHub is positioning itself as more of a core component, they see Git and code as the core thing that needs to be solved, and are leaving integrations up to the third parties. We have integrations and we see the value in them, but we want to build something that allows you to start making things work out of the box. Instead of saying &quot;You need to go buy Drone CI, you need to use Waffle.io, and need to wire them all up and read 10 different documentations to figure it out.&quot; We want that process to be as easy as possible.&lt;&#x2F;p&gt;

&lt;p&gt;Image &lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;lennykphotography&#x2F;26687024535&#x2F;in&#x2F;photolist-GEeYCF-hUAGKL-nQCwXy-Emhqdz-HRUzeG-EeGxU4-p2KCQa-Eroe6z-e4BpVm-dcZWfj-mQnNTJ-atd2f5-DSYEyA-DSqqGk-DFXwUA-aHPQVk-GucZJZ-EDGjje-CS8FYi-rymZ62-EBjtSY-DSfzQT-avJQMx-aYtqkR-CztMC7-dTRM3q-EPK3hD-DpeasQ-f2hdPB-eRwBGC-EoaxPD-b18F74-9sd1No-bkNuRx-byvPzZ-hxRZyb-D7F1xM-EVqmsh-CVBJBa-9pnw9W-eBWbNx-ftZrun-DXtJuT-p8As5e-DWQhdR-bkNdg7-oQCcaJ-b3JagT-8VoF1U-cgzLCU&quot;&gt;&quot;Lightroom Preset Balloon Release&quot;&lt;&#x2F;a&gt; by &lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;lennykphotography&#x2F;&quot;&gt;Lenny K Photography&lt;&#x2F;a&gt; is licensed under &lt;a href=&quot;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by&#x2F;4.0&#x2F;legalcode&quot;&gt;CC BY 4.0&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;em&gt;We want you to ask us anything! If you&#x27;re a user interested in sharing your story on our blog, please fill out this &lt;a href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;a&#x2F;gitlab.com&#x2F;forms&#x2F;d&#x2F;1K8ZTS1QvSSPos6mVh1ol8ZyagInYctX3fb9eglzeK70&#x2F;edit&quot;&gt;form&lt;&#x2F;a&gt;  and we’ll get in touch!&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;p&gt;&lt;em&gt;Tweet us &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;gitlab&quot;&gt;@GitLab&lt;&#x2F;a&gt; and check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;jobs&#x2F;&quot;&gt;job openings&lt;&#x2F;a&gt;.&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;blogimages&#x2F;a-creative-agencys-gitlab-wishlist.jpg&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>GitLab 8.14.5, 8.13.10, and 8.12.13 Released</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/14/gitlab-8-dot-14-dot-5-released/"/>
    <id>https://about.gitlab.com/2016/12/14/gitlab-8-dot-14-dot-5-released/</id>
    <published>2016-12-14T19:00:00+00:00</published>
    <updated>2016-12-14T19:00:00+00:00</updated>
    <author>
      <name>GitLab</name>
    </author>
    <content type="html">
&lt;p&gt;Today we are releasing versions 8.14.5, 8.13.10, and 8.12.13 for GitLab Community
Edition (CE) and Enterprise Edition (EE).&lt;&#x2F;p&gt;

&lt;p&gt;These versions contain important security fixes, and we recommend that all
affected GitLab installations be upgraded to one of these versions.&lt;&#x2F;p&gt;

&lt;p&gt;Please read on for more details.&lt;&#x2F;p&gt;



&lt;h2 id=&quot;security-fixes-in-8145-81310-and-81213&quot;&gt;Security fixes in 8.14.5, 8.13.10 and 8.12.13&lt;&#x2F;h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix missing Note access checks in by moving Note#search to updated NoteFinder (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;23867&quot;&gt;#23867&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Filter &lt;code&gt;incoming_email_token&lt;&#x2F;code&gt; and &lt;code&gt;runners_token&lt;&#x2F;code&gt; parameters (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;25687&quot;&gt;#25687&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;security-fixes-in-8145-and-81310&quot;&gt;Security fixes in 8.14.5 and 8.13.10&lt;&#x2F;h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Issue#visible_to_user moved to IssuesFinder (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;24637&quot;&gt;#24637&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h3 id=&quot;other-fixes-in-8145-81213-and-81310&quot;&gt;Other fixes in 8.14.5, 8.12.13 and 8.13.10&lt;&#x2F;h3&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; API: Memoize the current_user so that the sudo can work properly. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8017&quot;&gt;!8017&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h3 id=&quot;other-fixes-in-8145&quot;&gt;Other fixes in 8.14.5&lt;&#x2F;h3&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Omnibus GitLab&lt;&#x2F;strong&gt;: Add attribute client_output_buffer_limit_slave for redis (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;omnibus-gitlab&#x2F;merge_requests&#x2F;1147&quot;&gt;!1147&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
  &lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Remove &#x27;Leave Project&#x27; and &#x27;Leave Group&#x27; from settings dropdowns (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7600&quot;&gt;!7600&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix display hook error message (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7775&quot;&gt;!7775&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Shows group members in the project members list (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7899&quot;&gt;!7899&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Correct autocomplete for values with special characters (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7910&quot;&gt;!7910&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Remove wrong &#x27;.builds-feature&#x27; class from the MR settings fieldset (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7930&quot;&gt;!7930&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Avoid escaping relative links in Markdown twice (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7940&quot;&gt;!7940&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Allow branch names with dots on API endpoint (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7963&quot;&gt;!7963&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fixed timeago re-rendering every element (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7969&quot;&gt;!7969&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Use a single query in Projects::ProjectMembersController to fetch members (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7997&quot;&gt;!7997&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Displays milestone remaining days only when it&#x27;s present (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7998&quot;&gt;!7998&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix Crontab typo for PruneOldEventsWorker to run 4x&#x2F;day instead of 60x&#x2F;hour (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8051&quot;&gt;!8051&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Encode when migrating ProcessCommitWorker jobs (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8064&quot;&gt;!8064&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Updates the docs to require GitLab Shell 4.0.3 (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;8050&quot;&gt;!8050&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
  &lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;EE:&lt;&#x2F;strong&gt; Fix milestone total weight is missing on the milestone page (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ee&#x2F;merge_requests&#x2F;944&quot;&gt;!944&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;EE:&lt;&#x2F;strong&gt; Remove wrong &#x27;.builds-feature&#x27; class from the MR settings fieldset (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ee&#x2F;merge_requests&#x2F;947&quot;&gt;!947&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;EE:&lt;&#x2F;strong&gt; Group members in project members view (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ee&#x2F;merge_requests&#x2F;958&quot;&gt;!958&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;upgrade-barometer&quot;&gt;Upgrade barometer&lt;&#x2F;h2&gt;

&lt;p&gt;These versions do include a single migration, and will require brief
downtime of typically less than one minute.&lt;&#x2F;p&gt;

&lt;p&gt;Please be aware that by default the Omnibus packages will stop, run migrations,
and start again, no matter how “big” or “small” the upgrade is. This behavior
can be changed by adding a &lt;a href=&quot;http:&#x2F;&#x2F;doc.gitlab.com&#x2F;omnibus&#x2F;update&#x2F;README.html&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;gitlab&#x2F;skip-auto-migrations&lt;&#x2F;code&gt;
file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;updating&quot;&gt;Updating&lt;&#x2F;h2&gt;

&lt;p&gt;To update, check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;update&quot;&gt;update page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;enterprise-edition&quot;&gt;Enterprise Edition&lt;&#x2F;h2&gt;

&lt;p&gt;Interested in GitLab Enterprise Edition? Check out the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;features&#x2F;#enterprise&quot;&gt;features exclusive to
EE&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Access to GitLab Enterprise Edition is included with a
&lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;pricing&#x2F;&quot;&gt;subscription&lt;&#x2F;a&gt;. No time to upgrade GitLab
yourself? Subscribers receive upgrade and installation services.&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;default-blog-image.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>Continuous Delivery of a Spring Boot application with GitLab CI and Kubernetes</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/"/>
    <id>https://about.gitlab.com/2016/12/14/continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes/</id>
    <published>2016-12-14T00:00:00+00:00</published>
    <updated>2016-12-14T00:00:00+00:00</updated>
    <author>
      <name>Marco Lenzo</name>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;08&#x2F;05&#x2F;continuous-integration-delivery-and-deployment-with-gitlab&#x2F;&quot;&gt;Continuous Integration, Continuous Deployment and Continuous Delivery&lt;&#x2F;a&gt; are increasingly popular topics among modern development teams. Together they enable a team to build, test and deploy the code at any commit. The main benefit of these approaches is the ability to release more quality code more frequently through the means of automated pipelines. The tough part is building such pipelines. There is a myriad of tools available which we would need to choose, learn, install, integrate, and maintain.&lt;&#x2F;p&gt;

&lt;p&gt;Recently, I literally fell in love with &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;&quot;&gt;GitLab&lt;&#x2F;a&gt;! It offers a fully featured ecosystem of tools which enable us to create an automated pipeline in minutes! From source control to issue tracking and CI, we find everything under one roof, fully integrated and ready to use.&lt;&#x2F;p&gt;



&lt;p&gt;In this tutorial, we will create a &lt;a href=&quot;https:&#x2F;&#x2F;projects.spring.io&#x2F;spring-boot&#x2F;&quot;&gt;Spring Boot&lt;&#x2F;a&gt; application built, tested, and deployed with &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;gitlab-ci&#x2F;&quot;&gt;GitLab CI&lt;&#x2F;a&gt; on a &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;&quot;&gt;Kubernetes&lt;&#x2F;a&gt; cluster. Spring Boot is the leading &lt;a href=&quot;http:&#x2F;&#x2F;microservices.io&#x2F;patterns&#x2F;microservice-chassis.html&quot;&gt;microservice chassis&lt;&#x2F;a&gt; for Java. It allows a developer to build a production-grade stand-alone application, like a typical &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Create,_read,_update_and_delete&quot;&gt;CRUD&lt;&#x2F;a&gt; application exposing a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Representational_state_transfer&quot;&gt;RESTful API&lt;&#x2F;a&gt;, with minimal configuration, reducing the learning curve required for using the &lt;a href=&quot;https:&#x2F;&#x2F;spring.io&#x2F;&quot;&gt;Spring Framework&lt;&#x2F;a&gt; drastically. Kubernetes is an open-source container orchestrator inspired by &lt;a href=&quot;http:&#x2F;&#x2F;static.googleusercontent.com&#x2F;media&#x2F;research.google.com&#x2F;en&#x2F;&#x2F;pubs&#x2F;archive&#x2F;43438.pdf&quot;&gt;Google Borg&lt;&#x2F;a&gt; that schedules, scales and manages containerized applications.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;create-a-gitlab-project&quot;&gt;Create a GitLab project&lt;&#x2F;h2&gt;

&lt;p&gt;Let&#x27;s start by &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;projects&#x2F;new&quot;&gt;creating a new project&lt;&#x2F;a&gt; in GitLab named &lt;code&gt;actuator-sample&lt;&#x2F;code&gt;. Then we follow the command line instructions displayed in the project&#x27;s home page to clone the repository on our machine and perform the first commit.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git clone git@gitlab.com:marcolenzo&#x2F;actuator-sample.git
&lt;span class=&quot;nb&quot;&gt;cd &lt;&#x2F;span&gt;actuator-sample
touch README.md
git add README.md
git commit -m &lt;span class=&quot;s2&quot;&gt;&quot;add README&quot;&lt;&#x2F;span&gt;
git push -u origin master
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p class=&quot;alert alert-info&quot;&gt;Always replace &lt;code&gt;marcolenzo&lt;&#x2F;code&gt; with your own GitLab username whenever copying a snippet of code from this tutorial.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;create-a-spring-boot-application&quot;&gt;Create a Spring Boot application&lt;&#x2F;h2&gt;

&lt;p&gt;To bootstrap the Spring Boot application we navigate to the &lt;a href=&quot;https:&#x2F;&#x2F;start.spring.io&quot;&gt;Spring Initializr&lt;&#x2F;a&gt; web page and generate a &lt;strong&gt;Maven Project&lt;&#x2F;strong&gt; with the pre-selected Spring Boot &lt;strong&gt;Version&lt;&#x2F;strong&gt;. &lt;a href=&quot;https:&#x2F;&#x2F;maven.apache.org&#x2F;index.html&quot;&gt;Maven&lt;&#x2F;a&gt; is a project management tool commonly used in Java projects to define dependencies and the build lifecycle. We leave &lt;code&gt;com.example&lt;&#x2F;code&gt; as &lt;strong&gt;Group&lt;&#x2F;strong&gt; and set &lt;code&gt;actuator-sample&lt;&#x2F;code&gt; as the &lt;strong&gt;Artifact&lt;&#x2F;strong&gt; name. We select the &lt;code&gt;Web&lt;&#x2F;code&gt; dependency, which supports full stack web development with &lt;a href=&quot;http:&#x2F;&#x2F;tomcat.apache.org&#x2F;&quot;&gt;Tomcat&lt;&#x2F;a&gt; and &lt;a href=&quot;http:&#x2F;&#x2F;docs.spring.io&#x2F;spring&#x2F;docs&#x2F;current&#x2F;spring-framework-reference&#x2F;html&#x2F;mvc.html&quot;&gt;Spring MVC&lt;&#x2F;a&gt;, and the &lt;code&gt;Actuator&lt;&#x2F;code&gt; dependency which implements some production-grade features useful for monitoring and managing our application like health-checks and HTTP requests traces.&lt;&#x2F;p&gt;

&lt;p&gt;Finally, we generate the project and a Zip file named &lt;code&gt;actuator-sample.zip&lt;&#x2F;code&gt; will be downloaded to our machine.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes&#x2F;initializr.png&quot; alt=&quot;Spring Initializr&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;We can now unzip the archive and launch the application immediately. Spring Initializr has already created everything for us. We just need to have a &lt;a href=&quot;http:&#x2F;&#x2F;openjdk.java.net&#x2F;install&#x2F;&quot;&gt;Java JDK&lt;&#x2F;a&gt; 1.7 or later installed on our machine and the &lt;code&gt;JAVA_HOME&lt;&#x2F;code&gt; environment variable set accordingly. &lt;a href=&quot;http:&#x2F;&#x2F;openjdk.java.net&#x2F;&quot;&gt;OpenJDK&lt;&#x2F;a&gt; is the preferred option for most Linux distributions since it is readily available on their repositories. You can alternatively install &lt;a href=&quot;http:&#x2F;&#x2F;www.oracle.com&#x2F;technetwork&#x2F;java&#x2F;javase&#x2F;downloads&#x2F;index.html&quot;&gt;Oracle JDK&lt;&#x2F;a&gt; if it is a strict requirement for your team.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;### Installing OpenJDK 8 on Debian, Ubuntu, etc.&lt;&#x2F;span&gt;

sudo apt-get install openjdk-8-jre

&lt;span class=&quot;c&quot;&gt;### Installing OpenJDK 8 on Fedora, Oracle Linux, Red Hat Enteprise, CentOS, etc.&lt;&#x2F;span&gt;

su -c &lt;span class=&quot;s2&quot;&gt;&quot;yum install java-1.8.0-openjdk&quot;&lt;&#x2F;span&gt;

&lt;span class=&quot;c&quot;&gt;### Setting the JAVA_HOME environment variable&lt;&#x2F;span&gt;

&lt;span class=&quot;nb&quot;&gt;export &lt;&#x2F;span&gt;&lt;span class=&quot;nv&quot;&gt;JAVA_HOME&lt;&#x2F;span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;&#x2F;span&gt;&#x2F;path&#x2F;to&#x2F;your&#x2F;java&#x2F;home &lt;span class=&quot;c&quot;&gt;# e.g. &#x2F;usr&#x2F;lib&#x2F;jvm&#x2F;java-8-openjdk-amd64&#x2F;&lt;&#x2F;span&gt;

&lt;span class=&quot;c&quot;&gt;### Extracting and launching the application&lt;&#x2F;span&gt;

&lt;span class=&quot;gp&quot;&gt;~&#x2F;git&#x2F;actuator-sample$ &lt;&#x2F;span&gt;unzip ~&#x2F;Downloads&#x2F;actuator-sample.zip -d ..&#x2F;
&lt;span class=&quot;gp&quot;&gt;~&#x2F;git&#x2F;actuator-sample$ &lt;&#x2F;span&gt;.&#x2F;mvnw spring-boot:run

&lt;span class=&quot;o&quot;&gt;[&lt;&#x2F;span&gt;...]

2016-12-02 22:41:14.376  INFO 10882 --- &lt;span class=&quot;o&quot;&gt;[&lt;&#x2F;span&gt;           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port&lt;span class=&quot;o&quot;&gt;(&lt;&#x2F;span&gt;s&lt;span class=&quot;o&quot;&gt;)&lt;&#x2F;span&gt;: 8080 &lt;span class=&quot;o&quot;&gt;(&lt;&#x2F;span&gt;http&lt;span class=&quot;o&quot;&gt;)&lt;&#x2F;span&gt;
2016-12-02 22:41:14.420  INFO 10882 --- &lt;span class=&quot;o&quot;&gt;[&lt;&#x2F;span&gt;           main] com.example.ActuatorSampleApplication    : Started ActuatorSampleApplication &lt;span class=&quot;k&quot;&gt;in &lt;&#x2F;span&gt;17.924 seconds &lt;span class=&quot;o&quot;&gt;(&lt;&#x2F;span&gt;JVM running &lt;span class=&quot;k&quot;&gt;for &lt;&#x2F;span&gt;87.495&lt;span class=&quot;o&quot;&gt;)&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The application is up and running and we did not write one line of code! Spring Boot is opinionated and auto-configures the application with sane default values and beans. It also scans the classpath for known dependencies and initializes them. In our case, we immediately enjoy all the production-grade services offered by &lt;a href=&quot;http:&#x2F;&#x2F;docs.spring.io&#x2F;spring-boot&#x2F;docs&#x2F;current&#x2F;reference&#x2F;html&#x2F;production-ready-endpoints.html&quot;&gt;Spring Actuator&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;~$ &lt;&#x2F;span&gt;curl http:&#x2F;&#x2F;localhost:8080&#x2F;health
&lt;span class=&quot;o&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;status&quot;&lt;&#x2F;span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;UP&quot;&lt;&#x2F;span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;diskSpace&quot;&lt;&#x2F;span&gt;:&lt;span class=&quot;o&quot;&gt;{&lt;&#x2F;span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;status&quot;&lt;&#x2F;span&gt;:&lt;span class=&quot;s2&quot;&gt;&quot;UP&quot;&lt;&#x2F;span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;total&quot;&lt;&#x2F;span&gt;:981190307840,&lt;span class=&quot;s2&quot;&gt;&quot;free&quot;&lt;&#x2F;span&gt;:744776503296,&lt;span class=&quot;s2&quot;&gt;&quot;threshold&quot;&lt;&#x2F;span&gt;:10485760&lt;span class=&quot;o&quot;&gt;}}&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p class=&quot;alert alert-info&quot;&gt;If you wish to learn Spring Boot in greater detail, have a look at their &lt;a href=&quot;http:&#x2F;&#x2F;docs.spring.io&#x2F;spring-boot&#x2F;docs&#x2F;current&#x2F;reference&#x2F;htmlsingle&#x2F;&quot;&gt;reference documentation&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;spring.io&#x2F;guides&quot;&gt;guides&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;It is time to commit our changes and push them to &lt;code&gt;origin&lt;&#x2F;code&gt;. To simplify things a bit, we commit directly on &lt;code&gt;master&lt;&#x2F;code&gt; without using &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;workflow&#x2F;gitlab_flow.html#github-flow-as-a-simpler-alternative&quot;&gt;feature branches&lt;&#x2F;a&gt; since collaboration is not the focus of this tutorial. Later, we will use &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;workflow&#x2F;gitlab_flow.html#environment-branches-with-gitlab-flow&quot;&gt;environment branches&lt;&#x2F;a&gt; as specified in the &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;workflow&#x2F;gitlab_flow.html&quot;&gt;GitLab Flow&lt;&#x2F;a&gt; to deploy to different environments selectively, e.g. staging and production. If you are not familiar with the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2014&#x2F;09&#x2F;29&#x2F;gitlab-flow&#x2F;&quot;&gt;GitLab Flow&lt;&#x2F;a&gt;, I strongly recommend you to read its documentation.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git add --all
git commit -m &lt;span class=&quot;s2&quot;&gt;&quot;Creates actuator-example application&quot;&lt;&#x2F;span&gt;
git push origin master
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;creating-a-continuous-delivery-pipeline-with-gitlab-ci&quot;&gt;Creating a Continuous Delivery pipeline with GitLab CI&lt;&#x2F;h2&gt;

&lt;p&gt;While our code is now safe on GitLab, we still need to automate its integration and deployment. We need to verify each commit with an automated build and set of tests in order to discover issues as early as possible and, if the build is successful, deploy to a target environment. A few years ago, our only option was to install, configure and maintain a CI Server like &lt;a href=&quot;https:&#x2F;&#x2F;jenkins.io&#x2F;&quot;&gt;Jenkins&lt;&#x2F;a&gt; and possibly automate our deployment with a set of bash scripts. While the number of options has grown significantly, whether hosted or on the cloud, we still need to find a way to integrate our source control system with the CI Server of our choice.&lt;&#x2F;p&gt;

&lt;p&gt;Not anymore though! GitLab has fully integrated CI and CD Pipelines in its offering, allowing us to &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;10&#x2F;25&#x2F;gitlab-workflow-an-overview&#x2F;#build-test-and-deploy&quot;&gt;build, test and deploy&lt;&#x2F;a&gt; our code with ease.&lt;&#x2F;p&gt;

&lt;p&gt;For the purpose of this tutorial we will deploy to the &lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;container-engine&#x2F;&quot;&gt;Google Cloud Container Engine&lt;&#x2F;a&gt; which is a cluster management and orchestration system built on the open source &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;&quot;&gt;Kubernetes&lt;&#x2F;a&gt;. Kubernetes is supported by all main cloud providers and can be &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;getting-started-guides&#x2F;kubeadm&#x2F;&quot;&gt;easily installed on any Linux server&lt;&#x2F;a&gt; in minutes. That said, we will be able to re-use this configuration virtually on any environment running Kubernetes.&lt;&#x2F;p&gt;

&lt;p&gt;Before we can proceed to the creation of the pipeline, we need to add a couple of files to our repository to package our application as a Docker container and to describe the target deployment in Kubernetes terms.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;packaging-a-spring-boot-application-as-a-docker-container&quot;&gt;Packaging a Spring Boot application as a Docker container&lt;&#x2F;h3&gt;

&lt;p&gt;Let&#x27;s start by creating the &lt;code&gt;Dockerfile&lt;&#x2F;code&gt; in the root directory of our project.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;FROM openjdk:8u111-jdk-alpine
VOLUME &#x2F;tmp
ADD &#x2F;target&#x2F;actuator-sample-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT &lt;span class=&quot;o&quot;&gt;[&lt;&#x2F;span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;java&quot;&lt;&#x2F;span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;-Djava.security.egd=file:&#x2F;dev&#x2F;.&#x2F;urandom&quot;&lt;&#x2F;span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;-jar&quot;&lt;&#x2F;span&gt;,&lt;span class=&quot;s2&quot;&gt;&quot;&#x2F;app.jar&quot;&lt;&#x2F;span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;FROM&lt;&#x2F;code&gt; keyword defines the base Docker image of our container. We chose &lt;a href=&quot;http:&#x2F;&#x2F;openjdk.java.net&#x2F;&quot;&gt;OpenJDK&lt;&#x2F;a&gt; installed on &lt;a href=&quot;https:&#x2F;&#x2F;alpinelinux.org&#x2F;&quot;&gt;Alpine Linux&lt;&#x2F;a&gt; which is a lightweight Linux distribution. The &lt;code&gt;VOLUME&lt;&#x2F;code&gt; instruction creates a mount point with the specified name and marks it as holding externally mounted volumes from the native host or other containers. &lt;code&gt;ADD&lt;&#x2F;code&gt; copies the executable JAR generated during the build to the container root directory. Finally &lt;code&gt;ENTRYPOINT&lt;&#x2F;code&gt; defines the command to execute when the container is started. Since Spring Boot produces an executable JAR with embedded Tomcat, the command to execute is simply &lt;code&gt;java -jar app.jar&lt;&#x2F;code&gt;. The additiona flag &lt;code&gt;java.security.edg=file:&#x2F;dev&#x2F;.&#x2F;urandom&lt;&#x2F;code&gt; is used to speed up the application start-up and avoid possible freezes. By default, Java uses &lt;code&gt;&#x2F;dev&#x2F;random&lt;&#x2F;code&gt; to seed its &lt;code&gt;SecureRandom&lt;&#x2F;code&gt; class which is known to block if its entropy pool is empty.&lt;&#x2F;p&gt;

&lt;p&gt;Time to commit.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git add Dockerfile
git commit -m &lt;span class=&quot;s2&quot;&gt;&quot;Adds Dockerfile&quot;&lt;&#x2F;span&gt;
git push origin master
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;define-the-kubernetes-deployment&quot;&gt;Define the Kubernetes Deployment&lt;&#x2F;h3&gt;

&lt;p&gt;Let&#x27;s create a file named &lt;code&gt;deployment.yml&lt;&#x2F;code&gt; in the root directory of our project.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;apiVersion&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;extensions&#x2F;v1beta1&lt;&#x2F;span&gt;
&lt;span class=&quot;na&quot;&gt;kind&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;Deployment&lt;&#x2F;span&gt;
&lt;span class=&quot;na&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;actuator-sample&lt;&#x2F;span&gt;
&lt;span class=&quot;na&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;replicas&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;2&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;template&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;metadata&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;na&quot;&gt;labels&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
        &lt;span class=&quot;na&quot;&gt;app&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;actuator-sample&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;spec&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;na&quot;&gt;containers&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;actuator-sample&lt;&#x2F;span&gt;
        &lt;span class=&quot;na&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;registry.gitlab.com&#x2F;marcolenzo&#x2F;actuator-sample&lt;&#x2F;span&gt;
        &lt;span class=&quot;na&quot;&gt;imagePullPolicy&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;Always&lt;&#x2F;span&gt;
        &lt;span class=&quot;na&quot;&gt;ports&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;na&quot;&gt;containerPort&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;8080&lt;&#x2F;span&gt;
      &lt;span class=&quot;na&quot;&gt;imagePullSecrets&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
        &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;registry.gitlab.com&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the definition of a Kubernetes &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;user-guide&#x2F;deployments&#x2F;&quot;&gt;&lt;code&gt;Deployment&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; named &lt;code&gt;actuator-sample&lt;&#x2F;code&gt;. The &lt;code&gt;replicas&lt;&#x2F;code&gt; element defines the target number of &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;user-guide&#x2F;pods&#x2F;&quot;&gt;&lt;code&gt;Pods&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. Kubernetes performs automated binpacking and self-healing of the system to comply with the deployment specifications while achieving optimal utilization of compute resources. A Pod can be composed of multiple containers. In this scenario, we only include the &lt;code&gt;actuator-sample&lt;&#x2F;code&gt; image stored on our private &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;05&#x2F;23&#x2F;gitlab-container-registry&#x2F;&quot;&gt;GitLab Container Registry&lt;&#x2F;a&gt;. For this reason, we need to set an entry under the &lt;code&gt;imagePullSecrets&lt;&#x2F;code&gt; which is used to authenticate to the GitLab Container Registry.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;For a detailed explanation of Kubernetes resources and concepts refer to the &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;&quot;&gt;official documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Time to commit again and we are ready to define our GitLab CI pipeline.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git add deployment.yml
git commit -m &lt;span class=&quot;s2&quot;&gt;&quot;Adds Kubernetes Deployment definition&quot;&lt;&#x2F;span&gt;
git push origin master
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;creating-the-gitlab-ci-pipeline&quot;&gt;Creating the GitLab CI pipeline&lt;&#x2F;h3&gt;

&lt;p&gt;In order to make use of &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;gitlab-ci&#x2F;&quot;&gt;GitLab CI&lt;&#x2F;a&gt; we need to add the &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;yaml&#x2F;&quot;&gt;&lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; configuration file to the root directory of our repository. This file is used by &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;ci&#x2F;runners&#x2F;README.html&quot;&gt;GitLab Runners&lt;&#x2F;a&gt; to manage our project&#x27;s builds and deployments. Therein we can define an unlimited number of &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;yaml&#x2F;#jobs&quot;&gt;Jobs&lt;&#x2F;a&gt; and their role in the whole build lifecycle.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;docker:latest&lt;&#x2F;span&gt;
&lt;span class=&quot;na&quot;&gt;services&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;docker:dind&lt;&#x2F;span&gt;

&lt;span class=&quot;na&quot;&gt;variables&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;DOCKER_DRIVER&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;overlay&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;SPRING_PROFILES_ACTIVE&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gitlab-ci&lt;&#x2F;span&gt;

&lt;span class=&quot;na&quot;&gt;stages&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;build&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;package&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;deploy&lt;&#x2F;span&gt;

&lt;span class=&quot;na&quot;&gt;maven-build&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;maven:3-jdk-8&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;build&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;&#x2F;span&gt;&lt;span class=&quot;s&quot;&gt;mvn&lt;&#x2F;span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;s&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;s&quot;&gt;-B&quot;&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;artifacts&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;paths&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;target&#x2F;*.jar&lt;&#x2F;span&gt;

&lt;span class=&quot;na&quot;&gt;docker-build&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;package&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;docker build -t registry.gitlab.com&#x2F;marcolenzo&#x2F;actuator-sample .&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;docker push registry.gitlab.com&#x2F;marcolenzo&#x2F;actuator-sample&lt;&#x2F;span&gt;

&lt;span class=&quot;na&quot;&gt;k8s-deploy&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;google&#x2F;cloud-sdk&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;deploy&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;echo &quot;$GOOGLE_KEY&quot; &amp;gt; key.json&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud auth activate-service-account --key-file key.json&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set compute&#x2F;zone europe-west1-c&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set project actuator-sample&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set container&#x2F;use_client_certificate True&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud container clusters get-credentials actuator-sample&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl delete secret registry.gitlab.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl create secret docker-registry registry.gitlab.com --docker-server=https:&#x2F;&#x2F;registry.gitlab.com --docker-username=marcolenzo --docker-password=$REGISTRY_PASSWD --docker-email=lenzo.marco@gmail.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl apply -f deployment.yml&lt;&#x2F;span&gt; 
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Let&#x27;s break the file in pieces to understand what is going on.&lt;&#x2F;p&gt;

&lt;h4 id=&quot;image-and-services&quot;&gt;Image and Services&lt;&#x2F;h4&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;docker:latest&lt;&#x2F;span&gt;
&lt;span class=&quot;na&quot;&gt;services&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;docker:dind&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ee&#x2F;ci&#x2F;runners&#x2F;README.html&quot;&gt;GitLab Runner&lt;&#x2F;a&gt; can &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;docker&#x2F;using_docker_images.html&quot;&gt;use Docker images&lt;&#x2F;a&gt; to support our pipelines. The &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;yaml&#x2F;#image-and-services&quot;&gt;&lt;code&gt;image&lt;&#x2F;code&gt; element&lt;&#x2F;a&gt; defines the name of the Docker image we want to use. Valid images are those hosted in the local Docker Engine or on &lt;a href=&quot;https:&#x2F;&#x2F;hub.docker.com&#x2F;&quot;&gt;Docker Hub&lt;&#x2F;a&gt;. The &lt;code&gt;services&lt;&#x2F;code&gt; element defines additional Docker images which are linked to the main container. In our case the main container is a plain Docker image while the linked container is enabled for running Docker in Docker.&lt;&#x2F;p&gt;

&lt;h4 id=&quot;variables&quot;&gt;Variables&lt;&#x2F;h4&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;variables&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;DOCKER_DRIVER&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;overlay&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;SPRING_PROFILES_ACTIVE&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gitlab-ci&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is the definition of &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;yaml&#x2F;#variables&quot;&gt;&lt;code&gt;variables&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; to be set on our build environment. The &lt;code&gt;DOCKER_DRIVER&lt;&#x2F;code&gt; signals the Docker Engine which storage driver to use. We use &lt;code&gt;overlay&lt;&#x2F;code&gt; for &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;docker&#x2F;using_docker_build.html#using-the-overlayfs-driver&quot;&gt;performance reasons&lt;&#x2F;a&gt;. The &lt;code&gt;SPRING_PROFILES_ACTIVE&lt;&#x2F;code&gt; is very useful when dealing with Spring Boot applications. It activates &lt;a href=&quot;http:&#x2F;&#x2F;docs.spring.io&#x2F;autorepo&#x2F;docs&#x2F;spring-boot&#x2F;current&#x2F;reference&#x2F;html&#x2F;boot-features-profiles.html&quot;&gt;Spring Profiles&lt;&#x2F;a&gt;, which provide a way to segregate parts of our application configuration and make it available only in certain environments. For instance, we can define different database URIs per environment, e.g. &lt;code&gt;localhost&lt;&#x2F;code&gt; when running on the developer machine and &lt;code&gt;mongo&lt;&#x2F;code&gt; when running within GitLab CI.&lt;&#x2F;p&gt;

&lt;h4 id=&quot;stages&quot;&gt;Stages&lt;&#x2F;h4&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;stages&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;build&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;package&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;deploy&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;yaml&#x2F;#stages&quot;&gt;&lt;code&gt;stages&lt;&#x2F;code&gt; element&lt;&#x2F;a&gt; defines the lifecycle of our build. We associate each &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;yaml&#x2F;#jobs&quot;&gt;job&lt;&#x2F;a&gt; with one stage. All jobs within a stage are run in parallel and stages are triggered sequentially in the order we define them, i.e. the next stage is initiated only when the previous one is complete.&lt;&#x2F;p&gt;

&lt;h4 id=&quot;the--job&quot;&gt;The &lt;code&gt;maven-build&lt;&#x2F;code&gt; job&lt;&#x2F;h4&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;maven-build&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;maven:3-jdk-8&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;build&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;&#x2F;span&gt;&lt;span class=&quot;s&quot;&gt;mvn&lt;&#x2F;span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;s&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;s&quot;&gt;-B&quot;&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;artifacts&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;paths&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;target&#x2F;*.jar&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This is a job definition. Jobs can have any name except keywords. Have a look at the &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt; &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;yaml&#x2F;&quot;&gt;documentation&lt;&#x2F;a&gt; for the complete list of keywords.&lt;&#x2F;p&gt;

&lt;p&gt;The scope of this job is to perform a &lt;a href=&quot;https:&#x2F;&#x2F;maven.apache.org&#x2F;index.html&quot;&gt;Maven&lt;&#x2F;a&gt; build. For this reason, we define the &lt;code&gt;maven:3-jdk-8&lt;&#x2F;code&gt; as the Docker image on which this job should execute. This image comes with Maven 3 and the Java JDK 8 pre-installed for us.&lt;&#x2F;p&gt;

&lt;p&gt;We then specify &lt;code&gt;build&lt;&#x2F;code&gt; as the &lt;code&gt;stage&lt;&#x2F;code&gt; of this job. Jobs associated with the same stage run concurrently. This is extremely useful if you need to cross-compile your application. For instance, if we wanted to compile and test our application also on Java JDK 7, we could simply create another job with a different name and use the image &lt;code&gt;maven:3-jdk-7&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;maven-test-jdk-7&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;maven:3-jdk-7&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;build&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;&#x2F;span&gt;&lt;span class=&quot;s&quot;&gt;mvn&lt;&#x2F;span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;s&quot;&gt;package&lt;&#x2F;span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;&#x2F;span&gt;&lt;span class=&quot;s&quot;&gt;-B&quot;&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;artifacts&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;paths&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
      &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;target&#x2F;*.jar&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;As previously said, the &lt;code&gt;maven-test-jdk-7&lt;&#x2F;code&gt; job runs in parallel with the &lt;code&gt;maven-build&lt;&#x2F;code&gt;. Hence, it does not have an impact on the pipeline execution time.&lt;&#x2F;p&gt;

&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;yaml&#x2F;#script&quot;&gt;&lt;code&gt;script&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is a shell command to be executed by the GitLab Runner. The &lt;code&gt;mvn package -B&lt;&#x2F;code&gt; triggers a non-interactive Maven build up to the &lt;code&gt;package&lt;&#x2F;code&gt; phase. This phase is specific to the &lt;a href=&quot;https:&#x2F;&#x2F;maven.apache.org&#x2F;guides&#x2F;introduction&#x2F;introduction-to-the-lifecycle.html&quot;&gt;Maven build lifecycle&lt;&#x2F;a&gt; and it includes also the &lt;code&gt;validate&lt;&#x2F;code&gt;, &lt;code&gt;compile&lt;&#x2F;code&gt; and &lt;code&gt;test&lt;&#x2F;code&gt; phases. That means that our Maven project will be validated, compiled and (unit) tested as well. Tests are to be included in the &lt;code&gt;src&#x2F;test&#x2F;java&lt;&#x2F;code&gt; folder. In our specific case, Spring Initializr has already created a unit test which verifies that the application context loads without errors. We are free to add as many unit tests as we like. Finally, the &lt;code&gt;package&lt;&#x2F;code&gt; phase creates the executable JAR.&lt;&#x2F;p&gt;

&lt;p&gt;To persist the executable JAR and share it across jobs, we specify job &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;yaml&#x2F;#artifacts&quot;&gt;&lt;code&gt;artifacts&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;. These are files or directories that are attached to the build after success and made downloadable from the UI in the Pipelines screen.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes&#x2F;artifacts.png&quot; alt=&quot;Downloading artifacts from pipelines&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h4 id=&quot;the--job-1&quot;&gt;The &lt;code&gt;docker-build&lt;&#x2F;code&gt; job&lt;&#x2F;h4&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;docker-build&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;package&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;docker build -t registry.gitlab.com&#x2F;marcolenzo&#x2F;actuator-sample .&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;docker login -u gitlab-ci-token -p $CI_BUILD_TOKEN registry.gitlab.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;docker push registry.gitlab.com&#x2F;marcolenzo&#x2F;actuator-sample&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;docker-build&lt;&#x2F;code&gt; job packages the application into a Docker container. We define &lt;code&gt;package&lt;&#x2F;code&gt; as the build &lt;code&gt;stage&lt;&#x2F;code&gt; since we need the &lt;code&gt;maven-build&lt;&#x2F;code&gt; job to produce the executable JAR beforehand.&lt;&#x2F;p&gt;

&lt;p&gt;The scripts are a typical sequence of &lt;code&gt;docker&lt;&#x2F;code&gt; commands used to build an image, log in to a private registry and push the image to it. We will be pushing images to the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;05&#x2F;23&#x2F;gitlab-container-registry&#x2F;&quot;&gt;GitLab Container Registry&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;user&#x2F;project&#x2F;new_ci_build_permissions_model.html#container-registry&quot;&gt;&lt;code&gt;$CI_BUILD_TOKEN&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; is a pre-defined variable which is injected by GitLab CI into our build environment automatically. It is used to log in to the GitLab Container Registry.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;For a complete list of pre-defined variables, have a look at the &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;variables&#x2F;README.html#variables&quot;&gt;variables documentation&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h4 id=&quot;the--job-2&quot;&gt;The &lt;code&gt;k8s-deploy&lt;&#x2F;code&gt; job&lt;&#x2F;h4&gt;

&lt;p&gt;This job is responsible for deploying our application to the &lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;container-engine&#x2F;&quot;&gt;Google Container Engine&lt;&#x2F;a&gt;. I purposely decided to make use of the &lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;sdk&#x2F;gcloud&#x2F;&quot;&gt;Google Cloud SDK&lt;&#x2F;a&gt; (&lt;code&gt;gcloud&lt;&#x2F;code&gt;) because it gives us the possibility to programmatically create and manage Google Container Engine clusters and other products of the Google Cloud ecosystem. In this tutorial, we will simplify things a bit by creating the Google Container Engine cluster beforehand through the GUI.&lt;&#x2F;p&gt;

&lt;p&gt;First, we create a Google Cloud Project named &lt;code&gt;actuator-sample&lt;&#x2F;code&gt;. Take note of the &lt;code&gt;Project ID&lt;&#x2F;code&gt; since it sometimes differs from the project name we specify. Then we create a Google Container Engine cluster named &lt;code&gt;actuator-sample&lt;&#x2F;code&gt; as well. We can choose any machine type and any number of nodes. For the purpose of this tutorial one node and a small machine are sufficient. Let&#x27;s take note of the &lt;code&gt;zone&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes&#x2F;create-gce-cluster.png&quot; alt=&quot;Create a container cluster&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;Finally we need to create a service account which is necessary to perform a non-interactive login with &lt;code&gt;gcloud&lt;&#x2F;code&gt;. Navigate to Google Cloud &lt;strong&gt;API Manager&lt;&#x2F;strong&gt; &amp;gt; &lt;strong&gt;Credentials&lt;&#x2F;strong&gt; &amp;gt; &lt;strong&gt;Create Credentials&lt;&#x2F;strong&gt; and create a JSON key for the &lt;code&gt;Compute Engine default service account&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;We can now analyze the configuration.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;k8s-deploy&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;google&#x2F;cloud-sdk&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;deploy&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;echo &quot;$GOOGLE_KEY&quot; &amp;gt; key.json&lt;&#x2F;span&gt; &lt;span class=&quot;c1&quot;&gt;# Google Cloud service account key&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud auth activate-service-account --key-file key.json&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set compute&#x2F;zone europe-west1-c&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set project actuator-sample&lt;&#x2F;span&gt; 
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set container&#x2F;use_client_certificate True&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud container clusters get-credentials actuator-example&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl delete secret registry.gitlab.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl create secret docker-registry registry.gitlab.com --docker-server=https:&#x2F;&#x2F;registry.gitlab.com --docker-username=marcolenzo --docker-password=$REGISTRY_PASSWD --docker-email=lenzo.marco@gmail.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl apply -f deployment.yml&lt;&#x2F;span&gt; 
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;We use the &lt;code&gt;google&#x2F;cloud-sdk&lt;&#x2F;code&gt; image for this process since it comes preloaded with &lt;code&gt;gcloud&lt;&#x2F;code&gt; and all components and dependencies of the Google Cloud SDK including alpha and beta components. We obviously chose &lt;code&gt;deploy&lt;&#x2F;code&gt; as the &lt;code&gt;stage&lt;&#x2F;code&gt; since we want our application to be packaged beforehand and its container pushed to the GitLab Container Registry. Then we execute a set of scripts.&lt;&#x2F;p&gt;

&lt;p&gt;The &lt;code&gt;echo &quot;$GOOGLE_KEY&quot; &amp;gt; key.json&lt;&#x2F;code&gt; script injects the Google Cloud service account key in the container. &lt;code&gt;$GOOGLE_KEY&lt;&#x2F;code&gt; is a Secure Variable having the content of the Google Cloud service account key as its value. &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;variables&#x2F;#user-defined-variables-secure-variables&quot;&gt;Secure Variables&lt;&#x2F;a&gt; are user-defined variables that should not be shown in the &lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt;. They are set per project by navigating to &lt;strong&gt;Project&lt;&#x2F;strong&gt; &amp;gt; &lt;strong&gt;Variables&lt;&#x2F;strong&gt; &amp;gt; &lt;strong&gt;Add Variable&lt;&#x2F;strong&gt; in GitLab.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes&#x2F;secure-variables.png&quot; alt=&quot;Secure Variables&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;The &lt;code&gt;gcloud auth activate-service-account --key-file key.json&lt;&#x2F;code&gt; script performs the non-interactive authentication process. The &lt;code&gt;gcloud config set ...&lt;&#x2F;code&gt; scripts are selecting the target project, zone and cluster. Make sure these values correspond to those you jotted down before. The &lt;code&gt;gcloud container clusters get-credentials actuator-example&lt;&#x2F;code&gt; script downloads the &lt;code&gt;kubectl&lt;&#x2F;code&gt; configuration file. If we wanted to use Kubernetes on another cloud provider or custom installation, we would source the &lt;code&gt;kubectl&lt;&#x2F;code&gt; configuration &lt;code&gt;~&#x2F;.kube&#x2F;config&lt;&#x2F;code&gt; without the need to interact with &lt;code&gt;gcloud&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;The &lt;code&gt;kubectl create secret docker-registry ...&lt;&#x2F;code&gt; script creates the &lt;code&gt;imagePullSecret&lt;&#x2F;code&gt; we had defined in the &lt;code&gt;deployment.yml&lt;&#x2F;code&gt;. This is used by Kubernetes to authenticate with our private GitLab Container Registry and download the container images. The &lt;code&gt;kubectl delete secret&lt;&#x2F;code&gt; is necessary because the Kubernetes API is lacking the &lt;code&gt;replace&lt;&#x2F;code&gt; operation for &lt;code&gt;docker-registry&lt;&#x2F;code&gt; secrets. In a real-world scenario, I would suggest handling &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;docs&#x2F;user-guide&#x2F;secrets&#x2F;&quot;&gt;Kubernetes secrets&lt;&#x2F;a&gt; that can affect multiple pipelines (such as a password for a private Docker registry) in a separate pipeline or through configuration management tools like &lt;a href=&quot;https:&#x2F;&#x2F;www.ansible.com&#x2F;&quot;&gt;Ansible&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;saltstack.com&#x2F;&quot;&gt;Salt&lt;&#x2F;a&gt;, &lt;a href=&quot;https:&#x2F;&#x2F;puppet.com&#x2F;&quot;&gt;Puppet&lt;&#x2F;a&gt; or &lt;a href=&quot;https:&#x2F;&#x2F;www.chef.io&#x2F;&quot;&gt;Chef&lt;&#x2F;a&gt;. The reason is that such secrets should be rotated periodically for security reasons and updated in each GitLab project using them. There is also the risk of interference between pipelines because of the &lt;code&gt;kubectl delete&lt;&#x2F;code&gt; command. Note that &lt;code&gt;$REGISTRY_PASSWD&lt;&#x2F;code&gt; is another Secure Variable.&lt;&#x2F;p&gt;

&lt;p&gt;Time to check if everything is in order on our cluster.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;gp&quot;&gt;$ &lt;&#x2F;span&gt;kubectl get deployments
NAME              DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
actuator-sample   2         2         2            2           2m
&lt;span class=&quot;gp&quot;&gt;$ &lt;&#x2F;span&gt;kubectl get pods
NAME                               READY     STATUS    RESTARTS   AGE
actuator-sample-3641958612-3e5xy   1&#x2F;1       Running   0          2m
actuator-sample-5542343546-fr4gh   1&#x2F;1       Running   0          2m
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes&#x2F;kubernetes.png&quot; alt=&quot;Kubernetes&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;Deployed!&lt;&#x2F;p&gt;

&lt;h4 id=&quot;gitlab-environments&quot;&gt;GitLab Environments&lt;&#x2F;h4&gt;

&lt;p&gt;Before concluding the tutorial, we will learn about &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;environments.html&quot;&gt;GitLab Environments&lt;&#x2F;a&gt; which enable us to track environments and deployments.&lt;&#x2F;p&gt;

&lt;p&gt;Let&#x27;s refactor the &lt;code&gt;k8s-deploy&lt;&#x2F;code&gt; job and split it in two. One job will target the staging environment and the other production.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight yaml&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;k8s-deploy-staging&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;google&#x2F;cloud-sdk&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;deploy&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;echo &quot;$GOOGLE_KEY&quot; &amp;gt; key.json&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud auth activate-service-account --key-file key.json&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set compute&#x2F;zone europe-west1-c&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set project actuator-sample&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set container&#x2F;use_client_certificate True&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud container clusters get-credentials actuator-example&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl delete secret registry.gitlab.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl create secret docker-registry registry.gitlab.com --docker-server=https:&#x2F;&#x2F;registry.gitlab.com --docker-username=marcolenzo --docker-password=$REGISTRY_PASSWD --docker-email=lenzo.marco@gmail.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl apply -f deployment.yml --namespace=staging&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;environment&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;staging&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;https:&#x2F;&#x2F;example.staging.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;only&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;master&lt;&#x2F;span&gt;

&lt;span class=&quot;na&quot;&gt;k8s-deploy-production&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;image&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;google&#x2F;cloud-sdk&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;stage&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;deploy&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;script&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;echo &quot;$GOOGLE_KEY&quot; &amp;gt; key.json&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud auth activate-service-account --key-file key.json&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set compute&#x2F;zone europe-west1-c&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set project actuator-sample&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud config set container&#x2F;use_client_certificate True&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;gcloud container clusters get-credentials actuator-example&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl delete secret registry.gitlab.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl create secret docker-registry registry.gitlab.com --docker-server=https:&#x2F;&#x2F;registry.gitlab.com --docker-username=marcolenzo --docker-password=$REGISTRY_PASSWD --docker-email=lenzo.marco@gmail.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;kubectl apply -f deployment.yml --namespace=production&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;environment&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;name&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;production&lt;&#x2F;span&gt;
    &lt;span class=&quot;na&quot;&gt;url&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;https:&#x2F;&#x2F;example.production.com&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;when&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;manual&lt;&#x2F;span&gt;
  &lt;span class=&quot;na&quot;&gt;only&lt;&#x2F;span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;&#x2F;span&gt;
  &lt;span class=&quot;pi&quot;&gt;-&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;production&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The &lt;code&gt;environment&lt;&#x2F;code&gt; keyword associates the job with a specific environment while the &lt;code&gt;url&lt;&#x2F;code&gt; element is used to generate a handy hyperlink to our application on the GitLab Environments page (found under your project&#x27;s &lt;code&gt;Pipelines &amp;gt; Environments&lt;&#x2F;code&gt;). The &lt;code&gt;only&lt;&#x2F;code&gt; keyword signals to GitLab CI that the job should be executed only when the pipeline is building the listed branches. Finally, &lt;code&gt;when: manual&lt;&#x2F;code&gt; is used to turn the job execution from automatic to manual. Turning the execution of this job to &lt;code&gt;automatic&lt;&#x2F;code&gt; would project us in the world of &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;08&#x2F;05&#x2F;continuous-integration-delivery-and-deployment-with-gitlab&#x2F;#continuous-deployment&quot;&gt;Continuous Deployment&lt;&#x2F;a&gt; rather than &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;08&#x2F;05&#x2F;continuous-integration-delivery-and-deployment-with-gitlab&#x2F;#continuous-delivery&quot;&gt;Continuous Delivery&lt;&#x2F;a&gt;. From a Kubernetes perspective, we are making use of &lt;code&gt;namespaces&lt;&#x2F;code&gt; to segregate the different environments.&lt;&#x2F;p&gt;

&lt;p&gt;By committing on &lt;code&gt;master&lt;&#x2F;code&gt; and &lt;code&gt;production&lt;&#x2F;code&gt; we &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;08&#x2F;26&#x2F;ci-deployment-and-environments&#x2F;&quot;&gt;trigger a pipeline per environment&lt;&#x2F;a&gt;. As mentioned before, we are not making use of any collaboration tool because it is out of the scope of this tutorial. In real-world scenarios, we would use &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;10&#x2F;25&#x2F;gitlab-workflow-an-overview&#x2F;#merge-request&quot;&gt;merge requests&lt;&#x2F;a&gt; with &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;features&#x2F;review-apps&#x2F;&quot;&gt;Review Apps&lt;&#x2F;a&gt; to move code across branches. Merge requests allow the team to review and discuss the changes before they get merged into the target branch. &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;features&#x2F;review-apps&#x2F;&quot;&gt;Review Apps&lt;&#x2F;a&gt; take that one step further by spinning up dynamic environments for our merge requests, offering the team access to a deployed instance of our application without the need of checking out the branch. This is extremely useful not only for non-technical members of the team, but also to collaborators and project managers to preview the changes without having to clone and install the app and its dependencies when evaluating a proposal.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git commit -am &lt;span class=&quot;s2&quot;&gt;&quot;Showcasing Pipelines&quot;&lt;&#x2F;span&gt;
git push origin master
git checkout -b production
git push origin production
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes&#x2F;pipelines.png&quot; alt=&quot;Pipelines&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;The Pipelines screen details all pipeline executions. We can gather information about the branch and the individual result of each stage. In the case of the &lt;code&gt;production&lt;&#x2F;code&gt; pipeline the &lt;code&gt;k8s-deploy-production&lt;&#x2F;code&gt; is not executed automatically as expected but can be triggered from the GUI from where we can also download the build artifacts.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes&#x2F;environments.png&quot; alt=&quot;Environments&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;Environments are listed on a separate page, from which it is possible to redeploy the latest version of an environment or to roll back to a particular version of the environment by accessing the relative details page.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;continuous-delivery-of-a-spring-boot-application-with-gitlab-ci-and-kubernetes&#x2F;rollbacks.png&quot; alt=&quot;Rollbacks&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;

&lt;p&gt;In this tutorial, we were able to create a &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Continuous_delivery&quot;&gt;Continuous Delivery&lt;&#x2F;a&gt; pipeline with ease thanks to the suite of &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;&quot;&gt;GitLab&lt;&#x2F;a&gt; products that supported us at every stage. &lt;a href=&quot;https:&#x2F;&#x2F;projects.spring.io&#x2F;spring-boot&#x2F;&quot;&gt;Spring Boot&lt;&#x2F;a&gt; gave us agility by auto-configuring the application context and offering production-grade services out of the box. &lt;a href=&quot;http:&#x2F;&#x2F;kubernetes.io&#x2F;&quot;&gt;Kubernetes&lt;&#x2F;a&gt; abstracted us from the compute resources and orchestration duties allowing us to define only the desired deployment state. &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;gitlab-ci&#x2F;&quot;&gt;GitLab CI&lt;&#x2F;a&gt; was the core engine of our pipeline. Its declarative &lt;a href=&quot;https:&#x2F;&#x2F;docs.gitlab.com&#x2F;ce&#x2F;ci&#x2F;yaml&#x2F;&quot;&gt;&lt;code&gt;.gitlab-ci.yml&lt;&#x2F;code&gt;&lt;&#x2F;a&gt; file allowed us to define, version and manage our pipelines while the GUI gave us full visibility and control.&lt;&#x2F;p&gt;

&lt;p&gt;While this is a basic example, it clearly shows the immense benefits any team or company can gain by using the unified GUI of GitLab for issues, code review, CI and CD.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;about-guest-author&quot;&gt;About Guest Author&lt;&#x2F;h2&gt;

&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;marco_lenzo&quot;&gt;Marco Lenzo&lt;&#x2F;a&gt; is a Software Architect always up for a challenge. He has expertise in transaction processing and platform as a service (PaaS). Java, Spring, Go and Kubernetes are currently his bread and butter.&lt;&#x2F;p&gt;

&lt;!-- closes https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-com&#x2F;blog-posts&#x2F;issues&#x2F;309 --&gt;
&lt;!-- cover image: https:&#x2F;&#x2F;unsplash.com&#x2F;photos&#x2F;G86MS2ZsiJA --&gt;

&lt;style&gt;
  .h4 {
    font-weight: bold;
  }
&lt;&#x2F;style&gt;

&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;unsplash&#x2F;dew-leaf.jpg&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>GitLab and Gravitational discuss Kubernetes</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/12/gitlab-joins-forces-with-gravitational/"/>
    <id>https://about.gitlab.com/2016/12/12/gitlab-joins-forces-with-gravitational/</id>
    <published>2016-12-12T00:00:00+00:00</published>
    <updated>2016-12-12T00:00:00+00:00</updated>
    <author>
      <name>Rebecca Dodd</name>
    </author>
    <content type="html">
&lt;p&gt;You never know where a conversation on Hacker News might take you. That&#x27;s what Ev Kontsevoy learned when he left a comment on a post, sparking a conversation with another reader who turned out to be GitLab CEO, Sid Sijbrandij. Later that day, at a party in San Francisco, Ev spotted another party guest wearing a GitLab T-shirt and approached him to chat. &quot;Turns out it was Sid, again!&quot; Ev says, laughing. &quot;It&#x27;s like he&#x27;s everywhere.&quot;&lt;&#x2F;p&gt;



&lt;p&gt;&quot;So we bumped into each other twice in the same day and when we started chatting. Sid mentioned that right now GitLab is trying to figure out the Kubernetes story: how to work with companies that rely heavily on Kubernetes, and frankly also how to use it internally.&quot; &lt;a href=&quot;https:&#x2F;&#x2F;gravitational.com&#x2F;&quot;&gt;Gravitational&lt;&#x2F;a&gt; is a Kubernetes company, so Ev was quick to offer their services, which is how GitLab ended up collaborating with Gravitational.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;what-did-we-work-on-together&quot;&gt;What did we work on together?&lt;&#x2F;h2&gt;

&lt;p&gt;&quot;One area that we were looking at together is how to run PostgreSQL on Kubernetes really well. It’s definitely a problem that most users will be trying to solve and it’s just one of the things that Gravitational is good at: we help our companies migrate their existing applications to Kubernetes, including databases. We&#x27;ve also been working on a GitLab path towards adopting Kubernetes for SaaS internally, after I bumped into some of your team members at a Kubernetes conference in Seattle.&quot;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;why-kubernetes&quot;&gt;Why Kubernetes?&lt;&#x2F;h2&gt;

&lt;p&gt;Jacob Vosmaer, GitLab Senior Developer, had some questions for Ev about the partnership: &quot;What does a tool like Kubernetes make easier for an application like GitLab?&quot;&lt;&#x2F;p&gt;

&lt;p&gt;Ev: &quot;You mean, &#x27;Why even bother with Kubernetes at all?&#x27;&quot;&lt;&#x2F;p&gt;

&lt;p&gt;Jacob: &quot;I was being polite!&quot;&lt;&#x2F;p&gt;

&lt;p&gt;Ev: &quot;Server costs are a major line item on every company’s budget. When you are a certain size it can actually become more expensive than your engineering salaries. Developing software that utilizes servers effectively is difficult. This is where Kubernetes comes in. Unlike the old technology like virtualisation, which would statically partition your servers into smaller VMs, Kubernetes allows you to do this partitioning on the fly, which means that if your application needs more or less of particular resources as it runs, Kubernetes will be dynamically growing and shrinking different components of your application across the infrastructure that’s available to you. So that&#x27;s really the benefit of Kubernetes, you save a lot of money on hosting if you utilize it.&quot;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;will-kubernetes-become-the-industry-standard&quot;&gt;Will Kubernetes become the industry standard?&lt;&#x2F;h2&gt;

&lt;p&gt;Ev: &quot;We&#x27;re probably going to witness something similar to Windows vs Linux, where there will probably be No. 1 and No. 2, and perhaps a very small No. 3. It feels to me that No. 1 and 2 are going to be Kubernetes and DC&#x2F;OS from Mesosphere, for two reasons: DC&#x2F;OS is an older product, it’s fairly mature, there are now Fortune 500 companies publicly using it. This kind of success doesn’t appear overnight. Even though technically Mesosphere technology is competing with Kubernetes and with what we do, I wish them the best and I do believe they are going to be noticeable.&quot;&lt;&#x2F;p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&quot;Kubernetes is an unstoppable force right now&quot;&lt;&#x2F;p&gt;
&lt;&#x2F;blockquote&gt;

&lt;p&gt;&quot;In my line, Kubernetes is an unstoppable force right now, simply because there are so many companies with a proven track record of popularizing open source who are behind it. Companies like IBM, Red Hat, Google themselves – with so many backers pushing Kubernetes forward, it’s hard for me to imagine it not leading the platform. Look at what happened with Linux: it’s the exact same companies who keep pushing Linux Kernel forward. They&#x27;re now joining forces again to promote Kubernetes and to evolve and invest money into it.&quot;&lt;&#x2F;p&gt;

&lt;p&gt;&quot;Finally, there&#x27;s container pioneering company Docker, with their own technology called Docker Swarm, so Docker has enormous mind share with developers. Docker Swarm itself is kind of late out of the gate compared to Kubernetes and DC&#x2F;OS, and I’m very curious to see what’s going to happen. But those are the three players that I think will be carving out this pie, I don’t really see anyone else challenging that.&quot;&lt;&#x2F;p&gt;

&lt;p&gt;In addition to their work with GitLab on Kubernetes, Gravitational also helped us &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;22864&quot;&gt;build a Terminal into GitLab&lt;&#x2F;a&gt;, Ev explains, &quot;to allow developers or any GitLab users to easily jump inside the containers that are running on Kubernetes without leaving the GitLab environment&quot;. You can &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;11&#x2F;14&#x2F;idea-to-production&#x2F;&quot;&gt;find out how to use GitLab&#x27;s built-in terminal here&lt;&#x2F;a&gt;. Good news for open source! Thanks for working with us, Gravitational.&lt;&#x2F;p&gt;

&lt;p&gt;Image: &quot;&lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;rachaelvoorhees&#x2F;828353700&#x2F;&quot;&gt;Take the wheel and drive&lt;&#x2F;a&gt;&quot; by &lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;rachaelvoorhees&#x2F;&quot;&gt;rachaelvoorhees&lt;&#x2F;a&gt; is licensed under &lt;a href=&quot;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by&#x2F;2.0&#x2F;&quot;&gt;CC BY 2.0&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;blogimages&#x2F;ship-steering-wheel-kubernetes.jpg&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>Proposed server purchase for GitLab.com</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/11/proposed-server-purchase-for-gitlab-com/"/>
    <id>https://about.gitlab.com/2016/12/11/proposed-server-purchase-for-gitlab-com/</id>
    <published>2016-12-11T00:00:00+00:00</published>
    <updated>2016-12-11T00:00:00+00:00</updated>
    <author>
      <name>Sid Sijbrandij</name>
    </author>
    <content type="html">
&lt;p&gt;We want to make GitLab.com fast and we &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;2016&#x2F;11&#x2F;10&#x2F;why-choose-bare-metal&#x2F;&quot;&gt;knew it was time to leave the cloud&lt;&#x2F;a&gt; and purchase our own servers.
In this post is our thinking about what chassis, rack, memory, CPU, network, power, and hosting to buy.
We wanted to share what we learned and get your feedback on our proposal and questions.
When you reply to a question in the comments on our blog or Hacker News please reference it with the letter and number: &#x27;Regarding R1&#x27;.
We&#x27;ll try to update the questions with preliminary answers as we learn more.&lt;&#x2F;p&gt;



&lt;h1 id=&quot;overview&quot;&gt;Overview&lt;&#x2F;h1&gt;

&lt;p&gt;Today, GitLab.com hosts 96TB of data, and that number is growing rapidly. We
are attempting to build a fault-tolerant and performant CephFS cluster. We are
also attempting to move GitLab application servers and supporting services
(e.g. PostgreSQL) to bare metal.&lt;&#x2F;p&gt;

&lt;p&gt;Note that for now our CI Runners will stay in the cloud. Not only are they are
much less sensitive to latency, but autoscaling is easier with a cloud service.&lt;&#x2F;p&gt;

&lt;h1 id=&quot;chassis&quot;&gt;Chassis&lt;&#x2F;h1&gt;

&lt;p&gt;One of the team members that will join GitLab in 2017 recommended using a &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.nl&#x2F;products&#x2F;system&#x2F;2U&#x2F;6028&#x2F;SYS-6028TP-HTTR.cfm&quot;&gt;6028TP-HTTR SuperMicro 2U Twin2 server&lt;&#x2F;a&gt; chassis that has 4 dual processor nodes and is 2 &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Rack_unit&quot;&gt;rack units&lt;&#x2F;a&gt; (U) high. The advantages are:&lt;&#x2F;p&gt;

&lt;ol&gt;
  &lt;li&gt;Great density, 0.5U per dual processor server&lt;&#x2F;li&gt;
  &lt;li&gt;You have one common form factor&lt;&#x2F;li&gt;
  &lt;li&gt;Power supplies are shared for great efficiency similar to &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Blade_server&quot;&gt;blade servers&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;The network is per node for more bandwidth and reliability (like individual server)&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;

&lt;p&gt;We use the &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;nfo&#x2F;2UTwin2.cfm&quot;&gt;2U Twin2&lt;&#x2F;a&gt; instead of the &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;nfo&#x2F;1UTwin.cfm&quot;&gt;1U Twin&lt;&#x2F;a&gt; because it fits one more 3.5&quot; hard drive (3 per node instead of 2).&lt;&#x2F;p&gt;

&lt;p&gt;This server is on the list of global SKU&#x27;s for SuperMicro.
We&#x27;ll also ask for quotes from other vendors to see if they have a competitive alternative.
For example HPE has the &lt;a href=&quot;https:&#x2F;&#x2F;www.hpe.com&#x2F;h20195&#x2F;v2&#x2F;getpdf.aspx&#x2F;c04542552.pdf?ver=7&quot;&gt;Apollo 2000 series&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;C1 Should we use another version of the chassis than HTTR?&lt;&#x2F;p&gt;

&lt;p&gt;C2 What is the best Dell equivalent? =&amp;gt; &lt;a href=&quot;http:&#x2F;&#x2F;www.dell.com&#x2F;us&#x2F;business&#x2F;p&#x2F;poweredge-c6320&#x2F;pd&quot;&gt;C6320&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;

&lt;h1 id=&quot;servers&quot;&gt;Servers&lt;&#x2F;h1&gt;

&lt;p&gt;We need the following servers:&lt;&#x2F;p&gt;

&lt;ol&gt;
  &lt;li&gt;32x File storage (CephFS OSD)&lt;&#x2F;li&gt;
  &lt;li&gt;3x File Monitoring (CephFS MON)&lt;&#x2F;li&gt;
  &lt;li&gt;8x Application server (&lt;a href=&quot;https:&#x2F;&#x2F;bogomips.org&#x2F;unicorn&#x2F;&quot;&gt;Unicorn&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;7x Background jobs (&lt;a href=&quot;http:&#x2F;&#x2F;sidekiq.org&#x2F;&quot;&gt;Sidekiq&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;5x Key value store (&lt;a href=&quot;https:&#x2F;&#x2F;redis.io&#x2F;topics&#x2F;sentinel&quot;&gt;Redis Sentinel&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;4x Database (PostgreSQL)&lt;&#x2F;li&gt;
  &lt;li&gt;3x Load balancers (HAproxy)&lt;&#x2F;li&gt;
  &lt;li&gt;1x Staging&lt;&#x2F;li&gt;
  &lt;li&gt;1x Spare&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;

&lt;p&gt;For a total of 64 nodes.&lt;&#x2F;p&gt;

&lt;p&gt;We would like to have one common node so that they are interchangable.
This would mean installing only a few disks per node instead of having large fileservers.
This would distribute failures and IO.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;write_iops.png&quot; alt=&quot;IOPS on GitLab.com&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;The above picture shows the currently number of Input&#x2F;output Operations Per
Second (IOPS) on GitLab.com. On our current NFS servers, our peak write IOPS
often hit close to 500K, and our peak read IOPS reach 200K. These numbers
suggest that using spinning disks alone may not be enough; we need to use
high-performance SSDs judiciously.&lt;&#x2F;p&gt;

&lt;p&gt;One task that we could not fit on the common nodes was PostgreSQL.
Our current plan is to make PostgreSQL distributed in 2017 with the help of &lt;a href=&quot;https:&#x2F;&#x2F;www.citusdata.com&#x2F;&quot;&gt;Citus&lt;&#x2F;a&gt;.
But for now, we need to scale vertically so we need a lot of memory and CPU.
We need at least a primary and secondary database.
We wanted to add a second pair for testing and to ensure spares in case of failure.
Details about this are in the following sections.&lt;&#x2F;p&gt;

&lt;p&gt;Choosing a common node will mean that file storage servers will have too much CPU and that application servers will have too much disk space.
We plan to remedy that by running everything on Kubernetes.
This allows us to have a blended workload using all CPU and disk.
For example we can combine file storage and background jobs on the same server since one is disk heavy and one is CPU heavy.
We will start by having one workload per server to reduce complexity.
This means that when we need to grow we can still unlock almost twice as much disk space and CPU by blending the workloads.
Please note that this will be container based, to get maximum IO performance we won&#x27;t virtualize our workload.&lt;&#x2F;p&gt;

&lt;p&gt;S1 Shall we spread the database servers among different chassis to make sure they don&#x27;t all fail when one chassis fails?&lt;&#x2F;p&gt;

&lt;p&gt;S2 Does Ceph handle running 60 OSD nodes well or can this cause problems?&lt;&#x2F;p&gt;

&lt;h1 id=&quot;cpu&quot;&gt;CPU&lt;&#x2F;h1&gt;

&lt;p&gt;The &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.nl&#x2F;products&#x2F;system&#x2F;2U&#x2F;6028&#x2F;SYS-6028TP-HTTR.cfm&quot;&gt;SuperServer 6028TP-HTTR&lt;&#x2F;a&gt; supports dual E5-2600v4 processors per node.
We think the &lt;a href=&quot;http:&#x2F;&#x2F;ark.intel.com&#x2F;products&#x2F;92981&#x2F;Intel-Xeon-Processor-E5-2630-v4-25M-Cache-2_20-GHz&quot;&gt;E5-2630v4&lt;&#x2F;a&gt; is a good blend of power and cost.
It has 20 virtual cores at 2.20Ghz, 25MB cache, and costs about $669 per processor.
Every physical core is two virtual cores due to &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Hyper-threading&quot;&gt;hyperthreading&lt;&#x2F;a&gt;.
A slightly more powerful processor is the &lt;a href=&quot;https:&#x2F;&#x2F;ark.intel.com&#x2F;products&#x2F;92984&#x2F;Intel-Xeon-Processor-E5-2640-v4-25M-Cache-2_40-GHz&quot;&gt;E5-2640v4&lt;&#x2F;a&gt; but while the &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;SPECint&quot;&gt;SPECint score&lt;&#x2F;a&gt; increases from 845 to 887 the costs increase from $669 to $939.
You can find the scores by entering a &lt;a href=&quot;https:&#x2F;&#x2F;www.spec.org&#x2F;cgi-bin&#x2F;osgresults?conf=rint2006&quot;&gt;search on spec.org&lt;&#x2F;a&gt; with &#x27;Hewlett Packard Enterprise&#x27; as the hardware vendor and looking for ProLiant DL360 Gen9 as the platform.&lt;&#x2F;p&gt;

&lt;p&gt;Our current SQL server has one E5-2698B v3 with 32 virtual cores.
PostgreSQL commonly uses about 20-25 virtual cores.
Moving to dual processors should already help a lot.
To give us more months to grow before having to distribute the database we want to purchase some headroom.
That is why we&#x27;re getting a &lt;a href=&quot;https:&#x2F;&#x2F;ark.intel.com&#x2F;products&#x2F;91750&#x2F;Intel-Xeon-Processor-E5-2687W-v4-30M-Cache-3_00-GHz&quot;&gt;E5-2687Wv4&lt;&#x2F;a&gt; for the database servers.
This processor costs $2100 instead of $670 but has 4 extra virtual cores and runs continuously on 3 Ghz instead of 2.2 Ghz.
Comprated to the E5-2630v4 that leads to a SPEC score or 1230 instead of 845 and 51.3 SPEC per virtual core instead of 42.3.
For the 4 dual processor database servers this upgrade will cost $11k.
We think it is worth it since the 20-40% of extra performence will buy us the month or two of extra time to distribute the database that we need.&lt;&#x2F;p&gt;

&lt;h1 id=&quot;disk&quot;&gt;Disk&lt;&#x2F;h1&gt;

&lt;p&gt;Every node can fit 3 larger (3.5&quot;) harddrives.
We plan to purchase the largest one available, a 8TB Seagate with 6Gb&#x2F;s SATA and 7.2K RPM.
At 60 nodes this will give us 1.4PB of raw storage.
At a replication factor of 3 for Ceph this is 480TB of usable storage.
Right now GitLab.com uses 96TB (54TB for repo&#x27;s, 21TB for uploads, 21TB for LFS and build artifacts) so we can grow by a factor of almost 5.&lt;&#x2F;p&gt;

&lt;p&gt;Disks can be slow so we looked at improving latency.
Higher RPM hard drives typically come in &lt;a href=&quot;http:&#x2F;&#x2F;www.seagate.com&#x2F;enterprise-storage&#x2F;hard-disk-drives&#x2F;enterprise-performance-15k-hdd&#x2F;&quot;&gt;GB instead of TB sizes&lt;&#x2F;a&gt;.
Going all SSD is too expensive.
To improve latency we plan to fit every server with an SSD card.
On the fileservers this will be used as a cache.
We&#x27;re thinking about using &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Bcache&quot;&gt;Bcache&lt;&#x2F;a&gt; for this.&lt;&#x2F;p&gt;

&lt;p&gt;We plan to use &lt;a href=&quot;http:&#x2F;&#x2F;www.intel.com&#x2F;content&#x2F;www&#x2F;us&#x2F;en&#x2F;solid-state-drives&#x2F;ssd-dc-p3700-spec.html&quot;&gt;Intel DC P3700 series&lt;&#x2F;a&gt; or slight less powerful &lt;a href=&quot;http:&#x2F;&#x2F;www.intel.com&#x2F;content&#x2F;www&#x2F;us&#x2F;en&#x2F;solid-state-drives&#x2F;ssd-dc-p3600-spec.html&quot;&gt;P3600 series&lt;&#x2F;a&gt; of SSD&#x27;s because they are recommended by the CephFS experts we hired.
For most servers it will be the &lt;a href=&quot;http:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;nfo&#x2F;PCI-E_SSD.cfm?show=Intel&quot;&gt;800GB SSDPEDMD800G4&lt;&#x2F;a&gt;.
For the database servers we plan to use the the 1.6TB variant to have more headroom.
The endurance we need for the database server is 90TB&#x2F;year, the 3600 series is already above 4PB of endurance.&lt;&#x2F;p&gt;

&lt;p&gt;We plan to add a 64GB &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;nfo&#x2F;SATADOM.cfm&quot;&gt;SSD SATADOM boot drive&lt;&#x2F;a&gt; to the servers to boot from.
This way we can keep the large SSD as a separate volume.&lt;&#x2F;p&gt;

&lt;p&gt;D1 We plan to configure the disks as just a bunch of disks (JBOD) but heard that this caused performance problems with some controllers. Is this likely to impact us?&lt;&#x2F;p&gt;

&lt;p&gt;D2 Should we use Bcache to improve latency on on the Ceph OSD servers with SSD? =&amp;gt; Make sure you&#x27;re using a kernel &amp;gt;= 4.5, since that&#x27;s when a bunch of stability patches landed (https:&#x2F;&#x2F;lkml.org&#x2F;lkml&#x2F;2015&#x2F;12&#x2F;5&#x2F;38).&lt;&#x2F;p&gt;

&lt;p&gt;D3 We heard concerns about fitting the PCIe 3.0 x 4 SSD card into &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.nl&#x2F;products&#x2F;system&#x2F;2U&#x2F;6028&#x2F;SYS-6028TP-HTTR.cfm&quot;&gt;our chassis&lt;&#x2F;a&gt; that supports a PCI-E 3.0 x16 Low-profile slot. Will this fit? =&amp;gt; &lt;a href=&quot;http:&#x2F;&#x2F;disq.us&#x2F;p&#x2F;1eedj2n&quot;&gt;Florian Heigl&lt;&#x2F;a&gt;: &quot;Somewhat unlikely you will be able to fit a P3700. I have a Twin^2 too and the only SSD I could fit there was a consumer NVME with a PCIe adapter board.&quot;&lt;&#x2F;p&gt;

&lt;p&gt;D4 Should we ask for 8TB HGST drives instead of Seagate since they seem &lt;a href=&quot;https:&#x2F;&#x2F;www.backblaze.com&#x2F;blog&#x2F;hard-drive-reliability-stats-q1-2016&#x2F;&quot;&gt;more reliable&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;D5 Is it a good idea to have a boot drive or should we use &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;Preboot_Execution_Environment&quot;&gt;PXE boot&lt;&#x2F;a&gt; every time it starts? =&amp;gt; &lt;a href=&quot;https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=13153336&quot;&gt;dsr_&lt;&#x2F;a&gt;: You want a local boot drive, and you want it to fall back to PXE booting if the local drive is unavailable. Your PXE image should default to the last known working image, and have a boot-time menu with options for a rescue image and an installer for your distribution of choice.&lt;&#x2F;p&gt;

&lt;p&gt;D6 Should we go for the 3700 series SSD or save some money and go for the 3600 series? Both for the normal and the SQL servers?&lt;&#x2F;p&gt;

&lt;p&gt;D7 We&#x27;re planning on one SSD per node. For the OSD nodes (file server) that would mean having the Ceph journal and bcache on the same SSD. Is this a good idea?&lt;&#x2F;p&gt;

&lt;h1 id=&quot;memory&quot;&gt;Memory&lt;&#x2F;h1&gt;

&lt;p&gt;Suppose one node runs both as application server and fileserver.
We recommend virtual cores + 1 instances of Unicorn of about 0.5GB each, for a total of 21GB per node (2 processors * 21 unicorns per processor * 0.5GB).
Ceph recommends about 1GB per TB of data which comes out to 24 per node.
So theoretically we can fit everything in 45GB so 64GB should be enough.&lt;&#x2F;p&gt;

&lt;p&gt;But in practice we&#x27;ve seen 24TB OSD nodes use 79GB of memory.
And the rule of thumb is have about 2GB per virtual core for background jobs available (40GB).
So in order not to be to low we&#x27;ll spend the extra $30k to have 128GB of ECC memory per node instead of 64GB.&lt;&#x2F;p&gt;

&lt;p&gt;For the SQL nodes we&#x27;ll need much more memory, we currently give it 440GB and it uses all of that.
The database is about 250GB in size and growing with 40GB per month.
At 250GB of server memory we redlined the server, probably because it no longer fits into memory.
Theoretically the server supports 2TB of memory but it needs to fit in 16 memory slots per node.
We wanted to start with 1TB per server but we&#x27;re not sure if we should go from a 64GB DIMM to 128GB to be able to expand later.
By having only half of the memory banks full you get half the bandwidth.
And 64GB DIMMs already cost twice as much per GB as 32GB DIMMs, let alone 128GB ones.
At a price of about $940 per 64 DIMM the cost for 1TB of memory already is $15k per server.&lt;&#x2F;p&gt;

&lt;p&gt;Note that larger sizes such as 64GB come in the form of LRDIMM that has a &lt;a href=&quot;https:&#x2F;&#x2F;www.microway.com&#x2F;hpc-tech-tips&#x2F;ddr4-rdimm-lrdimm-performance-comparison&#x2F;&quot;&gt;small performance penalty&lt;&#x2F;a&gt; but this looks acceptable.&lt;&#x2F;p&gt;

&lt;p&gt;M1. Should we use 128GB DIMMS to be able to expand the database server later even though the will double the cost and half the bandwidth?&lt;&#x2F;p&gt;

&lt;h1 id=&quot;network&quot;&gt;Network&lt;&#x2F;h1&gt;

&lt;p&gt;The servers come with 2x 10Gbps RJ45 by default (Intel X540 Dual port 10GBase-T).
We want to &lt;a href=&quot;https:&#x2F;&#x2F;docs.oracle.com&#x2F;cd&#x2F;E37670_01&#x2F;E41138&#x2F;html&#x2F;ch11s05.html&quot;&gt;dual bound&lt;&#x2F;a&gt; the network connections to increase performance and reliability.
This will allow us to take routers out of service during low traffic times, for example to restart them after a software upgrade.
We think that 20Gbps is enough bandwidth to handle our data access and replication needs, right now our higest peaks are 1 Gbps.
This is important because we want to have minimal latency between the Ceph servers so network congestion would be a problem.&lt;&#x2F;p&gt;

&lt;p&gt;Ceph reference designs recommend a seperated front and back network with the back network reserved for Ceph traffic.
We think that this is not needed as long as there is enough capacity.
We do want to have user request termination in a DMZ, so our HA proxy servers will be the only ones with a public IP.&lt;&#x2F;p&gt;

&lt;p&gt;Each of the two physical network connections will connect to a different top of rack router.
We want to get a Software Defined Networking (SDN) compatible router so we have flexibility there.
We&#x27;re considering the &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;accessories&#x2F;Networking&#x2F;SSE-X3648S.cfm&quot;&gt;10&#x2F;40GbE SDN SuperSwitch (SSE-X3648S&#x2F;SSE-X3648SR)&lt;&#x2F;a&gt; that can switch 1440 Gbps.&lt;&#x2F;p&gt;

&lt;p&gt;Apart from those routers we&#x27;ll have a separate router for a 1Gbps management network.
For example to make &lt;a href=&quot;https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;STONITH&quot;&gt;STONITH&lt;&#x2F;a&gt; reliable when there is a lot of traffic on the normal network.
Each node already has a separate 1Gbps connection for this.&lt;&#x2F;p&gt;

&lt;p&gt;We have 64+1 nodes (1 for backup) and most routers seem to have 48 ports.
Every node has 2 network ports so that is a need for 130 ports in total.
We&#x27;re not use if we can use 3 routers with 48 ports each (144 in total) to cover that.&lt;&#x2F;p&gt;

&lt;p&gt;N1 Which router should we purchase?&lt;&#x2F;p&gt;

&lt;p&gt;N2 How do we interconnect the routers while keeping the network simple and fast?&lt;&#x2F;p&gt;

&lt;p&gt;N3 Should we have a separate network for Ceph traffic?&lt;&#x2F;p&gt;

&lt;p&gt;N4 Do we need an SDN compatible router or can we purchase something more affordable?&lt;&#x2F;p&gt;

&lt;p&gt;N5 What router should we use for the management network?&lt;&#x2F;p&gt;

&lt;h1 id=&quot;backup&quot;&gt;Backup&lt;&#x2F;h1&gt;

&lt;p&gt;We&#x27;re still early in figuring out the backup solution so there are still lots of questions.&lt;&#x2F;p&gt;

&lt;p&gt;Backing up 480TB of data (expected size in 2017) is pretty hard.
We thought about using &lt;a href=&quot;https:&#x2F;&#x2F;cloud.google.com&#x2F;storage-nearline&#x2F;&quot;&gt;Google Nearline&lt;&#x2F;a&gt; because with a price of $0.01 per GB per month means that for $4800 we don&#x27;t have to worry about much.
But restoring that over a 1Gbps connection takes 44 days, way too long.&lt;&#x2F;p&gt;

&lt;p&gt;We mainly want our backup to protect us against human and software errors.
Because all the files are already replicated 3 times hardware errors are unlikely to affect us.
Of course we should have a good &lt;a href=&quot;http:&#x2F;&#x2F;docs.ceph.com&#x2F;docs&#x2F;jewel&#x2F;rados&#x2F;operations&#x2F;crush-map&#x2F;&quot;&gt;Ceph CRUSH map&lt;&#x2F;a&gt; to prevent storing multiple copies on the same chassis.&lt;&#x2F;p&gt;

&lt;p&gt;We&#x27;re most afraid of human error or Ceph corruption. For that reason we don&#x27;t want to replicate on the Ceph level but on the file level.&lt;&#x2F;p&gt;

&lt;p&gt;We&#x27;re thinking about using &lt;a href=&quot;https:&#x2F;&#x2F;www.bareos.org&#x2F;en&#x2F;&quot;&gt;Bareos backup software&lt;&#x2F;a&gt; to replicate to a huge fileserver.
We&#x27;re inspired by the posts about the &lt;a href=&quot;https:&#x2F;&#x2F;www.backblaze.com&#x2F;blog&#x2F;open-source-data-storage-server&#x2F;&quot;&gt;latest 480TB Backblaze storage pod 6.0&lt;&#x2F;a&gt; and these are available for $6k without drives from &lt;a href=&quot;https:&#x2F;&#x2F;www.backuppods.com&#x2F;&quot;&gt;Backuppods&lt;&#x2F;a&gt;.
But SuperMicro offers a &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;chassis&#x2F;4U&#x2F;946&#x2F;SC946ED-R2KJBOD&quot;&gt;comparable solution in the form of a SuperChassis that can hold 90 drives&lt;&#x2F;a&gt;.
At 8TB per drive that is 720TB of raw storage.
Even with RAID overhead it should be possible to have 480TB of usable storage (66%).&lt;&#x2F;p&gt;

&lt;p&gt;The SuperChassis is only hard drives, it still needs a controller. In a &lt;a href=&quot;https:&#x2F;&#x2F;nexenta.com&#x2F;sites&#x2F;default&#x2F;files&#x2F;docs&#x2F;Nexenta_SMC_RA_DataSheet.pdf&quot;&gt;reference architecture by Nexenta (PDF download)&lt;&#x2F;a&gt; two &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;system&#x2F;2u&#x2F;6028&#x2F;sys-6028u-tr4_.cfm&quot;&gt;SYS6028U&lt;&#x2F;a&gt; with E5-2643v3 processors and 256GB of RAM is recommended. Unlike smaller configurations this one doesn&#x27;t come with an SSD for &lt;a href=&quot;https:&#x2F;&#x2F;blogs.oracle.com&#x2F;brendan&#x2F;entry&#x2F;test&quot;&gt;ZFS L2ARC&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Since backups are mostly linear we don&#x27;t need an SSD for caching. In general 1GB of memory per TB of raw ZFS disk space is recommended. That would mean getting 512GB of RAM, 16x 32GB. Unlike the reference architecture we&#x27;ll go with one controller. We&#x27;re considering the &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;system&#x2F;1U&#x2F;1028&#x2F;SYS-1028R-WC1RT.cfm&quot;&gt;SuperServer 1028R-WC1RT&lt;&#x2F;a&gt; since it is similar to our other servers, 1U, has 2x 10Gbps, 16 DIMM slots, and has 2 PCI slots. We&#x27;ll use our regular &lt;a href=&quot;http:&#x2F;&#x2F;ark.intel.com&#x2F;products&#x2F;92981&#x2F;Intel-Xeon-Processor-E5-2630-v4-25M-Cache-2_20-GHz&quot;&gt;E5-2630v4&lt;&#x2F;a&gt; processor.&lt;&#x2F;p&gt;

&lt;p&gt;The question is if this controller can saturate the 20 Gbps uplink.
For this it needs to use both 12 Gbps SAS buses.
And each drive has to do at least 30 MBps which seems reasonable for a continuous read.&lt;&#x2F;p&gt;

&lt;p&gt;The problem is that even at 20Gbps a full restore takes 2 days.
Of course many times you need to restore only part of the files (uploads).
And most of the time it won&#x27;t contain 480TB (we&#x27;ll start at about 100TB).
The question is if we can accept this worst case scenario for GitLab.com.&lt;&#x2F;p&gt;

&lt;p&gt;An alternative would be to use multiple controllers.
But you can&#x27;t aggregate ZFS pools over multiple servers.
Another option would be to have one controller with more IO.
We can use multiple disk enclosures and multiple SAS buses.
And we can add more network ports and&#x2F;or switch to 40Gbps.
But this all seems pretty complicated.&lt;&#x2F;p&gt;

&lt;p&gt;B0 Are we on the right track here or is 20 Gbps of restore speed not OK?&lt;&#x2F;p&gt;

&lt;p&gt;B1 Should we go for the &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;chassis&#x2F;4U&#x2F;?chs=946&quot;&gt;90 or 60 drive SuperChassis&lt;&#x2F;a&gt;? It looks like 60 drive one has more peak power (1600W vs. 800W) to start the drives.&lt;&#x2F;p&gt;

&lt;p&gt;B2 How should we configure the SuperChassis? &lt;a href=&quot;http:&#x2F;&#x2F;zfsonlinux.org&#x2F;&quot;&gt;ZFS on Linux&lt;&#x2F;a&gt; with &lt;a href=&quot;https:&#x2F;&#x2F;icesquare.com&#x2F;wordpress&#x2F;zfs-performance-mirror-vs-raidz-vs-raidz2-vs-raidz3-vs-striped&#x2F;&quot;&gt;RAIDZ3&lt;&#x2F;a&gt;?&lt;&#x2F;p&gt;

&lt;p&gt;B3 Will the SuperChassis be able to saturate the 20Gbsp connection?&lt;&#x2F;p&gt;

&lt;p&gt;B4 Should we upgrade the networking on the SuperChassis to be able to restore even faster?&lt;&#x2F;p&gt;

&lt;p&gt;B5 Is Bareos the right software to use?&lt;&#x2F;p&gt;

&lt;p&gt;B6 How should we configure the backup software?  Should we use incremental backups with parallel jobs to speed things up?&lt;&#x2F;p&gt;

&lt;p&gt;B7 Should we use the live filesystem or &lt;a href=&quot;http:&#x2F;&#x2F;docs.ceph.com&#x2F;docs&#x2F;master&#x2F;dev&#x2F;cephfs-snapshots&#x2F;&quot;&gt;CephFS snapshots&lt;&#x2F;a&gt; to back up from?&lt;&#x2F;p&gt;

&lt;p&gt;B8 How common is it to have a tape or cloud backup in addition to the above?&lt;&#x2F;p&gt;

&lt;p&gt;B9 Should we pick the top load model or &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;chassis&#x2F;JBOD&#x2F;index.cfm?show=SELECT&amp;amp;storage=90&quot;&gt;one of the front and rear access models&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;B10 Can we connect two SAS cables to get 2x 12 Gbps?&lt;&#x2F;p&gt;

&lt;p&gt;B11 What &lt;a href=&quot;https:&#x2F;&#x2F;www.supermicro.com&#x2F;products&#x2F;nfo&#x2F;storage_cards.cfm&quot;&gt;HBA card&lt;&#x2F;a&gt; should be added to the controller or does it come with an LSI 3108?&lt;&#x2F;p&gt;

&lt;p&gt;B12 Is it smart to make the controller a seperate 1U box or should we repurpose some of our normal nodes for this?&lt;&#x2F;p&gt;

&lt;p&gt;B13 Any hints on how to test the backup restore (on AWS or our hardware, how often, etc.)?&lt;&#x2F;p&gt;

&lt;h1 id=&quot;rack&quot;&gt;Rack&lt;&#x2F;h1&gt;

&lt;p&gt;The default rack height seems to be 45U nowadays (42U used to be the standard).&lt;&#x2F;p&gt;

&lt;p&gt;It is used as follows:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;32U for 16 chassis with 64 nodes&lt;&#x2F;li&gt;
  &lt;li&gt;3U for three network routers&lt;&#x2F;li&gt;
  &lt;li&gt;1U for the management network&lt;&#x2F;li&gt;
  &lt;li&gt;4U for the disk enclosure&lt;&#x2F;li&gt;
  &lt;li&gt;1U for the disk controller&lt;&#x2F;li&gt;
  &lt;li&gt;4U spare for 2 new chassis (maybe distributed PostgreSQL servers)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h1 id=&quot;power&quot;&gt;Power&lt;&#x2F;h1&gt;

&lt;p&gt;Each chassis has a 2000 watt power supply (comes to 1kW per U), 32kW in total.
Normal usage is guessed at 60% of the rated capacity, about 19kW.
That doesn&#x27;t account for the routers and backup.
Both hosting providers quoted 4 x 208v 30A power supplies (2 for redundancy).&lt;&#x2F;p&gt;

&lt;p&gt;P1 Does the quoted supply seem adequate for our needs?&lt;&#x2F;p&gt;

&lt;h1 id=&quot;hosting&quot;&gt;Hosting&lt;&#x2F;h1&gt;

&lt;p&gt;We&#x27;ve worked in &lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-com&#x2F;infrastructure&#x2F;issues&#x2F;732&quot;&gt;an issue&lt;&#x2F;a&gt; to see where we should host.&lt;&#x2F;p&gt;

&lt;p&gt;Apart from the obvious (reliable, affordable) we had the following needs:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;aws.amazon.com&#x2F;directconnect&#x2F;details&#x2F;&quot;&gt;AWS Direct connect&lt;&#x2F;a&gt; so we can use the cloud for temporary application server needs&lt;&#x2F;li&gt;
  &lt;li&gt;Based on the east coast of the USA since it provides the best latency tradeoff for most of our users&lt;&#x2F;li&gt;
  &lt;li&gt;Advanced remote hands service so we don&#x27;t have to station people near the datacenter at all times&lt;&#x2F;li&gt;
  &lt;li&gt;Ability to upgrade from one rack to a private cage&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;The following networking options are a plus:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;Carrier neutral (all major global network providers in its meet-me facility)&lt;&#x2F;li&gt;
  &lt;li&gt;Backbones to other locations to provide cheap 2nd site transit&lt;&#x2F;li&gt;
  &lt;li&gt;CDN services to reduce origin bandwidth costs&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;So far we&#x27;ve gotten quotes from &lt;a href=&quot;http:&#x2F;&#x2F;www.qtsdatacenters.com&#x2F;data-centers&#x2F;ashburn&quot;&gt;QTS in Ashburn, VA&lt;&#x2F;a&gt; and &lt;a href=&quot;https:&#x2F;&#x2F;www.nyi.net&#x2F;datacenters&#x2F;new-jersey&#x2F;&quot;&gt;NYI in Bridgewater, NJ&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;H1 Any watchouts when selecting hosting providers?&lt;&#x2F;p&gt;

&lt;p&gt;H2 Should we install the servers ourselves or is it OK to let the hosting provider do that?&lt;&#x2F;p&gt;

&lt;p&gt;H3 How can we minimize installation costs? Should we ask to configure the servers to PXE boot?&lt;&#x2F;p&gt;

&lt;p&gt;H4 Is there an Azure equivalent for AWS Direct Connect? =&amp;gt; Azure will let you work with a provider to &quot;peer into&quot; the Azure network at a data center of your choice. So for example we could pay to have a circuit established in a data center that was linked into the Azure &#x27;US East 2&#x27; data center (where we currently host out of) for direct connectivity needs.&lt;&#x2F;p&gt;

&lt;h1 id=&quot;expense&quot;&gt;Expense&lt;&#x2F;h1&gt;

&lt;p&gt;We can&#x27;t give cost details since all the quotes we receive are confidential.
The cloud hosting for GitLab.com excluding GitLab CI is currently costing us about $200k per month.
The capital needed for going to metal would be less than we pay for 1 quarter of hosting.
The hosting facility costs look to be less than $10k per month.
If you spread the capital costs over 2.5 years (10 quarters) it is 10x cheaper to host your own.&lt;&#x2F;p&gt;

&lt;p&gt;Of course the growth of GitLab.com will soon force us to buy additional hardware.
But we would also have to pay extra for additional cloud capacity.
Our proposed buying plan is about 5x the capacity we need now.
Having your own hardware means you&#x27;re always overprovisioned.
And we could probably have reduced the cost of cloud hosting by focussing on it.&lt;&#x2F;p&gt;

&lt;p&gt;The bigger expense will be hiring more people to deal with the additional complexity.
We&#x27;ll probably need to hire a couple of people more to deal with this.
We&#x27;re hiring &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;jobs&#x2F;production-engineer&#x2F;&quot;&gt;production engineers&lt;&#x2F;a&gt; and if you&#x27;re spotting mistakes in this post we would love to talk to you (and if you didn&#x27;t spot many mistakes but think you can help us we also want to talk to you).&lt;&#x2F;p&gt;

&lt;p&gt;We looked into initially having disks in only half the servers but that saves only $20k ($225 per disk) and it would create a lot of work when we eventually have to install them.&lt;&#x2F;p&gt;

&lt;p&gt;E1 If we want to look at leasing should we do that through SuperMicro or third party?&lt;&#x2F;p&gt;

&lt;p&gt;E2 Are there ways we can save money?&lt;&#x2F;p&gt;

&lt;h1 id=&quot;details&quot;&gt;Details&lt;&#x2F;h1&gt;

&lt;p&gt;Our detailed calculations and notes can be found in a &lt;a href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;spreadsheets&#x2F;d&#x2F;1XG9VXdDxNd8ipgPlEr7Nb7Eg22twXPuzgDwsOhtdYKQ&#x2F;edit#gid=894825456&quot;&gt;public Google sheet&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;default-blog-image.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>How to evaluate GitLab during an EE trial</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/09/how-to-evaluate-gitlab-during-ee-trial/"/>
    <id>https://about.gitlab.com/2016/12/09/how-to-evaluate-gitlab-during-ee-trial/</id>
    <published>2016-12-09T00:00:00+00:00</published>
    <updated>2016-12-09T00:00:00+00:00</updated>
    <author>
      <name>Rebecca Dodd</name>
    </author>
    <content type="html">
&lt;p&gt;Ever reach the end of a free trial and wonder if you even learned anything from the experience? We want you to get the most out of your time using GitLab Enterprise Edition, so here&#x27;s a spreadsheet you can use to evaluate the product.&lt;&#x2F;p&gt;



&lt;p&gt;Sometimes when you start a free trial you don&#x27;t have any particular criteria in mind and aren&#x27;t sure what exactly you&#x27;re looking for from GitLab EE, so you don&#x27;t get much out of your time using it. The spreadsheet below was created by one of our biggest EE customers to use when they were evaluating GitLab, and they&#x27;ve kindly shared it with us to help more users discover whether EE is the best choice for them.&lt;&#x2F;p&gt;

&lt;p&gt;We&#x27;d love for you to contribute to it and make it work for you so we can also learn more about what you&#x27;re looking for in EE. Please share your feedback in the comments!&lt;&#x2F;p&gt;

&lt;p&gt;Follow the instructions below to make an informed decision about whether GitLab EE is right for your company.&lt;&#x2F;p&gt;

&lt;ol&gt;
  &lt;li&gt;To get started, sign up for your &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;free-trial&#x2F;&quot;&gt;free 30-day trial of GitLab EE&lt;&#x2F;a&gt;.&lt;&#x2F;li&gt;
  &lt;li&gt;Make a copy of our &lt;a href=&quot;https:&#x2F;&#x2F;docs.google.com&#x2F;spreadsheets&#x2F;d&#x2F;1gUzEoiJqbkE35lCmpk8UqFP1bMfzG3SjmstFQKaVxFM&#x2F;edit?usp=sharing&quot;&gt;GitLab EE trial evaluation spreadsheet&lt;&#x2F;a&gt; and save it to your own Google Drive.&lt;&#x2F;li&gt;
  &lt;li&gt;Customize the spreadsheet to suit your needs: add other products you currently use or are considering and will be comparing to GitLab EE, and include additional tests that you would run to assess the trial.&lt;&#x2F;li&gt;
  &lt;li&gt;Create an evaluation timeline for your 30-day trial, and divide tasks between departments and teams if you like.&lt;&#x2F;li&gt;
  &lt;li&gt;At the end of the trial period, total the scores.&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;sales&#x2F;&quot;&gt;Contact our sales team&lt;&#x2F;a&gt; with any questions or feedback.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;

&lt;p&gt;Image: &quot;&lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;craigmoulding&#x2F;8399214678&#x2F;&quot;&gt;I Love Spreadsheets&lt;&#x2F;a&gt;&quot; by &lt;a href=&quot;https:&#x2F;&#x2F;www.flickr.com&#x2F;photos&#x2F;craigmoulding&#x2F;&quot;&gt;Craig Chew-Moulding&lt;&#x2F;a&gt; is licensed under &lt;a href=&quot;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by-sa&#x2F;2.0&#x2F;&quot;&gt;CC BY-SA 2.0&lt;&#x2F;a&gt;&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;blogimages&#x2F;i-love-spreadsheets-trial-evaluation.jpg&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>GitLab 8.14.4, 8.13.9, and 8.12.12 Released</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/08/gitlab-8-dot-14-dot-4-released/"/>
    <id>https://about.gitlab.com/2016/12/08/gitlab-8-dot-14-dot-4-released/</id>
    <published>2016-12-08T19:00:00+00:00</published>
    <updated>2016-12-08T19:00:00+00:00</updated>
    <author>
      <name>GitLab</name>
    </author>
    <content type="html">
&lt;p&gt;Today we are releasing versions 8.14.4, 8.13.9, and 8.12.12 for GitLab Community
Edition (CE) and Enterprise Edition (EE).&lt;&#x2F;p&gt;

&lt;p&gt;These versions contain important security fixes, and we &lt;strong&gt;strongly
recommend&lt;&#x2F;strong&gt; that all affected GitLab installations be upgraded to one of these
versions &lt;strong&gt;immediately&lt;&#x2F;strong&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Please read on for more details.&lt;&#x2F;p&gt;



&lt;h2 id=&quot;security-fixes-in-8144-8139-and-81212&quot;&gt;Security fixes in 8.14.4, 8.13.9 and 8.12.12&lt;&#x2F;h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Replace MR access checks with use of &lt;code&gt;MergeRequestsFinder&lt;&#x2F;code&gt; (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;23867&quot;&gt;#23867&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;security-fixes-in-8144&quot;&gt;Security fixes in 8.14.4&lt;&#x2F;h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Destroy a user&#x27;s session when they delete their account. (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;25015&quot;&gt;#25015&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Filter authentication tokens from Sentry output.&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; XSS when &lt;code&gt;LegacyDiffNote&lt;&#x2F;code&gt; is created on a merge request diff containing HTML (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;issues&#x2F;25249&quot;&gt;#25249&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;Thanks to Kristiyan Bogdanov via HackerOne.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;other-fixes-in-8144&quot;&gt;Other fixes in 8.14.4&lt;&#x2F;h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix pipeline author for Slack and use pipeline id for pipeline link (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7506&quot;&gt;!7506&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Resolve &quot;Highlighting lines is broken&quot; (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7090&quot;&gt;!7090&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix pipelines tabs (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7709&quot;&gt;!7709&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Fix compatibility with Internet Explorer 11 for merge requests (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7525&quot;&gt;!7525&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Authorize users into imported GitLab project (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7936&quot;&gt;!7936&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Remove caching of Repository#has_visible_content? (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7947&quot;&gt;!7947&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;CE&#x2F;EE:&lt;&#x2F;strong&gt; Bump gitlab-shell version to 4.0.3 (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ce&#x2F;merge_requests&#x2F;7953&quot;&gt;!7953&lt;&#x2F;a&gt;)&lt;&#x2F;p&gt;
  &lt;&#x2F;li&gt;
  &lt;li&gt;&lt;strong&gt;EE:&lt;&#x2F;strong&gt; Prevent remote mirrors from failing when project is in pending_delete (&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-org&#x2F;gitlab-ee&#x2F;merge_requests&#x2F;938&quot;&gt;!938&lt;&#x2F;a&gt;)&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;upgrade-barometer&quot;&gt;Upgrade barometer&lt;&#x2F;h2&gt;

&lt;p&gt;These versions do include a single migration, and will require brief
downtime of typically less than one minute.&lt;&#x2F;p&gt;

&lt;p&gt;Please be aware that by default the Omnibus packages will stop, run migrations,
and start again, no matter how “big” or “small” the upgrade is. This behavior
can be changed by adding a &lt;a href=&quot;http:&#x2F;&#x2F;doc.gitlab.com&#x2F;omnibus&#x2F;update&#x2F;README.html&quot;&gt;&lt;code&gt;&#x2F;etc&#x2F;gitlab&#x2F;skip-auto-migrations&lt;&#x2F;code&gt;
file&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;updating&quot;&gt;Updating&lt;&#x2F;h2&gt;

&lt;p&gt;To update, check out our &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;update&quot;&gt;update page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;enterprise-edition&quot;&gt;Enterprise Edition&lt;&#x2F;h2&gt;

&lt;p&gt;Interested in GitLab Enterprise Edition? Check out the &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;features&#x2F;#enterprise&quot;&gt;features exclusive to
EE&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Access to GitLab Enterprise Edition is included with a
&lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;pricing&#x2F;&quot;&gt;subscription&lt;&#x2F;a&gt;. No time to upgrade GitLab
yourself? Subscribers receive upgrade and installation services.&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;default-blog-image.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>Expanding Our Enterprise Offering: Announcing GitLab Enterprise Edition Premium</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/08/announcing-gitlab-enterprise-edition-premium/"/>
    <id>https://about.gitlab.com/2016/12/08/announcing-gitlab-enterprise-edition-premium/</id>
    <published>2016-12-08T10:35:00+00:00</published>
    <updated>2016-12-08T10:35:00+00:00</updated>
    <author>
      <name>Amara Nwaigwe</name>
    </author>
    <content type="html">
&lt;p&gt;Today we are announcing the addition of a new enterprise plan, GitLab Enterprise Edition Premium. GitLab Enterprise Edition (EE) Premium was built for global organizations who need a solution for remote teams, premium support, High Availability, and advanced workflow controls. GitLab EE Premium builds on top of our base enterprise plan and offers the following additional features:&lt;&#x2F;p&gt;



&lt;ul&gt;
  &lt;li&gt;Premium Support: 4-hour response times, 24&#x2F;7 emergency support, training, live upgrade assistance, and support for High Availability ensure that your team can focus on building great products.&lt;&#x2F;li&gt;
  &lt;li&gt;GitLab Geo: Make your remote teams more productive with read-only mirrors of your GitLab instance that significantly reduce the time it takes to clone and fetch large repos.&lt;&#x2F;li&gt;
  &lt;li&gt;File Locking: Improve how you manage your binary and text files with the ability to lock any file or directory.&lt;&#x2F;li&gt;
  &lt;li&gt;Pivotal Tile: Easily deploy GitLab as a pre-configured appliance using Ops Manager (BOSH) for Pivotal Cloud Foundry.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;GitLab EE Premium ensures your team has the tools and support they need today
as well as in the future. Premium features are features that
replace other products typically used within organizations. Take a look at some
of the premium features we are considering on &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;direction&#x2F;#new-products&quot;&gt;our direction page&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;GitLab EE Premium is now &lt;a href=&quot;https:&#x2F;&#x2F;about.gitlab.com&#x2F;products&#x2F;&quot;&gt;available for purchase&lt;&#x2F;a&gt; for $199 per user per year.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;what-has-changed&quot;&gt;What has changed?&lt;&#x2F;h2&gt;

&lt;p&gt;Previously, we offered one enterprise plan for $39 per user&#x2F;per year and a number of additional enterprise products you could purchase for $99 per product&#x2F;per user&#x2F;per year. Now, the products and services we used to offer as additional purchases will be bundled into GitLab EE Premium. The only change to the former GitLab Enterprise Edition is the name. Its features and price will be exactly the same. This plan has simply been renamed to GitLab Enterprise Edition Starter.&lt;&#x2F;p&gt;

&lt;p&gt;We are also improving our Premium Support offering to speed up our non-emergency SLA from next-day responses to a 4-hour response time. This faster response time means that we will no longer offer a dedicated service engineer. While dedicated resources can potentially offer more personalized service, they limit our ability to get back to you as quickly as possible. We know your team’s time is sensitive so we chose to optimize for faster response times.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;why-one-subscription-instead-of-multiple-products&quot;&gt;Why one subscription instead of multiple products?&lt;&#x2F;h2&gt;

&lt;p&gt;There are a few reasons:&lt;&#x2F;p&gt;

&lt;ol&gt;
  &lt;li&gt;The per product purchasing process slowed customers down. We&#x27;d release a new product that our customers needed but in order for customers to actually start using it they would have to start a new internal purchasing process.&lt;&#x2F;li&gt;
  &lt;li&gt;Unlocking certain features&#x2F;experiences on a per product reduces the usage, so we were not getting enough feedback from our customers on how we could improve.&lt;&#x2F;li&gt;
  &lt;li&gt;We think this will make ordering and upsell conversations less complex.&lt;&#x2F;li&gt;
&lt;&#x2F;ol&gt;

&lt;h2 id=&quot;what-does-this-mean-for-existing-enterprise-customers&quot;&gt;What does this mean for existing enterprise customers?&lt;&#x2F;h2&gt;

&lt;ul&gt;
  &lt;li&gt;For customers who did not purchase an EE product, there is no change.&lt;&#x2F;li&gt;
  &lt;li&gt;For customers with one EE Product, you were paying $138 per user&#x2F;per year for one product. With the new EE Premium plan you&#x27;ll have quicker support response times and access to the additional products for $199 per user&#x2F;per year.&lt;&#x2F;li&gt;
  &lt;li&gt;For customers with two or more EE Product, you will save money and enjoy quicker support response times.&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;We want all of our customers to have the best experience with our products so we are offering all enterprise customers a 25% discount for early renewal until January 31st, 2017. If you&#x27;ve purchased an EE product we&#x27;ll upgrade your plan to EE Premium so you can try the additional products and services for FREE until your contract renewal. For customers with two or more of the EE products, we will include the additional products and services, update your contract to reflect the new EE Premium price of $199&#x2F;per user, and give you money back (to refund the difference between your bill with multiple EE products and the new EE Premium price).&lt;&#x2F;p&gt;
&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;blogimages&#x2F;announcing-ee-premium-cover.jpg&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
  <entry>
    <title>Git Tips &amp; Tricks</title>
    <link rel="alternate" href="https://about.gitlab.com/2016/12/08/git-tips-and-tricks/"/>
    <id>https://about.gitlab.com/2016/12/08/git-tips-and-tricks/</id>
    <published>2016-12-08T10:34:00+00:00</published>
    <updated>2016-12-08T10:34:00+00:00</updated>
    <author>
      <name>Achilleas Pipinellis</name>
    </author>
    <content type="html">
&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&quot;&gt;Git&lt;&#x2F;a&gt; comes with a ton of commands, and that&#x27;s probably an understatement.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;a href=&quot;&#x2F;images&#x2F;theinternet.png&quot;&gt;The internet&lt;&#x2F;a&gt; is full of Git tips and it&#x27;s hard if not impossible to know
them all, but sometimes you stumble upon an aha! moment that changes your
whole workflow.&lt;&#x2F;p&gt;

&lt;p&gt;In this post, we gathered some Git tips and tricks we use at GitLab everyday.
Hopefully they will add up to your aha! moment.&lt;&#x2F;p&gt;



&lt;ul id=&quot;markdown-toc&quot;&gt;
  &lt;li&gt;&lt;a href=&quot;#intro&quot; id=&quot;markdown-toc-intro&quot;&gt;Intro&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;#gits-built-in-help&quot; id=&quot;markdown-toc-gits-built-in-help&quot;&gt;Git&#x27;s built-in help&lt;&#x2F;a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#the-most-common-commands&quot; id=&quot;markdown-toc-the-most-common-commands&quot;&gt;The most common commands&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#a-help-page-for-every-command&quot; id=&quot;markdown-toc-a-help-page-for-every-command&quot;&gt;A help page for every command&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#git-guides&quot; id=&quot;markdown-toc-git-guides&quot;&gt;Git guides&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
    &lt;&#x2F;ul&gt;
  &lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;#see-the-repository-status-in-your-terminals-prompt&quot; id=&quot;markdown-toc-see-the-repository-status-in-your-terminals-prompt&quot;&gt;See the repository status in your terminal&#x27;s prompt&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;#autocompletion-for-git-commands&quot; id=&quot;markdown-toc-autocompletion-for-git-commands&quot;&gt;Autocompletion for Git commands&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;#git-plugins&quot; id=&quot;markdown-toc-git-plugins&quot;&gt;Git plugins&lt;&#x2F;a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#the--plugin&quot; id=&quot;markdown-toc-the--plugin&quot;&gt;The &lt;code&gt;git-extras&lt;&#x2F;code&gt; plugin&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#the--plugin-1&quot; id=&quot;markdown-toc-the--plugin-1&quot;&gt;The &lt;code&gt;git-open&lt;&#x2F;code&gt; plugin&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
    &lt;&#x2F;ul&gt;
  &lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;#-on-steroids&quot; id=&quot;markdown-toc--on-steroids&quot;&gt;&lt;code&gt;.gitconfig&lt;&#x2F;code&gt; on steroids&lt;&#x2F;a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#set-a-global-&quot; id=&quot;markdown-toc-set-a-global-&quot;&gt;Set a global &lt;code&gt;.gitignore&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#delete-local-branches-that-have-been-removed-from-remote-on-fetchpull&quot; id=&quot;markdown-toc-delete-local-branches-that-have-been-removed-from-remote-on-fetchpull&quot;&gt;Delete local branches that have been removed from remote on fetch&#x2F;pull&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#enable-gits-autosquash-feature-by-default&quot; id=&quot;markdown-toc-enable-gits-autosquash-feature-by-default&quot;&gt;Enable Git&#x27;s autosquash feature by default&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#extra-info-when-using-git-submodules&quot; id=&quot;markdown-toc-extra-info-when-using-git-submodules&quot;&gt;Extra info when using Git submodules&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#change-the-editor-of-gits-messages&quot; id=&quot;markdown-toc-change-the-editor-of-gits-messages&quot;&gt;Change the editor of Git&#x27;s messages&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#change-the-tool-with-which-diffs-are-shown&quot; id=&quot;markdown-toc-change-the-tool-with-which-diffs-are-shown&quot;&gt;Change the tool with which diffs are shown&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
    &lt;&#x2F;ul&gt;
  &lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;#aliases&quot; id=&quot;markdown-toc-aliases&quot;&gt;Aliases&lt;&#x2F;a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#add-an-alias-to-pretty-log-graphs&quot; id=&quot;markdown-toc-add-an-alias-to-pretty-log-graphs&quot;&gt;Add an alias to pretty log graphs&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#add-an-alias-to-checkout-merge-requests-locally&quot; id=&quot;markdown-toc-add-an-alias-to-checkout-merge-requests-locally&quot;&gt;Add an alias to checkout merge requests locally&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#the-oh-my-zsh-git-aliases-plugin&quot; id=&quot;markdown-toc-the-oh-my-zsh-git-aliases-plugin&quot;&gt;The Oh-my-zsh Git aliases plugin&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
    &lt;&#x2F;ul&gt;
  &lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;#git-command-line-tips&quot; id=&quot;markdown-toc-git-command-line-tips&quot;&gt;Git command line tips&lt;&#x2F;a&gt;    &lt;ul&gt;
      &lt;li&gt;&lt;a href=&quot;#an-alias-of-&quot; id=&quot;markdown-toc-an-alias-of-&quot;&gt;An alias of &lt;code&gt;HEAD&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#quickly-checkout-the-previous-branch-you-were-on&quot; id=&quot;markdown-toc-quickly-checkout-the-previous-branch-you-were-on&quot;&gt;Quickly checkout the previous branch you were on&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#delete-local-branches-which-have-already-been-merged-into-master&quot; id=&quot;markdown-toc-delete-local-branches-which-have-already-been-merged-into-master&quot;&gt;Delete local branches which have already been merged into master&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#delete-local-branches-that-no-longer-exist-in-the-remote-repo&quot; id=&quot;markdown-toc-delete-local-branches-that-no-longer-exist-in-the-remote-repo&quot;&gt;Delete local branches that no longer exist in the remote repo&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
      &lt;li&gt;&lt;a href=&quot;#checking-out-a-new-branch-from-a-base-branch&quot; id=&quot;markdown-toc-checking-out-a-new-branch-from-a-base-branch&quot;&gt;Checking out a new branch from a base branch&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
    &lt;&#x2F;ul&gt;
  &lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;#references&quot; id=&quot;markdown-toc-references&quot;&gt;References&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;#conclusion&quot; id=&quot;markdown-toc-conclusion&quot;&gt;Conclusion&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;intro&quot;&gt;Intro&lt;&#x2F;h2&gt;

&lt;p&gt;Almost everybody at GitLab will need to use Git at some point. For newcomers
who know nothing about Git that can be a fearsome experience. We have a
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;gitlab-com&#x2F;marketing&#x2F;raw&#x2F;master&#x2F;design&#x2F;print&#x2F;git-cheatsheet&#x2F;print-pdf&#x2F;git-cheatsheet.pdf&quot;&gt;Git cheatsheet&lt;&#x2F;a&gt; and a &lt;code&gt;#git-help&lt;&#x2F;code&gt; chat channel where we ask questions and
provide help if some of us get stuck. That&#x27;s a quick way to provide help, and
if something is complicated or someone has messed up their local repository and
needs immediate help, there&#x27;s always a person to jump on a quick call.&lt;&#x2F;p&gt;

&lt;p&gt;Here&#x27;s a pack of Git tricks that will leverage your Git-fu and you&#x27;ll hopefully
find useful. Remember, the list is far from exhaustive :)&lt;&#x2F;p&gt;

&lt;h2 id=&quot;gits-built-in-help&quot;&gt;Git&#x27;s built-in help&lt;&#x2F;h2&gt;

&lt;p&gt;The majority of users rely on sites like &lt;a href=&quot;https:&#x2F;&#x2F;stackoverflow.com&quot;&gt;StackOverflow&lt;&#x2F;a&gt; to find answers to their
Git problems, but how often do you use Git&#x27;s built-in help to find more about a
command you are struggling with?&lt;&#x2F;p&gt;

&lt;h3 id=&quot;the-most-common-commands&quot;&gt;The most common commands&lt;&#x2F;h3&gt;

&lt;p&gt;Run &lt;code&gt;git help&lt;&#x2F;code&gt; to print a list of the most common commands. You&#x27;ll probably
notice you&#x27;ve used most of them, but how well do you really know them?
Thankfully, there is a help page for every command!&lt;&#x2F;p&gt;

&lt;h3 id=&quot;a-help-page-for-every-command&quot;&gt;A help page for every command&lt;&#x2F;h3&gt;

&lt;p&gt;Git&#x27;s documentation is comprehensive and is automatically installed with Git.
Run &lt;code&gt;git help &amp;lt;command&amp;gt;&lt;&#x2F;code&gt; to find out all about a command&#x27;s behavior and what
options it can take.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;git-guides&quot;&gt;Git guides&lt;&#x2F;h3&gt;

&lt;p&gt;Git comes with a handful of guides ready for you to explore. Run &lt;code&gt;git help -g&lt;&#x2F;code&gt;
to see what&#x27;s available:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight plaintext&quot;&gt;&lt;code&gt;The common Git guides are:

   attributes   Defining attributes per path
   everyday     Everyday Git With 20 Commands Or So
   glossary     A Git glossary
   ignore       Specifies intentionally untracked files to ignore
   modules      Defining submodule properties
   revisions    Specifying revisions and ranges for Git
   tutorial     A tutorial introduction to Git (for version 1.5.1 or newer)
   workflows    An overview of recommended workflows with Git
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Jump to a Git tutorial with &lt;code&gt;git help tutorial&lt;&#x2F;code&gt;, go through the glossary with
&lt;code&gt;git help glossary&lt;&#x2F;code&gt; or learn about the most common commands with
&lt;code&gt;git help everyday&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;see-the-repository-status-in-your-terminals-prompt&quot;&gt;See the repository status in your terminal&#x27;s prompt&lt;&#x2F;h2&gt;

&lt;p&gt;It&#x27;s very useful to be able to visualize the status of your repository at any
given time. While there are 3rd party tools that include this information
(&lt;a href=&quot;http:&#x2F;&#x2F;ohmyz.sh&#x2F;&quot;&gt;oh-my-zsh&lt;&#x2F;a&gt; anyone?), Git itself provides a script named &lt;code&gt;git-prompt.sh&lt;&#x2F;code&gt;
that does exactly that. You can &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git&#x2F;git&#x2F;blob&#x2F;master&#x2F;contrib&#x2F;completion&#x2F;git-prompt.sh&quot;&gt;download it&lt;&#x2F;a&gt; and follow the
instructions in it to install and use it in your system. If you&#x27;re using Linux
and have installed Git with your package manager, it may already be
present on your system, usually under &lt;code&gt;&#x2F;etc&#x2F;bash_completion.d&#x2F;&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Go ahead and replace your boring shell prompt with something like this:&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;git-tricks&#x2F;git-shell-info.png&quot; alt=&quot;Git shell prompt&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;p&gt;&lt;em&gt;Taken from oh-my-zsh&#x27;s &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;robbyrussell&#x2F;oh-my-zsh&#x2F;wiki&#x2F;Themes#kafeitu&quot;&gt;themes wiki&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;autocompletion-for-git-commands&quot;&gt;Autocompletion for Git commands&lt;&#x2F;h2&gt;

&lt;p&gt;You may also find it useful to use the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git&#x2F;git&#x2F;tree&#x2F;master&#x2F;contrib&#x2F;completion&quot;&gt;completion scripts&lt;&#x2F;a&gt; that provide Git
command completion for &lt;code&gt;bash&lt;&#x2F;code&gt;, &lt;code&gt;tcsh&lt;&#x2F;code&gt; and &lt;code&gt;zsh&lt;&#x2F;code&gt;. Again, follow the instructions
inside the scripts to learn how to install them. Once done, you can try out
typing a command.&lt;&#x2F;p&gt;

&lt;p&gt;Let&#x27;s say you want to type &lt;code&gt;git pull&lt;&#x2F;code&gt;. If Git completion is enabled, typing
just the first letter with &lt;code&gt;git p&lt;&#x2F;code&gt; followed by &lt;kbd&gt;Tab&lt;&#x2F;kbd&gt; will show the
following:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight plaintext&quot;&gt;&lt;code&gt;pack-objects   -- create packed archive of objects
pack-redundant -- find redundant pack files
pack-refs      -- pack heads and tags for efficient repository access
parse-remote   -- routines to help parsing remote repository access parameters
patch-id       -- compute unique ID for a patch
prune          -- prune all unreachable objects from the object database
prune-packed   -- remove extra objects that are already in pack files
pull           -- fetch from and merge with another repository or local branch
push           -- update remote refs along with associated objects
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;To show all available commands, type &lt;code&gt;git&lt;&#x2F;code&gt; in your terminal followed by
&lt;kbd&gt;Tab&lt;&#x2F;kbd&gt;+ &lt;kbd&gt;Tab&lt;&#x2F;kbd&gt;, and see the magic happening.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;https:&#x2F;&#x2F;media.giphy.com&#x2F;media&#x2F;12NUbkX6p4xOO4&#x2F;giphy.gif&quot; alt=&quot;It&#x27;s a kind of magic&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;git-plugins&quot;&gt;Git plugins&lt;&#x2F;h2&gt;

&lt;p&gt;Since Git is free software, it&#x27;s easy for people to write scripts that extend
its functionality. Let&#x27;s see some of the most common ones.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;the--plugin&quot;&gt;The &lt;code&gt;git-extras&lt;&#x2F;code&gt; plugin&lt;&#x2F;h3&gt;

&lt;p&gt;If you want to enhance Git with more commands, you&#x27;ll want to try out the
&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tj&#x2F;git-extras&quot;&gt;&lt;code&gt;git-extras&lt;&#x2F;code&gt; plugin&lt;&#x2F;a&gt;. It includes commands like &lt;code&gt;git info&lt;&#x2F;code&gt; (show
information about the repository), &lt;code&gt;git effort&lt;&#x2F;code&gt; (number of commits per file),
and the list goes on. After you &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tj&#x2F;git-extras&#x2F;blob&#x2F;master&#x2F;Installation.md&quot;&gt;install&lt;&#x2F;a&gt; it, make sure to visit
the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;tj&#x2F;git-extras&#x2F;blob&#x2F;master&#x2F;Commands.md&quot;&gt;documentation on the provided commands&lt;&#x2F;a&gt; in order to understand
what each one does before using it.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;the--plugin-1&quot;&gt;The &lt;code&gt;git-open&lt;&#x2F;code&gt; plugin&lt;&#x2F;h3&gt;

&lt;p&gt;If you want to quickly visit the website on which the repository you&#x27;re on is
hosted, &lt;code&gt;git-open&lt;&#x2F;code&gt; is for you. All major providers are supported (GitLab, GitHub,
Bitbucket) and you can even use them all at the same time if you set
them as different remotes.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;paulirish&#x2F;git-open#installation&quot;&gt;Install it&lt;&#x2F;a&gt;, and try it out by cloning a repository from
&lt;a href=&quot;https:&#x2F;&#x2F;gitlab.com&#x2F;explore&quot;&gt;GitLab.com&lt;&#x2F;a&gt;. From your terminal navigate to that
repository and run &lt;code&gt;git open&lt;&#x2F;code&gt; to be transferred to the project&#x27;s page on
GitLab.com.&lt;&#x2F;p&gt;

&lt;p&gt;It works by default for projects hosted on GitLab.com, but you can also use it
with your own GitLab instances. In that case, make sure to set up the domain
name with:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git config gitopen.gitlab.domain git.example.com
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You can even open different remotes and branches if they have been set up.
Read more in the &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;paulirish&#x2F;git-open#examples&quot;&gt;examples section&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h2 id=&quot;-on-steroids&quot;&gt;&lt;code&gt;.gitconfig&lt;&#x2F;code&gt; on steroids&lt;&#x2F;h2&gt;

&lt;p&gt;The &lt;code&gt;.gitconfig&lt;&#x2F;code&gt; file contains information on how you want Git to behave on
certain circumstances. There are options you can set at a repository level,
but you can also set them in a global &lt;code&gt;.gitconfig&lt;&#x2F;code&gt; so that all local config
will inherit its values. This file usually resides in your home directory.
If not, either you&#x27;ll have to create it manually or it will be automatically
be created when you issue a command starting with &lt;code&gt;git config --global&lt;&#x2F;code&gt; as
we&#x27;ll see below.&lt;&#x2F;p&gt;

&lt;p&gt;The very first encounter with &lt;code&gt;.gitconfig&lt;&#x2F;code&gt; was probably when you set your
name and email address for Git to know who you are.
To know more about the options &lt;code&gt;.gitconfig&lt;&#x2F;code&gt; can take, see the &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-config&quot;&gt;Git documentation
on &lt;code&gt;.gitconfig&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;p class=&quot;alert alert-info&quot;&gt;If you are using macOS or Linux, &lt;code&gt;.gitconfig&lt;&#x2F;code&gt; will probably be hidden if you are
trying to open it from a file manager. Either make sure the hidden files are
shown or open it using a command in the terminal: &lt;code&gt;atom ~&#x2F;.gitconfig&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Let&#x27;s explore some of the most useful config options.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;set-a-global-&quot;&gt;Set a global &lt;code&gt;.gitignore&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;

&lt;p&gt;If you want to avoid committing files like &lt;code&gt;.DS_Store&lt;&#x2F;code&gt;, Vim &lt;code&gt;swp&lt;&#x2F;code&gt; files, etc.,
you can set up a global &lt;code&gt;.gitignore&lt;&#x2F;code&gt; file.&lt;&#x2F;p&gt;

&lt;p&gt;First create the file:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;touch ~&#x2F;.gitignore
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Then run:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git config --global core.excludesFile ~&#x2F;.gitignore
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or manually add the following to your &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[core]&lt;&#x2F;span&gt;
  &lt;span class=&quot;py&quot;&gt;excludesFile&lt;&#x2F;span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;~&#x2F;.gitignore&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Gradually build up your own useful list of things you want Git to ignore. Read
the &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;gitignore&quot;&gt;gitignore documentation&lt;&#x2F;a&gt; to find out
more.&lt;&#x2F;p&gt;

&lt;hr &#x2F;&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-config#git-config-coreexcludesFile&quot;&gt;Git docs source&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;h3 id=&quot;delete-local-branches-that-have-been-removed-from-remote-on-fetchpull&quot;&gt;Delete local branches that have been removed from remote on fetch&#x2F;pull&lt;&#x2F;h3&gt;

&lt;p&gt;You might already have a bunch of stale branches in your local repository that
no longer exist in the remote one. To delete them in each fetch&#x2F;pull, run:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git config --global fetch.prune &lt;span class=&quot;nb&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or manually add the following to your &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[fetch]&lt;&#x2F;span&gt;
  &lt;span class=&quot;py&quot;&gt;prune&lt;&#x2F;span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-config#git-config-fetchprune&quot;&gt;Git docs source&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;h3 id=&quot;enable-gits-autosquash-feature-by-default&quot;&gt;Enable Git&#x27;s autosquash feature by default&lt;&#x2F;h3&gt;

&lt;p&gt;Autosquash makes it quicker and easier to squash or fixup commits during an
interactive rebase. It can be enabled for each rebase using
&lt;code&gt;git rebase -i --autosquash&lt;&#x2F;code&gt;, but it&#x27;s easier to turn it on by default.&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git config --global rebase.autosquash &lt;span class=&quot;nb&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or manually add the following to your &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[rebase]&lt;&#x2F;span&gt;
  &lt;span class=&quot;py&quot;&gt;autosquash&lt;&#x2F;span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p class=&quot;alert alert-info&quot;&gt;At this point, let us remind you of &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Git-Branching-Rebasing#The-Perils-of-Rebasing&quot;&gt;the perils of rebasing&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;hr &#x2F;&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-config#git-config-rebaseautoSquash&quot;&gt;Git docs source&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;
&lt;em&gt;(&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;thoughtbot&#x2F;dotfiles&#x2F;pull&#x2F;377&quot;&gt;tip taken from thoughbot&lt;&#x2F;a&gt;)&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;h3 id=&quot;extra-info-when-using-git-submodules&quot;&gt;Extra info when using Git submodules&lt;&#x2F;h3&gt;

&lt;p&gt;If you are using &lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;book&#x2F;en&#x2F;v2&#x2F;Git-Tools-Submodules&quot;&gt;submodules&lt;&#x2F;a&gt;, it might be useful to turn on the submodule summary.
From your terminal run:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git config --global status.submoduleSummary &lt;span class=&quot;nb&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or manually add the following to your &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[status]&lt;&#x2F;span&gt;
  &lt;span class=&quot;py&quot;&gt;submoduleSummary&lt;&#x2F;span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;true&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-config#git-config-statussubmoduleSummary&quot;&gt;Git docs source&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;h3 id=&quot;change-the-editor-of-gits-messages&quot;&gt;Change the editor of Git&#x27;s messages&lt;&#x2F;h3&gt;

&lt;p&gt;You can change the default text editor for use by Git commands.&lt;&#x2F;p&gt;

&lt;p&gt;From &lt;code&gt;git help var&lt;&#x2F;code&gt;:
the order of preference is the &lt;code&gt;$GIT_EDITOR&lt;&#x2F;code&gt; environment variable, then
&lt;code&gt;core.editor&lt;&#x2F;code&gt; configuration, then &lt;code&gt;$VISUAL&lt;&#x2F;code&gt;, then &lt;code&gt;$EDITOR&lt;&#x2F;code&gt;, and then the
default chosen at compile time, which is usually &lt;code&gt;vi&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;p&gt;Running &lt;code&gt;git config --show-origin core.editor&lt;&#x2F;code&gt; will tell you if &lt;code&gt;core.editor&lt;&#x2F;code&gt;
is set and from which file. This needs at least Git 2.8.&lt;&#x2F;p&gt;

&lt;p&gt;To change it to your favor editor (&lt;code&gt;vim&lt;&#x2F;code&gt;, &lt;code&gt;emacs&lt;&#x2F;code&gt;, &lt;code&gt;atom&lt;&#x2F;code&gt;, etc.), run:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git config --global core.editor vim
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or manually add the following to your &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[core]&lt;&#x2F;span&gt;
  &lt;span class=&quot;py&quot;&gt;editor&lt;&#x2F;span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;vim&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-config.html#git-config-coreeditor&quot;&gt;Git docs source&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;h3 id=&quot;change-the-tool-with-which-diffs-are-shown&quot;&gt;Change the tool with which diffs are shown&lt;&#x2F;h3&gt;

&lt;p&gt;&lt;code&gt;git diff&lt;&#x2F;code&gt; is useful as it shows the changes that are not currently staged.
When running this command Git usually uses its internal tool and displays
the changes in your terminal.&lt;&#x2F;p&gt;

&lt;p&gt;If you don&#x27;t like the default difftool there are a couple of others to choose
from:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;vimdiff&lt;&#x2F;code&gt; - &lt;a href=&quot;http:&#x2F;&#x2F;vimdoc.sourceforge.net&#x2F;htmldoc&#x2F;diff.html&quot;&gt;Vim&#x27;s built-in vimdiff&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;code&gt;magit&lt;&#x2F;code&gt; - &lt;a href=&quot;https:&#x2F;&#x2F;www.emacswiki.org&#x2F;emacs&#x2F;Magit&quot;&gt;Emacs most popular tool is Magit&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;code&gt;meld&lt;&#x2F;code&gt; - &lt;a href=&quot;http:&#x2F;&#x2F;meldmerge.org&#x2F;&quot;&gt;A visual diff and merge tool written in Python&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;code&gt;kdiff3&lt;&#x2F;code&gt; - &lt;a href=&quot;http:&#x2F;&#x2F;kdiff3.sourceforge.net&#x2F;&quot;&gt;A diff and merge program written in Qt&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;p&gt;To change the default tool for watching diffs run the following:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git config --global diff.tool vimdiff
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or manually add the following to your &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[diff]&lt;&#x2F;span&gt;
  &lt;span class=&quot;py&quot;&gt;tool&lt;&#x2F;span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;vimdiff&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Also related is the &lt;code&gt;merge.tool&lt;&#x2F;code&gt; setting which can be set to a tool to be used
as the merge resolution program. Similarly:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git config --global merge.tool vimdiff
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Or manually add the following to your &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[merge]&lt;&#x2F;span&gt;
  &lt;span class=&quot;py&quot;&gt;tool&lt;&#x2F;span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;vimdiff&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;hr &#x2F;&gt;

&lt;p&gt;&lt;em&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;docs&#x2F;git-difftool&quot;&gt;Git docs source&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;h2 id=&quot;aliases&quot;&gt;Aliases&lt;&#x2F;h2&gt;

&lt;p&gt;Git commands can take a lot of flags at a time. For example, for a log graph
you can use the following command:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git log --graph --pretty&lt;span class=&quot;o&quot;&gt;=&lt;&#x2F;span&gt;format:&lt;span class=&quot;s1&quot;&gt;&#x27;%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset&#x27;&lt;&#x2F;span&gt; --abbrev-commit --date&lt;span class=&quot;o&quot;&gt;=&lt;&#x2F;span&gt;relative
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;You sure don&#x27;t want to type this every time you need to run it. For that purpose,
Git supports aliases, which are custom user-defined commands that build on top
of the core ones. They are defined in &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt; under the &lt;code&gt;[alias]&lt;&#x2F;code&gt; group.&lt;&#x2F;p&gt;

&lt;p&gt;Open &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt; with your editor and start adding stuff.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;add-an-alias-to-pretty-log-graphs&quot;&gt;Add an alias to pretty log graphs&lt;&#x2F;h3&gt;

&lt;p&gt;In your &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt; add:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight ini&quot;&gt;&lt;code&gt;&lt;span class=&quot;nn&quot;&gt;[alias]&lt;&#x2F;span&gt;
  &lt;span class=&quot;py&quot;&gt;lg&lt;&#x2F;span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;log --graph --pretty=format:&#x27;%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr)%Creset&#x27; --abbrev-commit --date=relative&lt;&#x2F;span&gt;
  &lt;span class=&quot;py&quot;&gt;lol&lt;&#x2F;span&gt; &lt;span class=&quot;p&quot;&gt;=&lt;&#x2F;span&gt; &lt;span class=&quot;s&quot;&gt;log --graph --decorate --pretty=oneline --abbrev-commit&lt;&#x2F;span&gt;
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Next time you want the pretty log to appear, run: &lt;code&gt;git lg&lt;&#x2F;code&gt; or &lt;code&gt;git lol&lt;&#x2F;code&gt; for
some pretty log graphs.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;add-an-alias-to-checkout-merge-requests-locally&quot;&gt;Add an alias to checkout merge requests locally&lt;&#x2F;h3&gt;

&lt;p&gt;A merge request contains all the history from a repository, plus the additional
commits added to the branch associated with the merge request. Note that you
can checkout a public merge request locally even if the source project is a fork
(even a private fork) of the target project.&lt;&#x2F;p&gt;

&lt;p&gt;To checkout a merge request locally, add the following alias to your &lt;code&gt;~&#x2F;.gitconfig&lt;&#x2F;code&gt;:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight plaintext&quot;&gt;&lt;code&gt;[alias]
  mr = !sh -c &#x27;git fetch $1 merge-requests&#x2F;$2&#x2F;head:mr-$1-$2 &amp;amp;&amp;amp; git checkout mr-$1-$2&#x27; -
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Now you can check out a particular merge request from any repository and any
remote. For example, to check out the merge request with ID 5 as shown in GitLab
from the &lt;code&gt;upstream&lt;&#x2F;code&gt; remote, run:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight plaintext&quot;&gt;&lt;code&gt;git mr upstream 5
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;This will fetch the merge request into a local &lt;code&gt;mr-upstream-5&lt;&#x2F;code&gt; branch and check
it out. In the above example, &lt;code&gt;upstream&lt;&#x2F;code&gt; is the remote that points to GitLab
which you can find out by running &lt;code&gt;git remote -v&lt;&#x2F;code&gt;.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;the-oh-my-zsh-git-aliases-plugin&quot;&gt;The Oh-my-zsh Git aliases plugin&lt;&#x2F;h3&gt;

&lt;p&gt;If you are an &lt;a href=&quot;http:&#x2F;&#x2F;ohmyz.sh&#x2F;&quot;&gt;Oh My Zsh&lt;&#x2F;a&gt; user you&#x27;ll probably know this already.
Learn how you can &lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;robbyrussell&#x2F;oh-my-zsh&#x2F;wiki&#x2F;Plugin:git&quot;&gt;enable the Git plugin&lt;&#x2F;a&gt; provided with Oh My Zsh and
start using the short commands to save time. Some examples are:&lt;&#x2F;p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;code&gt;gl&lt;&#x2F;code&gt;  instead of &lt;code&gt;git pull&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;code&gt;gp&lt;&#x2F;code&gt;  instead of &lt;code&gt;git push&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;code&gt;gco&lt;&#x2F;code&gt; instead of &lt;code&gt;git checkout&lt;&#x2F;code&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;git-command-line-tips&quot;&gt;Git command line tips&lt;&#x2F;h2&gt;

&lt;p&gt;Here&#x27;s a list of Git tips we gathered.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;an-alias-of-&quot;&gt;An alias of &lt;code&gt;HEAD&lt;&#x2F;code&gt;&lt;&#x2F;h3&gt;

&lt;p&gt;Did you know &lt;code&gt;@&lt;&#x2F;code&gt; is the same as &lt;code&gt;HEAD&lt;&#x2F;code&gt;? Using it during a rebase is a life saver:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git rebase -i @~2
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;quickly-checkout-the-previous-branch-you-were-on&quot;&gt;Quickly checkout the previous branch you were on&lt;&#x2F;h3&gt;

&lt;p&gt;A dash (&lt;code&gt;-&lt;&#x2F;code&gt;) refers to the branch you were on before the current one.
Use it to checkout the previous branch (&lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;holman&#x2F;status&#x2F;530490167522779137&quot;&gt;source&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Checkout master&lt;&#x2F;span&gt;
git checkout master

&lt;span class=&quot;c&quot;&gt;# Create and checkout to a new branch&lt;&#x2F;span&gt;
git checkout -b git-tips

&lt;span class=&quot;c&quot;&gt;# Checkout master&lt;&#x2F;span&gt;
git checkout master

&lt;span class=&quot;c&quot;&gt;# Checkout to the previous branch (git-tips)&lt;&#x2F;span&gt;
git checkout -
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;delete-local-branches-which-have-already-been-merged-into-master&quot;&gt;Delete local branches which have already been merged into master&lt;&#x2F;h3&gt;

&lt;p&gt;If you are working everyday on a project that gets contributions all the time,
the local branches number increases without noticing it. Run the following
command to delete all local branches that are already merged into master
(&lt;a href=&quot;http:&#x2F;&#x2F;stevenharman.net&#x2F;git-clean-delete-already-merged-branches&quot;&gt;source&lt;&#x2F;a&gt;):&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;&lt;span class=&quot;c&quot;&gt;# Make sure you have checked out master first&lt;&#x2F;span&gt;
git checkout master

&lt;span class=&quot;c&quot;&gt;# Delete merged branches to master except master&lt;&#x2F;span&gt;
git branch --merged master | grep -v &lt;span class=&quot;s2&quot;&gt;&quot;master&quot;&lt;&#x2F;span&gt; | xargs -n 1 git branch -d
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;In the event that you accidentally delete master (💩 happens),  get it back with:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git checkout -b master origin&#x2F;master
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h3 id=&quot;delete-local-branches-that-no-longer-exist-in-the-remote-repo&quot;&gt;Delete local branches that no longer exist in the remote repo&lt;&#x2F;h3&gt;

&lt;p&gt;To remove all tracking branches that you have locally but are no more present in
the remote repository (&lt;code&gt;origin&lt;&#x2F;code&gt;):&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git remote prune origin
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;Use the &lt;code&gt;--dry-run&lt;&#x2F;code&gt; flag to only see what branches will be pruned, but not
actually prune them:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git remote prune origin --dry-run
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;If you want this to be run automatically every time you fetch&#x2F;pull, see
&lt;a href=&quot;#delete-local-branches-that-have-been-removed-from-remote-on-fetchpull&quot;&gt;how to add it to your &lt;code&gt;.gitconfig&lt;&#x2F;code&gt;&lt;&#x2F;a&gt;.&lt;&#x2F;p&gt;

&lt;h3 id=&quot;checking-out-a-new-branch-from-a-base-branch&quot;&gt;Checking out a new branch from a base branch&lt;&#x2F;h3&gt;

&lt;p&gt;You can checkout a new branch from a base branch without first checking out
the base branch. Confusing? Here&#x27;s an example.&lt;&#x2F;p&gt;

&lt;p&gt;If you are on a branch named &lt;code&gt;old-branch&lt;&#x2F;code&gt; and you want to
checkout &lt;code&gt;new-branch&lt;&#x2F;code&gt; based off &lt;code&gt;master&lt;&#x2F;code&gt;, you&#x27;d normally do:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git checkout master
git checkout -b new-branch
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;There&#x27;s a quicker way though. While still on the &lt;code&gt;old-branch&lt;&#x2F;code&gt;, run:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git checkout -b new-branch master
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;p&gt;The pattern is the following:&lt;&#x2F;p&gt;

&lt;pre class=&quot;highlight shell&quot;&gt;&lt;code&gt;git checkout -b new_branch base_branch
&lt;&#x2F;code&gt;&lt;&#x2F;pre&gt;
&lt;h2 id=&quot;references&quot;&gt;References&lt;&#x2F;h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;thoughtbot&#x2F;dotfiles&#x2F;blob&#x2F;master&#x2F;gitconfig&quot;&gt;Thoughbot&#x27;s gitconfig file&lt;&#x2F;a&gt;
contains useful tips some of which are also present in this post&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git-tips&#x2F;tips&#x2F;blob&#x2F;master&#x2F;README.md&quot;&gt;A collection of Git tips&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;http:&#x2F;&#x2F;usevim.com&#x2F;2012&#x2F;03&#x2F;21&#x2F;git-and-vimdiff&#x2F;&quot;&gt;Git and Vimdiff&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
  &lt;li&gt;&lt;a href=&quot;https:&#x2F;&#x2F;git-scm.com&#x2F;&quot;&gt;Git&#x27;s official site&lt;&#x2F;a&gt;&lt;&#x2F;li&gt;
&lt;&#x2F;ul&gt;

&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;&#x2F;h2&gt;

&lt;p&gt;As always, writing something about Git, only scratches the surface. While some
of the tips included in this post might come in handy, there are sure a lot
of other stuff we&#x27;re not familiar with.&lt;&#x2F;p&gt;

&lt;p&gt;&lt;img src=&quot;&#x2F;images&#x2F;blogimages&#x2F;git-tricks&#x2F;uncle-sam-wants-git.jpg&quot; alt=&quot;Uncle Sam wants you to tell your trick&quot; class=&quot;shadow&quot; &#x2F;&gt;&lt;&#x2F;p&gt;

&lt;hr &#x2F;&gt;

&lt;p&gt;&lt;em&gt;Image: &quot;&lt;a href=&quot;https:&#x2F;&#x2F;github.com&#x2F;git&#x2F;git-scm.com&#x2F;blob&#x2F;master&#x2F;public&#x2F;images&#x2F;branching-illustration%402x.png&quot;&gt;Branching illustration&lt;&#x2F;a&gt;&quot; by &lt;a href=&quot;https:&#x2F;&#x2F;twitter.com&#x2F;jasonlong&quot;&gt;Jason Long&lt;&#x2F;a&gt; is licensed under &lt;a href=&quot;https:&#x2F;&#x2F;creativecommons.org&#x2F;licenses&#x2F;by&#x2F;3.0&#x2F;&quot;&gt;CC BY 3.0&lt;&#x2F;a&gt;&lt;&#x2F;em&gt;&lt;&#x2F;p&gt;

&lt;!-- Links --&gt;

&lt;img src=&#x27;https:&#x2F;&#x2F;about.gitlab.com&#x2F;images&#x2F;blogimages&#x2F;git-tricks&#x2F;git-tricks-cover-image.png&#x27; class=&#x27;webfeedsFeaturedVisual&#x27; style=&#x27;display: none;&#x27; &#x2F;&gt;    </content>
  </entry>
</feed>
