diff --git a/tools/ci_build/github/apple/package_release_tasks.py b/tools/ci_build/github/apple/package_release_tasks.py new file mode 100755 index 0000000000000..38c3509dc84a7 --- /dev/null +++ b/tools/ci_build/github/apple/package_release_tasks.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 + +# Note: This script is intended to be called from the CocoaPods package release pipeline or a similar context. + +from __future__ import annotations + +import argparse +import os +import shlex +import subprocess +from enum import Enum +from pathlib import Path + + +class Task(Enum): + upload_pod_archive = 1 + update_podspec = 2 + + +def _run(command: list[str], **kwargs): + print(f"Running command: {shlex.join(command)}", flush=True) + kwargs.setdefault("check", True) + return subprocess.run(command, **kwargs) # noqa: PLW1510 # we add 'check' to kwargs if not present + + +def upload_pod_archive(pod_archive_path: Path): + env = os.environ.copy() + env.update( + { + # configure azcopy to use managed identity + "AZCOPY_AUTO_LOGIN_TYPE": "MSI", + "AZCOPY_MSI_CLIENT_ID": "63b63039-6328-442f-954b-5a64d124e5b4", + } + ) + + storage_account_name = "onnxruntimepackages" + storage_account_container_name = "$web" + dest_url = f"https://{storage_account_name}.blob.core.windows.net/{storage_account_container_name}/" + + upload_command = ["azcopy", "cp", str(pod_archive_path), dest_url] + + _run(upload_command, env=env) + + +def update_podspec(pod_archive_path: Path, podspec_path: Path): + storage_url = f"https://download.onnxruntime.ai/{pod_archive_path.name}" + + podspec_content = podspec_path.read_text() + podspec_content = podspec_content.replace("file:///http_source_placeholder", storage_url) + podspec_path.write_text(podspec_content) + + +def _parse_args(): + parser = argparse.ArgumentParser( + description="Helper script to perform release tasks. " + "Mostly useful for the CocoaPods package release pipeline.", + ) + + parser.add_argument( + "--pod-archive-path", + type=Path, + help="Pod archive path.", + ) + + parser.add_argument( + "--podspec-path", + type=Path, + help="Podspec path.", + ) + + parser.add_argument( + "task", + choices=[task.name for task in Task], + help="Specify the task to run.", + ) + + return parser.parse_args() + + +def _validate_args( + args: argparse.Namespace, require_pod_archive_path: bool = False, require_podspec_path: bool = False +): + if require_pod_archive_path: + assert args.pod_archive_path is not None, "--pod-archive-path must be specified." + args.pod_archive_path = args.pod_archive_path.resolve(strict=True) + + if require_podspec_path: + assert args.podspec_path is not None, "--podspec-path must be specified." + args.podspec_path = args.podspec_path.resolve(strict=True) + + +def main(): + args = _parse_args() + + task = Task[args.task] + + if task == Task.update_podspec: + _validate_args(args, require_pod_archive_path=True, require_podspec_path=True) + update_podspec(args.pod_archive_path, args.podspec_path) + + elif task == Task.upload_pod_archive: + _validate_args(args, require_pod_archive_path=True) + upload_pod_archive(args.pod_archive_path) + + +if __name__ == "__main__": + main() diff --git a/tools/ci_build/github/apple/upload_pod_archive_and_update_podspec.sh b/tools/ci_build/github/apple/upload_pod_archive_and_update_podspec.sh deleted file mode 100755 index 058d5ccfd991a..0000000000000 --- a/tools/ci_build/github/apple/upload_pod_archive_and_update_podspec.sh +++ /dev/null @@ -1,44 +0,0 @@ -#!/bin/bash - -# Note: This script is intended to be called from the iOS CocoaPods package release pipeline or a similar context. - -set -x - -IFS='' read -d '' -r USAGE_TEXT < - Example pod archive path glob pattern: "./pod-archive-*.zip" - Quote the pattern to avoid shell expansion. -USAGE - -set -e - -abspath() { - local INPUT_PATH=${1:?"Expected path as the first argument."} - echo "$(cd "$(dirname "${INPUT_PATH}")" && pwd)/$(basename "${INPUT_PATH}")" -} - -POD_ARCHIVE_PATH_PATTERN=${1:?${USAGE_TEXT}} -PODSPEC_PATH=$(abspath "${2:?${USAGE_TEXT}}") - -# expand pod archive path pattern to exactly one path -POD_ARCHIVE_PATHS=() -while IFS='' read -r line; do POD_ARCHIVE_PATHS+=("$line"); done < <( compgen -G "${POD_ARCHIVE_PATH_PATTERN}" ) -if [[ "${#POD_ARCHIVE_PATHS[@]}" -ne "1" ]]; then - echo "Did not find exactly one pod archive file." - exit 1 -fi - -POD_ARCHIVE_PATH=$(abspath "${POD_ARCHIVE_PATHS[0]}") -POD_ARCHIVE_BASENAME=$(basename "${POD_ARCHIVE_PATH}") - -STORAGE_ACCOUNT_NAME="onnxruntimepackages" -STORAGE_ACCOUNT_CONTAINER_NAME="\$web" -STORAGE_URL_PREFIX="https://download.onnxruntime.ai/" - -# upload the pod archive and set the podspec source to the pod archive URL -az storage blob upload \ - --account-name ${STORAGE_ACCOUNT_NAME} --container-name ${STORAGE_ACCOUNT_CONTAINER_NAME} \ - --file "${POD_ARCHIVE_PATH}" --name "${POD_ARCHIVE_BASENAME}" \ - --if-none-match "*" - -sed -i "" -e "s|file:///http_source_placeholder|${STORAGE_URL_PREFIX}${POD_ARCHIVE_BASENAME}|" "${PODSPEC_PATH}" diff --git a/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml b/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml index 32b67a1a35c91..2c9f968380a38 100644 --- a/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml +++ b/tools/ci_build/github/azure-pipelines/templates/stages/mac-ios-packaging-build-stage.yml @@ -142,7 +142,7 @@ stages: done # copy over helper script for use in release pipeline - cp tools/ci_build/github/apple/upload_pod_archive_and_update_podspec.sh "$(Build.ArtifactStagingDirectory)" + cp tools/ci_build/github/apple/package_release_tasks.py "$(Build.ArtifactStagingDirectory)" displayName: "Assemble artifacts" - script: |