From 393b72785303bcb9fa517371f71f27bf7505762d Mon Sep 17 00:00:00 2001 From: butterrobot Date: Wed, 9 Sep 2026 08:24:10 +0000 Subject: [PATCH 1/2] ci: migrate deploy pipeline from Woodpecker to Forgejo Actions Replaces .woodpecker/deploy.yml with .github/workflows/deploy.yml, keeping the same shape: build with Hugo, then rsync public/ to the web host over SSH using the existing SSH_HOST / SSH_USER / SSH_PATH / SSH_PRIVATE_KEY secrets. The hand-rolled SSH setup is replaced by actions/ssh-deploy-action, and the Woodpecker "Daily build" cron becomes a schedule: trigger, plus workflow_dispatch for manual runs. Hugo is installed from a pinned, checksum-verified extended release because the ci-base image does not ship it and the theme transpiles Sass. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/deploy.yml | 54 ++++++++++++++++++++++++++++++++++++ .woodpecker/deploy.yml | 33 ---------------------- README.md | 25 +++++++++++++++++ 3 files changed, 79 insertions(+), 33 deletions(-) create mode 100644 .github/workflows/deploy.yml delete mode 100644 .woodpecker/deploy.yml diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..3987d78 --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,54 @@ +name: Deploy + +on: + push: + branches: [master] + schedule: + # Daily rebuild so posts dated in the future get published on time. + - cron: '0 4 * * *' + workflow_dispatch: + +jobs: + deploy: + runs-on: docker + container: git.nakama.town/fmartingr/ci-images/ci-base:1.1.0 + steps: + - uses: actions/checkout@v7 + + # Hugo Modules resolve github.com/hugomods/images through the Go toolchain. + - uses: actions/setup-go@v7 + with: + go-version-file: go.mod + + - name: Install Hugo + env: + HUGO_VERSION: '0.165.0' + HUGO_SHA256_AMD64: f43494894cdf4a8630a201d5c828051c77f523cc66bb3938b30806835470ac20 + HUGO_SHA256_ARM64: f40ebc44dfda3896cecd3ae7ed44f5c44c4b4a30a2b7d976ece6da62da699a58 + run: | + set -eu + case "$(uname -m)" in + x86_64) arch=amd64; checksum="$HUGO_SHA256_AMD64" ;; + aarch64) arch=arm64; checksum="$HUGO_SHA256_ARM64" ;; + *) echo "Unsupported architecture: $(uname -m)" >&2; exit 1 ;; + esac + # The theme transpiles Sass, which only the extended build ships. + curl -fsSL -o hugo.tar.gz \ + "https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-${arch}.tar.gz" + echo "${checksum} hugo.tar.gz" | sha256sum -c - + tar -xzf hugo.tar.gz hugo + install -m 0755 hugo /usr/local/bin/hugo + rm -f hugo hugo.tar.gz + hugo version + + - name: Build site + run: hugo --gc --minify + + - name: Deploy + uses: actions/ssh-deploy-action@main + with: + host: ${{ secrets.SSH_HOST }} + username: ${{ secrets.SSH_USER }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + source: public + target: ${{ secrets.SSH_PATH }} diff --git a/.woodpecker/deploy.yml b/.woodpecker/deploy.yml deleted file mode 100644 index 06c081d..0000000 --- a/.woodpecker/deploy.yml +++ /dev/null @@ -1,33 +0,0 @@ -when: - - event: push - branch: master - - event: cron - branch: master - cron: Daily build - -steps: - - name: Hugo build - image: alpine:latest - commands: - - apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community go hugo git - - hugo --gc --minify - - ls public - - - name: Deploy - image: alpine:latest - environment: - SSH_HOST: - from_secret: SSH_HOST - SSH_USER: - from_secret: SSH_USER - SSH_PATH: - from_secret: SSH_PATH - SSH_PRIVATE_KEY: - from_secret: SSH_PRIVATE_KEY - commands: - - apk add --no-cache openssh-client rsync - - mkdir -p ~/.ssh - - echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa - - chmod 600 ~/.ssh/id_rsa - - ssh-keyscan $SSH_HOST >> ~/.ssh/known_hosts - - rsync -avz public/ $SSH_USER@$SSH_HOST:$SSH_PATH diff --git a/README.md b/README.md index 55dffc3..830ebdc 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,28 @@ # fmartingr.com Source code for my personal site hosted at [fmartingr.com](https://fmartingr.com) + +## Development + +```sh +make server # local preview, including drafts and future-dated posts +make new-post # scaffold a post under content/blog/YYYY/MM/DD/ +``` + +The theme transpiles Sass, so a Hugo **extended** build is required. + +## Deployment + +`.github/workflows/deploy.yml` builds the site and rsyncs `public/` to the web +host over SSH. It runs on pushes to `master`, on a daily schedule (so posts +dated in the future get published once their date arrives), and on manual +dispatch. + +It needs the following Actions secrets: + +| Secret | Description | +| --- | --- | +| `SSH_HOST` | Hostname of the web server | +| `SSH_USER` | SSH login user | +| `SSH_PATH` | Remote directory the site is copied into | +| `SSH_PRIVATE_KEY` | Private key contents for `SSH_USER` | -- 2.52.0 From 7375ce25e6c99a16160ce02e88ee8b8b6ff44e68 Mon Sep 17 00:00:00 2001 From: butterrobot Date: Wed, 9 Sep 2026 08:31:06 +0000 Subject: [PATCH 2/2] ci: verify the build on pull requests and rsync with --delete The build step now also runs for pull requests against master, so a broken site is caught before merge. Deploying is gated behind the event type, so only pushes to master, the daily schedule and manual dispatches publish. rsync now runs with --delete: files no longer produced by the build are removed from the server instead of lingering. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/deploy.yml | 9 +++++++-- README.md | 12 +++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 3987d78..20380fc 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -1,15 +1,17 @@ -name: Deploy +name: Build and deploy on: push: branches: [master] + pull_request: + branches: [master] schedule: # Daily rebuild so posts dated in the future get published on time. - cron: '0 4 * * *' workflow_dispatch: jobs: - deploy: + build-and-deploy: runs-on: docker container: git.nakama.town/fmartingr/ci-images/ci-base:1.1.0 steps: @@ -41,10 +43,12 @@ jobs: rm -f hugo hugo.tar.gz hugo version + # Runs on every pull request too, so a broken build is caught before merge. - name: Build site run: hugo --gc --minify - name: Deploy + if: github.event_name != 'pull_request' uses: actions/ssh-deploy-action@main with: host: ${{ secrets.SSH_HOST }} @@ -52,3 +56,4 @@ jobs: key: ${{ secrets.SSH_PRIVATE_KEY }} source: public target: ${{ secrets.SSH_PATH }} + args: --delete diff --git a/README.md b/README.md index 830ebdc..98dd15d 100644 --- a/README.md +++ b/README.md @@ -14,9 +14,15 @@ The theme transpiles Sass, so a Hugo **extended** build is required. ## Deployment `.github/workflows/deploy.yml` builds the site and rsyncs `public/` to the web -host over SSH. It runs on pushes to `master`, on a daily schedule (so posts -dated in the future get published once their date arrives), and on manual -dispatch. +host over SSH. + +The build runs on every pull request against `master`, so a broken site is +caught before merge. The deploy step is skipped there and only runs for pushes +to `master`, the daily schedule (so posts dated in the future get published once +their date arrives), and manual dispatches. + +The deploy rsyncs with `--delete`, so anything under `SSH_PATH` that the build +does not produce is removed from the server. It needs the following Actions secrets: -- 2.52.0