diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..20380fc --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,59 @@ +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: + build-and-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 + + # 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 }} + username: ${{ secrets.SSH_USER }} + key: ${{ secrets.SSH_PRIVATE_KEY }} + source: public + target: ${{ secrets.SSH_PATH }} + args: --delete 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..98dd15d 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,34 @@ # 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. + +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: + +| 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` |