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
ComponentB
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:
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.
Satu opsi untuk mencapai apa yang Anda inginkan adalah menggunakan penyiapan berikut ini:
Buat dua pekerjaan Jenkins:
Tentukan cabang
parameter build untuk "Component B":
Gunakan parameter ini sebagai penentu cabang "Git Plugin":
Sekarang Anda harus dapat secara manual memicu "Component B" build, dengan menentukan parameter cabang (tag) yang tepat untuk itu, misalnya tags/5.3.0
.
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".
Instal plugin Parameterized Trigger Jenkins, dan tambahkan "Trigger/call builds baru pada proyek lain" build step ke "Component A" job:
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.
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 <<EOF > b.properties
branch=tags/$LATEST
EOF
Ini akan mencantumkan semua tag, yang cocok dengan pola versi "B" di repositori "Component B" jarak jauh, dan menyimpan nomor versi terbaru di variabel LATEST
.
Tambahkan ini ke "Execute Shell" langkah dari "Component A" job,
dan seharusnya dapat menangani pola nomor versi seperti: 5.3.*
Yang menarik adalah bahwa skrip shell akan berjalan sebagai pengguna daemon Jenkins, sehingga harus memiliki kredensial yang tepat yang dikonfigurasi, untuk mengakses repositori Git jarak jauh (misalnya melalui pubkey ssh).
Sebagai alternatif, Anda mungkin ingin melihat Credentials Binding Plugin, untuk menggunakan kembali kredensial Git yang tersimpan di Jenkins itu sendiri.
Anda juga dapat menyelesaikan tugas yang ada dengan menggunakan [Pipeline] gaya Jenkins 2.0(https://jenkins.io/doc/book/pipeline/), yang memungkinkan Anda untuk memeriksa kode untuk komponen A dan B, ke dalam satu ruang kerja, dan kemudian menerapkan beberapa langkah build umum untuk mereka.
Pipeline Anda bisa terlihat seperti ini:
node {
//Settings
def credentialsId = '8fd28e34-b04e-4bc5-874a-87f4c0e05a03'
def repositoryA = 'ssh://[email protected]/projects/a.git'
def repositoryB = 'ssh://[email protected]/projects/b.git'
stage('Checkout component A') {
git credentialsId: credentialsId ,
url: repositoryA , branch : "master"
}
stage("Resolve and checkout component B") {
def deps = readProperties file: 'meta.properties'
echo "Resolved B version = ${deps['b']}"
dir("module/b") {
//Clone/Fetch Component B
checkout scm:[
$class: 'GitSCM',
userRemoteConfigs: [[url: repositoryB, credentialsId: credentialsId]],
branches: [[name: 'refs/tags/*']]
],
changelog: false, poll: false
//Checkout the tag, matching deps['b'] pattern
sshagent([credentialsId]) {
sh "git checkout \$(git tag -l \"${deps['b']}\" |sort -r --version-sort|head -1)"
}
}
}
stage("Build A+B") {
//Apply a common build step
}
}
Di sini kita menggunakan perintah "readProperties", yang merupakan bagian dari Pipeline Utility Steps Plugin untuk mengekstrak "Component B" pola versi dari meta.properties
. Ada juga perintah readYaml, readJSON yang tersedia.
Selanjutnya kita mengambil / mengkloning "Component B", dengan flag changelog: false, polling: false
, untuk mencegahnya didaftarkan untuk polling SCM, ke dalam folder "module/b" dari ruang kerja saat ini.
Kemudian panggil perintah shell untuk memilih tag, berdasarkan pola versi, yang telah kita peroleh di atas, dan periksa (wildcard gaya 5.3.* juga harus berfungsi).
Pemanggilan sh
, dibungkus dalam sshagent, untuk membuatnya menggunakan kembali kredensial yang sesuai dari Jenkins.
kredensial yang sesuai dari penyimpanan kredensial Jenkins.
Menggunakan Credentials Binding Plugin bekerja dengan sangat baik untuk saya (juga disebutkan oleh @zeppelin)
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)Letakkan komponen A di Source Code Management biasa di bawah bagian Git
semua bidang yang diperlukan (Repositori, Cabang, dll.).
Check out to a sub-directory
dan tulis: komponen_a
Pastikan juga untuk memeriksa di Build Triggers Build ketika perubahan didorong ke GitHub
Pada bagian Build Environment centang Gunakan teks atau file rahasia
Variabel
beberapa nama: MY_CREDKredensial
pilih Kredensial khusus yang Anda buat di langkah 1. 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
git clone 'https://****@github.com/proj/component_b.git' component_b
Lakukan semua penguraian konfigurasi dari komponen A untuk mendapatkan tag yang diinginkan: TAG=$(cat ./component_a/config.cfg | grep ... | sed ...)
Periksa Tag yang diinginkan: cd komponen_b; git checkout -f $TAG
-f
.Sekarang jalankan kode dan uji sesuai yang diinginkan...
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.