1 #! /usr/bin/env nix-shell
2 #! nix-shell -i python3 -p python3 python3.pkgs.semver nix-prefetch-github
3 from urllib
.request
import Request
, urlopen
17 SCRIPT_DIR
= os
.path
.dirname(os
.path
.abspath(__file__
))
18 NIXPKGS
= os
.path
.abspath(os
.path
.join(SCRIPT_DIR
, "../../../../"))
26 @dataclasses.dataclass
31 serverCargoHash
: str = ""
33 uiPNPMDepsHash
: str = ""
35 filename
: Optional
[str] = None
37 def write(self
) -> None:
39 raise ValueError("No filename set")
41 with
open(self
.filename
, "w") as fd
:
42 pin
= dataclasses
.asdict(self
)
44 json
.dump(pin
, fd
, indent
=2)
48 def github_get(path
: str) -> Dict
:
49 """Send a GET request to GitHub, optionally adding GITHUB_TOKEN auth header"""
50 url
= f
"https://api.github.com/{path.lstrip('/')}"
51 print(f
"Retrieving {url}")
55 if "GITHUB_TOKEN" in os
.environ
:
56 req
.add_header("authorization", f
"Bearer {os.environ['GITHUB_TOKEN']}")
58 with
urlopen(req
) as resp
:
59 return json
.loads(resp
.read())
62 def get_latest_release(owner
: str, repo
: str) -> str:
63 return github_get(f
"/repos/{owner}/{repo}/releases/latest")["tag_name"]
66 def prefetch_github(owner
: str, repo
: str, rev
: str) -> str:
67 """Prefetch GitHub rev and return SRI hash"""
68 print(f
"Prefetching {owner}/{repo}({rev})")
70 proc
= subprocess
.run(
71 ["nix-prefetch-github", owner
, repo
, "--rev", rev
, "--fetch-submodules"],
73 stdout
=subprocess
.PIPE
,
76 return json
.loads(proc
.stdout
)["hash"]
79 def get_latest_tag(owner
: str, repo
: str, prerelease
: bool = False) -> str:
80 """Get the latest tag from a GitHub Repo"""
83 # As the GitHub API doesn't have any notion of "latest" for tags we need to
84 # collect all of them and sort so we can figure out the latest one.
86 while i
<= 100: # Prevent infinite looping
88 resp
= github_get(f
"/repos/{owner}/{repo}/tags?page={i}")
92 # Filter out unparseable tags
95 parsed
= semver
.Version
.parse(tag
["name"])
97 semver
.Version
.parse(tag
["name"])
100 ): # Filter out release candidates
105 tags
.append(tag
["name"])
107 # Sort and return latest
108 return sorted(tags
, key
=lambda name
: semver
.Version
.parse(name
))[-1]
111 def get_fod_hash(attr
: str) -> str:
113 Get fixed output hash for attribute.
114 This depends on a fixed output derivation with an empty hash.
117 print(f
"Getting fixed output hash for {attr}")
119 proc
= subprocess
.run(["nix-build", NIXPKGS
, "-A", attr
], stderr
=subprocess
.PIPE
)
120 if proc
.returncode
!= 1:
121 raise ValueError("Expected nix-build to fail")
123 # Iterate list in reverse order so we get the "got:" line early
124 for line
in proc
.stderr
.decode().split("\n")[::-1]:
126 if cols
and cols
[0] == "got:":
129 raise ValueError("No fixed output hash found")
132 def make_server_pin(pin
: Pin
, attr
: str) -> None:
133 pin
.serverHash
= prefetch_github(OWNER
, SERVER_REPO
, pin
.serverVersion
)
135 pin
.serverCargoHash
= get_fod_hash(attr
)
139 def make_ui_pin(pin
: Pin
, attr
: str) -> None:
140 pin
.uiHash
= prefetch_github(OWNER
, UI_REPO
, pin
.uiVersion
)
142 pin
.uiPNPMDepsHash
= get_fod_hash(attr
)
146 if __name__
== "__main__":
148 server_version
= get_latest_tag(OWNER
, SERVER_REPO
)
150 # Get UI version (not always the same as lemmy-server)
151 ui_version
= get_latest_tag(OWNER
, UI_REPO
)
153 pin
= Pin(server_version
, ui_version
, filename
=os
.path
.join(SCRIPT_DIR
, "pin.json"))
154 make_server_pin(pin
, "lemmy-server")
155 make_ui_pin(pin
, "lemmy-ui")