diff --git a/action.yml b/action.yml index 94e9f0e..9a3900b 100644 --- a/action.yml +++ b/action.yml @@ -195,31 +195,6 @@ runs: write_fragment "$(printf '%s {\n\timport accesslog\n\troot * /srv/sites/%s\n\tfile_server\n\ttry_files {path} /index.html\n}\n' "$SITE_ADDR" "$DOMAIN")" - # ---- optional install-script subdomain: curl get. | sh ---- - # Opt-in via .env INSTALL_SH= (e.g. install.sh). - # Serves that one file as text/plain at get. (self-managed - # fragment ${SLUG}-get.caddy, separate from the main one). Unset the var - # → the subdomain is removed on the next deploy. Dev must add the DNS - # A-record get. → our IP themselves. - GFRAG="/srv/platform/caddy/sites/${SLUG}-get.caddy" - if [ -n "${INSTALL_SH:-}" ]; then - GDOM="get.${DOMAIN}" - [ -f "/srv/sites/${DOMAIN}/${INSTALL_SH}" ] \ - || echo "::warning::${INSTALL_SH} not in build output — ${GDOM} will 404 until you add public/${INSTALL_SH}" - dig +short A "$GDOM" 2>/dev/null | grep -q "$OUR_IP" \ - || echo "::warning::no A record ${GDOM} → ${OUR_IP} yet — add it; TLS issues once it resolves" - GNEW=$(printf '%s {\n\troot * /srv/sites/%s\n\trewrite * /%s\n\theader Content-Type text/plain\n\tfile_server\n}\n' "$GDOM" "$DOMAIN" "$INSTALL_SH") - if [ ! -f "$GFRAG" ] || [ "$(cat "$GFRAG")" != "$GNEW" ]; then - printf '%s' "$GNEW" > "$GFRAG" - reload_caddy && echo " install subdomain → https://${GDOM} (serves /${INSTALL_SH})" \ - || { echo "::error::caddy reload failed for $GFRAG"; rm -f "$GFRAG"; reload_caddy || true; } - else - echo " install subdomain fragment unchanged" - fi - elif [ -f "$GFRAG" ]; then - rm -f "$GFRAG"; reload_caddy || true; echo " install subdomain removed (INSTALL_SH unset)" - fi - # Remove any prior container LAST — zero-downtime: a pre-existing # container kept serving the domain (via its old fragment) all through # the build above, until the file_server fragment took over just now. @@ -241,16 +216,26 @@ runs: echo "::endgroup::" echo "::group::run container" - # runtime secrets: only keys listed in .env RUNTIME_KEYS, pulled from secrets_json + # Everything in .env (except platform-control keys) is passed straight into + # the container as env vars — the dev keeps config in .env and just pushes, + # nothing to set up by hand. Forgejo Actions secrets via RUNTIME_KEYS still + # work and are layered on top (and override .env on name clash). RTENV="/tmp/runtime.env"; : > "$RTENV" + CTRL=" DOMAIN DEPLOY BUILD_DIR APP_PORT WWW EXTRA_DOMAINS TWITTER TWITTER_URL X INSTALL_SH RUNTIME_KEYS ENABLED " + while IFS='=' read -r k v; do + [ -z "$k" ] && continue + case "$CTRL" in *" $k "*) continue ;; esac + printf '%s=%s\n' "$k" "$v" >> "$RTENV" + done < /tmp/envp RK="${RUNTIME_KEYS:-}" OLDIFS=$IFS; IFS=', ' for key in $RK; do [ -z "$key" ] && continue val=$(printf '%s' "$SJSON" | jq -r --arg k "$key" '.[$k] // empty') - if [ -n "$val" ]; then printf '%s=%s\n' "$key" "$val" >> "$RTENV"; echo " + runtime env: $key"; fi + if [ -n "$val" ]; then printf '%s=%s\n' "$key" "$val" >> "$RTENV"; echo " + secret from Forgejo: $key"; fi done IFS=$OLDIFS + echo " + $(grep -c . "$RTENV" || echo 0) env vars into container (from .env)" set -- --name "$SLUG" --network sites --restart unless-stopped --env-file "$RTENV" \ --label "platform.project=${REPO}" --label "platform.slug=${SLUG}" --label "platform.domain=${DOMAIN}" if [ "$DT" = "docker-db" ]; then @@ -270,4 +255,34 @@ runs: echo "::error::unknown DEPLOY=$DT (use static | docker | docker-db)"; exit 1 ;; esac + # ---- install subdomain (curl get. | sh) — static OR docker ---- + # Opt in via .env INSTALL_SH= (looked up in the repo at root or public/). + # The file is copied to a tiny dir and served as text/plain at get., + # regardless of deploy type. Unset INSTALL_SH → the subdomain is removed. + # Dev adds the DNS A-record get. → our IP themselves. + GFRAG="/srv/platform/caddy/sites/${SLUG}-get.caddy" + GDIR="/srv/sites/.get-${SLUG}" + if [ -n "${INSTALL_SH:-}" ]; then + GDOM="get.${DOMAIN}"; GFILE=$(basename "$INSTALL_SH") + SRC="" + for cand in "/tmp/repo/${INSTALL_SH}" "/tmp/repo/public/${INSTALL_SH}"; do + [ -f "$cand" ] && { SRC="$cand"; break; } + done + rm -rf "$GDIR"; mkdir -p "$GDIR" + if [ -n "$SRC" ]; then cp "$SRC" "$GDIR/$GFILE" + else echo "::warning::${INSTALL_SH} not found in repo (root or public/) — ${GDOM} will 404"; fi + dig +short A "$GDOM" 2>/dev/null | grep -q "$OUR_IP" \ + || echo "::warning::no A record ${GDOM} → ${OUR_IP} yet — add it; TLS issues once it resolves" + GNEW=$(printf '%s {\n\troot * %s\n\trewrite * /%s\n\theader Content-Type text/plain\n\tfile_server\n}\n' "$GDOM" "$GDIR" "$GFILE") + if [ ! -f "$GFRAG" ] || [ "$(cat "$GFRAG")" != "$GNEW" ]; then + printf '%s' "$GNEW" > "$GFRAG" + reload_caddy && echo " install subdomain → https://${GDOM}" \ + || { echo "::error::caddy reload failed for $GFRAG"; rm -f "$GFRAG"; reload_caddy || true; } + else + echo " install subdomain fragment unchanged" + fi + elif [ -f "$GFRAG" ]; then + rm -f "$GFRAG"; rm -rf "$GDIR"; reload_caddy || true; echo " install subdomain removed (INSTALL_SH unset)" + fi + echo "✅ deployed https://${DOMAIN}${ALT:+ + https://$ALT}"