'Why does this "complicated" git clone/checkout cause gitversion to fail?

I have the following pipeline syntax code in a Jenkinsfile to clone a git repo:

      checkout([$class: 'GitSCM',
                branches: [[name: "${branch}"]],
                doGenerateSubmoduleConfigurations: false,
                extensions: [[$class: 'SubmoduleOption',
                              disableSubmodules: false,
                              parentCredentials: false,
                              recursiveSubmodules: true,
                              reference: '',
                              trackingSubmodules: false],
                             [$class: 'LocalBranch',
                              localBranch: ""],
                             [$class: 'RelativeTargetDirectory',
                              relativeTargetDir: relative_dir]],
                submoduleCfg: [],
                userRemoteConfigs: [[credentialsId: cred_id,
                                     url: git_url]]])

Following is the output of one instance of this Jenkins job, which reveals the git commands used to clone a repo:

 > git init /home/user/workspace/CICD/PRJ/repo/PRJ/repo/121/src # timeout=10
Fetching upstream changes from ssh://[email protected]:7999/PRJ/repo.git
 > git --version # timeout=10
using GIT_SSH to set credentials user - ssh username with private key. 
 > git fetch --tags --progress -- ssh://[email protected]:7999/PRJ/repo.git +refs/heads/*:refs/remotes/origin/* # timeout=10
 > git config remote.origin.url ssh://[email protected]:7999/PRJ/repo.git # timeout=10
 > git config --add remote.origin.fetch +refs/heads/*:refs/remotes/origin/* # timeout=10
 > git config remote.origin.url ssh://[email protected]:7999/PRJ/repo.git # timeout=10
Fetching upstream changes from ssh://[email protected]:7999/PRJ/repo.git
using GIT_SSH to set credentials user - ssh username with private key. 
 > git fetch --tags --progress -- ssh://[email protected]:7999/PRJ/repo.git +refs/heads/*:refs/remotes/origin/* # timeout=10
 > git rev-parse refs/remotes/origin/feature/hcf^{commit} # timeout=10
 > git rev-parse refs/remotes/origin/refs/heads/feature/hcf^{commit} # timeout=10
Checking out Revision 37b9492373951ab0b4c70fa64a3320be58133e0e (refs/remotes/origin/feature/hcf)
 > git config core.sparsecheckout # timeout=10
 > git checkout -f 37b9492373951ab0b4c70fa64a3320be58133e0e # timeout=10
 > git branch -a -v --no-abbrev # timeout=10
 > git checkout -b feature/hcf 37b9492373951ab0b4c70fa64a3320be58133e0e # timeout=10
Commit message: "Uncomment set_fault"
 > git rev-list --no-walk 59ce67929be6c901975596db509de7a72b3c557a # timeout=10

This same Jenkinsfile automatically applies git tags using gitversion like so:

docker run -u $(id -u ${USER}):$(id -g ${USER}) --rm -v "$(pwd):/repo" artifactory.company.com/gittools/gitversion:5.7.1 /repo

The above methods of git cloning and using gitversion to generate new git tags has been working fine for several months without incident.

Problem:
Today, gitversion failed unexpectedly when this Jenkins job was run to build a git branch that I cannot see anything unique about (versus the many successfully-built branches).
The error, below, seems to indicate an inability to identify development or release branches, which are dev and master, respectively, in our case.

+ docker run -u 1172002866:1172000513 --rm -v /home/user/workspace/CICD/PRJ/repo/PRJ/repo/121/src:/repo artifactory.company.com/gittools/gitversion:5.7.1 /repo
INFO [01/26/22 23:30:14:02] Working directory: /repo
INFO [01/26/22 23:30:14:26] Project root is: /repo/
INFO [01/26/22 23:30:14:26] DotGit directory is: /repo/.git
INFO [01/26/22 23:30:14:59] Begin: Loading version variables from disk cache
  INFO [01/26/22 23:30:14:59] Cache file /repo/.git/gitversion_cache/AF7963E4F79300A465EFC56DBA14B2B679307C08.yml not found.
  INFO [01/26/22 23:30:14:59] End: Loading version variables from disk cache (Took: 1.50ms)
  INFO [01/26/22 23:30:14:61] Using latest commit on specified branch
  INFO [01/26/22 23:30:14:62] Begin: Attempting to inherit branch configuration from parent branch
    INFO [01/26/22 23:30:14:65] Begin: Finding branch source of 'feature/hcf'
    INFO [01/26/22 23:30:14:66] End: Finding branch source of 'feature/hcf' (Took: 15.87ms)
    INFO [01/26/22 23:30:14:67] Begin: Getting branches containing the commit '37b9492'.
      INFO [01/26/22 23:30:14:67] Trying to find direct branches.
      INFO [01/26/22 23:30:14:67] No direct branches found, searching through all branches.
      INFO [01/26/22 23:30:14:67] Searching for commits reachable from 'origin/dev'.
      INFO [01/26/22 23:30:14:69] The branch 'origin/dev' has no matching commits.
      INFO [01/26/22 23:30:14:69] Searching for commits reachable from 'origin/master'.
      INFO [01/26/22 23:30:14:70] The branch 'origin/master' has no matching commits.
      INFO [01/26/22 23:30:14:70] Searching for commits reachable from 'origin/release-npm2'.
      INFO [01/26/22 23:30:14:70] The branch 'origin/release-npm2' has no matching commits.
      INFO [01/26/22 23:30:14:70] Searching for commits reachable from 'origin/release-npm3'.
      INFO [01/26/22 23:30:14:71] The branch 'origin/release-npm3' has no matching commits.
      INFO [01/26/22 23:30:14:71] Searching for commits reachable from 'origin/release-5944.0'.
      INFO [01/26/22 23:30:14:72] The branch 'origin/release-5944.0' has no matching commits.
      INFO [01/26/22 23:30:14:72] Searching for commits reachable from 'origin/release-5944.1'.
      INFO [01/26/22 23:30:14:73] The branch 'origin/release-5944.1' has no matching commits.
    INFO [01/26/22 23:30:14:73] End: Getting branches containing the commit '37b9492'. (Took: 63.52ms)
    INFO [01/26/22 23:30:14:73] Found possible parent branches: 
  INFO [01/26/22 23:30:14:74] End: Attempting to inherit branch configuration from parent branch (Took: 116.47ms)
  ERROR [01/26/22 23:30:14:82] An unexpected error occurred:
System.InvalidOperationException: Gitversion could not determine which branch to treat as the development branch (default is 'develop') nor releaseable branch (default is 'main' or 'master'), either locally or remotely. Ensure the local clone and checkout match the requirements or considering using 'GitVersion Dynamic Repositories'
   at GitVersion.Configuration.BranchConfigurationCalculator.InheritBranchConfiguration(IBranch targetBranch, BranchConfig branchConfiguration, ICommit currentCommit, Config configuration, IList`1 excludedInheritBranches) in D:\a\GitVersion\GitVersion\src\GitVersion.Core\Configuration\BranchConfigurationCalculator.cs:line 137
   at GitVersion.Configuration.BranchConfigurationCalculator.GetBranchConfiguration(IBranch targetBranch, ICommit currentCommit, Config configuration, IList`1 excludedInheritBranches) in D:\a\GitVersion\GitVersion\src\GitVersion.Core\Configuration\BranchConfigurationCalculator.cs:line 47
   at GitVersion.GitVersionContextFactory.Create(GitVersionOptions gitVersionOptions) in D:\a\GitVersion\GitVersion\src\GitVersion.Core\Core\GitVersionContextFactory.cs:line 40
   at GitVersion.GitVersionCoreModule.<>c__DisplayClass0_0.<RegisterTypes>b__1() in D:\a\GitVersion\GitVersion\src\GitVersion.Core\GitVersionCoreModule.cs:line 38
   at System.Lazy`1.ViaFactory(LazyThreadSafetyMode mode)
   at System.Lazy`1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor)
   at System.Lazy`1.CreateValue()
   at System.Lazy`1.get_Value()
   at GitVersion.VersionCalculation.NextVersionCalculator.get_context() in D:\a\GitVersion\GitVersion\src\GitVersion.Core\VersionCalculation\NextVersionCalculator.cs:line 17
   at GitVersion.VersionCalculation.NextVersionCalculator.FindVersion() in D:\a\GitVersion\GitVersion\src\GitVersion.Core\VersionCalculation\NextVersionCalculator.cs:line 32
   at GitVersion.GitVersionCalculateTool.CalculateVersionVariables() in D:\a\GitVersion\GitVersion\src\GitVersion.Core\Core\GitVersionCalculateTool.cs:line 52
   at GitVersion.GitVersionExecutor.RunGitVersionTool(GitVersionOptions gitVersionOptions) in D:\a\GitVersion\GitVersion\src\GitVersion.App\GitVersionExecutor.cs:line 70
  INFO [01/26/22 23:30:14:82] Attempting to show the current git graph (please include in issue): 
  INFO [01/26/22 23:30:14:82] Showing max of 100 commits
  INFO [01/26/22 23:30:14:93] * 37b9492 3 minutes ago  (HEAD -> feature/hcf, origin/feature/hcf)

What I have tried:
When I manually clone the repo and check out the branch using the above git commands, I can reproduce the gitversion failure.

When I "simplify" my git clone and branch checkout to just:

$ git clone ssh://[email protected]:7999/PRJ/repo.git
$ git checkout feature/hcf
$ docker run -u $(id -u ${USER}):$(id -g ${USER}) --rm -v "$(pwd):/repo" artifactory.company.com/gittools/gitversion:5.7.1 /repo

...then gitversion succeeds and returns an expected value.

Questions:
Can the Jenkinsfile checkout() statement be modified so that it is functionally identical to the "simple" git clone and git checkout statements? There is obviously some salient difference between the two "methods" of cloning from git and checking out branches that is relevant to gitversion.
If possible, I would prefer a solution that uses the Jenkins pipeline checkout() function over a shell script invocation like sh(script:"git clone...") -- but perhaps an experienced answerer can convince me that that preference isn't justified.

Can someone explain how I can determine what is "unique" about this particular git repo or branch? With other repos/branches, the above checkout() statement in our Jenkinsfile continues to work simpatico with the subsequent gitversion invocation. So it would seem there is something unique about this one failing case that I don't know how to determine.



Solution 1:[1]

I don't use Jenkins myself, but it looks like the develop branch is missing from its clone of the repository, which may indicate that Jenkins is doing a sparse or shallow clone. As stated in GitVersion's requirements, it needs a full clone of the repository in order to do its calculations.

The reason your git clone && git checkout statements work is because, by default, Git performs a full clone of the repository. What you need to do is instruct Jenkins to do an unshallow clone of the repository. GitVersion's Jenkins documentation lists a number of things you can and should do to have GitVersion work properly:

  • Advanced clone behaviors
    • Enable Fetch tags
    • Enable Honor refspec on intial clone
  • Check out to matching local branch
  • Prune stale remote-tracking branches
  • Specify ref specs
    • Ref Spec: +refs/heads/*:refs/remotes/@{remote}/*

With the above Jenkins settings tuned correctly, it should work.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Asbjørn Ulsberg