Skip to content

Commit

Permalink
jenkins: always resolve tags to rev of the commit that got tagged
Browse files Browse the repository at this point in the history
FC-41962
Closes #200

Previously, we always resolved tags to the commit rev. However if this
failed, there was a fallback to the rev of the tag (the output of `git
ls-remote` without the `^{}` modifier).

This is a problem in a deployment where we rely on the rev being the
commit rev since that's part of the S3 url where the frontend assets are
stored. The reason for the fallback that lead to such a deployment
error was a timing issue where the first `ls-remote` failed like this

    ssh: Could not resolve hostname gitlab.customer.com: Try again
    fatal: Could not read from remote repository.
    Please make sure you have the correct access rights
    and the repository exists.

and the second one (resolving to the tag's rev) succeeded.

We now call `ls-remote` without the `^{}` modifier and check if the
refspec got resolved to a tag (i.e. `refs/tags/...`). If that's the
case, a second `ls-remote` is issued with the `^{}` modifier to
get the rev of the commit that got tagged. If this second call fails,
we fail hard to make sure we don't get incorrect results silently.
  • Loading branch information
Ma27 committed Nov 21, 2024
1 parent 339c2f1 commit edfd2d2
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 13 deletions.
3 changes: 3 additions & 0 deletions CHANGES.d/20241121_122503_mb_FC_41962_tag_resolution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Correctness fix for `jenkins set-version`: if a tag is resolved, make sure it's _always_
resolved to the rev of the tagged commit (instead of the tag's rev) or fail hard to avoid
incorrect revs.
35 changes: 22 additions & 13 deletions src/batou_ext/jenkins.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@
import sys


def git_ls_remote(url, ref):
cmd = subprocess.Popen(
["git", "ls-remote", url, ref], stdout=subprocess.PIPE
)
stdout, _ = cmd.communicate()
if stdout:
return stdout.decode("ascii").split("\t", 1)


def git_resolve(url, version):
if len(version) == 40:
# revision.
Expand All @@ -16,19 +25,19 @@ def git_resolve(url, version):
pass
else:
return version
# Symbolic name?
cmd = subprocess.Popen(
["git", "ls-remote", url, version + "^{}"], stdout=subprocess.PIPE
)
stdout, stderr = cmd.communicate()
# if its not a tag, start another more generic attempt
if not stdout:
cmd = subprocess.Popen(
["git", "ls-remote", url, version], stdout=subprocess.PIPE
)
stdout, stderr = cmd.communicate()
stdout = stdout.decode("ascii")
return stdout.split("\t", 1)[0]

if ls_remote := git_ls_remote(url, version):
rev, full_refspec = ls_remote
# If full_refspec indicates that a tag was found, retry with `^{}`
# to make sure we get the rev of the commit instead of the tag's rev.
if full_refspec.startswith("refs/tags"):
if ls_remote_tag := git_ls_remote(url, f"{version}^{{}}"):
rev = ls_remote_tag[0]
else:
raise ValueError(
f"git ls-remote {url} {version}^{{}} failed, see above for the error."
)
return rev


class VersionsUpdater:
Expand Down

0 comments on commit edfd2d2

Please sign in to comment.