1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-03 20:11:00 +00:00

support: finish support.py release flow

This commit is contained in:
matejcik 2018-08-24 15:21:11 +02:00
parent 0abfb6cd91
commit 15a971764a

View File

@ -1,6 +1,7 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import re import re
import os import os
import subprocess
import sys import sys
import click import click
import coin_info import coin_info
@ -204,13 +205,13 @@ def cli():
@cli.command() @cli.command()
def fix(): @click.option("-n", "--dry-run", is_flag=True, help="Do not write changes")
def fix(dry_run):
"""Fix expected problems. """Fix expected problems.
Prunes orphaned keys and ensures that ERC20 duplicate info matches support info. Prunes orphaned keys and ensures that ERC20 duplicate info matches support info.
""" """
all_coins = coin_info.get_all(deduplicate=False) all_coins, _ = coin_info.coin_info_with_duplicates()
coin_info.mark_duplicate_shortcuts(all_coins.as_list())
coins_dict = all_coins.as_dict() coins_dict = all_coins.as_dict()
orphaned = find_orphaned_support_keys(coins_dict) orphaned = find_orphaned_support_keys(coins_dict)
@ -220,7 +221,8 @@ def fix():
clear_support(device, orphan) clear_support(device, orphan)
process_erc20(coins_dict) process_erc20(coins_dict)
write_support_info() if not dry_run:
write_support_info()
@cli.command() @cli.command()
@ -242,8 +244,7 @@ def check(ignore_tokens, ignore_missing):
support info, but will not fail when missing coins are found. This is support info, but will not fail when missing coins are found. This is
useful in Travis. useful in Travis.
""" """
all_coins = coin_info.get_all(deduplicate=False) all_coins, _ = coin_info.coin_info_with_duplicates()
coin_info.mark_duplicate_shortcuts(all_coins.as_list())
coins_dict = all_coins.as_dict() coins_dict = all_coins.as_dict()
checks_ok = True checks_ok = True
@ -281,14 +282,27 @@ def check(ignore_tokens, ignore_missing):
@cli.command() @cli.command()
# fmt: off # fmt: off
@click.argument("version") @click.argument("device")
@click.option("--git-tag/--no-git-tag", "-g", default=False, help="create a corresponding Git tag") @click.option("-r", "--version", help="Set explicit version string (default: guess from latest release)")
@click.option("--git-tag/--no-git-tag", "-g", default=False, help="Create a corresponding Git tag")
@click.option("--release-soon/--no-release-soon", default=True, help="Release coins marked 'soon'") @click.option("--release-soon/--no-release-soon", default=True, help="Release coins marked 'soon'")
@click.option("--release-missing/--no-release-missing", default=True, help="Release coins with missing support info") @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("-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")
# fmt: on # fmt: on
def release(version, git_tag, release_soon, release_missing, dry_run, soon): @click.pass_context
def release(
ctx,
device: str,
version,
git_tag,
release_soon,
release_missing,
dry_run,
soon,
force,
):
"""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.
@ -297,41 +311,87 @@ def release(version, git_tag, release_soon, release_missing, dry_run, soon):
released firmware version. released firmware version.
Optionally tags the repository with the given version. Optionally tags the repository with the given version.
"""
version_tuple = list(map(int, version.split(".")))
device = f"trezor{version_tuple[0]}"
`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.
"""
# check condition(s)
if soon and git_tag: if soon and git_tag:
raise click.ClickException("Cannot git-tag a 'soon' revision") raise click.ClickException("Cannot git-tag a 'soon' revision")
# process `device`
if device.isnumeric():
device = f"trezor{device}"
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
if not version:
versions = coin_info.latest_releases()
latest_version = versions.get(device)
if latest_version is None:
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`
try:
version_numbers = list(map(int, version.split(".")))
expected_device = f"trezor{version_numbers[0]}"
if not force and device != expected_device:
raise click.ClickException(
f"Device {device} should not be version {version}. "
"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: if soon:
version = "soon" version = "soon"
print(f"Moving {device} missing infos to 'soon'") print(f"Moving {device} missing infos to 'soon'")
else: else:
print(f"Releasing {device} firmware version {version}") print(f"Releasing {device} firmware version {version}")
defs = coin_info.get_all(deduplicate=False) defs, _ = coin_info.coin_info_with_duplicates()
coin_info.mark_duplicate_shortcuts(defs.as_list())
coins_dict = defs.as_dict() coins_dict = defs.as_dict()
# process those darned ERC20 duplicates # Invoke data fixup as dry-run. That will modify data internally but won't write
# changes. We will write changes at the end based on our own `dry_run` value.
print("Fixing up data...")
ctx.invoke(fix, dry_run=True)
# process missing (not listed) supportinfos
if release_missing: if release_missing:
missing_list = find_unsupported_coins(coins_dict)[device] missing_list = find_unsupported_coins(coins_dict)[device]
for coin in missing_list: for coin in missing_list:
key = coin["key"] key = coin["key"]
if coin.get("duplicate") and coin_info.is_token(coin): # we should have no unprocessed dup tokens at this point
print(f"UNsupporting duplicate coin {key} ({coin['name']})") assert not (coin.get("duplicate") and coin_info.is_token(coin))
set_unsupported(device, key, ERC20_DUPLICATE_KEY) print(f"Adding missing {key} ({coin['name']})")
else: set_supported(device, key, version)
print(f"Adding missing {key} ({coin['name']})")
set_supported(device, key, version)
# if we're releasing, process coins marked "soon"
# (`not soon` because `soon` means set release version to "soon")
if not soon and release_soon: if not soon and release_soon:
supported, _ = support_dicts(device) supported, _ = support_dicts(device)
soon_list = [ soon_list = [
coins_dict[key] coins_dict[key]
for key, val in supported for key, val in supported.items()
if val == "soon" and key in coins_dict if val == "soon" and key in coins_dict
] ]
for coin in soon_list: for coin in soon_list:
@ -339,8 +399,13 @@ def release(version, git_tag, release_soon, release_missing, dry_run, soon):
print(f"Adding soon-released {key} ({coin['name']})") print(f"Adding soon-released {key} ({coin['name']})")
set_supported(device, key, version) set_supported(device, key, version)
tagname = f"{device}-{version}"
if git_tag: if git_tag:
print("git tag not supported yet") if dry_run:
print(f"Would tag current commit with {tagname}")
else:
print(f"Tagging current commit with {tagname}")
subprocess.check_call(["git", "tag", tagname])
if not dry_run: if not dry_run:
write_support_info() write_support_info()
@ -355,8 +420,7 @@ def show(keyword):
Keywords match against key, name or shortcut (ticker symbol) of coin. Keywords match against key, name or shortcut (ticker symbol) of coin.
""" """
defs = coin_info.get_all(deduplicate=False).as_list() defs = coin_info.coin_info_with_duplicates()
coin_info.mark_duplicate_shortcuts(defs)
for kw in keyword: for kw in keyword:
for coin in coin_info.search(defs, kw): for coin in coin_info.search(defs, kw):
@ -388,8 +452,8 @@ def set_support_value(key, entries, reason):
Entries with other names will be inserted into "others". This is a good place Entries with other names will be inserted into "others". This is a good place
to store links to 3rd party software, such as Electrum forks or claim tools. to store links to 3rd party software, such as Electrum forks or claim tools.
""" """
coins = coin_info.get_all(deduplicate=False).as_dict() defs, _ = coin_info.coin_info_with_duplicates()
coin_info.mark_duplicate_shortcuts(coins.values()) coins = defs.as_dict()
if key not in coins: if key not in coins:
click.echo(f"Failed to find key {key}") click.echo(f"Failed to find key {key}")
click.echo("Use 'support.py show' to search for the right one.") click.echo("Use 'support.py show' to search for the right one.")