Membangun CI/CD untuk RESTful Web Service berbasis Lumen (Laravel) di AWS
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.
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.
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”.
Kemudian akan muncul pop up seperti pada gambar berikut. Selanjutnya tekan saja tombol “Confirm”.
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.
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.
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.
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
.
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.
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/phpunitpost_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.
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.
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.
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.
Ada lima tahap dalam pembuatan AWS Code Pipeline yaitu:
- Pipeline settings
- Source stage
- Build stage
- Deploy stage
- 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.
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”.
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.
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.
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.
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
.
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.
Kemudian ada informasi yang diisikan pada tahap kedua.
Kemudian ada informasi yang diisikan pada tahap ketiga.
Dan terakhir ada informasi yang diisikan pada tahap keempat.
Bila sudah benar — benar yakin, Anda dapat menekan tombol “Create Pipeline”. Bila masih ada keraguan, dapat kembali lagi dengan menekan tombol “Previous”.
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:
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.
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:
Sebagai tambahan, Anda dapat melihat detail proses build dan testing di halaman detail proyek Code Build cicd-api seperti pada gambar — gambar berikut ini:
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.
Seperti pada ilustrasi 32, begitu tahap build berjalan berikutnya tahap deploy akan dieksekusi seperti pada ilustrasi 33.
Sampai akhirnya, perubahan pun sudah live di Elastic Beanstalk untuk endpoint /pokemon
.
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.