Stabilize staff concurrency and premium emoji; enable verified Drone deployment
Some checks failed
continuous-integration/drone/push Build is failing
Some checks failed
continuous-integration/drone/push Build is failing
This commit is contained in:
46
scripts/drone_deploy.py
Normal file
46
scripts/drone_deploy.py
Normal file
@@ -0,0 +1,46 @@
|
||||
"""Upload a tested artifact and environment over authenticated SSH; never log secrets."""
|
||||
import os
|
||||
from pathlib import Path
|
||||
import re
|
||||
import shlex
|
||||
import subprocess
|
||||
import tempfile
|
||||
import uuid
|
||||
|
||||
|
||||
def main():
|
||||
required = ["DEPLOY_HOST", "DEPLOY_USER", "DEPLOY_SSH_KEY", "DEPLOY_KNOWN_HOSTS", "DEPLOY_PATH", "LOTTERY_ENV"]
|
||||
for key in required:
|
||||
if not os.getenv(key, "").strip():
|
||||
raise SystemExit(f"Missing Drone secret/environment: {key}")
|
||||
host, user = os.environ["DEPLOY_HOST"], os.environ["DEPLOY_USER"]
|
||||
commit, build = os.environ["DRONE_COMMIT_SHA"], os.environ["DRONE_BUILD_NUMBER"]
|
||||
if not re.fullmatch(r"[a-zA-Z0-9.-]+", host) or not re.fullmatch(r"[a-zA-Z_][a-zA-Z0-9_-]*", user):
|
||||
raise SystemExit("Invalid deployment host/user")
|
||||
if not re.fullmatch(r"[a-f0-9]{40}", commit) or not re.fullmatch(r"[0-9]+", build):
|
||||
raise SystemExit("Invalid build identity")
|
||||
destination = f"{user}@{host}"
|
||||
remote = f"/tmp/lottery-deploy-{uuid.uuid4().hex}"
|
||||
with tempfile.TemporaryDirectory(prefix="lottery-ssh-") as directory:
|
||||
directory = Path(directory)
|
||||
key, known, environment = directory / "key", directory / "known_hosts", directory / "runtime.env"
|
||||
for path, value in ((key, "DEPLOY_SSH_KEY"), (known, "DEPLOY_KNOWN_HOSTS"), (environment, "LOTTERY_ENV")):
|
||||
path.write_text(os.environ[value].strip() + "\n", encoding="utf-8")
|
||||
path.chmod(0o600)
|
||||
options = ["-i", str(key), "-o", "BatchMode=yes", "-o", "IdentitiesOnly=yes",
|
||||
"-o", "StrictHostKeyChecking=yes", "-o", f"UserKnownHostsFile={known}",
|
||||
"-o", "ConnectTimeout=15"]
|
||||
def ssh(command):
|
||||
subprocess.run(["ssh", *options, destination, command], check=True, timeout=1200)
|
||||
ssh(f"umask 077; mkdir {shlex.quote(remote)}")
|
||||
try:
|
||||
subprocess.run(["scp", *options, "dist/lottery.tar.gz", "scripts/deploy_release.sh", str(environment),
|
||||
f"{destination}:{remote}/"], check=True, timeout=300)
|
||||
ssh("sh " + shlex.join([remote + "/deploy_release.sh", os.environ["DEPLOY_PATH"], remote, commit, build]))
|
||||
finally:
|
||||
# Remove only the exact uploaded secret, even when a deployment fails.
|
||||
ssh("rm -f -- " + shlex.quote(remote + "/runtime.env"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user