Skip to content
WebShield Docs

The site updates itself after git push

When a Hugo, Astro or other generator site is built and uploaded by hand, the site may end up on the wrong version. How to publish it automatically from GitHub Actions, GitLab CI, Gitea or Forgejo.

When a generator-built site is built and uploaded by hand, fixes pile up, and the site may end up running a build that is not in the repository.

The fix is publishing from CI: whatever is on the main branch is on the site. A token that can only publish one site makes it safe.

What you get: every push to main reaches the site as soon as the CI job finishes; no more manual uploads. You need: a site created with us, a repository on GitHub, GitLab, Gitea or Forgejo, and a working build command. Time: 10 minutes.

In the panel open the site with Manage, block Deploy tokens (CI) → Create token. Copy it right away: the full value is shown once.

The token can only upload files and publish this site. Site settings, the domain, DNS and other sites are out of its reach, so a leak from CI costs little — and you can revoke it in the same place with one click.

Name it WS_TOKEN: that is where the CLI looks without extra flags.

  • GitHub, Gitea, Forgejo: Settings → Secrets → Actions → New secret.
  • GitLab: Settings → CI/CD → Variables, with Masked and Protected ticked. The first keeps the token out of job logs, the second out of builds of other branches.

The token must never land in the repository itself, not even a private one.

GitHub Actions, Gitea, Forgejo share the syntax:

# .github/workflows/deploy.yml (Gitea and Forgejo: .gitea/workflows/ or .forgejo/workflows/)
name: Deploy site
on:
push:
branches: [main]
# Several pushes in a row — the last one publishes, the rest are cancelled.
concurrency:
group: deploy-site
cancel-in-progress: true
jobs:
deploy:
runs-on: ubuntu-latest
env:
WS_TOKEN: ${{ secrets.WS_TOKEN }}
steps:
- uses: actions/checkout@v5
- run: npm ci && npm run build # your build → ./dist
- name: Install CLI
run: curl -fsSL https://raw.githubusercontent.com/webshieldpro/webshield-cli/main/install.sh | sh
- name: Publish
run: ~/.local/bin/webshield sites publish www.example.com --dir ./dist

GitLab CI:

.gitlab-ci.yml
deploy:
image: node:24
rules:
- if: $CI_COMMIT_BRANCH == "main"
interruptible: true
script:
- npm ci && npm run build # your build → ./dist
- curl -fsSL https://raw.githubusercontent.com/webshieldpro/webshield-cli/main/install.sh | sh
- ~/.local/bin/webshield sites publish www.example.com --dir ./dist

Substitute your own build command and output folder. Popular generators are listed in the table: Hugo writes the site to public/, Astro to dist/, MkDocs to site/. Hugo is not built with npm — replace the build line, for example with the ready-made peaceiris/actions-hugo action and hugo --minify.

4. Make sure the right thing gets published

Section titled “4. Make sure the right thing gets published”

Before the first real run, look at the plan on your own machine:

Terminal window
WS_TOKEN=… webshield sites publish www.example.com --dir ./dist --dry-run

The CLI counts how many files it will upload, delete and keep as they are, and touches nothing. If the whole site is up for deletion, the folder is wrong.

Then push. The job log shows the same summary and a line saying the site was published.

  • Only the difference is uploaded. The CLI compares files with what we already hold and sends the changed ones. Editing one page uploads one file, not the whole site.
  • Publishing is atomic. A visitor sees either the previous version or the new one in full — never old CSS mixed with new HTML.
  • No cache to purge. Every publish is a new version, and the old cache does not apply to it.
  • A failed publish does not stay stuck. If the files went up but publishing failed, the next run notices and publishes again.
Terminal window
curl -sI https://www.example.com/ | head -1

The reply is HTTP/2 200, and the fresh change is on the site. If you don’t see it, reload the page bypassing the browser cache (Ctrl+F5).

Symptom Cause and fix
Authorization error The secret does not reach the job: check env: WS_TOKEN, and in GitLab that the branch is protected — otherwise a Protected variable is not passed to it.
Site not found The token was issued for another site, or the hostname in the command has a typo. A deploy token sees only its own site.
The summary deletes the whole site --dir does not point at the build output, or the build failed earlier and the folder is empty.
The job succeeds, the site does not change A different host is being published: compare the hostname in the command with the site name in the panel.
.exe, .apk and the like are rejected Executables are available on commercial plans only.