Skip to content

Nightly releases: test in real use, then promote the tested commit to stable #507

Description

@Jacksondr5

Goal

Adopt upstream's release practice (Jackson, 2026-10-09). Verify a change as far as AI review, screenshots and videos go; merge; publish a nightly from j5/main; run the nightly in real daily work, including multi-server setups that are hard to reproduce in tests; fix what breaks; then cut a stable release from the commit that was tested.

Where J5 is today

The app code J5 carries from upstream already understands a nightly channel, pointed at J5's GitHub releases: j5 update --channel nightly, the installer's channel option, the desktop app's Settings → Update track, the nightly update feed, and "J5 Code (Nightly)" branding. Signing and notarization use the same secrets as stable.

What blocks it:

  • J5 Release accepts only x.y.z and x.y.z-preview.<date>.<n> versions.
  • Versions are committed on throwaway release branches, so a stable release is never the commit that was tested. Upstream stamps the version at build time and promotes the nightly's commit.
  • Nothing publishes from j5/main on a schedule or on demand.
  • A nightly migrates a person's real database one way, and only two specific migrations take a snapshot first. j5 update and desktop app updates take no copy.

Decisions (Jackson, 2026-10-09)

  • Roll forward only. Going back to an older build is an emergency path: restore a snapshot. Supported downgrades are out of scope.
  • Snapshot, no refusal. Take a snapshot before any pending migration. Do not add a refusal to start on a database with unknown migrations: upstream logs and starts, and refusing would be a new divergence. A runbook step covers the deliberate downgrade. If a silent bad downgrade ever bites, offer the refusal upstream (Upstream give-back backlog (hold until V2 merges upstream) #276).
  • Version bump by pull request. After a stable release the bump to j5/main is a PR, not a bot push, so the branch rule stays as it is. It has to merge promptly: until it does, new nightlies sort below the stable just shipped.

Plan, in order

  1. Data safety. Extend the existing snapshot (apps/server/src/j5/persistence/LedgerMigrationSnapshot.ts, called from the seam in apps/server/src/persistence/Sqlite.ts) to run whenever any migration is pending in either lane, named for the version being left, with a cap on how many are kept. Add the rollback steps to the runbook. Ship this in a stable release before any machine takes a nightly.
  2. Callable workflows. Give j5-macos-build.yml and j5-release.yml a workflow_call entry taking a commit and a version, stamp the version in CI with scripts/update-release-package-versions.ts, and make the verify and publish steps channel-aware (J5 Code (Nightly).app, nightly-mac.yml, pre-release, never latest). The manual stable and preview paths keep working.
  3. Nightly workflow. On demand first. Resolve 0.0.(Z+1)-nightly.<date>.<run> from j5/main with upstream's scripts/resolve-nightly-release.ts, then build, archive and publish.
  4. Prove one nightly by hand. Install on a fresh server with the installer's nightly channel; switch an installed server with j5 update --channel nightly and the Mac app with Update track → Nightly; publish a second nightly and confirm both follow it; return both to stable.
  5. Promotion. J5 Release builds a chosen nightly's commit as x.y.z, publishes it as latest, and opens the version-bump PR.
  6. Docs, then a schedule. Runbook, the user docs' channel section, and FORK.md's CI section. Then turn on a daily schedule gated by upstream's .github/scripts/check-nightly-release.cjs (new commits since the last nightly).

Scope notes

  • Stable and nightly share one install, one profile and one database on a machine, switched in place, as upstream's do.
  • Mobile is out. The phone follows its host's channel for server updates, and J5 ships iOS only through a manual TestFlight build.
  • Start with one server and one Mac. A nightly that changes the client-server or peer protocol splits a mixed fleet until every machine moves.
  • Differences from upstream that remain, all in J5-owned workflows: a separate workflow (upstream's also publishes npm, the hosted app, the marketing site and AUR), two platforms, J5's own version line, and the PR for the bump.

To find out along the way

  • Whether GitHub lets the workflow tag a release at a commit j5/main has moved past. Upstream does this; docs/j5/runbooks/macos-packaging.md warns about it. The fallback is to push the tag at the start of the run.
  • How long a snapshot of a 2 GB database adds to startup, and how much disk the retention cap should allow.
  • Whether j5-macos-build.yml and j5-release.yml need the vendored-gitlink cleanup step the other J5 workflows have (neither has run since the upstream advance in feat(j5): advance to upstream main at 29980a3140 #500).

Activity

  1. Jacksondr5 commented on Oct 10, 2026

    @Jacksondr5
    OwnerAuthor

    Correction to step 1. The snapshot does not have to ship in a stable release first. It is taken by the new build at startup, before that build runs its migrations, so it only has to be in the nightly a machine moves to. (The "ship it in a stable first" note applied to the refusal-to-start, which was dropped.) The first nightly after #500 is also covered without it: #500's own migrations already take two targeted snapshots.

    Order after #500 merges (Jackson, 2026-10-09): build the nightly support and one nightly; move Jackson's server and clients to it; land the follow-up issues, which produces the second nightly; test that the server and clients follow it.

  2. Jacksondr5 commented on Oct 10, 2026

    @Jacksondr5
    OwnerAuthor

    Two things from the review of j5/nightly-releases to settle before step 6 (the daily schedule). Neither needs a code change now.

    The installer reads one page of releases; j5 update reads ten. scripts/install.sh finds the newest release of a channel from a single request, releases?per_page=100, while j5 update (packages/shared/src/cliRelease.ts) walks up to ten pages. Once 100 releases are newer than the latest stable, a fresh stable install fails with "could not find a stable release". Before nightlies run daily, either prune old nightly releases or make the installer page.

    What only a real dispatch can prove. The review could not establish these by reading:

    1. Whether GitHub lets the Actions token tag a commit j5/main has moved past.
    2. Whether electron-builder emits only nightly-mac.yml for a nightly version.
    3. Whether the in-place stable-to-nightly app update works across the bundle rename (J5 Code.app to J5 Code (Nightly).app).
    4. Whether the new bash gitlink-cleanup step passes on windows-2025. It now gates stable releases too, through monitors.
    5. Whether the gitlink cleanup is sufficient in the sparse-checkout release job.
    6. How GitHub applies the called workflows' own concurrency groups.

    Posted by Claude Opus 5.5 (Claude Code) while applying the review's findings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions