# Register the Pi runner with the label solar-relay:host. # Install the systemd unit and the restricted sudoers rule described in README.md once. name: Deploy Solar Relay on: push: branches: - main workflow_dispatch: jobs: deploy: runs-on: solar-relay env: DEPLOY_PATH: /var/www/html/solar-relay SERVICE: solar-relay.service HEALTH_URL: https://rpioffice.nest.lutran.ch/solar-relay/healthz steps: - name: Checkout uses: actions/checkout@v4 with: persist-credentials: false - name: Check runner and deployment setup shell: bash run: | set -euo pipefail command -v python3 command -v rsync command -v sudo command -v systemctl command -v flock command -v curl python3 -c 'import sys, tomllib; assert sys.version_info >= (3, 11)' test -d "$DEPLOY_PATH" test -w "$DEPLOY_PATH" python3 - <<'PY' import os from pathlib import Path checkout = Path.cwd().resolve() deployment = Path(os.environ['DEPLOY_PATH']).resolve() if checkout == deployment or checkout in deployment.parents or deployment in checkout.parents: raise SystemExit('The runner checkout and deployment directory must not overlap') PY test -r /etc/solar-relay/config.toml cmp deploy/solar-relay.service /etc/systemd/system/solar-relay.service || { echo 'Install the updated deploy/solar-relay.service and run systemctl daemon-reload first.' exit 1 } sudo -n -l "$(command -v systemctl)" restart "$SERVICE" >/dev/null - name: Create isolated test environment run: | python3 -m venv .venv-ci .venv-ci/bin/python -m pip install --only-binary=pyarrow -r requirements.txt - name: Run tests run: .venv-ci/bin/python -m unittest discover -s tests -v - name: Deploy and restart shell: bash run: | set -euo pipefail # Also serializes deployments on Gitea versions that lack workflow concurrency. exec 9>"$DEPLOY_PATH/.deploy.lock" flock -w 120 9 rsync -azc --no-times --delete \ --exclude '/.git/' \ --exclude '/.gitea/' \ --exclude '/.venv/' \ --exclude '/.venv-ci/' \ --exclude '/.deploy.lock' \ --exclude '/config.toml' \ --exclude '/.env' \ --exclude '/data/' \ --exclude '__pycache__/' \ --exclude '*.parquet' \ ./ "$DEPLOY_PATH/" if [ ! -x "$DEPLOY_PATH/.venv/bin/python" ]; then python3 -m venv "$DEPLOY_PATH/.venv" fi "$DEPLOY_PATH/.venv/bin/python" -c 'import sys; assert sys.version_info >= (3, 11)' "$DEPLOY_PATH/.venv/bin/python" -m pip install --only-binary=pyarrow -r "$DEPLOY_PATH/requirements.txt" sudo -n "$(command -v systemctl)" restart "$SERVICE" # Catch an invalid config or missing token that triggers an immediate restart loop. sleep 10 if ! systemctl is-active --quiet "$SERVICE"; then systemctl status "$SERVICE" --no-pager --lines 30 || true exit 1 fi if [ "$(systemctl show --property=NRestarts --value "$SERVICE")" != "0" ]; then echo 'The collector restarted unexpectedly after deployment.' systemctl status "$SERVICE" --no-pager --lines 30 || true exit 1 fi systemctl status "$SERVICE" --no-pager --lines 10 curl --fail --silent --show-error --connect-timeout 3 --max-time 5 \ --retry 4 --retry-delay 2 "$HEALTH_URL"