From 0643a90f0e21cc18b3325fba764f8f282c23522d Mon Sep 17 00:00:00 2001 From: Naga Nandyala Date: Tue, 13 Oct 2026 11:10:52 +1100 Subject: [PATCH 1/2] {Packaging} Remove retired Homebrew Formula pipeline --- azure-pipelines.yml | 150 ------------- doc/scrum-master's-playbook.md | 2 +- .../homebrew/docker/formula_generate.py | 204 ------------------ .../homebrew/docker/formula_template.txt | 63 ------ .../release/homebrew/docker/requirements.txt | 8 - scripts/release/homebrew/docker/run.sh | 23 -- scripts/release/homebrew/pipeline.sh | 27 --- .../release/homebrew/test_homebrew_package.py | 34 --- .../release/homebrew/test_homebrew_package.sh | 41 ---- scripts/release/homebrew/upload.sh | 21 -- 10 files changed, 1 insertion(+), 572 deletions(-) delete mode 100644 scripts/release/homebrew/docker/formula_generate.py delete mode 100644 scripts/release/homebrew/docker/formula_template.txt delete mode 100644 scripts/release/homebrew/docker/requirements.txt delete mode 100755 scripts/release/homebrew/docker/run.sh delete mode 100644 scripts/release/homebrew/pipeline.sh delete mode 100644 scripts/release/homebrew/test_homebrew_package.py delete mode 100755 scripts/release/homebrew/test_homebrew_package.sh delete mode 100644 scripts/release/homebrew/upload.sh diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 29c279685f2..280c045d7eb 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -625,156 +625,6 @@ jobs: - bash: ./scripts/ci/test_extensions.sh displayName: 'Load extensions' -- job: BuildHomebrewFormula - displayName: Build Homebrew Formula - - dependsOn: BuildPythonWheel - condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'Manual', 'Schedule')) - pool: - name: ${{ variables.ubuntu_pool }} - steps: - - task: DownloadPipelineArtifact@1 - displayName: 'Download Metadata' - inputs: - TargetPath: '$(Build.ArtifactStagingDirectory)/metadata' - artifactName: metadata - - - bash: | - #!/bin/bash - - root=$(cd $(dirname $0); pwd) - - set -evx - - CLI_VERSION=`cat $BUILD_ARTIFACTSTAGINGDIRECTORY/metadata/version` - HOMEBREW_UPSTREAM_URL=`curl -Ls -o /dev/null -w %{url_effective} https://api.github.com/repos/Azure/azure-cli/tarball/$BUILD_SOURCEVERSION` - - docker_files=$(cd $BUILD_SOURCESDIRECTORY/scripts/release/homebrew/docker; pwd) - src_files=$(cd $BUILD_SOURCESDIRECTORY/src; pwd) - - echo "Generating formula in docker container ... " - docker run -v $docker_files:/mnt/scripts \ - -v $src_files:/mnt/src \ - -e CLI_VERSION=$CLI_VERSION \ - -e HOMEBREW_UPSTREAM_URL=$HOMEBREW_UPSTREAM_URL \ - --name azurecli \ - mcr.microsoft.com/azurelinux/base/python:3.12 \ - /mnt/scripts/run.sh - - # clean up - rm -rf $BUILD_ARTIFACTSTAGINGDIRECTORY/metadata - - docker cp azurecli:azure-cli.rb $BUILD_ARTIFACTSTAGINGDIRECTORY/azure-cli.rb - docker rm --force azurecli - displayName: 'Build homebrew formula' - - - task: AzureArtifacts.manifest-generator-task.manifest-generator-task.ManifestGeneratorTask@0 - displayName: 'SBOM' - condition: startsWith(variables['Build.SourceBranch'], 'refs/heads/release') - inputs: - BuildDropPath: $(Build.ArtifactStagingDirectory) - - - task: PublishPipelineArtifact@0 - displayName: 'Publish Artifact: homebrew' - inputs: - TargetPath: $(Build.ArtifactStagingDirectory) - ArtifactName: homebrew - -- job: TestHomebrewFormula - displayName: Test Homebrew Formula - - dependsOn: BuildHomebrewFormula - condition: succeeded() - pool: - vmImage: ${{ variables.macos_pool }} - steps: - - task: DownloadPipelineArtifact@1 - displayName: 'Download Metadata' - inputs: - TargetPath: '$(Build.ArtifactStagingDirectory)/metadata' - artifactName: metadata - - - - task: DownloadPipelineArtifact@1 - displayName: 'Download Homebrew' - inputs: - TargetPath: '$(Build.ArtifactStagingDirectory)/homebrew' - artifactName: homebrew - - - - bash: | - set -ev - # Force relink python@3.xx in Homebrew to resolve the conflict with pre-installed python 3.xx on macOS-12 image - # See: https://github.com/Azure/azure-cli/issues/29054 - python_version=3.14 - brew unlink python@$python_version && brew link --overwrite python@$python_version || true - - echo == Remove pre-installed azure-cli == - if brew list --versions azure-cli >/dev/null 2>&1; then - brew uninstall azure-cli - else - echo "azure-cli is not pre-installed" - fi - - echo == Install azure-cli.rb formula == - # Need to create a dummy homebrew tap to install the formula - git config --global user.email "you@example.com" - git config --global user.name "Your Name" - brew tap-new dev/azure-cli - cp $SYSTEM_ARTIFACTSDIRECTORY/homebrew/azure-cli.rb $(brew --repository)/Library/Taps/dev/homebrew-azure-cli/Formula/ - # `no_autobump!` is carried over from the upstream homebrew-core formula but is only - # allowed in official Homebrew taps. Remove it so the formula can be installed from - # this local dev tap. It must remain in the released formula, so we only strip it here. - sed -i '' '/no_autobump!/d' $(brew --repository)/Library/Taps/dev/homebrew-azure-cli/Formula/azure-cli.rb - # TODO(packaging): remove once the macOS CI agent image's Homebrew provides formula_opt_prefix. - # The upstream homebrew-core formula calls `formula_opt_prefix("openssl@3")`, a newer - # Homebrew DSL helper not available on the older Homebrew on the macOS CI agent image - # (NoMethodError). Rewrite it to the backward-compatible `Formula["openssl@3"].opt_prefix` - # form for the local test install only; the generated/submitted formula stays upstream-faithful. - sed -E -i '' 's/formula_opt_prefix\(?[[:space:]]*"([^"]+)"[[:space:]]*\)?/Formula["\1"].opt_prefix/g' $(brew --repository)/Library/Taps/dev/homebrew-azure-cli/Formula/azure-cli.rb - - # Homebrew 6.0.0+ requires non-official taps to be explicitly trusted before it will - # load their Ruby code (see https://docs.brew.sh/Tap-Trust). Trust this local dev tap - # that we just created so the generated formula can be installed in CI. - brew trust dev/azure-cli - brew install --build-from-source dev/homebrew-azure-cli/azure-cli - - echo == Az Version == - az --version - - echo == Run Self-Test == - az self-test - - displayName: 'Bash Script' - -- job: TestHomebrewPackage - displayName: Test Homebrew Package - timeoutInMinutes: 180 - dependsOn: BuildHomebrewFormula - # condition: and(succeeded(), in(variables['Build.Reason'], 'IndividualCI', 'BatchedCI', 'Manual', 'Schedule')) - condition: false - pool: - vmImage: ${{ variables.macos_pool }} - steps: - - task: DownloadPipelineArtifact@1 - displayName: 'Download Metadata' - inputs: - TargetPath: '$(Build.ArtifactStagingDirectory)/metadata' - artifactName: metadata - - - - task: DownloadPipelineArtifact@1 - displayName: 'Download Build Artifacts' - inputs: - TargetPath: '$(Build.ArtifactStagingDirectory)/homebrew' - artifactName: homebrew - - - - bash: ./scripts/release/homebrew/test_homebrew_package.sh - - - displayName: 'Test Homebrew Package' - # ============================================================================ # HOMEBREW CASK JOBS (Pre-built, signed, notarized binaries) # Phase 1 runs in all projects; Phases 2-3 require the release project diff --git a/doc/scrum-master's-playbook.md b/doc/scrum-master's-playbook.md index 115f246a3db..bca2bcb92d9 100644 --- a/doc/scrum-master's-playbook.md +++ b/doc/scrum-master's-playbook.md @@ -101,7 +101,7 @@ Review and merge (do not squash) the above PR: ![](https://raw.githubusercontent.com/Azure/azure-cli/refs/heads/dev/doc/assets/phase2-4.png) -As part of "Publish to Homebrew", a PR gets created in [homebrew-core](https://github.com/Homebrew/homebrew-core). Wait for that PR to get approved and merged by community and resume this task to completion: +As part of "Publish CASK(Homebrew)", a PR gets created in [homebrew-cask](https://github.com/Homebrew/homebrew-cask). Wait for that PR to get approved and merged by the community and resume this task to completion: ![](https://raw.githubusercontent.com/Azure/azure-cli/refs/heads/dev/doc/assets/phase2-7.png) diff --git a/scripts/release/homebrew/docker/formula_generate.py b/scripts/release/homebrew/docker/formula_generate.py deleted file mode 100644 index b888921abf5..00000000000 --- a/scripts/release/homebrew/docker/formula_generate.py +++ /dev/null @@ -1,204 +0,0 @@ -# -------------------------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# -------------------------------------------------------------------------------------------- - -import os -import sys -import re -from typing import List, Tuple - -import requests -import jinja2 -from poet.poet import make_graph, RESOURCE_TEMPLATE, research_package -from collections import OrderedDict -import bisect -import argparse - -TEMPLATE_FILE_NAME = 'formula_template.txt' -CLI_VERSION = os.environ['CLI_VERSION'] -HOMEBREW_UPSTREAM_URL = os.environ['HOMEBREW_UPSTREAM_URL'] -HOMEBREW_FORMULAR_LATEST = "https://raw.githubusercontent.com/Homebrew/homebrew-core/master/Formula/a/azure-cli.rb" -PYTHON_VERSION = '3.14' - - -def main(): - print('Generate formula for Azure CLI homebrew release.') - - parser = argparse.ArgumentParser(prog='formula_generator.py') - parser.set_defaults(func=generate_formula) - parser.add_argument('-b', dest='build_method', choices=['update_existing', 'use_template'], - help='The build method, default is update_existing, the other option is use_template.') - args = parser.parse_args() - args.func(**vars(args)) - - -def generate_formula(build_method: str, **_): - content = '' - if build_method is None or build_method == 'update_existing': - content = update_formula() - elif build_method == 'use_template': - content = generate_formula_with_template() - with open('azure-cli.rb', mode='w') as fq: - fq.write(content) - - -def generate_formula_with_template() -> str: - """Generate a brew formula by using a template""" - template_path = os.path.join(os.path.dirname(__file__), TEMPLATE_FILE_NAME) - with open(template_path, mode='r') as fq: - template_content = fq.read() - - template = jinja2.Template(template_content) - content = template.render( - cli_version=CLI_VERSION, - upstream_url=HOMEBREW_UPSTREAM_URL, - upstream_sha=compute_sha256(HOMEBREW_UPSTREAM_URL), - resources=collect_resources(), - bottle_hash=last_bottle_hash() - ) - if not content.endswith('\n'): - content += '\n' - return content - - -def compute_sha256(resource_url: str) -> str: - import hashlib - sha256 = hashlib.sha256() - resp = requests.get(resource_url) - resp.raise_for_status() - sha256.update(resp.content) - - return sha256.hexdigest() - - -def collect_resources() -> str: - nodes = make_graph('azure-cli') - nodes_render = [] - for node_name in sorted(nodes): - if not resource_filter(node_name): - continue - - nodes_render.append(RESOURCE_TEMPLATE.render(resource=nodes[node_name])) - return '\n\n'.join(nodes_render) - - -def collect_resources_dict() -> dict: - nodes = make_graph('azure-cli') - - # Homebrew does not install pip and setuptools after Python 3.12 - # see https://github.com/Azure/azure-cli/pull/29887 - extra_dependencies = ['pip', 'setuptools'] - for dependency in extra_dependencies: - nodes[dependency] = research_package(dependency) - - filtered_nodes = {nodes[node_name]['name']: nodes[node_name] for node_name in sorted(nodes) if - resource_filter(node_name)} - return filtered_nodes - - -def resource_filter(name: str) -> bool: - # TODO remove need for any filters and delete this method. - return not name.startswith('azure-cli') and name not in ('futures', 'jeepney', 'entrypoints') - - -def last_bottle_hash(): - """Fetch the bottle do ... end from the latest brew formula""" - resp = requests.get(HOMEBREW_FORMULAR_LATEST) - resp.raise_for_status() - - lines = resp.text.split('\n') - look_for_end = False - start = 0 - end = 0 - for idx, content in enumerate(lines): - if look_for_end: - if 'end' in content: - end = idx - break - else: - if 'bottle do' in content: - start = idx - look_for_end = True - - return '\n'.join(lines[start: end + 1]) - - -def update_formula() -> str: - """Generate a brew formula by updating the existing one""" - nodes = collect_resources_dict() - - resp = requests.get(HOMEBREW_FORMULAR_LATEST) - resp.raise_for_status() - text = resp.text - - # update python version - text = re.sub('depends_on "python@.*"', f'depends_on "python@{PYTHON_VERSION}"', text, 1) - venv_str = f'venv = virtualenv_create(libexec, "python{PYTHON_VERSION}", system_site_packages: false)' - text = re.sub(r'venv = virtualenv_create.*', venv_str, text, 1) - - # update url and sha256 of azure-cli - text = re.sub('url ".*"', 'url "{}"'.format(HOMEBREW_UPSTREAM_URL), text, 1) - upstream_sha = compute_sha256(HOMEBREW_UPSTREAM_URL) - text = re.sub('sha256 ".*"', 'sha256 "{}"'.format(upstream_sha), text, 1) - text = re.sub('.*revision.*\n', '', text, 1) # remove revision for previous version if exists - pack = None - packs_to_remove = set() - lines = text.split('\n') - node_index_dict = OrderedDict() - line_idx_to_remove = set() - upgrade = False - for idx, line in enumerate(lines): - # In released formula, the url is in the release tag format, such as - # "https://github.com/Azure/azure-cli/archive/azure-cli-2.17.1.tar.gz". - # version is extracted from url. During build, the url is in the format like - # "https://codeload.github.com/Azure/azure-cli/legacy.tar.gz/7e09fd50c9ef02e1ed7d4709c7ab1a71acd3840b". - # We need to add the version explicitly after url. - # We will change the url in our release pipeline and remove version. - if line.startswith(" url"): - lines[idx] = lines[idx] + '\n' + ' version "{}"'.format(CLI_VERSION) - elif line.strip().startswith("resource"): - m = re.search(r'resource "(.*)" do', line) - if m is not None: - pack = m.group(1) - node_index_dict[pack] = idx - elif pack is not None: - if line.startswith(" url"): - # update the url of package - if pack in nodes.keys(): - url_match = re.search(r'url "(.*)"', line) - if url_match is not None and nodes[pack]['url'] != url_match.group(1): - lines[idx] = re.sub('url ".*"', 'url "{}"'.format(nodes[pack]['url']), line, 1) - upgrade = True - else: - packs_to_remove.add(pack) - elif line.startswith(" sha256"): - # update the sha256 of package - if pack in nodes.keys(): - lines[idx] = re.sub('sha256 ".*"', 'sha256 "{}"'.format(nodes[pack]['checksum']), line, 1) - del nodes[pack] - elif line.startswith(" end"): - pack = None - upgrade = False - elif upgrade: # In case of upgrading, remove any patch following url and sha256 but before end - line_idx_to_remove.add(idx) - elif line.strip().startswith('def install'): - if nodes: - # add new dependency packages - for node_name, node in nodes.items(): - # find the right place to insert the new resource per alphabetic order - i = bisect.bisect_left(list(node_index_dict.keys()), node_name) - line_idx = list(node_index_dict.items())[i][1] - resource = RESOURCE_TEMPLATE.render(resource=node) - lines[line_idx] = resource + '\n\n' + lines[line_idx] - lines = [line for idx, line in enumerate(lines) if idx not in line_idx_to_remove] - new_text = "\n".join(lines) - - # remove dependency packages that are no longer needed - for pack in packs_to_remove: - new_text = re.sub(r'resource "{}" do.*?\n end\n\s+'.format(pack), '', new_text, flags=re.DOTALL) - return new_text - - -if __name__ == '__main__': - main() diff --git a/scripts/release/homebrew/docker/formula_template.txt b/scripts/release/homebrew/docker/formula_template.txt deleted file mode 100644 index c8bbff14aeb..00000000000 --- a/scripts/release/homebrew/docker/formula_template.txt +++ /dev/null @@ -1,63 +0,0 @@ -class AzureCli < Formula - include Language::Python::Virtualenv - - desc "Microsoft Azure CLI 2.0" - homepage "https://learn.microsoft.com/cli/azure/overview" - url "{{ upstream_url }}" - version "{{ cli_version }}" - sha256 "{{ upstream_sha }}" - license "MIT" - head "https://github.com/Azure/azure-cli.git" - - livecheck do - url "https://github.com/Azure/azure-cli/releases/latest" - regex(%r{href=.*?/tag/azure-cli[._-]v?(\d+(?:\.\d+)+)["' >]}i) - end - -{{ bottle_hash }} - - depends_on "openssl@1.1" - depends_on "python@3.10" - - uses_from_macos "libffi" - - on_linux do - depends_on "pkg-config" => :build - end - -{{ resources }} - - def install - venv = virtualenv_create(libexec, "python3.10", system_site_packages: false) - venv.pip_install resources - - # Get the CLI components we'll install - components = [ - buildpath/"src/azure-cli", - buildpath/"src/azure-cli-telemetry", - buildpath/"src/azure-cli-core", - ] - - # Install CLI - components.each do |item| - cd item do - venv.pip_install item - end - end - - (bin/"az").write <<~EOS - #!/usr/bin/env bash - AZ_INSTALLER=HOMEBREW #{libexec}/bin/python -Im azure.cli \"$@\" - EOS - - bash_completion.install "az.completion" => "az" - end - - test do - json_text = shell_output("#{bin}/az cloud show --name AzureCloud") - azure_cloud = JSON.parse(json_text) - assert_equal azure_cloud["name"], "AzureCloud" - assert_equal azure_cloud["endpoints"]["management"], "https://management.core.windows.net/" - assert_equal azure_cloud["endpoints"]["resourceManager"], "https://management.azure.com/" - end -end diff --git a/scripts/release/homebrew/docker/requirements.txt b/scripts/release/homebrew/docker/requirements.txt deleted file mode 100644 index 0dd9c04cdc4..00000000000 --- a/scripts/release/homebrew/docker/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -# homebrew-pypi-poet uses pkg_resources, removed in setuptools 82. -# Keep this cap local to formula-generation tooling, with the security floor. -# See https://github.com/Azure/azure-cli/issues/32800 -setuptools>=78.1.1,<82 -homebrew-pypi-poet~=0.10.0 -jinja2~=3.1.6 -requests>=2.20.0 -applicationinsights >=0.11.1,<0.11.8 diff --git a/scripts/release/homebrew/docker/run.sh b/scripts/release/homebrew/docker/run.sh deleted file mode 100755 index b19e7a42bd3..00000000000 --- a/scripts/release/homebrew/docker/run.sh +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env bash - -root=$(cd $(dirname $0); pwd) - -if command -v tdnf &> /dev/null; then - # Azure Linux - tdnf install -y ca-certificates -elif command -v apt-get &> /dev/null; then - # Debian/Ubuntu - apt-get update && apt-get install -y ca-certificates -fi - -pip install wheel -pip install -U pip -pip install -r $root/requirements.txt -find /mnt/src/ -name pyproject.toml -type f | xargs -I {} dirname {} | grep -v azure-cli-testsdk | xargs pip install --no-deps -pip install -r /mnt/src/azure-cli/requirements.py3.Darwin.txt - -pip list - -# default option is update_existing to build from homebrew master branch, -# append '-b use_template' to build from formula_template.txt -python3 $root/formula_generate.py diff --git a/scripts/release/homebrew/pipeline.sh b/scripts/release/homebrew/pipeline.sh deleted file mode 100644 index 2cdbb3f060d..00000000000 --- a/scripts/release/homebrew/pipeline.sh +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash - -root=$(cd $(dirname $0); pwd) - -set -evx - -CLI_VERSION=`cat $SYSTEM_ARTIFACTSDIRECTORY/metadata/version` -HOMEBREW_UPSTREAM_URL=`cat $BUILD_STAGINGDIRECTORY/github/upstream_url` -TAR_NAME=azure-cli-$CLI_VERSION.tar.gz - -docker_files=$(cd $BUILD_SOURCESDIRECTORY/scripts/release/homebrew/docker; pwd) -src_files=$(cd $BUILD_SOURCESDIRECTORY/src; pwd) - -echo "Generating formula in docker container ... " -docker run -v $docker_files:/mnt/scripts \ - -v $src_files:/mnt/src \ - -e CLI_VERSION=$CLI_VERSION \ - -e HOMEBREW_UPSTREAM_URL=$HOMEBREW_UPSTREAM_URL \ - --name azurecli \ - python:3.12-bookworm \ - /mnt/scripts/run.sh - -# clean up -rm -rf $BUILD_STAGINGDIRECTORY/metadata - -docker cp azurecli:azure-cli.rb $BUILD_STAGINGDIRECTORY/azure-cli.rb -docker rm --force azurecli diff --git a/scripts/release/homebrew/test_homebrew_package.py b/scripts/release/homebrew/test_homebrew_package.py deleted file mode 100644 index 67fa7ff3d22..00000000000 --- a/scripts/release/homebrew/test_homebrew_package.py +++ /dev/null @@ -1,34 +0,0 @@ -# -------------------------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# -------------------------------------------------------------------------------------------- - -import os -import sys -import subprocess - -if len(sys.argv) < 2: - print('AZ_BASE or PYTHON_VERSION are not specified') - sys.exit(-1) - -az_base = sys.argv[1] -python_version = sys.argv[2] - -root_dir = '{}/lib/{}/site-packages/azure/cli/command_modules'.format(az_base, python_version) -mod_list = [mod for mod in sorted(os.listdir(root_dir)) if os.path.isdir(os.path.join(root_dir, mod)) and mod != '__pycache__'] - -pytest_base_cmd = 'PYTHONPATH={}/lib/{}/site-packages python -m pytest -v --forked -p no:warnings --log-level=WARN'.format(az_base, python_version) -pytest_parallel_cmd = '{} -n auto'.format(pytest_base_cmd) - -for mod_name in mod_list: - if mod_name in ['botservice', 'network', 'configure', 'monitor', 'cloud']: - exit_code = subprocess.call(['{} --junit-xml ./azure_cli_test_result/{}.xml --pyargs azure.cli.command_modules.{}'.format(pytest_base_cmd, mod_name, mod_name)], shell=True) - else: - exit_code = subprocess.call(['{} --junit-xml ./azure_cli_test_result/{}.xml --pyargs azure.cli.command_modules.{}'.format(pytest_parallel_cmd, mod_name, mod_name)], shell=True) - if exit_code == 5: - print('No tests found for {}'.format(mod_name)) - elif exit_code != 0: - sys.exit(exit_code) - -exit_code = subprocess.call(['{} --junit-xml ./azure_cli_test_result/azure-cli-core.xml --pyargs azure.cli.core'.format(pytest_base_cmd)], shell=True) -sys.exit(exit_code) diff --git a/scripts/release/homebrew/test_homebrew_package.sh b/scripts/release/homebrew/test_homebrew_package.sh deleted file mode 100755 index af99f4e4876..00000000000 --- a/scripts/release/homebrew/test_homebrew_package.sh +++ /dev/null @@ -1,41 +0,0 @@ -#/bin/bash - -set -ev - -CLI_VERSION=`cat $SYSTEM_ARTIFACTSDIRECTORY/metadata/version` - -echo == Remove pre-installed azure-cli == -if brew list --versions azure-cli >/dev/null 2>&1; then - brew uninstall azure-cli -else - echo "azure-cli is not pre-installed" -fi - -echo == Install azure-cli.rb formula == -# TODO(packaging): remove once the macOS CI agent image's Homebrew provides formula_opt_prefix. -# The upstream homebrew-core formula calls `formula_opt_prefix("openssl@3")`, a newer -# Homebrew DSL helper not available on the older Homebrew on the macOS CI agent image -# (NoMethodError). Rewrite it to the backward-compatible `Formula["openssl@3"].opt_prefix` -# form for the local test install only; the generated/submitted formula stays upstream-faithful. -sed -E -i '' 's/formula_opt_prefix\(?[[:space:]]*"([^"]+)"[[:space:]]*\)?/Formula["\1"].opt_prefix/g' $SYSTEM_ARTIFACTSDIRECTORY/homebrew/azure-cli.rb -brew install --build-from-source $SYSTEM_ARTIFACTSDIRECTORY/homebrew/azure-cli.rb - -AZ_BASE=/usr/local/Cellar/azure-cli/$CLI_VERSION/libexec -export PATH=$AZ_BASE/bin:$PATH -export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES -echo $PATH -# `build` is the PEP 517 frontend used by scripts/ci/build.sh. -pip install wheel build -./scripts/ci/build.sh -pip install pytest --prefix $AZ_BASE -pip install pytest-xdist --prefix $AZ_BASE -pip install pytest-forked --prefix $AZ_BASE - -find ./artifacts/build -name "azure_cli_testsdk*" | xargs pip install --prefix $AZ_BASE --upgrade --ignore-installed -find ./artifacts/build -name "azure_cli_fulltest*" | xargs pip install --prefix $AZ_BASE --upgrade --ignore-installed --no-deps - -# workaround for this bug (https://github.com/microsoft/azure-devops-python-api/issues/354) -mkdir -p ~/.vsts/python-sdk/cache - -PYTHON_VERSION=`ls $AZ_BASE/lib/ | head -n 1` -python ./scripts/release/homebrew/test_homebrew_package.py $AZ_BASE $PYTHON_VERSION \ No newline at end of file diff --git a/scripts/release/homebrew/upload.sh b/scripts/release/homebrew/upload.sh deleted file mode 100644 index b14d35135ff..00000000000 --- a/scripts/release/homebrew/upload.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/bash - -set -ev - -# Download the release package generated by the Github when a tag of the release is created to storage account - -: {AZURE_STORAGE_ACCOUNT:?"AZURE_STORAGE_ACCOUNT not set"} -: {AZURE_STORAGE_KEY:?"AZURE_STORAGE_KEY not set"} - -CLI_VERSION=`cat $SYSTEM_ARTIFACTSDIRECTORY/metadata/version` -TAR_NAME=azure-cli-$CLI_VERSION.tar.gz - -mkdir -p $BUILD_STAGINGDIRECTORY/github/ >/dev/null 2>&1 -curl -sL https://github.com/Azure/azure-cli/archive/$TAR_NAME -o $BUILD_STAGINGDIRECTORY/github/$TAR_NAME - -az storage blob upload -c releases -n $TAR_NAME -f $BUILD_STAGINGDIRECTORY/github/$TAR_NAME - -# Make sure the URL is publicly available -HOMEBREW_UPSTREAM_URL=$(az storage blob url -c releases -n $TAR_NAME -otsv) -curl -sfS -I $HOMEBREW_UPSTREAM_URL >/dev/null -echo -n $HOMEBREW_UPSTREAM_URL > $BUILD_STAGINGDIRECTORY/github/upstream_url From 805f4bcf20fa5127809492597dae7524338b7a01 Mon Sep 17 00:00:00 2001 From: Naga Nandyala Date: Tue, 13 Oct 2026 12:08:21 +1100 Subject: [PATCH 2/2] {Packaging} Remove retired Homebrew edge instructions --- README.md | 9 --------- 1 file changed, 9 deletions(-) diff --git a/README.md b/README.md index 6c6c143f90c..0f52a6db267 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,6 @@ You can download the latest builds by following the links below: | Package | Link | |:-----------------:|:-------------------------------------------| | MSI | https://aka.ms/InstallAzureCliWindowsEdge | -| Homebrew Formula | https://aka.ms/InstallAzureCliHomebrewEdge | | Ubuntu Bionic Deb | https://aka.ms/InstallAzureCliBionicEdge | | Ubuntu Focal Deb | https://aka.ms/InstallAzureCliFocalEdge | | Ubuntu Jammy Deb | https://aka.ms/InstallAzureCliJammyEdge | @@ -160,14 +159,6 @@ You can download the latest builds by following the links below: On Windows, you need to uninstall the official version before installing the edge build. (See https://github.com/Azure/azure-cli/issues/25607#issuecomment-1452855212) -You can easily install the latest Homebrew edge build with the following command: - -```bash -# You need to uninstall the stable version with `brew uninstall azure-cli` first -curl --location --silent --output azure-cli.rb https://aka.ms/InstallAzureCliHomebrewEdge -brew install --build-from-source azure-cli.rb -``` - You can install the edge build on Ubuntu Jammy with the following command: ```bash