Publish from CI
A game kept in a Git repository can publish itself: each push to main updates the site, with no one at the keyboard. The CI runs the same command as on your PC, with --json: it never asks a question, and it ends with the game's link and the build report.
Before you start
- Publish the game once from a terminal (first deploy) if you can, to answer its questions. A first deploy in CI takes the defaults; give it the site name with a
rwk.jsonin the game folder, or thesite-nameinput (--nameon the command line), or it is made from the folder's name. Access protection is set up through the API when the token has the Access permissions and the account already has a Zero Trust team. - Create a Cloudflare API token with the permissions the toolkit needs, for the one account, and save it in the CI's secrets as
CLOUDFLARE_API_TOKEN. AddCLOUDFLARE_ACCOUNT_IDif the token reaches several accounts (or put--account <ID>on the command line). - Put the game in the repository, in a folder such as
game/(the one withindex.htmlandjs/). Large pictures and sounds fit better in Git LFS.
The settings stay in your Cloudflare account, as for a deploy from your PC: change them with config on your PC. Feature settings apply at once; the others (include, exclude…) with the next CI run. To keep the site name and the files to leave out in the repository instead, next to the game, use a rwk.json: the pull request check (analyze) then counts the same files as the deploy.
GitHub Actions
.github/workflows/publish.yml in the game's repository:
name: Publish the game
on:
push:
branches: [main]
paths: ["game/**"]
workflow_dispatch:
# One publish at a time; a newer push waits for the one running.
concurrency: publish-game
permissions:
contents: read
jobs:
publish:
runs-on: ubuntu-latest
# A fork has no secrets: never publish from one.
if: ${{ !github.event.repository.fork }}
steps:
- uses: actions/checkout@v5
with:
lfs: true # if the game uses Git LFS
- id: rwk
uses: Kokoroou/rpgmaker-web-toolkit@v0.4.0 # a release tag: v0.4.0 or later
with:
game-folder: game
cloudflare-api-token: ${{ secrets.CLOUDFLARE_API_TOKEN }}
cloudflare-account-id: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
- run: echo "Published at $URL"
env:
URL: ${{ steps.rwk.outputs.url }}The action installs Node.js and the toolkit at the tag you pin, then publishes the folder. Pin a release tag rather than main, and move it up when you want a newer toolkit. The run's page shows a summary: the link, the number of files and the warnings.
| Input | Default | |
|---|---|---|
game-folder | . | The game folder, from the repository's root. For upgrade, the game's link or site name |
command | deploy | Or analyze, saves import, upgrade |
site-name | deploy: the site name of a first deploy. A published game must already have it | |
cloudflare-api-token | Required, except for analyze | |
cloudflare-account-id | When the token reaches several accounts: the one to publish to (its ID or name, see Several Cloudflare accounts) | |
node-version | 22 |
| Output | |
|---|---|
url | The game's link |
site | The site name |
warnings | How many warnings the run had |
result | The whole result as JSON (see below) |
Do not publish on pull_request: a pull request would replace the live site. Check it instead, as below.
Check pull requests without publishing
deploy --dry-run (or analyze) analyzes the game and counts its files against the free plan limits, with no Cloudflare token and nothing published. It fails the job when the build would not deploy (too many files, or a creator who does not allow publishing) and lists the warnings, so it suits pull_request:
on:
pull_request:
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Kokoroou/rpgmaker-web-toolkit@v0.4.0 # a release that has `analyze` (after v0.4.0)
with:
command: analyze
game-folder: gameNo cloudflare-api-token is needed, so a pull request from a fork can run it too.
Or from the shell: node cli/index.js deploy ./game --dry-run --json. The result has "dryRun": true and the build report (see Commands). It uses the first-deploy defaults, so a game with exclude patterns saved in R2 may count more files than its real deploy.
GitLab CI
.gitlab-ci.yml, with CLOUDFLARE_API_TOKEN as a masked CI/CD variable:
publish-game:
image: node:22
rules:
- if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
changes: ["game/**/*"]
variables:
RWK_REF: v0.4.0 # a release tag: v0.4.0 or later
script:
- curl -fsSL "https://raw.githubusercontent.com/Kokoroou/rpgmaker-web-toolkit/$RWK_REF/run.sh" | bash -s -- deploy "$CI_PROJECT_DIR/game" --json > rwk-result.json
artifacts:
when: always
paths: [rwk-result.json]Any other CI
Anything with Node.js 22 or newer, curl and tar runs the same line as GitLab, with CLOUDFLARE_API_TOKEN (and maybe CLOUDFLARE_ACCOUNT_ID) in the environment:
curl -fsSL https://raw.githubusercontent.com/Kokoroou/rpgmaker-web-toolkit/v0.4.0/run.sh | bash -s -- deploy ./game --json > rwk-result.jsonFrom a clone of the toolkit: node cli/index.js deploy ./game --json after npm ci.
The result
The log always goes to stderr. With --json, stdout holds one JSON object:
{
"schema": 1,
"ok": true,
"command": "deploy",
"site": "my-game",
"url": "https://my-game.alice.workers.dev",
"locked": false,
"build": { "files": 1834, "bytes": 412301204, "r2Files": 2, "r2Uploaded": 0 },
"next": ["On a phone: open the link → browser menu → “Add to Home Screen” to play fullscreen."],
"warnings": ["3 audio file(s) have no .m4a version: …"]
}A failed run has "ok": false, error, hint (what to try, or null) and exitCode instead: 1 for a failure (Cloudflare, wrangler, a file), 2 for a question only a person can answer, 64 for a wrong command line. schema changes only when a field is removed or changes meaning. In GitHub Actions the toolkit also writes ok, site, url and warnings as step outputs and the summary, with or without --json, and shows each warning (and the error of a failed run) as an annotation on the run's page and on the pull request.
Good to know
- Each run uploads only the files that changed, as on your PC; the free plan limits still apply.
- The game folder in the checkout is never changed. The toolkit never prints the token; keep it in the CI's secrets, never in the repository.
- Unattended, a deploy does not upload the
save/folder (saves importdoes) and never deletes the old Worker after arename: run those from a terminal.