515 lines · 20.4 KB
import { DurableObject } from "cloudflare:workers";
import { LogSubscribers } from "./log-stream";
import { ensureRunnerContainer, INTERNAL_API_URL } from "../containers/ready";
import { authenticatedRemote } from "../git/artifacts";
import { completeJob, loadJobExecution, markJobStarted, resolveSecrets, mintJobCloneToken, updateStep } from "./jobs";
import { buildJobScript, jobTimeoutCommand, MARKER_NONCE_FILE } from "./script";
import { addMaskValue, declaredNames, maskValues, parseMarker, withAddedMask, withOutput } from "./markers";
import { stepSecretNames } from "./compile";
import { run } from "../db";
import { jobTokenEnv, mintJobToken } from "./job-token";
import { randomId } from "../crypto";
import type { Conclusion } from "~/lib/types";

const POLL_INTERVAL_MS = 1500;
const READ_CHUNK_BYTES = 256 * 1024;
const TOKEN_GRACE_SECONDS = 600;
const SETUP_STEP = -1;
const WORKSPACE = "/workspace";
const SCRIPT_PATH = `${WORKSPACE}/.gitfor-job.sh`;
const LOG_PATH = `${WORKSPACE}/.gitfor-job.log`;
const EXIT_PATH = `${WORKSPACE}/.gitfor-job.exit`;
const GIT_TASK_TIMEOUT_SECONDS = 900;
const GIT_TASK_IDLE_MS = 5 * 60 * 1000;
const MAX_LOG_BYTES = 20 * 1024 * 1024;
const MAX_LINE_CHARS = 16 * 1024;
const LOG_BYTES_KEY = "logBytes";
const MAX_CLOUD_ARTIFACTS = 20;
const MAX_CLOUD_ARTIFACT_BYTES = 1024 * 1024 * 1024;
const MASKS_KEY = "masks";
const MASKING_UNAVAILABLE = "[masking unavailable; line hidden]";
const ARTIFACT_DIR = `${WORKSPACE}/.gitfor/artifacts`;

type JobMeta = {
  jobId: string;
  mode: "cloud" | "external";
  state: "running" | "finalizing" | "done";
  offset: number;
  step: number;
  artifacts: Array<{ name: string; path: string }>;
  conclusion: Conclusion | null;