Kiat untuk membuat alur kerja khusus di GitLab CI

Catatan perev. : Artikel asli ditulis oleh Miłosz Smółka, salah satu pendiri perusahaan kecil Polandia Three Dots Labs , yang berspesialisasi dalam "solusi backend canggih". Penulis mengacu pada pengalamannya dalam penggunaan aktif GitLab CI dan membagikan tips yang terakumulasi untuk pengguna lain dari produk Open Source ini. Setelah membacanya, kami menyadari betapa dekatnya masalah yang digambarkannya dekat dengan kami, jadi kami memutuskan untuk berbagi solusi yang diusulkan dengan khalayak yang lebih luas.



Kali ini saya akan membahas topik lebih lanjut di GitLab CI. Tugas umum di sini adalah mengimplementasikan fitur-fitur non-standar dalam pipa. Sebagian besar tip khusus untuk GitLab, meskipun beberapa di antaranya dapat diterapkan ke sistem CI lainnya.

Jalankan tes integrasi


Sebagai aturan, verifikasi kode menggunakan tes unit mudah disambungkan ke sistem CI apa pun. Biasanya ini tidak lebih rumit daripada menjalankan salah satu perintah yang dibangun ke dalam seperangkat utilitas standar dalam bahasa pemrograman. Dalam pengujian tersebut, Anda cenderung menggunakan berbagai moki dan bertopik untuk menyembunyikan detail implementasi dan fokus pada pengujian logika tertentu. Misalnya, Anda dapat menggunakan basis data dalam memori sebagai penyimpanan atau menulis stubs untuk klien HTTP yang akan selalu mengembalikan respons yang sudah disiapkan.

Namun, cepat atau lambat Anda akan memerlukan tes integrasi untuk mencakup situasi yang lebih tidak biasa dengan tes. Saya tidak akan berdiskusi tentang semua jenis pengujian yang mungkin dan katakan saja dengan integrasi yang saya maksudkan tes yang menggunakan beberapa jenis sumber daya eksternal. Ini bisa berupa server basis data nyata, layanan HTTP, penyimpanan terhubung, dll.

Di GitLab, mudah untuk menjalankan sumber daya yang dapat dicolokkan karena wadah Docker terkait dengan wadah tempat skrip dijalankan. Ketergantungan ini dapat didefinisikan menggunakan services . Mereka tersedia dengan nama gambar atau dengan nama pilihan Anda, jika Anda menentukannya di bidang alias .

Berikut adalah contoh sederhana menggunakan wadah pluggable dengan MySQL:

 integration_tests: stage: tests services: - name: mysql:8 alias: db script: - ./run_tests.sh db:3306 

Dalam hal ini, dalam skrip tes Anda harus terhubung ke host db . Menggunakan alias biasanya merupakan ide yang baik, karena memungkinkan Anda untuk mengganti gambar tanpa perlu memodifikasi kode uji. Misalnya, Anda dapat mengganti gambar mysql dengan mariadb , dan skrip akan tetap berfungsi dengan benar.

Menunggu kontainer


Karena wadah plug-in membutuhkan waktu untuk memuat, Anda mungkin perlu menunggu sebelum mengirim permintaan apa pun. Cara sederhana adalah dengan menunggu skrip wait-for-it.sh dengan batas waktu yang ditentukan.

Menggunakan Docker Compose


Untuk sebagian besar kasus, services harus memadai. Namun, terkadang interaksi dengan layanan eksternal mungkin diperlukan. Misalnya, dalam hal meluncurkan Kafka dan ZooKeeper dalam dua wadah terpisah (ini adalah bagaimana gambar resmi dikumpulkan). Contoh lain adalah menjalankan tes dengan jumlah node yang dinamis, seperti Selenium. Solusi terbaik untuk menjalankan layanan ini adalah Docker Compose :

 version: '3' services: zookeeper: image: confluentinc/cp-zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 ports: - 9092:9092 

Jika Anda menggunakan instalasi dengan pelari GitLab di server yang dapat dipercaya, Anda dapat menjalankan Docker Composer melalui pelaksana Shell . Opsi lain yang mungkin adalah dind Docker di Docker ( dind ). Tetapi dalam hal ini, baca artikel ini terlebih dahulu.

Salah satu cara untuk menggunakan Compose adalah dengan mengatur lingkungan Anda, menjalankan tes, dan kemudian menghancurkan semuanya. Script bash sederhana akan terlihat seperti ini:

 docker-compose up -d ./run_tests.sh localhost:9092 docker-compose down 

Selama Anda menjalankan tes di lingkungan minimal, semuanya akan baik-baik saja. Meskipun situasi mungkin muncul di mana Anda perlu menginstal beberapa dependensi ... Ada cara lain untuk menjalankan tes di Docker Compose - ini memungkinkan Anda untuk membuat gambar Docker Anda sendiri dengan lingkungan pengujian. Di salah satu wadah, Anda menjalankan tes dan keluar dengan kode pengembalian yang sesuai:

 version: '3' services: zookeeper: image: confluentinc/cp-zookeeper environment: ZOOKEEPER_CLIENT_PORT: 2181 kafka: image: confluentinc/cp-kafka environment: KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:9092 tests: image: registry.example.com/some-image command: ./run_tests.sh kafka:9092 

Perhatikan bahwa kami telah menghilangkan kebutuhan untuk memetakan porta. Dalam contoh ini, tes dapat berinteraksi dengan semua layanan secara langsung.

Dan peluncuran mereka dilakukan oleh satu perintah:

 docker-compose up --exit-code-from tests 

Opsi --exit-code-from menyiratkan --abort-on-container-exit , yang berarti: seluruh lingkungan yang diprakarsai oleh docker-compose up akan dihentikan setelah salah satu kontainer selesai. Kode penyelesaian untuk perintah ini akan setara dengan kode keluar dari layanan yang dipilih (mis. Ini adalah tests dalam contoh di atas). Jika perintah yang memulai tes dilengkapi dengan kode non-nol, maka seluruh docker-compose up akan keluar bersamanya.

Menggunakan label sebagai tag CI


Peringatan : ini adalah ide yang agak tidak biasa, tetapi bagi saya sepertinya sangat berguna dan fleksibel.

Seperti yang Anda ketahui, GitLab memiliki fitur Label yang tersedia di tingkat proyek dan grup. Label dapat ditetapkan pada tiket dan menggabungkan permintaan. Namun, mereka tidak memiliki hubungan dengan jaringan pipa.



Sedikit perbaikan akan memungkinkan Anda untuk mengakses label permintaan gabungan dalam skrip pekerjaan. Di GitLab 11.6, semuanya menjadi lebih mudah, karena variabel lingkungan CI_MERGE_REQUEST_IID telah muncul (ya, itu dengan IID , bukan ID ) jika pipa only: merge_requests menggunakan only: merge_requests .

Jika only: merge_requests tidak digunakan atau Anda bekerja dengan GitLab versi lama, MR masih dapat diperoleh - menggunakan panggilan API:

 curl "$CI_API_V4_URL/projects/$CI_PROJECT_ID/repository/commits/$CI_COMMIT_SHA/merge_requests?private_token=$GITLAB_TOKEN" 

Bidang yang kita butuhkan adalah iid . Namun, ingatlah bahwa banyak MR dapat kembali untuk komit yang diberikan.

Ketika MR IID diterima, tetap hanya untuk beralih ke API Permintaan Gabung dan menggunakan bidang labels dari jawabannya:

 curl "$CI_API_V4_URL/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID?private_token=$GITLAB_TOKEN" 

Login


Sayangnya, saat ini tidak mungkin menggunakan $CI_JOB_TOKEN untuk mengakses API proyek (setidaknya jika proyek tersebut tidak publik). Jika proyek memiliki akses terbatas (internal atau pribadi), untuk otorisasi dalam API GitLab Anda perlu membuat token API pribadi.



Namun, ini bukan solusi teraman, jadi berhati-hatilah. Jika token jatuh ke tangan yang buruk, maka akses tulis ke semua proyek Anda mungkin muncul dengan itu. Salah satu cara untuk mengurangi risiko adalah dengan membuat akun terpisah dengan hak untuk membaca repositori dan membuat token pribadi untuk akun ini.

Seberapa amankah variabel Anda?


Beberapa versi yang lalu, bagian Variabel disebut Variabel Rahasia , yang sepertinya dibuat untuk menyimpan kredensial dan informasi penting lainnya secara andal. Bahkan, variabel hanya disembunyikan dari pengguna yang tidak memiliki hak Maintainer. Mereka tidak dienkripsi pada disk, dan kebocoran mereka dapat dengan mudah terjadi melalui variabel lingkungan di skrip.

Ingatlah hal ini ketika menambahkan variabel apa pun dan pertimbangkan untuk menyimpan rahasia dalam solusi yang lebih aman (misalnya, Vault dari HashiCorp ).

Gunakan kasing


Apa yang harus dilakukan dengan daftar label terserah Anda. Berikut ini beberapa ide:

  • Gunakan mereka untuk mengelompokkan tes.
  • Gunakan semantik nilai kunci dengan titik dua sebagai pemisah (mis. Label seperti tests:auth , tests:user )
  • Sertakan fitur tertentu untuk pekerjaan.
  • Izinkan debugging pekerjaan tertentu jika label ada.

Memanggil API Eksternal


Meskipun GitLab hadir dengan berbagai fitur yang sudah tersedia, sangat mungkin Anda ingin menggunakan utilitas lain yang dapat diintegrasikan dengan saluran pipa. Cara paling sederhana untuk mengimplementasikannya, tentu saja, memanggil curl lama yang baik.

Jika Anda membuat alat sendiri, Anda dapat mengajari mereka untuk mendengarkan GitLab Webhooks (lihat tab Integrasi dalam pengaturan proyek). Namun, jika Anda bermaksud menggunakannya dengan sistem kritis, pastikan mereka memenuhi persyaratan ketersediaan tinggi.

Contoh: Anotasi Grafana


Jika Anda bekerja dengan Grafana , anotasi adalah cara yang bagus untuk menandai peristiwa yang terjadi seiring waktu pada grafik. Mereka dapat ditambahkan tidak hanya secara manual dengan mengklik di GUI, tetapi juga dengan memanggil Grafana REST API :



Untuk mengakses API, Anda harus membuat Kunci API. Pertimbangkan untuk membuat pengguna terpisah dengan akses terbatas:



Tentukan dua variabel dalam pengaturan proyek:

  • GRAFANA_URL - URL ke instalasi Grafana (misalnya, https://grafana.example.com );
  • GRAFANA_APIKEY - kunci yang dihasilkan untuk API.

Untuk dapat menggunakannya kembali, letakkan skrip di repositori dengan skrip umum :

 #!/bin/bash set -e if [ $# -lt 2 ]; then echo "Usage: $0 <text> <tag>" exit 1 fi readonly text="$1" readonly tag="$2" readonly time="$(date +%s)000" cat >./payload.json <<EOF { "text": "$text", "tags": ["$tag"], "time": $time, "timeEnd": $time } EOF curl -X POST "$GRAFANA_URL/api/annotations" \ -H "Authorization: Bearer $GRAFANA_APIKEY" \ -H "content-type: application/json" \ -d @./payload.json 

Sekarang Anda dapat menambahkan panggilannya ke konfigurasi CI dengan parameter yang diperlukan:

 deploy: stage: deploy script: - $SCRIPTS_DIR/deploy.sh production - $SCRIPTS_DIR/grafana-annotation.sh "$VERSION deployed to production" deploy-production 

Panggilan ini dapat ditempatkan dalam skrip deploy.sh untuk menyederhanakan konfigurasi CI.

Bonus: tips cepat


GitLab memiliki dokumentasi yang sangat baik tentang semua kata kunci yang memungkinkan yang dapat digunakan untuk mengonfigurasi CI. Saya tidak ingin menggandakan isinya di sini, tetapi saya akan menunjukkan beberapa kasus yang bermanfaat. Klik pada judul untuk melihat dokumentasi terkait.

Penggunaan lanjutan hanya / kecuali


Dengan mendefinisikan pola untuk variabel CI, Anda dapat menentukan rakitan khusus untuk beberapa cabang. Ini mungkin membantu, misalnya, untuk mengidentifikasi perbaikan dorong untuk perbaikan mendesak, tetapi jangan menyalahgunakannya:

 only: refs: - branches variables: - $CI_COMMIT_REF_NAME =~ /^hotfix/ 

GitLab memiliki banyak variabel yang telah ditentukan sebelumnya dalam setiap pekerjaan CI - gunakan mereka.

Yaml jangkar


Gunakan mereka untuk menghindari duplikasi.

Dari versi 11.3, Anda juga dapat menggunakan kata kunci extends :

 .common_before_script: &common_before_script before_script: - ... - ... deploy: <<: *common_before_script 

Pengecualian artefak


Secara default, semua artefak yang dikumpulkan dalam pipa akan ditransfer ke semua pekerjaan berikutnya. Jika Anda secara eksplisit mencantumkan artefak tempat pekerjaan bergantung, Anda dapat menghemat waktu dan ruang disk:

 dependencies: - build 

Atau - sebaliknya - lewati semuanya jika tidak ada yang diperlukan:

 dependencies: [] 

Strategi git


Abaikan kloning repositori jika pekerjaan tidak menggunakan file-file ini:

 variables: GIT_STRATEGY: none 

Itu saja!

Terima kasih sudah membaca! Untuk umpan balik dan pertanyaan, hubungi saya di Twitter atau Reddit .

Lebih banyak tips GitLab dapat ditemukan di posting sebelumnya:


PS dari penerjemah


Baca juga di blog kami:

Source: https://habr.com/ru/post/id436910/


All Articles