# Release Runbook Use this as the quick reference for day-to-day commits, CI checks, releases, and Docker publishing. ## 1) Normal development push Use this flow for regular updates to `main`. ```bash # from repository root git status git add git commit -m "Your message" git push ``` What happens automatically on push to `main`: - Security Audit workflow runs. - Docker image is built and pushed to GHCR. - Docker tags: - `latest` ## 2) Create an official release (ZIP + year-based Docker tag) Use this when you want a downloadable release artifact and a versioned container image. ```bash # from repository root git tag vYYYY.MM.patch git push origin vYYYY.MM.patch ``` What happens automatically on tag `v*`: - Release workflow builds and tests. - GitHub Release is created. - Release assets are uploaded: - `weathernode-deploy.zip` - `weathernode-deploy.zip.sha256` - Docker image is pushed with tag: - `vYYYY.MM.patch` ## 3) Verify published artifacts Release ZIP: - GitHub -> Releases -> latest tag - Confirm both ZIP and `.sha256` files exist Docker: ```bash # replace with your GHCR image path docker pull :latest docker pull :vYYYY.MM.patch ``` After pulling/redeploying a Docker release, verify runtime basics: ```bash docker exec weathernode-app php /var/www/html/artisan about --only=environment curl -I http://:/admin ``` - Ensure `APP_URL` includes scheme + port (for example `http://192.168.1.15:8089`). - Redirect `Location` should keep the same host/port. ## 4) Versioning rule (important) Use the year-based scheme consistently: - Git tags (`v...`) - `VERSION` file - updater comparisons Required format: - `vYYYY.MM.patch` for releases (example: `v2026.03.0`) - optional `-dev` suffix for development builds (example: `v2026.03.0-dev`) Do not mix year-based and semver tags in the same update channel. ## 5) If CI fails Open the failed workflow and copy the first concrete error block, then fix only that root cause. Common examples: - `MissingAppKeyException` during tests -> ensure test APP_KEY is defined. - `manifest.json not found` -> build Vite assets before tests. - Composer lock incompatibility -> ensure CI/Docker PHP version matches lockfile requirements. ## 6) Keep GitHub Free-Tier Storage Under Control Use the `GHCR Cleanup` workflow regularly: - Weekly schedule cleans old GHCR package versions (keeps `latest` and newest year-based tags). - Separate monthly schedule cleans old year-based GitHub Releases. - Safe default is `dry_run=true` when run manually. Recommended manual run settings: - `dry_run=true` first, verify output. - `keep_release_tags=6` - `keep_github_releases=6` - `delete_release_tags=false` (enable only if you intentionally want old git tags deleted too). ## 7) Docker First-Boot Lessons Learned - Generate `APP_KEY` as `base64:` + 32-byte value: - `echo "base64:$(openssl rand -base64 32)"` - If first boot shows write/readonly errors, mounted volume permissions are wrong (`storage`, `bootstrap/cache`, `database`). - If you do not set `ADMIN_EMAIL` / `ADMIN_PASSWORD` in compose, create the first user via `/setup/admin` (only available before any users exist). - Either way the first login opens the two step setup: where the station is, then where its readings come from. Worth walking on a release candidate, since it is the first thing every new user meets. - If `/admin` redirects to the host panel/login on custom ports, `APP_URL` is incomplete or not applied.