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"