Deploy from GitHub Actions and GitLab CI in one step
If your CI already builds the site, you do not need a separate hosting pipeline. One line
after npm run build is enough:
npx @tuqo/cli deploy ./dist --site $TUQO_SITE_ID --wait
The key lives in the TUQO_API_KEY secret and the site ID in a variable. The CLI does the
rest: it computes the sha256 of every file, asks the server which blobs it does not have yet,
uploads only the missing ones and publishes the new version. A repeat deploy of the same site
is almost instant: editing text does not push the photos again.
Step 1. A key with editor rights
Panel → project → API keys → create a key. The editor level is enough
to deploy (readonly cannot publish, and full is only needed to manage the project). The full
key, tqk_<prefix>_<secret>, is shown once, so copy it right away. After that you can
only reissue it.
The site ID (site_id) is shown on the site’s page in the panel; whoami and create_site
in the API return it too.
Step 2. Secrets in the repository
GitHub: Settings → Secrets and variables → Actions → New repository secret →
TUQO_API_KEY. The site ID does not need to be secret: add it on the Variables tab as
TUQO_SITE_ID.
GitLab: Settings → CI/CD → Variables → Add variable. Mark the key Masked, so it never
shows up in job logs, and Protected, so only pipelines on protected branches such as
main can read it (merge requests from forks cannot).
Never keep the key in the repository. If you use a multi-site tuqo.json, the CLI checks the
file on purpose and refuses to run if it finds a key field there.
Step 3. GitHub Actions
name: Deploy to Tuqo
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci && npm run build
- run: npx @tuqo/cli deploy ./dist --site ${{ vars.TUQO_SITE_ID }} --wait
env:
TUQO_API_KEY: ${{ secrets.TUQO_API_KEY }}
Step 3 (alternative). GitLab CI
deploy:
image: node:20
stage: deploy
rules:
- if: $CI_COMMIT_BRANCH == "main"
script:
- npm ci && npm run build
- npx @tuqo/cli deploy ./dist --site "$TUQO_SITE_ID" --wait
# TUQO_API_KEY and TUQO_SITE_ID: Settings → CI/CD → Variables (the key is masked)
The --wait flag waits until the version is published and prints the live URL on the second
line. On failure it exits with code 1, so the CI job turns red instead of passing “green”
with an unpublished version. Logs and progress go to stderr, which means you can safely
capture stdout in a variable:
URL=$(npx @tuqo/cli deploy ./dist --site "$TUQO_SITE_ID" --wait | tail -n1)
echo "Published: $URL"
Pull request previews: —no-activate
The --no-activate flag builds a version but does not put it on the live address:
visitors keep seeing the current one. The build gets a secret link, which is handy to post
as a comment on the PR:
name: Preview
on: pull_request
jobs:
preview:
runs-on: ubuntu-latest
env:
TUQO_API_KEY: ${{ secrets.TUQO_API_KEY }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 20 }
- run: npm ci && npm run build
- id: dep
run: |
D=$(npx @tuqo/cli deploy ./dist --site ${{ vars.TUQO_SITE_ID }} --no-activate)
echo "url=$(npx @tuqo/cli preview "$D")" >> "$GITHUB_OUTPUT"
- run: echo "Preview: ${{ steps.dep.outputs.url }}"
Without --wait, stdout holds just the deploy ID, which is what preview takes. The
preview command is idempotent: calling it again returns the same link. Happy with the
result? Publish it with npx @tuqo/cli promote <deploy_id>; the same command rolls the site
back to any kept version.
The preview link does not ask for a password, even if the site is gated, so share it only with people you trust; you can turn it off in the panel. Build preview is available from the Start plan (590 ₽/mo; approximate prices in dollars and euros are on the pricing page). Details are on the build preview page.
How this differs from Git CD
| The CLI in your CI | Git CD | |
|---|---|---|
| Who builds | your runner, your steps | Tuqo: Node 20, npm ci && npm run build |
| What to set up | YAML + a secret with the key | link the repository in the panel |
| Plan build minutes | not used | used by every build |
| Tests, linters, code generation | anything you like | no, the standard build only |
| Webhook | not needed | created automatically |
The rule is simple. You need your own steps before the build: use the CLI from CI. You just want “push → site in production”: use Git CD, which needs no YAML and no keys. More in the guides on auto-deploy from Git and CI/CD without GitHub Actions.
FAQ
Do I need to install the CLI in the image?
No. npx @tuqo/cli downloads the package on first run. It needs Node.js 18 or newer, and the
package has no dependencies. On GitLab the node:20 image is enough.
What are the limits of a single deploy?
Up to 2000 files and up to 50 MB per file, in total within your plan’s storage quota. The
folder must have index.html at its root. Files go up one by one, so there is no request
body size limit.
Can I publish several sites from one repository?
Yes. Put a tuqo.json with a folder-to-site map at the repository root and run
npx @tuqo/cli deploy without arguments: one run publishes every site and prints one line
per site to stdout. Pass the key in the environment variable as before.
{ "sites": { "site/com": "<site_id_com>", "site/ru": "<site_id_ru>" } }
The build failed in CI. What happens to the site?
Nothing changes: until a new version is published, the live address serves the previous one.
With --wait, a failed deploy ends the command with code 1, so the pipeline stops on its own.
All CLI commands and flags → · Build preview → · Auto-deploy from Git →