Cara memilih cabang git secara dinamis untuk digunakan dalam build Jenkins

Saya mencoba membuat konfigurasi proyek baru untuk server build Jenkins. Untuk menyederhanakan apa yang saya coba lakukan, saya hanya akan menggunakan dua komponen untuk menggambarkan masalahnya.

KomponenA

  • Perubahan pada komponen ini memicu build proyek ini di server CI.
  • Server CI memiliki cabang yang dikonfigurasi secara statis untuk memantau perubahan dan membangun. Misalnya master atau cabang pengembangan.
  • Komponen ini berisi file konfigurasi dengan versi yang diperlukan dari ComponentB yang bergantung padanya.

ComponentB

  • Perubahan pada komponen ini tidak memicu build proyek ini di server CI (akan ada proyek lain untuk mencakup pengembangan ComponentB).
  • Versi individual dari komponen diberi tag
  • ComponentA memiliki versi ComponentB yang diperlukan dalam file konfigurasinya
  • Server CI tidak tahu cabang (tag) apa yang harus diperiksa sampai file konfigurasi ComponentA diurai.

Apa cara yang tepat untuk mencapai hal ini di Jenkins? Saya mencoba mencari tahu bagaimana cara menambahkan perilaku dinamis ini untuk mengurai file konfigurasi dan membuat Plugin Git untuk memeriksa cabang berdasarkan versi yang diharapkan dari ComponentB tetapi sejauh ini saya tidak tahu.

Pada langkah selanjutnya saya bahkan mungkin ingin memiliki wildcard (seperti 5.3.*) di file konfigurasi sehingga saya harus menemukan tag ComponentB terbaru yang cocok dengan wildcard.

EDIT

Sekarang saya melihat bahwa saya terlalu menyederhanakan masalah saya dan karena penyederhanaan tersebut, batasan utama tidak lagi ada.

Batasan utamanya adalah bahwa Komponen A dan B harus dibangun bersama-sama. Tidak mungkin untuk membangunnya secara terpisah karena mereka membentuk satu executable / library dan build script membutuhkan file sumber dari kedua komponen tersebut.

Jika Anda bertanya mengapa konfigurasi yang aneh seperti itu, mari kita beri penjelasan tentang Komponen A dan B:

  • KomponenA: Kode spesifik platform asli
  • KomponenB: Kode independen platform asli

Mungkin ada banyak ComponentA - satu untuk setiap platform, tetapi hanya satu Component B. Penggabungan A tertentu dengan B menghasilkan kode sumber lengkap untuk platform tunggal tetapi tidak setiap platform dapat diperbarui ke versi terbaru dari B sehingga perlu memiliki kontrol atas versi B mana yang harus digunakan untuk dibangun.

Larutan

Satu opsi untuk mencapai apa yang Anda inginkan adalah menggunakan penyiapan berikut ini:

Buat dua pekerjaan Jenkins:

  • "Komponen A" (secara otomatis dipicu pada perubahan SCM)
  • "Komponen B" ("dipicu secara manual")

Langkah #1

Tentukan cabang parameter build untuk "Component B":

[![masukkan deskripsi gambar di sini][1]][1]

Gunakan parameter ini sebagai penentu cabang "Git Plugin":

[![masukkan deskripsi gambar di sini][2]][2]

Sekarang Anda harus dapat secara manual memicu "Component B" build, dengan menentukan parameter cabang (tag) yang tepat untuk itu, misalnya tags/5.3.0.

Langkah #2

Tambahkan "Execute Shell" build step baru ke "Component A" build, yang akan mengekstrak versi "Component B" dari berkas konfigurasi di ruang kerja, dan menyiapkan berkas b.properties dengan parameter build "Component B".

[![masukkan deskripsi gambar di sini][3]][3]

Instal plugin Parameterized Trigger Jenkins, dan tambahkan "Trigger/call builds baru pada proyek lain" build step ke "Component A" job:

[![masukkan deskripsi gambar di sini][4]][4]

Menggunakan file b.properties Anda sebagai sumber parameter build.

Sekarang setiap kali "Component A" dibangun ulang, sebuah "Component B" build baru akan dipicu, dengan cabang/tag target sebagai parameter build.

Menambahkan dukungan wildcard

Jika Anda ingin mendukung versi wildcard, Anda dapat menggunakan perintah git ls-remote untuk menemukan tag terbaru, seperti itu:


#B=$(obtain B version from the config file in a usual way)   

LATEST=$(\
    git ls-remote --tags YOUR_REPOSITORY_URL "$B"\
    |cut -d / -f3|sort -r --version-sort|head -1\
)

cat 
Komentar (3)

Menggunakan Credentials Binding Plugin bekerja dengan sangat baik untuk saya (juga disebutkan oleh @zeppelin)

Langkah-langkah:

Pada bagian Kredensial global:

  1. Tambahkan Kredensial dari tipe: "Nama pengguna dengan kata sandi". Ini harus berupa nama pengguna dan kata sandi untuk server git repositori komponen B menggunakan protokol HTTPS (opsi SSH tidak baik untuk tujuan ini)

Dalam konfigurasi pekerjaan Jenkins Anda:

  1. Letakkan komponen A di Source Code Management biasa di bawah bagian Git semua bidang yang diperlukan (Repositori, Cabang, dll.).

    • Akan lebih jelas dan lebih bersih untuk meletakkan repositori di sub-direktori: di bawah Additional Behaviours pilih Check out to a sub-directory dan tulis: komponen_a
  2. Pastikan juga untuk memeriksa di Build Triggers Build ketika perubahan didorong ke GitHub

  3. Pada bagian Build Environment centang Gunakan teks atau file rahasia

    • masukkan ke dalam Variabel beberapa nama: MY_CRED
    • di Kredensial pilih Kredensial khusus yang Anda buat di langkah 1.

  4. Sekarang dengan menggunakan MY_CRED dalam kode Execute shell Anda akan memiliki akses ke repositori komponen B:

     DIR="component_b"
     if [ "$(ls -A $DIR/.git)" ]; then
         cd $DIR
         git fetch
     else
         git clone https://$MY_CRED@github.com/proj/component_b.git $DIR
         cd $DIR
     fi
     git show

    • Catatan: Anda TIDAK akan melihat pengguna dan kata sandi di log, jadi seharusnya aman. Anda akan melihat: git clone 'https://****@github.com/proj/component_b.git' component_b
  5. Lakukan semua penguraian konfigurasi dari komponen A untuk mendapatkan tag yang diinginkan: TAG=$(cat ./component_a/config.cfg | grep ... | sed ...)

  6. Periksa Tag yang diinginkan: cd komponen_b; git checkout -f $TAG

    • Catatan: tag paksa -f.
  7. Sekarang jalankan kode dan uji sesuai yang diinginkan...

Komentar (1)

1 - apakah menambahkan proyek B sebagai sub repo dari proyek A bisa menjadi solusi yang memungkinkan?

2- (jika menyertakan kode sumber lengkap untuk B benar-benar harus dihindari): apakah mendorong build B ke beberapa repo B_builds, dan menambahkan repo ini sebagai sub-repo dari A menjadi solusi yang memungkinkan ?


Rasional : salah satu cara untuk membuat ketergantungan antara A dan B lebih eksplisit adalah dengan merepresentasikannya di dalam dependensi repositori.

Hal ini akan membutuhkan penambahan langkah ekstra ketika mengelola proyek A:

update `B` sub repo in `A` project, and push this to `A`

setiap kali Anda membuat versi baru untuk B.

Namun, Anda akan memiliki pandangan yang jelas, dari A, tentang kapan versi B diintegrasikan (misalnya: "kami hanya menggunakan B 2.0.1 mulai dari A 4.3.2 &"), dan mendorong ke A akan memicu aliran Jenkins yang biasa Anda lakukan.

Komentar (0)