<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>git on Andrew Beaton</title>
    <link>https://andrewbeaton.net/tags/git/</link>
    <description>Recent content in git on Andrew Beaton</description>
    <image>
      <title>Andrew Beaton</title>
      <url>https://andrewbeaton.net/me.jpeg</url>
      <link>https://andrewbeaton.net/me.jpeg</link>
    </image>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Wed, 31 May 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://andrewbeaton.net/tags/git/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Deploying to Cloudflare Pages with Drone</title>
      <link>https://andrewbeaton.net/posts/2023/05/drone-io-cloudflare-pages-deploy/</link>
      <pubDate>Wed, 31 May 2023 00:00:00 +0000</pubDate>
      
      <guid>https://andrewbeaton.net/posts/2023/05/drone-io-cloudflare-pages-deploy/</guid>
      <description>Deploying to Cloudflare Pages with Drone</description>
      <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>Due to some unexpected downtime with my current web host, and a bit of spare time on my hands, I thought I would give a go at configuring Drone to deploy to Cloudflare Pages.</p>
<p>A very basic description of Cloudflare Pages, is that it&rsquo;s a platform that makes it easy to create and host websites whilst Cloudflare takes care of the more technical side of website hosting. For a more technical overview, take a look at the official documentation.</p>
<p>For my use case, as I use Hugo to generate all my static website files, I can just use Cloudflare Pages to host the content. With my domain name already proxying through Cloudflare, everything is now all handled in one place, and so far, it all just works.</p>
<p>So let&rsquo;s cover off what&rsquo;s needed to get Drone to deploy your Hugo (or static files) to Cloudflare Pages.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before getting started, make sure you have the following prerequisites in place:</p>
<ul>
<li><em><strong>A working Hugo website:</strong></em>
<ul>
<li>Set up a Hugo website.</li>
</ul>
</li>
<li><em><strong>A Git repository:</strong></em>
<ul>
<li>Host your Hugo website&rsquo;s code in a Gitea / Git repository.</li>
</ul>
</li>
<li><em><strong>A working Drone instance:</strong></em>
<ul>
<li>Your Drone instance should be working correctly with your Gitea repository.</li>
</ul>
</li>
<li><em><strong>A Cloudflare account:</strong></em>
<ul>
<li>Your Cloudflare account is running, and you have configured both a new Cloudflare Page and have a Cloudflare Workers API set up.</li>
</ul>
</li>
</ul>
<h2 id="a-drone-build-step-for-cloudflare-pages">A Drone Build Step for Cloudflare Pages</h2>
<p>This guide follows on from my previous post where I walk through setting up a full drone pipeline with Test, Staging and Production builds and deployments. To catch up have a look at <a href="/posts/2023/05/complete-drone-pipeline/">Creating a Full Drone Pipeline with Gitea and Drone</a></p>
<p>The following is a step that will build static content located in /drone/src/<!-- raw HTML omitted -->/. Deploy to a Cloudflare Page defined by <!-- raw HTML omitted -->, and a <a href="https://docs.drone.io/secret/repository/">Drone secret</a> called &lt;CLOUDFLARE_API_TOKEN&gt; containing a <a href="https://developers.cloudflare.com/workers/wrangler/ci-cd/#create-a-cloudflare-api-token">Cloudflare API token</a>.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-YAML" data-lang="YAML"><span style="display:flex;"><span>- <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Build Node.js</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">node:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>: 
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">npm install npm@latest -g </span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">mkdir -p dist</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">cp -R /drone/src/&lt;your static files location&gt;/* dist/ </span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Deploy to Cloudflare Pages</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">node:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">CLOUDFLARE_API_TOKEN</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">from_secret</span>: <span style="color:#ae81ff">CLOUDFLARE_API_TOKEN</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>: 
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">npm install wrangler --save-dev  </span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">cd /drone/src/dist/</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">npx wrangler pages deploy /drone/src/dist --project-name &#34;&lt;project&gt;&#34; --env production --branch main --commit-dirty=true</span>
</span></span></code></pre></div><p>There are a number of Docker images out there using Wrangler to deploy to Cloudflare. Unfortunately they all seem to use the previous version of the Cloudflare API which will deprecated shortly. So I went down the route of building Wrangler and NodeJS directly.</p>
<p>Do get in touch if you find a more recent Docker image for me to try.</p>
<h2 id="a-drone-pipeline-for-cloudflare-pages">A Drone Pipeline for Cloudflare Pages</h2>
<p>This is a direct copy of my current production build pipeline. This has added debugging information that I find useful whilst making changes.</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-YAML" data-lang="YAML"><span style="display:flex;"><span>---
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">pipeline</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">type</span>: <span style="color:#ae81ff">docker</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">name</span>: <span style="color:#e6db74">&#34;Production Environment&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">trigger</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">branch</span>: 
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">main </span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">event</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">include</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">push</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">steps</span>:   
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Clone Git Submodules</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">alpine/git </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">git submodule init</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">git submodule update --recursive --remote</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Build with Hugo</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">binaryronin/drone-hugo:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">pull</span>: <span style="color:#ae81ff">always </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">echo &#34;Checking Hugo version.&#34;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">hugo version</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">cd /drone/src/hugo/</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">hugo --environment production --verbose --debug </span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">ls -al /drone/src/hugo/public</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Build Node.js</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">node:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">ls -la /drone/src/</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">npm install npm@latest -g</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">pwd</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">mkdir -p dist</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">cp -R /drone/src/hugo/public/* dist/</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">ls -la dist/</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Deploy to Cloudflare Pages</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">node:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">CLOUDFLARE_API_TOKEN</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">from_secret</span>: <span style="color:#ae81ff">CLOUDFLARE_API_TOKEN</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">ls -la /drone/src/</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">npm install wrangler --save-dev </span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">npx wrangler --version</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">cd /drone/src/dist/</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">npx wrangler pages deploy /drone/src/dist --project-name &#34;&lt;project-name&gt;&#34; --env production --branch main --commit-message &#34;Drone Production Build&#34; --commit-dirty=true</span>
</span></span></code></pre></div><h2 id="summary">Summary</h2>
<p>Once deployed, a new Deployment will be available for you in your Cloudflare Pages area that can be accessed either by the temporary <a href="https://developers.cloudflare.com/pages/platform/preview-deployments/">preview deployment</a> domain or your <a href="https://developers.cloudflare.com/pages/platform/preview-deployments/#preview-aliases">preview alias</a> project domain.</p>
<p>Once happy you can now set up a <a href="https://developers.cloudflare.com/pages/platform/custom-domains/">custom domain</a> to point to the new Page.</p>
<p>Although a few extra steps than an existing Docker Cloudflare setup, this method does allow you to clearly see what&rsquo;s going on and debug any issues should they happen.</p>
<p>If you want to look further in to any of the above tools, do take a look at my previous posts and read the official documentation from the following sites:</p>
<p><a href="https://developers.cloudflare.com/workers/">Cloudflare Workers</a>
<a href="https://gitea.io/en-us/">Gitea</a>
<a href="https://www.drone.io/">Drone</a>
<a href="https://gohugo.io/">Hugo</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Creating a Full Drone Pipeline with Gitea and Drone</title>
      <link>https://andrewbeaton.net/posts/2023/05/complete-drone-pipeline/</link>
      <pubDate>Mon, 29 May 2023 00:00:00 +0000</pubDate>
      
      <guid>https://andrewbeaton.net/posts/2023/05/complete-drone-pipeline/</guid>
      <description>Creating a Full Drone Pipeline with Gitea and Drone</description>
      <content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>In my previous posts, I&rsquo;ve covered how to set up Drone, Gitea and deploy a build to an FTP server.
In this post, I&rsquo;ll be covering how to configure a full pipeline to include:</p>
<ul>
<li>A continuous testing build on each commit to the Develop branch.</li>
<li>An automated build to a staging environment on commit to the Main branch.</li>
<li>A manual deployment to a production environment using the Promote function in Drone.</li>
</ul>
<p><img loading="lazy" src="/Gitea-Drone-Workflow.png" alt="Gitea Drone Setup"  />
</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before getting started, make sure you have the following prerequisites in place:</p>
<ul>
<li><em><strong>A working Hugo website:</strong></em>
<ul>
<li>Set up a Hugo website locally.</li>
</ul>
</li>
<li><em><strong>A Git repository:</strong></em>
<ul>
<li>Host your Hugo website&rsquo;s code in a Gitea repository.</li>
</ul>
</li>
<li><em><strong>A working Drone instance:</strong></em>
<ul>
<li>Your Drone instance should be working correctly with your Gitea repository.</li>
</ul>
</li>
<li><em><strong>An FTP server</strong></em>
<ul>
<li>An FTP server configured with username and password, a valid user home directory and web content loaded from that location.</li>
</ul>
</li>
</ul>
<h2 id="what-is-a-drone-pipeline">What is a Drone Pipeline?</h2>
<p>In Drone, a pipeline refers to a sequence of steps and actions that are executed in a predefined order to build, test, and deploy software. It provides a structured and automated workflow for managing the different stages of the development process.</p>
<p>A pipeline in Drone is typically defined using a configuration file named &lsquo;.drone.yml&rsquo;. This file specifies the steps to be executed, the order in which they should run, and any required configurations or dependencies.</p>
<p>Here are the key components and concepts associated with a pipeline in Drone:</p>
<ul>
<li>
<p><em><strong>Stages:</strong></em><br>
A pipeline is divided into stages, which represent different phases of the software development lifecycle. Common stages include building, testing, and deploying. Each stage contains one or more steps that define the actions to be performed.</p>
</li>
<li>
<p><em><strong>Steps:</strong></em><br>
Steps are the individual units of work within a stage. They represent specific actions to be executed, such as running a command, running tests, or deploying the application. Steps can be executed sequentially or in parallel, depending on the requirements.</p>
</li>
<li>
<p><em><strong>Dependencies:</strong></em><br>
A step in a pipeline may have dependencies on previous steps. This allows for the establishment of a logical flow, where certain steps must be completed successfully before proceeding to the next ones. Dependencies ensure that the pipeline runs in a consistent and controlled manner.</p>
</li>
<li>
<p><em><strong>Conditions:</strong></em><br>
Conditions are used to control the execution of steps based on specific criteria. For example, a step may only run if a certain condition is met, such as the branch name, the outcome of a previous step, or the presence of a specific environment variable. Conditions provide flexibility and allow for conditional execution based on the project&rsquo;s needs.</p>
</li>
<li>
<p><em><strong>Artifacts:</strong></em><br>
Artifacts are files or directories generated during the pipeline execution that can be passed between steps or stored for later use. They allow for sharing data, test reports, build artifacts, or any other relevant files between different stages of the pipeline.</p>
</li>
<li>
<p><em><strong>Triggers:</strong></em><br>
Triggers determine when the pipeline should run. They can be defined to automatically start the pipeline on specific events, such as code pushes, pull requests, or scheduled intervals. Triggers ensure that the pipeline is executed whenever a relevant change occurs, maintaining an up-to-date and automated development process.</p>
</li>
</ul>
<h2 id="development-build">Development Build</h2>
<p>In my current setup, every commit to the Develop branch is picked up by Drone and creates a build.
This build pulls the develop branch from the Gitea repository, installs the Hugo modules and builds the Hugo website in development mode.</p>
<p>I have also set this to fail on any warnings, so that I can quickly see if there are any problems with my code.</p>
<p>This step is where I would run any tests on the output code and fail the build should any fail. More to come on that in future posts.</p>
<p>The specific steps for this in the drone.yaml file are:</p>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-YAML" data-lang="YAML"><span style="display:flex;"><span>---
</span></span><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">pipeline</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">type</span>: <span style="color:#ae81ff">docker</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">name</span>: <span style="color:#e6db74">&#34;Test Environment&#34;</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">trigger</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">branch</span>: 
</span></span><span style="display:flex;"><span>    - <span style="color:#ae81ff">develop </span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">event</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">include</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">push</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">steps</span>:   
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Clone Git Submodules</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">alpine/git </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">git submodule init</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">git submodule update --recursive --remote</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Build with Hugo</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">binaryronin/drone-hugo:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">pull</span>: <span style="color:#ae81ff">always </span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">echo &#34;Checking Hugo version.&#34;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">hugo version</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">cd /drone/src/hugo/</span>
</span></span><span style="display:flex;"><span>      <span style="color:#75715e"># Disable panicOnWarning due to bug in Hugo.</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">hugo --environment development --verbose --debug</span> <span style="color:#75715e"># --panicOnWarning</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">ls -al /drone/src/hugo/public</span>
</span></span></code></pre></div><p>As you can see, every push to the &lsquo;develop&rsquo; branch will trigger the following steps.
I have this configured to also show debug and more verbose information to help with investigating any problems.
You&rsquo;ll see I also specify the development environment in Hugo, this is to prevent items such as Google Analytics from running in a test setup.</p>
<h2 id="staging-build">Staging Build</h2>
<p>My staging build is run when a commit is made to the main branch. A nice approach would be to lock down the main branch so that no commits can be made directly to it. Any merges from the develop branch must come via a pull request. A tad overkill for a home setup, but it&rsquo;s good practice.</p>
<p>This build will do the same as the Test build, but also includes a step to deploy to my staging web server.</p>
<pre tabindex="0"><code>---
kind: pipeline
type: docker
name: &#34;Staging Environment&#34;

trigger:
  branch:
    - main
  event:
    include: 
      - push

steps:
  - name: Clone Git Submodules
    image: alpine/git
    commands:
      - git submodule init
      - git submodule update --recursive --remote

  - name: Build with Hugo
    image: binaryronin/drone-hugo:latest
    pull: always 
    commands:
      - echo &#34;Checking Hugo version.&#34;
      - hugo version
      - cd /drone/src/hugo/
      - hugo --environment develop --verbose
      - ls -al /drone/src/hugo/public

  - name: Deploy to Staging FTP
    image: cschlosser/drone-ftps
    environment:
        FTP_USERNAME:
          from_secret: staging_ftp_username
        FTP_PASSWORD:
          from_secret: staging_ftp_password 
        PLUGIN_SECURE: true
        PLUGIN_VERIFY: true
        PLUGIN_HOSTNAME:
          from_secret: staging_ftp_hostname
        PLUGIN_SRC_DIR: /hugo/public/
        PLUGIN_DEST_DIR: 
          from_secret: staging_ftp_directory
        PLUGIN_AUTO_CONFIRM: true
        PLUGIN_DEBUG: true 
        PLUGIN_ONLY_NEWER: true
</code></pre><p>You can see that I specify the environment for Hugo, as development. And this time, take advantage of Drone secrets for the Staging server details and credentials.</p>
<h2 id="production-build">Production Build</h2>
<p>Now the production build is slightly different, in that it can only be run through Drone by promoting an existing successful Staging build.</p>
<pre tabindex="0"><code>---
kind: pipeline
type: docker
name: &#34;Production Environment&#34;

trigger:
  target: 
    - production

steps:
  - name: Clone Git Submodules
    image: alpine/git
    commands:
      - git submodule init
      - git submodule update --recursive --remote

  - name: Build with Hugo
    image: binaryronin/drone-hugo:latest
    pull: always 
    commands:
      - echo &#34;Checking Hugo version.&#34;
      - hugo version
      - cd /drone/src/hugo/
      - hugo --environment production --verbose
      - ls -al /drone/src/hugo/public

  - name: Deploy to Production FTP
    image: cschlosser/drone-ftps
    environment:
        FTP_USERNAME:
          from_secret: production_ftp_username
        FTP_PASSWORD:
          from_secret: production_ftp_password 
        PLUGIN_SECURE: true
        PLUGIN_VERIFY: true
        PLUGIN_HOSTNAME:
          from_secret: production_ftp_hostname
        PLUGIN_SRC_DIR: /hugo/public/
        PLUGIN_DEST_DIR: 
          from_secret: production_ftp_directory
        PLUGIN_AUTO_CONFIRM: true
        PLUGIN_DEBUG: true 
        PLUGIN_ONLY_NEWER: true
</code></pre><p>Here you&rsquo;ll see that we change the environment for Hugo to be production and use Drone secrets again to specify the Production details and credentials.</p>
<h2 id="complete-drone-configuration">Complete Drone Configuration</h2>
<p>Putting all of these steps together, the complete config.yml file looks like this:</p>
<pre tabindex="0"><code>---
kind: pipeline
type: docker
name: &#34;Test Environment&#34;

trigger:
  branch: 
    - develop 
  event:
    include:
      - push

steps:   
  - name: Clone Git Submodules
    image: alpine/git 
    commands:
      - git submodule init
      - git submodule update --recursive --remote

  - name: Build with Hugo
    image: binaryronin/drone-hugo:latest
    pull: always 
    commands:
      - echo &#34;Checking Hugo version.&#34;
      - hugo version
      - cd /drone/src/hugo/
      # Disable panicOnWarning due to bug in Hugo.
      - hugo --environment development --verbose --debug # --panicOnWarning
      - ls -al /drone/src/hugo/public

---
kind: pipeline
type: docker
name: &#34;Staging Environment&#34;

trigger:
  branch:
    - main
  event:
    include: 
      - push

steps:
  - name: Clone Git Submodules
    image: alpine/git
    commands:
      - git submodule init
      - git submodule update --recursive --remote

  - name: Build with Hugo
    image: binaryronin/drone-hugo:latest
    pull: always 
    commands:
      - echo &#34;Checking Hugo version.&#34;
      - hugo version
      - cd /drone/src/hugo/
      - hugo --environment development --verbose
      - ls -al /drone/src/hugo/public

  - name: Deploy to Staging FTP
    image: cschlosser/drone-ftps
    environment:
        FTP_USERNAME:
          from_secret: staging_ftp_username
        FTP_PASSWORD:
          from_secret: staging_ftp_password 
        PLUGIN_SECURE: true
        PLUGIN_VERIFY: true
        PLUGIN_HOSTNAME:
          from_secret: staging_ftp_hostname
        PLUGIN_SRC_DIR: /hugo/public/
        PLUGIN_DEST_DIR: 
          from_secret: staging_ftp_directory
        PLUGIN_AUTO_CONFIRM: true
        PLUGIN_DEBUG: true 
        PLUGIN_ONLY_NEWER: true

---
kind: pipeline
type: docker
name: &#34;Production Environment&#34;

trigger:
  target: 
    - production

steps:
  - name: Clone Git Submodules
    image: alpine/git
    commands:
      - git submodule init
      - git submodule update --recursive --remote

  - name: Build with Hugo
    image: binaryronin/drone-hugo:latest
    pull: always 
    commands:
      - echo &#34;Checking Hugo version.&#34;
      - hugo version
      - cd /drone/src/hugo/
      - hugo --environment production --verbose
      - ls -al /drone/src/hugo/public

  - name: Deploy to Production FTP
    image: cschlosser/drone-ftps
    environment:
        FTP_USERNAME:
          from_secret: production_ftp_username
        FTP_PASSWORD:
          from_secret: production_ftp_password 
        PLUGIN_SECURE: true
        PLUGIN_VERIFY: true
        PLUGIN_HOSTNAME:
          from_secret: production_ftp_hostname
        PLUGIN_SRC_DIR: /hugo/public/
        PLUGIN_DEST_DIR: 
          from_secret: production_ftp_directory
        PLUGIN_AUTO_CONFIRM: true
        PLUGIN_DEBUG: true 
        PLUGIN_ONLY_NEWER: true
</code></pre><h2 id="summary">Summary</h2>
<p>With the above setup, you can see how easily a full work flow can be configured in Drone that will enable automatic and continuous builds and deployments. Hopefully saving you some time in the future and catching any problems well before they reach the production environment.</p>
<p>I&rsquo;ll continue documenting my journey with Gitea, Drone and Hugo and share the interesting things I find along the way.</p>
<p>If you want to look further in to any of the above tools, do take a look at my previous posts and read the official documentation from the following sites:</p>
<p><a href="https://gitea.io/en-us/">Gitea</a>
<a href="https://www.drone.io/">Drone</a>
<a href="https://gohugo.io/">Hugo</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Deploy to an FTP server with Drone</title>
      <link>https://andrewbeaton.net/posts/2023/05/drone-io-ftp-deploy/</link>
      <pubDate>Mon, 29 May 2023 00:00:00 +0000</pubDate>
      
      <guid>https://andrewbeaton.net/posts/2023/05/drone-io-ftp-deploy/</guid>
      <description>Deploy to an FTP server with Drone</description>
      <content:encoded><![CDATA[<p>In the previous posts, I covered how to set up Drone IO with either GitHub or Gitea, and deploy them to a server using SCP. This short post will cover how to set up Drone to deploy to an FTP server.</p>
<p>This is the setup that I&rsquo;m using for both my staging website and my production one (This one!).</p>
<p>Hugo does come with a built-in server for viewing your site locally but having a staging site gives me more confidence that everything will work correctly when deployed to my main website, especially as the whole process is automated.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before getting started, make sure you have the following prerequisites in place:</p>
<ul>
<li><em><strong>A working Hugo website:</strong></em>
<ul>
<li>Set up a Hugo website locally.</li>
</ul>
</li>
<li><em><strong>A Git repository:</strong></em>
<ul>
<li>Host your Hugo website&rsquo;s code in a Git repository.</li>
</ul>
</li>
<li><em><strong>An FTP server</strong></em>
<ul>
<li>An FTP server configured with username and password, a valid user home directory and web content loaded from that location.</li>
</ul>
</li>
</ul>
<h2 id="step-1-configure-the-droneio-pipeline">Step 1: Configure the Drone.io Pipeline</h2>
<ol>
<li>In your websites Git repository, create a <code>.drone.yml</code> file in the root directory.</li>
<li>Add the following code to the <code>.drone.yml</code> file:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">pipeline</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">name</span>: <span style="color:#ae81ff">your-pipeline-name</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">steps</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Clone Git Submodules</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">alpine/git</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">git submodule init</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">git submodule update --recursive --remote</span>
</span></span><span style="display:flex;"><span>      
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Build with Hugo</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">binaryronin/drone-hugo:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">pull</span>: <span style="color:#ae81ff">always</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">echo &#34;Checking Hugo version.&#34;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">hugo version</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">cd /drone/src/hugo/</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">hugo --verbose </span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">ls -al /drone/src/hugo/public </span>
</span></span><span style="display:flex;"><span>      
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Deploy to FTP server</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">cschlosser/drone-ftps</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">FTP_USERNAME</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">from_secret</span>: <span style="color:#ae81ff">ftp_username</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">FTP_PASSWORD</span>:
</span></span><span style="display:flex;"><span>            <span style="color:#f92672">from_secret</span>: <span style="color:#ae81ff">ftp_password </span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">PLUGIN_SECURE</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">PLUGIN_VERIFY</span>: <span style="color:#66d9ef">false</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">PLUGIN_HOSTNAME</span>: <span style="color:#ae81ff">ftp://host:21</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">PLUGIN_SRC_DIR</span>: <span style="color:#ae81ff">/hugo/public/</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">PLUGIN_DEST_DIR</span>: <span style="color:#ae81ff">/home/ftp_username</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">PLUGIN_AUTO_CONFIRM</span>: <span style="color:#66d9ef">true</span>
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">PLUGIN_DEBUG</span>: <span style="color:#66d9ef">true</span> 
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">PLUGIN_ONLY_NEWER</span>: <span style="color:#66d9ef">true</span>
</span></span></code></pre></div><p>Replace <code>your-pipeline-name</code> with a suitable name for your pipeline.</p>
<ol start="3">
<li>
<p>Adjust the <code>PLUGIN_HOSTNAME</code> and <code>PLUGIN_DEST_DIR</code> fields to match your remote server details and deployment directory.</p>
</li>
<li>
<p>Add secret for your remote server&rsquo;s username and password by going to your Drone.io repository settings and adding secrets with the keys <code>ftp_username</code>, <code>ftp_password</code> and the corresponding values.</p>
</li>
</ol>
<h2 id="step-2-trigger-the-pipeline">Step 2: Trigger the Pipeline</h2>
<ol>
<li>Push your updated <code>.drone.yml</code> file to your Git repository.</li>
<li>This will trigger the Drone.io pipeline to run.</li>
<li>Monitor the build process in the Drone.io interface to ensure everything is working correctly.</li>
<li>Once the pipeline completes successfully, your Hugo website will be deployed to the specified remote server.</li>
</ol>
<p>You have successfully set up Drone with an FTP server. Now, whenever you push changes to your Git repository, Drone.io will automatically build your Hugo website and deploy it to your remote FTP server.</p>
<p>I&rsquo;ll continue documenting my journey with Gitea, Drone and Hugo and share the interesting things I find along the way.</p>
<p>If you want to look further in to any of the above tools, do take a look at my previous posts and read the official documentation from the following sites:</p>
<p><a href="https://gitea.io/en-us/">Gitea</a>
<a href="https://www.drone.io/">Drone</a>
<a href="https://gohugo.io/">Hugo</a></p>
]]></content:encoded>
    </item>
    
    <item>
      <title>Set up Hugo with Drone and GitHub</title>
      <link>https://andrewbeaton.net/posts/2023/05/hugo-drone-io-github/</link>
      <pubDate>Sat, 20 May 2023 00:00:00 +0000</pubDate>
      
      <guid>https://andrewbeaton.net/posts/2023/05/hugo-drone-io-github/</guid>
      <description>Set up Hugo with Drone and GitHub</description>
      <content:encoded><![CDATA[<p>If you&rsquo;re looking for an efficient way to automate your Hugo website deployment, using a Docker Drone.io container as your continuous integration and delivery (CI/CD) platform can be a great choice.</p>
<p>In this guide, I&rsquo;ll walk you through the process of setting up Hugo with a Docker Drone.io container and GitHub, allowing you to streamline your website deployment workflow.</p>
<h2 id="prerequisites">Prerequisites</h2>
<p>Before getting started, make sure you have the following prerequisites in place:</p>
<ul>
<li><em><strong>Docker installed:</strong></em>
<ul>
<li>Ensure you have Docker installed on your local machine.</li>
</ul>
</li>
<li><em><strong>Basic knowledge of Docker:</strong></em>
<ul>
<li>Familiarity with Docker and Docker Compose will be helpful.</li>
</ul>
</li>
<li><em><strong>A working Hugo website:</strong></em>
<ul>
<li>Set up a Hugo website locally.</li>
</ul>
</li>
<li><em><strong>A GitHub repository:</strong></em>
<ul>
<li>Host your Hugo website&rsquo;s code in a GitHub repository.</li>
</ul>
</li>
</ul>
<h2 id="step-1-set-up-a-docker-droneio-container">Step 1: Set Up a Docker Drone.io Container</h2>
<ol>
<li>Create a new directory on your machine for the Docker Drone.io container configuration.</li>
<li>Create a <code>docker-compose.yml</code> file within that directory and add the following content:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">version</span>: <span style="color:#e6db74">&#39;3&#39;</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">services</span>:
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">drone-server</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">drone/drone:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">ports</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#e6db74">&#34;8080:80&#34;</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">./drone-data:/data</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">always</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">environment</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">DRONE_GITHUB_CLIENT_ID=your-github-client-id</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">DRONE_GITHUB_CLIENT_SECRET=your-github-client-secret</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  <span style="color:#f92672">drone-runner</span>:
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">drone/drone-runner-docker:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">volumes</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">/var/run/docker.sock:/var/run/docker.sock</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">restart</span>: <span style="color:#ae81ff">always</span>
</span></span></code></pre></div><ol start="3">
<li>
<p>Save the file and navigate to the Docker Drone.io container configuration directory in your terminal.</p>
</li>
<li>
<p>Replace <code>your-github-client-id</code> and <code>your-github-client-secret</code> with the appropriate values. These can be obtained by registering a new OAuth application within GitHub&rsquo;s settings.</p>
</li>
<li>
<p>Run the command <code>docker-compose up -d</code> to start the Docker Drone.io container.</p>
</li>
</ol>
<p>Drone.io should now be accessible at <a href="http://localhost:8080">http://localhost:8080</a>.</p>
<h2 id="step-2-connect-droneio-to-github">Step 2: Connect Drone.io to GitHub</h2>
<ol>
<li>Open Drone.io in your web browser at <a href="http://localhost:8080">http://localhost:8080</a>.</li>
<li>Sign in with your GitHub credentials.</li>
<li>Authorise Drone.io to access your GitHub repositories.</li>
</ol>
<h2 id="step-3-configure-the-droneio-pipeline">Step 3: Configure the Drone.io Pipeline</h2>
<ol>
<li>Within your Hugo website&rsquo;s GitHub repository, create a <code>.drone.yml</code> file in the root directory.</li>
<li>Add the following code to the <code>.drone.yml</code> file:</li>
</ol>
<div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;"><code class="language-yaml" data-lang="yaml"><span style="display:flex;"><span><span style="color:#f92672">kind</span>: <span style="color:#ae81ff">pipeline</span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">name</span>: <span style="color:#ae81ff">your-pipeline-name</span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span><span style="color:#f92672">steps</span>:
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Clone Git Submodules</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">alpine/git</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">git submodule init</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">git submodule update --recursive --remote</span>
</span></span><span style="display:flex;"><span>      
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Build with Hugo</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">binaryronin/drone-hugo:latest</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">pull</span>: <span style="color:#ae81ff">always</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">commands</span>:
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">echo &#34;Checking Hugo version.&#34;</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">hugo version</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">cd /drone/src/hugo/</span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">hugo --verbose </span>
</span></span><span style="display:flex;"><span>      - <span style="color:#ae81ff">ls -al /drone/src/hugo/public </span>
</span></span><span style="display:flex;"><span>
</span></span><span style="display:flex;"><span>  - <span style="color:#f92672">name</span>: <span style="color:#ae81ff">Deploy</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">image</span>: <span style="color:#ae81ff">appleboy/drone-scp</span>
</span></span><span style="display:flex;"><span>    <span style="color:#f92672">settings</span>:
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">host</span>: <span style="color:#ae81ff">your-remote-host</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">username</span>: <span style="color:#ae81ff">your-remote-username</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">password</span>:
</span></span><span style="display:flex;"><span>        <span style="color:#f92672">from_secret</span>: <span style="color:#ae81ff">your-remote-password-secret</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">source</span>: 
</span></span><span style="display:flex;"><span>        - <span style="color:#ae81ff">/hugo/public/</span>
</span></span><span style="display:flex;"><span>      <span style="color:#f92672">target</span>: <span style="color:#ae81ff">/path/to/your/remote/directory</span>
</span></span></code></pre></div><p>Replace <code>your-pipeline-name</code> with a suitable name for your pipeline.</p>
<ol start="3">
<li>
<p>Adjust the <code>host</code>, <code>username</code>, <code>password</code>, and <code>target</code> fields to match your remote server details and deployment directory.</p>
</li>
<li>
<p>Add a secret for your remote server&rsquo;s password by going to your Drone.io repository settings and adding a secret with the key <code>your-remote-password-secret</code> and the corresponding value.</p>
</li>
</ol>
<h2 id="step-4-trigger-the-pipeline">Step 4: Trigger the Pipeline</h2>
<ol>
<li>Push your updated <code>.drone.yml</code> file to your GitHub repository.</li>
<li>This will trigger the Drone.io pipeline to run.</li>
<li>Monitor the build process in the Drone.io interface to ensure everything is working correctly.</li>
<li>Once the pipeline completes successfully, your Hugo website will be deployed to the specified remote server.</li>
</ol>
<p>You have successfully set up Hugo with a Docker Drone.io container and GitHub. Now, whenever you push changes to your GitHub repository, Drone.io will automatically build your Hugo website and deploy it to your remote server.</p>
<p>I&rsquo;ll continue documenting my journey with Gitea, Drone and Hugo and share the interesting things I find along the way.</p>
<p>If you want to look further in to any of the above tools, do take a look at my previous posts and read the official documentation from the following sites:</p>
<p><a href="https://gitea.io/en-us/">Gitea</a>
<a href="https://www.drone.io/">Drone</a>
<a href="https://gohugo.io/">Hugo</a></p>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
