<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jim Sheldon</title>
    <description>The latest articles on Forem by Jim Sheldon (@jimsheldon).</description>
    <link>https://forem.com/jimsheldon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F840488%2Fc7d2e192-ed3e-4d62-a118-387f73d4b0f8.png</url>
      <title>Forem: Jim Sheldon</title>
      <link>https://forem.com/jimsheldon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jimsheldon"/>
    <language>en</language>
    <item>
      <title>React App and Build Pipeline with Task and Gitness</title>
      <dc:creator>Jim Sheldon</dc:creator>
      <pubDate>Fri, 05 Apr 2024 14:01:13 +0000</pubDate>
      <link>https://forem.com/harness/react-app-and-build-pipeline-with-task-and-gitness-178l</link>
      <guid>https://forem.com/harness/react-app-and-build-pipeline-with-task-and-gitness-178l</guid>
      <description>&lt;p&gt;&lt;a href="https://taskfile.dev/" rel="noopener noreferrer"&gt;Task&lt;/a&gt; is a task runner/automation tool written in &lt;a href="https://go.dev/" rel="noopener noreferrer"&gt;Go&lt;/a&gt; and distributed as a single binary.&lt;/p&gt;

&lt;p&gt;A Taskfile is written in YAML, which may provide a shorter learning curve than alternative tools, like &lt;a href="https://www.gnu.org/software/make/" rel="noopener noreferrer"&gt;GNU Make&lt;/a&gt;. Task can also leverage Go's robust &lt;a href="https://taskfile.dev/usage/#gos-template-engine" rel="noopener noreferrer"&gt;template engine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Task can be useful in build and test pipelines. Logic for running builds and tests can be written once in &lt;code&gt;Taskfile.yml&lt;/code&gt; (or other &lt;a href="https://taskfile.dev/usage/#supported-file-names" rel="noopener noreferrer"&gt;supported filenames&lt;/a&gt;), then used in both local development workflows and under automation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://gitness.com?utm_source=dev.to&amp;amp;utm_content=blog&amp;amp;utm_medium=blog&amp;amp;utm_term=gitness-task-in-ci"&gt;Gitness&lt;/a&gt; is an open source development platform from &lt;a href="https://www.harness.io?utm_source=dev.to&amp;amp;utm_content=blog&amp;amp;utm_medium=blog&amp;amp;utm_term=gitness-task-in-ci"&gt;Harness&lt;/a&gt; that hosts your source code repositories and runs your software development lifecycle pipelines.&lt;/p&gt;

&lt;p&gt;In this guide, we'll craft a &lt;code&gt;Taskfile.yml&lt;/code&gt; for a sample &lt;a href="https://react.dev/" rel="noopener noreferrer"&gt;React&lt;/a&gt; app, suitable for both local development and integration with your pipelines powered by Gitness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://taskfile.dev/installation/" rel="noopener noreferrer"&gt;Install Task&lt;/a&gt; and verify you can run &lt;code&gt;task&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;p&gt;This guide was tested with Task version 3.35.1.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ task --version
Task version: v3.35.1 (h1:zjQ3tLv+LIStDDTzOQx8F97NE/8FSTanjZuwgy/hwro=)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://www.docker.com/products/docker-desktop/" rel="noopener noreferrer"&gt;Install Docker&lt;/a&gt; and verify you can run &lt;code&gt;docker&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;p&gt;This guide was tested with Docker version 24.0.7.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ docker --version
Docker version 24.0.7, build afdd53b


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;a href="https://nodejs.org/en/download" rel="noopener noreferrer"&gt;Install Node&lt;/a&gt; and verify you can run &lt;code&gt;node&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;p&gt;This guide was tested with Node version 20.12.0.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

$ node --version
v20.12.0


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ℹ️ Note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Installing Node also installs &lt;code&gt;npm&lt;/code&gt; and &lt;code&gt;npx&lt;/code&gt; binaries.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Create React Application
&lt;/h2&gt;

&lt;p&gt;Use the &lt;a href="https://create-react-app.dev/" rel="noopener noreferrer"&gt;Create React App&lt;/a&gt; project to automatically generate the application. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npx create-react-app my-react-app


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Your &lt;code&gt;my-react-app&lt;/code&gt; directory structure will look like this.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

my-react-app/
├── README.md
├── node_modules/
├── package-lock.json
├── package.json
├── public/
│   ├── favicon.ico
│   ├── index.html
│   ├── logo192.png
│   ├── logo512.png
│   ├── manifest.json
│   └── robots.txt
└── src/
    ├── App.css
    ├── App.js
    ├── App.test.js
    ├── index.css
    ├── index.js
    ├── logo.svg
    ├── reportWebVitals.js
    └── setupTests.js


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Change to the application directory.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

cd my-react-app


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Start the application.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

npm start


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Open &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; in your browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F854iu180bjjtd05fn17u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F854iu180bjjtd05fn17u.png" alt="Sample React application running in a browser"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You now have a working React application! 🎉&lt;/p&gt;

&lt;p&gt;In your terminal, type Ctrl-C to stop the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create &lt;code&gt;Taskfile.yml&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;Create a &lt;code&gt;Taskfile.yml&lt;/code&gt; file in your &lt;code&gt;my-react-app&lt;/code&gt; directory with this configuration.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;3'&lt;/span&gt;

&lt;span class="na"&gt;tasks&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;npm-install&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;npm-install&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm run build&lt;/span&gt;

  &lt;span class="na"&gt;test&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;deps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;npm-install&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
    &lt;span class="na"&gt;cmds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;npm test&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;build&lt;/code&gt; task runs &lt;code&gt;npm run build&lt;/code&gt;, which creates a &lt;a href="https://create-react-app.dev/docs/production-build/" rel="noopener noreferrer"&gt;production build&lt;/a&gt; of your application.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;test&lt;/code&gt; task runs &lt;code&gt;npm test&lt;/code&gt;, which runs &lt;a href="https://create-react-app.dev/docs/running-tests" rel="noopener noreferrer"&gt;unit tests&lt;/a&gt;. There is only one unit test in &lt;code&gt;src/App.test.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;npm-install&lt;/code&gt; task is a &lt;a href="https://taskfile.dev/usage/#task-dependencies" rel="noopener noreferrer"&gt;dependency&lt;/a&gt; of the &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; tasks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build and Test
&lt;/h2&gt;

&lt;p&gt;Run &lt;code&gt;task build&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2kc7r49oy6fex39pjrt3.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2kc7r49oy6fex39pjrt3.gif" alt="Animated gif of the build task output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default, &lt;code&gt;npm test&lt;/code&gt; will run tests interactively. To simulate running tests under &lt;a href="https://create-react-app.dev/docs/running-tests/#continuous-integration" rel="noopener noreferrer"&gt;Continuous Integration&lt;/a&gt;, set the CI environment variable.&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;CI=true task test&lt;/code&gt; in your terminal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj554xflkjr2d3r1g26nh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj554xflkjr2d3r1g26nh.gif" alt="Animated gif of the test task output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Note that &lt;code&gt;task&lt;/code&gt; passed the &lt;code&gt;CI=true&lt;/code&gt; &lt;a href="https://taskfile.dev/usage/#variables" rel="noopener noreferrer"&gt;variable&lt;/a&gt; to the &lt;code&gt;npm test&lt;/code&gt; command.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setup Gitness
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;a href="https://docs.gitness.com/#install-gitness" rel="noopener noreferrer"&gt;Install Gitness&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.gitness.com/#create-a-project" rel="noopener noreferrer"&gt;Create a project&lt;/a&gt; named &lt;code&gt;demo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Either &lt;a href="https://docs.gitness.com/#create-a-repository" rel="noopener noreferrer"&gt;create a repository&lt;/a&gt; named &lt;code&gt;my-react-app&lt;/code&gt; and push your sample app code, or &lt;a href="https://docs.gitness.com/repositories/overview#import-a-repository" rel="noopener noreferrer"&gt;import&lt;/a&gt; the repository &lt;a href="https://github.com/jimsheldon/my-react-app" rel="noopener noreferrer"&gt;jimsheldon/my-react-app&lt;/a&gt;, which I created for this guide&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Create Pipeline
&lt;/h2&gt;

&lt;p&gt;Open &lt;a href="http://localhost:3000/demo/my-react-app/pipelines" rel="noopener noreferrer"&gt;http://localhost:3000/demo/my-react-app/pipelines&lt;/a&gt; in your browser and select &lt;strong&gt;New Pipeline&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Enter &lt;code&gt;build-and-test&lt;/code&gt; in the &lt;strong&gt;Name&lt;/strong&gt; field (this will automatically populate the &lt;strong&gt;YAML Path&lt;/strong&gt; field), then select &lt;strong&gt;Create&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkycohke003skh6ghhbi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvkycohke003skh6ghhbi.png" alt="Create Gitness pipeline"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter this Gitness &lt;a href="https://docs.gitness.com/category/pipelines" rel="noopener noreferrer"&gt;pipeline&lt;/a&gt; in the YAML editor.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;

&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pipeline&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;stages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;task example&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ci&lt;/span&gt;
      &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;install task&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;run&lt;/span&gt;
            &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alpine&lt;/span&gt;
              &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                &lt;span class="s"&gt;apk add curl&lt;/span&gt;
                &lt;span class="s"&gt;sh -c "$(curl --location https://taskfile.dev/install.sh)" -- -d&lt;/span&gt;
                &lt;span class="s"&gt;./bin/task --version&lt;/span&gt;

          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;run&lt;/span&gt;
            &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:20&lt;/span&gt;
              &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                &lt;span class="s"&gt;./bin/task build&lt;/span&gt;

          &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;test&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;run&lt;/span&gt;
            &lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
              &lt;span class="na"&gt;container&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;node:20&lt;/span&gt;
              &lt;span class="na"&gt;script&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
                &lt;span class="s"&gt;./bin/task test&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This Gitness pipeline has a single stage with three steps. The &lt;code&gt;install task&lt;/code&gt; step uses the &lt;code&gt;alpine&lt;/code&gt; Docker image to &lt;a href="https://taskfile.dev/installation/#install-script" rel="noopener noreferrer"&gt;install&lt;/a&gt; the &lt;code&gt;task&lt;/code&gt; binary into the workspace, where it can be reused by the following &lt;code&gt;build&lt;/code&gt; and &lt;code&gt;test&lt;/code&gt; steps, which run in the &lt;code&gt;node&lt;/code&gt; Docker image.&lt;/p&gt;

&lt;p&gt;Select &lt;strong&gt;Save and Run&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc6vpd8qmyheshdie1mf.png" alt="Gitness pipeline yaml editor"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Observe the pipeline execution.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0dkkplxjhaz1sq2ixk5v.png" alt="Gitness pipeline execution"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This workflow improves the &lt;a href="https://en.wikipedia.org/wiki/Separation_of_concerns" rel="noopener noreferrer"&gt;separation of concerns&lt;/a&gt; between local development and pipeline execution.&lt;/p&gt;

&lt;p&gt;As long as the application can be built and tested with &lt;code&gt;task build&lt;/code&gt; and &lt;code&gt;task test&lt;/code&gt; commands, developers always keep the same workflow, and &lt;strong&gt;the pipeline does not need to be modified&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example, the developers could &lt;a href="https://classic.yarnpkg.com/lang/en/docs/migrating-from-npm/" rel="noopener noreferrer"&gt;switch to yarn&lt;/a&gt; by changing &lt;code&gt;Taskfile.yml&lt;/code&gt; to use &lt;code&gt;yarn&lt;/code&gt; commands rather than &lt;code&gt;npm&lt;/code&gt; commands. This change would be transparent to developers, who would continue to run &lt;code&gt;task build&lt;/code&gt; and &lt;code&gt;task test&lt;/code&gt;, and the Gitness pipeline yaml would not need to be changed.&lt;/p&gt;

&lt;p&gt;Next steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;See more examples of using &lt;a href="https://docs.gitness.com/pipelines/samples/task" rel="noopener noreferrer"&gt;Task with Gitness&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Create &lt;a href="https://docs.gitness.com/pipelines/triggers" rel="noopener noreferrer"&gt;triggers&lt;/a&gt; to automatically run the pipeline when commits are pushed to the repository&lt;/li&gt;
&lt;li&gt;Learn how Gitness &lt;a href="https://docs.gitness.com/installation/data" rel="noopener noreferrer"&gt;manages your data&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Learn how to manage Gitness &lt;a href="https://docs.gitness.com/administration/project-management" rel="noopener noreferrer"&gt;projects and roles&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Build Arm Docker images five times faster on native hardware</title>
      <dc:creator>Jim Sheldon</dc:creator>
      <pubDate>Tue, 31 Oct 2023 19:24:44 +0000</pubDate>
      <link>https://forem.com/harness/build-arm-docker-images-five-times-faster-on-native-hardware-49e8</link>
      <guid>https://forem.com/harness/build-arm-docker-images-five-times-faster-on-native-hardware-49e8</guid>
      <description>&lt;p&gt;The ARMv8 (a.k.a. ARM64) CPU architecture, &lt;a href="https://web.archive.org/web/20190101024118/https://www.arm.com/about/newsroom/arm-discloses-technical-details-of-the-next-version-of-the-arm-architecture.php"&gt;announced&lt;/a&gt; 12 years ago, was the first &lt;a href="https://www.arm.com/"&gt;Arm&lt;/a&gt; architecture to support a 64-bit instruction set. Apple famously introduced its ARM64-based M1 chip in November of 2020. In June of this year, Apple completed its transition away from Intel-based CPUs by &lt;a href="https://finance.yahoo.com/news/apple-refreshes-the-mac-pro-with-its-new-m2-ultra-chip-173145016.html"&gt;launching&lt;/a&gt; a new Mac Pro model powered by the M2 revision of the chip. In the PC market, Arm notebooks are expected to increase to &lt;a href="https://www.counterpointresearch.com/insights/arm-based-pcs-to-nearly-double-market-share-by-2027/"&gt;27% market share by 2027&lt;/a&gt;. In the cloud computing space, all major service providers &lt;a href="https://www.arm.com/campaigns/cloud-computing"&gt;offer Arm solutions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We have entered a world where Arm can’t be ignored. If your company isn’t adapting your applications and running infrastructure on Arm, chances are your competition is.&lt;/p&gt;

&lt;h2&gt;
  
  
  Cost and Energy Savings with Arm
&lt;/h2&gt;

&lt;p&gt;The Arm architecture offers significant potential cost and energy savings. A recent study showed that moving to Arm-based cloud infrastructure can achieve up to &lt;a href="https://www.anandtech.com/show/15578/cloud-clash-amazon-graviton2-arm-against-intel-and-amd/9"&gt;40% better performance per dollar&lt;/a&gt; over comparable Intel-based infrastructure.&lt;/p&gt;

&lt;p&gt;Companies like Squeaky &lt;a href="https://squeaky.ai/blog/development/how-switching-to-aws-graviton-slashed-our-infrastructure-bill-by-35-percent"&gt;reduced their cloud spending by 35%&lt;/a&gt; by switching to Arm. When analyzing CPU, memory, and latency metrics after the migration, Squeaky reports "no performance degradation" on the new hardware.&lt;/p&gt;

&lt;p&gt;Database company Aerospike saw &lt;a href="https://pages.aerospike.com/rs/229-XUE-318/images/Aerospike-White-Paper-AWS-Graviton-Benchmark.pdf"&gt;annual costs decrease by an estimated 27%&lt;/a&gt; after switching to Graviton2 processors on AWS EC2. They also cut carbon emissions by an estimated 49% while achieving aggressive targets for transaction throughput and data access latency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker and Arm
&lt;/h2&gt;

&lt;p&gt;The &lt;a href="https://survey.stackoverflow.co/2022/#most-popular-technologies-tools-tech-prof"&gt;2022 StackOverflow Developer Survey&lt;/a&gt; found that &lt;a href="https://www.docker.com/"&gt;Docker&lt;/a&gt; is becoming a "fundamental tool for Professional Developers, increasing from 55% to 69%." According to the &lt;a href="https://www.cncf.io/reports/cncf-annual-survey-2022/"&gt;CNCF 2022 annual survey&lt;/a&gt;, 44% of respondents use containers for nearly all applications and business segments, and another 35% say they use containers for at least a few production applications.&lt;/p&gt;

&lt;p&gt;This means that &lt;strong&gt;the first challenge many companies face when adopting Arm is how to build their application containers for this different architecture&lt;/strong&gt;. While Docker supports building images for other CPU architectures under emulation, this can significantly impact performance.&lt;/p&gt;

&lt;h2&gt;
  
  
  Native Builds vs. Emulation
&lt;/h2&gt;

&lt;p&gt;To visualize the difference in performance, we built base Docker images for &lt;a href="https://github.com/docker-library/python/tree/master/3.8/alpine3.18"&gt;Python&lt;/a&gt;, &lt;a href="https://github.com/docker-library/ruby/tree/master/3.2/alpine3.18"&gt;Ruby&lt;/a&gt;, &lt;a href="https://github.com/docker-library/haproxy/tree/master/2.9/alpine"&gt;HAProxy&lt;/a&gt; and &lt;a href="https://github.com/docker-library/redis/tree/master/7.2/alpine3.18"&gt;Redis&lt;/a&gt; using both emulation and native ARM64 hardware.&lt;/p&gt;

&lt;p&gt;This graph shows build time in minutes for native Arm hardware compared to emulation &lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Tqc6CGQ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1suxxg3hwbb5uo6okws.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Tqc6CGQ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/q1suxxg3hwbb5uo6okws.png" alt="Docker image build times" width="800" height="494"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These results show &lt;strong&gt;builds completed five times faster on average with native Arm hardware&lt;/strong&gt;. This is valuable time your developers could be using for &lt;em&gt;development&lt;/em&gt;, rather than waiting for pipelines.&lt;/p&gt;

&lt;p&gt;While Arm clearly has incredible momentum, some companies in the continuous integration space have been &lt;a href="https://github.com/actions/runner-images/issues/5631"&gt;slow to provide hosted resources&lt;/a&gt;. &lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/actions/runner-images/issues/5631#issuecomment-1517045800"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--A9-wwsHG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Comment for
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#5631&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/mfittko"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--FnZ2xWgM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://avatars.githubusercontent.com/u/326798%3Fu%3D49d19b5f1c5911f5107bb03bc27e05ad03dd416c%26v%3D4" alt="mfittko avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/mfittko"&gt;mfittko&lt;/a&gt;
        &lt;/strong&gt; commented on &lt;a href="https://github.com/actions/runner-images/issues/5631#issuecomment-1517045800"&gt;&lt;time&gt;Apr 20, 2023&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;It's just way more convenient to work with arm based images and not having to deal with multi arch, if you have an ARM based mac, so big +1 here, too ;) it would just be so much more sustainable to be able to work and build for a single platform (of choice) - think of the environment! All these wasted cpu cycles!&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/actions/runner-images/issues/5631#issuecomment-1517045800"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;Here at &lt;a href="https://www.harness.io/"&gt;Harness&lt;/a&gt;, Arm infrastructure has been available in &lt;a href="https://www.harness.io/products/continuous-integration"&gt;Harness CI Cloud&lt;/a&gt; since the beginning.&lt;/p&gt;

&lt;p&gt;To sign up for Harness Cloud and get 2,000 free monthly build credits for your pipelines, see the &lt;a href="https://www.harness.io/blog/arm-harness-ci-cloud"&gt;original blog post for this article&lt;/a&gt;.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Tested with minimum 4 vCPUs and 16GB memory ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>arm</category>
      <category>docker</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>Build and test a Golang app with Gitness</title>
      <dc:creator>Jim Sheldon</dc:creator>
      <pubDate>Fri, 20 Oct 2023 19:33:22 +0000</pubDate>
      <link>https://forem.com/harness/build-and-test-a-golang-app-with-gitness-5cf6</link>
      <guid>https://forem.com/harness/build-and-test-a-golang-app-with-gitness-5cf6</guid>
      <description>&lt;p&gt;&lt;a href="https://gitness.com?utm_source=dev.to&amp;amp;utm_content=blog&amp;amp;utm_medium=blog&amp;amp;utm_term=gitness-build-and-test-golang-app"&gt;Gitness&lt;/a&gt; is an open source development platform from &lt;a href="https://www.harness.io?utm_source=dev.to&amp;amp;utm_content=blog&amp;amp;utm_medium=blog&amp;amp;utm_term=gitness-build-and-test-golang-app"&gt;Harness&lt;/a&gt; that hosts your source code repositories and runs your development life cycle pipelines.&lt;/p&gt;

&lt;p&gt;This tutorial covers how to build and test a Golang application with Gitness.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;You can &lt;a href="https://docs.gitness.com/#installation"&gt;install&lt;/a&gt; Gitness on any computer running &lt;a href="https://www.docker.com"&gt;Docker&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Run this command to start Gitness:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d \
  -p 3000:3000 \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v /tmp/gitness:/data \
  --name gitness \
  --restart always \
  harness/gitness
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Visit &lt;a href="http://localhost:3000"&gt;http://localhost:3000&lt;/a&gt; in your browser and you will be greeted with the Gitness login page.&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Sign Up&lt;/strong&gt; link.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--z5_RpsGy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5tzsdclld76ymj1nu764.png" alt="Gitness login page" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Enter your desired user ID, email address and password, then click &lt;strong&gt;Sign Up&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NpnFHBDD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ree9uxd0ztlk4sl1bhsw.png" alt="Gitness sign up page" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ℹ️ Note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;strong&gt;By default, the first user to sign up will be granted administrator access.&lt;/strong&gt; To learn more about how to configure Gitness, refer to the &lt;a href="https://docs.gitness.com/administration/configuration"&gt;configuration&lt;/a&gt; documentation.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Create Project
&lt;/h2&gt;

&lt;p&gt;Create a &lt;a href="https://docs.gitness.com/administration/project-management"&gt;project&lt;/a&gt; which will contain the Git repository.&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;New Project&lt;/strong&gt; button.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lIVpiXEX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/14tavsu9odimyy49ij05.png" alt="Gitness new project" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Give the project a name and optional description, then click the &lt;strong&gt;Create Project&lt;/strong&gt; button.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---mr7Sx0n--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lgqy9u3cz4l094pvrp5y.png" alt="Gitness create project" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Import Repository
&lt;/h2&gt;

&lt;p&gt;Expand the &lt;strong&gt;New Repository&lt;/strong&gt; drop-down menu and select &lt;strong&gt;Import Repository&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gkOETx-q--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qs4acmsbgc6edzx67xsz.png" alt="Gitness new repository" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/jimsheldon/go-outyet"&gt;jimsheldon/go-outyet&lt;/a&gt;, is a simple Golang application that reports whether a version of Golang has been released yet.&lt;/p&gt;

&lt;p&gt;Enter &lt;code&gt;https://github.com/jimsheldon/go-outyet&lt;/code&gt; in the &lt;strong&gt;Repository URL&lt;/strong&gt; field, then click &lt;strong&gt;Import Repository&lt;/strong&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--y6kEIMmF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rpz8ox5xqkstakuft1h3.png" alt="Gitness import repository" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Create Pipeline
&lt;/h2&gt;

&lt;p&gt;Click on the imported repository, then open the &lt;strong&gt;Pipelines&lt;/strong&gt; view from the menu on the left.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cnlpjvBI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bhnowaadm6tphyz1kqn7.png" alt="Gitness open pipelines" width="800" height="456"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Click the &lt;strong&gt;New Pipeline&lt;/strong&gt; button.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DI5AoG9i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/euni8g3z3ljifmfi8mis.png" alt="Gitness new pipeline" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Give the pipeline a name, the YAML path will be generated automatically (it can be changed if desired), then click the &lt;strong&gt;Create&lt;/strong&gt; button.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XI03s1Z5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cljz75dpba9eyyabwege.png" alt="Gitness create new pipeline" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Gitness can automatically generate a pipeline based on the code in the repository.&lt;/p&gt;

&lt;p&gt;Click the &lt;strong&gt;Generate&lt;/strong&gt; button above the pipeline editor.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PRaeKw7N--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/algy949s174ybkwa4qpl.png" alt="Gitness generate pipeline" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Examine the pipeline that was generated, you will see &lt;a href="https://docs.gitness.com/pipelines/steps/run"&gt;run steps&lt;/a&gt; that build and test the app, and a Docker build &lt;a href="https://docs.gitness.com/pipelines/steps/plugin"&gt;plugin step&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The build step compiles the binary, and the test step runs unit tests from the &lt;code&gt;main_test.go&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;The Docker build step builds a Docker image from the &lt;code&gt;Dockerfile&lt;/code&gt; file, but does not publish the image (the &lt;code&gt;dry_run: true&lt;/code&gt; setting prevents publishing).&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Save and Run&lt;/strong&gt; button.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LZyVOgV2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tjo47sgyczymidxjmdgf.png" alt="Gitness save and run pipeline" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;ℹ️ Note&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Gitness will commit the pipeline file to your repository and create a default pipeline &lt;a href="https://docs.gitness.com/pipelines/triggers"&gt;trigger&lt;/a&gt; for pull request events, which can be customized if desired.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Run Pipeline
&lt;/h2&gt;

&lt;p&gt;Click the &lt;strong&gt;Run pipeline&lt;/strong&gt; button in the window that appears.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1RTIxNUB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c5k7mvfofyssinjad022.png" alt="Gitness run pipeline" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;You will see the pipeline execution view.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--mIL7qwD3--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yshgvevwiudvj184ir1t.png" alt="Gitness pipeline execution" width="800" height="450"&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Congratulations, you just imported a repository and ran a pipeline!&lt;/strong&gt; 🎉&lt;/p&gt;

&lt;p&gt;In this tutorial, we have just scratched the surface of what is possible with Gitness 😄&lt;/p&gt;

&lt;h2&gt;
  
  
  Next Steps
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Create &lt;a href="https://docs.gitness.com/pipelines/triggers"&gt;triggers&lt;/a&gt; to automatically run the pipeline on certain events&lt;/li&gt;
&lt;li&gt;Define &lt;a href="https://docs.gitness.com/pipelines/conditions"&gt;conditions&lt;/a&gt; to only run specific steps for certain events&lt;/li&gt;
&lt;li&gt;Set values dynamically at runtime with &lt;a href="https://docs.gitness.com/pipelines/expressions"&gt;expressions&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Review &lt;a href="https://docs.gitness.com/category/samples"&gt;samples&lt;/a&gt; for other languages and write some pipelines of your own!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gitness.com?utm_source=dev.to&amp;amp;utm_content=blog&amp;amp;utm_medium=blog&amp;amp;utm_term=gitness-build-and-test-golang-app"&gt;Gitness website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.gitness.com"&gt;Gitness documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/harness/gitness"&gt;Gitness GitHub repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.gitness.com/support#slack"&gt;Harness Community Slack&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cover image by &lt;a href="https://unsplash.com/@josholalde?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash"&gt;Josh Olalde&lt;/a&gt; on &lt;a href="https://unsplash.com/photos/X1P1_EDNnok?utm_content=creditCopyText&amp;amp;utm_medium=referral&amp;amp;utm_source=unsplash"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>go</category>
      <category>tutorial</category>
      <category>gitness</category>
    </item>
    <item>
      <title>Managing the ‘Git’ in ‘GitOps’: 4 Ways to Structure Code in Your GitOps Repos</title>
      <dc:creator>Jim Sheldon</dc:creator>
      <pubDate>Wed, 15 Jun 2022 14:57:55 +0000</pubDate>
      <link>https://forem.com/harness/managing-the-git-in-gitops-4-ways-to-structure-code-in-your-gitops-repos-dbp</link>
      <guid>https://forem.com/harness/managing-the-git-in-gitops-4-ways-to-structure-code-in-your-gitops-repos-dbp</guid>
      <description>&lt;p&gt;Implementing &lt;a href="https://harness.io/blog/devops/gitops/" rel="noopener noreferrer"&gt;GitOps&lt;/a&gt; practices will take your software delivery pipelines to the next level. &lt;a href="https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/" rel="noopener noreferrer"&gt;Declarative&lt;/a&gt;, &lt;a href="https://www.cncf.io/online-programs/immutable-infrastructure-in-the-age-of-kubernetes/" rel="noopener noreferrer"&gt;immutable&lt;/a&gt;, and continuously &lt;a href="https://github.com/open-gitops/documents/blob/v1.0.0/GLOSSARY.md#reconciliation" rel="noopener noreferrer"&gt;reconciled&lt;/a&gt; infrastructure brings many &lt;a href="https://harness.io/blog/devops/gitops-benefits/" rel="noopener noreferrer"&gt;benefits&lt;/a&gt; when managed through &lt;a href="https://harness.io/blog/devops/gitops-best-practices/" rel="noopener noreferrer"&gt;GitOps best practices&lt;/a&gt;. Over the years, I have helped many development teams build and improve their GitOps workflows. In this blog, I will share four approaches to managing code used in those pipelines.&lt;/p&gt;

&lt;p&gt;The “Ops” half of “GitOps” refers to configuration code, or &lt;a href="https://harness.io/blog/devops/infrastructure-as-code/" rel="noopener noreferrer"&gt;Infrastructure as Code&lt;/a&gt; (IaC). Software depends on the resources managed by this code to function. Managing this configuration in &lt;a href="https://git-scm.com/" rel="noopener noreferrer"&gt;Git&lt;/a&gt; repositories offers many benefits. Often the structure of this code is an afterthought, which leads to significant refactoring in the future.&lt;/p&gt;

&lt;h2&gt;
  
  
  Application and Infrastructure Code in One Repository
&lt;/h2&gt;

&lt;p&gt;The first example manages application code and infrastructure code in the same repository. A single &lt;a href="https://medium.com/@peter.hozak/long-lived-git-branches-survival-guide-f3b1028d21d" rel="noopener noreferrer"&gt;long-lived&lt;/a&gt; branch exists (&lt;a href="https://www.theserverside.com/feature/Why-GitHub-renamed-its-master-branch-to-main" rel="noopener noreferrer"&gt;main&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Below is a Node.js project with application code in the root, and YAML files in the kubernetes directory. Changes to development.yaml apply to the development environment, changes to production.yaml apply to the production environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.harness.io%2Fwp-content%2Fuploads%2F2022%2F06%2FScreen-Shot-2022-06-10-at-11.23.21-AM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.harness.io%2Fwp-content%2Fuploads%2F2022%2F06%2FScreen-Shot-2022-06-10-at-11.23.21-AM.png" alt="Node.js project with application code in the root"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Infrastructure code and application code in the same repository keeps everything versioned together. There is no need to connect the dots between multiple repositories to reproduce the state of the application and configuration at a certain point in time.&lt;/li&gt;
&lt;li&gt;One repository means less &lt;a href="https://pacohq.com/blog/guide/the-high-price-of-context-switching-for-developers/" rel="noopener noreferrer"&gt;context switching&lt;/a&gt; for developers. Developers don’t need to change repositories when making changes to infrastructure code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No &lt;a href="https://harness.io/blog/devops/pipeline-security-devsecops-catalyst/" rel="noopener noreferrer"&gt;privilege separation&lt;/a&gt;. Developers with access to the repository will be able to change both application and infrastructure code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some organizations require separation between application and infrastructure code. The examples below all manage application and infrastructure code in their own repositories. This improves privilege separation as each Git repository can set its own user privileges.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separate Infrastructure Repository, Multiple Branches
&lt;/h2&gt;

&lt;p&gt;You may be familiar with Git branching workflows such as &lt;a href="https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow" rel="noopener noreferrer"&gt;Gitflow&lt;/a&gt;. Gitflow has fallen &lt;a href="https://georgestocker.com/2020/03/04/please-stop-recommending-git-flow/" rel="noopener noreferrer"&gt;out of favor&lt;/a&gt; recently as &lt;a href="https://www.atlassian.com/continuous-delivery/continuous-integration/trunk-based-development" rel="noopener noreferrer"&gt;trunk-based&lt;/a&gt; development has gained popularity. There are good reasons to avoid more than one long-lived branch in your Git repository. Yet, multiple long-lived branches are still worth considering in certain cases.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Below is a &lt;a href="https://helm.sh/" rel="noopener noreferrer"&gt;Helm&lt;/a&gt; chart repository with two long-lived branches, development, and production. Changes always originate in the development branch. Promotion to production requires &lt;a href="https://git-scm.com/docs/git-merge" rel="noopener noreferrer"&gt;merging&lt;/a&gt; development into production. The development environment uses the development-values.yaml &lt;a href="https://helm.sh/docs/chart_template_guide/values_files/" rel="noopener noreferrer"&gt;values&lt;/a&gt; file in the development branch. The production environment uses the production-values.yaml values file in the production branch.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.harness.io%2Fwp-content%2Fuploads%2F2022%2F06%2Fimage.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.harness.io%2Fwp-content%2Fuploads%2F2022%2F06%2Fimage.png" alt="Helm chart repo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Low risk of &lt;a href="https://harness.io/blog/devops/infrastructure-as-code/#consistency" rel="noopener noreferrer"&gt;configuration drift&lt;/a&gt; when promoting changes between environments. Merging branches ensures that no changes will be missed.&lt;/li&gt;
&lt;li&gt;Improved privilege separation between development and production changes. For example, GitHub supports branch &lt;a href="https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule" rel="noopener noreferrer"&gt;protection rules&lt;/a&gt;. The owner of the repository can control which users can commit to a branch.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;This is a “one lane road” for your infrastructure code. Changes in the development branch can block production changes (without &lt;a href="https://git-scm.com/docs/git-cherry-pick" rel="noopener noreferrer"&gt;cherry-picking&lt;/a&gt; desired changes).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Separate Infrastructure Repository, Directory-Based
&lt;/h2&gt;

&lt;p&gt;Now, let’s consider a repository where a single long-lived branch exists (main). Each environment has its own directory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Below is a &lt;a href="https://harness.io/blog/devops/terraform-201-tutorial/" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt; repository with separate development and production directories. Changes to development use the development.tfvars &lt;a href="https://www.terraform.io/language/values/variables#variable-definitions-tfvars-files" rel="noopener noreferrer"&gt;tfvars&lt;/a&gt; file in the development directory. Changes to production use the production.tfvars tfvars file in the production directory.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.harness.io%2Fwp-content%2Fuploads%2F2022%2F06%2Fimage-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.harness.io%2Fwp-content%2Fuploads%2F2022%2F06%2Fimage-1.png" alt="Terraform repository"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Changes made in the development directory do not affect the production directory.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Increased risk of configuration drift between environments. There is a high burden on the developer to understand differences between directories.&lt;/li&gt;
&lt;li&gt;No privilege separation. Users can make changes to both development and production environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Multiple Infrastructure Repositories, One per Environment
&lt;/h2&gt;

&lt;p&gt;Let’s consider an approach where each &lt;a href="https://harness.io/blog/continuous-delivery/deployment-environments/" rel="noopener noreferrer"&gt;environment&lt;/a&gt; has its own dedicated repository. Each repository has a single long-lived branch (main).&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;Here is an example Terraform project, where development and production are separate repositories. Changes to development use the development.tfvars tfvars file in the development repository. Changes to production use the production.tfvars tfvars file in the production repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.harness.io%2Fwp-content%2Fuploads%2F2022%2F06%2Fimage-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fblog.harness.io%2Fwp-content%2Fuploads%2F2022%2F06%2Fimage-2.png" alt="Terraform project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Highest level of privilege separation. Any feature that your Git host provides around user/group access at the repository level will be available to you. Only users that need to make changes to production will be able to commit changes to the production repository.&lt;/li&gt;
&lt;li&gt;Easier to bring up new environments, or migrate existing environments. When bringing up a new environment, create a new repository. There is no need to integrate with an existing repository to bring up a new environment. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Drawbacks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Higher risk for configuration drift between environments. There is a high burden on the developer to understand differences between repositories.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In my experience, one repository per environment is the most &lt;a href="https://en.wikipedia.org/wiki/Future-proof" rel="noopener noreferrer"&gt;future-proof&lt;/a&gt; method for managing your GitOps code. The privilege and environment separation benefits outweigh the potential drawbacks. If you decide the separation is not required in the future, you can collapse multiple repositories into one. The good news is that whatever method you choose, &lt;strong&gt;Harness’ suite of products supports them all.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Whether you are building, testing, and publishing artifacts with &lt;a href="https://harness.io/products/continuous-integration" rel="noopener noreferrer"&gt;Harness CI&lt;/a&gt;, deploying with &lt;a href="https://harness.io/products/continuous-delivery" rel="noopener noreferrer"&gt;Harness CD&lt;/a&gt;, or taking your pipelines to the next level with &lt;a href="https://harness.io/gitops-beta/" rel="noopener noreferrer"&gt;Harness GitOps&lt;/a&gt; (currently in beta), we’ve got you covered! Also, every Harness pipeline can take advantage of advanced features around &lt;a href="https://harness.io/blog/continuous-delivery/ci-cd-pipeline-governance/" rel="noopener noreferrer"&gt;governance&lt;/a&gt;, &lt;a href="https://harness.io/blog/product-updates/introducing-harness-chaos-engineering/" rel="noopener noreferrer"&gt;chaos engineering&lt;/a&gt;, and more.&lt;/p&gt;

&lt;p&gt;Come see how Harness can help accelerate your GitOps journey. Sign up for a &lt;a href="https://harness.io/pricing" rel="noopener noreferrer"&gt;14-day free trial&lt;/a&gt; and follow our &lt;a href="https://ngdocs.harness.io/article/knunou9j30-kubernetes-cd-quickstart" rel="noopener noreferrer"&gt;Kubernetes CD Quickstart&lt;/a&gt; guide to deploy an application to your cluster. If you are looking for a guided tour, &lt;a href="https://harness.io/demo/" rel="noopener noreferrer"&gt;book a demo&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We would love to answer any questions you might have in our &lt;a href="https://community.harness.io/" rel="noopener noreferrer"&gt;forum&lt;/a&gt;, &lt;a href="https://harnesscommunity.slack.com/" rel="noopener noreferrer"&gt;community Slack&lt;/a&gt;, or at an upcoming &lt;a href="https://www.meetup.com/harness/" rel="noopener noreferrer"&gt;Harness &amp;amp; Drone User Group&lt;/a&gt; virtual meetup.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://dev.to/davenielsen/managing-the-git-in-gitops-4-ways-to-structure-code-in-your-gitops-repos-3ff4-temp-slug-4938802"&gt;Managing the ‘Git’ in ‘GitOps’: 4 Ways to Structure Code in Your GitOps Repos&lt;/a&gt; appeared first on &lt;a href="https://blog.harness.io" rel="noopener noreferrer"&gt;Harness&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>gitops</category>
      <category>devops</category>
      <category>git</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Run your own Drone CI</title>
      <dc:creator>Jim Sheldon</dc:creator>
      <pubDate>Sat, 02 Apr 2022 15:22:05 +0000</pubDate>
      <link>https://forem.com/jimsheldon/run-your-own-drone-ci-4335</link>
      <guid>https://forem.com/jimsheldon/run-your-own-drone-ci-4335</guid>
      <description>&lt;p&gt;Started in 2012, &lt;a href="https://www.drone.io" rel="noopener noreferrer"&gt;Drone CI&lt;/a&gt; is a container-native, event-based, multi-architecture, multi-OS platform for busy teams looking to tighten their software development lifecycles.&lt;/p&gt;

&lt;p&gt;Since its &lt;a href="https://www.prnewswire.com/news-releases/harness-acquires-continuous-integration-pioneer-droneio-and-commits-to-open-source-301106473.html" rel="noopener noreferrer"&gt;acquisition&lt;/a&gt; by &lt;a href="http://harness.io" rel="noopener noreferrer"&gt;Harness&lt;/a&gt; in August of 2020, Drone CI has made significant improvements in usability and features. Let's see how, in just a few minutes, you can start experimenting with running Drone CI pipelines on any computer running &lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Be comfortable running commands in the terminal&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; account&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://ngrok.com" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt; account&lt;/li&gt;
&lt;li&gt;Computer that can run &lt;a href="https://en.wikipedia.org/wiki/X86-64" rel="noopener noreferrer"&gt;amd64&lt;/a&gt; or &lt;a href="https://en.wikipedia.org/wiki/AArch64" rel="noopener noreferrer"&gt;arm64&lt;/a&gt; &lt;a href="https://www.docker.com" rel="noopener noreferrer"&gt;Docker&lt;/a&gt; containers (this includes the new &lt;a href="https://en.wikipedia.org/wiki/Apple_M1" rel="noopener noreferrer"&gt;M1&lt;/a&gt;-based Macs)

&lt;ul&gt;
&lt;li&gt;In your terminal, verify you have &lt;code&gt;docker&lt;/code&gt; and &lt;code&gt;docker-compose&lt;/code&gt; commands available&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;Drone CI supports multiple SCM solutions, such as &lt;a href="https://github.com" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;, &lt;a href="https://bitbucket.org" rel="noopener noreferrer"&gt;Bitbucket&lt;/a&gt;, &lt;a href="https://gitea.io" rel="noopener noreferrer"&gt;Gitea&lt;/a&gt;, &lt;a href="https://gitlab.com" rel="noopener noreferrer"&gt;GitLab&lt;/a&gt; and &lt;a href="https://docs.drone.io/server/overview/" rel="noopener noreferrer"&gt;more&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This guide will focus on GitHub. Because we have chosen GitHub, we need to allow GitHub to send &lt;a href="https://docs.github.com/en/developers/webhooks-and-events/webhooks/about-webhooks" rel="noopener noreferrer"&gt;webhooks&lt;/a&gt; to the Drone CI process on our computer. We will use &lt;a href="https://ngrok.com" rel="noopener noreferrer"&gt;ngrok&lt;/a&gt; to create a &lt;a href="https://en.wikipedia.org/wiki/Tunneling_protocol" rel="noopener noreferrer"&gt;tunnel&lt;/a&gt; to the internet so our Drone CI process can receive webhook traffic from GitHub.&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the &lt;code&gt;ngrok&lt;/code&gt; tunnel
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Login to &lt;a href="https://ngrok.com" rel="noopener noreferrer"&gt;https://ngrok.com&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Open &lt;a href="https://dashboard.ngrok.com/get-started/setup" rel="noopener noreferrer"&gt;https://dashboard.ngrok.com/get-started/setup&lt;/a&gt;, follow the steps to install the &lt;code&gt;ngrok&lt;/code&gt; binary and connect to your account&lt;/li&gt;
&lt;li&gt;Create the tunnel by running &lt;code&gt;ngrok http 8080&lt;/code&gt; in your terminal, &lt;strong&gt;do not stop the process&lt;/strong&gt; until you are finished with this guide&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ngrok&lt;/code&gt; will create your tunnel and provide you with a URL such as &lt;code&gt;https://34f3-146-168-58-81.ngrok.io&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your terminal should display session information similar to this screenshot:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnujkee9w7v4zh83z0k9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwnujkee9w7v4zh83z0k9.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Create the GitHub OAuth Application
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Follow &lt;a href="https://docs.drone.io/server/provider/github/#create-an-oauth-application" rel="noopener noreferrer"&gt;Create an OAuth Application&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;For the "Homepage URL", enter the &lt;code&gt;ngrok&lt;/code&gt; URL from the previous step&lt;/li&gt;
&lt;li&gt;For the "Authorization callback URL", enter the same &lt;code&gt;ngrok&lt;/code&gt; URL, with &lt;code&gt;/login&lt;/code&gt; appended&lt;/li&gt;
&lt;li&gt;You will be given the "Client ID" and a "Client secret", make a note of each (the secret is only displayed once, if you misplace it, you will need to generate a new client secret)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Your OAuth application should look similar to this screenshot (for extra authenticity, upload the official Drone CI &lt;a href="https://raw.githubusercontent.com/drone/brand/master/logos/png/dark/drone-logo-png-dark-256.png" rel="noopener noreferrer"&gt;logo&lt;/a&gt;):&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhuir37mtc7iobjod5hmn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhuir37mtc7iobjod5hmn.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;ngrok&lt;/code&gt; URLs are temporary with the free plan. If you terminate your &lt;code&gt;ngrok&lt;/code&gt; session and create a new one, your URL will change and you will need to update the "Homepage URL" and "Authorization callback URL" in your OAuth Application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Start the Drone and Drone Runner processes
&lt;/h2&gt;

&lt;p&gt;The Drone &lt;a href="https://docs.drone.io/server/overview/" rel="noopener noreferrer"&gt;server&lt;/a&gt; process requires at least one &lt;a href="https://docs.drone.io/runner/overview/" rel="noopener noreferrer"&gt;runner&lt;/a&gt; process where pipelines will execute. Drone CI supports multiple runners, but the &lt;a href="https://docs.drone.io/runner/docker/overview/" rel="noopener noreferrer"&gt;Docker runner&lt;/a&gt; is the most popular.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://docs.github.com/en/get-started/quickstart/fork-a-repo" rel="noopener noreferrer"&gt;Fork&lt;/a&gt; the repository &lt;a href="https://github.com/jimsheldon/drone-quickstart" rel="noopener noreferrer"&gt;https://github.com/jimsheldon/drone-quickstart&lt;/a&gt; and &lt;a href="https://docs.github.com/en/repositories/creating-and-managing-repositories/cloning-a-repository" rel="noopener noreferrer"&gt;clone&lt;/a&gt; the forked repository to your computer&lt;/li&gt;
&lt;li&gt;Edit the file &lt;code&gt;run.sh&lt;/code&gt;

&lt;ul&gt;
&lt;li&gt;Set &lt;code&gt;DRONE_GITHUB_CLIENT_ID&lt;/code&gt; and &lt;code&gt;DRONE_GITHUB_CLIENT_SECRET&lt;/code&gt; using the "Client ID" and "Client secret" from the previous section&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;DRONE_GITHUB_ADMIN&lt;/code&gt; to your GitHub username&lt;/li&gt;
&lt;li&gt;Set &lt;code&gt;DRONE_SERVER_HOST&lt;/code&gt; to your &lt;code&gt;ngrok&lt;/code&gt; URL, without the &lt;code&gt;https://&lt;/code&gt; (if your &lt;code&gt;ngrok&lt;/code&gt; URL is &lt;code&gt;https://34f3-146-168-58-81.ngrok.io&lt;/code&gt;, set &lt;code&gt;DRONE_SERVER_HOST&lt;/code&gt; to &lt;code&gt;34f3-146-168-58-81.ngrok.io&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Save your changes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Open a new terminal session and change to the directory where you checked out the repository

&lt;ul&gt;
&lt;li&gt;Execute &lt;code&gt;run.sh&lt;/code&gt; by typing &lt;code&gt;./run.sh&lt;/code&gt; and hitting enter&lt;/li&gt;
&lt;li&gt;Open your &lt;code&gt;ngrok&lt;/code&gt; URL in a browser, you should be greeted with "&lt;strong&gt;Welcome to Drone&lt;/strong&gt;"! 🎉
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F55ps00ib0bd09tej7904.png" alt="Image description"&gt;
&lt;/li&gt;
&lt;li&gt;Click "Continue" and you will be asked to authorize your OAuth application
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs8w8udbu1bg6tin6mxxt.png" alt="Image description"&gt;
&lt;/li&gt;
&lt;li&gt;Next you will see the "Complete your Drone Registration" screen
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs7snpuqe15njmni64qdp.png" alt="Image description"&gt;
&lt;/li&gt;
&lt;li&gt;Click "Submit" and you will see the Drone CI interface, filter by "quickstart" to see your forked repository
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fck7olm1u2j5nimxdtghv.png" alt="Image description"&gt;
&lt;/li&gt;
&lt;li&gt;Click on the repository, then click "Activate Repository"
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1mszaov5tf1xothsqlik.png" alt="Image description"&gt;
&lt;/li&gt;
&lt;li&gt;Your repository should now be activated
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F78aith8gt0sqizcudp4k.png" alt="Image description"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Run your first pipeline
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Edit the &lt;code&gt;.drone.yml&lt;/code&gt; file in the root off your repository. Change the &lt;code&gt;echo hello world&lt;/code&gt; message to something of your choice. If your CPU is amd64 (Intel, AMD) you should remove the &lt;code&gt;platform&lt;/code&gt; section, which is currently specific to arm64 (Apple M1, Raspberry Pi)&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/git-guides/git-push" rel="noopener noreferrer"&gt;Push&lt;/a&gt; your change to a &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-branches" rel="noopener noreferrer"&gt;branch&lt;/a&gt; and open a &lt;a href="https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests" rel="noopener noreferrer"&gt;pull request&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Your pull request will trigger a check in Drone CI called "continuous-integration/drone/pr"
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw3y44tsvhr92uje3qois.png" alt="Image description"&gt;
&lt;/li&gt;
&lt;li&gt;Click the "Details" link, you will see your pipeline execution in Drone CI! Click the "hello" step to see your message printed
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwcg424ks499plizhgw5.png" alt="Image description"&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You now have your very own &lt;a href="https://www.drone.io/enterprise/" rel="noopener noreferrer"&gt;Drone CI Enterprise&lt;/a&gt; installation! Drone CI Enterprise includes a free trial of up to 5,000 builds. To learn more about licensing options, see the Drone CI &lt;a href="https://docs.drone.io/enterprise/" rel="noopener noreferrer"&gt;Enterprise FAQ&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The official Drone CI documentation provides example pipelines in &lt;a href="https://docs.drone.io/pipeline/docker/examples/" rel="noopener noreferrer"&gt;virtually every language&lt;/a&gt;. Try it out on one of your own projects!&lt;/p&gt;

&lt;h2&gt;
  
  
  Teardown
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In the directory where you ran &lt;code&gt;run.sh&lt;/code&gt; run &lt;code&gt;docker-compose down&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In the terminal where your &lt;code&gt;ngrok&lt;/code&gt; session is running, type &lt;code&gt;CTRL-C&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;ngrok&lt;/code&gt; URLs are temporary with the free plan. If you terminate your &lt;code&gt;ngrok&lt;/code&gt; session, the next time you run &lt;code&gt;ngrok http 8080&lt;/code&gt; your URL will change, and you will need to update the "Homepage URL" and "Authorization callback URL" in your GitHub OAuth Application, as well as the &lt;code&gt;DRONE_SERVER_HOST&lt;/code&gt; value in &lt;code&gt;run.sh&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Hopefully this gives you a quick way to get started running Drone CI pipelines from your GitHub repositories.&lt;/p&gt;

&lt;p&gt;If you would like to learn more and participate in the Drone CI and Harness communities, here are some helpful links:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Official Drone CI documentation: &lt;a href="https://docs.drone.io" rel="noopener noreferrer"&gt;https://docs.drone.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Harness Slack community: &lt;a href="https://harnesscommunity.slack.com" rel="noopener noreferrer"&gt;https://harnesscommunity.slack.com&lt;/a&gt; (&lt;a href="https://harnesscommunity.slack.com/archives/C028FPGCPF0" rel="noopener noreferrer"&gt;#drone&lt;/a&gt; channel)&lt;/li&gt;
&lt;li&gt;Harness community forum: &lt;a href="https://community.harness.io" rel="noopener noreferrer"&gt;https://community.harness.io&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Harness &amp;amp; Drone User Group: &lt;a href="https://www.meetup.com/harness/" rel="noopener noreferrer"&gt;https://www.meetup.com/harness/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Drone CI official Twitter account: &lt;a href="https://twitter.com/droneio" rel="noopener noreferrer"&gt;https://twitter.com/droneio&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>droneci</category>
      <category>cicd</category>
      <category>devops</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
