Skip to content

Commit

Permalink
Update the version generated for addon builds to be compatible with MV3
Browse files Browse the repository at this point in the history
  • Loading branch information
gabrielBusta committed Jun 7, 2024
1 parent bfeeb29 commit 5dc6761
Showing 1 changed file with 72 additions and 18 deletions.
90 changes: 72 additions & 18 deletions taskcluster/docker/node/build.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,17 +75,32 @@ def write_package_info(package_info):

def get_buildid():
now = datetime.utcnow()
return now.strftime("%Y%m%d.%H%M%S")
# note the `-` (hyphen) in `%-H`
# this removes the leading zero
# from the hour (leading zeros are not allowed)
return now.strftime("%Y%m%d.%-H%M%S")


def get_buildid_version(version):
"""Version schema check+append a `buildid{buildid}` to ensure unique version."""
# XXX is there a more precise schema we should verify ourselves against?
if len(version.split(".")) not in (1, 2, 3):
raise Exception("{version} has too many version parts!")
if "buildid" in version:
raise Exception("{version} already has a buildid specified!")
buildid_version = f"{version}buildid{get_buildid()}"
"""Check the version's formating and append `date.time` as a buildid to ensure a unique version.
The addon's in-tree extension/manifest.json file specifies `major.minor.0`.
The format of the resulting version field is:
<number>.<number>.%Y%m%d.%-H%M%S
"""
parts = [int(part) for part in version.split(".")]
if len(parts) not in (1, 2, 3):
raise Exception(
f"{version} has an invalid number of version parts! The pipeline supports a `major.minor.0` version format in the extension's manifest"
)
# Append (or override) the last two parts of the version with a timestamp to ensure a unique version that is compliant with MV3.
if len(parts) == 3:
# Print a noisy warning if we override an element in the extension's version field.
if parts[2] != "0":
msg = "WARNING: THE 3RD ELEMENT IN THE VERSION {version} IS NOT 0. THIS VALUE WILL BE OVERRIDEN BY THE PIPELINE!"
print(f"{'!' * len(msg)}\n\n{msg}\n\n{'!' * len(msg)}")
parts = parts[:2]
version = ".".join([str(part) for part in parts])
buildid_version = f"{version}.{get_buildid()}"
print(f"Buildid version is {buildid_version}")
return buildid_version

Expand Down Expand Up @@ -128,11 +143,35 @@ def mkdir(path):
def get_hash(path, hash_alg="sha256"):
h = hashlib.new(hash_alg)
with open(path, "rb") as fh:
for chunk in iter(functools.partial(fh.read, 4096), b''):
for chunk in iter(functools.partial(fh.read, 4096), b""):
h.update(chunk)
return h.hexdigest()


def is_version_mv3_compliant(version):
# Split the version string by dots
parts = version.split(".")

# Check if there are 1 to 4 parts
if len(parts) < 1 or len(parts) > 4:
return False

for part in parts:
# Check if the part is a number
if not part.isdigit():
return False
# Check that the part doesn't have leading zeros (unless it's "0")
if part[0] == "0" and part != "0":
return False
# Convert part to integer to check the digit count
num = int(part)
# Check if the integer has more than 9 digits
if num > 999999999:
return False

return True


def check_manifest(path, buildid_version):
xpi = ZipFile(path, "r")
manifest = {}
Expand All @@ -150,20 +189,35 @@ def check_manifest(path, buildid_version):
continue
_found = True
if not _id.endswith(ID_ALLOWLIST):
raise Exception(f"{_key}.gecko.id {_id} must end with one of the following suffixes!\n{ID_ALLOWLIST}")
raise Exception(
f"{_key}.gecko.id {_id} must end with one of the following suffixes!\n{ID_ALLOWLIST}"
)
else:
print(f"Add-on id {_id} matches the allowlist.")
if manifest["version"] != buildid_version:
raise Exception(f"{manifest['version']} doesn't match buildid version {buildid_version}!")
raise Exception(
f"{manifest['version']} doesn't match buildid version {buildid_version}!"
)
if not is_version_mv3_compliant(manifest["version"]):
raise Exception(
(
f"The version in {manifest_name} is {manifest['version']}, which is not MV3 compliant. "
"The value must be a string with 1 to 4 numbers separated by dots (e.g., 1.2.3.4). "
"Each number can have up to 9 digits and leading zeros before another digit are not allowed "
"(e.g., 2.01 is forbidden, but 0.2, 2.0.1, and 2.1 are allowed)."
)
)
if not _found:
raise Exception("Can't find addon ID in manifest.json!")


def main():
test_var_set([
"ARTIFACT_PREFIX",
"XPI_NAME",
])
test_var_set(
[
"ARTIFACT_PREFIX",
"XPI_NAME",
]
)

artifact_prefix = os.environ["ARTIFACT_PREFIX"]
xpi_name = os.environ["XPI_NAME"]
Expand Down Expand Up @@ -204,10 +258,10 @@ def main():
run_command(["npm", "install"])
run_command(["npm", "run", "build"])

if 'XPI_ARTIFACTS' in os.environ:
if "XPI_ARTIFACTS" in os.environ:
xpi_artifacts = os.environ["XPI_ARTIFACTS"].split(";")
else:
xpi_artifacts = glob.glob('*.xpi') + glob.glob("**/*.xpi")
xpi_artifacts = glob.glob("*.xpi") + glob.glob("**/*.xpi")

all_paths = []
for artifact in xpi_artifacts:
Expand All @@ -232,4 +286,4 @@ def main():
fh.write(json.dumps(build_manifest, indent=2, sort_keys=True))


__name__ == '__main__' and main()
__name__ == "__main__" and main()

0 comments on commit 5dc6761

Please sign in to comment.