In our CI release flow, we'd like to number Conan packages based on a git tag applied in our repo.
Right now if I apply a tag 0.0.8, then fetch that and and use git branch I see:
$ git branch
* (HEAD detached at 0.0.8)
whereas if I use git describe --tags I see:
0.0.8
I'd like to be able to use 0.0.8 as the Conan package version.
If I try using the example from https://docs.conan.io/en/latest/howtos/capture_version.html, namely:
return "%s_%s" % (git.get_branch(), git.get_revision())
on that checked out tag I see:
E:\DevelopBp\mmaguir1\src\nx\replicant>conan create . PORT/stable
version[HEAD (no branch)_0dfb63c9c341536e528ef63f2e66746cf83c8539]
ERROR: Value provided for package version, 'HEAD (no branch)_0dfb63c9c341536e528ef63f2e66746cf83c8539' (type Version), is too long. Valid names must contain at most 51 characters.
Alternatively, if there's some magic combination of the existing Git tools that will let me retrieve that tag name, that would be much appreciated!
Related:
https://github.com/conan-io/conan/issues/548 "generating version from git"
https://github.com/conan-io/conan/issues/1764 "Add Git helpers"
To help us debug your issue please explain:
A tag is just a pointer to a commit. To develop a get_tag(), probably we should use the git describe command:
The command finds the most recent tag that is reachable from a commit.
If the tag points to the commit, then only the tag is shown.
Otherwise, it suffixes the tag name with the number of additional commits on top of
the tagged object and the abbreviated object name of the most recent commit.
e.g, on the Conan master branch:
$ git describe
1.9.2
e.g on the Conan develop branch:
$ git describe
1.9.1-31-g6bf1fc73
So we can detect if a simple "pure" tag is returned or return None otherwise.
Actually, if the purpose is to create a version from the Git repo automatically, the git describe command is a flexible way to get a human-readable version string for a given commit. So a method like Git.describe with some keyword arguments for customization (derived from command line arguments) should be simple enough and solve most of the problem for Git repos.
For example, we usually use git describe --always --tags --match 'v*.*' in CI to get a version tag, so if the build is made from a tag matching 'v.', the version will be exactly the tag name.
Thanks for the info @himikof
I'm not sure if Conan should provide a complete wrapper over git command line or just provide access to the features that we are consuming from SCM feature (or Conan core features). I'm afraid about introducing too many arguments, custom function calls that address single use cases,... it will be hard to maintain.
There is an function member that can be used to call _ad hoc_ commands, for example, given the proposal by @himikof we can just use Git class in the following way:
def get_version():
git = Git(os.path.dirname(__file__)) # Initialize git object in the same folder where this file is.
v = git.run("describe --always --tags --match 'v*.*'")
# May need some more logic in case it is not a matching tag
return v
I'm not sure if Conan should provide a complete wrapper over git command line or just provide access to the features that we are consuming from SCM feature (or Conan core features).
I would say both, but as you said, only for general purpose stuff. I think that getting the tag (if the repo is "in a commit tag") is not a single use case but a general purpose one. If you want more specific behavior like controlling the name of the tags (beginning with 'v') and so on, you would need to implement it yourself.
For me, as I said, I would like a function to return a "pure" tag name (when the last commit is tagged) or None otherwise (If the tag doesn't belong to the latest commit).
Ok, then we should provide the same functionality for SVN too (it is almost implemented). Also, as the function def get_branch(self): is raising if no branch can be retrieved, I would suggest to raise here too if no tag can be found.
Ok, then we should provide the same functionality for SVN too
We could, but they are not strictly attached as this is not part of the SCM common feature. I think we should start with the git one and implement later the SVN when someone requests it. But if it is trivial and almost done we could include it also. If you have already some implementation, please refer it or paste it here to have better information when we assign this feature to a release.
is raising if no branch can be retrieved, I would suggest to raise here too if no tag can be found.
Ok, if someone asks for a tag I assume he expects to get one, I'm ok raising.
Pasting here current implementation for SVN::get_branch():
def get_branch(self):
url = self._show_item('relative-url')
try:
pattern = "(tags|branches)/[^/]+|trunk"
branch = re.search(pattern, url)
if branch is None:
return None
else:
return branch.group(0)
except Exception as e:
raise ConanException("Unable to get svn branch from %s: %s" % (self.folder, str(e)))
If I can remember it well, it was introduced by @climblinne. We should split this functionality into get_tag and get_branch as the pattern at this moment is matching both (it can break something, but from the name if the function it is clear that the aim of it was retrieving branch name).
get_branch() isn't either directly used by the scm feature, right? In that case, yes, we should split it.