Skip to content

PushOutput ​

Type, in @jr2/orchestrator/src/sandbox-effect.ts. It is an export of @jr2/orchestrator, on the Authoring surface page, in Effects.

ts
type PushOutput =
  | Exclude<PushWireOutput, { outcome: "pushed" }>
  | (Omit<Extract<PushWireOutput, { outcome: "pushed" }>, "bundle"> & { sync: SyncState; syncReason?: string });

The output of a push Effect: what the onDone of its state gets as event.output. Every outcome is output, so route on outcome:

  • pushed: the remote has the commit. published is the commit on the remote, and source is the Agent's commit that it comes from. They are the same commit, unless the push was signed or squashed. previous is what the remote had before, and unchanged is true when the remote had the commit already. squashed is signed or unsigned when the commit on the remote is one squashed commit. via tells how jr2 found the new commits after a signed push: ancestry, pair, cherry or force.
  • rejected: git or the remote refused the push. stage tells where, reason tells why, and detail has the words of git.
  • diverged: the commit on the remote is not in the history of the Agent's branch, and jr2 could not pair it with a commit there. Nothing was pushed. reason tells why, and published and source name the two commits.
  • unknown: jr2 cannot tell what the push did. reason tells why.

Beside pushed, sync tells what jr2 did to the Agent's branch after the push:

  • synced: the commit on the remote is not the Agent's own, and jr2 moved the branch to the published commits.
  • already: the branch has the published commit already.
  • skipped: the remote has the Agent's own commit, so the branch does not move.
  • busy: a rebase, merge, cherry-pick or revert of the branch is in progress. Nothing changed.
  • not-synced: the branch did not move.

With busy or not-synced, syncReason tells why, and jr2 tries again before the next push.

Forms: it is one of these objects.

  • Form 1: outcome, stage, reason, detail

    • outcome: "rejected"
    • stage: string
    • reason: string
    • detail (optional): string
  • Form 2: outcome, reason, published, source

    • outcome: "diverged"
    • reason: string
    • published: string
    • source: string
  • Form 3: outcome, reason

    • outcome: "unknown"
    • reason: string
  • Form 4: outcome, published, source, previous, via, unchanged, newCommits, squashed, sync, syncReason

    • outcome: "pushed"
    • published: string
    • source: string
    • previous (optional): string
    • via (optional): string
    • unchanged (optional): boolean
    • newCommits (optional): number
    • squashed (optional): "signed" | "unsigned"
    • sync: SyncState
    • syncReason (optional): string

Example

ts
import { fail, jr2Setup, push, type PushOutput, workspace, type Workspaced } from "@jr2/orchestrator";

type Input = Workspaced<{ sha: string }, "app">;

// A push that did not happen (`rejected` or `diverged`) is a different problem from one jr2
// cannot see (`unknown`).
const notPushed = (output: PushOutput): boolean =>
  output.outcome === "rejected" || output.outcome === "diverged";

const body = jr2Setup({
  types: {} as { context: Input; input: Input },
  actors: { publish: push({ pin: true }), fail: fail() },
}).createMachine({
  id: "release",
  context: ({ input }) => input,
  on: { "workspace.lost": ".lost" },
  initial: "publishing",
  states: {
    publishing: {
      invoke: {
        src: "publish",
        input: ({ context }) => ({ sha: context.sha }),
        onDone: [
          { guard: ({ event }) => event.output.outcome === "pushed", target: "published" },
          { guard: ({ event }) => notPushed(event.output), target: "notPushed" },
          { target: "unknown" },
        ],
      },
    },
    published: { type: "final" },
    // Not final states: each one fails the run, with its own reason.
    notPushed: { invoke: { src: "fail", input: { reason: "the remote refused the push" } } },
    unknown: { invoke: { src: "fail", input: { reason: "jr2 cannot tell if the push happened" } } },
    lost: { invoke: { src: "fail", input: { reason: "the Sandbox is gone" } } },
  },
});

export const machine = workspace(body, {
  repos: { app: { url: "https://github.com/you/app.git" } },
  spec: () => ({ branch: "release" }),
});

See also

The docs of Kit version 0.5.1. Each page is also at its .md URL.