123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103 |
- # Copyright Materialize, Inc. and contributors. All rights reserved.
- #
- # Use of this software is governed by the Business Source License
- # included in the LICENSE file at the root of this repository.
- #
- # As of the Change Date specified in that file, in accordance with
- # the Business Source License, use of this software will be governed
- # by the Apache License, Version 2.0.
- # This file contains a class that can be used to upload a tarball to the materialize-binaries S3 bucket.
- import os
- import tarfile
- import tempfile
- import time
- from pathlib import Path
- import boto3
- import humanize
- from materialize import git
- from materialize.mz_version import TypedVersionBase
- BINARIES_BUCKET = "materialize-binaries"
- class TarballUploader:
- def __init__(self, package_name: str, version: TypedVersionBase):
- self.package_name = package_name
- self.version = version
- self.version_str = f"v{version.str_without_prefix()}"
- def _create_tardir(self, name: str) -> tarfile.TarInfo:
- """Takes a dir path and creates a TarInfo. Sets the
- modification time, mode, and type of the dir."""
- d = tarfile.TarInfo(name)
- d.mtime = int(time.time())
- d.mode = 0o40755
- d.type = tarfile.DIRTYPE
- return d
- def _sanitize_tarinfo(self, tarinfo: tarfile.TarInfo) -> tarfile.TarInfo:
- tarinfo.uid = tarinfo.gid = 0
- tarinfo.uname = tarinfo.gname = "root"
- return tarinfo
- def _upload_redirect(self, key: str, to: str) -> None:
- with tempfile.NamedTemporaryFile() as empty:
- boto3.client("s3").upload_fileobj(
- Fileobj=empty,
- Bucket=BINARIES_BUCKET,
- Key=key,
- ExtraArgs={"WebsiteRedirectLocation": to},
- )
- def _upload_tarball(self, tarball: Path, platform: str) -> None:
- """Uploads the tarball (.tar) to the S3 bucket."""
- s3_object = f"{self.package_name}-{self.version_str}-{platform}.tar.gz"
- boto3.client("s3").upload_file(
- Filename=str(tarball),
- Bucket=BINARIES_BUCKET,
- Key=s3_object,
- )
- if "aarch64" in platform:
- self._upload_redirect(
- f"{self.package_name}-{self.version_str}-{platform.replace('aarch64', 'arm64')}.tar.gz",
- f"/{s3_object}",
- )
- def _upload_latest_redirect(self, platform: str) -> None:
- """Uploads an S3 object for the latest version redirect."""
- self._upload_redirect(
- f"{self.package_name}-latest-{platform}.tar.gz",
- f"/{self.package_name}-{self.version_str}-{platform}.tar.gz",
- )
- if "aarch64" in platform:
- self._upload_latest_redirect(platform.replace("aarch64", "arm64"))
- def deploy_tarball(self, platform: str, binary_path: Path) -> None:
- """Creates and uploads a tarball containing the binary."""
- tar_path = Path(f"{self.package_name}-{platform}.tar.gz")
- with tarfile.open(str(tar_path), "x:gz") as f:
- f.addfile(self._create_tardir("mz/bin"))
- f.add(
- str(binary_path),
- arcname=f"mz/bin/{binary_path.name}",
- filter=self._sanitize_tarinfo,
- )
- size = humanize.naturalsize(os.lstat(tar_path).st_size)
- print(f"Tarball size: {size}")
- self._upload_tarball(tar_path, platform)
- self._upload_latest_redirect(platform)
- def is_latest_version(version: TypedVersionBase) -> bool:
- latest_version = max(
- t
- for t in git.get_version_tags(version_type=type(version))
- if t.prerelease is None
- )
- return version == latest_version
|