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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
# -------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for
# license information.
# --------------------------------------------------------------------------
import argparse
import os
import shlex
import sys
try:
from dotenv import load_dotenv
load_dotenv()
except:
pass
import subprocess
# This file contains a script for managing test recordings in the azure-sdk-assets repository with Docker.
#
# INSTRUCTIONS FOR USE:
#
# - Set GIT_TOKEN, GIT_COMMIT_OWNER, and GIT_COMMIT_EMAIL environment variables to authenticate git requests.
# These can be set in-process or added to a .env file at the root of or directory above your local copy of the
# azure-sdk-for-python repository.
# - Set your working directory to be inside your local copy of the azure-sdk-for-python repository.
# - Run the following command:
#
# `python {path to script}/manage_recordings.py {verb} {relative path to package's assets.json file}`
#
# For example, with the root of the azure-sdk-for-python repo as the working directory, you can push modified
# azure-keyvault-keys recordings to the assets repo with:
#
# `python scripts/manage_recordings.py push sdk/keyvault/azure-keyvault-keys/assets.json`
#
# - In addition to "push", you can also use the "restore" or "reset" verbs in the same command format.
#
# * push: pushes recording updates to a new assets repo tag and updates the tag pointer in `assets.json`.
# * restore: fetches recordings from the assets repo, based on the tag pointer in `assets.json`.
# * reset: discards any pending changes to recordings, based on the tag pointer in `assets.json`.
#
# For more information about how recording asset synchronization, please refer to
# https://github.com/Azure/azure-sdk-tools/blob/main/tools/test-proxy/documentation/asset-sync/README.md.
# Load environment variables from user's .env file
CONTAINER_NAME = "azsdkengsys.azurecr.io/engsys/test-proxy"
GIT_TOKEN = os.getenv("GIT_TOKEN", "")
GIT_OWNER = os.getenv("GIT_COMMIT_OWNER", "")
GIT_EMAIL = os.getenv("GIT_COMMIT_EMAIL", "")
# ----- HELPERS ----- #
discovered_roots = []
def ascend_to_root(start_dir_or_file: str) -> str:
"""
Given a path, ascend until encountering a folder with a `.git` folder present within it. Return that directory.
:param str start_dir_or_file: The starting directory or file. Either is acceptable.
"""
if os.path.isfile(start_dir_or_file):
current_dir = os.path.dirname(start_dir_or_file)
else:
current_dir = start_dir_or_file
while current_dir is not None and not (os.path.dirname(current_dir) == current_dir):
possible_root = os.path.join(current_dir, ".git")
# we need the git check to prevent ascending out of the repo
if os.path.exists(possible_root):
if current_dir not in discovered_roots:
discovered_roots.append(current_dir)
return current_dir
else:
current_dir = os.path.dirname(current_dir)
raise Exception(f'Requested target "{start_dir_or_file}" does not exist within a git repo.')
def delete_container() -> None:
"""Delete container if it remained"""
proc = subprocess.Popen(
shlex.split(f"docker rm -f {CONTAINER_NAME}"),
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.DEVNULL,
)
output, stderr = proc.communicate(timeout=10)
return None
def get_image_tag(repo_root: str) -> str:
"""Gets the test proxy Docker image tag from the target_version.txt file in /eng/common/testproxy"""
version_file_location = os.path.relpath("eng/common/testproxy/target_version.txt")
version_file_location_from_root = os.path.abspath(os.path.join(repo_root, version_file_location))
with open(version_file_location_from_root, "r") as f:
image_tag = f.read().strip()
return image_tag
# ----- CORE LOGIC ----- #
if not (GIT_TOKEN and GIT_OWNER and GIT_EMAIL):
raise ValueError(
"GIT_TOKEN, GIT_COMMIT_OWNER, and GIT_COMMIT_EMAIL environment variables must be set, "
"either in-process or in a .env file"
)
# Prepare command arguments
parser = argparse.ArgumentParser(description="Script for managing recording assets with Docker.")
parser.add_argument("verb", help='The action verb for managing recordings: "restore", "push", or "reset".')
parser.add_argument(
"path",
default="assets.json",
help='The *relative* path to your package\'s `assets.json` file. Default is "assets.json".',
)
args = parser.parse_args()
if args.verb and args.path:
current_directory = os.getcwd()
repo_root = ascend_to_root(current_directory)
image_tag = get_image_tag(repo_root)
root_path = os.path.abspath(repo_root)
cwd_relpath = os.path.relpath(current_directory, root_path)
assets_path = os.path.join(cwd_relpath, args.path).replace("\\", "/")
delete_container() # Delete any lingering container so a new one can be created with necessary environment variables
subprocess.run(
shlex.split(
f'docker run --rm -v "{repo_root}:/srv/testproxy" '
f'-e "GIT_TOKEN={GIT_TOKEN}" -e "GIT_COMMIT_OWNER={GIT_OWNER}" -e "GIT_COMMIT_EMAIL={GIT_EMAIL}" '
f"{CONTAINER_NAME}:{image_tag} test-proxy {args.verb.lower()} -a {assets_path}"
),
stdout=sys.stdout,
stderr=sys.stderr,
)
|