216 lines
5.5 KiB
Python
216 lines
5.5 KiB
Python
#!/usr/bin/env python3
|
|
|
|
from __future__ import annotations
|
|
|
|
from dataclasses import dataclass
|
|
from datetime import datetime, timezone
|
|
from typing import Mapping
|
|
|
|
from ci_utils import write_github_output, write_github_summary
|
|
|
|
|
|
ADD_KNOWN_HOSTS_SCRIPT = """
|
|
set -euo pipefail
|
|
mkdir -p ~/.ssh
|
|
ssh-keyscan -H "${SERVER_IP}" >> ~/.ssh/known_hosts
|
|
"""
|
|
|
|
INSTALL_DOCKER_PUSSH_SCRIPT = """
|
|
set -euo pipefail
|
|
mkdir -p ~/.docker/cli-plugins
|
|
curl -fsSL https://raw.githubusercontent.com/psviderski/unregistry/v0.3.1/docker-pussh \
|
|
-o ~/.docker/cli-plugins/docker-pussh
|
|
chmod +x ~/.docker/cli-plugins/docker-pussh
|
|
"""
|
|
|
|
INSTALL_RCLONE_SCRIPT = """
|
|
set -euo pipefail
|
|
if ! command -v rclone >/dev/null 2>&1; then
|
|
curl -fsSL https://rclone.org/install.sh | sudo bash
|
|
fi
|
|
"""
|
|
|
|
|
|
def rclone_config_script(
|
|
*,
|
|
endpoint: str,
|
|
acl: str,
|
|
profile: str = "ovh",
|
|
env_auth: bool = True,
|
|
expand_vars: bool = False,
|
|
) -> str:
|
|
heredoc = "RCLONEEOF" if expand_vars else "'RCLONEEOF'"
|
|
env_auth_value = "true" if env_auth else "false"
|
|
lines = [
|
|
"set -euo pipefail",
|
|
"mkdir -p ~/.config/rclone",
|
|
f"cat > ~/.config/rclone/rclone.conf <<{heredoc}",
|
|
f"[{profile}]",
|
|
"type = s3",
|
|
"provider = Other",
|
|
f"env_auth = {env_auth_value}",
|
|
f"endpoint = {endpoint}",
|
|
f"acl = {acl}",
|
|
"RCLONEEOF",
|
|
]
|
|
return "\n".join(lines) + "\n"
|
|
|
|
|
|
def bot_user_id_script() -> str:
|
|
return (
|
|
"set -euo pipefail\n"
|
|
"echo \"user-id=$(gh api \"/users/${APP_SLUG}[bot]\" --jq .id)\" >> \"$GITHUB_OUTPUT\"\n"
|
|
)
|
|
|
|
|
|
def record_deploy_commit_script(*, include_env: bool, include_sentry: bool) -> str:
|
|
lines = [
|
|
"set -euo pipefail",
|
|
"sha=$(git rev-parse HEAD)",
|
|
"echo \"Deploying commit ${sha}\"",
|
|
]
|
|
if include_env:
|
|
lines.append("printf 'DEPLOY_SHA=%s\\n' \"$sha\" >> \"$GITHUB_ENV\"")
|
|
if include_sentry:
|
|
lines.extend(
|
|
[
|
|
"printf 'SENTRY_BUILD_SHA=%s\\n' \"$sha\" >> \"$GITHUB_ENV\"",
|
|
"printf 'SENTRY_BUILD_NUMBER=%s\\n' \"$GITHUB_RUN_NUMBER\" >> \"$GITHUB_ENV\"",
|
|
"printf 'SENTRY_BUILD_TIMESTAMP=%s\\n' \"$(date +%s)\" >> \"$GITHUB_ENV\"",
|
|
]
|
|
)
|
|
return "\n".join(lines) + "\n"
|
|
|
|
|
|
def set_build_timestamp_script(*, env_name: str = "BUILD_TIMESTAMP") -> str:
|
|
return (
|
|
"set -euo pipefail\n"
|
|
f"echo \"{env_name}=$(date -u +%s)\" >> \"$GITHUB_ENV\"\n"
|
|
)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class ReleaseMetadata:
|
|
version: str
|
|
channel: str
|
|
source_ref: str
|
|
sha_short: str
|
|
timestamp: str
|
|
date_ymd: str
|
|
build_number: str
|
|
|
|
|
|
def build_release_metadata(
|
|
*,
|
|
version_input: str,
|
|
channel: str,
|
|
source_ref: str,
|
|
env: Mapping[str, str],
|
|
now: datetime | None = None,
|
|
) -> ReleaseMetadata:
|
|
run_number = env.get("GITHUB_RUN_NUMBER", "")
|
|
sha = env.get("GITHUB_SHA", "")
|
|
version = version_input or f"0.0.{run_number}"
|
|
instant = now or datetime.now(timezone.utc)
|
|
timestamp = instant.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
date_ymd = instant.strftime("%Y%m%d")
|
|
sha_short = sha[:7]
|
|
return ReleaseMetadata(
|
|
version=version,
|
|
channel=channel,
|
|
source_ref=source_ref,
|
|
sha_short=sha_short,
|
|
timestamp=timestamp,
|
|
date_ymd=date_ymd,
|
|
build_number=run_number,
|
|
)
|
|
|
|
|
|
def write_release_metadata(metadata: ReleaseMetadata) -> None:
|
|
write_github_output(
|
|
{
|
|
"version": metadata.version,
|
|
"channel": metadata.channel,
|
|
"source_ref": metadata.source_ref,
|
|
"sha_short": metadata.sha_short,
|
|
"timestamp": metadata.timestamp,
|
|
"date": metadata.date_ymd,
|
|
"build_number": metadata.build_number,
|
|
}
|
|
)
|
|
|
|
|
|
def build_release_summary(
|
|
*,
|
|
title: str,
|
|
channel: str,
|
|
version: str,
|
|
build_number: str,
|
|
sha: str,
|
|
sha_short: str,
|
|
timestamp: str,
|
|
source_ref: str,
|
|
build_result: str,
|
|
image_tags: str,
|
|
image_digest: str,
|
|
registry: str,
|
|
image_name: str,
|
|
date_ymd: str,
|
|
) -> str:
|
|
lines: list[str] = [
|
|
f"## {title}",
|
|
"",
|
|
f"channel: {channel}",
|
|
f"version: v{version}",
|
|
f"build: {build_number}",
|
|
f"sha: {sha} (short: {sha_short})",
|
|
f"time: {timestamp}",
|
|
f"source_ref: {source_ref}",
|
|
"",
|
|
f"build result: {build_result}",
|
|
"",
|
|
]
|
|
|
|
if build_result == "success":
|
|
lines.extend(
|
|
[
|
|
"tags:",
|
|
"```",
|
|
image_tags,
|
|
"```",
|
|
f"digest: `{image_digest}`",
|
|
"",
|
|
]
|
|
)
|
|
|
|
if channel == "nightly":
|
|
lines.extend(
|
|
[
|
|
"pull:",
|
|
"```bash",
|
|
f"docker pull {registry}/{image_name}:nightly",
|
|
f"docker pull {registry}/{image_name}:nightly-{date_ymd}",
|
|
f"docker pull {registry}/{image_name}:sha-{sha_short}",
|
|
"```",
|
|
]
|
|
)
|
|
else:
|
|
lines.extend(
|
|
[
|
|
"pull:",
|
|
"```bash",
|
|
f"docker pull {registry}/{image_name}:stable",
|
|
f"docker pull {registry}/{image_name}:latest",
|
|
f"docker pull {registry}/{image_name}:v{version}",
|
|
"```",
|
|
]
|
|
)
|
|
|
|
return "\n".join(lines) + "\n"
|
|
|
|
|
|
def write_release_summary(summary: str, *, build_result: str) -> None:
|
|
write_github_summary(summary)
|
|
if build_result == "failure":
|
|
raise SystemExit(1)
|