Revision control

Copy as Markdown

# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
"""
Add github links for release notifications
"""
import os
import re
from datetime import datetime
from mozilla_version.mobile import MobileVersion
from taskgraph.transforms.base import TransformSequence
from taskgraph.util.taskcluster import find_task_id, get_task_definition
from taskgraph.util.vcs import get_repository
transforms = TransformSequence()
CHANGESET_URL_TEMPLATE = "{repo}/compare/{from_version}...{to_version}"
TAG_PREFIX = "focus-v"
# XXX is there a better index we can use to get from buildid to revision?
GECKO_INDEX = "gecko.v2.{repo}.pushdate.{build_date}.{build_timestamp}.mobile-l10n.android-geckoview-fat-aar-opt.multi"
GECKO_KT = "android-components/plugins/dependencies/src/main/java/Gecko.kt"
BUILDID_RE = re.compile(r'version = "[0-9]*\.[0-9]*\.([0-9]*)"', re.MULTILINE)
CHANNEL_RE = re.compile(
r"val channel = GeckoChannel.(NIGHTLY|BETA|RELEASE)", re.MULTILINE
)
HG_CHANGESET_URL_TEMPLATE = (
"{repo}/{logtype}?rev={to_version}+%25+{from_version}&revcount=1000"
)
REPO_FROM_CHANNEL = {
"NIGHTLY": "mozilla-central",
"BETA": "mozilla-beta",
"RELEASE": "mozilla-release",
}
def get_gecko_revision(channel, buildid):
repo = REPO_FROM_CHANNEL[channel]
build_date = datetime.strptime(buildid, "%Y%m%d%H%M%S").strftime("%Y.%m.%d")
index_path = GECKO_INDEX.format(
repo=repo, build_date=build_date, build_timestamp=buildid
)
task_id = find_task_id(index_path)
task_definition = get_task_definition(task_id)
rev = task_definition["payload"]["env"]["GECKO_HEAD_REV"]
return rev
def get_gecko_channel_and_buildid(repo, commit):
gecko_kt = repo.run("show", f"{commit}:{GECKO_KT}")
buildid_match = BUILDID_RE.search(gecko_kt)
channel_match = CHANNEL_RE.search(gecko_kt)
if not buildid_match or not channel_match:
return
return channel_match[1], buildid_match[1]
def get_previous_tag_version(current_version, tags):
prefixlen = len(TAG_PREFIX)
versions = [MobileVersion.parse(t[prefixlen:]) for t in tags]
return max(v for v in versions if v < current_version)
@transforms.add
def add_github_link(config, tasks):
version = MobileVersion.parse(config.params["version"])
repo = get_repository(".")
git_tags = repo.run("tag", "-l", TAG_PREFIX + "*").splitlines()
if not git_tags:
raise Exception("Git tags not found! Try running: git pull <remote> --tags")
previous_version = get_previous_tag_version(version, git_tags)
current_revision = config.params["head_rev"]
repo_url = config.params["base_repository"]
compare_url = CHANGESET_URL_TEMPLATE.format(
repo=repo_url,
from_version=f"{TAG_PREFIX}{previous_version}",
to_version=current_revision,
)
try:
previous_gecko_revision = get_gecko_revision(
*get_gecko_channel_and_buildid(repo, f"{TAG_PREFIX}{previous_version}")
)
gecko_channel, gecko_buildid = get_gecko_channel_and_buildid(
repo, current_revision
)
assert gecko_channel in ("BETA", "RELEASE")
current_gecko_revision = get_gecko_revision(gecko_channel, gecko_buildid)
gecko_url = (
)
gecko_changelog_url = HG_CHANGESET_URL_TEMPLATE.format(
repo=gecko_url,
logtype="log",
from_version=previous_gecko_revision,
to_version=current_gecko_revision,
)
gecko_changelog = f"[Full Gecko mercurial changelog]({gecko_changelog_url})"
except Exception:
gecko_changelog = ""
for task in tasks:
task["notifications"][
"message"
] = """\
Commit: [{revision}]({repo}/commit/{revision})
Task group: [{task_group_id}]({root_url}/tasks/groups/{task_group_id})
Comparing git changes from {from_version} to {to_version}:
[Full Git changelog]({compare_url})
{gecko_changelog}
""".format(
repo=repo_url,
revision=current_revision,
# TASK_ID isn't set when e.g. using taskgraph locally
task_group_id=os.getenv("TASK_ID", "<decision>"),
root_url=os.getenv("TASKCLUSTER_ROOT_URL"),
from_version=previous_version,
to_version=version,
compare_url=compare_url,
gecko_changelog=gecko_changelog,
)
yield task