[Packaging] | Add a new ways (preview) to install azure-cli on macOS#32880
[Packaging] | Add a new ways (preview) to install azure-cli on macOS#32880naga-nandyala wants to merge 13 commits intoAzure:devfrom
Conversation
️✔️AzureCLI-FullTest
|
️✔️AzureCLI-BreakingChangeTest
|
|
Thank you for your contribution! We will review the pull request and get back to you soon. |
|
The git hooks are available for azure-cli and azure-cli-extensions repos. They could help you run required checks before creating the PR. Please sync the latest code with latest dev branch (for azure-cli) or main branch (for azure-cli-extensions). pip install azdev --upgrade
azdev setup -c <your azure-cli repo path> -r <your azure-cli-extensions repo path>
|
There was a problem hiding this comment.
Pull request overview
Adds a new macOS distribution path for Azure CLI that packages the CLI as a Python-site-packages tarball (no bundled Python), supports both Homebrew Cask and offline installs, and wires up an Azure Pipelines flow to build → sign/notarize → test.
Changes:
- Introduces macOS packaging assets: tarball builder, cask generator, launcher script, and offline README template.
- Adds Azure Pipelines templates/jobs for macOS build, ESRP signing/notarization, cask generation/testing, and publishing.
- Updates pipeline variables and repo
.gitignoreto support the new workflow.
Reviewed changes
Copilot reviewed 12 out of 13 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| scripts/release/macos/templates/azure-cli.rb.in | Homebrew cask template for installing the prebuilt tarball. |
| scripts/release/macos/templates/az_launcher.sh.in | az launcher that selects Homebrew Python or AZ_PYTHON for offline installs. |
| scripts/release/macos/templates/README.txt.in | Offline/Homebrew tarball README included in the distribution. |
| scripts/release/macos/cask_generate.py | Renders the cask template by injecting version + SHA256s + repo. |
| scripts/release/macos/build_binary_tar_gz.py | Builds the “no bundled Python” macOS tarball layout from source + pinned deps. |
| azure-pipelines.yml | Hooks new macOS cask build/sign/test phases into the main pipeline. |
| .gitignore | Adds .venv/ to ignored paths. |
| .azure-pipelines/templates/variables.yml | Adds macOS image/pool variables for new pipeline templates. |
| .azure-pipelines/templates/macos/macos-build-jobs.yml | Builds unsigned macOS tarballs for ARM64 + Intel via matrix. |
| .azure-pipelines/templates/macos/macos-sign-notarize-jobs.yml | ESRP signing + notarization pipeline for macOS artifacts. |
| .azure-pipelines/templates/macos/macos-cask-generation-and-tests.yml | Generates cask + tests temp tap install + offline tarball install. |
| .azure-pipelines/templates/macos/macos-publish-jobs.yml | Publishes GitHub release and updates the Homebrew tap cask. |
| .azure-pipelines/macos-standalone-release.yml | Standalone end-to-end macOS release pipeline wiring templates together. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 12 out of 13 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| strategy :github_latest | ||
| end | ||
|
|
||
| depends_on formula: "python@3.13" |
There was a problem hiding this comment.
The cask hardcodes depends_on formula: "python@3.13", but the pipeline introduces a macos_cask_python_version variable/parameter. To avoid the template drifting from the pipeline configuration, consider templating the Python version here (and in the generator) so a single version setting drives both.
| depends_on formula: "python@3.13" | |
| depends_on formula: "python@{{ macos_cask_python_version }}" |
| # Python version we're building for (must match Homebrew python@3.13) | ||
| PYTHON_MAJOR_MINOR = "3.13" | ||
| PYTHON_BIN = "python3" |
There was a problem hiding this comment.
PYTHON_MAJOR_MINOR is hardcoded to 3.13, but the pipeline passes a Python version parameter (PythonVersion) when installing Homebrew Python. If/when the pipeline version changes, this script will still look for 3.13 and fail. Consider accepting the target Python version as a CLI argument/env var and wiring it through from the pipeline.
| ((SIGNED_COUNT++)) | ||
| [ -z "$FIRST_SIGNED" ] && FIRST_SIGNED="$file" | ||
|
|
||
| # 2. Strict verification (only for signed files) | ||
| if codesign --verify --deep --strict "$file" 2>/dev/null; then | ||
| ((STRICT_PASS++)) | ||
| else | ||
| ((STRICT_FAIL++)) | ||
| STRICT_FAILED_FILES+=("$filename") | ||
| fi | ||
|
|
||
| # 3. Developer ID check (only for signed files) | ||
| if codesign -dvv "$file" 2>&1 | grep -q "Developer ID"; then | ||
| ((DEVID_PASS++)) | ||
| else | ||
| ((DEVID_FAIL++)) | ||
| DEVID_FAILED_FILES+=("$filename") | ||
| fi | ||
| else | ||
| ((UNSIGNED_COUNT++)) |
There was a problem hiding this comment.
The verification bash script runs with set -e, but uses post-increment arithmetic like ((SIGNED_COUNT++)). In bash, ((var++)) returns exit status 1 when the expression evaluates to 0 (e.g., on the first increment), which can cause the step to exit early. Use a form that always returns success under set -e (e.g., ((++SIGNED_COUNT)) / SIGNED_COUNT=$((SIGNED_COUNT+1))) for all the counters in this loop.
| ((SIGNED_COUNT++)) | |
| [ -z "$FIRST_SIGNED" ] && FIRST_SIGNED="$file" | |
| # 2. Strict verification (only for signed files) | |
| if codesign --verify --deep --strict "$file" 2>/dev/null; then | |
| ((STRICT_PASS++)) | |
| else | |
| ((STRICT_FAIL++)) | |
| STRICT_FAILED_FILES+=("$filename") | |
| fi | |
| # 3. Developer ID check (only for signed files) | |
| if codesign -dvv "$file" 2>&1 | grep -q "Developer ID"; then | |
| ((DEVID_PASS++)) | |
| else | |
| ((DEVID_FAIL++)) | |
| DEVID_FAILED_FILES+=("$filename") | |
| fi | |
| else | |
| ((UNSIGNED_COUNT++)) | |
| ((++SIGNED_COUNT)) | |
| [ -z "$FIRST_SIGNED" ] && FIRST_SIGNED="$file" | |
| # 2. Strict verification (only for signed files) | |
| if codesign --verify --deep --strict "$file" 2>/dev/null; then | |
| ((++STRICT_PASS)) | |
| else | |
| ((++STRICT_FAIL)) | |
| STRICT_FAILED_FILES+=("$filename") | |
| fi | |
| # 3. Developer ID check (only for signed files) | |
| if codesign -dvv "$file" 2>&1 | grep -q "Developer ID"; then | |
| ((++DEVID_PASS)) | |
| else | |
| ((++DEVID_FAIL)) | |
| DEVID_FAILED_FILES+=("$filename") | |
| fi | |
| else | |
| ((++UNSIGNED_COUNT)) |
| - name: GitHubRepo | ||
| displayName: 'GitHub Repository (owner/repo)' | ||
| type: string | ||
| default: 'Azure/homebrew-azure-cli' |
There was a problem hiding this comment.
GitHubRepo is used for creating the GitHub release and for generating the cask download URL, but the default is set to the Homebrew tap repo (Azure/homebrew-azure-cli). That will publish the release assets to the wrong repository by default; the default should point to the Azure CLI repo (e.g., Azure/azure-cli) while HomebrewTapRepo remains Azure/homebrew-azure-cli.
| default: 'Azure/homebrew-azure-cli' | |
| default: 'Azure/azure-cli' |
There was a problem hiding this comment.
This is a standalone pipeline used for testing.. it will not be part of live code..
…or PYTHON_MAJOR_MINOR, fix arithmetic exit code
d2d8493 to
8906268
Compare
Related command
Description
Introducing new ways to install azure-cli on macOS (arm64 & x86_64) via:
Testing Guide
History Notes
[Component Name 1] BREAKING CHANGE:
az command a: Make some customer-facing breaking change[Component Name 2]
az command b: Add some customer-facing featureThis checklist is used to make sure that common guidelines for a pull request are followed.
The PR title and description has followed the guideline in Submitting Pull Requests.
I adhere to the Command Guidelines.
I adhere to the Error Handling Guidelines.