diff --git a/.github/workflows/compose.yml b/.github/workflows/compose.yml new file mode 100644 index 0000000000..cc90b558c5 --- /dev/null +++ b/.github/workflows/compose.yml @@ -0,0 +1,33 @@ +name: Production Compose + +on: + push: + branches: [main] + paths: + - "deploy/compose/**" + - "prometheus.yml" + - ".github/workflows/compose.yml" + pull_request: + paths: + - "deploy/compose/**" + - "prometheus.yml" + - ".github/workflows/compose.yml" + +permissions: + contents: read + +concurrency: + group: compose-${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: ${{ github.event_name == 'pull_request' }} + +jobs: + validate: + name: Validate production Compose renders + runs-on: ubuntu-24.04 + timeout-minutes: 5 + steps: + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + - name: Check deployment scripts + run: shellcheck deploy/compose/run.sh deploy/compose/test.sh + - name: Render base, TLS, and development stacks + run: deploy/compose/test.sh diff --git a/deploy/compose/README.md b/deploy/compose/README.md index bb0e63fe15..cf2147f804 100644 --- a/deploy/compose/README.md +++ b/deploy/compose/README.md @@ -59,3 +59,13 @@ $EDITOR .env curl -fsS "http://127.0.0.1:$(grep -E '^BUZZ_HTTP_PORT=' .env | cut -d= -f2-)/_liveness" ./run.sh status ``` + +The repository also validates every supported Compose merge without starting +containers: + +```bash +./test.sh +``` + +This renders the base stack, the Caddy/TLS override, and the development +override using only the placeholder values from `.env.example`. diff --git a/deploy/compose/test.sh b/deploy/compose/test.sh new file mode 100755 index 0000000000..73da7507f5 --- /dev/null +++ b/deploy/compose/test.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +WORK_DIR="$(mktemp -d /tmp/buzz-compose-test.XXXXXXXXXX)" + +cleanup() { + case "${WORK_DIR}" in + /tmp/buzz-compose-test.*) rm -rf -- "${WORK_DIR}" ;; + esac +} +trap cleanup EXIT + +install -d "${WORK_DIR}/deploy/compose" +cp \ + "${SCRIPT_DIR}/.env.example" \ + "${SCRIPT_DIR}/Caddyfile" \ + "${SCRIPT_DIR}/compose.yml" \ + "${SCRIPT_DIR}/compose.caddy.yml" \ + "${SCRIPT_DIR}/compose.dev.yml" \ + "${WORK_DIR}/deploy/compose/" +cp "${SCRIPT_DIR}/../../prometheus.yml" "${WORK_DIR}/prometheus.yml" +cp "${SCRIPT_DIR}/.env.example" "${WORK_DIR}/deploy/compose/.env" + +cd "${WORK_DIR}/deploy/compose" + +render() { + local name="$1" + shift + docker compose \ + --env-file .env \ + -f compose.yml \ + "$@" \ + config --quiet + printf 'Validated production Compose render: %s\n' "${name}" +} + +render base +render tls -f compose.caddy.yml +render dev -f compose.dev.yml +render tls-dev -f compose.caddy.yml -f compose.dev.yml