Refactoring CI Configuration

Post kali ini adalah cerita pengalaman kami mengelola Jenkins dengan maksud membuat proses Continuous Integration menjadi semakin ringkas.

Kami memiliki 2 buah proses utama:

Post ini bercerita tentang optimasi proses yang pertama.

Alokasi Agen

Langkah pertama yang dilakukan ialah migrasi konfigurasi Jenkins yang berada di dalam web interface menjadi Pipeline. Dalam pengerjaannya, kita juga berusaha memperbaharui dan meremajakan proses-proses yang ada.

Sebelumnya, sebuah parent job di master node akan memicu banyak test jobs secara paralel yang akan jalan di agent node yang ditetapkan untuk tiap job tersebut. Dengan kata lain, sebuah job akan selalu mendapatkan agent dengan label yang sama.

foo-job -> foo-agent
bar-job -> bar-agent
..
baz-job -> baz-agent

Di proses yang baru, kami mencoba membuat alokasi node dinamis (parameterized). Hal ini dilakukan agar job list tidak membengkak di antarmuka Jenkins. Kami juga tidak menutup kemungkinan untuk menambah/memecah job, jadi langkah ini cukup masuk akal. Akibatnya, semua agent berlabel sama.

job(x) -> agent(x)

Alokasi dinamis ini memiliki kekurangan. Karena tiap job akan selalu berpindah-pindah agent, maka pelacakan sejarah suatu job akan menjadi sangat sulit. Ini dapat kami abaikan. Kami juga membuat informasi durasi dan tautan ke semua test jobs bisa dibaca di master job console sehingga memudahkan kunjungan ke url tiap jobs.

Optimasi

Setelah diselidiki lebih jauh ternyata kompilasi aset banyak memakan waktu, meski sudah dioptimasi agar hanya dilakukan kalau folder-folder aset berubah. Kompilasi aset adalah bagian dari setiap test job. Kami memiliki satu-dua job yang cukup lama, tetapi tidak membutuhkan aset. Proses kompilasi aset ini akhirnya diekstrak keluar menjadi job sendiri dan menyimpan hasil kompilasi lewat artifak. Hanya job yang membutuhkan aset yang akan menyalin artifak kompilasi.

Sebagai gambaran, awalnya kami menjalankan semua jobs secara paralel:

parallel jobs

Setelah kompilasi aset diekstrak keluar dan hanya dipakai oleh jobs yang membutuhkan, kofigurasi menjadi seperti:

parallel(
  'requireAssets': {
    build job: 'Assets'
    parallel jobsWithAssets
  },
  'noAssets': {
    parallel jobsWithoutAssets
  }
)

Dengan demikian, jobsWithoutAssets memiliki head start ketimbang jobsWithAssets. Dengan adanya kerangka seperti ini, mudah-mudahan durasi jobs bisa dibuat seseragam mungkin di kemudian hari since the suite is as fast as our slowest job.

Peremajaan konfigurasi juga dilakukan dengan harapan kami semua bisa mengubah, debug, dan mengoptimalkannya di masa depan. Meski demikian, perlu diingat bahwa inti dari CI ialah kemudahan agar selalu bisa memasukkan kode ke main branch. Sebisa mungkin jangan memfasilitasi hal yang membuat kita menunda/mempersulit hal tersebut.