modTarget mod
Use the slug from the PalMods URL. It must match the token's bound mod.
Build your mod once. The official action creates the archive, carries over your release notes, uploads it to PalMods, waits for scanning, and leaves a complete job summary in GitHub.
palmods/palmods-publish@v1Four-step setup
Bind one short-lived credential to one PalMods mod.
Map build output to PalMods metadata in .palmods.yml.
Build from the immutable tag and run the first-party action.
Release notes, files, scanning, and status now travel together.
Create the PalMods mod page before issuing a token. You may keep the mod as a draft while you validate the workflow, so a test file never becomes public.
Authenticate GitHub
Sign in to PalMods, open Settings, and select the Developer tab.
Choose the mod, give the token a recognizable repository name, and choose a rotation window. PalMods displays the secret once.
Open the repository's Settings → Secrets and variables → Actions page and add a repository secret named PALMODS_PUBLISH_TOKEN.
Never place it in workflow YAML, source, release notes, screenshots, artifacts, or a committed environment file. If it appears anywhere public, revoke it and create a replacement.
Describe the artifact
schema: 1
mod: aqua-circuit
files:
- path: build/palmods
archive_name: aqua-circuit-${version}.zip
category: main
loader: lua
side: both
game_versions:
- '1.0'modUse the slug from the PalMods URL. It must match the token's bound mod.
pathPoint to a directory or existing ZIP inside the checked-out workspace.
archive_nameEnd with .zip. The ${version} placeholder uses the normalized release tag.
category / loader / sideChoose values that match the archive users will actually install.
game_versionsList only the Palworld versions you tested with the final archive.
channelOmit it to map stable releases to release and GitHub prereleases to beta.
Add up to ten independent entries under filesfor client, server, or optional archives. Each entry receives its own upload and PalMods job. JSON is also supported through the action's config input.
Run on release
name: Publish to PalMods
on:
release:
types: [published]
permissions:
contents: read
concurrency:
group: palmods-release-${{ github.event.release.id }}
cancel-in-progress: false
jobs:
publish:
runs-on: ubuntu-latest
steps:
- name: Check out the release tag
uses: actions/checkout@v6
with:
ref: ${{ github.event.release.tag_name }}
persist-credentials: false
- name: Build the release directory
run: ./scripts/build-release.sh
- name: Publish to PalMods
id: palmods
uses: palmods/palmods-publish@v1
with:
token: ${{ secrets.PALMODS_PUBLISH_TOKEN }}The runner builds the commit the author released, not a newer default-branch commit.
The action does not need write access to repository contents. The PalMods token supplies its separate, narrow permission.
The concurrency key prevents overlapping attempts for the same GitHub Release while still allowing safe reruns.
@v1 follows reviewed, compatible v1 releases. Security-sensitive repositories can pin the full commit SHA from the verified action release .
Ship the first version
v1.4.0.v1.4.0 → 1.4.0release channelbeta channel by defaultready and warning succeed. rejected, failed, and expired fail after the action writes links and details to the job summary.
After you click Publish
Use an existing ZIP or let the action create a deterministic archive from a directory.
The token is checked against the target mod before PalMods allocates an upload.
The file goes directly to its signed storage destination; the token does not.
PalMods applies the same configured virus and package checks as a website upload.
The job summary links to every PalMods job and records its final state.
Repository ID, GitHub Release ID, and archive name form the stable submission identity. Retryable requests resume that identity; changed metadata requires a new release.
Security defaults
It is masked before processing and is never sent to the signed storage upload URL.
API and storage redirects cannot forward credentials or signed headers to an unexpected host.
Config and artifact paths cannot escape the checkout, and the repository root cannot be packaged.
Directory packaging rejects symbolic links, sockets, devices, and other non-regular files.
Found a publishing security issue? Use the repository's private security reporting guidance . Never include a real token or signed upload URL in a public issue.
Troubleshooting
| Error | What it means | What to do |
|---|---|---|
invalid_token / expired_token | The secret is missing, revoked, malformed, or past its expiry. | Check the secret name. If the one-time value is unavailable, create a replacement token and update GitHub. |
mod_access_denied | The token cannot publish to the configured mod. | Verify the mod slug, token binding, and current owner or co-author access. |
invalid_package_metadata | A loader, side, category, channel, or game version is not accepted. | Compare .palmods.yml with the fields below and the packaging contract. |
idempotency_conflict | This GitHub Release and logical file were already submitted with different metadata. | Publish a new release tag after changing the archive or its metadata. |
Timed out while scanning | GitHub stopped waiting, but the durable PalMods job is still running. | Rerun the failed job. The action resumes the existing submission instead of creating a duplicate. |
Start with a draft mod if you want a private end-to-end test before publishing to users.