Deploy Caddyfile to valhalla / deploy (push) Successful in 11s
Runs 137-139 all failed at "cp: can't stat '/dest/Caddyfile/Caddyfile'". The step bound "$PWD/Caddyfile" into an alpine container, but the job workspace is a Docker volume -- the daemon resolved that source on the HOST, found nothing, and created an empty directory there instead (it left a root-owned /workspace/ginnoir/homelabstack/Caddyfile/ on valhalla). So alpine got a directory as its copy source and cp failed, leaving the live Caddyfile stale since run 136. The premise was wrong: act_runner's container.options already binds /config/caddy and /var/run/docker.sock into every job container. Copy straight into the bind and reload through the Docker Engine API over the socket -- which also drops the 40s apt-get install of docker.io. Uses cp rather than mv/install because /config/caddy/Caddyfile is bound into the caddy container as a single file, so the bind follows the inode. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
54 lines
2.2 KiB
YAML
54 lines
2.2 KiB
YAML
name: Deploy Caddyfile to valhalla
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
paths:
|
|
- Caddyfile
|
|
- .gitea/workflows/deploy-caddy.yml
|
|
workflow_dispatch:
|
|
|
|
jobs:
|
|
deploy:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Checkout
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Push Caddyfile and reload Caddy
|
|
run: |
|
|
set -euo pipefail
|
|
|
|
# The runner (act_runner config.yaml `container.options`) binds
|
|
# /config/caddy and /var/run/docker.sock into every job container,
|
|
# so both are already here -- no docker-from-docker, no docker CLI.
|
|
#
|
|
# Do NOT bind $PWD into a `docker run`: the workspace is a Docker
|
|
# volume, so the daemon resolves the source on the HOST, finds
|
|
# nothing, and creates an empty directory there instead. That is
|
|
# what broke runs 137-139.
|
|
#
|
|
# cp (not mv/install): /config/caddy/Caddyfile is bind-mounted into
|
|
# the caddy container as a single FILE, so the bind follows the
|
|
# inode. Replacing the inode would silently detach caddy from it.
|
|
cp Caddyfile /config/caddy/Caddyfile
|
|
|
|
# Reload via the Docker Engine API over the mounted socket.
|
|
SOCK=/var/run/docker.sock
|
|
api() { curl -sS --unix-socket "$SOCK" "$@"; }
|
|
json() { node -e 'let d="";process.stdin.on("data",c=>d+=c).on("end",()=>console.log(JSON.parse(d)[process.argv[1]]))' "$1"; }
|
|
|
|
EXEC_ID=$(api -X POST -H 'Content-Type: application/json' \
|
|
-d '{"AttachStdout":true,"AttachStderr":true,"Cmd":["caddy","reload","--config","/etc/caddy/Caddyfile"]}' \
|
|
"http://localhost/containers/caddy/exec" | json Id)
|
|
|
|
# Strip the stream-multiplexing frame headers from the output.
|
|
api -X POST -H 'Content-Type: application/json' -d '{"Detach":false,"Tty":false}' \
|
|
"http://localhost/exec/$EXEC_ID/start" | tr -d '\000-\010\013\014\016-\037'
|
|
echo
|
|
|
|
# caddy reload validates before applying; a bad Caddyfile fails here.
|
|
CODE=$(api "http://localhost/exec/$EXEC_ID/json" | json ExitCode)
|
|
echo "caddy reload exit code: $CODE"
|
|
exit "$CODE"
|