Add native macOS and Windows installers for vip-next - #3055
Merged
Merged
Conversation
Contributor
Dependency ReviewThe following issues were found:
License Issues.github/workflows/ci-go.yml
OpenSSF ScorecardScorecard details
Scanned Files
|
mokagio
reviewed
Sep 16, 2026
`abaa9bdb` added a `configure_installer_signing` call inside `sign_and_notarize_installer` to test whether running `match` there worked around `setup_ci` keychain behaviour. It did not: the real cause was the lane fetching the wrong certificate type entirely, so the call only duplicated the one `.buildkite/build-macos-installer.sh` already makes before packaging. --- Generated with the help of Claude Code, https://code.claude.com Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`developer_id_installer` is accepted as match's top-level `type`, but match never maps it through to the certificate generator: `generate_certificate` special-cases `developer_id_application` alone, so `Cert::Runner` runs with `generate_apple_certs: true` and mints an **Apple Distribution** certificate, which match then files under `certs/developer_id_installer/`. Readonly runs install that certificate and report success, and the first sign of trouble is `productsign` failing to find the identity much later. `additional_cert_types` is the supported route and is what the option exists for. Write mode goes with it. Apple restricts creating Developer ID certificates to the Account Holder, so the App Store Connect API key cannot produce this certificate anyway — while `type: 'developer_id'` means a write-mode run could renew the shared Developer ID Application certificate as a side effect. The certificate is provisioned out of band with `fastlane match import`. Verified against live match storage: the lane now installs `Developer ID Application` rather than `Apple Distribution`, then fails cleanly on the genuinely absent installer certificate. --- Generated with the help of Claude Code, https://code.claude.com Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`match` reports "All required keys, certificates and provisioning profiles are installed" for whatever certificate it finds in storage, without checking that it is the type that was asked for. When storage held the wrong certificate the build ran on for another ninety seconds — downloading artefacts, building both packages — before `productsign` failed with an error that pointed at the keychain rather than at match. Checking the identity where it is fetched fails the job in seconds, at the cause. --- Generated with the help of Claude Code, https://code.claude.com Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The previous note said the certificate "must be added through the team's existing certificate provisioning process", which is not a followable instruction and left the impression a write-mode build could produce it. Records the two facts that cost a day: creation is Account Holder only, and `match import` takes `developer_id_installer` as a top-level `--type` while `match` itself does not. --- Generated with the help of Claude Code, https://code.claude.com Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
App Store Connect's API does not model `DEVELOPER_ID_INSTALLER`: `filter[certificateType]` rejects it as an invalid value and names the accepted set, which has `DEVELOPER_ID_APPLICATION` and `DEVELOPER_ID_KEXT` but no installer entry. `match import` looks a certificate up by type to recover its ID, so the recipe committed in the previous change would have failed on that filter — wasting the time of the one person able to run it. `--skip_certificate_matching true` bypasses the lookup. The same gap means no API query can confirm whether the team already holds this certificate, so the check belongs on the Developer website rather than in a script. --- Generated with the help of Claude Code, https://code.claude.com Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Contributor
|
@rinatkhaziev I just realized I didn't sync with you about pushing to the branch straight instead of having a stacked PR. Sorry for the noise. Anyway, after a few issues, the signing process succeeds in CI.
Handing the ball back to you. |
mokagio
self-requested a review
September 18, 2026 15:40
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.





Description
The Go CLI currently ships portable archives, so installing it requires extracting both binaries and configuring PATH manually. This adds macOS PKG and Windows MSI installers through separate native Buildkite jobs, while retaining all existing archives for portable installations and self-updates.
Packaging and installation
vip-nextandgo-search-replaceunder/usr/local/lib/vip-cli/bin, with a matching/etc/paths.dentry. The packages reject conflicting installation paths and downgrades, and include a scoped uninstaller that preserves user configuration and credentials.%ProgramFiles%\Automattic\VIP CLI, with a minimal installation wizard, system PATH management, major upgrades, downgrade refusal, and normal uninstall support. WiX 5.0.2 and its matching UI extension are restored into a temporary build directory; .NET is build tooling only.vip-next updatedirects installer-managed installations to the appropriate package instead of replacing their files. Portable installations retain the existing self-update behavior. Novipalias is introduced, and the Node/npm runtime is unchanged.Signing and release promotion
Binary signing and installer signing run in separate Buildkite jobs. Each installer job depends on its platform's binary job, downloads the signed archives from that exact build/step, verifies their checksums and strict two-file payload, and packages the existing signed bytes. Installer jobs use
soft_failso installer tooling or certificate failures cannot fail a binary release. Binary jobs remain required.macOS binary signing retrieves only the Developer ID Application certificate. The separate installer job retrieves only Developer ID Installer in readonly mode, then signs, notarizes, and staples each PKG. Buildkite #95 confirmed the Installer identity is currently unavailable: the former combined certificate setup failed before binary signing and uploaded zero macOS artifacts. Provisioning that certificate remains necessary to produce PKGs. Windows uses the existing Azure Authenticode setup in both jobs. There is no unsigned fallback.
Installer jobs extract completed packages and compare their contents with the intended inputs before generating checksums. They explicitly upload only after every signature and payload check passes; post-failure automatic installer uploads are disabled. Prerelease promotion requires all five archive/checksum pairs (10 assets) and includes available complete installer/checksum pairs (up to 16 assets). Missing installers do not block binary releases; incomplete pairs, corrupt checksums, unexpected/duplicate/unfinished artifacts, and invalid containers still do. Native signature verification remains in Buildkite.
Both package formats use an ordered numeric version derived from the semantic release version:
major.minor.(patch*1000+stage), with development, alpha, beta, RC, and stable stages. Major/minor are limited to 255, patch to 64, and prerelease sequence to 199. Unsupported installer versions fail only installer jobs; the binary release version range is unchanged. Development MSI builds sharing a numeric version may require uninstalling the previous build first.Changelog Description
Added
Validation
Passed locally:
make test— 56 Go packages reported successful results.make lint.git diff --check.The existing native Go Actions matrix now exercises actual installer install/upgrade/downgrade/PATH/ownership/uninstall behavior on disposable macOS and Windows runners. These tests use distinct fixture payloads, require an explicit CI-only gate, and refuse existing installations. They do not install the CLI on shared Buildkite agents.
CI on the initial commit passed macOS and Windows installer lifecycle tests, Windows signed MSI production, Linux builds, and the Go/Node checks. Buildkite #95's macOS certificate failure motivated the isolation fix above. The documentation formatting failure is also corrected. On the isolation commit
a444a163, all three binary jobs passed in Buildkite #96, and all native Actions jobs and formatting passed. Both installer jobs actually soft-failed, despite green GitHub statuses: macOS lacks its Installer identity; Windows could not match the stored backslash artifact paths using a slash-prefixed download query. The follow-up uses a separator-independent query scoped to the Windows binary step, with a PowerShell regression that executes the real installer script against both stored path styles. Signed MSI production on this revised pipeline must be verified from the job exit status and artifacts, not its soft-fail GitHub status. Actual PKG signing still requires the unavailable Installer identity. No release was dispatched.Pull request checklist
docs/SETUP.md.Steps to Test
make testandmake lint.PYTHONDONTWRITEBYTECODE=1 python3 -m unittest discover -s packaging/macos -p 'test_package.py'. This builds and inspects packages without installing them on the host.docs/BUILD-SIGNING.mdfor the platform verification commands.