Membangun CI/CD untuk RESTful Web Service berbasis Lumen (Laravel) di AWS

Ridwan Fajar
Serverless Indonesia
12 min readMay 19, 2020
Pembangkit Listrik Tenaga Geotermal Kamojang, Perbatasan Kabupaten Bandung dan Kabupaten Garut, Jawa Barat, Indonesia

Pendahuluan

Code Build merupakan sarana yang disediakan oleh Amazon Web Service untuk membuat sebuah lingkungan yang cocok untuk aplikasi Anda ketika melakukan proses building menjadi deliverable software.

Source code yang ditulis oleh rekan — rekan developer pastilah masih dalam bentuk mentah yang belum di-compile ataupun belum dibersihkan dari file — file yang tidak diperlukan saat deployment nanti. Selain itu, deliverable pun mestilah diuji terlebih dahulu sebelum digabungkan dengan code base yang sudah berjalan di lingkungan produksi.

Code Build merupakan komponen utama dari Code Pipeline nantinya. Code Pipeline sendiri adalah sebuah sistem otomasi yang akan menerima deliverable dari repository aplikasi Anda (berupa commit) kemudian akan memacu Code Build untuk melakukan proses building. Bila lolos tahap testing maka deliverable tersebut dapat di-deploy otomatis ke platform yang digunakan. Platform tersebut dapat berupa Elastic Beanstalk, S3 Bucket, ECR, EC2, dan lain — lain. Code Pipeline sendiri dapat memiliki beberapa stage seperti source, build dan deploy.

Sebagai gambaran, berikut adalah contoh cara pembuatan proyek Code Build dan Code Pipeline untuk aplikasi web PHP.

A.1. Code Build

A.1.1. Membuat Code Build untuk aplikasi web PHP

Untuk memulainya, silahkan cari “Code Build” di pencarian layanan AWS. Setelah itu, Anda akan dibawa ke halaman seperti pada gambar berikut.

Ilustrasi 1 — Halaman utama Code Build

Disana terdapat tombol “Create Build Project” yang dapat ditekan untuk mulai membuat proyek baru Code Build. Selanjutnya, Anda akan dibawa ke halaman pembuatan proyek Code Build seperti pada gambar berikut.

Ilustrasi 2 — konfigurasi utama proyek Code Build

Pada gambar diatas, Anda dapat menentukan proyek Code Build yang akan dibuat. Misal pada ilustrasi diatas, proyek Code Build bernama cicd-api. Anda juga dapat menyertakan deskripsi bila diperlukan. Kalau sangat suka dengan menyediakan build badge dapat Anda centang agar nantinya tampil di halaman repository aplikasi Anda.

A.1.2. Menentukan repository dari proyek aplikasi

Misal ada sebuah repository bernama “cicd-api” dari user “ridwanbejo” di Github. Repository tersebut dapat dibidik oleh Code Build sebagai sumber kode yang akan dijadikan target oleh sarana ini.

Di tahap kedua, Anda dapat memilih “Source Provider” untuk Code Build. Provider yang dapat dipilih diantaranya AWS Code Commit, Github dan lainnya. Sebagai ilustrasi, kita akan coba memilih Github sebagai provider, kemudian Anda harus menghubungkan dulu akun Github kita dengan Code Build melalui mekanisme OAuth.

Pilih menu “Connect using OAuth”, kemudian tekan tombol “Connect to Github”.

Ilustrasi 3— memilih source provider Github sebagai target Code Build

Kemudian akan muncul pop up seperti pada gambar berikut. Selanjutnya tekan saja tombol “Confirm”.

Ilustrasi 4— proses konfimasi autentikasi OAuth ke Github

Setelah berhasil terhubung dengan Github, pilihan di “Repository” akan berubah menjadi “Public repository” atau “Repository in my Github account”. Misal kita kan memilih “Public Repository”, kemudian tinggal diisi saja “Repository URL” yang diinginkan.

Seperti yang dijelaskan sebelumnya, kita asumsikan ada sebuah repository dengan URL https://github.com/ridwanbejo/aws-cicd-api-demo. Kita coba gunakan repository tersebut. Selanjutnya pilih branch yang akan menjadi target Code Build. Pada gambar, branch development dipilih sebagai target.

Ilustrasi 5 — memilih repository dari Github yang akan menjadi target proyek Code Build

A.1.3. Menentukan environment saat build time

Untuk bagian ini, bisa disebut sebagai bagian paling menarik. Karena Anda dapat menggunakan image yang disediakan oleh Code Build sendiri, atau menggunakan image Docker yang sudah Anda buat sebelumnya untuk dijadikan lingkungan saat proses building.

Namun sebagai ilustrasi, kita pilih saja dahulu “Managed Image” dengan sistem operasi Ubuntu yang mengunakan runtime “Standard”.

Kemudian image yang digunakan adalah aws/codebuild/standard:1.0 dan versi yang digunakan adalah latest.

Ilustrasi 6— memilih environment untuk proses building aplikasi

Selanjutnya kita pilih “Environment Type” Linux sebagai lanjutan dari pemilihan environment. Lalu “Service Role” yang akan digunakan dapat menggunakan role yang sudah ada atau membuat yang baru.

Ilustrasi 7— form lanjutan menentukan environment

Misal untuk role, kita buat baru dengan nama codebuild-cicd-api-service-role . Nantinya role ini akan terbuat otomatis dan didaftarkan di IAM Roles.

Sebagai gambaran, bila ada perintah AWS CLI khusus yang disertakan saat proses building, Anda harus menambahkan permission tertentu ke role untuk Code Build tersebut agar proses building tidak mengalami gangguan seperti exit status 225 .

Ilustrasi 8 — service role baru untuk proyek Code Build yang akan dibuat

A.1.4. Menentukan buildspec

Lalu dilanjutkan dengan menentukan buildspec, yaitu sebuah file yang berisi sejumlah perintah untuk dieksekusi selama proses building di dalam Code Build. Format yang digunakan adalah YAML (Yet Another Markup Language) dengan ekstensi .yml yang secara resmi didukung oleh Code Build sendiri.

Ilustrasi 9— menentukan buildspec file dan artifacts

Namun di tutorial ini, kita akan membuat file buildspec.yml sendiri dari dalam proyek yang akan kita buat di bagian selanjutnya. Berikut adalah contoh snippet dari buildspec.yml yang nantinya akan dibaca oleh Code Build saat proses building:

version: 0.2phases:
pre_build:
commands:
- echo Starting code build ...
- curl -s https://getcomposer.org/installer | php
- mv composer.phar /usr/local/bin/composer
- echo Downloading dependencies ...
- composer --version
- composer install
- cp .env.example .env
- php artisan key:generate

build:
commands:
- echo Run unit testing ...
- vendor/bin/phpunit
post_build:
commands:
- echo Build completed on `date`

Untuk artifacts sendiri, dapat Anda tentukan apakah ingin menyimpan hasil build di S3 atau di tempat lain yang Anda inginkan.

A.1.5. Konfigurasi sistem log

Untuk konfigurasi sistem log, Code Build mendukung Cloud Watch sebagai sarana penyimpanan log yang berisi pesan — pesan saat proses building. Hal itu tentu dapat berguna untuk proses inspeksi saat terjadi kegagalan pada waktu building aplikasi Anda.

Ilustrasi 10 — konfigurasi pengiriman log untuk proyek Code Build ke Cloud Watch

Pada gambar diatas, kita coba memberikan nama untuk “Group Name” dan “Stream Name” di Cloud Watch.

Untuk mengakhiri fase ini, Anda dapat menekan tombol “Create Build Project” yang akan memindahkan Anda ke halaman detail proyek Code Build.

A.1.6. Melihat proyek Code Build yang berhasil dibuat

Setelah selesai dengan konfigurasi yang lengkap dan cukup panjang, sampailah kita pada halaman detail proyek Code Build.

Ilustrasi 11 — Contoh halaman proyek Code Build yang berhasil dibuat dengan nama cicd-api

Di halaman tersebut, Anda dapat melihat tombol “Edit” dan “Delete build project”. Juga dapat melakukan proses building secara manual dengan tombol “Start Build”. Atau nantinya, Anda pun dapat melihat rekam jejak proses building bila sudah melakukan beberapa kali percobaan.

Sebagai ilustrasi apa yang akan muncul di halaman detail Code Build saat Code Pipeline berhasil dijalankan. Anda akan melihat sejumlah history proses building di halaman tersebut. Baik proses building yang sukses maupun yang gagal.

Ilustrasi 12— contoh build history yang terdapat di halaman detail proyek Code Build

B. Code Pipeline

B.1.1. Membuat Code Pipeline untuk aplikasi web PHP

Untuk membuat Code Pipeline, silahkan buka halaman Code Pipeline melalui pencarian service AWS. Di sana Anda dapat melihat welcome page dan ada tombol “Create Pipeline” disebelah kanan halaman seperti pada ilustrasi 13. Dengan menekan tombol tersebut, Anda dapat memulai pembuatan Code Pipeline.

Ilustrasi 13 — memulai pembuatan Code Pipeline

Ada lima tahap dalam pembuatan AWS Code Pipeline yaitu:

  1. Pipeline settings
  2. Source stage
  3. Build stage
  4. Deploy stage
  5. Review

Di tahapan pertama ini, Anda diminta untuk mengisi nama pipeline yang akan dibuat. Kemudian Anda juga akan ditanya apakah ingin membuat service role baru atau menggunakan yang sudah pernah dibuat sebelumnya. Role name pun akan dibantu oleh form dengan membuatkan nama service role secara otomatis.

Ilustrasi 14 — Pengaturan utama Code Pipeline

Kemudian ada bagian “Advance Settings” tapi dapat Anda abaikan bila tidak memerlukannya. Bila dirasa sudah yakin dengan tahap pertama, kita dapat lanjutkan dengan menekan tombol “Next”.

Ilustrasi 15 — Lanjut ke tahap source

Bila ingin mengurungkan pembuatan Code Pipeline, Anda dapat menekan tombol “Cancel”.

B.1.2. Konfigurasi tahap source

Di tahap ini Anda dapat memilih source provider yang Anda gunakan. Bisa AWS CodeCommit, Github atau lainnya. Namun di dalam ilustrasi, Github dipilih sebagai source provider. Kemudian kita harus menghubungkan Github dengan Code Pipeline melalui tombol “Connect to Github”. Event yang digunakan untuk trigger pun adalah GitHub Webhook. Ketika nanti ada commit baru ke branch yang menjadi target Code Pipeline, maka pipeline pun akan berjalan.

Ilustrasi 16 — Memilih source proyek untuk Code Pipeline

Di ilustrasi 16, kita hanya baru memilih source provider. Setelah Github dan Code Pipeline terhubung, kita dapat memilih repository yang diinginkan dan branch yang akan menjadi target Code Pipeline.

Ilustrasi 17 — Memilih repo dan branch yang akan dijadikan target Code Pipeline

Bila sudah yakin dengan tahap dua, mari kita maju ke tahap tiga dengan menekan tombol “Next”.

B.1.3. Konfigurasi tahap build

Di tahap ini, Anda dapat menentukan build provider. Anda dapat memilih Jenkins atau AWS Code Build. Tapi kita akan pilih AWS Code Build. Kemudian pilih region yang digunakan oleh Code Build. Lalu pilih nama proyek Code Build yang akan digunakan. Misal kita gunakan cicd-api sebagai proyek Code Build yang sudah dibuat di bagian A.

Ilustrasi 18 — Memilih proyek Code Build yang telah dibuat untuk Code Pipeline

Bila tidak ada yang terlewat, kita bisa tekan tombol “Next” untuk maju ke langkah berikutnya.

B.1.4. Konfigurasi tahap deploy

Di tahap deploy, Anda dapat memilih deploy provider dapat berupa Elastic Beanstalk, S3, EC2 atau lainnya. Namun kali ini kita coba Elastic Beanstalk untuk target deployment (Untuk melihat gambaran bagaimana membuat aplikasi Elastic Beanstalk di AWS, Anda dapat mengunjungi artikel “Deploy Aplikasi Web PHP di AWS Elastic Beanstalk”).

Misal dalam tahap ini, Elastic Beanstalk sudah dibuat terlebih dahulu dengan application namecicd-api-app dan environment name CicdApiApp-env . Aplikasi Elastic Beanstalk tersebut berada di us-east-1 .

Ilustrasi 19 — memilih aplikasi dan environment Elastic Beanstalk yang akan menjadi target deploy dari Code Pipeline

Bila tidak ada yang terlewat mari melangkah ke tahap terakhir dengan menekan tombol “Next”.

B.1.5. Tahap Review

Di tahap terakhir ini, Anda hanya akan diperlihatkan setiap value yang sudah diisikan di form — form sebelumnya. Mulai dari tahap pertama.

Ilustrasi 20 — review untuk pipeline settings

Kemudian ada informasi yang diisikan pada tahap kedua.

Ilustrasi 21 — review untuk tahap source

Kemudian ada informasi yang diisikan pada tahap ketiga.

Ilustrasi 22 — review untuk tahap build

Dan terakhir ada informasi yang diisikan pada tahap keempat.

Ilustrasi 23 — review untuk tahap deploy

Bila sudah benar — benar yakin, Anda dapat menekan tombol “Create Pipeline”. Bila masih ada keraguan, dapat kembali lagi dengan menekan tombol “Previous”.

Ilustrasi 24 — Code Pipeline berhasil dibuat

Bila berhasil, Code Pipeline dengan nama cicd-api-pipeline akan terbuat seperti pada Ilustrasi 24. Dan seketika setelah dibuat, Code Pipeline akan langsung menjalankan setiap tahapannya mulai dari source, build, kemudian deploy.

C. Menguji Code Pipeline yang telah dibuat

Sebelum maju ke pembahasan selanjutnya, ada sedikit gambaran mengenai beberapa bagian source code yang akan dilibatkan dalam Code Pipeline di dalam proyek aplikasi web PHP yang menjadi target Code Pipeline, yaitu ridwanbejo/aws-cicd-api-demo. Mulai dari routes/web.php:

<?phpuse Illuminate\Support\Facades\Storage;$router->get('/', function () use ($router) {
return $router->app->version();
});
$router->get('/demo', function () use ($router) {
return response()->json(['name' => 'Abigail', 'state' => 'CA']);
});
$router->get('/pokemon', function () use ($router) {

$vals = explode("\n", Storage::disk('local')->get('pokemon.csv'));
$pokemons = [];
$num = 0;
foreach($vals as $data) {
$data = explode(",", $data);if (count($data) == 1){
continue;
}
if ($data[1] == "Name"){
continue;
}
/*
0: "No."
1: "Name"
2: "Type 1"
3: "Type 2"
4: "Total"
5: "HP"
6: "Attack"
7: "Defense"
8: "Sp. Atk"
9: "Sp. Def"
10: "Speed"
11: "Generation"
12: "Legendary"
*/
$pokemon = [
"No." => $num,
"Name" => $data[1],
"Type 1" => $data[2],
"Type 2" => $data[3],
"Total" => $data[4],
"HP" => $data[5],
"Attack" => $data[6],
"Defense" => $data[7],
"Sp. Atk" => $data[8],
"Sp. Def" => $data[9],
"Speed" => $data[10],
"Generation" => $data[11],
"Legendary" => $data[12]
];
array_push($pokemons, $pokemon);
$num++;
}
return response()->json($pokemons);
});

Pada snippet diatas terdapat tiga endpoint yaitu:

  • /
  • /demo
  • /pokemon

Untuk endpoint pertama dan kedua hanya mengirimkan response tanpa melibatkan proses I/O. Sedangkan endpoint /pokemon melibatkan pembacaan file CSV yang berisi data Pokemon. File tersebut disimpan di storage/public di dalam proyek aplikasi.

Dan file yang berlokasi di tests/ExampleTest.php. File tersebut berisi sejumlah test cases yang akan dijalankan selama proses build berlangsung:

<?phpuse Laravel\Lumen\Testing\DatabaseMigrations;
use Laravel\Lumen\Testing\DatabaseTransactions;
class ExampleTest extends TestCase
{
/**
* A basic test example.
*
* @return void
*/
public function testExample()
{
$this->get('/');
$this->assertEquals(
$this->app->version(), $this->response->getContent()
);
}
/**
* A basic test demo endpoint.
*
* @return void
*/
public function testDemo()
{
$response = $this->call('GET', '/demo');
$this->assertEquals(200, $response->status());

$response_json = $this->json('GET', '/demo');
$response_json->seeJson(['name' => 'Abigail', 'state' => 'CA']);
}/**
* A basic test pokemon endpoint.
*
* @return void
*/
public function testPokemon()
{
$response = $this->call('GET', '/pokemon');
$this->assertEquals(200, $response->status());
}
}

Kedua file diatas akan kita edit untuk menguji Code Pipeline yang telah dibuat.

C.1. Deployment awal

Misal di ilustrasi 24, commit terakhir adalah fix buildspec 16:43 di branch development. Di awal deployment begitu Code Pipeline berhasil dibuat, commit terakhir tersebut akan dijadikan starting point untuk tahap build. Anda dapat menunggu sampai semua tahapan selesai dijalankan. Bila tahap build dan stage berhasil dibuat, aplikasi web PHP akan di-deploy ke Elastic Beanstalk.

Kurang lebih setelah deployment tahap awal, aplikasi web dapat diakses seperti pada gambar berikut:

Ilustrasi 25 — root endpoint aplikasi web PHP yang di deploy dengan Code Pipeline
Ilustrasi 26 — endpoint demo aplikasi web PHP yang di deploy dengan Code Pipeline
Ilustrasi 27 — endpoint pokemon aplikasi web PHP yang di deploy dengan Code Pipeline

Sekarang mari kita maju ke bagian selanjutnya untuk mencoba membuat endpoint baru.

C.2. Membuat endpoint baru

Di bagian ini kita akan menambahkan endpoint baru di routes/web.php :

...$router->get('/check-beanstalk', function () use ($router) {
return response()->json(['name' => 'Elastic Beanstalk', 'region' => 'us-east-1']);
});

Kemudian kita coba tambahkan test case baru di dalam tests/ExampleTest.php:

...    public function testCheckBeanstalk()
{
$response = $this->call('GET', '/check-beanstalk');
$this->assertEquals(200, $response->status());
}
}

Kemudian kita simpan perubahan tersebut dengan Git dan push commit tersebut ke repository:

$ git add .
$ git commit -m 'add check-beanstalk endpoint and new test case for it'
$ git push origin development

Begitu proses push commit selesai dilakukan. Selang beberapa detik kemudian, Code Pipeline akan menerima event berupa webhook terhadap repository yang kita jadikan target Code Pipeline dari branch development. Kemudian setelah diverifikasi oleh tahap source, tahap build akan melakukan tugasnya untuk menjalankan Code Build yang sudah didefinisikan, yaitu cicd-api.

Sampai proses build selesai dan lolos testing berdasarkan test cases yang sudah disusun, proses selanjutnya adalah tahap deploy. Dimana artifak baru akan dibuat di AWS S3 dan di-deploy ke Elastic Beanstalk cicd-api-app.

Ilustrasi 28 — tahapan Code Pipeline untuk endpoint baru

Bila proses build dan testing berhasil maka endpoint baru dapat diakses melalui URL http://cicdapiapp-env.eba-6mnmqsmk.us-east-1.elasticbeanstalk.com/public/index.php/check-beanstalk . Seperti pada gambar berikut:

Ilustrasi 29 — endpoint baru berhasil melalui tahapan di Code Pipeline dan dapat diakses dari Elastic Beanstalk

Sebagai tambahan, Anda dapat melihat detail proses build dan testing di halaman detail proyek Code Build cicd-api seperti pada gambar — gambar berikut ini:

Ilustrasi 30 — Detail log dari proses build dan testing di proyek Code Build yang digunakan oleh Code Pipeline
Ilustrasi 31 — urutan history proses build dari cicd-api saat menerima permintaan build and test dari Code Pipeline

C.3. Mengubah struktur respon endpoint Pokemon

Sekarang mari kita ubah struktur endpoint /pokemon yang berada di routes/web.php dengan mengubah kata Sp. menjadi Special untuk dua key yang ada di dalam struktur data Pokemon. Kurang lebih seperti pada snippet dibawah ini:

....

$pokemon = [
"No." => $num,
"Name" => $data[1],
"Type 1" => $data[2],
"Type 2" => $data[3],
"Total" => $data[4],
"HP" => $data[5],
"Attack" => $data[6],
"Defense" => $data[7],
"Special Atk" => $data[8],
"Special Def" => $data[9],
"Speed" => $data[10],
"Generation" => $data[11],
"Legendary" => $data[12]
];
array_push($pokemons, $pokemon);
$num++;
}
....

Kemudian kita kirim perubahan baru tersebut sebagai commit baru. Kira — kira perintah yang harus dieksekusi di console adalah seperti berikut:

$ git add .
$ git commit -m 'change Sp. to Special in pokemon endpoint'
$ git push origin development

Begitu commit di-push, maka Code Pipeline akan merespon perubahan tersebut dimulai dari tahap source. Kemudian dilanjutkan ke tahap build dan deploy.

Ilustrasi 32 — tahap build saat menerima commit “change Sp. to Special in pokemon endpoint”

Seperti pada ilustrasi 32, begitu tahap build berjalan berikutnya tahap deploy akan dieksekusi seperti pada ilustrasi 33.

Ilustrasi 33— tahap deploy saat menerima commit “change Sp. to Special in pokemon endpoint”

Sampai akhirnya, perubahan pun sudah live di Elastic Beanstalk untuk endpoint /pokemon .

Ilustrasi 323 — commit “change Sp. to Special in pokemon endpoint” berhasil di deploy ke Elastic Beanstalk cicd-api-app

Selamat! Anda sudah berada di akhir perjalanan panjang ini. Kira — kira seperti itulah cara kerja Code Build dan Code Pipeline yang paling dasar.

Kesimpulan

Code Build merupakan sarana yang disediakan AWS untuk mendukung sistem CI/CD yang akan Anda bangun. Di dalamnya terdapat sejumlah fitur lengkap seperti environment yang dapat disesuaikan dengan keinginan Anda.

Sumber kode yang dapat dipilih pun cukup beragam mulai dari Github sampai AWS Code Commit sendiri. Code Build ini akan berjalan lebih efektif saat diintegrasikan dengan Code Pipeline.

Code Pipeline sendiri membantu developer untuk membuat sejumlah otomatisasi saat mengirim deliverable dan mengujinya ke environment yang mereka tuju.

Terima kasih kepada Fajri Abdillah yang telah berkenan meminjamkan akun AWS-nya untuk keperluan artikel ini dan membantu review artikel ini.

--

--