Skip to content

Commit

Permalink
use |git describe --abbrev=0| to find the latest tag
Browse files Browse the repository at this point in the history
  • Loading branch information
escapewindow committed Jan 10, 2017
1 parent 431bbe4 commit 8cbe10a
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 19 deletions.
1 change: 0 additions & 1 deletion CHANGELOG.md
Expand Up @@ -4,7 +4,6 @@ This project adheres to [Semantic Versioning](http://semver.org/).

## Unreleased
### Added
- `git_key_repo_tag` config option
- `verify_signed_tag`, which verifies the tag's signature and makes sure we're updated to it.

### Changed
Expand Down
5 changes: 2 additions & 3 deletions scriptworker.yaml.tmpl
Expand Up @@ -78,10 +78,9 @@ gpg_lockfile: "/tmp/gpg_homedir.lock"
# the git_key_repo_url is cloned into git_key_repo_dir.
git_key_repo_dir: "/tmp/key_repo"

# Uncomment and edit to override the default url and/or tag name. This shouldn't be necessary
# unless you're testing changes to the chain of trust.
# Uncomment and edit to override the default url. This shouldn't be necessary unless you're
# testing changes to the chain of trust.
# git_key_repo_url: "https://github.com/mozilla-releng/cot-gpg-keys.git"
# git_key_repo_tag: "production"

# this directory holds pubkeys that are allowed to sign git commits in the git_key_repo_url
git_commit_signing_pubkey_dir: "/tmp/valid_git_fingerprints/"
Expand Down
1 change: 0 additions & 1 deletion scriptworker/constants.py
Expand Up @@ -78,7 +78,6 @@
"gpg_lockfile": os.path.join(os.getcwd(), "gpg_homedir.lock"),
"git_key_repo_dir": "...",
"git_key_repo_url": "https://github.com/mozilla-releng/cot-gpg-keys.git",
"git_key_repo_tag": "production",
"last_good_git_revision_file": os.path.join(os.getcwd(), "git_revision"),
"pubkey_path": "...",
"privkey_path": "...",
Expand Down
43 changes: 34 additions & 9 deletions scriptworker/gpg.py
Expand Up @@ -1163,6 +1163,32 @@ async def get_git_revision(path, ref="HEAD",
return revision.decode('utf-8').rstrip()


async def get_latest_tag(path,
exec_function=asyncio.create_subprocess_exec):
"""Get the latest tag in path.
Args:
path (str): the path to run ``git describe --abbrev=0`` in.
Returns:
str: the tag name found.
Raises:
ScriptWorkerRetryException: on failure.
"""
proc = await exec_function(
'git', "describe", "--abbrev=0", cwd=path,
stdout=PIPE, stderr=DEVNULL, stdin=DEVNULL, close_fds=True,
)
tag, err = await proc.communicate()
exitcode = await proc.wait()
if exitcode:
raise ScriptWorkerRetryException(
"Can't get tag at {}: {}!".format(path, err)
)
return tag.decode('utf-8').rstrip()


async def update_signed_git_repo(context, repo="origin", ref="master",
exec_function=asyncio.create_subprocess_exec,
log_function=pipe_to_log):
Expand All @@ -1183,7 +1209,6 @@ async def update_signed_git_repo(context, repo="origin", ref="master",
ScriptWorkerRetryException: on ``git pull`` failure.
"""
path = context.config['git_key_repo_dir']
tag = context.config['git_key_repo_tag']

async def _run_git_cmd(cmd):
log.info("Running {} in {}".format(cmd, path))
Expand All @@ -1201,27 +1226,27 @@ async def _run_git_cmd(cmd):
for cmd in (
["git", "checkout", ref],
["git", "pull", "--ff-only", "--tags", repo],
["git", "checkout", tag],
):
await _run_git_cmd(cmd)
await verify_signed_tag(context)

tag = await get_latest_tag(path)
await _run_git_cmd(["git", "checkout", tag])
await verify_signed_tag(context, tag)
revision = await get_git_revision(path, tag)
return revision


async def verify_signed_tag(context, exec_function=subprocess.check_call):
"""Verify ``git_key_repo_dir`` is at the valid signed ``git_key_repo_tag``.
async def verify_signed_tag(context, tag, exec_function=subprocess.check_call):
"""Verify ``git_key_repo_dir`` is at the valid signed ``tag``.
Args:
context (scriptworker.context.Context): the scriptworker context.
exec_function (function, optional): the function to use to run ``git tag -v``
Defaults to subprocess.check_call
tag (str): the tag to verify.
Raises:
ScriptWorkerGPGException: if we're not updated to ``git_key_repo_tag``
ScriptWorkerGPGException: if we're not updated to ``tag``
"""
path = context.config['git_key_repo_dir']
tag = context.config['git_key_repo_tag']
try:
exec_function(["git", "tag", "-v", tag], cwd=path)
except subprocess.CalledProcessError as exc:
Expand Down
20 changes: 15 additions & 5 deletions scriptworker/test/test_gpg.py
Expand Up @@ -589,7 +589,8 @@ def test_rebuild_gpg_home_signed(context, trusted_email, tmpdir):
assert messages == []


# get_git_revision {{{1
# get_git_revision, get_latest_tag {{{1
# TODO these two tests should use a tarball with a test git repo inside
@pytest.mark.asyncio
async def test_get_git_revision():
parent_dir = os.path.dirname(__file__)
Expand All @@ -598,7 +599,15 @@ async def test_get_git_revision():


@pytest.mark.asyncio
async def test_get_git_revision_exception(mocker):
async def test_get_latest_tag():
parent_dir = os.path.dirname(__file__)
expected = subprocess.check_output(["git", "describe", "--abbrev=0"], cwd=parent_dir)
assert await sgpg.get_latest_tag(parent_dir) == expected.decode('utf-8').rstrip()


@pytest.mark.parametrize("func", (sgpg.get_git_revision, sgpg.get_latest_tag))
@pytest.mark.asyncio
async def test_get_git_revision_exception(mocker, func):
x = mock.MagicMock()

async def fake(*args, **kwargs):
Expand All @@ -615,7 +624,7 @@ async def fake_communicate(*args, **kwargs):

parent_dir = os.path.dirname(__file__)
with pytest.raises(ScriptWorkerRetryException):
await sgpg.get_git_revision(parent_dir, exec_function=fake)
await func(parent_dir, exec_function=fake)


# update_signed_git_repo {{{1
Expand Down Expand Up @@ -643,6 +652,7 @@ async def fake_exec(*args, **kwargs):
return value

mocker.patch.object(sgpg, "get_git_revision", new=fake_revision)
mocker.patch.object(sgpg, "get_latest_tag", new=noop_async)
mocker.patch.object(sgpg, "verify_signed_tag", new=noop_async)
if return_value:
with pytest.raises(ScriptWorkerRetryException):
Expand Down Expand Up @@ -675,9 +685,9 @@ def fake_exec(*args, **kwargs):
mocker.patch.object(sgpg, "get_git_revision", new=fake_revision)
if raises:
with pytest.raises(ScriptWorkerGPGException):
await sgpg.verify_signed_tag(context, exec_function=fake_exec)
await sgpg.verify_signed_tag(context, "foo", exec_function=fake_exec)
else:
await sgpg.verify_signed_tag(context, exec_function=fake_exec)
await sgpg.verify_signed_tag(context, "foo", exec_function=fake_exec)


# build_gpg_homedirs_from_repo {{{1
Expand Down

0 comments on commit 8cbe10a

Please sign in to comment.