This commit is contained in:
2026-07-28 21:28:53 +04:00
parent 3b01afeeb2
commit f395d2515d
3 changed files with 81 additions and 37 deletions
+4
View File
@@ -37,6 +37,10 @@ Install the Python dependency if required:
python -m pip install boto3 python -m pip install boto3
``` ```
The PowerShell entry point calls `tool/upload_launcher_release.py` as a regular
Python file. Keep this helper beside the deployment script; it performs the S3
upload and verifies the uploaded object's byte length.
Back up `.moonwell_signing\dsa_priv.pem` in the project secret store. Never Back up `.moonwell_signing\dsa_priv.pem` in the project secret store. Never
commit it, upload it to Object Storage, or send it through chat. Losing this key commit it, upload it to Object Storage, or send it through chat. Losing this key
prevents released launchers from accepting future updates. prevents released launchers from accepting future updates.
+7 -37
View File
@@ -617,45 +617,15 @@ try {
$env:MOONWELL_RELEASE_KEY = $S3Key $env:MOONWELL_RELEASE_KEY = $S3Key
$env:MOONWELL_RELEASE_VERSION = $version $env:MOONWELL_RELEASE_VERSION = $version
$env:MOONWELL_RELEASE_SHA256 = $installerSha256 $env:MOONWELL_RELEASE_SHA256 = $installerSha256
$uploadScript = @' $uploadHelper = Join-Path `
import os $repositoryRoot `
import boto3 'tool\upload_launcher_release.py'
from botocore.config import Config if (-not (Test-Path -LiteralPath $uploadHelper -PathType Leaf)) {
throw "S3 upload helper was not found: $uploadHelper"
}
path_style = os.getenv("AWS_USE_PATH_STYLE_ENDPOINT", "true").lower()
addressing_style = "path" if path_style in ("1", "true", "yes") else "virtual"
s3 = boto3.client(
"s3",
endpoint_url=os.environ["MOONWELL_RELEASE_ENDPOINT"],
region_name=os.getenv("AWS_DEFAULT_REGION", "ru-central1"),
config=Config(s3={"addressing_style": addressing_style}),
)
s3.upload_file(
os.environ["MOONWELL_RELEASE_FILE"],
os.environ["MOONWELL_RELEASE_BUCKET"],
os.environ["MOONWELL_RELEASE_KEY"],
ExtraArgs={
"ACL": "public-read",
"ContentType": "application/x-msdownload",
"CacheControl": "no-cache, max-age=0",
"Metadata": {
"launcher-version": os.environ["MOONWELL_RELEASE_VERSION"],
"sha256": os.environ["MOONWELL_RELEASE_SHA256"],
},
},
)
response = s3.head_object(
Bucket=os.environ["MOONWELL_RELEASE_BUCKET"],
Key=os.environ["MOONWELL_RELEASE_KEY"],
)
print("S3_VERSION_ID=" + str(response.get("VersionId", "")))
print("S3_CONTENT_LENGTH=" + str(response["ContentLength"]))
'@
try { try {
Invoke-RequiredCommand -Command $python -Arguments @( Invoke-RequiredCommand -Command $python -Arguments @($uploadHelper)
'-c',
$uploadScript
)
} }
finally { finally {
Remove-Item Env:MOONWELL_RELEASE_FILE -ErrorAction SilentlyContinue Remove-Item Env:MOONWELL_RELEASE_FILE -ErrorAction SilentlyContinue
+70
View File
@@ -0,0 +1,70 @@
"""Upload a MoonWell Launcher installer to S3-compatible storage.
Release metadata is supplied by ``deploy_launcher.ps1`` through environment
variables. A real Python file avoids Windows PowerShell quoting problems that
occur when a multiline program is passed to ``python -c``.
"""
from __future__ import annotations
import os
from pathlib import Path
import boto3
from botocore.config import Config
def required_environment_value(name: str) -> str:
value = os.environ.get(name, "").strip()
if not value:
raise RuntimeError(f"Required environment variable is missing: {name}")
return value
release_file = Path(required_environment_value("MOONWELL_RELEASE_FILE"))
endpoint = required_environment_value("MOONWELL_RELEASE_ENDPOINT")
bucket = required_environment_value("MOONWELL_RELEASE_BUCKET")
object_key = required_environment_value("MOONWELL_RELEASE_KEY")
version = required_environment_value("MOONWELL_RELEASE_VERSION")
sha256 = required_environment_value("MOONWELL_RELEASE_SHA256")
if not release_file.is_file():
raise FileNotFoundError(f"Installer does not exist: {release_file}")
path_style = os.getenv("AWS_USE_PATH_STYLE_ENDPOINT", "true").lower()
addressing_style = (
"path" if path_style in ("1", "true", "yes") else "virtual"
)
s3 = boto3.client(
"s3",
endpoint_url=endpoint,
region_name=os.getenv("AWS_DEFAULT_REGION", "ru-central1"),
config=Config(s3={"addressing_style": addressing_style}),
)
s3.upload_file(
str(release_file),
bucket,
object_key,
ExtraArgs={
"ACL": "public-read",
"ContentType": "application/x-msdownload",
"CacheControl": "no-cache, max-age=0",
"Metadata": {
"launcher-version": version,
"sha256": sha256,
},
},
)
response = s3.head_object(Bucket=bucket, Key=object_key)
local_size = release_file.stat().st_size
remote_size = int(response["ContentLength"])
if remote_size != local_size:
raise RuntimeError(
f"Uploaded object size mismatch: local={local_size}, "
f"remote={remote_size}"
)
print("S3_VERSION_ID=" + str(response.get("VersionId", "")))
print("S3_CONTENT_LENGTH=" + str(remote_size))