ObjoPublisher is a collection of reusable GitHub Actions workflows for publishing applications created with Objo Studio.
The repository centralizes all publishing logic so that individual application repositories only need small wrapper workflows that provide project-specific parameters and secrets.
Using reusable workflows has several advantages:
- Publishing logic is maintained in one place.
- Improvements automatically benefit every project.
- Build workflows remain small and easy to understand.
- Publishing behavior is consistent across all projects.
- Objo Studio installation and caching are handled automatically.
- License activation and cleanup are handled automatically.
| Workflow | Description |
|---|---|
| publish_objo_macos.yml | Publishes macOS applications, optionally signs and notarizes them using Apple Developer certificates. |
| publish_objo_linux.yml | Publishes Linux applications for one or more runtime targets. |
| publish_objo_windows.yml | Publishes Windows applications and signs generated MSIX packages using the official Azure Trusted Signing GitHub Action. |
| publish_objo_windows_objosign.yml | Publishes Windows applications and lets Objo Studio perform Azure Trusted Signing during publishing. |
All reusable workflows share the same design principles.
The macOS, Linux, and Windows publishing workflows can optionally upload generated artifacts to an SFTP server after the normal GitHub artifact upload succeeds.
SFTP upload is enabled only when all four values are supplied:
sftp-urlsftp-usernamesftp-passwordsftp-host-fingerprint
If any of them is missing or empty, SFTP upload is skipped and publishing continues normally.
Before any file is uploaded, the workflow verifies that the SSH host key presented by the SFTP server matches the expected fingerprint supplied through the sftp-host-fingerprint secret. This protects against connecting to an unexpected or malicious server and avoids the "trust on first use" approach commonly used with SSH. On Windows only RSA SHA256 is accepted, version of curl in Windows runners doesn't support ECDSA or ED25519. If you want higher security on Linux or macOS you can create two repository secrets: one for Windows holding SHA256 RSA key format, the other holding SHA256 ED25519 or ECDSA key formats, then you pass first one to Windows publishing workflow, second one to Linux and/or macOS.
Only after the host key has been successfully verified is the server added to the runner's known_hosts file and the upload allowed to continue.
The workflows upload files into a platform-specific subdirectory below sftp-url:
| Platform | Destination |
|---|---|
| macOS | <sftp-url>/macos/ |
| Linux | <sftp-url>/linux/ |
| Windows | <sftp-url>/windows/ |
The fail-on-sftp-error boolean input controls what happens when the application build succeeds but SFTP upload fails.
| Build | SFTP upload | fail-on-sftp-error |
Result |
|---|---|---|---|
| success | success | either | exit code 0 |
| failure | not attempted | either | exit code 1 |
| success | failed | true |
exit code 2 |
| success | failed | false |
exit code 0 |
| success | skipped | either | exit code 0 |
Each reusable workflow exposes an sftp-upload workflow output with one of these values:
successfailedskipped
The workflows also write a summary to the GitHub Actions workflow summary showing the build and SFTP results.
If the requested version of Objo Studio is already cached on the GitHub runner, it is restored immediately.
Otherwise the workflow automatically downloads the requested version from the official Objo download site and stores it in the GitHub Actions cache for future workflow runs.
By default the latest released version of Objo Studio is used.
The workflows select the licensing scheme from the resolved Objo Studio version:
- Versions earlier than 26.8.4 use persistent activation. The workflow creates a temporary key file, activates the license, publishes, deactivates the license even if publishing fails, and removes the key file.
- Version 26.8.4 and later use temporary activation by passing
--license-key-env OBJO_LICENSE_KEYtoobjo publish. No persistent activation or deactivation is performed.
Instead of publishing into fixed platform-specific folders, every workflow publishes into a directory under the current runner user's home directory.
Default locations are:
| Platform | Default output directory |
|---|---|
| macOS | $HOME/Documents/Publish |
| Linux | $HOME/Publish |
| Windows | %USERPROFILE%\Publish |
The output directory can be changed using the output-directory workflow input.
The macOS, Linux and Windows reusable workflows support publishing multiple runtime identifiers in a single execution.
Example:
with:
targets: "osx-arm64, osx-x64"with:
targets: "linux-x64, linux-arm64"with:
targets: "win-x64, win-arm64"Whitespace around target names is ignored automatically.
By default every reusable workflow automatically determines the latest released version of Objo Studio.
A specific version can be requested:
with:
objo-version: "26.7.1".github/
└── workflows/
publish_objo_linux.yml
publish_objo_macos.yml
publish_objo_windows.yml
publish_objo_windows_objosign.yml
Each workflow can be called from another repository using:
jobs:
publish:
uses: madamov/ObjoPublisher/.github/workflows/<workflow>.yml@v1Files created by an earlier job must be transferred through a workflow artifact because reusable workflows run on a separate runner. For example:
jobs:
prepare-resources:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Generate release notes
run: ./scripts/generate-release-notes.sh
- uses: actions/upload-artifact@v7
with:
name: release-resources
path: RELEASE_NOTES.md
publish:
needs: prepare-resources
uses: madamov/ObjoPublisher/.github/workflows/<workflow>.yml@v1
with:
solution-file: MyGreatApp.objosln
project-file: Projects/MyGreatApp/project.json
resource-artifact-name: release-resourcesUse resource-files for files committed to the application repository and resource-artifact-name for generated files. Artifact files are copied into the project's Resources/Files directory by basename; existing files with the same names are overwritten.
The following sections describe each reusable workflow in detail.
Publishes one or more macOS application bundles created with Objo Studio.
Depending on the available secrets, the workflow can produce either:
- unsigned DMG packages, or
- fully signed and notarized DMG packages ready for distribution.
Apple code signing is optional. If the Apple signing secrets are not supplied, the workflow automatically skips all signing and notarization steps and produces unsigned DMG files.
Generated DMG files can also be uploaded to an SFTP server when SFTP parameters are supplied.
Checkout repository
│
▼
Validate inputs
│
▼
Determine Objo Studio version
│
▼
Restore or download Objo Studio
│
▼
(Optional)
Install Apple signing certificate
│
▼
(Optional)
Create notarization profile
│
▼
(Optional)
Update project.json
│
▼
Activate Objo Studio license
│
▼
Publish application
│
▼
Collect DMG files
│
▼
Upload GitHub artifact
│
▼
(Optional)
Upload DMG files to SFTP
│
▼
Deactivate license
│
▼
Write workflow summary
| Input | Required | Default | Description |
|---|---|---|---|
solution-file |
✔ | Path to the Objo solution file. | |
project-file |
✔ | Path to project.json. |
|
resource-files |
empty | Newline-separated file paths copied into the project's Resources/Files directory before publishing. |
|
resource-artifact-name |
empty | Artifact containing files generated by an earlier job. Its files are copied into the project's Resources/Files directory. |
|
application-name |
✔ | Application name used when collecting artifacts. | |
app-version |
empty | Semantic application version. Valid values update MajorVersion, MinorVersion, and PatchVersion; empty or invalid values leave them unchanged. |
|
output-directory |
Publish |
Output directory under $HOME/Documents. |
|
targets |
osx-arm64,osx-x64 |
Comma-separated list of runtime identifiers. | |
artifact-name |
objo-macos-publish |
Uploaded artifact name. | |
apple-notary-profile |
objo-notarization |
Name of the temporary notarytool profile. | |
objo-version |
latest | Specific Objo Studio version to use. | |
sftp-url |
empty | Base SFTP URL. SFTP upload is skipped when this or either SFTP credential is missing. | |
fail-on-sftp-error |
false |
Exit with code 2 when build succeeds but SFTP upload fails. |
| Secret | Description |
|---|---|
objo-license |
Objo Studio license key. |
If every Apple signing secret below is supplied, the application is signed and notarized.
If one or more are omitted, publishing continues without signing.
| Secret | Description |
|---|---|
apple-certificate |
Base64 encoded Apple Developer certificate (.p12). |
apple-certificate-name |
Signing identity name. |
apple-certificate-password |
Password protecting the .p12 file. |
apple-team-id |
Apple Developer Team ID. |
apple-id |
Apple Developer account email address. |
apple-app-specific-password |
App-specific password used by notarytool. |
| Secret | Description |
|---|---|
sftp-username |
Username used to authenticate to the SFTP server. |
sftp-password |
Password used to authenticate to the SFTP server. |
sftp-host-fingerprint |
Expected SHA256 (RSA, ECDSA and ED25519 are all supported) fingerprint of the SFTP server’s SSH host key. The workflow verifies the server’s identity before uploading any files. |
Both credentials, sftp-host-fingerprint and sftp-url must be supplied for SFTP upload to run.
Supported runtime identifiers are those supported by Objo Studio.
Typical examples are:
| Runtime identifier | Platform |
|---|---|
osx-arm64 |
Apple Silicon |
osx-x64 |
Intel Macs |
Example:
with:
targets: "osx-arm64"or
with:
targets: "osx-arm64, osx-x64"The default output directory is
$HOME/Documents/Publish
It can be overridden:
with:
output-directory: Documents/MyApplicationwhich becomes
$HOME/Documents/MyApplication
Absolute paths are also supported.
The workflow automatically collects every generated DMG.
Typical uploaded artifacts are:
MyApplication-macOS-Apple-Silicon.dmg
MyApplication-macOS-Intel.dmg
Only artifacts that actually exist are uploaded.
For example, when publishing only
targets: osx-arm64only the Apple Silicon DMG is uploaded.
When SFTP is configured, the same collected DMG files are uploaded to:
<sftp-url>/macos/
The reusable workflow exposes:
${{ needs.publish.outputs.sftp-upload }}when called from a job named publish.
Possible values are:
success
failed
skipped
jobs:
publish:
uses: madamov/ObjoPublisher/.github/workflows/publish_objo_macos.yml@v1
with:
solution-file: MyGreatApp.objosln
project-file: Projects/MyGreatApp/project.json
resource-artifact-name: release-resources
application-name: MyGreatApp
output-directory: Publish
targets: "osx-arm64, osx-x64"
artifact-name: mygreatapp-macos
# Optional
# objo-version: "26.7.1"
# Optional SFTP upload
sftp-url: ${{ vars.SFTP_SERVER_URL }}
fail-on-sftp-error: true
secrets:
objo-license: ${{ secrets.OBJO_LICENSE }}
# Optional Apple signing
apple-certificate: ${{ secrets.APPLE_CERTIFICATE }}
apple-certificate-name: ${{ secrets.APPLE_CERTIFICATE_NAME }}
apple-certificate-password: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }}
apple-team-id: ${{ secrets.APPLE_TEAM_ID }}
apple-id: ${{ secrets.APPLE_ID }}
apple-app-specific-password: ${{ secrets.APPLE_APP_SPECIFIC_PASSWORD }}
# Optional SFTP upload
sftp-username: ${{ secrets.BINARIES_USER }}
sftp-password: ${{ secrets.BINARIES_PASSWORD }}
sftp-host-fingerprint: ${{ secrets.SFTP_HOST_FINGERPRINT }}- The workflow automatically creates and removes a temporary keychain.
- The temporary notarization profile exists only for the duration of the workflow.
- Persistent Objo Studio licenses used with versions earlier than 26.8.4 are deactivated before the workflow finishes.
- The downloaded Objo Studio installation is cached by version.
- If Apple signing is disabled, the workflow still produces valid unsigned DMG files.
- SFTP upload is skipped unless
sftp-url,sftp-username, andsftp-passwordare all supplied. - SFTP artifacts are uploaded under
<sftp-url>/macos/. - The workflow writes a GitHub Actions summary and exposes the
sftp-uploadoutput.
Publishes one or more Linux applications created with Objo Studio.
The workflow restores or downloads the requested Objo Studio version, selects the compatible licensing scheme, publishes the application for one or more Linux runtime identifiers, collects the generated archives, uploads them as workflow artifacts, and optionally uploads them to SFTP.
Unlike the macOS and Windows workflows, Linux publishing does not require any platform-specific signing.
Checkout repository
│
▼
Validate inputs
│
▼
Determine Objo Studio version
│
▼
Restore or download Objo Studio
│
▼
Activate Objo Studio license
│
▼
Publish application
│
▼
Collect Linux archives
│
▼
Upload GitHub artifact
│
▼
(Optional)
Upload Linux archives to SFTP
│
▼
Deactivate license
│
▼
Write workflow summary
| Input | Required | Default | Description |
|---|---|---|---|
solution-file |
✔ | Path to the Objo solution file. | |
project-file |
✔ | Path to project.json. |
|
resource-files |
empty | Newline-separated file paths copied into the project's Resources/Files directory before publishing. |
|
resource-artifact-name |
empty | Artifact containing files generated by an earlier job. Its files are copied into the project's Resources/Files directory. |
|
application-name |
✔ | Application name used when naming uploaded artifacts. | |
app-version |
empty | Semantic application version. Valid values update MajorVersion, MinorVersion, and PatchVersion; empty or invalid values leave them unchanged. |
|
output-directory |
Publish |
Output directory under the current user's home directory. | |
targets |
linux-x64 |
Comma-separated list of Linux runtime identifiers. | |
artifact-name |
objo-linux-publish |
Uploaded artifact name. | |
objo-version |
latest | Specific Objo Studio version to use. | |
sftp-url |
empty | Base SFTP URL. SFTP upload is skipped when this or either SFTP credential is missing. | |
fail-on-sftp-error |
false |
Exit with code 2 when build succeeds but SFTP upload fails. |
| Secret | Required | Description |
|---|---|---|
objo-license |
✔ | Objo Studio license key used during publishing. |
sftp-username |
Optional SFTP username. | |
sftp-password |
Optional SFTP password. | |
sftp-host-fingerprint |
Expected SHA256 (RSA, ECDSA and ED25519 are all supported) fingerprint of the SFTP server’s SSH host key. The workflow verifies the server’s identity before uploading any files. |
Both credentials, sftp-host-fingerprint and sftp-url must be supplied for SFTP upload to run.
The workflow supports any Linux runtime identifier supported by Objo Studio.
Typical examples include:
| Runtime identifier | Platform |
|---|---|
linux-x64 |
64-bit Intel/AMD Linux |
linux-arm64 |
ARM64 Linux |
Examples:
with:
targets: "linux-x64"or
with:
targets: "linux-x64, linux-arm64"Whitespace surrounding runtime identifiers is ignored automatically.
The default output directory is
$HOME/Publish
It can be overridden:
with:
output-directory: Applications/MyGreatAppwhich becomes
$HOME/Applications/MyGreatApp
Absolute paths are also supported.
The workflow searches the publish directory recursively and automatically uploads every archive produced by Objo Studio.
Supported archive formats include:
.tar.gz.tgz.zip
Artifacts are renamed to include the application name and runtime identifier when appropriate.
Typical uploaded artifacts might look like:
MyGreatApp-linux-x64.tar.gz
MyGreatApp-linux-arm64.tar.gz
When SFTP is configured, the collected artifacts are also uploaded to:
<sftp-url>/linux/
The reusable workflow exposes the sftp-upload output.
Possible values are:
success
failed
skipped
A calling workflow can read it using:
${{ needs.publish.outputs.sftp-upload }}when the reusable workflow job is named publish.
jobs:
publish:
uses: madamov/ObjoPublisher/.github/workflows/publish_objo_linux.yml@v1
with:
solution-file: MyGreatApp.objosln
project-file: Projects/MyGreatApp/project.json
resource-artifact-name: release-resources
application-name: MyGreatApp
output-directory: Publish
targets: "linux-x64"
artifact-name: mygreatapp-linux
# Optional
# objo-version: "26.7.1"
# Optional SFTP upload
sftp-url: ${{ vars.SFTP_SERVER_URL }}
fail-on-sftp-error: true
secrets:
objo-license: ${{ secrets.OBJO_LICENSE }}
# Optional SFTP upload
sftp-username: ${{ secrets.BINARIES_USER }}
sftp-password: ${{ secrets.BINARIES_PASSWORD }}
sftp-host-fingerprint: ${{ secrets.SFTP_HOST_FINGERPRINT }}- Linux publishing does not require platform-specific certificates.
- Multiple runtime identifiers can be published during a single workflow run.
- The latest Objo Studio release is used automatically unless a specific version is requested.
- The downloaded Objo Studio installation is cached by version.
- Persistent Objo Studio licenses used with versions earlier than 26.8.4 are deactivated even if publishing fails.
- Every generated Linux archive is collected and uploaded automatically.
- SFTP upload is skipped unless all three SFTP values are supplied.
- SFTP artifacts are uploaded under
<sftp-url>/linux/. - The workflow writes a GitHub Actions summary and exposes the
sftp-uploadoutput.
Publishes one or more Windows applications created with Objo Studio and signs the generated MSIX packages using the official Azure Trusted Signing GitHub Action:
azure/trusted-signing-action@v2
In this workflow, Objo Studio is responsible only for generating the MSIX packages. The Azure signing fields in project.json are cleared so that Objo does not attempt to invoke signtool.exe itself.
After publishing finishes, the reusable workflow signs all generated MSIX files using the Azure Trusted Signing action.
Generated MSIX files can optionally be uploaded to an SFTP server.
Checkout repository
│
▼
Validate inputs
│
▼
Determine Objo Studio version
│
▼
Restore or download Objo Studio
│
▼
Configure project.json for external signing
│
▼
Activate Objo Studio license
│
▼
Publish unsigned MSIX packages
│
▼
Deactivate Objo Studio license
│
▼
Sign MSIX packages using
azure/trusted-signing-action
│
▼
Collect signed MSIX packages
│
▼
Upload GitHub artifact
│
▼
(Optional)
Upload MSIX packages to SFTP
│
▼
Write workflow summary
| Input | Required | Default | Description |
|---|---|---|---|
solution-file |
✔ | Path to the Objo solution file. | |
project-file |
✔ | Path to project.json. |
|
resource-files |
empty | Newline-separated file paths copied into the project's Resources/Files directory before publishing. |
|
resource-artifact-name |
empty | Artifact containing files generated by an earlier job. Its files are copied into the project's Resources/Files directory. |
|
application-name |
✔ | Application name used when collecting artifacts and generating the default correlation ID. | |
app-version |
empty | Semantic application version. Valid values update MajorVersion, MinorVersion, and PatchVersion; empty or invalid values leave them unchanged. |
|
output-directory |
Publish |
Output directory under the current Windows user's home directory. | |
targets |
win-x64 |
Comma-separated list of Windows runtime identifiers. | |
windows-format |
MSIX |
Windows output format: MSIX, folder, or zip. With Azure signing, zip is published as a folder, signed, and then zipped. Folder output is also zipped after signing for artifact and SFTP upload. |
|
artifact-name |
objo-windows-publish |
Uploaded artifact name. | |
objo-version |
latest | Specific Objo Studio version to use. | |
azure-correlation-id |
generated | Optional Azure signing correlation ID. When omitted, a value based on the application name and GitHub run ID is generated. | |
sftp-url |
empty | Base SFTP URL. SFTP upload is skipped when this or either SFTP credential is missing. | |
fail-on-sftp-error |
false |
Exit with code 2 when build succeeds but SFTP upload fails. |
| Secret | Required | Description |
|---|---|---|
objo-license |
✔ | Objo Studio license key used during publishing. |
azure-tenant-id |
✔ | Microsoft Entra tenant ID used by the Azure Trusted Signing action. |
azure-client-id |
✔ | Application or service-principal client ID used to authenticate to Azure. |
azure-client-secret |
✔ | Client secret associated with the Azure application registration. |
azure-endpoint |
✔ | Azure Trusted Signing endpoint, for example https://wus2.codesigning.azure.net/. |
azure-account-name |
✔ | Azure Trusted Signing account name. |
azure-certificate-profile-name |
✔ | Trusted Signing certificate profile name. |
azure-package-publisher |
✔ | Publisher value written into the MSIX manifest. It must match the publisher identity used by the signing certificate profile. |
azure-timestamp-url |
Optional RFC 3161 timestamp server URL. When omitted, the signing action runs without timestamping. | |
sftp-username |
Optional SFTP username. | |
sftp-password |
Optional SFTP password. | |
sftp-host-fingerprint |
Expected SHA256 (** ONLY RSA IS SUPPORTED UNDER WINDOWS**) fingerprint of the SFTP server’s SSH host key. The workflow verifies the server’s identity before uploading any files. |
Both credentials, sftp-host-fingerprint and sftp-url must be supplied for SFTP upload to run.
Before publishing, the workflow modifies the Windows signing section in project.json.
The Azure signing fields used by Objo are cleared:
{
"AzureEndpoint": "",
"AzureAccountName": "",
"AzureCertificateProfileName": "",
"AzureCorrelationId": "",
"TimestampUrl": ""
}Only the package publisher remains populated:
{
"PackagePublisher": "CN=..."
}This prevents Objo from attempting to sign the package locally with signtool.exe and Azure.CodeSigning.Dlib.dll.
The generated MSIX is then signed by:
uses: azure/trusted-signing-action@v0The workflow supports any Windows runtime identifier supported by Objo Studio.
Typical examples include:
| Runtime identifier | Platform |
|---|---|
win-x64 |
64-bit Intel/AMD Windows |
win-arm64 |
ARM64 Windows |
win-x86 |
32-bit Windows |
Examples:
with:
targets: "win-x64"or
with:
targets: "win-x64, win-arm64"Whitespace around targets is removed automatically.
The default output directory is:
%USERPROFILE%\Publish
On a GitHub-hosted Windows runner, this is typically similar to:
C:\Users\runneradmin\Publish
It can be changed:
with:
output-directory: Documents\ObjoPublisherwhich becomes:
%USERPROFILE%\Documents\ObjoPublisher
Absolute Windows paths are also supported.
The correlation ID input is optional.
A caller can provide one explicitly:
with:
azure-correlation-id: "MyGreatApp-release-42"When omitted, the workflow generates a value similar to:
MyGreatApp-1234567890
where the numeric part is the GitHub Actions run ID.
The correlation ID is useful when reviewing Azure signing diagnostics and correlating a signing request with a specific GitHub Actions run.
When azure-timestamp-url is provided, the workflow uses the timestamp-enabled signing step.
When the secret is empty or omitted, the workflow uses a second signing step that does not pass timestamp parameters to the Azure action.
This avoids supplying an empty timestamp-rfc3161 value.
The workflow searches the output directory recursively for .msix packages after signing.
The packages are copied into:
%OUTPUT_DIRECTORY%\artifacts
and uploaded using actions/upload-artifact.
Typical uploaded packages might include:
com.objo.app.mygreatapp_1.1.0.0_x64.msix
com.objo.app.mygreatapp_1.1.0.0_arm64.msix
If multiple packages have the same filename, the workflow adds information from the parent directory to prevent overwriting.
When SFTP is configured, the collected packages are also uploaded to:
<sftp-url>/windows/
The workflow prefers an SFTP-capable curl.exe installed with Git for Windows and verifies SFTP support before upload.
The reusable workflow exposes the sftp-upload output.
Possible values are:
success
failed
skipped
A calling workflow can read it using:
${{ needs.publish-windows.outputs.sftp-upload }}when the reusable workflow job is named publish-windows.
name: ObjoPublisher for Windows
on:
workflow_dispatch:
jobs:
publish-windows:
uses: madamov/ObjoPublisher/.github/workflows/publish_objo_windows.yml@v1
with:
solution-file: MyGreatApp.objosln
project-file: Projects/MyGreatApp/project.json
resource-artifact-name: release-resources
application-name: MyGreatApp
output-directory: Publish
targets: "win-x64"
artifact-name: mygreatapp-windows
# Optional
# objo-version: "26.7.1"
# azure-correlation-id: "MyGreatApp-${{ github.run_id }}"
# Optional SFTP upload
sftp-url: ${{ vars.SFTP_SERVER_URL }}
fail-on-sftp-error: true
secrets:
objo-license: ${{ secrets.OBJO_LICENSE }}
azure-tenant-id: ${{ secrets.AZURE_TENANT_ID }}
azure-client-id: ${{ secrets.AZURE_CLIENT_ID }}
azure-client-secret: ${{ secrets.AZURE_CLIENT_SECRET }}
azure-endpoint: ${{ secrets.AZURE_ENDPOINT }}
azure-account-name: ${{ secrets.AZURE_ACCOUNTNAME }}
azure-certificate-profile-name: ${{ secrets.AZURE_CERTIFICATEPROFILENAME }}
azure-package-publisher: ${{ secrets.AZURE_PACKAGEPUBLISHER }}
# Optional
azure-timestamp-url: ${{ secrets.AZURE_TIMESTAMPURL }}
# Optional SFTP upload
sftp-username: ${{ secrets.BINARIES_USER }}
sftp-password: ${{ secrets.BINARIES_PASSWORD }}
sftp-host-fingerprint: ${{ secrets.SFTP_HOST_FINGERPRINT }}- Objo Studio does not perform Windows signing in this workflow.
- Azure signing metadata is deliberately cleared from
project.json. - The package publisher is still written into the project because the MSIX manifest must contain the correct publisher identity.
- The official Azure Trusted Signing GitHub Action signs all generated MSIX packages recursively.
- Persistent Objo Studio licenses used with versions earlier than 26.8.4 are deactivated immediately after publishing.
- Multiple Windows targets are supported in one run.
- Objo Studio is cached by version.
- Timestamping is optional.
- SFTP upload is skipped unless all three SFTP values are supplied.
- SFTP artifacts are uploaded under
<sftp-url>/windows/. - The workflow writes a GitHub Actions summary and exposes the
sftp-uploadoutput.
Publishes one or more Windows applications created with Objo Studio and lets Objo Studio perform Azure Trusted Signing during the publish operation.
Unlike publish_objo_windows.yml, this workflow does not use the official Azure Trusted Signing GitHub Action.
Instead, it:
- installs the Microsoft Azure Artifact Signing Client Tools,
- locates
Azure.CodeSigning.Dlib.dll, - configures the Windows signing section in
project.json, - lets Objo invoke
signtool.exe, - and produces already signed MSIX packages.
This workflow is useful when you prefer Objo Studio to manage both publishing and signing.
Checkout repository
│
▼
Validate inputs
│
▼
Determine Objo Studio version
│
▼
Restore or download Objo Studio
│
▼
Install Azure Artifact Signing Client Tools
│
▼
Locate Azure.CodeSigning.Dlib.dll
│
▼
Configure Windows signing in project.json
│
▼
Activate Objo Studio license
│
▼
Publish and sign application
│
▼
Deactivate license
│
▼
Collect signed MSIX packages
│
▼
Upload artifacts
| Input | Required | Default | Description |
|---|---|---|---|
solution-file |
✔ | Path to the Objo solution file. | |
project-file |
✔ | Path to project.json. |
|
resource-files |
empty | Newline-separated file paths copied into the project's Resources/Files directory before publishing. |
|
resource-artifact-name |
empty | Artifact containing files generated by an earlier job. Its files are copied into the project's Resources/Files directory. |
|
application-name |
✔ | Application name used when generating the default Azure correlation ID and naming artifacts. | |
app-version |
empty | Semantic application version. Valid values update MajorVersion, MinorVersion, and PatchVersion; empty or invalid values leave them unchanged. |
|
output-directory |
Publish |
Output directory under the current Windows user's home directory. | |
targets |
win-x64 |
Comma-separated list of Windows runtime identifiers. | |
windows-format |
MSIX |
Windows output format: MSIX, folder, or zip. With Azure signing, zip is published as a folder, signed, and then zipped. Folder output is also zipped after signing for artifact and SFTP upload. |
|
artifact-name |
objo-windows-signed-publish |
Uploaded artifact name. | |
objo-version |
latest | Specific Objo Studio version to use. | |
azure-correlation-id |
generated | Optional Azure correlation ID. When omitted, the workflow generates one automatically. |
| Secret | Required | Description |
|---|---|---|
objo-license |
✔ | Objo Studio license key. |
azure-endpoint |
✔ | Azure Trusted Signing endpoint, for example https://wus2.codesigning.azure.net/. |
azure-account-name |
✔ | Azure Trusted Signing account name. |
azure-certificate-profile-name |
✔ | Azure Trusted Signing certificate profile name. |
azure-package-publisher |
✔ | Publisher value written into the MSIX manifest. It must match the publisher configured in the Azure certificate profile. |
azure-timestamp-url |
Optional RFC 3161 timestamp server URL. When omitted, Objo signs without timestamping. | |
sftp-username |
Optional SFTP username. | |
sftp-password |
Optional SFTP password. | |
sftp-host-fingerprint |
Expected SHA256 (** ONLY RSA IS SUPPORTED UNDER WINDOWS**) fingerprint of the SFTP server’s SSH host key. The workflow verifies the server’s identity before uploading any files. |
Both credentials, sftp-host-fingerprint and sftp-url must be supplied for SFTP upload to run.
This workflow does not require Azure authentication credentials such as:
- Azure Tenant ID
- Azure Client ID
- Azure Client Secret
Objo Studio performs Azure Trusted Signing using Microsoft's Azure Artifact Signing Client Tools and the authentication mechanisms supported by those tools on the runner.
Before publishing begins, the workflow installs Microsoft's Azure Artifact Signing Client Tools using winget.
After installation, it automatically searches several known installation locations to locate:
Azure.CodeSigning.Dlib.dll
The discovered DLL path is exported as:
AZURE_CODESIGNING_DLIB
allowing Objo Studio to invoke Azure Trusted Signing through Microsoft's signing library.
Before publishing, the workflow writes the Azure signing configuration into project.json.
The following values are configured:
- Azure Endpoint
- Azure Account Name
- Azure Certificate Profile Name
- Azure Correlation ID
- Timestamp URL
- Package Publisher
Because these values are present, Objo Studio automatically signs every generated MSIX package during publishing.
Typical runtime identifiers include:
| Runtime identifier | Platform |
|---|---|
win-x64 |
64-bit Windows |
win-arm64 |
ARM64 Windows |
win-x86 |
32-bit Windows |
Examples:
with:
targets: "win-x64"or
with:
targets: "win-x64, win-arm64"Whitespace surrounding target names is ignored automatically.
The correlation ID is optional.
When not supplied, the workflow automatically generates one using:
- application name
- GitHub run ID
- GitHub run attempt
Example:
MyGreatApp-1234567890-1
Timestamping is optional.
If azure-timestamp-url is supplied, it is written into project.json and Objo requests timestamping while signing.
If omitted, the timestamp field is left empty and Objo signs without timestamping.
Default output directory:
%USERPROFILE%\Publish
Typical GitHub-hosted runner location:
C:\Users\runneradmin\Publish
Custom example:
with:
output-directory: Documents\ReleasesResult:
C:\Users\runneradmin\Documents\Releases
After publishing completes, the workflow searches recursively for every generated .msix package.
The packages are copied into:
artifacts
and uploaded using actions/upload-artifact.
Typical uploaded artifacts:
com.objo.app.mygreatapp_1.1.0.0_x64.msix
com.objo.app.mygreatapp_1.1.0.0_arm64.msix
Duplicate filenames are renamed automatically to avoid overwriting.
name: ObjoPublisher Windows (Objo Signing)
on:
workflow_dispatch:
jobs:
publish:
uses: madamov/ObjoPublisher/.github/workflows/publish_objo_windows_objosign.yml@v1
with:
solution-file: MyGreatApp.objosln
project-file: Projects/MyGreatApp/project.json
resource-artifact-name: release-resources
application-name: MyGreatApp
output-directory: Publish
targets: "win-x64"
artifact-name: mygreatapp-windows
# Optional
# objo-version: "26.7.1"
# azure-correlation-id: "Release-42"
secrets:
objo-license: ${{ secrets.OBJO_LICENSE }}
azure-endpoint: ${{ secrets.AZURE_ENDPOINT }}
azure-account-name: ${{ secrets.AZURE_ACCOUNTNAME }}
azure-certificate-profile-name: ${{ secrets.AZURE_CERTIFICATEPROFILENAME }}
azure-package-publisher: ${{ secrets.AZURE_PACKAGEPUBLISHER }}
# Optional
azure-timestamp-url: ${{ secrets.AZURE_TIMESTAMPURL }}| Feature | publish_objo_windows.yml |
publish_objo_windows_objosign.yml |
|---|---|---|
| MSIX generation | Objo Studio | Objo Studio |
| MSIX signing | Azure Trusted Signing GitHub Action | Objo Studio |
| Azure Artifact Signing Client Tools | Not required | Installed automatically |
Azure.CodeSigning.Dlib.dll |
Not used | Located automatically |
| Azure Tenant / Client credentials | Required | Not required |
project.json Azure settings |
Cleared | Fully populated |
Uses azure/trusted-signing-action |
✔ | ✘ |
Objo invokes signtool.exe |
✘ | ✔ |
- Objo Studio performs both publishing and signing.
- Microsoft's Azure Artifact Signing Client Tools are installed automatically.
- The workflow automatically locates
Azure.CodeSigning.Dlib.dll. - No additional signing step is required after publishing.
- Persistent Objo Studio licenses used with versions earlier than 26.8.4 are deactivated before the workflow finishes.
- Objo Studio is cached by version.
- Multiple Windows runtime identifiers are supported.
- Timestamping is optional.