GitLab CI: 6 fitur dari rilis terbaru yang telah kami tunggu-tunggu



Di era CI / CD di mana-mana, kita dihadapkan dengan berbagai alat terkait, termasuk sistem CI. Namun, GitLab-lah yang paling dekat dengan kami, benar-benar "asli". Dia mendapatkan popularitas terkemuka di industri secara keseluruhan *. Para pengembang produk tidak ketinggalan ketertarikan yang tumbuh dalam penggunaannya, secara teratur memuaskan komunitas pengembang dan insinyur DevOps dengan versi baru.


Bulan repositori GitLab dan agregasi tag

GitLab adalah kasus ketika pengembangan aktif membawa banyak fitur baru dan menarik. Jika bagi pengguna potensial, ini hanyalah salah satu faktor dalam memilih alat, untuk yang sudah ada, situasinya adalah sebagai berikut: jika Anda belum memperbarui instalasi GitLab Anda pada bulan lalu, maka dengan probabilitas tinggi Anda melewatkan sesuatu yang menarik. Termasuk pembaruan keamanan yang muncul secara berkala.

Tentang yang paling signifikan - yaitu diminta oleh para insinyur dan pelanggan DevOps kami - inovasi dalam rilis terbaru edisi Komunitas GitLab, dan artikel ini akan dibahas.

* 5 , «GitLab», : «, GitHub?». — , Google Trends 5- «gitlab» . «» , . , , «» .

№1: needs


  • job'.
  • GitLab: 12.2.
  • .

Pikir dependencies- ini yang Anda butuhkan? Mungkin, kami bukan satu-satunya yang melakukan kesalahan dalam menetapkan arahan ini ... Diperlukan untuk membuat daftar pekerjaan sebelumnya, artefak yang diperlukan. Itu adalah artefak, dan bukan ketergantungan pada kinerja tugas sebelumnya.

Misalkan terjadi bahwa dalam satu tahap ada pekerjaan yang tidak perlu dilakukan, tetapi untuk beberapa alasan tidak ada kemungkinan atau hanya keinginan untuk membawa mereka ke tahap yang terpisah (kemalasan adalah mesin kemajuan, tetapi jangan terbawa).

Situasi:



Seperti yang Anda lihat, stage Deploy berisi tombol untuk meluncurkan produksi dan stage, dan tes Selenium jobuntuk beberapa alasan tidak dieksekusi. Sederhana saja: ia menunggu sampai semua pekerjaan dari tahap sebelumnya berhasil diselesaikan. Namun, dalam kerangka pipeline yang sama, kita tidak perlu menggunakan stage sekarang untuk menjalankan tes (dipompa keluar sebelumnya tidak dalam tag). Apa yang harus dilakukan? Kalau begitu datanglah ke kebutuhan penyelamatan !

Kami hanya mencantumkan pekerjaan yang diperlukan sebelumnya untuk menjalankan tes kami:

  needs:
    - To production (Cluster 1)
    - To production (Cluster 2)

... dan kami mendapatkan pekerjaan, yang secara otomatis dipanggil setelah hanya pekerjaan yang terdaftar dieksekusi:



Mudah, bukan? Tetapi begitu saya berharap bahwa arahan akan bekerja seperti ini dependencies...

2: meluas



Bosan membaca gulungan .gitlab-ci.yaml? Prinsip kode reuse hilang? Maka Anda sudah mencoba dan mungkin berhasil membawa milik Anda .gitlab-ci.yamlke keadaan seperti ini:

.base_deploy: &base_deploy
  stage: deploy
  script:
    - my_deploy_command.sh
  variables:
    CLUSTER: "default-cluster"
    MY_VAR: "10"

Deploy Test:
  <<: *base_deploy
  environment:
    url: test.example.com
    name: test

Deploy Production:
  <<: *base_deploy
  environment:
    url: production.example.com
    name: production
  variables:
    CLUSTER: "prod-cluster"
    MY_VAR: "10"

Kedengarannya bagus? Namun, jika Anda melihat lebih dekat, sesuatu menarik perhatian Anda ... Mengapa kami mengubah produksi tidak hanya variables.CLUSTER, tetapi juga ditentukan untuk kedua kalinya variables.MY_VAR=10? Haruskah variabel ini diambil base_deploy? Ternyata itu seharusnya tidak: YAML bekerja sehingga, mendefinisikan ulang apa yang diterima dari jangkar, itu tidak memperluas konten bidang yang cocok, tetapi menggantinya . Oleh karena itu, kami dipaksa untuk membuat daftar variabel yang sudah diketahui kami dalam paragraf yang cocok.

Ya, "ekspansi" adalah kata yang tepat: inilah yang disebut sebagai fitur yang dimaksud. ExtendsMereka memungkinkan kita tidak hanya menulis ulang bidang, seperti yang terjadi dengan jangkar, tetapi untuk melakukan penggabungan yang cerdas untuk itu:

.base_deploy: 
  stage: deploy
  script:
    - my_deploy_command.sh
  variables:
    CLUSTER: "default-cluster"
    MY_VAR: "10"

Deploy Production:
  extends: .base_deploy
  environment:
    url: production.example.com
    name: production
  variables:
    CLUSTER: "prod-cluster"

Di sini, di pekerjaan akhir Deploy Production akan ada variabel MY_VARdengan nilai default dan yang diganti CLUSTER.

Tampaknya ini adalah hal yang sepele, tetapi bayangkan: Anda memiliki satu base_deploydan 20 sirkuit yang dikerahkan dengan cara yang sama. Mereka perlu diteruskan ke orang lain cluster, environment.namesambil mempertahankan seperangkat variabel tertentu atau bidang yang cocok lainnya ... Kesenangan kecil ini memungkinkan kita untuk mengurangi deskripsi penyebaran rangkaian rangkaian dev sebanyak 2-3 kali.

3: termasuk



.gitlab-ci.yamlmasih terlihat seperti instruksi lipat untuk penyedot debu dalam 20 bahasa (yang Anda hanya mengerti yang asli) apakah sulit ketika Anda harus berurusan dengan salah satu bagiannya tanpa mengubah dalam menghadapi pekerjaan yang tidak diketahui yang dihadapi dalam perjalanan?

Teman pemrograman lama akan membantu include:

stages:
  - test
  - build
  - deploy

variables:
  VAR_FOR_ALL: 42

include:
  - local: .gitlab/ci/test.yml
  - local: .gitlab/ci/build.yml
  - local: .gitlab/ci/deploy-base.yml
  - local: .gitlab/ci/deploy-production.yml

Itu Sekarang kami dengan berani mengedit penyebaran dalam produksi, sementara penguji sibuk memodifikasi file mereka, yang bahkan kita tidak melihatnya. Selain itu, ini membantu menghindari penggabungan konflik: tidak selalu menyenangkan untuk memahami kode orang lain.

Tetapi bagaimana jika kita mengetahui pipa 20 proyek kita secara terus menerus, dapatkah kita menjelaskan logika masing-masing pekerjaan darinya? Bagaimana ini akan membantu kami? Bagi mereka yang telah mencapai pencerahan dalam penggunaan kembali kode dan untuk semua yang memiliki banyak proyek serupa, Anda dapat:


Selusin jenis proyek yang sama dengan kode yang berbeda, tetapi digunakan dengan cara yang sama - dengan mudah dan tanpa mempertahankan CI terbaru di semua repositori!

Contoh penggunaan praktis includejuga diberikan dalam artikel ini .

Nomor 4: hanya / kecuali referensi


  • Kondisi komprehensif, termasuk perubahan variabel dan file.
  • Karena ini adalah seluruh keluarga fungsi, beberapa bagian mulai muncul di GitLab 10.0, sementara yang lain (misalnya, changes) mulai muncul di 11.4.
  • docs.gitlab.com/ce/ci/yaml/#onlyexcept-advanced

Kadang-kadang bagi saya tampaknya ini bukan saluran pipa mendengarkan kita, tetapi kita dia. Alat manajemen yang sangat baik adalah only/ except- sekarang terintegrasi. Apa artinya ini?

Dalam kasus yang paling sederhana (dan mungkin yang paling menyenangkan), lewati tahapan:

Tests:
  only:
    - master
  except:
    refs:
    - schedules
    - triggers
    variables:
    - $CI_COMMIT_MESSAGE =~ /skip tests/

Dalam contoh pekerjaan, ini hanya berjalan di cabang master, tetapi tidak dapat dipicu oleh jadwal atau pemicu (GitLab berbagi pemanggilan dan pemicu API, meskipun ini pada dasarnya adalah API yang sama). Pekerjaan tidak akan dieksekusi jika ada passphrase tes lewati dalam pesan komit . Misalnya, kesalahan ketik dalam README.mdproyek atau dokumentasi telah diperbaiki - mengapa menunggu hasil tes?

"Hei, 2020 ada di luar!" Mengapa saya setiap kali harus menjelaskan kepada kotak besi bahwa tidak perlu melakukan tes ketika mengubah dokumentasi? " Dan sungguh: only:changesini memungkinkan Anda untuk menjalankan tes ketika mengubah file hanya di direktori tertentu. Contohnya:

  only:
    refs:
      - master
      - merge_requests
    changes:
      - "front/**/*"
      - "jest.config.js"
      - "package.json"

Dan untuk tindakan sebaliknya - mis. jangan lari - ya except:changes.

Nomor 5: aturan



Arahan ini sangat mirip dengan yang sebelumnya only:*, tetapi dengan perbedaan penting: ini memungkinkan Anda untuk mengontrol parameter when. Misalnya, jika Anda tidak ingin sepenuhnya menghapus kemungkinan memulai pekerjaan. Anda cukup meninggalkan tombol, yang, jika diinginkan, akan dipanggil secara independen, tanpa meluncurkan pipa baru atau tanpa membuat komit.

# 6: environment: auto_stop_in



Kami belajar tentang peluang ini tepat sebelum penerbitan artikel dan belum memiliki cukup waktu untuk mencobanya dalam praktik, tetapi ini jelas merupakan "hal yang sama" yang sangat diharapkan dalam beberapa proyek.

Anda dapat menentukan parameter di lingkungan GitLab on_stop- ini sangat berguna ketika Anda ingin membuat dan menghapus lingkungan secara dinamis, misalnya, untuk setiap cabang. Pekerjaan yang ditandai dengan k on_stopdieksekusi, misalnya, ketika penggabungan MR ada di cabang master atau ketika MR ditutup (atau bahkan hanya dengan mengklik tombol), yang karenanya lingkungan yang tidak perlu dihapus secara otomatis.

Semuanya nyaman, logis, berfungsi ... jika bukan karena faktor manusia. Banyak pengembang menggabungkan MR bukan dengan mengklik tombol di GitLab, tetapi secara lokal via git merge. Anda dapat memahaminya: nyaman! Namun dalam hal ini, logikanyaon_stopitu tidak berhasil, kami telah mengumpulkan lingkungan yang terlupakan ... Di sinilah yang lama ditunggu-tunggu berguna auto_stop_in.

Bonus: gubuk sementara saat tidak ada peluang yang cukup


Terlepas dari semua ini (dan banyak lainnya), fungsi baru yang dituntut dari GitLab, sayangnya, kadang-kadang kondisi untuk memenuhi suatu pekerjaan tidak mungkin digambarkan dalam kerangka kemampuan yang tersedia saat ini.

GitLab tidak sempurna, tetapi menyediakan alat dasar untuk membangun jalur pipa impian ... jika Anda siap untuk melampaui DSL sederhana, terjun ke dunia scripting. Berikut adalah beberapa solusi dari pengalaman kami, yang sama sekali tidak berpura-pura benar atau direkomendasikan secara ideologis, tetapi disajikan lebih untuk menunjukkan kemungkinan yang berbeda dengan kurangnya fungsionalitas API bawaan.

Solusi No. 1: luncurkan dua pekerjaan dengan satu tombol


script:
  - > 
    export CI_PROD_CL1_JOB_ID=`curl -s -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs" | \
      jq '[.[] | select(.name == "Deploy (Cluster 1)")][0] | .id'`
  - > 
    export CI_PROD_CL2_JOB_ID=`curl -s -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/pipelines/${CI_PIPELINE_ID}/jobs" | \
      jq '[.[] | select(.name == "Deploy (Cluster 2)")][0] | .id'`
  - > 
    curl -s --request POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/jobs/$CI_PROD_CL1_JOB_ID/play"
  - > 
    curl -s --request POST -H "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" \ 
      "https://gitlab.domain/api/v4/projects/${CI_PROJECT_ID}/jobs/$CI_PROD_CL2_JOB_ID/play"

Dan mengapa tidak, jika Anda benar-benar menginginkannya?

Solusi No. 2: transfer diubah dalam file MR rb untuk rubocop di dalam gambar


Rubocop:
  stage: test
  allow_failure: false
  script:
    ...
    - export VARFILE=$(mktemp)
    - export MASTERCOMMIT=$(git merge-base origin/master HEAD)
    - echo -ne 'CHANGED_FILES=' > ${VARFILE}
    - if [ $(git --no-pager diff --name-only ${MASTERCOMMIT} | grep '.rb$' | wc -w |awk '{print $1}') -gt 0 ]; then
        git --no-pager diff --name-only ${MASTERCOMMIT} | grep '.rb$' |tr '\n' ' ' >> ${VARFILE} ;
      fi
    - if [ $(wc -w ${VARFILE} | awk '{print $1}') -gt 1 ]; then
        werf --stages-storage :local run rails-dev --docker-options="--rm --user app --env-file=${VARFILE}" -- bash -c /scripts/rubocop.sh ;
      fi
    - rm ${VARFILE}

Tidak ada gambar di dalamnya .git, jadi saya harus keluar untuk memeriksa hanya file yang diubah.

Catatan: Ini bukan situasi yang sangat standar dan upaya putus asa untuk mematuhi banyak kondisi masalah, deskripsi yang tidak termasuk dalam ruang lingkup artikel ini.

Penanganan # 3: pemicu untuk memulai pekerjaan dari repositori lain saat diluncurkan


  before_script:
    - |
      echo '### Trigger review: infra'
      curl -s -X POST \
        -F "token=$REVIEW_TOKEN_INFRA" \
        -F "ref=master" \
        -F "variables[REVIEW_NS]=$CI_ENVIRONMENT_SLUG" \
        -F "variables[ACTION]=auto_review_start" \
        https://gitlab.example.com/api/v4/projects/${INFRA_PROJECT_ID}/trigger/pipeline

Tampaknya hal yang sederhana dan perlu (dalam dunia layanan-mikro) meluncurkan perangkat-layanan lain ke dalam rangkaian yang baru dibuat sebagai ketergantungan. Tapi itu bukan, karena itu, diperlukan panggilan API dan fitur yang sudah dikenal (dijelaskan di atas):

  only:
    refs:
    - triggers
    variables:
    - $ACTION == "auto_review_start"

Catatan:

  • Pekerjaan pada pemicu dirancang untuk dikaitkan dengan meneruskan variabel ke API, mirip dengan contoh No. 1. Lebih logis untuk mengimplementasikan ini pada API dengan nama pekerjaan disahkan.
  • Ya, fungsinya ada dalam versi komersial (EE) dari GitLab, tetapi kami tidak mempertimbangkannya.

Kesimpulan


GitLab mencoba mengikuti tren, secara bertahap menerapkan fitur yang menyenangkan dan diminati oleh komunitas DevOps. Mereka cukup mudah digunakan, dan ketika fitur dasar tidak cukup, mereka selalu dapat diperluas dengan skrip. Dan jika kita melihat ternyata ternyata tidak begitu elegan dan nyaman untuk mendukung ... itu masih menunggu rilis baru GitLab - atau untuk membantu proyek dengan kontribusi kami .

PS


Baca juga di blog kami:


All Articles