Membuat CI/CD Workflow Menggunakan GitHub Action dan Deployer pada Framework Laravel
Tags: laravel, programming, devops
Published: 2024-06-02 14:02:12


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xta0703qrmunhelau1sd.png)

CI/CD adalah _abbreviation_ atau akronim dari _Continuous Integration/Continuous Deployment_ yang merupakan proses distribusi kode dari local development ke repository kemudian dilanjutkan ke server production yang dilakukan secara otomatis. Pastinya dengan metode CI/CD ini para developer akan terbantu sekali dalam distribusi kode program ke server production yang siap digunakan oleh pengguna.

Bicara masalah apa saja yang kita butuhkan ketika membuat CI/CD workflow ini. Pastikan temen-temen mengenal terlebih dahulu dari Deployer yang akan kita gunakan kali ini. Deployer merupakan tools yang digunakan untuk bahasa pemrograman PHP dalam melakukan distribusi kode dengan menggunakan metode CI/CD. Enaknya pakai deployer ini kita bisa mendistribusikan kode program kita kapan pun dan dimanapun. Selain itu, kita juga bisa melakukan rollback version apabila terdapat kesalahan ketika melakukan proses CI/CD.

### Persyaratan

- [PHP 7.4 atau lebih](https://www.php.net/)
- [Laravel 8 atau lebih](https://www.laravel.com/)
- [Deployer](https://deployer.org/)

### Instalasi Deployer

Jalankan perintah berikut untuk melakukan instalasi package Deployer pada projek Laravel

```bash
composer require --dev deployer/deployer
```

Lakukan inisialisasi deployer menggunakan perintah berikut

```bash
vendor/bin/dep init
```

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v673x2bj16wqsa1owyhf.png)

Kemudian pilih [0] php karena kita akan melakukan konfigurasi menggunakan php nantinya.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5dczmxah29mqxg9pxbvh.png)

Lalu pilih [11] Laravel karena kita menggunakan Laravel Framework.

---

### Konfigurasi Deployer
Ubah file deployer.php pada root project dari Laravel menjadi seperti ini :

```php
<?php
namespace Deployer;

require 'recipe/laravel.php';
require 'contrib/npm.php';

set('bin/php', function () {
    return '/usr/local/bin/php'; // change
});

// HARUS DIGANTI SESUAI KEBUTUHAN ANDA
set('application', 'Nama Aplikasi'); 
set('repository', 'SSH_GIT_CLONE'); // Git Repository contoh set('repository', 'git@github.com:yogameleniawan/laravel-cicd-deployer.git');
// HARUS DIGANTI SESUAI KEBUTUHAN ANDA

set('git_tty', true);
set('git_ssh_command', 'ssh -o StrictHostKeyChecking=no');

set('keep_releases', 5);

set('writable_mode', 'chmod'); // jika menggunakan shared hosting tuliskan baris kode ini

// Shared files/dirs between deploys
add('shared_files', ['.env']);
add('shared_dirs', ['storage']);

// Writable dirs by web server
add('writable_dirs', [
    "bootstrap/cache",
    "storage",
    "storage/app",
    "storage/framework",
    "storage/logs",
]);

set('composer_options', '--verbose --prefer-dist --no-progress --no-interaction --no-dev --optimize-autoloader');

// Hosts

// HARUS DIGANTI SESUAI KEBUTUHAN ANDA

host('NAMA_REMOTE_HOST') // Nama remote host server ssh anda | contoh host('NAMA_REMOTE_HOST')
->setHostname('NAMA_HOSTNAME_ATAU_IP') // Hostname atau IP address server anda | contoh  ->setHostname('10.10.10.1') 
->set('remote_user', 'USER_SSH') // SSH user server anda | contoh ->set('remote_user', 'u1234567')
->set('port', 65002) // SSH port server anda, untuk kasus ini server yang saya gunakan menggunakan port custom | contoh ->set('remote_user', 65002)
->set('branch', 'master') // Git branch anda
->set('deploy_path', '~/PATH/SUB_PATH'); // Lokasi untuk menyimpan projek laravel pada server | contoh ->set('deploy_path', '~/public_html/api-deploy');

// HARUS DIGANTI SESUAI KEBUTUHAN ANDA

// Tasks

task('deploy:secrets', function () {
    file_put_contents(__DIR__ . '/.env', getenv('DOT_ENV'));
    upload('.env', get('deploy_path') . '/shared');
});

desc('Build assets');
task('deploy:build', [
    'npm:install',
]);

task('deploy', [
    'deploy:prepare',
    'deploy:secrets',       
    'deploy:vendors',
    'deploy:shared',
    'artisan:storage:link',
    'artisan:queue:restart',
    'deploy:publish',
    'deploy:unlock',
]);

// [Optional] jika deploy gagal maka deployer akan otomatis melakukan unlock
after('deploy:failed', 'deploy:unlock');

// uncomment baris kode dibawah jika ingin melakukan migrate database sebelum dilakukan symlink folder

// before('deploy:symlink', 'artisan:migrate');
```

Perlu diperhatikan pada kode program berikut :

```php
// HARUS DIGANTI SESUAI KEBUTUHAN ANDA

host('NAMA_REMOTE_HOST') // Nama remote host server ssh anda | contoh host('NAMA_REMOTE_HOST')
->setHostname('NAMA_HOSTNAME_ATAU_IP') // Hostname atau IP address server anda | contoh  ->setHostname('10.10.10.1') 
->set('remote_user', 'USER_SSH') // SSH user server anda | contoh ->set('remote_user', 'u1234567')
->set('port', 65002) // SSH port server anda, untuk kasus ini server yang saya gunakan menggunakan port custom | contoh ->set('remote_user', 65002)
->set('branch', 'master') // Git branch anda
->set('deploy_path', '~/PATH/SUB_PATH'); // Lokasi untuk menyimpan projek laravel pada server | contoh ->set('deploy_path', '~/public_html/api-deploy');

// HARUS DIGANTI SESUAI KEBUTUHAN ANDA
```

Contoh penyesuaian pada Server temen-temen :

```php
host('ServerProduction')
->setHostname('10.10.10.1') // Hostname atau IP address server anda | contoh  ->setHostname('10.10.10.1') 
->set('remote_user', 'u1234567') // SSH user server anda | contoh ->set('remote_user', 'u1234567')
->set('port', 65002) // SSH port server anda, untuk kasus ini server yang saya gunakan menggunakan port custom | contoh ->set('remote_user', 65002)
->set('branch', 'master') // Git branch anda
->set('deploy_path', '~/public_html/api-deploy'); // Lokasi untuk menyimpan projek laravel laravel pada server | contoh ->set('deploy_path', '~/public_html/api-deploy');
```

---

### Membuat GitHub Workflow
Jalankan perintah berikut pada Terminal :

```bash
touch .github/workflows/master.yml
```

> catatan: master.yml merupakan branch yang akan kita gunakan untuk melakukan CI/CD workflow. Jadi ketika ada pembaruan kode pada branch ini maka akan menjalankan proses CI/CD. Jadi silahkan sesuaikan branch yang ingin temen-temen gunakan tidak harus master. Tapi saya sangat menyarankan silahkan buat branch master untuk mengikuti yang ada pada artikel ini.

Silahkan ubah isi master.yml dengan kode berikut :

```yaml
on:
  push:
    branches:
      - master (sesuaikan dengan branch yang digunakan)

jobs:
  build-js-production:
    name: Build JavaScript/CSS for Production Server
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/master' (sesuaikan dengan branch yang digunakan)
    steps:
      - uses: actions/checkout@v1
      - name: NPM Build
        run: |
          npm install
          npm run build
      - name: Put built assets in Artifacts
        uses: actions/upload-artifact@v1
        with:
          name: assets
          path: public
          retention-days: 3
  deploy-production:
    name: Deploy Project to Production Server
    runs-on: ubuntu-latest
    needs: [ build-js-production ]
    if: github.ref == 'refs/heads/master' (sesuaikan dengan branch yang digunakan)
    steps:
      - uses: actions/checkout@v1
      - name: Fetch built assets from Artifacts
        uses: actions/download-artifact@v1
        with:
          name: assets
          path: public
      - name: Setup PHP
        uses: shivammathur/setup-php@master
        with:
          php-version: '8.0'
          extension-csv: mbstring, bcmath
      - name: Composer install
        run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
      - name: Setup Deployer
        uses: atymic/deployer-php-action@master
        with:
          ssh-private-key: ${{ secrets.SSH_PRIVATE_KEY }}
          ssh-known-hosts: ${{ secrets.SSH_KNOWN_HOSTS }}
      - name: Deploy to Development
        env:
          DOT_ENV: ${{ secrets.DOT_ENV_PRODUCTION }}
        run: php vendor/bin/dep deploy ServerProduction branch=master (sesuaikan dengan branch yang digunakan)
```

> Jika temen-temen tidak menggunakan branch master, silahkan disesuaikan dengan branch yang temen-temen gunakan.

pada baris kode berikut :

```yaml
run: php vendor/bin/dep deploy ServerProduction branch=master (sesuaikan dengan branch yang digunakan)
```

**ServerProduction** ini akan mengeksekusi host yang sudah kita definisikan pada file deployer.php sebelumnya.

**branch=master** merupakan branch yang digunakan temen-temen.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4lwbtpok8x4gag1v5n0k.png)

---

### Menambahkan GitHub Action Credential
Buka repository github kemudian pilih Settings :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sibwgyzdby1yu2lc5g3v.png)

Lalu pilih Secrets and variables - Actions

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4i4c1j9uz8huumstwsri.png)

Lalu tambahkan variabel secret baru

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cn3nxnud9lc2lmjkp211.png)

Buat SSH_PRIVATE_KEY

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5s1xvpwbzdvktselglkh.png)

Untuk mendapatkan SSH Private Key bisa menggunakan cara berikut :

- Buka **Terminal Server** bukan **Terminal Lokal** (Laptop/PC). Atau temen-temen bisa akses server temen-temen menggunakan SSH.
- Lalu jalankan perintah berikut :

```bash
ssh-keygen -t ed25519 -C "email_anda@example.com"
```

- Jika muncul tulisan "Enter a file in which to save the key," press Enter. Tekan enter saja sampai selesai.
- Lalu jalankan perintah berikut :

```bash
cat ~/.ssh/id_ed25519
```

Setelah itu akan muncul SSH Private Key seperti ini silahkan di-copy semua

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yxs9489yw6qjcl7qgz2t.png)

Lalu Pastekan pada **SSH_PRIVATE_KEY** action secrets yang akan temen-temen buat tadi. Lalu **Add Secret**


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5k4afgi32i0bdqhlq5y1.png)

Buat variabel **SSH_KNOWN_HOSTS**

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y3q8l15hgysvaor84q9j.png)

Untuk mendapatkan **SSH Known Hosts** bisa menggunakan cara berikut :

- Buka **Terminal Server** bukan **Terminal Lokal** (Laptop/PC). Atau temen-temen bisa akses server temen-temen menggunakan SSH.
- Lalu jalankan perintah berikut :

```bash
ssh-keyscan -p 65002 IP_SERVER_ANDA
```

Kemudian copy dan isikan pada Secret Action yang temen-temen akan buat tadi.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t8bx5z5r3z5mld4ppr2d.png)

Buat variabel **DOT_ENV_PRODUCTION**.

- Silahkan copy semua isi file .env

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gb67jic917qihsbjk2ok.png)

- Kemudian isikan pada Actions Secrets seperti ini :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a144w5w4ljxjc213p79u.png)

---

### Menjalankan Proses CI/CD Workflow

Silahkan melakukan perubahan atau git push pada repository anda maka Github Actions dan Deployer akan berjalan sebagaimana mestinya.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/on4kucqtabzxi0pi738p.png)

Ketika kode berhasil didistribusikan maka pada direktori server hosting akan seperti ini :

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nycr54jr133gtbds169a.png)

### Penutupan
Kurang lebih pembuatan CI/CD Workflow menggunakan GitHub Action dengan dikombinasikan menggunakan Deployer pada Framework Laravel seperti itu ya temen-temen. Semoga bertemu di lain kesempatan dengan artikel yang berbeda.