Skip to content

Wire startPushDaemon() in API boot so commits actually propagate to the data remote #37

@themightychris

Description

@themightychris

The gap

The API boot path never calls repo.startPushDaemon(). The deploy plan (PR #35) shipped:

  • The deploy key mounting in Helm
  • GIT_SSH_COMMAND env wiring in the entrypoint
  • Documentation in docs/operations/secrets.md and deploy.md

…but no actual startPushDaemon() call in apps/api/src/store/boot.ts (or anywhere else). So commits made via store.transact land in the local working tree at CFP_DATA_REPO_PATH and are never pushed to CFP_DATA_REMOTE.

This fell between storage-foundation's closeout (which deferred "deploy key wiring" to deploy) and deploy's scope (which focused on container/Helm/CI artifacts).

What to wire

In apps/api/src/store/boot.ts (or a small plugin):

if (env.CFP_DATA_REMOTE) {
  const daemon = await repo.startPushDaemon({
    remote: 'origin',
    branch: env.CFP_DATA_BRANCH ?? 'main',
    backoff: 'exponential',
  });
  // Wire events
  daemon.on('push', ({ commit, durationMs }) => log.info({ commit, durationMs }, 'pushed'));
  daemon.on('retry', ({ attempt, nextDelayMs }) => log.info({ attempt, nextDelayMs }, 'push retry'));
  daemon.on('error', ({ err, attempt, reason }) => {
    if (reason === 'non-fast-forward') {
      log.error({ err: String(err), attempt }, 'push rejected non-fast-forward — manual reconciliation needed');
    } else {
      log.warn({ err: String(err), attempt }, 'push failed');
    }
  });
  // Graceful shutdown on SIGTERM/SIGINT (Fastify onClose hook)
}

NFF detection (gitsheets v1.0.5)

The error handler above already discriminates reason: 'non-fast-forward' from transient errors per PushFailureReason in gitsheets v1.0.5+. On NFF, the daemon won't retry (terminal), and the API should log loud + ideally page somebody (no automated reconciliation in v1).

Acceptance

  • Boot path starts the daemon when CFP_DATA_REMOTE is set
  • A commit produced via store.transact is observed pushed (test against a local bare remote)
  • Daemon stop on SIGTERM (Fastify shutdown hook)
  • NFF rejections are logged with the non-fast-forward reason, no retry spin
  • fastify.pushDaemon.status() exposed via a hidden admin route or just the logs

Out of scope

  • Multi-remote replication (gitsheets internal #157 deferred path is "stop daemon, pull, restart")
  • The actual cluster stand-up + deploy-key generation (that's #36)

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