From 7a3cf5e7a3ca7473a258f9faed4bebd6aca03500 Mon Sep 17 00:00:00 2001 From: Wikid82 Date: Mon, 10 Aug 2026 10:14:50 -0400 Subject: [PATCH 1/6] fix: accept development-branch CI run as proof of nightly health MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit sync-nightly.yml never creates a new commit on nightly — it only fast-forwards or resets nightly to development's exact SHA. That means checking for a completed CI run scoped to branch:nightly misses two real cases: a sync pushed with the GITHUB_TOKEN fallback (doesn't trigger downstream workflows), or nightly already matching development when the sync ran (no push event at all). Either way CI already ran and passed on development for that same SHA, which is equally valid proof. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/promote-nightly-to-main.yml | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/.github/workflows/promote-nightly-to-main.yml b/.github/workflows/promote-nightly-to-main.yml index 1917977..4e455c3 100644 --- a/.github/workflows/promote-nightly-to-main.yml +++ b/.github/workflows/promote-nightly-to-main.yml @@ -61,19 +61,27 @@ jobs: const headSha = branch.commit.sha; core.info(`nightly HEAD: ${headSha}`); - // A few retries in case CI hasn't materialized yet for this exact - // HEAD (e.g. nightly just synced minutes ago). + // sync-nightly.yml never creates a new commit — nightly is always + // either untouched or fast-forwarded/reset to development's exact + // SHA. So a completed CI run on 'development' at this same SHA is + // equally valid proof of health, and covers two gaps in checking + // 'nightly' alone: (1) if nightly was synced with the GITHUB_TOKEN + // fallback (doesn't trigger downstream workflows), CI never ran on + // nightly at all; (2) if nightly already matched development when + // the sync ran, no push happened, so no nightly-branch run exists + // for this SHA even with a trigger token configured. let run = null; for (let attempt = 1; attempt <= 4; attempt += 1) { const { data } = await github.rest.actions.listWorkflowRuns({ owner: context.repo.owner, repo: context.repo.repo, workflow_id: 'ci.yml', - branch: 'nightly', status: 'completed', per_page: 20, }); - run = data.workflow_runs.find((r) => r.head_sha === headSha); + run = data.workflow_runs.find( + (r) => r.head_sha === headSha && (r.head_branch === 'nightly' || r.head_branch === 'development'), + ); if (run) break; core.info(`No completed CI run for nightly HEAD yet (attempt ${attempt}/4), waiting...`); await new Promise((resolve) => setTimeout(resolve, 15000)); From 37490bc5c544dbd015891d854bea232fe07631bf Mon Sep 17 00:00:00 2001 From: Wikid82 Date: Mon, 10 Aug 2026 10:19:49 -0400 Subject: [PATCH 2/6] docs: clarify branching convention for small edits vs CI vs feature work Co-Authored-By: Claude Sonnet 5 --- CLAUDE.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 6fa7f38..3eaec82 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,6 +17,26 @@ asking permission for routine decisions — but flag anything that's a real product or architecture fork in the road (auth approach, data model shape, adding a new external dependency) before just doing it. +## Workflow + +- Do not use git worktrees for work in this repo — work directly on a + branch in the normal checkout. Jeremy likes to build and test the app + himself before merging, and a worktree puts the change somewhere he + isn't already looking. +- Only switch/create a branch for major feature work. Small edits and + fixes happen directly on whatever branch is currently checked out — + don't branch reflexively for every change. Branch (and open a PR) when + something is a real chore that needs build/CI testing before landing. +- CI/workflow changes (`.github/workflows/*`) are committed directly to + `main` for now, since that's the branch CI actually runs on and needs + to reflect immediately — `propagate-main-to-development.yml` carries + them down to `development` automatically. Once the project is more + mature this will switch to normal PRs against `development` like + everything else; ask if it's unclear which regime is current. +- Otherwise, open PRs against `development`, not `main`. `main` is the + release/stable branch; `development` is the integration branch, + periodically synced back into `main`. + ## Product shape - **Users**: parents/admins who can log into a household account remotely, From 9f919f41032a4d9734e1643921c56f55595c08ce Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 14:20:12 +0000 Subject: [PATCH 3/6] chore(main): release hestia 0.2.3 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 949ce4c..0451499 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.2.2" + ".": "0.2.3" } diff --git a/CHANGELOG.md b/CHANGELOG.md index 3bb39de..eb906c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.2.3](https://github.com/Wikid82/hestia/compare/hestia-v0.2.2...hestia-v0.2.3) (2026-08-10) + + +### Bug Fixes + +* accept development-branch CI run as proof of nightly health ([7a3cf5e](https://github.com/Wikid82/hestia/commit/7a3cf5e7a3ca7473a258f9faed4bebd6aca03500)) + ## [0.2.2](https://github.com/Wikid82/hestia/compare/hestia-v0.2.1...hestia-v0.2.2) (2026-08-09) diff --git a/package-lock.json b/package-lock.json index 8dced12..2c3fe80 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "hestia", - "version": "0.2.2", + "version": "0.2.3", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "hestia", - "version": "0.2.2", + "version": "0.2.3", "dependencies": { "better-sqlite3": "^13.0.3", "drizzle-orm": "^0.45.2", diff --git a/package.json b/package.json index 3c5e028..2400bac 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hestia", - "version": "0.2.2", + "version": "0.2.3", "private": true, "type": "module", "scripts": { From 88fa2e337e7e1685bd4dd05cd21c41e522810c3b Mon Sep 17 00:00:00 2001 From: Wikid82 Date: Mon, 10 Aug 2026 11:20:00 -0400 Subject: [PATCH 4/6] fix: retry GHCR and Docker Hub logins on transient denial MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docker-build.yml's merge job failed with "Get \"https://ghcr.io/v2/\": denied: denied" on GHCR login, seconds after the build jobs' identical login succeeded with the same GITHUB_TOKEN — a known GHCR transient denial, not an actual permissions gap. Wrap all three registry logins (build's GHCR, merge's GHCR and Docker Hub) with nick-fields/retry. Co-Authored-By: Claude Sonnet 5 --- .github/workflows/docker-build.yml | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 0b9474d..36ec408 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -119,11 +119,12 @@ jobs: - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4 - name: Log in to GHCR - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4 + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3 with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + max_attempts: 3 + timeout_minutes: 2 + retry_wait_seconds: 10 + command: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - name: Free disk space uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 @@ -203,17 +204,20 @@ jobs: - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4 - name: Log in to GHCR - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4 + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3 with: - registry: ghcr.io - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} + max_attempts: 3 + timeout_minutes: 2 + retry_wait_seconds: 10 + command: echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin - name: Log in to Docker Hub - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4 + uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08 # v3 with: - username: ${{ secrets.DOCKERHUB_USERNAME }} - password: ${{ secrets.DOCKERHUB_TOKEN }} + max_attempts: 3 + timeout_minutes: 2 + retry_wait_seconds: 10 + command: echo "${{ secrets.DOCKERHUB_TOKEN }}" | docker login -u ${{ secrets.DOCKERHUB_USERNAME }} --password-stdin - name: Docker metadata id: meta From 6b0319616b2defa6e9a5bb658159af7189053651 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Aug 2026 15:20:31 +0000 Subject: [PATCH 5/6] chore(main): release hestia 0.2.4 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 11 insertions(+), 4 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 0451499..69535c6 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.2.3" + ".": "0.2.4" } diff --git a/CHANGELOG.md b/CHANGELOG.md index eb906c7..0a880f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [0.2.4](https://github.com/Wikid82/hestia/compare/hestia-v0.2.3...hestia-v0.2.4) (2026-08-10) + + +### Bug Fixes + +* retry GHCR and Docker Hub logins on transient denial ([88fa2e3](https://github.com/Wikid82/hestia/commit/88fa2e337e7e1685bd4dd05cd21c41e522810c3b)) + ## [0.2.3](https://github.com/Wikid82/hestia/compare/hestia-v0.2.2...hestia-v0.2.3) (2026-08-10) diff --git a/package-lock.json b/package-lock.json index 2c3fe80..ac58bfa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "hestia", - "version": "0.2.3", + "version": "0.2.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "hestia", - "version": "0.2.3", + "version": "0.2.4", "dependencies": { "better-sqlite3": "^13.0.3", "drizzle-orm": "^0.45.2", diff --git a/package.json b/package.json index 2400bac..79092b1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "hestia", - "version": "0.2.3", + "version": "0.2.4", "private": true, "type": "module", "scripts": { From eb42806d3f0036c073121c26a601d71f6f36c64c Mon Sep 17 00:00:00 2001 From: Wikid82 Date: Mon, 10 Aug 2026 11:29:50 -0400 Subject: [PATCH 6/6] chore(release): customize release-please PR description --- release-please-config.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/release-please-config.json b/release-please-config.json index 5987c28..e0d7c1a 100644 --- a/release-please-config.json +++ b/release-please-config.json @@ -1,6 +1,8 @@ { "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", "release-type": "node", + "pull-request-header": "Here's what's new in Hestia", + "pull-request-footer": "Merge this PR to cut the release.", "packages": { ".": {} }