• Jenkins:Git拉取代码版本不对


    结论:
    对于想要指定特定分支进行拉取,最好的四种没有二义性的写法是:

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

    最近在使用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*分支。

    img

    然后看看之前有问题那次构建的记录(打开job当次构建的详情页),点击Git Build Data(左侧):

    这里显示了两个remote的branch,我在GitPlugin里面只配置了一个qa分支,这里应该只有一个叫做qa的分支被下载才对,怎么会有两个分支呢?

    我开始怀疑可能是在配置Git Plugin中BranchName的规则匹配问题,导致在这里匹配了两个分支(一个叫做qa,一个叫origin/qa)。

    再次打开Jenkins上对应job的配置,我们看到在BranchSpecifier这里填的是"/qa",是一个通配符,会不会在这个工程下正好有两个branch,如上图中的(origin/qa和qa),正好匹配到了*/qa呢?

    img

    这么一想就有点解释得通了,于是我点击了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/这种语法

    The safest way is to use the refs/heads/ syntax. This way the expected branch is unambiguous.

    //如果你的分支里面包含‘/’(例如叫origin/qa),最好就用上面提到的语法:refs/heads/

    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只是个通配符,比如realese可以匹配release分支,也可能匹配origin/release,一般不要这么写(否则会和我一样踩同样的坑)

    //由于指定存在二义性,建议使用refs/heads/来明确指定具体的远程分支。

    Tracks/checks out the specified branch. If ambiguous the first result is taken, which is not necessarily the expected one. Better use refs/heads/.

    E.g. master, feature1,...

    • refs/heads/

    Tracks/checks out the specified branch. //checkout远程的某个分支

    E.g. refs/heads/master, refs/heads/feature1/master,...

    • /

    Tracks/checks out the specified branch. If ambiguous the first result is taken, which is not necessarily the expected one.

    Better use refs/heads/. //这种指定远程具体分支的方法可能存在二义性,建议使用refs/heads/

    E.g. origin/master

    • remotes//

    Tracks/checks out the specified branch. //这种指定方式也是比较精确的。

    E.g. remotes/origin/master

    • refs/remotes//

    Tracks/checks out the specified branch.

    E.g. refs/remotes/origin/master //checkout指定的tag,实际上这里tagName不会被当做tag,不建议这么写。

    This does not work since the tag will not be recognized as tag.

    Use refs/tags/ instead. .. //checkout指定的tag,这才是正确的语法。

    E.g. git-2.3.0

    • refs/tags/

    Tracks/checks out the specified tag.

    E.g. refs/tags/git-2.3.0

    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},...

    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.

    • :

    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代码版本也正确了。

    img

  • 相关阅读:
    Windows快捷键
    visual studio code颜色主题切换
    visual studio code中文语言包安装
    顶点缓存与索引缓存
    程序结构(2)
    ansible常用模块
    ansible常用模块
    ubuntu实用技巧
    ubuntu实用技巧
    Sqoop导出MySQL数据
  • 原文地址:https://www.cnblogs.com/SimonHu1993/p/15109976.html
Copyright © 2020-2023  润新知