GitHub Actions for GDAM, the Godot Addon Manager. One definition of how to install the CLI and how to publish an addon, shared by every repository that needs either.
- uses: aviorstudio/gdam-actions/install@v0.3.0Pin the version for reproducible runs:
- uses: aviorstudio/gdam-actions/install@v0.3.0
with:
version: v0.0.8For retries of older releases or existing addons published with a user credential,
pass api-key: ${{ secrets.GDAM_API_KEY }} to publish or release. Create that scoped Clerk
key through the GDAM app. The action sends it as a Bearer credential and verifies
the release asset bytes before publishing. This path does not require OIDC
permissions or a matching workflow commit; the key's current owner permissions
are checked by the registry. The old secret-key input is unsupported. This mode publishes existing addons only.
| Input | Default | Purpose |
|---|---|---|
version |
latest |
Release to install. 0.0.8 and v0.0.8 are equivalent. |
token |
${{ github.token }} |
Authenticates the API call that resolves latest. The default is almost always right — pass one only if the release lives somewhere the workflow's own token cannot read. |
archive-sha256 |
empty | Reviewed archive SHA256; requires an exact release version. |
install-dir |
$RUNNER_TEMP/gdam-bin |
Where the binary goes. Needs no sudo. |
| Output | Purpose |
|---|---|
version |
What was installed, as gdam --version reports it. |
The binary is added to PATH, so later steps can just call gdam. The download
is checksum-verified against the release's checksums.txt. The installer script
itself is fetched from a full gdam commit SHA rather than mutable main; the
checksum verification remains part of that pinned script.
jobs:
publish:
permissions:
contents: read # read the release and its asset
id-token: write # mint the GitHub Actions OIDC token the registry trusts
steps:
- uses: aviorstudio/gdam-actions/publish@v0.3.0
with:
tag: ${{ steps.release.outputs.tag }}v0.3.0 publishes by trusted publishing: the action reads the GitHub
Release named by tag, picks one asset, downloads it to hash its bytes, and
posts the release facts (release id, asset id, name, size, SHA256, target
commit, published_at, prerelease) to POST /api/v1/publish with the job's
GitHub Actions OIDC token for audience api.gdam.dev. There is no registry
credential: the registry trusts the token's repository identity. The GDAM CLI is no longer needed to
publish, and install is unchanged.
| Input | Default | Purpose |
|---|---|---|
api-key |
empty | Optional scoped Clerk key; omitting it selects GitHub OIDC. |
tag |
required | Exact, case-sensitive GitHub Release tag, e.g. v1.2.3. |
addon |
@<owner>/<repo> |
Addon spec. The owner must be the workflow's GitHub organisation. |
asset |
automatic | Exact asset name. Omit when the release has exactly one asset or one named @<owner>_<addon>.gdam.zip. |
api-url |
https://api.gdam.dev |
Registry base URL. |
audience |
api.gdam.dev |
OIDC token audience the registry expects. |
editor-plugin |
empty | true marks the addon as an editor plugin; the registry records it only when this publish creates the addon. |
token |
${{ github.token }} |
Reads the release and downloads the asset for hashing. |
| Output | Purpose |
|---|---|
created |
true for a new registry row; false when the registry already held identical facts (a re-run is idempotent). |
sha256 |
SHA256 of the published asset bytes. |
With OIDC, the registry enforces the following workflow identity policy:
- The token's
repository_ownermust equal the addon's owner handle, so@aviorstudio/*is published only by workflows ofgithub.com/aviorstudio/*. The first publish binds the addon to the workflow's repository; later publishes must come from the same repository. commit_shamust equal the commit the workflow checked out (the token'ssha). The action resolves the tag's commit and fails early, before any token is minted, when it differs fromGITHUB_SHA. Aworkflow_dispatchfrommaintherefore publishes only a release whose tag points atmain's head.- The run must be a
push,releaseorworkflow_dispatchevent on a branch or tag ref, never a pull request. - A tag already recorded with identical facts answers
200(success,created: false); different facts under the same tag, or the same GitHub release under another tag, answer409and the action fails with the registry's message.
If GitHub declares an asset digest, it must match the downloaded bytes; a
mismatch, a size mismatch or a draft release fails before anything is sent.
The action prints the registry's response and never prints either token.
The action reads the asset it hashed and attests two more facts with the
release: dependencies, the addons map of the asset's root gdam.json
("@owner/addon": "<exact tag>"), and global_classes, every class_name
its scripts declare. Both are sent on every publish, empty when the asset
declares nothing. The registry refuses a dependency that is not published or
that declares global classes, and gdam install uses the declaration to
install the whole set (see the gdam README).
Before any token is minted the asset is linted on those bytes, and any failure stops the publish:
- it is a zip with
plugin.cfgat its root, or under the single top-level directory gdam installs from; - it ships no
.gdam/directory and nogdam.lock(both are generated bygdam install; exclude them when packaging); gdam.jsonholds only anaddonsobject of@owner/addonentries with exact tags, none of them the addon itself;- no script refers to another addon's
res://addons/...directory directly. A dependency is reached through the.gdam/deps.gdthatgdam installgenerates, because its address differs between a hoisted and a nested install.
No separate semantic package version is accepted or sent. Release identity is
the one exact tag, preserved byte-for-byte; Release-V1.2.3 and
release-v1.2.3 are different tags.
aviorstudio/gdam-actions/release creates the GitHub Release from a ZIP the
same job verified and then runs publish on it. Its secret-key input is
gone too; the job needs contents: write and id-token: write.
v0.2.0 and earlier shelled out to gdam publish with an owner-scoped
secret-key. The registry no longer fills release facts in from GitHub, so
those releases (and CLI v0.0.8 gdam publish) can no longer publish. Upgrade
the pin, add id-token: write, and delete the GDAM_SECRET_KEY secret.
Every release has its own tag, and repository policy is never to move one. Pin one:
- uses: aviorstudio/gdam-actions/install@v0.3.0Correction: earlier documentation called those tags immutable. Git tags can be moved or deleted; GitHub documents a full 40-character commit SHA as the only immutable action pin. Prefer a verified full SHA when that guarantee is needed. Version tags remain the readable project convention and are protected by the release workflow's no-overwrite check and the repository's no-move policy.
There used to be a moving @v0 that each release repointed. It bought "a fix
reaches every repository without 17 pull requests" and cost the other half of
that sentence: a BAD release also reached every repository, immediately, with
no way to stay on the previous one short of finding its SHA by hand — and
nothing in a consumer's workflow recorded which files it was actually running.
Seventeen pull requests is the price of knowing.
A commit SHA is the immutable option because a tag can be deleted and recreated.
These actions are pre-1.0 on purpose: while the line is 0.x, inputs may still
change between releases. Read the release notes before bumping.
Releases are cut by the Release workflow —
workflow_dispatch with a patch/minor/major choice. It re-runs CI
against the commit first, then creates the tag and the release.
MIT