Jenkins高階篇之Pipeline實踐篇-9-Selenium和Jenkins持續整合-日誌檔案歸檔和外掛rebuild介紹--完結篇
寫到這裡,我記得我前面提出的兩個需求,引數化構建和報告和日誌顯示就差一個日誌檔案顯示了。本篇就先來介紹如何在jenkins上提供日誌檔案下載,第二個介紹一下rebuild外掛。如果一個jenkins job有十個以上的引數化構建,那麼下一次構建,選擇rebuild選單是最方便,rebuild選單會記住上一次構建的輸入值,支援修改後再提交構建。
1.日誌檔案歸檔
早期jenkins中,檔案歸檔使用的命令是archive,然後這個方法就棄用了,改成了archiveArtifacts,這裡我兩個方法都測試了下。這裡我先貼出關鍵程式碼,完整程式碼我後面給出,大部分程式碼都是和前面一篇相同。
post{ always{ script{ node(win_node){ //delete report file println "Start to delete old html report file." bat("del /s /q C:\\JenkinsNode\\workspace\\selenium-pipeline-demo\\test-output\\*.html") //list the log files on jenkins ui archive 'log/*.log' } } } }
看最後一行程式碼,archive是方法名稱,後面表示在根目錄下的log資料夾下所有以.log結尾的檔案進行歸檔操作,在jenkns當前構建頁面可以看到這些歸檔檔案。
我測試了下,發現有下面這個提示錯誤,構建失敗。
The archive step is deprecated, please use archiveArtifacts instead.
然後,只能嘗試archiveArtifacts了。
post{ always{ script{ node(win_node){ //delete report file println "Start to delete old html report file." bat("del /s /q C:\\JenkinsNode\\workspace\\selenium-pipeline-demo\\test-output\\*.html") //list the log files on jenkins ui //archive 'log/*.log' archiveArtifacts artifacts: 'log/*.log' } } } }
測試效果如下。
如果你想看日誌內容,直接點選紅框內的檔案就可以。當然,我們框架內log資料夾下有三個日誌檔案,這裡還缺一個html檔案。
你可以歸檔的時候寫成以下這樣。
post{ always{ script{ node(win_node){ //delete report file println "Start to delete old html report file." bat("del /s /q C:\\JenkinsNode\\workspace\\selenium-pipeline-demo\\test-output\\*.html") //list the log files on jenkins ui archiveArtifacts artifacts: 'log/*.*' } } } }
我們知道,按照上面這麼寫,就是把log資料夾下所有檔案都歸檔,效果如下
這裡三個檔案都出來,但是不要擔心.gitkeep這個檔案,這個我原來程式碼倉庫中,需要保留一個空的log資料夾,在git中為了能push一個空的資料夾,需要在這個資料夾下寫一個.gitkeep檔案,並且在這個檔案寫幾行內容,內容如下。
# Ignore everything in this directory
*
# Except this file !.gitkeep
同理,在我github這個程式碼倉庫中,有log,screenshots,test-output三個資料夾都使用了這個檔案。以上兩種方法,一個是精確到log檔案型別,一個是模糊的一個資料夾下所有檔案都歸檔。結合你自己專案實際情況,自己選擇取捨。
2.這裡介紹一個rebuild外掛
在pipeline的開發和測試過程中,有一個rebuild外掛,這裡介紹下。rebuild安裝完會變成一個選單,點選之後,會自動記錄前面的構建時填寫的引數。這樣其實是很方便,特別是一個專案有十多個引數是需要每次構建都選擇或者填寫的,而且預設值不一定是你要的,這樣如果沒有rebuild功能,你每次點選引數化構建,都需要填寫多次引數變數的值,這樣就很麻煩。
所以,你得去安裝一個rebuild的外掛,外掛名稱就叫rebuild,搜尋並安裝,很簡單,下面是一個效果圖。
這裡注意下rebuild和replay的區別,在實際工作中,兩者往往是經常使用,前一個構建使用了replay是為了debug,改程式碼,下一個構建為了再次驗證,點選rebuild就可以。
上面的圖表示,下一次構建,也就是第83次構建是在82的記錄下觸發的,這個時候按鈕是Rebuild,而不是引數化構建頁面的build的按鈕。
3.新增事後刪除日誌功能
和前面報告一樣,每次構建,都會產生日誌檔案和報告檔案,那麼我們這裡也新增事後清空日誌資料夾的功能。當然,也會把.gitkeep檔案一塊刪除,但是由於刪除的是本地拉取完之後的檔案,不會影響到github上的檔案,所以這個就不要擔心。
這裡,我把兩個groovy檔案的程式碼都貼出來。
檔案:selenium-jenkins.groovy
import hudson.model.*;
pipeline{
agent any
parameters {
string(name: 'BROWSER_TYPE', defaultValue: 'chrome', description: 'Type a browser type, should be chrome/firefox')
string(name: 'TEST_SERVER_URL', defaultValue: '', description: 'Type the test server url')
string(name: 'NODE', defaultValue: 'win-anthony-demo', description: 'Please choose a windows node to execute this job.')
}
stages{
stage("Initialization"){
steps{
script{
browser_type = BROWSER_TYPE?.trim()
test_url = TEST_SERVER_URL?.trim()
win_node = NODE?.trim()
}
}
}
stage("Git Checkout"){
steps{
script{
node(win_node) {
checkout([$class: 'GitSCM', branches: [[name: '*/master']],
userRemoteConfigs: [[credentialsId: '6f4fa66c-eb02-46dc-a4b3-3a232be5ef6e',
url: 'https://github.com/QAAutomationLearn/JavaAutomationFramework.git']]])
}
}
}
}
stage("Set key value"){
steps{
script{
node(win_node){
selenium_test = load env.WORKSPACE + "\\pipeline\\selenium.groovy"
config_file = env.WORKSPACE + "\\Configs\\config.properties"
try{
selenium_test.setKeyValue("browser", browser_type, config_file)
file_content = readFile config_file
println file_content
}catch (Exception e) {
error("Error met:" + e)
}
}
}
}
}
stage("Run Selenium Test"){
steps{
script{
node(win_node){
run_bat = env.WORKSPACE + "\\run.bat"
bat (run_bat)
}
}
}
}
stage("Publish Selenium HTML Report"){
steps{
script{
node(win_node){
html_file_name = selenium_test.get_html_report_filename("test-output")
publishHTML (target: [
allowMissing: false,
alwaysLinkToLastBuild: false,
keepAll: true,
reportDir: 'test-output',
reportFiles: html_file_name,
reportName: "Selenium Test Report"
])
}
}
}
}
}
post{
always{
script{
node(win_node){
//delete report file
println "Start to delete old html report file."
bat("del /s /q C:\\JenkinsNode\\workspace\\selenium-pipeline-demo\\test-output\\*.html")
//archive the log files on jenkins ui
archive 'log/*.*'
println "Start to delete old log files."
bat("del /s /q C:\\JenkinsNode\\workspace\\selenium-pipeline-demo\\log\\*.*")
}
}
}
}
}
檔案:selenium.groovy
import hudson.model.*;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
def setKeyValue(key, value, file_path) {
// read file, get string object
file_content_old = readFile file_path
println file_content_old
lines = file_content_old.tokenize("\n")
new_lines = []
lines.each { line ->
if(line.trim().startsWith(key)) {
line = key + "=" + value
new_lines.add(line)
}else {
new_lines.add(line)
}
}
// write into file
file_content_new = ""
new_lines.each{line ->
file_content_new += line + "\n"
}
writeFile file: file_path, text: file_content_new, encoding: "UTF-8"
}
def get_html_report_filename(report_store_path) {
get_html_file_command = "cd ${report_store_path}&dir /b /s *.html"
out = bat(script:get_html_file_command,returnStdout: true).trim()
out = out.tokenize("\n")[1] // get the second line string
println out
html_report_filename = out.split("test-output")[1].replace("\\", "")
println html_report_filename
return html_report_filename
}
return this;
完整程式碼在github上
https://github.com/QAAutomationLearn/JavaAutomationFramework.git
總結:
到了這裡,我算把jenkins+pipeline+selenium持續整合的方案全部介紹完了,希望對於那些想學習pipeline的朋友有一些幫助。我不得不吐槽下,我的Jenkins環境太慢了,由於jenkins master機器在美國洛杉磯,我本地個人膝上型電腦作為一臺windows slave機器連線,每次跑Jenkins job,拉取程式碼到windows上都很慢,而且連線很不穩定,寫這個系列文章花了很多測試時間,總之,比我預想的要慢很多。從我現在的pipeline使用經驗和技術水平來講,我覺得我完成了pipeline從入門到實戰運用,這篇系列教程,我個人感覺寫得還不錯,至少比java+selenium系列和python+selenium系列要寫得好,只是,在國內,不管開發還是測試還是運維,使用pipeline的人還是很少數,希望這個隊伍會越來越壯大。將來的軟體都會在雲端,所以雲端軟體的自動化和基礎設施的自動化測試會越來越多,工作機會相信也會一樣越多。學會pipeline去用程式碼的方式完成不同專案的CI和CD的開發測試工作,這個要求會在招聘需求裡越來越突出。