<?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: N. Fajri</title>
    <description>The latest articles on DEV Community by N. Fajri (@masb0ymas).</description>
    <link>https://dev.to/masb0ymas</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%2F520037%2Fb6120732-adfb-4bf3-9d52-8b5a51972057.jpeg</url>
      <title>DEV Community: N. Fajri</title>
      <link>https://dev.to/masb0ymas</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/masb0ymas"/>
    <language>en</language>
    <item>
      <title>How to release a version of a web app using GitHub Workflow with GitHub Actions</title>
      <dc:creator>N. Fajri</dc:creator>
      <pubDate>Thu, 12 Dec 2024 07:18:43 +0000</pubDate>
      <link>https://dev.to/masb0ymas/how-to-release-a-version-of-a-web-app-using-github-workflow-with-github-actions-2oj4</link>
      <guid>https://dev.to/masb0ymas/how-to-release-a-version-of-a-web-app-using-github-workflow-with-github-actions-2oj4</guid>
      <description>&lt;p&gt;Maybe you ask me, why do I use a release version for a web application or library? Why not build on a local server or device?&lt;/p&gt;

&lt;p&gt;If I build a web application on the server and then the base code encounters an error, how do I revert to the previous code? maybe you can reset git commit with &lt;code&gt;git reset --hard xxxx&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Will you do it every time or every mistake? it's a bad idea to manage your web applications. It's a waste of time for me, I think the best practice for this problem is the release version, I can use the latest version or the oldest version.&lt;/p&gt;

&lt;p&gt;You can see the version tag of this repository.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F2ju17f7mq7u9efqwzakt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2ju17f7mq7u9efqwzakt.png" alt="git tag" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For information about release versions you can read the blog about &lt;a href="https://masb0ymas.com/blog/why-i-use-semantic-versioning" rel="noopener noreferrer"&gt;Semantic Release&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.github.com/en/actions/using-workflows" rel="noopener noreferrer"&gt;GitHub Workflows&lt;/a&gt; are typically used to Test a &lt;code&gt;library&lt;/code&gt; or &lt;code&gt;project&lt;/code&gt; before sending a &lt;code&gt;Pull Request&lt;/code&gt; for a Feature or Issue of your code to collaborate with others developers.&lt;/p&gt;

&lt;p&gt;For more information about GitHub Workflow you can read the official docs is here: &lt;a href="https://docs.github.com/en/actions/using-workflows" rel="noopener noreferrer"&gt;https://docs.github.com/en/actions/using-workflows&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the case I using &lt;code&gt;NodeJs&lt;/code&gt; for release a version of a web app using GitHub Workflow. For step like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup GitHub Secret Actions&lt;/li&gt;
&lt;li&gt;Using &lt;code&gt;standard-version&lt;/code&gt; library&lt;/li&gt;
&lt;li&gt;Prepare a Dockerfile to create a Docker Image&lt;/li&gt;
&lt;li&gt;Create a GitHub Workflow&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Setup GitHub Secret Actions
&lt;/h3&gt;

&lt;p&gt;Select your project repository, then the &lt;code&gt;Settings&lt;/code&gt; tab, and look below in the &lt;code&gt;Security&lt;/code&gt; &lt;code&gt;Secrets and Variables&lt;/code&gt; section, like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F2o8kh39f9a33m4r1fzhk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2o8kh39f9a33m4r1fzhk.png" alt="github secret actions" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And then you can add new secret with just a click &lt;code&gt;New Repository Secret&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can customize Docker credentials with 2 variables like, &lt;code&gt;DOCKERHUB_USERNAME&lt;/code&gt; and &lt;code&gt;DOCKERHUB_PASSWORD&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fc61xp45nqt6qydn7t1cc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fc61xp45nqt6qydn7t1cc.png" alt="new secret" width="800" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once the setup is complete it looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Flgn92hmslpb50ajwv1mx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Flgn92hmslpb50ajwv1mx.png" alt="secret list" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Using standard-version library
&lt;/h3&gt;

&lt;p&gt;You can install this library for release with git tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; standard-version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can update &lt;code&gt;package.json&lt;/code&gt; script, and add release command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="err"&gt;scripts:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postrelease"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git push --follow-tags origin main"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"standard-version"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release:pre"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run release -- --prerelease"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release:patch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run release -- --release-as patch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release:minor"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run release -- --release-as minor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"release:major"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"npm run release -- --release-as major"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So when you run the &lt;code&gt;yarn release&lt;/code&gt; command after standard-version has done app version tagging, it continues with the push code because of the &lt;code&gt;postrelease&lt;/code&gt; command.&lt;/p&gt;

&lt;h3&gt;
  
  
  Prepare a Dockerfile to create a Docker Image
&lt;/h3&gt;

&lt;p&gt;In this case, I used NextJs for the configuration of the Dockerfile and then created a Docker Image. You can customize next.config.mjs like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="cm"&gt;/** @type {import('next').NextConfig} */&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;reactStrictMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;swcMinify&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;standalone&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The most important thing in &lt;code&gt;next.config.mjs&lt;/code&gt; is the output: &lt;code&gt;"standalone"&lt;/code&gt; which makes the docker image size lower. Now you can using my Dockerfile config.&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="s"&gt;FROM node:18-alpine AS base&lt;/span&gt;
&lt;span class="s"&gt;LABEL author="author_name"&lt;/span&gt;
&lt;span class="s"&gt;LABEL name="your_application_name"&lt;/span&gt;

&lt;span class="c1"&gt;# Install dependencies only when needed&lt;/span&gt;
&lt;span class="s"&gt;FROM base AS deps&lt;/span&gt;
&lt;span class="c1"&gt;# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.&lt;/span&gt;
&lt;span class="s"&gt;RUN apk add --no-cache libc6-compat&lt;/span&gt;
&lt;span class="s"&gt;WORKDIR /app&lt;/span&gt;

&lt;span class="c1"&gt;# Install dependencies based on the preferred package manager&lt;/span&gt;
&lt;span class="s"&gt;COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./&lt;/span&gt;
&lt;span class="s"&gt;RUN \&lt;/span&gt;
  &lt;span class="s"&gt;if [ -f package-lock.json ]; then npm ci; \&lt;/span&gt;
  &lt;span class="s"&gt;elif [ -f yarn.lock ]; then yarn --frozen-lockfile; \&lt;/span&gt;
  &lt;span class="s"&gt;elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm &amp;amp;&amp;amp; pnpm i --frozen-lockfile; \&lt;/span&gt;
  &lt;span class="s"&gt;else echo "Lockfile not found." &amp;amp;&amp;amp; exit 1; \&lt;/span&gt;
  &lt;span class="s"&gt;fi&lt;/span&gt;

&lt;span class="c1"&gt;# Rebuild the source code only when needed&lt;/span&gt;
&lt;span class="s"&gt;FROM base AS builder&lt;/span&gt;
&lt;span class="s"&gt;WORKDIR /app&lt;/span&gt;

&lt;span class="s"&gt;COPY --from=deps /app/node_modules ./node_modules&lt;/span&gt;
&lt;span class="s"&gt;COPY . .&lt;/span&gt;

&lt;span class="c1"&gt;# RUN cp .env.docker-production .env&lt;/span&gt;

&lt;span class="c1"&gt;# Next.js collects completely anonymous telemetry data about general usage.&lt;/span&gt;
&lt;span class="c1"&gt;# Learn more here: https://nextjs.org/telemetry&lt;/span&gt;
&lt;span class="c1"&gt;# Uncomment the following line in case you want to disable telemetry during the build.&lt;/span&gt;
&lt;span class="c1"&gt;# ENV NEXT_TELEMETRY_DISABLED 1&lt;/span&gt;

&lt;span class="c1"&gt;# If using npm comment out above and use below instead&lt;/span&gt;
&lt;span class="s"&gt;RUN npm run build&lt;/span&gt;

&lt;span class="c1"&gt;# Production image, copy all the files and run next&lt;/span&gt;
&lt;span class="s"&gt;FROM base AS runner&lt;/span&gt;
&lt;span class="s"&gt;WORKDIR /app&lt;/span&gt;

&lt;span class="s"&gt;ENV NODE_ENV production&lt;/span&gt;
&lt;span class="c1"&gt;# Uncomment the following line in case you want to disable telemetry during runtime.&lt;/span&gt;
&lt;span class="c1"&gt;# ENV NEXT_TELEMETRY_DISABLED 1&lt;/span&gt;

&lt;span class="s"&gt;RUN addgroup --system --gid 1001 nodejs&lt;/span&gt;
&lt;span class="s"&gt;RUN adduser --system --uid 1001 nextjs&lt;/span&gt;

&lt;span class="s"&gt;COPY --from=builder /app/public ./public&lt;/span&gt;

&lt;span class="c1"&gt;# Automatically leverage output traces to reduce image size&lt;/span&gt;
&lt;span class="c1"&gt;# https://nextjs.org/docs/advanced-features/output-file-tracing&lt;/span&gt;
&lt;span class="s"&gt;COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./&lt;/span&gt;
&lt;span class="s"&gt;COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static&lt;/span&gt;

&lt;span class="s"&gt;USER nextjs&lt;/span&gt;

&lt;span class="s"&gt;EXPOSE &lt;/span&gt;&lt;span class="m"&gt;3000&lt;/span&gt;

&lt;span class="s"&gt;ENV PORT &lt;/span&gt;&lt;span class="m"&gt;3000&lt;/span&gt;

&lt;span class="s"&gt;CMD ["node", "server.js"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here there are 3 layers, &lt;code&gt;deps&lt;/code&gt;, &lt;code&gt;builder&lt;/code&gt; and &lt;code&gt;runner&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;deps&lt;/code&gt; only install a dependency for the &lt;code&gt;builder&lt;/code&gt; needed.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;builder&lt;/code&gt; only build a project to production mode.&lt;/p&gt;

&lt;p&gt;For &lt;code&gt;runner&lt;/code&gt; he runs the project with docker image runtime.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a GitHub Workflow
&lt;/h3&gt;

&lt;p&gt;Before you run GitHub Workflow, make sure you have created a repository in docker hub.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fu37lzy35m034ka0y055m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fu37lzy35m034ka0y055m.png" alt="dockerhub" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;First, define a running workflow based on its branches or tags. If you want to trigger a workflow with a branch it can be like this:&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="nn"&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 Image to Docker Hub&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="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;releases/**"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I usually trigger when push tags.&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="nn"&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 Image to Docker Hub&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then determine the OS used and the environment variable.&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 and Push Image to Docker Hub&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&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-push-release&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 to Docker Hub ( Release )&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="c1"&gt;# using ubuntu latest for running workflow&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;IMAGE_NAME&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your_docker_hub_repository&lt;/span&gt; &lt;span class="c1"&gt;# change this&lt;/span&gt;
      &lt;span class="na"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your_docker_hub_account&lt;/span&gt; &lt;span class="c1"&gt;# change this&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Next step get tagging from GitHub tags.&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 and Push Image to Docker Hub&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&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-push-release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;steps&lt;/span&gt;&lt;span class="err"&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&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;Github Tag Release Version&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;latestTag&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|-&lt;/span&gt;
        &lt;span class="s"&gt;echo "Tag name from GITHUB_REF_NAME: $GITHUB_REF_NAME"&lt;/span&gt;
        &lt;span class="s"&gt;echo "RELEASE_VERSION=release-${{ github.ref_name }}" &amp;gt;&amp;gt; $GITHUB_ENV&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And then login to docker hub with &lt;code&gt;docker/login-action@v3&lt;/code&gt; and create a docker image. Secrets obtained from Secrets and Variables can be set for the first time.&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;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-push-release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;- name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;login to docker registry&lt;/span&gt;
      &lt;span class="s"&gt;uses&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;docker/login-action@v3&lt;/span&gt;
      &lt;span class="s"&gt;with&lt;/span&gt;&lt;span class="err"&gt;:&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;${{secrets.DOCKERHUB_USERNAME}}&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.DOCKERHUB_PASSWORD}}&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 Docker Image&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|-&lt;/span&gt;
        &lt;span class="s"&gt;docker build -t $IMAGE_NAME:latest .&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once the build a Docker Image is complete. It's time for us to tag the docker image and push it to docker hub.&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;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-push-release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;- name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Push Docker Image to Hub Docker&lt;/span&gt;
        &lt;span class="s"&gt;run&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|-&lt;/span&gt;
          &lt;span class="s"&gt;docker tag $IMAGE_NAME:latest ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:latest&lt;/span&gt;
          &lt;span class="s"&gt;docker tag $IMAGE_NAME:latest ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:release&lt;/span&gt;
          &lt;span class="s"&gt;docker tag $IMAGE_NAME:latest ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE_VERSION }}&lt;/span&gt;
          &lt;span class="s"&gt;docker push ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:latest&lt;/span&gt;
          &lt;span class="s"&gt;docker push ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:release&lt;/span&gt;
          &lt;span class="s"&gt;docker push ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE_VERSION }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your docker image has done and you can check on hub.docker.com.&lt;/p&gt;

&lt;p&gt;Optional, if you want to send a notification after step above is complete, you can add step for notification like this:&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;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-push-release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
    &lt;span class="s"&gt;- name&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Call Webhook&lt;/span&gt;
      &lt;span class="s"&gt;uses&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s"&gt;joelwmale/webhook-action@2.3.2&lt;/span&gt;
      &lt;span class="s"&gt;env&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;IMAGE_REGISTRY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Docker Hub&lt;/span&gt;
        &lt;span class="na"&gt;IMAGE_REPOSITORY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hub.docker.com/${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}&lt;/span&gt;
        &lt;span class="na"&gt;IMAGE_TAG&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.RELEASE_VERSION }}&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;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://your_domain.com/notification&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{"push_data":{"tag":"${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;env.IMAGE_TAG&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"},"repository":{"name":"${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;env.IMAGE_REPOSITORY&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a complete GitHub Workflow script like this:&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="nn"&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 Image to Docker Hub&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="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&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-push-release&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 to Docker Hub ( Release )&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;env&lt;/span&gt;&lt;span class="pi"&gt;:&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;your_docker_hub_repository&lt;/span&gt; &lt;span class="c1"&gt;# change this&lt;/span&gt;
      &lt;span class="na"&gt;PROJECT_ID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your_docker_hub_account&lt;/span&gt; &lt;span class="c1"&gt;# change this&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&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;Github Tag Release Version&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;latestTag&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|-&lt;/span&gt;
          &lt;span class="s"&gt;echo "Tag name from GITHUB_REF_NAME: $GITHUB_REF_NAME"&lt;/span&gt;
          &lt;span class="s"&gt;echo "RELEASE_VERSION=release-${{ github.ref_name }}" &amp;gt;&amp;gt; $GITHUB_ENV&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;login to docker 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@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;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{secrets.DOCKERHUB_USERNAME}}&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.DOCKERHUB_PASSWORD}}&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 Docker Image&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|-&lt;/span&gt;
          &lt;span class="s"&gt;docker build -t $IMAGE_NAME:latest .&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;Push Docker Image to Docker Hub&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|-&lt;/span&gt;
          &lt;span class="s"&gt;docker tag $IMAGE_NAME:latest ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:latest&lt;/span&gt;
          &lt;span class="s"&gt;docker tag $IMAGE_NAME:latest ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:release&lt;/span&gt;
          &lt;span class="s"&gt;docker tag $IMAGE_NAME:latest ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE_VERSION }}&lt;/span&gt;
          &lt;span class="s"&gt;docker push ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:latest&lt;/span&gt;
          &lt;span class="s"&gt;docker push ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:release&lt;/span&gt;
          &lt;span class="s"&gt;docker push ${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}:${{ env.RELEASE_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;Call Webhook&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;joelwmale/webhook-action@2.3.2&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;IMAGE_REGISTRY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Docker Hub&lt;/span&gt;
          &lt;span class="na"&gt;IMAGE_REPOSITORY&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;hub.docker.com/${{ env.PROJECT_ID }}/${{ env.IMAGE_NAME }}&lt;/span&gt;
          &lt;span class="na"&gt;IMAGE_TAG&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ env.RELEASE_VERSION }}&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;url&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;https://your_domain.com/notification&lt;/span&gt;
          &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;{"push_data":{"tag":"${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;env.IMAGE_TAG&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"},"repository":{"name":"${{&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;env.IMAGE_REPOSITORY&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;}}"}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;With the release version I can use the latest or oldest version of my web application. Then with GitHub Actions, I easily create and push docker images to the Registry, can also use AWS Container Registry, GCP Artifact Registry, and Docker Hub.&lt;/p&gt;

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