1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
|
"""
scripts/release/repo_init.py
Run ONCE PER PLATFORM, by the maintainer, locally, on a machine running that
platform (no cross-compiling — build and sign Windows releases on Windows,
Linux releases on Linux/WSL2, etc.). Generates that platform's TUF signing
keys and initial repository metadata (including root.json, which later gets
bundled into that platform's build via labui.spec).
Every platform gets its own keystore/repository tree, under
scripts/release/<platform>/ — Windows and Linux builds of the same version
are different byte-for-byte archives, and TUF's metadata filenames
(root.json, timestamp.json, ...) aren't platform-prefixed, so they can't
share one repo/release without one platform silently overwriting the
other's trust root and metadata.
Running this again after a platform's repo already exists is safe (tufup
skips re-creating keys/roles that already exist) but there is normally no
reason to run it more than once per platform.
Keys land in ./<platform>/keystore — never commit that directory (already
gitignored). Back it up somewhere safe and private, once per platform;
losing a platform's root key means you can never publish another trusted
update to that platform's existing installs.
"""
import os
import sys
from pathlib import Path
from tufup.repo import Repository, RolesDict
def _platform_key() -> str:
"""win / mac / linux — must match core.updater._platform_key() and the
"updates-<key>" release tag on the publishing side."""
if sys.platform.startswith("win"):
return "win"
if sys.platform == "darwin":
return "mac"
return "linux"
PLATFORM = _platform_key()
# Run from this script's own platform subdirectory — tufup's config file
# (.tufup-repo-config) and all repo_dir/keys_dir paths are resolved relative
# to the current working directory, so invocation location must be
# consistent every time.
_PLATFORM_DIR = Path(__file__).resolve().parent / PLATFORM
_PLATFORM_DIR.mkdir(parents=True, exist_ok=True)
os.chdir(_PLATFORM_DIR)
APP_NAME = "labui"
# tufup-example's 1-day timestamp / 7-day snapshot defaults assume an
# automated CI worker re-signs on a schedule. We're signing manually
# (see README.md in this directory), so use longer, human-manageable
# expirations instead. Whichever of these lapses first is the cadence
# you need to re-sign at, even between actual app releases.
EXPIRATION_DAYS = RolesDict(root=365, targets=90, snapshot=90, timestamp=90)
def main():
# Not using app_version_attr here: tufup's setuptools-based attribute
# reader resolves dotted paths relative to the current working directory,
# which we deliberately pin to this script's own directory below (tufup's
# own config-file/relative-path handling expects that) — the two
# assumptions conflict. repo_release.py passes the version explicitly
# instead, which sidesteps this entirely.
repo = Repository(
app_name=APP_NAME,
repo_dir=Path("repository"),
keys_dir=Path("keystore"),
expiration_days=EXPIRATION_DAYS,
)
repo.initialize()
repo.save_config()
print(f"Initialized tufup repo for '{APP_NAME}' ({PLATFORM}) in "
f"{_PLATFORM_DIR / 'repository'}, keys in {_PLATFORM_DIR / 'keystore'}")
print(f"Back up {_PLATFORM_DIR / 'keystore'} now, somewhere private and "
f"durable. It is gitignored on purpose.")
if __name__ == "__main__":
main()
|