ProHoster > blog > administrasi > Lingkaran neraka dengan Tindakan GitHub (membangun pipa CI/CD untuk proyek Java)
Lingkaran neraka dengan Tindakan GitHub (membangun pipa CI/CD untuk proyek Java)
Saya sering harus membangun saluran pipa untuk proyek pembangunan di Jawa. Terkadang open source, terkadang tidak. Saya baru-baru ini memutuskan untuk mencoba memindahkan beberapa repositori saya dari Travis-CI dan TeamCity ke GitHub Actions, dan inilah hasilnya.
Apa yang akan kami otomatisasi?
Pertama, kita membutuhkan proyek yang akan kita otomatisasi, mari kita buat aplikasi kecil di Spring boot/Java 11/Maven. Untuk keperluan artikel ini, kami tidak akan tertarik pada logika aplikasi sama sekali; infrastruktur di sekitar aplikasi penting bagi kami, jadi pengontrol REST API sederhana sudah cukup bagi kami.
Anda dapat melihat sumbernya di sini: github.com/antkorwin/github-actions Semua tahapan pembangunan saluran pipa tercermin dalam permintaan tarik untuk proyek ini.
JIRA dan perencanaan
Patut dikatakan bahwa kami biasanya menggunakan JIRA sebagai pelacak masalah, jadi mari buat papan terpisah untuk proyek ini dan tambahkan masalah pertama di sana:
Nanti kita akan kembali ke hal-hal menarik apa yang dapat ditawarkan oleh JIRA dan GitHub dalam kombinasi.
Kami mengotomatiskan perakitan proyek
Proyek pengujian kami dibangun melalui maven, jadi pembuatannya cukup sederhana, yang kami perlukan hanyalah paket mvn clean.
Untuk melakukan ini menggunakan Github Actions, kita perlu membuat file di repositori yang menjelaskan alur kerja kita, ini bisa dilakukan dengan file yml biasa, saya tidak bisa mengatakan bahwa saya suka "pemrograman yml", tapi apa yang bisa kita lakukan - kita melakukannya di direktori .github/ alur kerja/ file build.yml di mana kami akan menjelaskan tindakan saat membangun cabang master:
on β ini adalah deskripsi acara di mana skrip kita akan diluncurkan.
pada: pull_request/push β menunjukkan bahwa alur kerja ini perlu diluncurkan setiap kali push dilakukan ke master dan permintaan pull dibuat.
Berikut ini adalah uraian tugas (pekerjaan) dan langkah eksekusi (tangga) untuk setiap tugas.
berjalan terus - di sini kita dapat memilih OS target, yang mengejutkan, Anda bahkan dapat memilih Mac OS, tetapi pada repositori pribadi ini cukup mahal (dibandingkan dengan Linux).
kegunaan memungkinkan Anda untuk menggunakan kembali tindakan lain, misalnya, menggunakan tindakan tindakan/setup-java yang kami instal di lingkungan untuk Java 11.
Melalui dengan kita dapat menentukan parameter yang digunakan untuk meluncurkan tindakan, pada dasarnya ini adalah argumen yang akan diteruskan ke tindakan tersebut.
Yang tersisa hanyalah menjalankan proyek yang dibangun di Maven: run: mvn -B clean package bendera -B mengatakan bahwa kita memerlukan mode non-interaktif agar pakar tiba-tiba tidak mau menanyakan sesuatu kepada kita
Besar! Sekarang, setiap kali Anda berkomitmen pada master, pembangunan proyek dimulai.
Mengotomatiskan peluncuran pengujian
Perakitannya bagus, tetapi kenyataannya, sebuah proyek dapat dirakit dengan aman, tetapi tidak berhasil. Oleh karena itu, langkah selanjutnya adalah mengotomatiskan pengujian yang dijalankan. Selain itu, cukup mudah untuk melihat hasil kelulusan tes ketika Anda melakukan tinjauan PR - Anda tahu pasti bahwa tes tersebut lulus dan tidak ada yang lupa menjalankan cabangnya sebelum melakukan penggabungan.
Kami akan menjalankan pengujian saat membuat permintaan tarik dan menggabungkannya ke dalam master, dan pada saat yang sama kami akan menambahkan pembuatan laporan cakupan kode.
Untuk menutupi pengujian, saya menggunakan codecov bersama dengan plugin jacoco. codecov memiliki tindakannya sendiri, tetapi memerlukan token agar dapat berfungsi dengan permintaan penarikan kami:
${{ secrets.CODECOV_TOKEN }} β kita akan melihat konstruksi ini lebih dari sekali, rahasia adalah mekanisme untuk menyimpan rahasia di GitHub, kita dapat menulis di sana kata sandi/tokens/host/url dan data lain yang tidak boleh disertakan dalam basis kode repositori.
Anda dapat menambahkan variabel ke rahasia dalam pengaturan repositori di GitHub:
Anda bisa mendapatkan token di codecov.io Setelah otorisasi melalui GitHub, untuk menambahkan proyek publik Anda hanya perlu mengikuti tautan seperti ini: Nama pengguna GitHub/[nama repo]. Repositori pribadi juga dapat ditambahkan; untuk melakukan ini, Anda perlu memberikan hak codecov ke aplikasi di Github.
Sekarang bot codecov akan memasukkan setiap permintaan penarikan kami dan menambahkan grafik perubahan cakupan:
Mari tambahkan penganalisa statis
Di sebagian besar proyek sumber terbuka, saya menggunakan sonar cloud untuk analisis kode statis, cukup mudah untuk terhubung ke travis-ci. Jadi, merupakan langkah logis saat bermigrasi ke GitHub Actions untuk melakukan hal yang sama. Pasar tindakan adalah hal yang keren, tapi kali ini sedikit mengecewakan saya, karena karena kebiasaan saya menemukan tindakan yang saya butuhkan dan menambahkannya ke alur kerja. Namun ternyata sonar tidak mendukung pengerjaan tindakan untuk menganalisis proyek di maven atau gradle. Tentu saja, ini tertulis di dokumentasi, tapi siapa yang membacanya?!
Hal ini tidak mungkin dilakukan melalui tindakan, jadi kami akan melakukannya melalui plugin mvn:
SONAR_TOKEN - dapat diperoleh di sonarcloud.io dan Anda perlu mendaftarkannya secara rahasia. GITHUB_TOKEN - ini adalah token bawaan yang dihasilkan GitHub, dengan bantuan sonarcloud[bot] yang dapat masuk ke Git untuk meninggalkan pesan kepada kami dalam permintaan tarik.
Dsonar.projectKey β nama proyek di sonar, Anda dapat melihatnya di pengaturan proyek.
Dsonar.organisasi β nama organisasi dari GitHub.
Kami membuat permintaan tarik dan menunggu sonarcloud[bot] muncul di komentar:
Manajemen rilis
Build telah dikonfigurasi, pengujian telah dijalankan, dan kami dapat melakukan rilis. Mari kita lihat bagaimana GitHub Actions dapat membuat manajemen rilis menjadi lebih mudah.
Di tempat kerja, saya memiliki proyek yang basis kodenya ada di bitbucket (semuanya seperti dalam cerita itu βSaya menulis ke bitbucket di siang hari, berkomitmen ke GitHub di malam hariβ). Sayangnya, bitbucket tidak memiliki alat manajemen rilis bawaan. Ini adalah masalah, karena untuk setiap rilis Anda harus secara manual membuat halaman di confluence dan membuang semua fitur yang disertakan dalam rilis di sana, mencari melalui istana pikiran, tugas di jira, melakukan di repositori. Ada banyak kemungkinan untuk membuat kesalahan, Anda bisa melupakan sesuatu atau memasukkan sesuatu yang sudah dirilis terakhir kali, terkadang tidak jelas apa yang mengklasifikasikan permintaan penarikan - apakah itu fitur atau perbaikan bug, atau tes pengeditan, atau sesuatu infrastruktur.
Bagaimana tindakan GitHub dapat membantu kita? Ada tindakan hebat - drafter rilis, ini memungkinkan Anda mengatur templat file catatan rilis untuk mengatur kategori permintaan tarik dan secara otomatis mengelompokkannya dalam file catatan rilis:
Contoh templat untuk menyiapkan laporan (.github/release-draafter.yml):
Semua permintaan penarikan mulai sekarang akan dikumpulkan dalam catatan rilis secara otomatis - ajaib!
Di sini mungkin timbul pertanyaan: bagaimana jika pengembang lupa memberi tag di PR? Maka tidak jelas harus memasukkannya ke dalam kategori mana, dan sekali lagi Anda harus menanganinya secara manual, dengan masing-masing PR secara terpisah. Untuk memperbaiki masalah ini, kita dapat menggunakan tindakan lain - pemverifikasi label - yang memeriksa keberadaan tag pada permintaan penarikan. Jika tidak ada tag yang diperlukan, maka pemeriksaan akan gagal dan kami akan melihat pesan tentang ini di permintaan penarikan kami.
Sekarang setiap permintaan tarik harus ditandai dengan salah satu tag: type:fix, type:features, type:documentation, type:tests, type:config.
Anotasi otomatis permintaan tarik
Karena kita telah menyentuh topik seperti kerja efektif dengan permintaan tarik, ada baiknya membicarakan tindakan seperti pelabel, yang menempatkan tag di PR berdasarkan file mana yang telah diubah. Misalnya, kita dapat menandai sebagai [build] permintaan penarikan apa pun yang berisi perubahan pada direktori .github/workflow.
Saya tidak berhasil memasangkan tindakan yang secara otomatis menempatkan label dalam permintaan tarik dengan tindakan yang memeriksa keberadaan label yang diperlukan; label yang cocok tidak ingin melihat label yang ditambahkan oleh bot. Tampaknya lebih mudah untuk menulis tindakan Anda sendiri yang menggabungkan kedua tahap tersebut. Namun bahkan dalam bentuk ini cukup nyaman digunakan, Anda perlu memilih label dari daftar saat membuat permintaan tarik.
Saatnya untuk menyebarkan
Saya mencoba beberapa opsi penerapan melalui GitHub Actions (melalui ssh, melalui scp, dan menggunakan docker-hub), dan saya dapat mengatakan bahwa, kemungkinan besar, Anda akan menemukan cara untuk mengunggah biner ke server, tidak peduli seberapa bengkoknya saluran pipa Anda. adalah.
Saya menyukai opsi untuk menyimpan seluruh infrastruktur di satu tempat, jadi mari kita lihat cara menerapkan Paket GitHub (ini adalah repositori untuk konten biner, npm, jar, docker).
Skrip untuk membuat image buruh pelabuhan dan menerbitkannya dalam Paket GitHub:
Pertama, kita perlu membuat file JAR aplikasi kita, setelah itu kita menghitung jalur ke registri buruh pelabuhan GitHub dan nama gambar kita. Ada beberapa trik di sini yang belum kami temukan:
konstruksi seperti: echo β::set-output name=NAME::VALUEβ memungkinkan Anda menyetel nilai variabel pada langkah saat ini, sehingga dapat dibaca di semua langkah lainnya.
Anda bisa mendapatkan nilai kumpulan variabel pada langkah sebelumnya melalui pengidentifikasi langkah ini: ${{steps.global_env.outputs.DOCKERHUB_IMAGE_NAME }}
Variabel GITHUB_REPOSITORY standar menyimpan nama repositori dan pemiliknya (βpemilik/nama repoβ). Untuk memotong semuanya dari baris ini kecuali nama repositori, kita akan menggunakan sintaks bash: ${GITHUB_REPOSITORY#*/}
Selanjutnya kita perlu membuat image buruh pelabuhan:
Untuk menunjukkan versi gambar, kami menggunakan digit pertama dari hash SHA dari komit - GITHUB_SHA ada juga nuansa di sini, jika Anda membuat build seperti itu tidak hanya saat menggabungkan ke master, tetapi juga sesuai dengan pembuatan permintaan tarik acara, maka SHA mungkin tidak cocok dengan hash yang kita lihat di riwayat git, karena tindakan/tindakan checkout membuat hash uniknya sendiri untuk menghindari tindakan kebuntuan di PR.
Jika semuanya berjalan dengan baik, lalu membuka bagian paket (https://github.com/antkorwin/github-actions/packages) di repositori, Anda akan melihat gambar buruh pelabuhan baru:
Di sana Anda juga dapat melihat daftar versi gambar buruh pelabuhan.
Yang tersisa hanyalah mengonfigurasi server kami agar berfungsi dengan registri ini dan memulai ulang layanan. Saya mungkin akan membicarakan cara melakukan ini melalui systemd lain kali.
Pemantauan
Mari kita lihat opsi sederhana tentang cara melakukan pemeriksaan kesehatan untuk aplikasi kita menggunakan GitHub Actions. Aplikasi boot kami memiliki aktuator, jadi kami bahkan tidak perlu menulis API untuk memeriksa statusnya; kami sudah melakukan semuanya untuk yang malas. Anda hanya perlu menarik hostnya: SERVER-URL:PORT/actuator/health
Yang kita perlukan hanyalah menulis tugas untuk mengecek server menggunakan cron, dan jika tiba-tiba tidak menjawab kita maka kita akan mengirimkan notifikasi melalui telegram.
Pertama, mari kita cari tahu cara menjalankan alur kerja cron:
Mari kita periksa status server secara manual melalui curl:
jobs:
ping:
runs-on: ubuntu-18.04
steps:
- name: curl actuator
id: ping
run: |
echo "::set-output name=status::$(curl ${{secrets.SERVER_HOST}}/api/actuator/health)"
- name: health check
run: |
if [[ ${{ steps.ping.outputs.status }} != *"UP"* ]]; then
echo "health check is failed"
exit 1
fi
echo "It's OK"
Pertama, kita simpan ke dalam variabel apa yang ditanggapi server terhadap permintaan tersebut, pada langkah selanjutnya kita periksa apakah statusnya UP dan, jika tidak demikian, maka kita keluar dengan kesalahan. Jika Anda perlu "membanjiri" suatu tindakan dengan tangan Anda, maka keluar 1 - senjata yang cocok.
- name: send alert in telegram
if: ${{ failure() }}
uses: appleboy/telegram-action@master
with:
to: ${{ secrets.TELEGRAM_TO }}
token: ${{ secrets.TELEGRAM_TOKEN }}
message: |
Health check of the:
${{secrets.SERVER_HOST}}/api/actuator/health
failed with the result:
${{ steps.ping.outputs.status }}
Kami mengirim ke telegram hanya jika tindakan gagal pada langkah sebelumnya. Untuk mengirim pesan kami menggunakan appleboy/telegram-action; Anda dapat membaca tentang cara mendapatkan token bot dan id chat di dokumentasi: github.com/appleboy/telegram-action
Jangan lupa tulis rahasia di Github: URL untuk server dan token untuk bot telegram.
Lagu bonus - JIRA untuk yang malas
Saya berjanji bahwa kami akan kembali ke JIRA, dan kami telah kembali. Ratusan kali saya mengamati situasi stand-up ketika pengembang membuat fitur, menggabungkan cabang, tetapi lupa menyeret masalah tersebut ke JIRA. Tentu saja, jika semua ini dilakukan di satu tempat, itu akan lebih mudah, tetapi sebenarnya kita menulis kode di IDE, menggabungkan cabang ke bitbucket atau GitHub, lalu menyeret tugas ke Jira, untuk ini kita perlu membuka jendela baru , terkadang masuk lagi dan lain-lain. Ketika Anda benar-benar mengingat apa yang perlu Anda lakukan selanjutnya, maka tidak ada gunanya membuka papan lagi. Akibatnya, di pagi hari saat standup Anda perlu meluangkan waktu untuk memperbarui papan tugas.
GitHub juga akan membantu kita dalam tugas rutin ini; sebagai permulaan, kita dapat menyeret masalah secara otomatis ke kolom code_review ketika kita mengirimkan permintaan penarikan. Yang perlu Anda lakukan hanyalah mengikuti konvensi penamaan cabang:
misalnya, jika kunci proyek "GitHub Actions" adalah GA, maka GA-8-jira-bot bisa menjadi cabang pelaksanaan tugas GA-8.
Integrasi dengan JIRA berhasil melalui tindakan dari Atlassian, tindakan tersebut tidak sempurna, saya harus mengatakan bahwa beberapa di antaranya tidak berhasil sama sekali untuk saya. Namun yang akan kita bahas hanya yang benar-benar berfungsi dan digunakan secara aktif.
Pertama, Anda harus masuk ke JIRA menggunakan tindakan: atlassian/gajira-login
Kami mengekstrak pengidentifikasi tugas dari nama cabang:
- name: Find Issue
id: find_issue
shell: bash
run: |
echo "::set-output name=ISSUE_ID::$(echo ${GITHUB_HEAD_REF} | egrep -o 'GA-[0-9]{1,4}')"
echo brach name: $GITHUB_HEAD_REF
echo extracted issue: ${GITHUB_HEAD_REF} | egrep -o 'GA-[0-9]{1,4}'
- name: Check Issue
shell: bash
run: |
if [[ "${{steps.find_issue.outputs.ISSUE_ID}}" == "" ]]; then
echo "Please name your branch according to the JIRA issue: [project_key]-[task_number]-branch_name"
exit 1
fi
echo succcessfully found JIRA issue: ${{steps.find_issue.outputs.ISSUE_ID}}
Jika Anda mencari di pasar GitHub, Anda dapat menemukan tindakan untuk tugas ini, tetapi saya harus menulis hal yang sama menggunakan grep menggunakan nama cabang, karena tindakan dari Atlassian ini tidak ingin mengerjakan proyek saya dengan cara apa pun. , untuk mencari tahu apa yang salah di sana - lebih lama daripada melakukan hal yang sama dengan tangan Anda.
Yang tersisa hanyalah memindahkan tugas ke kolom βTinjauan kodeβ saat membuat permintaan tarik:
Ada tindakan khusus untuk ini di GitHub, yang diperlukan hanyalah ID masalah yang diperoleh pada langkah sebelumnya dan otorisasi di JIRA yang kami lakukan di atas.
Dengan cara yang sama, Anda dapat menyeret tugas saat menggabungkan ke master, dan acara lainnya dari alur kerja GitHub. Secara umum, semuanya tergantung pada imajinasi dan keinginan Anda untuk mengotomatisasi proses rutin.
Temuan
Jika Anda melihat diagram DEVOPS klasik, kami telah membahas semua tahapan, kecuali mungkin pengoperasiannya, saya rasa jika Anda mencobanya, Anda dapat menemukan beberapa tindakan di pasar untuk integrasi dengan sistem pusat bantuan, jadi kami akan berasumsi bahwa jalur pipa telah berubah harus menyeluruh dan kesimpulan dapat diambil berdasarkan penggunaannya.
Pro:
Marketplace dengan aksi siap pakai untuk semua kesempatan, ini sangat keren. Di sebagian besarnya, Anda juga dapat melihat kode sumber untuk memahami cara memecahkan masalah serupa atau memposting permintaan fitur ke pembuatnya langsung di repositori GitHub.
Memilih platform target untuk perakitan: Linux, mac os, windows merupakan fitur yang cukup menarik.
Paket Github adalah hal yang luar biasa, nyaman untuk menyimpan seluruh infrastruktur di satu tempat, Anda tidak perlu menjelajahi jendela yang berbeda, semuanya berada dalam radius satu atau dua klik mouse dan terintegrasi sempurna dengan GitHub Actions. Dukungan registri Docker dalam versi gratis juga merupakan keuntungan yang baik.
GitHub menyembunyikan rahasia di log build, jadi menggunakannya untuk menyimpan kata sandi dan token tidaklah terlalu menakutkan. Selama semua percobaan saya, saya tidak pernah bisa melihat rahasia dalam bentuknya yang murni di konsol.
Gratis untuk proyek Sumber Terbuka
Cons:
YML, yah, aku tidak menyukainya. Saat bekerja dengan aliran seperti itu, pesan komit paling umum yang saya miliki adalah "perbaiki format yml", lalu Anda lupa meletakkan tab di suatu tempat, atau Anda menulisnya di baris yang salah. Secara umum, duduk di depan layar dengan busur derajat dan penggaris bukanlah pengalaman yang paling menyenangkan.
DEBUG, men-debug aliran dengan commit, menjalankan pembangunan kembali, dan mengeluarkan output ke konsol tidak selalu mudah, tetapi ini lebih merupakan kategori "Anda berlebihan"; Anda terbiasa bekerja dengan IDEA yang mudah digunakan, ketika Anda dapat men-debug apa pun .
Anda dapat menulis tindakan Anda pada apa pun jika Anda membungkusnya di Docker, tetapi hanya javascript yang didukung secara asli, tentu saja ini masalah selera, tapi saya lebih suka yang lain daripada js.
Minggu depan saya akan tampil bersama laporan pada konferensi Piter Heisenbug 2020. Saya tidak hanya akan memberi tahu Anda cara menghindari kesalahan saat menyiapkan data pengujian, tetapi juga berbagi rahasia saya dalam bekerja dengan kumpulan data dalam aplikasi Java!