mirror of
https://github.com/Shu-Ying/main_plugin_farm.git
synced 2026-10-27 20:50:06 +08:00
101 lines
3.9 KiB
Python
101 lines
3.9 KiB
Python
"""只向固定真寻预览分支普通更新;默认离线dry-run。"""
|
|
|
|
import argparse
|
|
import base64
|
|
import json
|
|
import os
|
|
from urllib.error import HTTPError
|
|
from urllib.request import Request, urlopen
|
|
|
|
from verify_zhenxun import read_package, verify_files
|
|
|
|
REPOSITORY = "Shu-Ying/zhenxun_plugin_farm"
|
|
BRANCH = "farm-preview"
|
|
|
|
|
|
def github(method, path, payload, token):
|
|
request = Request(
|
|
f"https://api.github.com/repos/{REPOSITORY}/{path}",
|
|
data=json.dumps(payload).encode() if payload is not None else None,
|
|
headers={"Authorization": f"Bearer {token}",
|
|
"Accept": "application/vnd.github+json",
|
|
"X-GitHub-Api-Version": "2022-11-28",
|
|
"User-Agent": "farm-preview-publisher"}, method=method,
|
|
)
|
|
try:
|
|
with urlopen(request, timeout=30) as response:
|
|
return json.load(response)
|
|
except HTTPError as error:
|
|
if error.code == 404 and method == "GET":
|
|
return None
|
|
raise RuntimeError(
|
|
f"GitHub request failed: HTTP {error.code}",
|
|
) from None
|
|
|
|
|
|
def publish(package, confirmed=False, request=None):
|
|
files = read_package(package)
|
|
manifest = verify_files(files)
|
|
result = {"repository": REPOSITORY, "branch": BRANCH,
|
|
"version": manifest["version"], "published": False}
|
|
if not confirmed:
|
|
return result
|
|
if manifest["source"]["dirty"]:
|
|
raise ValueError("Publish requires a clean source checkout")
|
|
token = os.environ.get("FARM_RELEASE_TOKEN")
|
|
if not token:
|
|
raise ValueError("Configure FARM_RELEASE_TOKEN in a protected job")
|
|
call = request or (lambda method, path, data: github(
|
|
method, path, data, token,
|
|
))
|
|
repository = call("GET", "", None)
|
|
if not repository or repository.get("default_branch") == BRANCH:
|
|
raise ValueError("Preview must not be the repository default branch")
|
|
ref = call("GET", f"git/ref/heads/{BRANCH}", None)
|
|
parent = ref["object"]["sha"] if ref else None
|
|
if parent:
|
|
owned = call("GET", f"contents/FARM-MANIFEST.json?ref={BRANCH}", None)
|
|
if not owned or owned.get("encoding") != "base64":
|
|
raise ValueError("Existing preview branch is not generated by Farm")
|
|
previous = json.loads(base64.b64decode(owned["content"]))
|
|
if (previous.get("target") != "zhenxun"
|
|
or previous.get("plugin") != manifest["plugin"]):
|
|
raise ValueError("Existing preview branch ownership differs")
|
|
tree = []
|
|
for name, content in sorted(files.items()):
|
|
blob = call("POST", "git/blobs", {
|
|
"content": base64.b64encode(content).decode(), "encoding":"base64",
|
|
})
|
|
tree.append({"path":name, "mode":"100644", "type":"blob",
|
|
"sha":blob["sha"]})
|
|
generated = call("POST", "git/trees", {"tree":tree})
|
|
commit = call("POST", "git/commits", {
|
|
"message": f"Generate farm preview {manifest['version']} "
|
|
f"from {manifest['source']['commit']}",
|
|
"tree": generated["sha"], "parents": [parent] if parent else [],
|
|
})
|
|
if parent:
|
|
current = call("GET", f"git/ref/heads/{BRANCH}", None)
|
|
if not current or current["object"]["sha"] != parent:
|
|
raise RuntimeError("Preview branch changed; retry explicitly")
|
|
call("PATCH", f"git/refs/heads/{BRANCH}", {
|
|
"sha": commit["sha"], "force": False,
|
|
})
|
|
else:
|
|
call("POST", "git/refs", {
|
|
"ref": f"refs/heads/{BRANCH}", "sha": commit["sha"],
|
|
})
|
|
return {**result, "published": True, "commit": commit["sha"]}
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("package")
|
|
parser.add_argument("--publish", action="store_true")
|
|
args = parser.parse_args()
|
|
print(json.dumps(publish(args.package, args.publish), ensure_ascii=False))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|