1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-24 15:28:10 +00:00

feat(common): create release script

This commit is contained in:
matejcik 2021-08-23 12:55:57 +02:00 committed by matejcik
parent 8dd7ad3c3e
commit 2173f6cec7
2 changed files with 106 additions and 106 deletions

27
common/tools/release.sh Executable file
View File

@ -0,0 +1,27 @@
#!/bin/sh
HERE=$(dirname $0)
CHECK_OUTPUT=$(mktemp -d)
trap "rm -r $CHECK_OUTPUT" EXIT
$HERE/cointool.py check > $CHECK_OUTPUT/pre.txt
ETH_DIR=$HERE/../defs/ethereum
ETH_REPOS="chains tokens"
for dir in $ETH_REPOS; do
(
cd $ETH_DIR/$dir; \
git checkout master; \
git pull origin master
)
done
$HERE/support.py release
$HERE/cointool.py check > $CHECK_OUTPUT/post.txt
make -C $HERE/../.. gen
diff $CHECK_OUTPUT/pre.txt $CHECK_OUTPUT/post.txt

View File

@ -2,7 +2,6 @@
import json import json
import os import os
import re import re
import subprocess
import sys import sys
import click import click
@ -37,6 +36,19 @@ def clear_support(device, key):
unsupported.pop(key, None) unsupported.pop(key, None)
def support_setdefault(device, key, value, reason=None):
"""Set value only if no other value is set"""
supported, unsupported = support_dicts(device)
if value is not False and key not in unsupported:
supported.setdefault(key, value)
if value is False:
if reason is None:
raise ValueError("reason must be given for unsupported keys")
if key not in supported:
unsupported[key] = reason
def set_supported(device, key, value): def set_supported(device, key, value):
clear_support(device, key) clear_support(device, key)
supported, _ = support_dicts(device) supported, _ = support_dicts(device)
@ -291,94 +303,56 @@ def check(check_tokens, ignore_missing):
@cli.command() @cli.command()
# fmt: off # fmt: off
@click.argument("device") @click.option("--v1", help="Version for T1 release (default: guess from latest)")
@click.option("-r", "--version", help="Set explicit version string (default: guess from latest release)") @click.option("--v2", help="Version for TT release (default: guess from latest)")
@click.option("--git-tag/--no-git-tag", "-g", default=False, help="Create a corresponding Git tag")
@click.option("--release-missing/--no-release-missing", default=True, help="Release coins with missing support info")
@click.option("-n", "--dry-run", is_flag=True, help="Do not write changes") @click.option("-n", "--dry-run", is_flag=True, help="Do not write changes")
@click.option("-s", "--soon", is_flag=True, help="Only set missing support-infos to be released 'soon'")
@click.option("-f", "--force", is_flag=True, help="Proceed even with bad version/device info") @click.option("-f", "--force", is_flag=True, help="Proceed even with bad version/device info")
@click.option("-y", "--add-all", is_flag=True, help="Do not ask for confirmation, add all selected coins")
@click.option("-v", "--verbose", is_flag=True, help="Be more verbose") @click.option("-v", "--verbose", is_flag=True, help="Be more verbose")
@click.option("--skip-testnets/--no-skip-testnets", default=True, help="Automatically exclude testnets")
# fmt: on # fmt: on
@click.pass_context @click.pass_context
def release( def release(
ctx, ctx,
device: str, v1,
version, v2,
git_tag,
release_missing,
dry_run, dry_run,
soon,
force, force,
add_all,
verbose, verbose,
skip_testnets,
): ):
"""Release a new Trezor firmware. """Release a new Trezor firmware.
Update support infos so that all coins have a clear support status. Update support infos so that all coins have a clear support status.
By default, marks duplicate tokens as unsupported, and all coins that either By default, marks duplicate tokens and testnets as unsupported, and all coins that
don't have support info, or they are supported "soon", are set to the don't have support info are set to the released firmware version.
released firmware version.
Optionally tags the repository with the given version. The tool will ask you to confirm each added coin. ERC20 tokens are added
automatically. Use `--verbose` to see them.
`device` can be "1", "2", or a string matching `support.json` key. Version
is autodetected by downloading a list of latest releases and incrementing
micro version by one, or you can specify `--version` explicitly.
Unless `--add-all` is specified, the tool will ask you to confirm each added
coin. ERC20 tokens are added automatically. Use `--verbose` to see them.
""" """
# check condition(s) latest_releases = coin_info.latest_releases()
if soon and git_tag:
raise click.ClickException("Cannot git-tag a 'soon' revision")
# process `device` def bump_version(version_tuple):
if device.isnumeric(): version_list = list(version_tuple)
device = f"trezor{device}" version_list[-1] += 1
return ".".join(str(n) for n in version_list)
if not force and device not in coin_info.VERSIONED_SUPPORT_INFO:
raise click.ClickException(
f"Non-releasable device {device} (support info is not versioned). "
"Use --force to proceed anyway."
)
if not soon:
# guess `version` if not given # guess `version` if not given
if not version: if not v1:
versions = coin_info.latest_releases() v1 = bump_version(latest_releases["trezor1"])
latest_version = versions.get(device) if not v2:
if latest_version is None: v2 = bump_version(latest_releases["trezor2"])
raise click.ClickException(
"Failed to guess version. "
"Please use --version to specify it explicitly."
)
else:
latest_version = list(latest_version)
latest_version[-1] += 1
version = ".".join(str(n) for n in latest_version)
# process `version` versions = {"trezor1": v1, "trezor2": v2}
try:
version_numbers = list(map(int, version.split("."))) for number in "1", "2":
expected_device = f"trezor{version_numbers[0]}" device = f"trezor{number}"
if not force and device != expected_device: version = versions[device]
if not force and not version.startswith(number + "."):
raise click.ClickException( raise click.ClickException(
f"Device {device} should not be version {version}. " f"Device trezor{device} should not be version {version}. "
"Use --force to proceed anyway." "Use --force to proceed anyway."
) )
except ValueError as e:
if not force:
raise click.ClickException(
f"Failed to parse '{version}' as a version. "
"Use --force to proceed anyway."
) from e
if soon:
version = "soon"
print(f"Moving {device} missing infos to 'soon'")
else:
print(f"Releasing {device} firmware version {version}") print(f"Releasing {device} firmware version {version}")
defs, _ = coin_info.coin_info_with_duplicates() defs, _ = coin_info.coin_info_with_duplicates()
@ -389,31 +363,33 @@ def release(
print("Fixing up data...") print("Fixing up data...")
ctx.invoke(fix, dry_run=True) ctx.invoke(fix, dry_run=True)
def maybe_add(coin, label): def maybe_add(coin):
add = False add = click.confirm(
if add_all: f"Add missing coin {coin['key']} ({coin['name']})?", default=True
add = True )
else: if not add:
text = f"Add {label} coin {coin['key']} ({coin['name']})?" unsupport_reason = click.prompt(
add = click.confirm(text, default=True) "Enter reason for not supporting (blank to skip)",
if add: default="",
set_supported(device, coin["key"], version) show_default=False,
)
if not unsupport_reason:
return
# if we're releasing, process coins marked "soon" for device, version in versions.items():
if not soon: if add:
supported, _ = support_dicts(device) support_setdefault(device, coin["key"], version)
soon_list = [ else:
coins_dict[key] support_setdefault(device, coin["key"], False, unsupport_reason)
for key, val in supported.items()
if val == "soon" and key in coins_dict
]
for coin in soon_list:
key = coin["key"]
maybe_add(coin, "soon")
# process missing (not listed) supportinfos # process missing (not listed) supportinfos
if release_missing: missing_list = []
missing_list = find_unsupported_coins(coins_dict)[device] unsupported = find_unsupported_coins(coins_dict)
for val in unsupported.values():
for coin in val:
if coin not in missing_list:
missing_list.append(coin)
tokens = [coin for coin in missing_list if coin_info.is_token(coin)] tokens = [coin for coin in missing_list if coin_info.is_token(coin)]
nontokens = [coin for coin in missing_list if not coin_info.is_token(coin)] nontokens = [coin for coin in missing_list if not coin_info.is_token(coin)]
for coin in tokens: for coin in tokens:
@ -421,18 +397,15 @@ def release(
# assert not coin.get("duplicate"), key # assert not coin.get("duplicate"), key
if verbose: if verbose:
print(f"Adding missing {key} ({coin['name']})") print(f"Adding missing {key} ({coin['name']})")
set_supported(device, key, version) for device, version in versions.items():
support_setdefault(device, key, version)
for coin in nontokens: for coin in nontokens:
maybe_add(coin, "missing") if skip_testnets and "testnet" in coin["name"].lower():
for device, version in versions.items():
tagname = f"{device}-{version}" support_setdefault(device, coin["key"], False, "(AUTO) exclude testnet")
if git_tag:
if dry_run:
print(f"Would tag current commit with {tagname}")
else: else:
print(f"Tagging current commit with {tagname}") maybe_add(coin)
subprocess.check_call(["git", "tag", tagname])
if not dry_run: if not dry_run:
write_support_info() write_support_info()