forked from pantsbuild/pants
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeploy_to_s3.py
executable file
·117 lines (94 loc) · 3.75 KB
/
deploy_to_s3.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
#!/usr/bin/env python3
# Copyright 2019 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).
from __future__ import annotations
import argparse
import logging
import os
import shutil
import subprocess
from common import die
logger = logging.getLogger(__name__)
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument(
"--scope",
help=(
"The subdirectory of dist/deploy to deploy to S3; by default, everything under that "
"directory."
),
)
options = parser.parse_args()
perform_deploy(scope=options.scope)
def _run(args, env=None) -> None:
try:
subprocess.run(
args=args,
env=env,
capture_output=True,
check=True,
)
except subprocess.CalledProcessError as ex:
logger.error(f"Process `{' '.join(args)}` failed with exit code {ex.returncode}.")
logger.error(f"stdout: {ex.stdout}")
logger.error(f"stderr: {ex.stderr}")
raise
def perform_deploy(*, aws_cli_symlink_path: str | None = None, scope: str | None = None) -> None:
"""Deploy the contents of dist/deploy to S3.
The `aws` CLI app will be installed if needed and will be symlinked into the system standard
$PATH unless `aws_cli_symlink_path` is provided, in which case it will be symlinked into that
directory.
The full contents of the local dist/deploy directory will be synced to The S3 bucket mounted at
https://binaries.pantsbuild.org unless a scope is provided, in which case just that subdirectory
of dist/deploy will be synced to the corresponding "path" under https://binaries.pantsbuild.org.
"""
if shutil.which("aws") is None:
install_aws_cli(symlink_path=aws_cli_symlink_path)
validate_authentication()
deploy(scope=scope)
def install_aws_cli(symlink_path: str | None = None) -> None:
env = {"AWS_CLI_SYMLINK_PATH": symlink_path} if symlink_path else {}
_run(["./build-support/bin/install_aws_cli.sh"], env={**os.environ, **env})
def validate_authentication() -> None:
access_key_id = "AWS_ACCESS_KEY_ID"
if access_key_id not in os.environ:
die(f"Must set {access_key_id}.")
secret_access_key = "AWS_SECRET_ACCESS_KEY"
if secret_access_key not in os.environ:
die(f"Must set {secret_access_key}.")
def deploy(scope: str | None = None) -> None:
# NB: we use the sync command to avoid transferring files that have not changed. See
# https://github.com/pantsbuild/pants/issues/7258.
local_path = "dist/deploy"
s3_dest = "s3://binaries.pantsbuild.org"
s3_dest_region = "us-east-1"
if scope:
local_path = f"{local_path}/{scope}"
s3_dest = f"{s3_dest}/{scope}"
_run(
[
"aws",
"--region",
s3_dest_region,
"s3",
"sync",
# This instructs the sync command to ignore timestamps, which we must do to allow
# distinct shards—which may finish building their wheels at different times—to not
# overwrite otherwise-identical wheels.
"--size-only",
# Turn off the dynamic progress display, which clutters the CI output.
"--no-progress",
"--acl",
"public-read",
str(local_path),
s3_dest,
]
)
# Create/update the index file in S3. After running on both the MacOS and Linux shards
# the index file will contain the wheels for both.
wheels_dir = "dist/deploy/wheels/pantsbuild.pants"
if os.path.isdir(wheels_dir):
for sha in os.listdir(wheels_dir):
_run(["./build-support/bin/create_s3_index_file.sh", sha])
if __name__ == "__main__":
main()