Note about this article
The original version of this article was written entirely by me in Japanese.
I used AI to translate and polish the English version for a global audience, but the ideas, design decisions, implementation details, and original content are all my own work.
If you'd like to read the original Japanese article, you can find it here:
Managing Intune Apps as Code with RelayPublisher
Managing custom applications in Microsoft Intune has always felt more complicated than it should be.
When you need to publish an internal application, you typically have a few options:
- Register it manually through the Intune portal
- Use one of the sample PowerShell scripts available online
- Build your own automation around Microsoft Graph APIs
All of these approaches work, but none of them feel particularly developer-friendly.
In my case, the process was even more frustrating because I normally don't operate with elevated privileges. Every time I needed to publish or update an application, I had to perform a PIM elevation before making changes.
That led me to a simple question:
Why can't Intune application publishing work more like winget?
I wanted a workflow where application definitions could live in source control, be described in YAML, and be published automatically through CI/CD.
That idea became RelayPublisher.
Relaypublisher
Relaypublisher publishes winget-like YAML manifests as Microsoft Intune LOB apps from CI.
Distribution:
- NuGet global tool package id:
relaypublisher
- Command name:
relaypublisher
- Package version: injected by CI from Git tag
vX.Y.Z
- Feeds: nuget.org, GitHub Packages (this repository), and Azure Artifacts
- Self-contained single-file apps for
win-x64, win-arm64, and osx-arm64 are attached to each
GitHub release. They are neither code-signed nor notarized, so macOS shows a Gatekeeper warning.
Quick install:
dotnet tool install --global relaypublisher
See doc/05-operation.md for installing
from GitHub Packages or Azure Artifacts instead.
The repository now contains the .NET CLI foundation for the normal workflow:
-
validate checks manifest schema rules and repository-wide identity uniqueness.
-
plan resolves the target manifest set once and writes manifest-list.json for later CI jobs.
-
package stages app files: Windows Win32 .intunewin packages (Windows runner required) or a
staged, checksum-verified macOS .pkg (any OS).
-
publish creates or updates Intune apps, uploads packaged content…
Relaypublisher
Relaypublisher publishes winget-like YAML manifests as Microsoft Intune LOB apps from CI.
Distribution:
- NuGet global tool package id:
relaypublisher - Command name:
relaypublisher - Package version: injected by CI from Git tag
vX.Y.Z - Feeds: nuget.org, GitHub Packages (this repository), and Azure Artifacts
- Self-contained single-file apps for
win-x64,win-arm64, andosx-arm64are attached to each GitHub release. They are neither code-signed nor notarized, so macOS shows a Gatekeeper warning.
Quick install:
dotnet tool install --global relaypublisher
See doc/05-operation.md for installing from GitHub Packages or Azure Artifacts instead.
The repository now contains the .NET CLI foundation for the normal workflow:
-
validatechecks manifest schema rules and repository-wide identity uniqueness. -
planresolves the target manifest set once and writesmanifest-list.jsonfor later CI jobs. -
packagestages app files: Windows Win32.intunewinpackages (Windows runner required) or a staged, checksum-verified macOS.pkg(any OS). -
publishcreates or updates Intune apps, uploads packaged content…
What is RelayPublisher?
RelayPublisher is an open-source tool that allows you to define Intune applications using YAML and publish them through automation.
Instead of clicking through the Intune portal, you manage application definitions as code.
If you're already familiar with Infrastructure as Code (IaC) or GitOps practices, the concept should feel natural.
Why I Built It
Historically, building this type of tool felt like a lot of work.
There are many moving parts:
- Microsoft Graph integration
- Intune packaging
- Authentication
- Configuration management
- Error handling
The emergence of generative AI significantly reduced the effort required to create and maintain a project like this. Tasks that would previously have been tedious became much easier to implement.
As a result, I was finally able to build the tool I had wanted for a long time.
Key Features
- YAML-based application definitions
- CI/CD-friendly workflow
- Microsoft Intune integration
- Source-controlled application management
- Support for GitHub and Azure Repos workflows
A sample YAML definition is included in the repository to help you get started quickly.
Example:
SchemaVersion: "1.0"
PackageIdentifier: Microsoft.PowerShell
PackageName: PowerShell
Developer: Microsoft Corporation
Publisher: Microsoft Corporation
Description: PowerShell 7 cross-platform automation and configuration tool.
PackageVersion: 7.6.5
AssignmentSync: merge
Apps:
- Platform: macos
Architecture: arm64
InstallerType: pkg
# pkg (default): unmanaged macOSPkgApp, unsigned allowed, up to 8 GB, and the
# only AppType that can target MinimumOSVersion 14+ (v14_0/v15_0 are beta-only
# flags; see doc/01-manifest-schema.md 5.7 and MacOsMinimumOperatingSystemTable).
AppType: pkg
DisplayName: PowerShell [macOS ARM64]
# Single Source item for macOS (unified source item shape, doc/01-manifest-schema.md 5.0.1).
# PowerShell/PowerShell is a public repository, so Auth.Type: none is enough
# for anonymous asset download.
Source:
Type: githubRelease
Owner: PowerShell
Repository: PowerShell
Tag: v7.6.5
AssetName: powershell-7.6.5-osx-arm64.pkg
Destination: powershell-7.6.5-osx-arm64.pkg
Sha256: "6ea58f4e91ab2df133ac18a42e291e4e870a623e3c5ab6f8368259cd9ac22770"
Auth:
Type: none
Requirements:
# PowerShell 7.6 (LTS) supports macOS 14 (Sonoma), 15 (Sequoia), and 26 (Tahoe).
# 14.0 is the lowest version Relaypublisher's version table can map (26.0 is not
# yet defined there); AppType: pkg allows the beta-only v14_0 flag.
MinimumOSVersion: "15.0"
Detection:
IgnoreAppVersion: false
IncludedApps:
- BundleId: com.microsoft.powershell
BundleVersion: 7.6.5
# Optional, AppType: pkg only (doc/01-manifest-schema.md §5.4.2): pre/post-install
# shell scripts, mapped to Graph macOSPkgApp.preInstallScript/postInstallScript.
# Paths are relative to --repo-root (samples/, per this file's own README).
Scripts:
PreInstall: scripts/macos/powershell/preinstall.sh
PostInstall: scripts/macos/powershell/postinstall.sh
# Left empty so this manifest applies unmodified in any tenant. Add your own
# target group(s) before a real (non-dry-run) publish, for example:
# Assignments:
# - Target: group
# GroupId: "<your-assignment-group-guid>"
# Intent: required
Assignments: []
Top comments (0)