Skip to content

Commit

Permalink
Obtain branch name in CI environment
Browse files Browse the repository at this point in the history
Adds support to obtain the name of the git branch associated to the
current commit in CI environments. In this scenarios, the commit is
checked out in detached HEAD state, which does not allow to obtain the
name of the branch via Git. CI services such as Gitlab, Jenkins, Travis,
etc. define a variable name that contains the name of the branch, which
is what this code looks for in order to define the CI service-agnostic
GIT_BRANCH variable.
  • Loading branch information
ivotron committed May 7, 2020
1 parent 376c6f6 commit e78aee3
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 14 deletions.
22 changes: 8 additions & 14 deletions cli/popper/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,16 @@ def __init__(self, engine_name=None, resman_name=None, config_file=None,
self.skip_pull = skip_pull
self.skip_clone = skip_clone

# attempt to create a git.Repo. If folder doesn't exist, we get None
# if no git repository exists in workspace_dir or its parents, the repo
# variable is None and all git_* variables are assigned to 'na'
self.repo = scm.new_repo(self.workspace_dir)
self.git_commit = scm.get_sha(self.repo)
self.git_sha_short = scm.get_sha(self.repo, short=7)
self.git_branch = scm.get_branch(self.repo)

if self.repo:
sha = self.repo.head.object.hexsha
self.git_commit = self.repo.git.rev_parse(sha)
self.git_sha_short = self.repo.git.rev_parse(sha, short=7)
if self.repo.head.is_detached:
self.git_branch = self.git_sha_short
else:
self.git_branch = self.repo.active_branch.name
else:
self.git_commit = 'na'
self.git_sha_short = 'na'
self.git_branch = 'na'

# wid is used to associate a unique id to this workspace. This is then
# used by runners to name resources in a way that there is no name
# clash between concurrent workflows being executed
wid = shake_256(self.workspace_dir.encode('utf-8')).hexdigest(4)
self.wid = wid

Expand Down
40 changes: 40 additions & 0 deletions cli/popper/scm.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,43 @@ def parse(url):
log.debug(f' version: {version}')

return service_url, service, user, repo, step_dir, version


def get_sha(repo, short=None):
"""Returns the commit id for the currently checked out version on the
given repository object. If short is given, it is interpreted as the number
of characters from the SHA that get returned. E.g. short=7 returns the
first 7 characters, otherwise it returns the entire SHA1 string.
"""
if not repo:
return 'na'

if short:
return repo.git.rev_parse(repo.head.object.hexsha, short=short)

return repo.git.rev_parse(repo.head.object.hexsha)


def get_branch(repo):
"""Get name of branch. If the repo is in detached head state, it looks for
for environment variables commonly used in CI services: TRAVIS_BRANCH,
GIT_BRANCH (Jenkins), CIRCLE_BRANCH and CI_COMMIT_REF_NAME (Gitlab)
"""
if not repo:
return 'na'

if not repo.head.is_detached:
return repo.active_branch.name

branch = os.environ.get('TRAVIS_BRANCH')
if branch:
return branch
branch = os.environ.get('GIT_BRANCH')
if branch:
return branch
branch = os.environ.get('CIRCLE_BRANCH')
if branch:
return branch
branch = os.environ.get('CI_COMMIT_REF_NAME')
if branch:
return branch
7 changes: 7 additions & 0 deletions cli/test/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,16 @@ def mk_repo(self):
readme = os.path.join(tempdir, 'README.md')
open(readme, 'w').close()

# create first commit
repo.index.add([readme])
repo.index.commit('first commit')

# create second commit
with open(readme, 'w') as f:
f.write('README content\n')
repo.index.add([readme])
repo.index.commit('second commit')

# create a remote
repo.create_remote('origin', url='https://github.com/my/repo')

Expand Down
20 changes: 20 additions & 0 deletions cli/test/test_scm.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,26 @@ def test_get_remote_url(self):

self.assertEqual(scm.get_remote_url(None), '')

def test_get_branch_in_detached_head_state(self):
repo = self.mk_repo()
repo.git.checkout('HEAD~1')

os.environ['TRAVIS_BRANCH'] = 'travis'
self.assertEqual('travis', scm.get_branch(repo))
os.environ.pop('TRAVIS_BRANCH')

os.environ['GIT_BRANCH'] = 'jenkins'
self.assertEqual('jenkins', scm.get_branch(repo))
os.environ.pop('GIT_BRANCH')

os.environ['CIRCLE_BRANCH'] = 'circle'
self.assertEqual('circle', scm.get_branch(repo))
os.environ.pop('CIRCLE_BRANCH')

os.environ['CI_COMMIT_REF_NAME'] = 'gitlab'
self.assertEqual('gitlab', scm.get_branch(repo))
os.environ.pop('CI_COMMIT_REF_NAME')

def test_clone(self):
tempdir = tempfile.mkdtemp()
tdir = os.path.join(tempdir, 'test_clone')
Expand Down

0 comments on commit e78aee3

Please sign in to comment.