hugo: Switch to webhook-based builder

This commit switches Hugo to a webhook-based building process, with
support for Github, Gitlab, and Gitea hooks (including local versions of
Gitea) initially. In addition, Hugo-based sites are now intended to be
served under a single volume, with ingress configuration pointing to
sub-paths into the volume.

Documentation for webhook setup and NGINX proxy configuration is still
underway, and will be filled in later.
This commit is contained in:
Alex Palaistras 2022-10-28 17:47:34 +01:00
parent e637394c12
commit a99e97abfe
9 changed files with 166 additions and 50 deletions

View File

@ -61,3 +61,6 @@ LLDAP_JWT_SECRET=password
LLDAP_ADMIN_EMAIL=admin@localhost
LLDAP_ADMIN_USERNAME=admin
LLDAP_ADMIN_PASSWORD=password
# Configuration for Hugo.
HUGO_DEPLOY_SECRET=password

View File

@ -1,15 +1,25 @@
FROM docker.io/golang:1.19-bullseye AS builder
WORKDIR /build
ENV GOBIN=/build/bin
RUN go install github.com/adnanh/webhook@latest
FROM docker.io/debian:bullseye-slim
ARG VERSION=0.97.2
ARG VERSION=0.104.3
RUN apt-get update -y && apt-get install -y --no-install-recommends \
ca-certificates curl git inotify-tools gosu
ca-certificates curl git gettext gosu openssh-client
ENV PACKAGE_URL https://github.com/gohugoio/hugo/releases/download/v${VERSION}/hugo_${VERSION}_Linux-64bit.tar.gz
RUN curl -L ${PACKAGE_URL} | tar -C /bin --no-same-owner -xvzf - hugo && chmod +x /bin/hugo
RUN curl -L https://github.com/gohugoio/hugo/releases/download/v${VERSION}/hugo_${VERSION}_Linux-64bit.tar.gz | \
tar -C /bin --no-same-owner -xvzf - hugo && chmod +x /bin/hugo
RUN apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false curl
RUN addgroup --system --gid 10000 hugo
RUN adduser --system --uid 10000 --ingroup hugo --no-create-home hugo
COPY --from=builder /build/bin/webhook /bin/webhook
COPY container/config /etc/hugo
COPY container/run-hugo /run-hugo
ENTRYPOINT ["/run-hugo"]

View File

@ -0,0 +1,31 @@
#!/bin/sh
set -eu
GIT_REPO_URL="$1"
GIT_BRANCH="$2"
if test -z "$GIT_REPO_URL"; then
echo "Repository URL not defined, aborting..." >&2
exit 1
elif test -z "$GIT_BRANCH"; then
echo "Branch name not defined, aborting..." >&2
exit 1
fi
GIT_DIR_NAME=$(basename "$GIT_REPO_URL" .git)
GIT_SSH_COMMAND="ssh -o StrictHostKeychecking=no -o UserKnownHostsFile=/dev/null"
for t in rsa ecdsa ed25519; do
GIT_SSH_COMMAND="$GIT_SSH_COMMAND -i /etc/ssh/keys/ssh_host_${t}_key"
done
export GIT_SSH_COMMAND
if test -d "$GIT_DIR_NAME"; then
cd "$GIT_DIR_NAME"
git fetch origin "$GIT_BRANCH"
else
git clone --branch "$GIT_BRANCH" -- "$GIT_REPO_URL" "$GIT_DIR_NAME"
cd "$GIT_DIR_NAME"
fi
hugo --verbose --destination "/build/${GIT_DIR_NAME}"

View File

@ -0,0 +1,76 @@
---
# Webhook for Github.
- id: github
execute-command: /etc/hugo/deploy.sh
command-working-directory: /tmp
include-command-output-in-response: true
include-command-output-in-response-on-error: true
pass-arguments-to-command:
- source: payload
name: repository.ssh_url
- source: string
name: ${HUGO_DEPLOY_BRANCH}
trigger-rule:
and:
- match:
type: payload-hmac-sha256
secret: ${HUGO_DEPLOY_SECRET}
parameter:
source: header
name: X-Hub-Signature-256
- match:
type: value
value: refs/heads/${HUGO_DEPLOY_BRANCH}
parameter:
source: payload
name: ref
# Webhook for Gitea.
- id: gitea
execute-command: /etc/hugo/deploy.sh
command-working-directory: /tmp
include-command-output-in-response: true
include-command-output-in-response-on-error: true
pass-arguments-to-command:
- source: payload
name: repository.ssh_url
- source: string
name: ${HUGO_DEPLOY_BRANCH}
trigger-rule:
and:
- match:
type: payload-hmac-sha256
secret: ${HUGO_DEPLOY_SECRET}
parameter:
source: header
name: X-Hub-Signature-256
- match:
type: value
value: refs/heads/${HUGO_DEPLOY_BRANCH}
parameter:
source: payload
name: ref
# Webhook for Gitlab.
- id: gitlab
execute-command: /etc/hugo/deploy.sh
command-working-directory: /tmp
include-command-output-in-response: true
include-command-output-in-response-on-error: true
pass-arguments-to-command:
- source: payload
name: repository.git_ssh_url
- source: string
name: ${HUGO_DEPLOY_BRANCH}
trigger-rule:
and:
- match:
type: value
value: ${HUGO_DEPLOY_SECRET}
parameter:
source: header
name: X-Gitlab-Token
- match:
type: value
value: refs/heads/${HUGO_DEPLOY_BRANCH}
parameter:
source: payload
name: ref

View File

@ -2,31 +2,19 @@
set -eu
# Set up shared variables.
GIT_REPO="$1"
GIT_BRANCH="$2"
# Generate host keys if none were found.
for t in rsa ecdsa ed25519; do
if test ! -f /etc/ssh/keys/ssh_host_${t}_key; then
ssh-keygen -q -t $t -f /etc/ssh/keys/ssh_host_${t}_key -C '' -N '' > /dev/null
chown hugo:hugo /etc/ssh/keys/ssh_host_${t}_key*
fi
# Ensure correct usage and state.
if test -z "$GIT_REPO"; then
echo "Git repository path is empty, please provide a valid path as the first argument."
exit 1
elif test -z "$GIT_BRANCH"; then
echo "Git branch name is empty, please provide a valid branch name as the second argument."
exit 1
elif test ! -e "/src/${GIT_REPO}/refs/heads/${GIT_BRANCH}"; then
echo "Unable to find HEAD reference for '${GIT_REPO}', branch '${GIT_BRANCH}', is this a valid Git repository?"
exit 2
fi
echo "Host key type '$t' for SSH authentication:"
cat /etc/ssh/keys/ssh_host_${t}_key.pub
done
chown -R hugo:hugo /dest
gosu hugo git clone --quiet --shared --branch "${GIT_BRANCH}" "/src/${GIT_REPO}" /tmp/src
# Create configuration file from collected templates.
envsubst < /etc/hugo/hooks.yaml.template > /etc/hugo/hooks.yaml
# Wait for updates to watched branch for the given site, and build static content anew.
(
cd /tmp/src
while inotifywait -qq --event modify "/src/${GIT_REPO}/refs/heads/${GIT_BRANCH}"; do
gosu hugo git fetch origin "${GIT_BRANCH}" && gosu hugo git reset --hard "${GIT_BRANCH}"
done
) &
gosu hugo hugo --watch --verbose --source /tmp/src --destination /dest
# Run webhook listener for configured hooks.
gosu hugo /bin/webhook -verbose -port 8080 -hooks /etc/hugo/hooks.yaml

View File

@ -0,0 +1,3 @@
# Deploy configuration.
HUGO_DEPLOY_BRANCH=master
HUGO_DEPLOY_SECRET=${HUGO_DEPLOY_SECRET}

View File

@ -6,3 +6,7 @@ storage:
local: service/hugo/
- path: /etc/systemd/system
local: service/hugo/systemd/
systemd:
units:
- name: hugo.service
enabled: true

View File

@ -1,21 +0,0 @@
[Unit]
Description=Hugo Build for Local %I Repository
Wants=container-build@hugo.service container-volume@hugo-build-%i.service git.service
After=container-build@hugo.service container-volume@hugo-build-%i.service git.service
[Service]
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
Restart=on-failure
Environment=PODMAN_SYSTEMD_UNIT=%n
Environment=GIT_REPO=%i.git GIT_BRANCH=master
ExecStart=/bin/podman run --replace --name %p-%i --net internal --sdnotify=conmon \
--volume git:/src:z,ro \
--volume hugo-build-%i:/dest:z \
localhost/hugo:latest $GIT_REPO $GIT_BRANCH
ExecStop=/bin/podman stop --ignore --time 10 %p-%i
ExecStopPost=/bin/podman rm --ignore --force %p-%i
[Install]
WantedBy=multi-user.target

View File

@ -0,0 +1,22 @@
[Unit]
Description=Hugo static site builder
Wants=container-build@%N.service container-volume@%N.service nginx-serve-volume@%N.service
After=container-build@%N.service container-volume@%N.service
Before=nginx-serve-volume@%N.service
[Service]
Type=notify
NotifyAccess=all
SyslogIdentifier=%N
Restart=on-failure
Environment=PODMAN_SYSTEMD_UNIT=%n
ExecStart=/bin/podman run --replace --name %N --net internal --sdnotify=conmon \
--env-file %E/coreos-home-server/%N/%N.env \
--volume %N:/build:z \
--volume %N-ssh:/etc/ssh/keys:z \
localhost/%N:latest
ExecStop=/bin/podman stop --ignore --time 10 %N
ExecStopPost=/bin/podman rm --ignore --force %N
[Install]
WantedBy=multi-user.target