Pembaruan Proses CI / CD: Persiapan dan Perencanaan

gambar

Pada tahun 2020, mungkin cukup sulit untuk menemukan proyek dalam deskripsi tumpukan yang tidak akan memiliki salah satu dari kata-kata berikut: IaC, microservices, kubernetes, buruh pelabuhan, aws / azure / gcloud, blockchain, ML, VR dan sebagainya. Dan itu luar biasa! Kemajuan tidak berhenti. Kami berkembang, proyek kami berkembang bersama kami, alat yang lebih nyaman dan fungsional muncul yang memecahkan masalah modern.

Halo. Jadi saya ingin memulai artikel ini. Tetapi kemudian saya meninjau beberapa hal, berbicara dengan kolega saya, dan menyadari bahwa saya akan salah. Masih ada proyek yang sudah berusia lebih dari 15 tahun, dengan manajer dan peserta yang beriman lama, dan karenanya proyek ini memiliki tumpukan teknologi kuno yang cukup sulit untuk dipelihara di kebun binatang yang ada. Dan untuk beberapa alasan, proyek ini tidak dapat diperbarui secara global (pelanggan adalah kelaparan, tidak ada pembaruan, proyek sangat besar, dan migrasi tertunda, atau semua orang senang dengan segalanya), dan Anda harus mendukungnya. Bahkan lebih tidak menyenangkan ketika proyek serupa masih aktif dikembangkan. Ini seperti bola salju. Pelanggan dan publik memerlukan fitur, kode membutuhkan pengiriman, server memerlukan perhatian dan perawatan ... Tapi bitpack - jadi secara umum, berhenti mendukung merkuri. Kasus seperti itu diusulkan untuk dipertimbangkan.

Apa yang akan dipertimbangkan: mengubah mercurial-git, memindahkan CI dari CruiseControl.NET ke TeamCity, dari git-deployment ke Octopus dengan deskripsi kecil dari keseluruhan proses.

Teksnya ternyata banyak, sehingga akan dibagi menjadi beberapa bagian terpisah untuk memudahkan persepsi. Akan ada daftar isi.
Bagian 1: apa itu, mengapa tidak seperti, perencanaan, sedikit bash. Saya akan menyebut bagian ini hampir teknis.
Bagian 2: teamcity.
Bagian 3: penyebaran gurita.
Bagian 4: di belakang layar. Momen tidak menyenangkan, rencanakan masa depan, mungkin juga FAQ. Kemungkinan besar, itu juga bisa disebut dekat-teknis.

Saya tidak akan menyebut ini sebagai panduan untuk pengulangan karena banyak alasan: kurangnya perendaman dalam proses proyek karena kurangnya waktu, praktik yang tidak memadai dari hal-hal seperti itu, sebuah monolit besar di mana semua sub-proyek saling terkait erat, dan banyak nuansa lain yang membuat Anda terbakar, heran, tahan dengan mereka , tetapi dalam hal apapun jangan harap. Dan juga, karena fitur-fitur proyek (ini cukup unik), beberapa langkah akan dirancang khusus untuk kasus ini.

Pengantar klasik


Kami memiliki repositori lincah, 300+ (terbuka!) Brunches, ccnet, ccnet + git lain (untuk penyebaran), dan sejumlah modul proyek dengan konfigurasi dan klien kami sendiri, empat lingkungan dan seluruh kumpulan kumpulan di IIS, serta cmd skrip, SQL, lebih dari lima ratus domain, dua lusin build, dan pengembangan aktif sebagai tambahan. Bukan berarti semua ini perlu, tetapi itu berhasil, dan itu tidak nyaman dan panjang. Satu-satunya hal yang membuat saya prihatin adalah kehadiran proyek lain yang membutuhkan perhatian saya. Tidak ada dalam proses bekerja dengan tugas sebesar ini lebih berbahaya daripada kurangnya konsentrasi dan gangguan.

Saya tahu bahwa cepat atau lambat saya harus memperhatikan tugas-tugas lain, dan itulah sebabnya saya menghabiskan banyak waktu mempelajari infrastruktur yang ada sehingga setidaknya tidak ada masalah yang tidak terselesaikan.

Sayangnya, saya tidak dapat memberikan deskripsi lengkap tentang proyek ini, karena NDA, sehingga poin teknis umum akan dipertimbangkan. Semua nama yang terkait dengan proyek juga akan dilukis. Saya minta maaf atas noda hitam pada tangkapan layar.

Salah satu fitur utama dari proyek ini adalah bahwa ia memiliki sejumlah modul yang memiliki satu inti, tetapi berbeda dalam konfigurasi. Ada juga modul dengan pendekatan "khusus", yang dirancang untuk pengecer dan terutama pelanggan besar. Satu modul dapat melayani lebih dari satu klien. Klien harus dipahami sebagai organisasi atau kelompok orang yang terpisah yang mendapatkan akses ke modul tertentu. Setiap klien mendapatkan akses di domainnya sendiri, memiliki desain sendiri dan pengaturan default uniknya sendiri. Klien diidentifikasi oleh domain yang digunakannya.

Skema umum dari bagian proyek ini dapat direpresentasikan sebagai berikut:


Seperti yang Anda lihat, intinya digunakan sama di mana-mana, dan ini bisa digunakan.

Alasan mengapa tugas muncul untuk meninjau dan memperbarui proses CI / CD:

  1. CruiseControl.NET digunakan sebagai sistem pembangunan. Bekerja dengannya adalah prinsip yang meragukan. Konfigurasi XML pada beberapa layar, banyak dependensi dan menghubungkan konfigurasi satu sama lain, kurangnya solusi modern untuk masalah modern.
  2. Beberapa pengembang (terutama prospek) pada proyek harus memiliki akses untuk membangun server, dan mereka terkadang suka mengubah konfigurasi ccnet yang tidak boleh diubah. Coba tebak apa yang terjadi selanjutnya. Anda perlu memiliki manajemen hak yang sederhana dan nyaman dalam sistem CI, tanpa menghilangkan akses pengembang ke server. Sederhananya, tidak ada konfigurasi teks - tidak ada tempat untuk memanjat dengan tangan main-main.
  3. - … CCNET, git. (. ).
  4. , . , . 
  5. - , — ( ) .
  6. . ? ? ? .
  7. Penggunaan sumber daya secara tidak optimal dan proses perakitan dan pengiriman kode yang ketinggalan zaman.

Gambar hingga paragraf 3:


Pada tahap perencanaan, diputuskan untuk menggunakan Teamcity sebagai sistem pembangunan, dan Gurita sebagai sistem penyebaran. Infrastruktur "besi" pelanggan tetap tidak berubah: server khusus yang terpisah untuk pengembangan, pengujian, pementasan dan produksi, serta server pengecer (terutama lingkungan produksi).

Pelanggan diberikan Bukti Konsep pada contoh salah satu modul, rencana tindakan ditulis, pekerjaan persiapan dilakukan (instalasi, konfigurasi, dll.). Mungkin tidak ada gunanya menggambarkan hal ini. Cara memasang city team dapat dibaca di situs web resmi. Saya akan membahas secara terpisah beberapa persyaratan yang dirumuskan untuk sistem baru:

  1. Perawatan mudah dengan semua konsekuensinya (cadangan, pembaruan, penyelesaian masalah, jika ada).
  2. Keuniversalan. Idealnya, kembangkan skema umum yang dengannya semua modul dirakit dan dikirimkan, dan gunakan sebagai templat.
  3. Minimalkan waktu untuk menambahkan konfigurasi dan pemeliharaan gedung baru. Klien ditambahkan / dihapus. Terkadang menjadi perlu untuk membuat pengaturan baru. Sangat penting bahwa saat membuat modul baru seharusnya tidak ada penundaan dengan konfigurasi pengirimannya.

Pada sekitar titik ini, kami ingat penghentian dukungan untuk repositori lincah dengan bitbucket, dan persyaratan ditambahkan untuk mentransfer repositori ke git sambil mempertahankan cabang dan sejarah komitmen.

Persiapan: konversi repositori


Tampaknya seseorang dengan jelas memecahkan masalah ini di hadapan kita dan bukannya kita. Anda hanya perlu menemukan solusi kerja yang sudah jadi. Ekspor cepat ternyata tidak terlalu cepat. Plus, itu tidak berhasil. Sayangnya, tidak ada log dan tangkapan layar yang tersisa. Faktanya adalah dia tidak bisa. Bitbucket tidak menyediakan konverter sendiri (tetapi bisa). Beberapa lagi metode Google, dan juga oleh. Saya memutuskan untuk menulis skrip saya sendiri, lagi pula ini bukan satu-satunya repositori lincah, itu akan berguna di masa depan. Perkembangan awal akan disajikan di sini (karena mereka masih tetap dalam bentuk yang sama). Logika kerja terlihat seperti ini:

  1. Kami mengambil ekstensi mercurial hggit sebagai dasar. 
  2. Kami mendapatkan daftar semua cabang dari repositori mercurial. 
  3. Kami mengonversi nama cabang (terima kasih untuk lincah dan pengembang untuk spasi dalam nama cabang, terima kasih khusus untuk umlaut dan karakter lain yang menambah keceriaan untuk kehidupan).
  4. Buat bookmark (bookmark hg) dan dorong ke repositori perantara. Untuk apa? Karena bitbucket, dan karena Anda tidak dapat membuat bookmark dengan nama yang sama dengan nama cabang (misalnya, pementasan). 
  5. Dalam repositori (sudah git) yang baru, hapus postfix dari nama cabang dan migrasi hgignore ke gitignore. 
  6. Dorong ke repositori utama.

Daftar perintah sesuai dengan poin:

  1. $ cd /path/to/hg/repo
    $ cat << EOF >> ./.hg/hgrc
    [extensions]
    hggit=
    EOF
    
  2. $ hg branches > ../branches
    
  3. #!/usr/bin/env bash
    hgBranchList="./branches"
    sed -i 's/:.*//g' ${hgBranchList}
    symbolsToDelete=$(awk '{print $NF}' FS=" " ${hgBranchList} > sym_to_del.tmp)
     
    i=0
    while read hgBranch; do
      hgBranches[$i]=${hgBranch}
      i=$((i+1))
    done <${hgBranchList}
     
    i=0
    while read str; do
      strToDel[$i]=${str}
      i=$((i+1))
    done < ./sym_to_del.tmp
     
    for i in ${!strToDel[@]}
    do
      echo ${hgBranches[$i]} | sed "s/${strToDel[$i]}//" >> result.tmp
    done
     
    sed -i 's/[ \t]*$//' result.tmp
    sed 's/^/"/g' result.tmp > branches_hg
    sed -i 's/$/"/g' branches_hg
    sed 's/ /-/g' result.tmp > branches_git
    sed -i 's/-\/-/\//g' branches_git
    sed -i 's/-\//\//g' branches_git
    sed -i 's/\/-/\//g' branches_git
    sed -i 's/---/-/g' branches_git
    sed -i 's/--/-/g' branches_git
    rm sym_to_del.tmp
    rm result.tmp
    
  4. #!/usr/bin/env bash
    gitBranchList="./branches_git"
    hgBranchList="./branches_hg"
    hgRepo="/repos/reponame"
     
    i=0
    while read hgBranch; do
      hgBranches[$i]=${hgBranch}
      i=$((i+1))
    done <${hgBranchList}
     
    i=0
    while read gitBranch; do
      gitBranches[$i]=${gitBranch}
      i=$((i+1))
    done <${gitBranchList}
     
    cd ${hgRepo}
    for i in ${!gitBranches[@]}
    do
      hg bookmark -r "${hgBranches[$i]}" "${gitBranches[$i]}-cnv"
    done
     
    hg push git+ssh://git@bitbucket.org:username/reponame-temp.git
    echo "Done."
    
  5. #!/bin/bash
    # clone repo, run git branch -a, delete remotes/origin words to leave only branch names, delete -cnv postfix, delete default branch string because we can't delete it
    repo="/repos/repo"
    gitBranchList="./branches_git"
    defaultBranch="default-cnv"
    while read gitBranch; do   gitBranches[$i]=${gitBranch};   i=$((i+1)); done < $gitBranchList
    cd $repo
    for i in ${!gitBranches[@]}; do git checkout ${gitBranches[$i]}-cnv; done
    git checkout $defaultBranch
    for i in ${!gitBranches[@]}; do
        git branch -m ${gitBranches[$i]}-cnv ${gitBranches[$i]}
        git push origin :${gitBranches[$i]}-cnv ${gitBranches[$i]}
        git push origin -u ${gitBranches[$i]}
    done
    
  6. #!/bin/bash
    # clone repo, run git branch -a, delete remotes/origin words to leave only branch names, delete -cnv postfix, delete default branch string because we can't delete it
    repo="/repos/repo"
    gitBranchList="./branches_git"
    defaultBranch="default"
    while read gitBranch; do   gitBranches[$i]=${gitBranch};   i=$((i+1)); done < $gitBranchList
    cd $repo
    for i in ${!gitBranches[@]}; do
        git checkout ${gitBranches[$i]}
        sed -i '1d' .hgignore
        mv .hgignore .gitignore
        git add .
        git commit -m "Migrated ignore file"
    done
    

Saya akan mencoba menjelaskan arti dari beberapa tindakan, yaitu penggunaan repositori perantara. Awalnya, dalam repositori setelah konversi, nama-nama cabang berisi postfix "-cnv". Ini karena fitur bookmark hg. Anda perlu menghapus postfix ini, dan juga membuat file gitignore alih-alih hgignore. Semua ini menambah histori, dan karenanya meningkatkan ukuran repositori (dan tidak masuk akal). Sebagai contoh lain, saya bisa mengutip yang berikut: mencoba membuat repositori, dan mendorong komit pertama ke 300M dengan kode ke dalamnya. Kemudian tambahkan ke gitignore, dan dorong tanpa itu. Dia akan tetap dalam sejarah. Sekarang cobalah untuk menghapusnya dari histori (git filter-branch). Dengan jumlah komit tertentu, ukuran repositori yang dihasilkan tidak akan berkurang, tetapi meningkat. Ini diselesaikan dengan optimasi, tetapi tidak dapat dimulai pada bitbucket.Itu dilakukan hanya ketika mengimpor repositori. Oleh karena itu, semua operasi kasar dilakukan dengan perantara, dan kemudian impor ke yang baru dilakukan. Ukuran repositori perantara di final adalah 1,15G, dan ukuran 350M yang dihasilkan. 

Kesimpulan


Seluruh proses migrasi dibagi menjadi beberapa tahap, yaitu:

  • persiapan (demo kepada pelanggan menggunakan contoh one build, instalasi perangkat lunak, konversi repositori, memperbarui konfigurasi ccnet yang ada);
  • Konfigurasi CI / CD untuk lingkungan dev dan pengujiannya (sistem lama tetap bekerja secara paralel);
  • Pengaturan CI / CD untuk lingkungan yang tersisa (paralel dengan "baik" yang ada) dan pengujian;
  • dev migrasi, pementasan dan uji;
  • Memigrasi produksi dan mentransfer domain dari instance IIS lama ke yang baru.

Deskripsi fase persiapan yang berhasil diselesaikan saat ini sedang diselesaikan. Beberapa keberhasilan muluk tidak tercapai di sini, kecuali bahwa sistem yang ada tidak rusak dan repositori lincah di git dimigrasikan. Namun, tanpa deskripsi proses ini, tidak akan ada konteks untuk bagian yang lebih teknis. Bagian selanjutnya akan menjelaskan proses pengaturan sistem CI berdasarkan teamcity.

All Articles