-
-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ocis-bin: support more architectures and add update script
* Adds an update script that can be used by the passthru updateScript [0] * this script tracks the Production (aka stable) channel for oCIS https://owncloud.dev/ocis/release_roadmap/#release-types as decided by the package maintainers * Adds the full range of architectures released by owncloud * darwin: amd64, aarch64 * linux: i686, x86_64, arm, aarch64 [0]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/README.md#automatic-package-updates
- Loading branch information
Showing
2 changed files
with
258 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,215 @@ | ||
#!/usr/bin/env nix-shell | ||
##!nix-shell -I nixpkgs=./. -i python312 -p common-updater-scripts gnused nix coreutils python312 | ||
""" | ||
Updater script for the ocis-bin package. | ||
This script fetches an HTML table from a specified URL and parses it to determine the release type | ||
(either "Rolling" or "Production") of a given software version. It uses the built-in urllib.request | ||
for fetching the HTML content and the built-in html.parser for parsing the HTML. By relying only on | ||
standard library modules, we avoid dependencies on third-party libraries, which simplifies deployment | ||
and improves portability. | ||
""" | ||
import urllib.request | ||
import os | ||
import subprocess | ||
import json | ||
import sys | ||
from datetime import datetime | ||
from html.parser import HTMLParser | ||
|
||
TRACKING_CHANNEL = "Production" # Either Rolling or Production | ||
|
||
GITHUB_TOKEN = os.getenv("GITHUB_TOKEN", None) | ||
|
||
|
||
class TableParser(HTMLParser): | ||
def __init__(self, version): | ||
super().__init__() | ||
self.version = version | ||
self.in_td = False | ||
self.current_row = [] | ||
self.release_type = None | ||
self.in_target_row = False | ||
|
||
def handle_starttag(self, tag, attrs): | ||
if tag == "td": | ||
self.in_td = True | ||
|
||
if tag == "a": | ||
href = dict(attrs).get("href", "") | ||
if self.version in href: | ||
self.in_target_row = True | ||
|
||
def handle_endtag(self, tag): | ||
if tag == "td": | ||
self.in_td = False | ||
|
||
if tag == "tr" and self.in_target_row: | ||
self.release_type = self.current_row[1] | ||
self.in_target_row = False | ||
|
||
if tag == "tr": | ||
self.current_row = [] | ||
|
||
def handle_data(self, data): | ||
if self.in_td: | ||
self.current_row.append(data.strip()) | ||
|
||
|
||
def get_release_type(content, version): | ||
parser = TableParser(version) | ||
parser.feed(content) | ||
return parser.release_type | ||
|
||
|
||
def get_latest_version(): | ||
url = "https://api.github.com/repos/owncloud/ocis/releases?per_page=1" | ||
req = urllib.request.Request(url) | ||
|
||
if GITHUB_TOKEN: | ||
req.add_header("Authorization", f"Bearer {GITHUB_TOKEN}") | ||
|
||
with urllib.request.urlopen(req) as response: | ||
if response.status != 200: | ||
raise Exception(f"HTTP request failed with status {response.status}") | ||
|
||
data = response.read() | ||
releases = json.loads(data) | ||
latest_version = releases[0]["tag_name"].lstrip("v") | ||
|
||
return latest_version | ||
|
||
|
||
def get_all_versions(): | ||
url = "https://api.github.com/repos/owncloud/ocis/releases" | ||
req = urllib.request.Request(url) | ||
|
||
if GITHUB_TOKEN: | ||
req.add_header("Authorization", f"Bearer {GITHUB_TOKEN}") | ||
|
||
with urllib.request.urlopen(req) as response: | ||
if response.status != 200: | ||
raise Exception(f"HTTP request failed with status {response.status}") | ||
|
||
data = response.read() | ||
releases = json.loads(data) | ||
|
||
versions = [] | ||
for release in releases: | ||
version = release["tag_name"].lstrip("v") | ||
published_date = datetime.strptime( | ||
release["published_at"], "%Y-%m-%dT%H:%M:%SZ" | ||
) | ||
versions.append({"version": version, "published_date": published_date}) | ||
|
||
return versions | ||
|
||
|
||
def get_current_version(): | ||
result = subprocess.run( | ||
[ | ||
"nix-instantiate", | ||
"--eval", | ||
"-E", | ||
"with import ./. {}; ocis-bin.version or (lib.getVersion ocis-bin)", | ||
], | ||
capture_output=True, | ||
text=True, | ||
) | ||
result.check_returncode() | ||
return result.stdout.strip().strip('"') | ||
|
||
|
||
def get_hash(os_name, arch, version): | ||
url = f"https://github.com/owncloud/ocis/releases/download/v{version}/ocis-{version}-{os_name}-{arch}" | ||
result = subprocess.run( | ||
["nix-prefetch-url", "--type", "sha256", url], capture_output=True, text=True | ||
) | ||
result.check_returncode() | ||
pkg_hash = result.stdout.strip() | ||
result = subprocess.run( | ||
["nix", "hash", "to-sri", f"sha256:{pkg_hash}"], capture_output=True, text=True | ||
) | ||
result.check_returncode() | ||
return result.stdout.strip() | ||
|
||
|
||
def update_source_version(pkg_name, version, hash_value, system): | ||
subprocess.run( | ||
[ | ||
"update-source-version", | ||
pkg_name, | ||
version, | ||
hash_value, | ||
f"--system={system}", | ||
"--ignore-same-version", | ||
], | ||
check=True, | ||
) | ||
|
||
|
||
def main(): | ||
all_versions = get_all_versions() | ||
latest_version = all_versions[0] | ||
nix_current_version = get_current_version() | ||
|
||
current_version = None | ||
for version in all_versions: | ||
if nix_current_version == version["version"]: | ||
current_version = version | ||
break | ||
|
||
if not current_version: | ||
print( | ||
f"error: cannot find github release for current nix version of ocis-bin {nix_current_version}" | ||
) | ||
sys.exit(1) | ||
|
||
if current_version == latest_version: | ||
print(f"ocis-bin is up-to-date: {current_version}") | ||
return | ||
|
||
roadmap_url = "https://owncloud.dev/ocis/release_roadmap/" | ||
response = urllib.request.urlopen(roadmap_url) | ||
content = response.read().decode("utf-8") | ||
latest_version_channel = get_release_type(content, latest_version["version"]) | ||
current_version_channel = get_release_type(content, current_version["version"]) | ||
|
||
target_version = None | ||
if latest_version_channel == TRACKING_CHANNEL: | ||
target_version = latest_version | ||
elif latest_version_channel != TRACKING_CHANNEL: | ||
for version in all_versions: | ||
channel = get_release_type(content, version["version"]) | ||
if ( | ||
channel == TRACKING_CHANNEL | ||
and version["published_date"] > current_version["published_date"] | ||
): | ||
target_version = version | ||
print( | ||
f"ocis-bin found newer version {version['version']} in channel {TRACKING_CHANNEL}" | ||
) | ||
break | ||
|
||
if not target_version: | ||
print( | ||
f"ocis-bin could not find newer version in {TRACKING_CHANNEL} than the current {current_version['version']}" | ||
) | ||
return | ||
|
||
systems = [ | ||
("darwin", "arm64", "aarch64-darwin"), | ||
("darwin", "amd64", "x86_64-darwin"), | ||
("linux", "arm64", "aarch64-linux"), | ||
("linux", "arm", "armv7l-linux"), | ||
("linux", "amd64", "x86_64-linux"), | ||
("linux", "386", "i686-linux"), | ||
] | ||
|
||
for os_name, arch, system in systems: | ||
hash_value = get_hash(os_name, arch, target_version["version"]) | ||
update_source_version("ocis-bin", target_version["version"], hash_value, system) | ||
|
||
|
||
if __name__ == "__main__": | ||
main() |