Dari 75 menit jadi 15: cara kami merilis Atlas sekarang

Commit yang sama dites empat kali dan dibangun dua kali. Tes sekali, build dari tag, dan rilis yang merge sendiri memangkas deploy jadi 14 menit.

Membawa perubahan yang sudah selesai dari pull request yang hijau sampai production dulu makan waktu lebih dari satu jam. Di hari yang sibuk mendekati satu setengah jam, dan hampir tidak ada bagian dari waktu itu yang mengerjakan sesuatu yang baru. Minggu ini kami membangun ulang pipeline rilis untuk API Atlas, admin, dan paket layer. Rilis pertama yang lewat jalur baru, API v0.1.37, sampai di production 14 menit 23 detik setelah promosi di-merge, tanpa disentuh siapa pun di tengahnya.

Ke mana waktunya pergi

Kami mengukur satu rilis biasa langkah demi langkah. Polanya langsung kelihatan begitu ditulis: kode yang sama dites berulang-ulang.

  • CI di pull request fitur, sekitar sepuluh menit. Ini memang perlu.
  • CI lagi saat push ke dev, untuk commit yang sama.
  • CI lagi di promosi dev ke main, dua kali, karena run push dan run pull request sama-sama jalan.
  • CI lagi di pull request rilis, yang isinya cuma mengubah version.txt dan changelog. CI-nya juga tidak pernah jalan sendiri: release-please membukanya dengan token bawaan, dan pull request yang dibuat begitu tidak memicu workflow, jadi seseorang harus push commit kosong untuk membangunkannya.
  • Job tes di dalam build image, dan build image di setiap push ke main, jadi promosi dan rilis masing-masing membangun image.
  • Rector, pemeriksa upgrade PHP kami, timeout di runner bersama dengan pesan "some parallel jobs have not finished". Setiap kali kena, butuh rerun sepuluh menit lagi. Dalam satu sore saja kena tiga kali.

Tes sekali

Sebuah commit sekarang dites di pull request-nya dan saat push ke dev, tidak di tempat lain. Pull request promosi dari dev ke main dan pull request rilis melewati job yang berat: tree yang persis sama sudah lulus, dan pull request rilis cuma menaikkan versi. Sebagai gantinya muncul job kecil gate yang lulus dalam hitungan detik, jadi setiap pull request tetap punya centang hijau. Branch hotfix yang langsung masuk ke main tetap menjalankan seluruh suite.

Build sekali

Image dibangun saat tag rilis di-push, bukan di setiap push ke main. Kami sempat menimbang memakai ulang image yang sudah dibangun di dev, tapi API membaca versinya dari version.txt saat berjalan, dan file itu berubah di commit rilis. Membangun dari tag menjaga versi yang terlihat oleh operator sesuai dengan kode yang berjalan.

Rilis me-merge dirinya sendiri

release-please sekarang membuka pull request-nya dengan token GitHub App, bukan token bawaan, jadi CI jalan sendiri dan tidak ada lagi commit kosong. Sebuah workflow kecil menunggu run CI itu. Saat lulus, workflow itu me-merge pull request rilis dengan merge commit, tapi hanya kalau pull request-nya masih menunjuk commit yang persis sama dengan yang dites. Kalau ada yang bergeser, workflow itu tidak melakukan apa-apa dan run berikutnya yang memutuskan.

Tag men-deploy dirinya sendiri, dengan titik pemulihan lebih dulu

Build image memanggil deploy production sebagai reusable workflow, di commit milik tag itu sendiri. Kami sengaja memilih ini daripada trigger workflow_run: workflow_run men-checkout branch bawaan, jadi deploy akan membaca file stack dari dev, bukan dari rilisnya.

Sebelum migrasi apa pun, deploy membuat dump database production ke file bertanggal di host. Lalu file itu diperiksa: minimal satu kilobyte, dan diakhiri baris "Dump completed" milik alat dump-nya sendiri. Dump yang kosong atau terpotong menghentikan deploy sebelum satu migrasi pun jalan. Semua langkah pengaman yang sudah ada tetap dipakai: health check, satu deploy dalam satu waktu, dan deteksi rollback yang minggu ini sudah menangkap satu kegagalan pull image.

Rector yang lebih tenang

Timeout Rector berasal dari terlalu banyak worker di runner yang dipakai bersama banyak hal lain. Kami memberinya timeout sepuluh menit, empat worker, dan job yang lebih kecil. Sedikit lebih lambat saat runner sepi, dan selesai dengan andal saat runner sibuk, dan itu memang yang kami mau.

Seperti apa rilis sekarang

Ini v0.1.37, diukur sejak promosi di-merge:

  • 36 detik: release-please membuka pull request rilis.
  • 52 detik: CI-nya lulus dan bot me-merge-nya.
  • Sekitar satu menit: tag dan GitHub release sudah ada dan changelog terkirim.
  • Tujuh setengah menit: image selesai dibangun dan di-push.
  • 14 menit 23 detik: snapshot database diambil, migrasi jalan, dan semua service menjalankan image baru.

Satu-satunya langkah manual yang tersisa adalah promosinya sendiri, karena di situlah seseorang memutuskan sebuah rilis sudah siap. Semua setelahnya bersifat mekanis, jadi tidak seharusnya butuh orang.

Yang akan kami sampaikan ke tim lain

  • Ukur dulu sebelum mempercepat. Kami kira deploy-nya yang lambat. Ternyata cuma tujuh menit dari tujuh puluh lima.
  • Hitung berapa kali tree yang sama dites. Setiap run tambahan terasa tidak berbahaya kalau dilihat sendiri-sendiri.
  • Pastikan robotnya membuktikan bahwa yang di-merge adalah yang dites. Membandingkan commit sebelum merge cuma butuh satu baris.
  • Jangan pernah migrasi tanpa titik pemulihan yang sudah diperiksa. Dump yang ada belum tentu dump yang selesai.

//Baca juga

Lainnya dari blog

Semua artikel →

//Kelola setiap brand dari satu tempat.

Mulai gratis untuk satu brand. Ajak tim Anda saat sudah siap.

$ npm install @atlas/client @atlas/nuxt

Gratis untuk satu brandTanpa kartu kreditUpgrade kapan saja