<?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>DEV Community: Natalí</title>
    <description>The latest articles on DEV Community by Natalí (@natilou).</description>
    <link>https://dev.to/natilou</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%2F1126600%2Fbe81e3e9-d799-4391-83fb-c62617d515c0.jpg</url>
      <title>DEV Community: Natalí</title>
      <link>https://dev.to/natilou</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/natilou"/>
    <language>en</language>
    <item>
      <title>Automating Tag Creation, Release, and Docker Image Publish with GitHub Actions</title>
      <dc:creator>Natalí</dc:creator>
      <pubDate>Wed, 26 Jul 2023 20:13:21 +0000</pubDate>
      <link>https://dev.to/natilou/automating-tag-creation-release-and-docker-image-publishing-with-github-actions-49jg</link>
      <guid>https://dev.to/natilou/automating-tag-creation-release-and-docker-image-publishing-with-github-actions-49jg</guid>
      <description>&lt;p&gt;I'm currently working on the improvement of the &lt;a href="https://github.com/natilou/wallabag-kindle-consumer" rel="noopener noreferrer"&gt;wallabag-kindle-consumer&lt;/a&gt; service.  Since the original repository hasn't been maintained, I decided to fork it. My first goal was to have an initial dev version (0.1.0) and a Docker image published on ghcr.io. Additionally, I wanted to automate the tag creation, the release of the service, and the process of building and publishing the Docker image using GitHub Actions.&lt;/p&gt;

&lt;p&gt;I watched a couple of YouTube videos (I'll leave the links at the end of the article) and read GitHub Actions documentation, but the resources showed how to use different GitHub Actions separately and didn't combine them. After many tries, I finally managed to do it. I decided to write this article to show how I accomplished it, and hopefully, it can help others who want to do the same but don't know where to start.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1&lt;/strong&gt; - &lt;strong&gt;&lt;a href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens" rel="noopener noreferrer"&gt;Create a Personal Access Token (PAT)&lt;/a&gt;on GitHub&lt;/strong&gt;. Make sure to select the &lt;code&gt;repo&lt;/code&gt; and &lt;code&gt;write:packages&lt;/code&gt; scopes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 2&lt;/strong&gt; - &lt;strong&gt;Add the created &lt;code&gt;PAT&lt;/code&gt; in the repository's secrets&lt;/strong&gt;:&lt;br&gt;
   In the repository's page, navigate to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Settings&lt;/code&gt; &amp;gt;&amp;gt; &lt;code&gt;Secrets and variables&lt;/code&gt; &amp;gt;&amp;gt; &lt;code&gt;Actions&lt;/code&gt; &amp;gt;&amp;gt; click in &lt;code&gt;New repository secret&lt;/code&gt; and paste the created token.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Step 3&lt;/strong&gt; - &lt;strong&gt;Grant read and write permissions to GitHub Actions&lt;/strong&gt;:&lt;br&gt;
   In the repository's page, navigate to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Settings&lt;/code&gt; &amp;gt;&amp;gt; &lt;code&gt;Actions&lt;/code&gt; &amp;gt;&amp;gt; &lt;code&gt;General&lt;/code&gt; &amp;gt;&amp;gt; Scroll to the end of the page to find &lt;code&gt;Workflow permissions&lt;/code&gt;, then select &lt;code&gt;Read and write permissions&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These steps are necessary because when using GitHub Actions, the workflows automatically create a &lt;code&gt;GITHUB_TOKEN&lt;/code&gt;, which is available as an environment variable within every GitHub Actions workflow. However, this token lacks the specific permissions we need in this case. By using the &lt;code&gt;PAT&lt;/code&gt;, we can trigger subsequent workflows, such as building and publishing the Docker image after tag creation and release. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 4&lt;/strong&gt; - &lt;strong&gt;Create workflows using the following actions&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;For automating releases based on &lt;a href="https://www.conventionalcommits.org/en/v1.0.0/" rel="noopener noreferrer"&gt;conventional commits&lt;/a&gt;, I used the &lt;a href="https://github.com/google-github-actions/release-please-action" rel="noopener noreferrer"&gt;google-github-actions/release-please-action@v3&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For the Docker image workflow, I used:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/docker/login-action" rel="noopener noreferrer"&gt;docker/login-action@v2&lt;/a&gt; to login against a Docker registry.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/docker/metadata-action" rel="noopener noreferrer"&gt;docker/metadata-action@v4&lt;/a&gt; to extract metadata (tags, labels) from Git reference and GitHub events for Docker.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/docker/build-push-action" rel="noopener noreferrer"&gt;docker/build-push-action@v4&lt;/a&gt; to build and push Docker images with Buildx.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;First workflow file (&lt;code&gt;relese-please.yml&lt;/code&gt;):&lt;br&gt;
&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release-please&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;
  &lt;span class="na"&gt;pull-requests&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;release-please&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&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;release-please&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;google-github-actions/release-please-action@v3&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;release-type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;simple&lt;/span&gt;
          &lt;span class="na"&gt;package-name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release&lt;/span&gt;
          &lt;span class="na"&gt;bump-minor-pre-major&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;bump-patch-for-minor-pre-major&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;token&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.PAT }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Second workflow file (&lt;code&gt;deploy.yml&lt;/code&gt;):&lt;br&gt;
&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;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;build-docker-image&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;v*'&lt;/span&gt;

&lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;REGISTRY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ghcr.io&lt;/span&gt;
  &lt;span class="na"&gt;IMAGE_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.repository }}&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-and-push-image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;permissions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;contents&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;read&lt;/span&gt;
      &lt;span class="na"&gt;packages&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;write&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;Checkout repository&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&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;Log in to the Container registry&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;registry&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.REGISTRY }}&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ github.actor }}&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.PAT }}&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;Extract metadata (tags, labels) for Docker&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;meta&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/metadata-action@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;images&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
            &lt;span class="s"&gt;type=semver,pattern={{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 and push Docker image&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/build-push-action@v4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;context&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
          &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
          &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.meta.outputs.tags }}&lt;/span&gt;
          &lt;span class="na"&gt;labels&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ steps.meta.outputs.labels }}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;It's important to note that the first version of the release when using Release Please Action will be "1.0.0" by default. If you want "0.1.0" as initial version (like me), you can achieve this by creating an empty commit with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git commit &lt;span class="nt"&gt;--allow-empty&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"chore: release 0.1.0"&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"Release-As: 0.1.0"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create a pull request with the desired version. You can find more information in the &lt;a href="https://github.com/googleapis/release-please#how-do-i-change-the-version-number" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In summary, using these two workflows and a Personal Access Token, we can configure GitHub Actions to automate the tags creation, releases, and the process of building and publishing the Docker image.&lt;/p&gt;

&lt;p&gt;Thanks to &lt;a href="https://www.youtube.com/@DevOpsJourney" rel="noopener noreferrer"&gt;@DevOpsJourney&lt;/a&gt; for the &lt;a href="https://www.youtube.com/watch?v=gqseP_wTZsk" rel="noopener noreferrer"&gt;GitHub Packages.. Containers in a GitHub repo?&lt;/a&gt; video and thanks to &lt;a href="https://www.youtube.com/@eddiejaoude" rel="noopener noreferrer"&gt;@eddiejaoude&lt;/a&gt; for the &lt;a href="https://www.youtube.com/watch?v=fcHJZ4pMzBs&amp;amp;t=319s" rel="noopener noreferrer"&gt;GitHub Actions can automate your releases from your git commit messages - conventional commits&lt;/a&gt; video. &lt;/p&gt;

</description>
      <category>githubactions</category>
      <category>cicd</category>
      <category>automation</category>
      <category>docker</category>
    </item>
  </channel>
</rss>
