Publishing with GitHub Actions
OpenUPM can publish a package version automatically after you push a Git tag or publish a GitHub Release. The official GitHub Action triggers an OpenUPM package scan and waits until the matching version is published, fails, or reaches the workflow timeout.
Use this when you maintain the package repository and want the tag workflow to report whether the OpenUPM registry has accepted the new package version. This does not replace the normal OpenUPM package submission process: the package must already be registered on OpenUPM, and the registered repoUrl must point to the same public GitHub repository that runs the workflow.
This workflow is best for new package repositories that are integrated with OpenUPM from the beginning, or for repositories that have already been imported to OpenUPM and then add the action for future releases. It is not intended to be the first importer for an existing repository with a large tag history. Submit or import the package normally first, let OpenUPM establish the package state, then use this action to speed up later tagged releases.
What the Action Does
The action performs three steps:
- Request a short-lived GitHub Actions OIDC token from GitHub.
- Send the package name and Git tag to OpenUPM.
- Poll OpenUPM until the version is installable from the registry, fails, or reaches the configured timeout.
You do not need an OpenUPM account, an OpenUPM token, a GitHub personal access token, or a shared webhook secret. OpenUPM verifies the GitHub OIDC token and checks that the workflow repository matches the package repoUrl.
Tag Push Workflow
Only send tags that contain a parseable semver package version to the action, for example 1.2.3, v1.2.3, upm/1.2.3, or com.example.package@v1.2.3. Other tags are rejected by the action before it contacts OpenUPM.
Add this workflow to the package repository:
name: OpenUPM
on:
push:
tags:
- '**'
permissions:
id-token: write
contents: read
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: openupm/openupm-action@v1
with:
package: com.example.openupm-action
tag: ${{ github.ref_name }}
The id-token: write permission lets the action request a GitHub OIDC token. The token is scoped to the workflow run and expires quickly.
GitHub Release Workflows
For packages that publish through GitHub Release asset tracking, including signed packages, OpenUPM needs the GitHub Release and its package asset to exist before it scans the version. Choose the workflow shape based on who creates the GitHub Release.
Case 1: The Release Already Exists
Use a release: published workflow when the GitHub Release is created outside this workflow, and the package asset is already attached when the release event fires. This is a good fit for manually published releases or external release tools that publish the release after uploading the asset.
name: OpenUPM
on:
release:
types: [published]
permissions:
id-token: write
contents: read
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: openupm/openupm-action@v1
with:
package: com.example.openupm-action
tag: ${{ github.event.release.tag_name }}
Case 2: This Workflow Creates The Release
If a GitHub Actions workflow builds the package, creates the GitHub Release, and uploads the package asset, call openupm/openupm-action as a later step in that same workflow after the upload:
name: Build signed package and publish to OpenUPM
on:
push:
tags:
- '**'
permissions:
id-token: write
contents: write
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# Build, sign, and verify the UPM tarball here.
- name: Upload GitHub Release asset
uses: softprops/action-gh-release@v2
with:
files: path/to/com.example.package-*.tgz
- uses: openupm/openupm-action@v1
with:
package: com.example.package
tag: ${{ github.ref_name }}
A release created by a workflow's GITHUB_TOKEN does not normally start another workflow from the release event. Even when a separate release event workflow does run, it can start before later asset upload steps finish. Keeping the OpenUPM action after the asset upload avoids both cases.
Inputs
| Input | Required | Default | Description |
|---|---|---|---|
package | Yes | OpenUPM package name, such as com.company.tool. | |
tag | Yes | Git tag that triggered the workflow. It must contain an OpenUPM-compatible package version. | |
timeout-minutes | No | 15 | Maximum time to wait before failing the workflow. |
poll-interval-seconds | No | 15 | Delay between status checks. |
Outputs
| Output | Description |
|---|---|
state | Final OpenUPM release state, such as succeeded or failed. |
reason | Public failure reason when OpenUPM reports one. |
published-version | Registry version reported by OpenUPM when available. |
signed | Whether OpenUPM reports the package version as signed. |
package-url | OpenUPM package page URL. |
status-url | OpenUPM release status API URL. |
Failure Behavior
The workflow fails when OpenUPM rejects the trigger request, the package version fails to build, or the timeout is reached before the version becomes installable.
A successful action run means the requested version is available from the OpenUPM registry. The package detail page and website search may update through their own refresh cycle after the registry publish completes.
If the action reports a build failure, use the package page's build history and the Troubleshooting Build Errors guide to fix the package, then create a new version tag or re-tag a failed version when your repository policy allows it.
Rate Limit
OpenUPM accepts up to 20 refresh trigger requests per hour for each package, GitHub repository, and caller IP combination. When the limit is exceeded, the API returns 429 RateLimitExceeded with a Retry-After header.
The limit is meant to absorb accidental workflow loops, repeated tag events, and short-lived OIDC token replay without requiring OpenUPM accounts or package owner profiles. Normal tag or release publishing should not hit it.
Example Repository
The openupm/com.example.openupm-action repository demonstrates a minimal Unity package that publishes through the tag-push workflow. Packages that use GitHub Release asset tracking should use one of the GitHub Release workflows instead.