Skip to content

ci(fork): build nightly candidates by merging upstream #63

Description

@incognitojam

Context

Fork Nightly currently creates nightly-candidate by rebasing the fork patch stack onto the latest upstream/main. This is appropriate for deliberate maintainer-led maintenance of main, but it makes the automated release candidate a rewritten patch stack and gives the ephemeral workflow ownership of rebase semantics.

During the migration 39 collision, that distinction mattered: the candidate could be mechanically rebased while still requiring a fork-specific compatibility decision before it was safe to release.

The architecture review recommended a hybrid model:

  • Keep main as a deliberate, human-reviewed rebase-maintained patch stack.
  • Build ephemeral nightly candidates by merging the latest upstream/main into the fork head.

A merge will not eliminate source or semantic conflicts, but it preserves both histories and makes the exact upstream integration tested by the nightly auditable as a merge candidate.

Proposed change

Update .github/workflows/fork-nightly.yml so candidate preparation:

  1. Checks out the fork or PR head as it does today.
  2. Fetches the latest upstream/main.
  3. Creates the ephemeral nightly-candidate branch and merges the fetched upstream commit instead of rebasing onto it.
  4. Runs the existing checks, tests, and platform builds against that exact merge candidate.
  5. Promotes the candidate to nightly only after the release succeeds.

The workflow must continue to leave main untouched. Maintaining/rebasing main remains a separate, reviewed operation.

Acceptance criteria

  • Scheduled, manual, and pull-request candidate preparation use the intended merge behavior.
  • A merge conflict fails candidate preparation before nightly-candidate, nightly, or a release is promoted.
  • fork_ref, upstream_ref, candidate SHA, release-note generation, and previous-nightly comparison remain correct.
  • The existing tree-based no-change detection does not publish a duplicate nightly when the effective candidate content is unchanged.
  • dry_run retains its current behavior and never promotes nightly.
  • The ephemeral nightly-candidate ref may still be replaced with --force-with-lease; main must never be force-updated by the workflow.
  • Focused workflow tests or release-smoke coverage exercise the merge path, conflict handling, no-change path, and dry-run path.
  • Contributor or operations documentation clearly distinguishes reviewed rebases of main from automated merge construction of nightly candidates.

Follow-up consideration

The current dry run intentionally leaves an unpublished draft with full artifacts. Decide separately whether successful dry-run drafts should remain for inspection or receive an explicit cleanup mechanism.

When this arose

The question came out of the August 9, 2026 main deployment recorded in the repository activity log:

  • main was force-pushed from 527d79b to 43dc4dd, landing fix(server): separate fork migration history after the reviewed upstream rebase.
  • A normal one-commit push then advanced 43dc4dd...824f160 with fix(web): return resolved draft ids, making Fork CI green before the nightly release.

Those adjacent events made the ownership boundary concrete: maintainers intentionally rewrite the fork patch stack when updating main, while Fork Nightly only needs an auditable, tested integration candidate.

Author metadata correction

The activity-log hashes above identify the events as originally recorded. The two commits were subsequently recreated with identical trees and corrected author metadata:

Current main, nightly, nightly-candidate, and the .126 release tag use the corrected history.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions