<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Epul Dev</title><description>My Documentation Blogs</description><link>https://blogs.msaepul.my.id/</link><language>id</language><item><title>Mengenal Konsep Design System: Clean Architecture</title><link>https://blogs.msaepul.my.id/posts/clean-architecture/</link><guid isPermaLink="true">https://blogs.msaepul.my.id/posts/clean-architecture/</guid><pubDate>Wed, 11 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Clean Architecture: Cara Biar Project Tidak Jadi “Spaghetti Code”&lt;/h1&gt;
&lt;p&gt;Sering pusing karena project kamu kelihatan tidak efisien, susah di-maintain, dan semua logic tercampur di satu tempat?&lt;/p&gt;
&lt;p&gt;File controller penuh dengan query database, business logic bercampur dengan validasi, bahkan kadang helper random ikut nimbrung di situ juga.&lt;/p&gt;
&lt;p&gt;Kalau projectnya masih kecil dan kita kerjakan sendiri, mungkin masih bisa diatasi. Kamu masih ingat semua alur kodenya di kepala.&lt;/p&gt;
&lt;p&gt;Namun bagaimana jika project tersebut dikerjakan bersama tim?&lt;/p&gt;
&lt;p&gt;Mulai muncul pertanyaan seperti:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;“Logic ini ada di mana ya?”&lt;/li&gt;
&lt;li&gt;“Kalau ubah fitur ini nanti efeknya ke mana saja?”&lt;/li&gt;
&lt;li&gt;“Kenapa function ini dipanggil dari tiga tempat berbeda?”&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Akhirnya kita sebagai developer harus bolak-balik bertanya ke orang lain yang handle kode tsb hanya untuk memahami struktur project.&lt;/p&gt;
&lt;p&gt;Dan di sinilah konsep &lt;strong&gt;Clean Architecture&lt;/strong&gt; mulai terasa penting.&lt;/p&gt;
&lt;p&gt;Clean Architecture membantu kita membuat sistem yang &lt;strong&gt;terstruktur, mudah dipahami, dan lebih mudah di-maintain dalam jangka panjang.&lt;/strong&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Apa Itu Clean Architecture?&lt;/h2&gt;
&lt;p&gt;Clean Architecture adalah konsep arsitektur software yang diperkenalkan oleh Robert C. Martin (Uncle Bob).&lt;/p&gt;
&lt;p&gt;Tujuan utamanya sederhana:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Memisahkan tanggung jawab dalam aplikasi agar setiap bagian memiliki peran yang jelas.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Dengan pemisahan ini kita mendapatkan beberapa keuntungan:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Code lebih mudah dipahami&lt;/li&gt;
&lt;li&gt;Mudah melakukan testing&lt;/li&gt;
&lt;li&gt;Tidak bergantung pada framework&lt;/li&gt;
&lt;li&gt;Lebih mudah melakukan perubahan di masa depan&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Masalah Umum Tanpa Arsitektur yang Jelas&lt;/h2&gt;
&lt;p&gt;Kita coba lihat contoh struktur project yang sering terjadi.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;controllers/
    userController.js
    orderController.js

models/
    userModel.js
    orderModel.js

routes/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Masalahnya?&lt;/p&gt;
&lt;p&gt;Sering kali controller berisi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Query database&lt;/li&gt;
&lt;li&gt;Validasi&lt;/li&gt;
&lt;li&gt;Business logic&lt;/li&gt;
&lt;li&gt;Response API&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contohnya:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;async function createUser(req, res) {
   const user = await db.query(&quot;INSERT INTO users ...&quot;)

   if(user.age &amp;lt; 18){
       return res.json({error: &quot;Too young&quot;})
   }

   sendEmail(user.email)

   return res.json(user)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Semua logic tercampur di satu tempat.&lt;/p&gt;
&lt;p&gt;Akibatnya:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Susah di test&lt;/li&gt;
&lt;li&gt;Susah di reuse&lt;/li&gt;
&lt;li&gt;Susah di maintain&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Semakin besar project, semakin terasa dampaknya.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Konsep Dasar Clean Architecture&lt;/h2&gt;
&lt;p&gt;Clean Architecture biasanya dibagi menjadi beberapa layer:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Entities
Use Cases
Interface Adapters
Frameworks &amp;amp; Drivers
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Atau jika disederhanakan:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Domain
Usecase
Repository
Handler / Controller
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Mari kita bahas satu per satu.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;1. Entities (Domain)&lt;/h3&gt;
&lt;p&gt;Ini adalah inti dari aplikasi.&lt;/p&gt;
&lt;p&gt;Berisi:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Struct / Model&lt;/li&gt;
&lt;li&gt;Business rules utama&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type User struct {
    ID    string
    Name  string
    Email string
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Layer ini &lt;strong&gt;tidak boleh bergantung pada database, framework, atau API&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Tujuannya supaya domain logic tetap bersih.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;2. Usecase (Business Logic)&lt;/h3&gt;
&lt;p&gt;Layer ini berisi logic aplikasi.&lt;/p&gt;
&lt;p&gt;Contohnya:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Create user&lt;/li&gt;
&lt;li&gt;Login&lt;/li&gt;
&lt;li&gt;Calculate price&lt;/li&gt;
&lt;li&gt;Process order&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contoh sederhana:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type UserUsecase struct {
    repo UserRepository
}

func (u *UserUsecase) CreateUser(user User) error {
    return u.repo.Create(user)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Usecase hanya tahu &lt;strong&gt;apa yang harus dilakukan&lt;/strong&gt;, bukan &lt;strong&gt;bagaimana implementasinya&lt;/strong&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;3. Repository&lt;/h3&gt;
&lt;p&gt;Repository adalah layer yang bertugas berkomunikasi dengan database.&lt;/p&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;type UserRepository interface {
    Create(user User) error
    FindByEmail(email string) (*User, error)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Implementasinya bisa berbeda:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;PostgreSQL&lt;/li&gt;
&lt;li&gt;MySQL&lt;/li&gt;
&lt;li&gt;MongoDB&lt;/li&gt;
&lt;li&gt;bahkan API&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Usecase tidak perlu tahu.&lt;/p&gt;
&lt;hr /&gt;
&lt;h3&gt;4. Handler / Controller&lt;/h3&gt;
&lt;p&gt;Layer ini menangani request dari luar.&lt;/p&gt;
&lt;p&gt;Contoh:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;HTTP API&lt;/li&gt;
&lt;li&gt;CLI&lt;/li&gt;
&lt;li&gt;gRPC&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contoh sederhana:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;func (h *UserHandler) CreateUser(c *fiber.Ctx) error {
    var req CreateUserRequest

    if err := c.BodyParser(&amp;amp;req); err != nil {
        return err
    }

    err := h.usecase.CreateUser(req.ToDomain())

    return c.JSON(&quot;success&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Controller hanya bertugas:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;menerima request&lt;/li&gt;
&lt;li&gt;memanggil usecase&lt;/li&gt;
&lt;li&gt;mengembalikan response&lt;/li&gt;
&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;Prinsip Penting Clean Architecture&lt;/h2&gt;
&lt;p&gt;Ada satu aturan utama:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Dependency harus mengarah ke dalam (inward).&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Artinya:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Controller -&amp;gt; Usecase -&amp;gt; Domain
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Bukan sebaliknya.&lt;/p&gt;
&lt;p&gt;Domain tidak boleh tahu tentang:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;database&lt;/li&gt;
&lt;li&gt;framework&lt;/li&gt;
&lt;li&gt;HTTP&lt;/li&gt;
&lt;li&gt;library eksternal&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dengan begitu, domain tetap stabil walaupun teknologi berubah.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Contoh Struktur Project&lt;/h2&gt;
&lt;p&gt;Contoh struktur project:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;internal/

    domain/
        user.go

    repository/
        user_repository.go
        user_repository_impl.go

    usecase/
        user_usecase.go

    handler/
        user_handler.go
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Struktur seperti ini membuat code lebih mudah dipahami oleh developer lain.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Kapan Clean Architecture Dibutuhkan?&lt;/h2&gt;
&lt;p&gt;Clean Architecture sangat berguna ketika:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Project mulai membesar&lt;/li&gt;
&lt;li&gt;Banyak developer dalam satu project&lt;/li&gt;
&lt;li&gt;Sistem memiliki banyak business logic&lt;/li&gt;
&lt;li&gt;Project diharapkan bertahan lama&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Namun untuk project kecil atau prototype, arsitektur sederhana mungkin sudah cukup.&lt;/p&gt;
&lt;hr /&gt;
&lt;h2&gt;Penutup&lt;/h2&gt;
&lt;p&gt;Clean Architecture bukan sekadar membuat folder yang banyak.&lt;/p&gt;
&lt;p&gt;Tujuannya adalah &lt;strong&gt;memisahkan tanggung jawab dalam sistem&lt;/strong&gt; agar kode tetap rapi, scalable, dan mudah dipahami.&lt;/p&gt;
&lt;p&gt;Dengan menerapkan arsitektur yang baik sejak awal, kita bisa menghindari masalah klasik seperti:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;spaghetti code&lt;/li&gt;
&lt;li&gt;sulit testing&lt;/li&gt;
&lt;li&gt;sulit maintain&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dan yang paling penting, developer lain tidak perlu lagi kebingungan mencari logic di dalam project,&lt;/p&gt;
&lt;p&gt;Mungkin sampai disini saja yang bisa dapat saya bagikan, dan semoga yang saya bagikan dapat bermanfaat kedepanya :)&lt;/p&gt;
&lt;p&gt;Sekian dan Nuhunn ~&lt;/p&gt;
</content:encoded></item><item><title>Deploy Service Go Ke Vps Dengan Resource Kecil</title><link>https://blogs.msaepul.my.id/posts/deploy-cicd-on-minimum-resource/</link><guid isPermaLink="true">https://blogs.msaepul.my.id/posts/deploy-cicd-on-minimum-resource/</guid><pubDate>Sun, 07 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Deploy Service Go ke VPS dengan Resource Terbatas menggunakan Docker dan GitHub Actions, Emang Bisa?&lt;/h1&gt;
&lt;p&gt;Sebagian developer sangat ingin membuat sesuatu, tapi kadang terkendala dengan resource server yang terbatas seperti dengan spesifikasi server 1GB Ram 1 Core CPU, betul kan? hehe.&lt;/p&gt;
&lt;p&gt;Di sini, aku akan coba membahas cara mengakali keterbatasan tersebut agar service yang dibuat tetap bisa dijalankan di VPS, &lt;strong&gt;tanpa harus membebani server&lt;/strong&gt; saat build. Caranya adalah dengan memanfaatkan &lt;strong&gt;Docker Hub&lt;/strong&gt; untuk menyimpan image, dan &lt;strong&gt;GitHub Actions&lt;/strong&gt; untuk otomatisasi build &amp;amp; push image.&lt;/p&gt;
&lt;p&gt;&amp;lt;div align=&quot;center&quot;&amp;gt;
&amp;lt;img src=&quot;/contents/Capture-Github-Actions.png&quot; alt=&quot;Github Actions Screenshot&quot; width=&quot;600&quot;/&amp;gt;
&amp;lt;/div&amp;gt;&lt;/p&gt;
&lt;p&gt;Dengan pendekatan ini:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Build service dilakukan di GitHub Actions (bukan di VPS), sehingga VPS tidak perlu resource besar.&lt;/li&gt;
&lt;li&gt;VPS hanya melakukan &lt;strong&gt;pull image&lt;/strong&gt; terbaru dan menjalankannya menggunakan Docker.&lt;/li&gt;
&lt;li&gt;Proses deployment menjadi lebih cepat dan konsisten.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Blog ini akan memandumu langkah demi langkah, mulai dari setup project dan workflow dengan github action, membuat repository untuk meyimpan hasil build image di docker hub, sampai setting up worfklow untuk pulling image dari docker hub ke VPS.&lt;/p&gt;
&lt;p&gt;tapi sebelum mulai, kamu mungkin perlu tau kenapa harus menggunakan github action? dan apa aja sih kekurangannya menggunakan github action ini?&lt;/p&gt;
&lt;h2&gt;Kenapa Menggunakan GitHub Actions?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Terintegrasi langsung dengan GitHub: Tidak perlu layanan CI/CD pihak ketiga. Semua bisa dijalankan langsung dari repo kamu, jadi kamu tidak perlu mengubah kodenya lagi di berbagai platform.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Automatisasi penuh: Bisa otomatis build, test, push image, deploy ke server atau cloud.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Workflow yang fleksibel: Bisa menentukan event trigger, branch, atau manual dispatch.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Gratis untuk repositori publik: Menyediakan kuota cukup untuk project hobby mu atau sekedar untuk projek skala kecil dan menegah.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Mudah dibagikan: Workflow bisa digunakan ulang atau dibagi ke repo lain jika orang tesebut memiliki akses ke repo mu.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Banyak action dan tool yang tersedia: Github Telah Menyediakan Marketplace untuk berbagai tool dan action yang bisa digunakan.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Notifikasi &amp;amp; monitoring: Bisa menerima notifikasi sukses/gagal langsung ke email yang terdaftar dari github mu dan memonitor log build.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Kekurangan Menggunakan GitHub Actions&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Kuota terbatas untuk private repo: Gratisan untuk private repo punya batasan menit eksekusi per bulan.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Kurang fleksibel untuk server internal: Deploy ke server di network lokal kadang perlu setup tambahan (SSH, firewall, dsb).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Debugging bisa tricky: Log Actions cukup jelas, tapi jika ada error di step tertentu, kadang perlu trial &amp;amp; error.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Tergantung GitHub: Kalau GitHub down atau ada maintenance, workflow akan berhenti sementara.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Apa Yang Diperlukan Untuk Tutorial Kali Ini?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Repository github yang sudah memiliki dockerfile / docker compose&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Akun Docker Hub&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Dan server / vps untuk deployment service&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Langsung Gass Kita Coba&lt;/h3&gt;
&lt;p&gt;Yang pertama pastikan kamu udah buat akun untuk docker hub, kalo belum bisa buatnya klik &lt;a href=&quot;https://hub.docker.com/signup&quot;&gt;disini&lt;/a&gt; ketika sudah berada di dashboard cari bagian repository dan klik &lt;code&gt;Create Repository&lt;/code&gt; dan isikan nama repository nya lalu klik &lt;code&gt;Create Repository&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;setelah itu kita harus membuat secret docker hub, klik pada bagian avatar -? di bagian atas -&amp;gt; &lt;code&gt;Settings&lt;/code&gt; -&amp;gt; &lt;code&gt;Secrets&lt;/code&gt; dan klik &lt;code&gt;Personal Access Tokens&lt;/code&gt; lalu klik &lt;code&gt;New Token&lt;/code&gt; dan isikan nama token nya dan token yang dihasilkan, klik &lt;code&gt;Create Token&lt;/code&gt; setelah token terbuat copy secret nya.&lt;/p&gt;
&lt;h3&gt;Setting Up Environtment repo&lt;/h3&gt;
&lt;p&gt;Yang kedua disini kita harus set env secret di github, dari halaman projek repository mu klik &lt;code&gt;Settings And Variable&lt;/code&gt; -&amp;gt; &lt;code&gt;Actions&lt;/code&gt; -&amp;gt; &lt;code&gt;Repository Secrets&lt;/code&gt; dan klik &lt;code&gt;New repository secret&lt;/code&gt; lalu isikan secret berikut sesuai dengan yang kamu punya:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Secret Name&lt;/th&gt;
&lt;th&gt;Deskripsi&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DOCKER_USERNAME&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Username Docker Hub kamu&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DOCKER_SECRET&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Token / password Docker Hub (disarankan gunakan token)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VPS_HOST&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;IP atau hostname VPS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VPS_PORT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Port SSH untuk login VPS (contoh: &lt;code&gt;22&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VPS_USER&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;User SSH untuk login VPS (contoh: &lt;code&gt;root&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VPS_SSH_KEY&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Private key untuk SSH (disimpan di GitHub Secrets)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3&gt;Setting Up Workflow&lt;/h3&gt;
&lt;p&gt;Disini kita buat dulu workflow di github action untuk membuild docker compose kita untuk pushing result build image nya ke docker hub, dan pulling image ke instance/vps pastiin dulu kalo repo mu udah ada docker-compose.yml nya yaaa~&lt;/p&gt;
&lt;p&gt;dari tampilan repositori mu sekarang klik &lt;code&gt;Actions&lt;/code&gt; dibagian atas kanan -&amp;gt; &lt;code&gt;New Workflow&lt;/code&gt; dan isikan kode  berikut:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;build.yml&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name: Build and Push to Docker Hub

on:
  push:
    branches: [&quot;main&quot;]

jobs:
  build-and-push:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up Go
        uses: actions/setup-go@v4
        with:
          go-version: &quot;1.24.2&quot;

      - name: Cache Go modules
        uses: actions/cache@v3
        with:
          path: |
            ~/.cache/go-build
            ~/go/pkg/mod
          key: ${{ runner.os }}-go-${{ hashFiles(&apos;**/go.sum&apos;) }}
          restore-keys: |
            ${{ runner.os }}-go-

      - name: Install dependencies
        run: go mod tidy

      - name: Log in to Docker Hub
        run: echo &quot;${{ secrets.DOCKER_SECRET }}&quot; | docker login -u &quot;${{ secrets.DOCKER_USERNAME }}&quot; --password-stdin

      - name: Build Docker image
        run: docker build -t ${{ secrets.DOCKER_USERNAME }}/namarepo-dockerhubmu:latest .

      - name: Push Docker image
        run: docker push ${{ secrets.DOCKER_USERNAME }}/namarepo-dockerhubmu:latest

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;kode diatas adalah template workflow yang kita gunakan untuk build service kita ke docker image di instance github action yang nantinya akan di push ke docker hub sebagai media penyimpanan image dan share image antar platform.&lt;/p&gt;
&lt;p&gt;oiya sebelum lanjut ke kode dibawah, pastikan kamu udah setting up repository project mu ke vps/instance dengan directory yang udah kamu tentukan dan pastikan juga kamu udah menginstall docker dan docker compose di server mu.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;pull.yml&lt;/strong&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;name: Deploy via SSH

on:
  workflow_run:
    workflows: [&quot;Build and Push to Docker Hub&quot;]
    types:
      - completed

jobs:
  deploy:
    if: ${{ github.event.workflow_run.conclusion == &apos;success&apos; }}
    runs-on: ubuntu-latest

    steps:
      - name: Deploy to VPS via SSH
        uses: appleboy/ssh-action@v1.0.0
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          port: ${{ secrets.VPS_PORT }}
          script: |
            cd /root/yourprojectrepo

            # Pull Latest Code From Github
            git pull origin main

            # Pull latest image from Docker Hub
            docker compose pull

            # Stop and remove running containers
            docker compose down

            # Rebuild and start services with latest image
            docker compose up -d --remove-orphans
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Seperti sebelumnya, kode diatas adalah template workflow yang kita gunakan untuk pulling image terbaru dari docker hub ke instance VPS yang nantinya akan di run dengan docker compose.&lt;/p&gt;
&lt;h3&gt;Finishing Up&lt;/h3&gt;
&lt;p&gt;Nah akhirnya kita udah sampai ke proses terakhir, disini kita bisa coba update repo mu untuk melihat hasil build dan deployment yang udah kita buat tadi sambil lihat docker logs nya jikalau ada yang belum sesuai bisa di perbaiki kembali :)&lt;/p&gt;
&lt;p&gt;Kalau semua step udah jalan mulus, berarti kamu sekarang udah punya alur &lt;strong&gt;CI/CD sederhana&lt;/strong&gt; yang bisa dipakai bahkan di VPS dengan resource terbatas 🎉.&lt;/p&gt;
&lt;p&gt;Langkah selanjutnya, kamu bisa:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Menambahkan service lain ke dalam &lt;code&gt;docker-compose.yml&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Setup notifikasi (misalnya ke Discord/Telegram) untuk tahu kalau deploy sukses/gagal.&lt;/li&gt;
&lt;li&gt;Optimasi Docker image supaya lebih kecil dan cepat ditarik di server.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Dengan cara ini, kamu nggak perlu lagi build langsung di VPS, cukup push code ke GitHub dan biarkan workflow yang urus deploymentmu :)&lt;/p&gt;
&lt;p&gt;Akhir kata, Jikalau ada kesalahan atau ada yang ingin di tanyakan pada blog ini jangan ragu untuk menghubungi ku via dm di social media yang udah ku tampilkan, sekian :)&lt;/p&gt;
</content:encoded></item></channel></rss>