Tim harus fokus pada pembuatan game yang indah dan sukses, karena semua yang lain ada CI.
Di mana kita menerapkan CI? Apa pendekatan dan konsep yang kita gunakan? Mengapa membangun dan menguji membangun? Sebuah kisah terperinci tentang CI dan bagaimana itu diatur dalam Playrix akan menarik kuliah. Di bawah luka - pemerasan singkat dan beberapa aksen.
Hai
Pertama, sedikit pemanasan: apa itu Continuous Integration? Jika tim menggunakan repositori dan mengumpulkan build malam - apakah itu sudah CI? Apa perbedaan antara Penyebaran dan Pengiriman Berkelanjutan? Itu hampir tidak penting. Detail - untuk lingkaran sempit spesialis. Jika Anda ingin melibatkan seluruh perusahaan dalam beberapa proses, buatlah nama yang sederhana dan bagus untuk itu. Di Playrix, kami menyebut semua pendekatan ini CI. Ini adalah merek lokal dan logo keren:
Ide
CI bukan tujuan, itu adalah alat. Pasti ada tujuan yang ingin Anda capai dengan Continuous Integration, masalah yang perlu dipecahkan. Kebetulan proses pengembangan dan pelepasan dalam tim dibangun di atas prinsip "berdoa dan berproduksi." Terkadang itu dibenarkan, tetapi jarang.
Kami merumuskan tujuan kami sebagai berikut: untuk meminimalkan kemungkinan masalah integrasi, untuk meminimalkan sumber daya yang diperlukan untuk memperbaiki kesalahan yang ditemukan, untuk mengurangi waktu tim pengembangan proyek untuk mendukung dan mendukung proses CI.
CI adalah otomatisasi proses pembuatan, pengujian kode, dan pengirimannya ke berbagai lingkungan, otomatisasi proses pengembangan rutin, integrasi timbal balik layanan yang kita semua gunakan.
Idenya adalah dalam suatu sistem yang secara otomatis mengumpulkan segala sesuatu secara otomatis, melakukan hal ini sering, menguji dan memberikan build, dan juga dengan tepat melaporkan laporan yang mudah jika terjadi kesalahan.
Di mana kita menerapkan CI?
- Mesin dan utilitas,
- game kami untuk semua platform,
- kode server
- analitik, layanan pemasaran, berbagai otomatisasi, layanan CI,
- infrastruktur.
Itu ada di mana-mana atau hampir di mana-mana.
Perakitan dan pengujian kontainer, penyebaran otomatis dalam Test, Staging dan Prod, Rolling dan Canary pembaruan - semua ini kita miliki dan lebih berlaku untuk layanan dan aplikasi web. Hari ini kami akan berkonsentrasi pada CI untuk gim: membangun build, mengujinya, dan mengirimkannya.
Paradigma
Untuk mencapai tujuan yang disebutkan di atas, Anda perlu menyelesaikan beberapa masalah. Di bawah ini adalah rencana yang kami ikuti ketika kami mengotomatisasi beberapa proses dalam pengembangan, misalnya, merakit klien game seluler. Sangat mudah untuk memiliki daftar pertanyaan, menjawab yang mana, Anda dapat memecahkan masalah yang termasuk dalam tim CI.
Instruksi perakitan build adalah dokumentasi, deskripsi proses otomatis kami. Seringkali dokumentasi semacam itu ada di kepala programmer. Jika sebuah tim memiliki spesialis super dalam membangun build dan tanpa itu tidak ada yang bisa membangun build yang cepat dan bebas kesalahan lagi - sekarang saatnya untuk mengubah sesuatu, tidak akan ada pengiriman.
Nah, jika dokumentasi tersebut dibingkai dalam bentuk skrip: Saya memasukkan baris perintah dan satu set parameter pada mesin dengan lingkungan yang disiapkan - Saya mendapat build.
Dokumentasi proses terbaik adalah kode
kucing . Bahkan jika karena alasan tertentu Anda perlu mengulang operasi secara manual, Anda selalu dapat melakukannya dengan melihatnya.
Log build memungkinkan Anda untuk selalu mengatakan dengan pasti: siapa, kapan, dari mana komit, dan dengan hasil apa build ini atau itu dikumpulkan. Kemarin, bangunannya akan, tapi hari ini, tidak. Kami melihat log, kami menemukan floppy build pertama, kami melihat daftar commit yang sampai di sana - untung.
Majalah ini bahkan lebih berguna ketika datang, misalnya, ke kode server. Jika tidak ada informasi tentang siapa yang memperbarui prod dan kapan, maka dalam kasus umum tidak diketahui kode mana yang saat ini bekerja di sana. Dan terkadang itu sangat penting.
Anda dapat menyimpan jurnal seperti itu di buku besar, lebih disukai di dalam tabel atau wiki. Daftar build dalam sistem CI sangat berharga.
Ketika datang untuk membangun bangunan dan menyebarkan ke beberapa jenis lingkungan, pertanyaan selalu muncul: di mana menyimpan kata sandi login / akses? Mereka biasanya membutuhkan banyak: ke repositori untuk mengunduh data sumber, ke penyimpanan file untuk mengisi sumber daya permainan, ke HockeyApp untuk mengirim karakter, ke server untuk memperbarui kode, dll.
Itu terjadi bahwa semua akses yang diperlukan disimpan dalam repositori. Ada hipotesis bahwa ini tidak terlalu baik. Seringkali Anda dapat melihat bidang "masukkan kata sandi", misalnya, di Jenkins, tempat penulis build memasukkan karakter tersembunyi.
Mengingat semua kata sandi dengan hati adalah keterampilan yang baik. Server CI kami sendiri menerima akses yang diperlukan tergantung pada unit. Biasanya, ini adalah token berumur pendek yang dihasilkan pada awal pembuatan dan memberikan hak minimal di mana kami menyebarkan sesuatu atau dari mana kami membaca sesuatu.
Manajemen perakitan dan penyebaran yang terpusat memungkinkan Anda untuk memecahkan masalah membedakan hak akses ke infrastruktur. Mengapa memberikan seseorang akses ke server jika Anda hanya dapat memberikan akses ke perakitan bangunan terkait yang melakukan operasi yang diperlukan pada server ini? Dan karena ada bangunan, maka kami memiliki dokumentasi dan penjurnalan, Anda mengerti.
Biasanya ada banyak jejak yang tersisa selama waktu pembuatan. Tidak, tidak seperti itu: saat membangun, perlu meninggalkan jejak sebanyak mungkin. Di repositori, di pelacak tugas, di sistem distribusi build. Di mana-mana, di mana pun Anda bertemu bangunan, harus ada jejak yang menuntun Anda untuk melengkapi informasi tentangnya.
Jejak-jejak ini tidak perlu disapu, sebaliknya, mereka harus hati-hati dibiarkan dan dilestarikan. Selanjutnya saya akan bercerita lebih banyak tentang ini, tetapi pertama-tama kita perlu mengumpulkan bangunan kami. Ayo pergi.
Kait pra-komit
Sekali lagi, idenya adalah sistem yang mengumpulkan, menguji, dan melaporkan segalanya. Tetapi mengapa membangun sebuah bangunan jika Anda tidak dapat membangunnya?
Semua pengembang game kami memiliki kait pra-komitmen terpasang, mis. serangkaian cek yang dilakukan ketika mencoba melakukan sesuatu. Pemeriksaan dijalankan hanya untuk file yang dimodifikasi, tetapi kami menerapkan sistem pencarian lintas-ketergantungan yang sangat licik untuk memeriksa semua konten terkait juga. Yaitu jika artis menambahkan tekstur, maka kait akan memastikan bahwa mereka tidak lupa mendaftarkannya di mana pun dibutuhkan, dan tidak pernah menyegelnya.
Ternyata kait menangkap sebagian besar kesalahan kecil. Mereka menghemat sumber daya sistem bangun dan membantu pengembang dengan cepat memperbaiki masalah: dia melihat pesan yang mengatakan secara terperinci apa yang salah. Dan dia tidak perlu beralih di antara tugas-tugas: dia benar-benar hanya membuat perubahan dan sesuai konteks. Waktu koreksi kesalahan minimal.
Kami sangat menyukainya sehingga kami bahkan membuat sistem yang memeriksa apakah kait dibuat untuk komit yang masuk ke repositori. Jika tidak, pembuat komit semacam itu akan secara otomatis menerima tugas yang meminta mereka untuk mengonfigurasinya dan instruksi terperinci tentang cara melakukan ini.
Kait distandarisasi untuk semua proyek. Jumlah tes khusus minimal. Ada penyesuaian yang nyaman, termasuk tergantung pada pengguna yang menjalankan: ini sangat nyaman untuk pengujian pengujian.
Membangun
Untuk melihat masalah dalam pembuatan sedini mungkin, Anda perlu mengumpulkan dan menguji bangunan ini sesering mungkin. Klien game kami berkumpul untuk semua platform, untuk setiap komitmen, untuk semua proyek. Mungkin ada beberapa pengecualian, tetapi tidak banyak.
Biasanya, klien, terutama yang seluler, memiliki beberapa versi berbeda: dengan dan tanpa curang, bertanda tangan berbeda, dll. Untuk setiap komit, kami mengumpulkan bangunan "biasa", yang digunakan pengembang dan penguji secara konstan.
Ada build yang sangat jarang digunakan, misalnya, store ios build - hanya satu kali dalam pengiriman, mis. sebulan sekali. Namun, kami percaya bahwa semua bangunan harus dikumpulkan secara teratur. Jika terjadi masalah dengan jenis perakitan ini, di sisi pengembangan atau infrastruktur, tim proyek akan mengetahuinya bukan pada hari pembangunan dikirim, tetapi jauh lebih awal, dan akan dapat menanggapi dan memperbaiki masalah di muka.
Sebagai hasilnya, kami memiliki aturan sederhana: setiap build diluncurkan setidaknya sekali sehari. Tim pengembangan proyek mencari tahu tentang adanya masalah pada platform apa pun dalam kasus terburuk keesokan paginya setelah masalah ini muncul di repositori.
Frekuensi pertemuan dan pengujian semacam itu membutuhkan pendekatan khusus untuk mengoptimalkan waktu pelaksanaannya.
- Semua bangunan pelanggan reguler bersifat inkremental.
- Mengemas atlas dan menyiapkan sumber daya juga bersifat inkremental.
- Assemblies bersifat granular: beberapa langkah berada dalam konfigurasi build terpisah - ini memungkinkan Anda untuk mengeksekusinya secara paralel, serta menggunakan kembali hasil antara.
Ini adalah tangkapan layar yang hampir lengkap dari rantai pembuatan dan pengujian untuk WildScapes. Penuh tidak bisa dilakukan: itu sekitar dua kali lebih besar.
Tes Statis
Setelah perakitan, pengujian statis dilakukan: kami mengambil folder dengan build dan melakukan serangkaian pemeriksaan semua konten yang ada. Kode juga konten, jadi analisis statisnya (cppcheck + PVS-Studio) juga ada di sini.
Pada habr ada
bahan terperinci tentang bagaimana kami telah menerapkan pengujian statis, saya merekomendasikannya. Saya hanya menekankan bahwa tes statis setelah build dan pre-commit hook dieksekusi oleh kode yang sama. Ini sangat menyederhanakan dukungan sistem.
Tes runtime
Jika pengujian statis berhasil, Anda dapat melanjutkan dan mencoba menjalankan pembangunan yang sudah dirakit. Kami menguji bangunan di semua platform kecuali UWP, mis. Windows, MacO, iOS, Android. UWP - juga akan, tetapi sedikit kemudian.
Mengapa uji desktop dibuat jika tampaknya hanya diperlukan dalam pengembangan? Jawaban atas pertanyaannya adalah: buruk jika seorang seniman atau perancang level mendapatkan bangunan yang mogok saat startup karena alasan konyol. Oleh karena itu, Smoke-Test, set minimum pemeriksaan untuk runability dan gameplay dasar, dilakukan untuk semua platform.
Segala sesuatu yang ditulis di atas tentang build juga berlaku untuk pengujian pada perangkat - setidaknya sekali sehari. Dengan beberapa pengecualian: ada tes yang sangat panjang yang tidak punya waktu untuk menyelesaikan dalam sehari.
Tes asap dilakukan untuk setiap komit. Berhasil menyelesaikan pemeriksaan dasar adalah prasyarat bagi build untuk masuk ke sistem distribusi. Biasanya tidak masuk akal untuk memberi seseorang akses ke bangunan yang jelas tidak berhasil. Di sini Anda dapat mengajukan keberatan dan mengajukan pengecualian. Proyek memiliki solusi untuk memberikan akses ke bangunan yang tidak berfungsi, tetapi mereka jarang menggunakannya.
Apa tes lain yang ada:
- Benchmark: kami memeriksa kinerja pada FPS dan memori dalam berbagai situasi dan pada semua perangkat.
- Tes unit Match-3: setiap elemen dan masing-masing mekanik diuji baik secara individu maupun dalam semua kombinasi interaksi.
- Bagian dari seluruh permainan dari awal hingga akhir.
- Berbagai uji regresi, misalnya, uji lokalisasi, atau semua jendela UI terbuka dengan benar, atau adegan fishdom di Fishdom diputar tanpa kesalahan.
- Semua sama, tetapi dengan AddressSanitizer .
- Tes kompatibilitas untuk versi game: ambil pengguna menyimpan file dari versi sebelumnya, buka di versi baru dan pastikan semuanya baik-baik saja.
- Berbagai tes khusus yang relevan dengan mekanik proyek tertentu.

Untuk menjalankan tes, kami menggunakan test stand kami sendiri untuk perangkat iOS dan Android. Ini memungkinkan kami untuk meluncurkan build yang diperlukan pada perangkat secara fleksibel, berinteraksi dengan perangkat dari kode. Kami memiliki kontrol penuh, tingkat keandalan yang dapat dipahami, kami tahu masalah apa yang mungkin kami hadapi dan berapa lama untuk menyelesaikannya. Tidak ada layanan cloud yang menyediakan perangkat pengujian yang menawarkan kenyamanan seperti itu.
KUCING
Tes yang tercantum di atas dilaksanakan di dalam kode proyek. Secara teori ini memungkinkan untuk melakukan pengujian kompleksitas apa pun, tetapi membutuhkan upaya dan sumber daya dari pengembangan proyek untuk mengimplementasikan dan mendukung pengujian ini. Sumber daya ini sering tidak tersedia, dan menguji regresi berganda dengan tangan sulit dan tidak perlu. Saya benar-benar ingin para penguji sendiri melakukan otomatisasi pengujian. Dan kami datang dengan kerangka kerja untuk mereka - Sistem Pengujian Otomasi Berkelanjutan, atau CATS.
Apa idenya: untuk mengaktifkan penulis skrip uji untuk berinteraksi dengan aplikasi game, sama sekali tidak peduli tentang bagaimana semuanya bekerja. Kami menulis skrip dengan python primitif, kami mengakses aplikasi melalui serangkaian abstraksi. Sebagai contoh: "Homescapes, buka saya jendela belanja dan beli produk ini dan itu." Periksa hasilnya, bingo.
Seluruh implementasi perintah skrip tersembunyi di balik serangkaian abstraksi. API yang mengimplementasikan interaksi dengan aplikasi memungkinkan Anda melakukan tindakan apa pun dengan beberapa cara:
- mengirim permintaan http ke server, yang dibangun ke dalam mesin game, dengan semacam perintah. Perintah ini diproses oleh kode permainan. Biasanya ini semacam cheat, bisa semaunya sederhana atau kompleks. Misalnya, "beri saya koordinat tengah tombol dengan pengenal yang ditentukan." Atau "berikan saya permainan dari sini ke level dengan angka yang ditunjukkan."
- Kita dapat membuka jendela melalui cheat atau menemukan koordinat tombol yang digunakan jendela ini, kita dapat meniru mengklik tombol ini, kita dapat melakukan klik virtual padanya.
- Akhirnya, kita dapat melakukan klik "nyata" pada koordinat yang ditentukan seolah-olah itu dilakukan dengan jari di layar.
Metode yang terakhir membuka ruang untuk imajinasi penguji yang sering ingin menguji membangun "pertempuran", di mana tidak ada cheat. Mempertahankan skenario seperti itu lebih sulit, tetapi "membangun tempur" adalah membangun "pertempuran".
Ternyata sangat nyaman untuk bekerja dengan koordinat tengah tombol: koordinat kadang berubah, tetapi pengidentifikasi tombol jarang terjadi. Ini mengarah ke properti penting lain dari sistem: kemampuan untuk menulis satu skrip pengujian untuk semua platform dan semua resolusi layar.
Pengiriman, Laporan & Jejak
Dengan pengiriman, semuanya ternyata cukup sederhana: kami menggunakan penyimpanan bersama tunggal untuk membangun artefak dan untuk penyimpanan dalam sistem distribusi. "Memuat" dari build diturunkan untuk memanggil sepasang permintaan ke api layanan distribusi build, pada dasarnya mendaftar. Dengan cara ini, kami menghemat sedikit waktu untuk memompa bangunan dan uang untuk penyimpanan mereka.
Ingat, Anda berbicara tentang meminimalkan sumber daya yang diperlukan untuk memperbaiki kesalahan yang ditemukan pada build? Laporan dan trek - hanya tentang ini:
- Melaporkan masalah yang ditemukan adalah tugas di Asana. Mudah untuk mengontrol, menugaskannya ke pengembang yang tepat, mentransfernya ke tim CI jika ada kesalahan dalam infrastruktur.
- Kami mengumpulkan bangunan untuk setiap komit. Kami tahu penulis komit ini, jadi hanya dia yang akan melihat tugas ini. Jadi kami menghemat waktu untuk pengembang lain: mereka tidak perlu terganggu oleh masalah yang tidak ada sangkut pautnya dengan mereka dan membantu dalam penyelesaian yang, kemungkinan besar, mereka tidak akan mampu.
- Jika Anda membangun bangunan dari komit berikutnya, kemungkinan besar itu masih rusak. Akan ada komentar dalam tugas: "Build masih rusak", penulis komit baru tidak akan melihat tugas dan tidak akan membuang waktu untuk masalah orang lain.
- Kami mengirim laporan ke Slack. Diperlukan - secara pribadi kepada orang yang "merusak" bangunan, dan jika proyek menginginkannya - ke saluran khusus atau ke karyawan Playrix. Semuanya sefleksibel mungkin.
Jejak diperlukan agar di mana-mana ada informasi lengkap tentang bangunan dan perubahan yang dikumpulkan. Agar tidak mencari apa pun, sehingga semuanya sudah dekat dan tidak perlu menghabiskan waktu mencari detail yang sering diperlukan ketika meneliti masalah.
- Laporan tersebut berisi tautan ke build, ke log build, teks kesalahan kompilasi yang ditemukan, dan nama-nama tes yang dibalik. Seringkali seorang programmer, setelah menerima tugas laporan, dapat segera memperbaiki kesalahan: nama file, teks baris dan kesalahan ada dalam laporan.
- Pesan di Slack berisi semua tautan + yang sama dengan tugas di Asana.
- Di Teamcity, tautan ke tugas. Build engineer dapat langsung masuk ke tugas, dalam satu klik, Anda tidak perlu mencari apa pun.
- Dalam github - status dengan tautan ke build, di komentar ke commit - tautan ke tugas untuk mana build ini dibuat. Dalam tugas - komentar dengan tautan ke komit.
- Di layanan distribusi build: tautan ke build, tautan ke komit.
Tidak ada yang perlu diingat, tetapi Anda memahami idenya: tautan ke segalanya, di mana saja. Ini sangat mempercepat studi tentang situasi yang tidak dapat dipahami.
Pertanian
Kami mengumpulkan dan menguji bangunan untuk semua platform. Untuk ini, kami membutuhkan banyak agen yang berbeda. Melacak dan memeliharanya secara manual memang panjang dan sulit. Semua agen disiapkan secara otomatis. Kami menggunakan Packer dan Ansible.
Semua log dari semua agen, Teamcity, semua layanan yang ada di sekitar, kami simpan (dalam kasus kami - di ELK). Semua layanan, pemrosesan build, tambahkan jumlah build ini ke setiap baris log. Kita dapat melihat dalam satu permintaan seluruh siklus bangunan dari penampilannya dalam antrian hingga akhir pengiriman semua laporan.
Kami telah menerapkan mekanisme optimasi antrian kami sendiri. Yang ada di Teamcity tidak bekerja dengan baik pada angka kita. Berbicara tentang angka:
- Kami mengumpulkan sekitar 5.000 bangunan setiap hari. Ini adalah sekitar 500 jam kerja mesin.
- Membangun ketiga juta adalah sebulan yang lalu.
- Kami memiliki lebih dari 50 server build di 10 lokasi berbeda.
- 40+ perangkat seluler di bangku tes.
- Tepatnya 1 server Teamcity.
CI sebagai Layanan
Playrix CI adalah layanan. Ada banyak proyek, banyak ide juga.
Kami mengoptimalkan waktu dari memasukkan build ke antrian hingga akhir pelaksanaannya, karena itulah “waktu build” yang dipertimbangkan oleh pengguna layanan, pengembang. Ini memungkinkan kami untuk mencari dan menemukan keseimbangan antara waktu pembuatan dan waktu yang dihabiskan dalam antrian. Tampaknya logis bahwa dengan pertumbuhan perusahaan dan jumlah proyek, membangun pertanian yang mengumpulkan proyek-proyek ini juga akan tumbuh. Namun berkat optimalisasi, tingkat pertumbuhan pertanian jauh di belakang tingkat pertumbuhan perusahaan.
Setiap optimasi dimulai dengan pemantauan, dengan koleksi statistik yang metodis. Kami mengumpulkan banyak statistik dan kami benar-benar tahu segalanya tentang bangunan kami. Tapi selain volume build farm, ada juga tim yang mendukung sistem CI dan membuatnya sehingga tidak ada yang perlu memikirkan dari mana build berasal.
Optimalisasi proses dalam tim ini juga merupakan proses yang menarik dan menghibur.
Sebagai contoh, kami menulis tes untuk pengaturan konfigurasi build, karena ada banyak konfigurasi ini, tanpa tes serupa tidak mudah untuk menemukan semua tempat yang perlu diedit. Untuk hampir semua perubahan, pertama-tama kita menulis tes, dan kemudian membuatnya, mis., Kita memiliki TDD. Ada banyak proses yang berkaitan dengan tugas, manajemen insiden, penjadwalan aliran tugas masuk.Pengembang harus fokus pada pembuatan gim yang hebat dan sukses tanpa khawatir dari mana asalnya. Untuk ini, Playrix memiliki CI. Pasti ada tujuan yang ingin Anda capai dengan Continuous Integration, masalah yang perlu dipecahkan. Penting untuk tidak menemukan masalah, yaitu untuk menemukannya. Dan ketika Anda menemukannya, ingat pengalaman kami dan lakukan yang lebih baik. Dan ingat:CI tidak pernah tidurSampai jumpa!