optional Step - Automatic Desktop Update - using Azure DevOps pipeline
Complete Steps 1–4 before.
This workflow updates an existing macOS app (PKG). It does not create the initial Intune application, configuration profile, or assignments. Start with an app assigned only to pilot devices.
Before You Begin: Permissions and Responsibilities
You need an active Intune tenant, the existing macOS app ID, an Azure DevOps project and repository, and available Microsoft-hosted macOS pipeline capacity.
Manage the Intune application
Use Application Manager or an approved custom role with the required app read, update, and assignment permissions. Include the correct scope groups and tags. Configuration profile changes require separate profile-management permissions.
Maintain the App Registration
The administrator must be permitted to register applications and manage the selected registration and its certificates. If registration is restricted, have your Entra administrator create it and assign its approved owners.
Grant Graph application consent
A Privileged Role Administrator or Global Administrator grants consent. Intune Administrator, Application Administrator, and Cloud Application Administrator alone cannot grant this Microsoft Graph application permission. Activate the required role through PIM if applicable.
Run the unattended update
The pipeline service principal requires Microsoft Graph Application permission DeviceManagementApps.ReadWrite.All, admin consent, and a registered certificate.
Maintain Azure DevOps
Use repository access, normally Basic or higher, with Read and Contribute permissions, plus the required Create build pipeline and Edit build pipeline permissions. Creating a repository requires Create repository permission.
Run and inspect pipelines
Operators need Queue builds, View builds, and View build pipeline. Editing variables requires Edit build pipeline. The pipeline needs access to the repository, hosted agent pool, and deployment environment.
Manage the deployment environment
An environment Creator can create the environment; its Administrator can maintain access. Assign approved people to manage its checks and approve deployments.
Agree who maintains the registration, credentials, pipeline, and failed-run notifications before enabling scheduled updates. The administrator who operates the pipeline does not need permanent Global Administrator access. The build identity needs repository read access for checkout; this workflow does not require it to write to the repository.
The Graph application permission permits Intune application management across the tenant. The target app ID is a script input, not a permission restriction. Protect repository changes, pipeline variables, and queue permissions accordingly. The deployment environment's approval check controls the supplied Publish stage, but cannot protect against a pipeline editor rewriting the credential-bearing validation steps.
How the Pipeline Works
Validation-only
Downloads the PKG and matching checksum, validates the package, and publishes artifacts. No Graph authentication or Intune changes.
Review only (What-If)
Authenticates, reads the existing macOS PKG app, and compares its SCA bundle version with the selected release. Produces a decision manifest. No PKG download, package validation, or Intune writes.
Publish to Intune
Compares versions, downloads and validates a newer package, then passes that artifact to the Publish stage. The stage uses the configured deployment environment and updates the existing app.
Use only the checkbox combinations shown below. Do not select both Publish to Intune and Review only (What-If). The supplied YAML does not exclude What-If in its Publish-stage condition; selecting both can enter that stage without the required validated package artifact.
Identify the Existing Intune Application
In Intune, open Apps → All apps and select the SCA macOS application created in Step 2.
Confirm its type is macOS app (PKG). Record its Intune app ID from the application address if necessary: the GUID following
appId/.Review Included apps. There must be exactly one entry matching
de.provectus.SecureContactsDesktop, with the actual deployed numeric bundle version.Confirm Ignore app version is No for this version-controlled rollout and review the app's assignments. Record the current package version and pilot scope.
Publishing replaces content in the selected app object. Existing assignments remain effective, so already assigned production devices may receive the update. The environment name does not select a pilot group or tenant; the app ID and its assignments determine the target.
Create the Pipeline App Registration
Open Microsoft Entra admin center → App registrations → New registration.
Enter SCA macOS Intune Update Pipeline, select Accounts in this organizational directory only, and leave the redirect URI empty. Select Register.
Record the Directory (tenant) ID and Application (client) ID.
Open API permissions → Add a permission → Microsoft Graph → Application permissions. Add
DeviceManagementApps.ReadWrite.All.
Confirm the permission is listed as Application and granted for your tenant.
Prepare and Register the Certificate
Obtain an organization-approved certificate with a public certificate file and a matching password-protected PKCS#12 file (
.p12or.pfx) containing the private key.
Open Terminal and run:
Store the export password in your approved password manager; this is the pipeline certificate password.
In the pipeline App Registration, select Certificates & secrets → Certificates → Upload certificate. Upload the public
.cerfile.Confirm that the certificate is listed. Record its expiry date and responsible owner.
Copy the PKCS#12 file as a single Base64 value:
For an existing certificate, substitute its actual path. Paste the result into the secret variable in Configure Pipeline Variables below.
The Base64 value contains the private credential. Base64 does not encrypt it. Keep it and the export password in secret variables; do not commit them or print them in logs. Upload only the public certificate to Entra ID.
Create the Pipeline and Deployment Environment
Open the release repository through Step 2, download the source ZIP, and locate
.azure-pipelines.Commit the complete folder to your administrator-owned Azure Repos repository using your normal reviewed Git workflow:
The checkout must contain exactly one
Validate-SecureContactsPackage.sh, withSync-SecureContactsToIntune.shbeside it.In Pipelines → New pipeline, select Azure Repos Git, your repository, and Existing Azure Pipelines YAML file.
Select the reviewed branch and
.azure-pipelines/azure-publish-sca-intune-macos.yml. Save the pipeline and name it SCA macOS - Update Intune.Open Pipelines → Environments → Create environment. Create an empty environment named exactly intune-production, matching the supplied YAML.
Select None for resources.
Confirm that the pipeline can use the environment and that an approver is available for the first publication.
An environment name alone does not create an approval requirement.
Configure Pipeline Variables
Open the pipeline and select Edit → Variables → New variable.
Add these exact names as pipeline variables:
INTUNE_TENANT_ID
Directory (tenant) ID.
No
INTUNE_CLIENT_ID
Application (client) ID of the pipeline registration.
No
INTUNE_MACOS_APP_ID
Intune app ID of the existing macOS PKG app.
No
INTUNE_CERTIFICATE_BASE64
Single-line Base64 content of the password-protected PKCS#12 file.
Yes
INTUNE_CERTIFICATE_PASSWORD
PKCS#12 export password.
Yes
SECURE_CONTACTS_GITHUB_TOKEN
Optional customer-owned token for release access or authenticated API limits.
Yes
Enable Keep this value secret for the certificate, password, and optional token. Use a read-only GitHub token with access to the release repository if required.
Save the variables. If you use a variable group instead, add its group reference to the YAML and authorize this pipeline to use it; creating a group alone does not make its values available.
Run Validation-only
Select Run pipeline and choose the reviewed branch.
Leave both Publish to Intune and Review only (What-If) unchecked.
Select Run.
Watch Download and validate package in the Validate stage. It checks the checksum, installer signer, Gatekeeper assessment, bundle identity, version, and ARM64 executable.
Download secure-contacts-macos-intune-artifacts from the run summary. Review the PKG, its matching checksum file, and validation-manifest.json. Confirm ValidationResult is Validated and the package identity and version are expected.
Validation-only checks the package without connecting to Intune. It does not test certificate authentication or app installation.
Run a What-If Preview
Start another run with:
Publish to Intune
Unchecked
Review only (What-If)
Checked
Review Compare GitHub and Intune versions and open
decision-manifest.jsoninsecure-contacts-macos-intune-artifacts.Check
IntuneAppId,BundleId,CandidateVersion,IntuneBundleVersion, andDecision. Confirm that the target is the intended macOS app.
Interpret the result:
UpdateExistingApp: the candidate version is newer.NoUpdateRequired: the candidate is equal to or older than the existing included-app version.
Publish the Update
Recheck the target app's assignments and confirm that the currently assigned devices may receive the update.
Start a run with:
Publish to Intune
Checked
Review only (What-If)
Unchecked
The Validate stage compares versions. If no newer version is available, the Publish stage is skipped. Otherwise, it downloads and validates the package.
If approval is configured on
intune-production, review the validation artifact from this run before approving the Publish stage. Confirm its package version, bundle ID, and validation result.The Publish stage consumes that artifact, validates it again, authenticates, uploads the encrypted content, and commits the new version to Intune.
Review Publish validated package to Intune, the final run result, and
secure-contacts-macos-intune-publish-artifacts. A validation manifest alone is not proof of successful publication.
Separate runs resolve the latest release independently. The preflight and download within Validate also resolve it separately. Approve the actual validation artifact, not just an earlier What-If result. Publish uses the validated artifact through --use-existing-package. For a fixed release, an administrator can add the same --release-tag vMAJOR.MINOR.PATCH argument to both release-resolving script calls in Validate; replace that example with the approved tag. The supplied run dialog has no release-tag field.
Verify the Updated Mac
Synchronize the pilot Mac and allow Intune to process the update.
Confirm Intune installation status and the actual installed version.
Verify that managed preferences, licensing, sign-in, and contact synchronization still work. Updating the package does not update the preference profile.
Expand assignments after pilot acceptance. If the app already had production assignments, publishing has already exposed the update to that scope.
Optional: Schedule Update Checks and Publishing
Complete a successful manual publication and pilot verification first.
In the existing YAML parameter block, set the default for
publishtotrueand keepwhatIfatfalse:
Uncomment the supplied schedule, or add this top-level block after trigger: none:
Replace
mainif necessary and commit to that branch. Remove any conflicting UI schedule, then commit a change so Azure DevOps reevaluates the YAML schedule. Inspect Scheduled runs.Review the first scheduled run and assign an owner for failures and certificate expiry. Configure the team's Azure DevOps notifications according to your operating process.
Operational Acceptance
Before enabling unattended operation, record:
The Azure DevOps pipeline, reviewed branch, and source revision.
The target tenant and macOS Intune app ID.
The environment approval policy and authorized approvers.
The registration owners, certificate expiry, and renewal contact.
The successful publish run and corresponding pilot-device results.
The team responsible for reviewing failed or approval-pending runs.
Keep the decision and validation artifacts with the release record. Review repository updates before replacing your pipeline bundle; copying the files once does not automatically keep the customer repository synchronized with upstream changes.
Troubleshooting and Certificate Renewal
No macOS agent available
Check hosted parallel-job capacity and agent-pool access.
Environment missing or unauthorized
Check the exact environment name, its existence, and pipeline permissions.
Waiting for approval
Review the current run's artifact and contact the configured environment approver.
Script lookup fails
Keep one validator in the checkout and the sync script beside it.
Certificate cannot be unlocked
Check the Base64 value, export password, and private key in the PKCS#12 file.
Graph authentication or access fails
Check tenant/client IDs, certificate registration and expiry, application permission, and admin consent.
Target is not a macOSPkgApp
Use the Intune ID of the macOS app (PKG), not a LOB app or the Windows app.
Included-app match or version fails
Check the exact SCA bundle ID and its single numeric version entry.
Package validation fails
Inspect the first validator error and the selected release assets. Do not bypass validation.
NoUpdateRequired
The included-app version is already equal or newer; the normal pipeline skips publication.
Publishing fails or times out
Inspect the app's content state and version before retrying. Publication uses several operations and is not automatically rolled back.
Do not run concurrent publications for the same app. A failed run can leave uncommitted content or partially completed changes. An older release is not an automatic rollback: the publisher rejects downgrades, and the normal preflight skips equal or older releases.
To renew the certificate:
The pipeline removes its temporary certificate files, and the script cleans up its temporary authentication files. That does not remove credentials exported on the administrator workstation.
The macOS update workflow is ready for regular operation after a successful publication and device-level pilot verification.
Last updated
Was this helpful?