Build: Tahap di Mana Kode Berubah Menjadi Sesuatu yang Dapat Dijalankan

Kamu baru saja mendorong perubahan terbaru. Pipeline mengambilnya, melakukan checkout kode, dan menyiapkan lingkungan. Lalu apa? Langkah selanjutnya adalah memastikan bahwa kode tersebut benar-benar bisa dijalankan di suatu tempat. Itulah tahap build.

Banyak orang yang baru mengenal pipeline mengira build hanyalah kompilasi. Jika kamu menulis Java, kamu mengompilasi ke bytecode. Jika kamu menulis Go, kamu mengompilasi ke binary. Itu memang bagian dari build, tetapi build sebenarnya lebih luas dari itu. Setiap jenis pekerjaan dalam pengiriman perangkat lunak membutuhkan langkah build, meskipun outputnya bukan file biner.

Apa Arti Build Sebenarnya

Kode yang ditulis developer biasanya belum siap dijalankan di server. Kode perlu diubah menjadi sesuatu yang bisa dieksekusi oleh sistem target. Untuk aplikasi Java, itu berarti mengompilasi kode sumber menjadi bytecode dan mengemasnya ke dalam file JAR atau WAR. Untuk aplikasi Node.js, build mungkin berarti menjalankan bundler, minifier, atau transpiler agar kode siap produksi. Untuk aplikasi Go, build berarti mengompilasi menjadi binary mandiri.

Namun build tidak hanya untuk kode aplikasi. Database juga membutuhkan langkah build. Kode SQL, stored procedure, dan skema database perlu dikompilasi atau divalidasi. Outputnya bukan binary, melainkan sekumpulan file migrasi yang siap dijalankan terhadap database target dalam urutan yang benar. Build untuk database biasanya menghasilkan perintah SQL yang telah terverifikasi, diperiksa kesalahan sintaks, dan diurutkan dependensinya.

Berikut adalah contoh bagaimana tahap build terlihat dalam konfigurasi pipeline untuk dua tipe aplikasi umum:

build-nodejs:
  stage: build
  script:
    - npm ci
    - npm run build
  artifacts:
    paths:
      - dist/

build-go:
  stage: build
  script:
    - go build -o app .
  artifacts:
    paths:
      - app

Infrastruktur juga melalui proses build. File Terraform, template CloudFormation, dan playbook Ansible perlu diperiksa sintaksnya, divalidasi, dan terkadang dikompilasi menjadi representasi yang lebih mudah di-deploy. Output dari build infrastruktur bisa berupa file konfigurasi yang telah divalidasi, template yang diperiksa, atau bahkan image mesin yang sudah dibangun sebelumnya.

Benang merahnya adalah: build mengubah sumber menjadi sesuatu yang dapat diverifikasi dan kemudian digunakan oleh tahap-tahap selanjutnya.

Diagram di bawah ini merangkum bagaimana build mengubah berbagai jenis kode sumber menjadi artifact yang dapat dijalankan:

flowchart TD A[Kode Sumber] --> B{Tahap Build} B --> C[Aplikasi: Binary / Paket / Image Kontainer] B --> D[Database: Skrip Migrasi Terverifikasi] B --> E[Infrastruktur: Konfigurasi / Rencana Tervalidasi] C --> F[Artifact dengan Metadata] D --> F E --> F F --> G[Tahap Selanjutnya: Uji & Pindai]

Apa yang Dihasilkan oleh Build yang Baik

Build harus menghasilkan output yang dapat diperiksa. Setelah build selesai, kamu perlu mengetahui tiga hal: apakah berhasil, apa yang dihasilkan, dan apakah output sesuai dengan ekspektasi.

Output build yang terstruktur dengan baik mencakup:

  • Artifact yang siap digunakan. Ini bisa berupa binary, paket, image kontainer, atau file migrasi.
  • Catatan versi dan commit yang memicu build ini.
  • Metadata seperti hash atau checksum sehingga kamu dapat memverifikasi bahwa artifact tidak berubah selama transit.
  • Status sukses atau gagal yang jelas.

Tanpa semua ini, kamu tidak bisa mempercayai apa yang diberikan pipeline ke tahap selanjutnya.

Build Harus Dapat Diulang

Jika kamu menjalankan build yang sama dua kali dengan kode yang sama, kamu harus mendapatkan hasil yang sama. Ini disebut build deterministik. Ini penting karena jika build tidak dapat diulang, timmu tidak akan pernah yakin bahwa artifact benar-benar berasal dari kode yang kamu kira.

Build non-deterministik biasanya terjadi karena dua alasan. Pertama, build bergantung pada library eksternal yang versinya tidak dikunci. Suatu hari library diperbarui, dan tiba-tiba build-mu menghasilkan artifact yang berbeda meskipun kode tidak berubah. Kedua, build berjalan di lingkungan yang tidak konsisten. Mungkin satu agent build memiliki versi alat yang berbeda dari yang lain, atau beberapa file cache tersisa dari build sebelumnya.

Kunci dependensi kamu. Tetapkan versi alat yang digunakan. Gunakan lingkungan build yang bersih. Praktik-praktik ini membuat build-mu andal dan timmu percaya diri.

Build Adalah Gerbang Pertama

Build adalah titik pertama dalam pipeline di mana keputusan dibuat: apakah perubahan ini boleh dilanjutkan atau tidak? Jika build gagal, pipeline harus berhenti. Tidak ada gunanya menjalankan pengujian atau deploy jika artifact itu sendiri rusak.

Ini berarti build harus cepat. Developer membutuhkan umpan balik dalam hitungan menit, bukan jam. Jika build memakan waktu terlalu lama, orang berhenti menunggunya. Mereka beralih ke tugas berikutnya, dan ketika build akhirnya gagal, mereka sudah berganti konteks. Umpan baliknya putus.

Jaga agar build tetap ramping. Lakukan hanya apa yang diperlukan untuk menghasilkan artifact yang valid. Serahkan pemeriksaan yang lebih dalam ke tahap selanjutnya. Build yang berjalan di bawah lima menit memberi developer sinyal cepat yang mereka butuhkan untuk memperbaiki masalah saat kode masih segar di ingatan mereka.

Build untuk Berbagai Jenis Pekerjaan

Mari kita lihat bagaimana build bekerja untuk setiap area utama.

Aplikasi. Untuk bahasa yang dikompilasi, build berarti kompilasi dan pengemasan. Untuk bahasa yang diinterpretasi, build bisa berarti resolusi dependensi, kompilasi aset, dan bundling. Aplikasi yang dikontainerisasi menambahkan langkah tambahan: membangun image kontainer itu sendiri menjadi bagian dari tahap build.

Database. Build untuk database berarti memvalidasi sintaks SQL, memeriksa bahwa file migrasi diurutkan dengan benar, dan terkadang menjalankan dry run terhadap salinan skema. Outputnya adalah sekumpulan skrip migrasi terverifikasi yang siap dieksekusi.

Infrastruktur. Build untuk infrastruktur berarti memvalidasi file konfigurasi, memeriksa kesalahan sintaks, dan terkadang menghasilkan rencana yang menunjukkan apa yang akan berubah. Untuk alat seperti Terraform, tahap build mungkin termasuk menjalankan terraform plan untuk menghasilkan pratinjau perubahan.

Setiap jenis pekerjaan memiliki persyaratan build sendiri, tetapi prinsipnya sama: ubah sumber menjadi artifact yang terverifikasi, dapat diulang, dan dapat diserahkan ke tahap selanjutnya.

Daftar Periksa Build Cepat

Sebelum kamu menyatakan tahap build selesai, periksa poin-poin ini:

  • Build menghasilkan artifact yang dapat diverifikasi (binary, image, file migrasi, konfigurasi)
  • Build bersifat deterministik: kode yang sama, hasil yang sama, setiap saat
  • Build berjalan di bawah lima menit
  • Build gagal dengan cepat dan memberikan pesan error yang jelas
  • Output build menyertakan metadata versi, commit, dan checksum
  • Dependensi eksternal dikunci ke versi tertentu
  • Lingkungan build bersih dan konsisten di setiap eksekusi

Apa Selanjutnya

Setelah build selesai dan artifact siap, pipeline beralih ke tahap berikutnya: memeriksa apakah artifact tersebut benar-benar berfungsi dan aman untuk di-deploy. Itulah tahap uji dan pindai. Namun sebelum sampai di sana, pastikan build-mu kokoh. Tahap build yang lemah menciptakan masalah yang harus ditangani oleh setiap tahap selanjutnya.

Build bukan sekadar kompilasi. Ini adalah pemeriksaan nyata pertama bahwa kode-mu siap menjadi sesuatu yang berguna. Lakukan dengan benar, dan sisa pipeline akan memiliki fondasi yang kokoh untuk bekerja.