Jenkins:Git拉取代碼版本不對


血淚史

最近在使用Jenkins拉取Git工程編譯代碼時候遇到一個很奇怪的的問題:Jenkins的GitPlugin下載代碼的版本不對(commitId不對)。由於線上部署和線下部署的編譯產物是同一版本,導致最后發布到生產環境的代碼版本也不對。這個問題在線上驗證階段才最終被發現,回顧整個job構建過程,控制台沒有報錯,也成功編譯出來了上線包,那到底是哪里出了問題?

初步定位

我最開始懷疑是本地Git工程殘留的問題,於是嘗試刪除jenkins對應job所運行的機器節點上的WORKSPACE目錄,保證下次觸發Jenkins構建能拉取到最新代碼。

刪除方式:

1. 登陸到運行這個job的節點的機器(在控制台中查看這個job運行的節點,在第一行有打印)。

2. 查看$WORKSPACE(在job的控制台中查看;如果找不到,直接在shell executor中加一行echo $WORKSPACE,重新執行job)

3. 刪除對應的WORKSPACE信息。請謹慎操作,先看清楚WORKSPACE的值對不對(echo $WORKSPACE),別搞錯導致刪除了根目錄!!!

[ -d "$WORKSPACE" ] && rm -rf ${WORKSPACE}

4.刪除后重新觸發job

這么操作后,最終打包出來的編譯產物還是版本不對。

既然不是本地代碼緩存問題,那有沒有可能在GIt拉取代碼的時候版本就不對呢?

二次排錯

打開Jenkins上job的配置詳情,我在BranchSpecifier這里只填寫了" */qa", 我的預期是匹配git特定工程(Repository URL)中的 qa分支。

 

然后看看之前有問題那次構建的記錄(打開job當次構建的詳情頁),點擊Git Build Data(左側):

這里顯示了兩個remote的branch,我在GitPlugin里面只配置了一個qa分支,這里應該只有一個叫做qa的分支被下載才對,怎么會有兩個分支呢?

我開始懷疑可能是在配置Git Plugin中BranchName的規則匹配問題,導致在這里匹配了兩個分支(一個叫做qa,一個叫origin/qa)。

 
 
 
再次打開Jenkins上對應job的配置,我們看到在BranchSpecifier這里填的是"*/qa",*是一個通配符,會不會在這個工程下正好有兩個branch,如上圖中的(origin/qa和qa),正好匹配到了*/qa呢?

 這么一想就有點解釋得通了,於是我點擊了Branches Specifier這一欄右側的問號查看幫助,可以看到使用幫助信息。

詳情分析

//下面這句話的意思是:如果你不填寫branch specifier(留空或者寫的是any),那么任意分支都會被匹配,也就是你無法工程使用的是哪個分支。一般不建議這么用。

Specify the branches if you'd like to track a specific branch in a repository. If left blank, all branches will be examined for changes and built.

//下面這句話的意思是:最安全的方式是使用refs/heads/<branchName>這種語法

The safest way is to use the refs/heads/<branchName> syntax. This way the expected branch is unambiguous. 
//如果你的分支里面包含‘/’(例如叫 origin/qa),最好就用上面提到的語法: refs/heads/<branchName>
If your branch name has a / in it make sure to use the full reference above. When not presented with a full path the plugin will only use the part of the string right of the last slash. Meaning foo/bar will actually match bar.
 
If you use a wildcard branch specifier, with a slash (e.g. release/), you'll need to specify the origin repository in the branch names to make sure changes are picked up. So e.g. origin/release/
Possible options:  
  • <branchName>         //branchName只是個通配符,比如realese可以匹配release分支,也可能匹配origin/release,一般不要這么寫(否則會和我一樣踩同樣的坑)
//由於指定<branchName>存在二義性,建議使用 refs/heads/<branchName>來明確指定具體的遠程分支。
Tracks/checks out the specified branch. If ambiguous the first result is taken, which is not necessarily the expected one. Better use refs/heads/<branchName>.
E.g. master, feature1,...    
  • refs/heads/<branchName>
 
Tracks/checks out the specified branch.        //checkout遠程的某個分支
E.g. refs/heads/master, refs/heads/feature1/master,...
  • <remoteRepoName>/<branchName>
 
Tracks/checks out the specified branch. If ambiguous the first result is taken, which is not necessarily the expected one.
Better use refs/heads/<branchName>.       //這種指定遠程具體分支的方法可能存在二義性,建議使用 refs/heads/<branchName>
E.g. origin/master
  • remotes/<remoteRepoName>/<branchName>
 
Tracks/checks out the specified branch.  //這種指定方式也是比較精確的。
E.g. remotes/origin/master
  • refs/remotes/<remoteRepoName>/<branchName>
 
Tracks/checks out the specified branch.
E.g. refs/remotes/origin/master            //checkout指定的tag,實際上這里tagName不會被當做tag,不建議這么寫。
  • <tagName>
This does not work since the tag will not be recognized as tag.
Use refs/tags/<tagName> instead. ..     //checkout指定的tag,這才是正確的語法。
E.g. git-2.3.0
  • refs/tags/<tagName>
Tracks/checks out the specified tag.
E.g. refs/tags/git-2.3.0
 
  • <commitId>
Checks out the specified commit.       //checkout指定的commitid
E.g. 5062ac843f2b947733e6a3b105977056821bd352, 5062ac84, ...
  • ${ENV_VARIABLE}
It is also possible to use environment variables. In this case the variables are evaluated and the result is used as described above.
E.g. ${TREEISH}, refs/tags/${TAGNAME},...
  • <Wildcards>
The syntax is of the form: REPOSITORYNAME/BRANCH. In addition, BRANCH is recognized as a shorthand of */BRANCH, '*' is recognized as a wildcard, and '**' is recognized as wildcard that includes the separator '/'. Therefore, origin/branches* would match origin/branches-foo but not origin/branches/foo, while origin/branches** would match both origin/branches-foo and origin/branches/foo.
  • :<regular expression>
The syntax is of the form: :regexp. Regular expression syntax in branches to build will only build those branches whose names match the regular expression.
Examples:
  • :^(?!(origin/prefix)).*
  • matches: origin or origin/master or origin/feature
  • does not match: origin/prefix or origin/prefix_123 or origin/prefix-abc
  • :origin/release-\d{8}
  • matches: origin/release-20150101
  • does not match: origin/release-2015010 or origin/release-201501011 or origin/release-20150101-something
  • :^(?!origin/master$|origin/develop$).*
  • matches: origin/branch1 or origin/branch-2 or origin/master123 or origin/develop-123
  • does not match: origin/master or origin/develop

 所以對於想要指定特定分支進行拉取,最好的四種沒有二義性的寫法是:

  • refs/heads/<branchName>
  • refs/remotes/<remoteRepoName>/<branchName>
  • refs/tags/<tagName>
  • <commitId>

到這里基本問題就真相大白了,我去gitlab上看了下這個工程的分支列表,發現還真有一個叫做origin/qa的分支,經過和其他同事的確認,有人手抖創建了這個origin/qa的分支。

我把原來的*/qa換成refs/heads/qa,這樣就精確地匹配到了具體的分支。嘗試再次觸發job構建,這次下載的Git代碼版本也正確了。

 

本文為原創踩坑史,如果對你有幫助,辛苦手下留贊,謝謝! 

博主:測試生財(一個不為996而996的測開碼農)

座右銘:專注測試開發與自動化運維,努力讀書思考寫作,為內卷的人生奠定財務自由。

內容范疇:技術提升,職場雜談,事業發展,閱讀寫作,投資理財,健康人生。

csdn:https://blog.csdn.net/ccgshigao

博客園:https://www.cnblogs.com/qa-freeroad/

51cto:https://blog.51cto.com/14900374

微信公眾號:測試生財(定期分享獨家內容和資源)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM