UNPKG

backport

Version:

A CLI tool that automates the process of backporting commits

170 lines 7.83 kB
import { z } from 'zod'; export const PROJECT_CONFIG_DOCS_LINK = 'https://github.com/sorenlouv/backport/blob/main/docs/configuration.md#project-config-backportrcjson'; export const GLOBAL_CONFIG_DOCS_LINK = 'https://github.com/sorenlouv/backport/blob/main/docs/configuration.md#global-config-backportconfigjson'; // ── Schema helpers ────────────────────────────────────────────────── /** * Target branch choice — either a plain string or an object with name/value/checked. */ const targetBranchChoiceSchema = z.union([ z.string(), z .object({ name: z.string(), value: z.string().optional(), checked: z.boolean().optional(), }) .transform((obj) => ({ ...obj, value: obj.value ?? obj.name })), ]); // ── Core config schema ────────────────────────────────────────────── /** * Schema for options that can appear in config files, module API, or CLI. * This is the single source of truth for option types and defaults. */ export const configOptionsSchema = z.object({ githubToken: z.string().optional(), assignees: z.array(z.string()).default([]), author: z.string().nullable().optional(), autoAssign: z.boolean().default(false), autoFixConflicts: z .custom((val) => typeof val === 'function') .optional(), autoMerge: z.boolean().default(false), autoMergeMethod: z.enum(['merge', 'rebase', 'squash']).default('merge'), backportBinary: z.string().default('backport'), backportBranchName: z.string().optional(), branchLabelMapping: z.record(z.string(), z.string()).optional(), cherryPickRef: z.boolean().default(true), conflictResolution: z.enum(['abort', 'commit', 'theirs']).default('abort'), commitPaths: z.array(z.string()).default([]), copySourcePRLabels: z .union([z.boolean(), z.string(), z.array(z.string())]) .default(false), copySourcePRReviewers: z.boolean().default(false), cwd: z.string().default(process.cwd()), since: z.string().nullable().default(null), until: z.string().nullable().default(null), verbose: z.boolean().default(false), workdir: z.string().optional(), draft: z.boolean().default(false), dryRun: z.boolean().optional(), editor: z.string().optional(), fork: z.boolean().default(true), gitAuthorEmail: z.string().optional(), gitAuthorName: z.string().optional(), gitHostname: z.string().default('github.com'), githubActionRunId: z.number().optional(), githubApiBaseUrlV3: z.string().optional(), githubApiBaseUrlV4: z.string().optional(), globalConfigFile: z.string().optional(), interactive: z.boolean().default(true), logFilePath: z.string().optional(), mainline: z.number().optional(), ls: z.boolean().optional(), maxCount: z.number().default(10), multipleBranches: z.boolean().default(true), multipleCommits: z.boolean().default(false), noVerify: z.boolean().default(true), noUnmergedBackportsHelp: z.boolean().default(false), onlyMissing: z.boolean().optional(), prDescription: z.string().optional(), prQuery: z.string().optional(), prTitle: z.string().optional(), projectConfigFile: z.string().optional(), publishStatusCommentOnAbort: z.boolean().default(false), publishStatusCommentOnFailure: z.boolean().default(false), publishStatusCommentOnSuccess: z.boolean().default(true), pullNumber: z.union([z.number(), z.array(z.number())]).optional(), repoForkOwner: z.string().optional(), repoName: z.string().optional(), repoOwner: z.string().optional(), resetAuthor: z.boolean().default(false), reviewers: z.array(z.string()).default([]), sha: z.union([z.string(), z.array(z.string())]).optional(), signoff: z.boolean().default(false), skipRemoteConfig: z.boolean().optional(), sourceBranch: z.string().optional(), sourcePRLabels: z.array(z.string()).default([]), targetBranchChoices: z.array(targetBranchChoiceSchema).default([]), targetBranches: z.array(z.string()).default([]), targetPRLabels: z.array(z.string()).default([]), }); /** * The default values for all config options, derived from Zod schema. */ export const defaultConfigOptions = configOptionsSchema.parse({}); // ── Config file schema (includes deprecated fields) ───────────────── /** * Extended schema for JSON config files that might contain deprecated fields. * The deprecated fields are stripped during parsing in `read-config-file.ts`. * * IMPORTANT: When adding or removing deprecated fields here, also update * `normalizeDeprecatedOptions()` in `read-config-file.ts` — it handles the * runtime mapping from old keys to new keys. */ export const configFileOptionsSchema = configOptionsSchema.extend({ // yargs options (allowed in configs for passthrough) help: z.boolean().optional(), version: z.boolean().optional(), v: z.boolean().optional(), /** @deprecated Use `githubToken` instead. Kept for backward compatibility. */ accessToken: z.string().optional(), /** @deprecated Replaced by `repoOwner` and `repoName` */ upstream: z.string().optional(), /** @deprecated Replaced by `targetBranchChoices` */ branches: z.array(targetBranchChoiceSchema).optional(), /** @deprecated Replaced by `targetPRLabels` */ labels: z.array(z.string()).optional(), /** @deprecated Replaced by `copySourcePRReviewers` */ addOriginalReviewers: z.boolean().optional(), /** @deprecated Replaced by `conflictResolution: 'commit'` */ commitConflicts: z.boolean().optional(), /** @deprecated Replaced by `conflictResolution: 'theirs'` */ autoResolveConflictsWithTheirs: z.boolean().optional(), /** @deprecated Replaced by `maxCount` */ maxNumber: z.number().optional(), /** @deprecated Replaced by `prQuery` */ prFilter: z.string().optional(), /** @deprecated Replaced by `since` */ dateSince: z.string().optional(), /** @deprecated Replaced by `until` */ dateUntil: z.string().optional(), /** @deprecated Replaced by `workdir` */ dir: z.string().optional(), /** @deprecated Replaced by `cherryPickRef` */ cherrypickRef: z.boolean().optional(), /** @deprecated Replaced by `verbose` */ details: z.boolean().optional(), /** @deprecated Replaced by `author: null` */ all: z.boolean().optional(), }); // ── Valid (fully resolved) options schema ─────────────────────────── /** * Schema for the final validated options that include required fields * resolved during startup (github token, repo info, authenticated user). */ export const validOptionsSchema = configOptionsSchema .extend({ githubToken: z.string().min(1), author: z.string().nullable().default(null), repoName: z.string().min(1), repoOwner: z.string().min(1), repoForkOwner: z.string(), authenticatedUsername: z.string(), sourceBranch: z.string(), isRepoPrivate: z.boolean().optional(), }) // Require target branches unless running in list-only mode (--ls) .superRefine((data, ctx) => { if (!data.ls && data.targetBranches.length === 0 && data.targetBranchChoices.length === 0 && (!data.branchLabelMapping || Object.keys(data.branchLabelMapping).length === 0)) { ctx.addIssue({ code: z.ZodIssueCode.custom, message: `Please specify a target branch: "--branch 6.1".\n\nRead more: ${PROJECT_CONFIG_DOCS_LINK}`, fatal: true, }); } }); //# sourceMappingURL=option-schema.js.map