@teambit/ci 1.0.643 → 1.0.644
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{preview-1792680082427.js → preview-1792690941466.js} +1 -1
- package/dist/sync/agents-md.d.ts +50 -0
- package/dist/sync/agents-md.js +172 -0
- package/dist/sync/agents-md.js.map +1 -0
- package/dist/sync/agents-md.spec.d.ts +1 -0
- package/dist/sync/agents-md.spec.js +216 -0
- package/dist/sync/agents-md.spec.js.map +1 -0
- package/dist/sync/agents-sync-section.md +132 -0
- package/dist/sync/init-scaffold.d.ts +5 -2
- package/dist/sync/init-scaffold.js +19 -3
- package/dist/sync/init-scaffold.js.map +1 -1
- package/dist/sync/lane-sync-executor.js +2 -1
- package/dist/sync/lane-sync-executor.js.map +1 -1
- package/dist/sync/lane-sync-executor.spec.js +4 -1
- package/dist/sync/lane-sync-executor.spec.js.map +1 -1
- package/dist/sync/sync-orchestrator.d.ts +3 -2
- package/dist/sync/sync-orchestrator.js +23 -6
- package/dist/sync/sync-orchestrator.js.map +1 -1
- package/package.json +12 -12
- package/sync/agents-md.spec.ts +206 -0
- package/sync/agents-md.ts +146 -0
- package/sync/agents-sync-section.md +132 -0
- package/sync/init-scaffold.ts +20 -10
- package/sync/lane-sync-executor.spec.ts +6 -1
- package/sync/lane-sync-executor.ts +2 -1
- package/sync/sync-orchestrator.ts +22 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_cli","data","require","_fs","_interopRequireDefault","path","_interopRequireWildcard","_bitError","_ci","_git","_syncConfig","_laneSyncExecutor","_mainSyncExecutor","_gitHostProvider","_gitOps","_initScaffold","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty","getOwnPropertyDescriptors","defineProperties","_toPropertyKey","value","configurable","writable","_toPrimitive","Symbol","toPrimitive","TypeError","String","Number","assertCleanForDryRun","dirtyFiles","named","slice","join","BitError","SyncOrchestrator","constructor","deps","sync","opts","init","lane","branch","all","main","dryRun","syncInit","narrower","undefined","selectors","selector","Boolean","winner","cfg","resolveSyncConfig","config","defaultScope","workspace","defaultBranch","ci","getDefaultBranchName","mainLaneName","lanes","getDefaultLaneId","name","statusAtStart","git","status","catch","files","map","file","isNonContentPath","logger","consoleWarning","remoteUrl","remote","provider","gitHost","reason","noGitHostReason","selectGitHostProvider","listGitHostProviders","trim","debug","laneSync","LaneSyncExecutor","mainSync","MainSyncExecutor","checkout","summarizeSync","syncMain","mainSyncBranch","laneName","syncableLaneNameForBranch","skipReason","laneNotSyncableReason","syncLane","hostScope","target","parseLaneTarget","explicitTarget","lines","lanesToSync","errors","listLanesToSync","console","formatTitle","origin","detectedBranch","detectDefaultBranchName","chooseInitDefaultBranch","currentBranchOr","repoRoot","gitRepoRoot","scaffoldRoot","realPath","p","fs","existsSync","realpathSync","wsDir","relative","split","sep","fileOutcomes","scaffoldWorkflowFiles","startsWith","displayPath","abs","fromCwd","process","cwd","isAbsolute","configAdded","ensureSyncConfigBlock","repoHasCommits","raw","then","out","handled","outcome","relativePath","toStage","ignored","isIgnored","changed","renderInitReport","scopeId","ownerRepo","deriveOwnerRepo","originUrl","defaultBranchGuessed","repoRootFromCwd","inGitRepo","configDisplayPath","fallback","current","isValidGitBranchName","wsConfig","getWorkspaceConfig","existing","extension","CiAspect","id","setExtension","mergeIntoExisting","ignoreVersion","write","reasonForChange","laneNameToBranch","shouldSyncLane","JSON","stringify","formatWarningSummary","names","Set","getLanes","add","msg","toString","includes","HALT_SUMMARY_PREFIX","listRemoteBranches","branchToLaneName","message","sort","summary","halted","line","refusals","REFUSED_SUMMARY_PREFIX","exports"],"sources":["sync-orchestrator.ts"],"sourcesContent":["import { formatTitle, formatWarningSummary } from '@teambit/cli';\nimport fs from 'fs';\nimport * as path from 'path';\nimport { BitError } from '@teambit/bit-error';\nimport type { Logger } from '@teambit/logger';\nimport type { Workspace } from '@teambit/workspace';\nimport type { LanesMain } from '@teambit/lanes';\nimport type { CheckoutMain } from '@teambit/checkout';\nimport { CiAspect } from '../ci.aspect';\nimport type { CiMain, CiWorkspaceConfig } from '../ci.main.runtime';\nimport { git } from '../git';\nimport type { CiSyncConfig } from './sync-config';\nimport {\n branchToLaneName,\n isValidGitBranchName,\n laneNameToBranch,\n parseLaneTarget,\n resolveSyncConfig,\n shouldSyncLane,\n syncableLaneNameForBranch,\n} from './sync-config';\nimport { HALT_SUMMARY_PREFIX, REFUSED_SUMMARY_PREFIX, LaneSyncExecutor } from './lane-sync-executor';\nimport { MainSyncExecutor } from './main-sync-executor';\nimport { selectGitHostProvider } from './git-host-provider';\nimport { gitRepoRoot, isNonContentPath, listRemoteBranches } from './git-ops';\nimport { chooseInitDefaultBranch, deriveOwnerRepo, renderInitReport, scaffoldWorkflowFiles } from './init-scaffold';\n\n/**\n * Refuse a `--dry-run` whose plan would be computed by force-checking-out branches over uncommitted\n * work: the main-scope drift is a diff, so the tree IS written before the dry-run return. A dry run\n * promises to write nothing, so it may not discard either — with a clean tree the write-then-restore\n * loses nothing.\n */\nexport function assertCleanForDryRun(dirtyFiles: string[]): void {\n if (!dirtyFiles.length) return;\n const named = `${dirtyFiles.slice(0, 10).join(', ')}${dirtyFiles.length > 10 ? ', …' : ''}`;\n throw new BitError(\n `bit ci sync --dry-run refuses to run: the working tree has ${dirtyFiles.length} uncommitted change(s), ` +\n `and computing the plan force-checkouts branches and removes untracked files, which would discard ` +\n `them. Commit or stash them first: ${named}`\n );\n}\n\n/** Everything the sync orchestration needs from `CiMain`, passed explicitly. */\nexport type SyncOrchestratorDeps = {\n ci: CiMain;\n workspace: Workspace;\n logger: Logger;\n lanes: LanesMain;\n checkout: CheckoutMain;\n config: CiWorkspaceConfig;\n};\n\n/**\n * Routing and aggregation for `bit ci sync`: decides which targets a run visits and how their\n * summaries combine. What reconciling a target means lives in the two executors, both stateless and\n * idempotent, so the trigger only ever decides when the reconciler runs.\n */\nexport class SyncOrchestrator {\n constructor(private deps: SyncOrchestratorDeps) {}\n\n /**\n * `bit ci sync` — reconcile Bit lanes and the main scope with git branches and pull requests.\n * Returns the per-target summary lines; throws the joined summary after the loop when any target\n * halted or was refused, so CI exits non-zero while every other target was still attempted. A skip\n * is neither — it reports itself and leaves the run green.\n */\n async sync(\n opts: { lane?: string; branch?: string; all?: boolean; main?: boolean; dryRun?: boolean; init?: boolean } = {}\n ): Promise<string> {\n if (opts.init) {\n if (opts.lane || opts.branch || opts.all || opts.main || opts.dryRun) {\n throw new BitError(\n 'bit ci sync --init cannot be combined with a lane argument, --branch, --all, --main or ' +\n '--dry-run: it only scaffolds onboarding files (workflows + workspace.jsonc config) and exits ' +\n '— it never reconciles'\n );\n }\n return this.syncInit();\n }\n\n // Refuse contradictory flag combinations rather than silently letting one target win.\n const narrower = opts.lane\n ? `a lane argument (\"${opts.lane}\")`\n : (opts.branch && `--branch (\"${opts.branch}\")`) || (opts.main && '--main') || undefined;\n if (opts.all && narrower) {\n throw new BitError(\n `--all cannot be combined with ${narrower}: --all reconciles every mapped lane plus the main ` +\n `scope, and is what runs when no target is given`\n );\n }\n\n // A lane argument, `--branch` and `--main` each select the single target; any two contradict.\n const selectors = [\n opts.lane && `a lane argument (\"${opts.lane}\")`,\n opts.branch && `--branch (\"${opts.branch}\")`,\n opts.main && '--main',\n ].filter((selector): selector is string => Boolean(selector));\n if (selectors.length > 1) {\n const winner = opts.main ? '--main' : `--branch (\"${opts.branch}\")`;\n throw new BitError(\n `${selectors[0]} cannot be combined with ${selectors.slice(1).join(' or with ')}: each selects ` +\n `the single target this run reconciles, and only ${winner} would have run — the rest would be ` +\n `silently dropped, leaving a run that reports success while a target you named was never visited`\n );\n }\n\n const cfg = resolveSyncConfig(this.deps.config.sync);\n const defaultScope = this.deps.workspace.defaultScope;\n const defaultBranch = await this.deps.ci.getDefaultBranchName();\n const mainLaneName = this.deps.lanes.getDefaultLaneId().name;\n\n // The executors force-checkout branches and remove untracked files; warn up front, naming the\n // files at stake, before an interactive run discards anything.\n const statusAtStart = await git.status().catch(() => undefined);\n const dirtyFiles = (statusAtStart?.files ?? []).map((file) => file.path).filter((file) => !isNonContentPath(file));\n if (opts.dryRun) assertCleanForDryRun(dirtyFiles);\n if (dirtyFiles.length) {\n this.deps.logger.consoleWarning(\n `the working tree has ${dirtyFiles.length} uncommitted change(s). \"bit ci sync\" force-checkouts branches ` +\n `and removes untracked files (except .bit/ and node_modules/), so these will be discarded: ` +\n `${dirtyFiles.slice(0, 10).join(', ')}${dirtyFiles.length > 10 ? ', …' : ''}`\n );\n }\n\n const remoteUrl = await git.remote(['get-url', 'origin']).catch(() => undefined);\n const { provider: gitHost, reason: noGitHostReason } = selectGitHostProvider(\n this.deps.ci.listGitHostProviders(),\n typeof remoteUrl === 'string' ? remoteUrl.trim() : undefined\n );\n if (gitHost) this.deps.logger.debug(`bit ci sync: using the \"${gitHost.name}\" git host provider`);\n // Warn once, up front — the executors' per-action lines can only say PRs were skipped, not why.\n else if (noGitHostReason) this.deps.logger.consoleWarning(noGitHostReason);\n\n const laneSync = new LaneSyncExecutor({\n lanes: this.deps.lanes,\n ci: this.deps.ci,\n logger: this.deps.logger,\n gitHost,\n cfg,\n defaultScope,\n });\n const mainSync = new MainSyncExecutor({\n checkout: this.deps.checkout,\n lanes: this.deps.lanes,\n workspace: this.deps.workspace,\n ci: this.deps.ci,\n logger: this.deps.logger,\n gitHost,\n cfg,\n defaultBranch,\n defaultScope,\n });\n\n if (opts.main) {\n return this.summarizeSync([await mainSync.syncMain({ dryRun: opts.dryRun })]);\n }\n\n if (opts.branch) {\n const branch = opts.branch;\n // Under the default `branchPrefix: ''` these two would resolve to the bogus lanes \"main\" /\n // \"bit-sync/main\"; both are reconciled by the main-scope path, never as lanes.\n if (branch === defaultBranch) {\n return `branch ${branch} is the default branch — reconcile it with \"bit ci sync --main\"; nothing to do`;\n }\n if (branch === cfg.mainSyncBranch) {\n return `branch ${branch} is the main sync branch maintained by this command; nothing to do`;\n }\n const laneName = syncableLaneNameForBranch(branch, cfg);\n if (!laneName) return `branch ${branch} does not map to a valid lane name; nothing to do`;\n const skipReason = this.laneNotSyncableReason(laneName, cfg, mainLaneName, defaultBranch);\n if (skipReason) return `${skipReason} (branch ${branch})`;\n // A branch name carries no scope, so this path can only resolve the lane against `defaultScope`;\n // resolving a foreign-hosted lane to the wrong scope is safe (no-op, never a deletion).\n return this.summarizeSync([\n await laneSync.syncLane({ hostScope: defaultScope, name: laneName }, { dryRun: opts.dryRun }),\n ]);\n }\n\n if (opts.lane) {\n // Every guard below is asked about the NAME: \"main\" is not a lane whichever scope hosts it, and\n // the `lanes` patterns match lane names, not lane ids.\n const target = parseLaneTarget(opts.lane, defaultScope);\n const skipReason = this.laneNotSyncableReason(target.name, cfg, mainLaneName, defaultBranch);\n if (skipReason) return skipReason;\n return this.summarizeSync([await laneSync.syncLane(target, { dryRun: opts.dryRun, explicitTarget: true })]);\n }\n\n // `--all` (also the no-arguments default): every mapped lane, then the main scope. Sequential on\n // purpose — the lanes share one workspace and one git checkout.\n const lines: string[] = [];\n const { lanes: lanesToSync, errors } = await this.listLanesToSync(cfg, mainLaneName, defaultBranch);\n lines.push(...errors);\n this.deps.logger.console(\n formatTitle(\n `Reconciling ${lanesToSync.length} mapped lane(s) of ${defaultScope}` +\n `${lanesToSync.length ? `: ${lanesToSync.join(', ')}` : ''}`\n )\n );\n for (const laneName of lanesToSync) {\n // Every enumerated target is hosted on `defaultScope` by construction; foreign-hosted lanes are\n // explicit-target only.\n // oxlint-disable-next-line no-await-in-loop\n lines.push(await laneSync.syncLane({ hostScope: defaultScope, name: laneName }, { dryRun: opts.dryRun }));\n }\n lines.push(await mainSync.syncMain({ dryRun: opts.dryRun }));\n return this.summarizeSync(lines);\n }\n\n /**\n * `bit ci sync --init` — one-command onboarding: scaffolds the two workflow files, adds the sync\n * config block to workspace.jsonc if missing, and returns the report of the steps left. Safe to\n * re-run: existing files are skipped, an existing config block is left alone; it never reconciles.\n */\n private async syncInit(): Promise<string> {\n const remoteUrl = await git.remote(['get-url', 'origin']).catch(() => undefined);\n const origin = typeof remoteUrl === 'string' ? remoteUrl.trim() : undefined;\n // The remote knows the default branch. When it can't answer (no origin, a repository not pushed\n // yet, a server out of reach), guess: the checked-out branch when it's main or master, else main.\n // A feature branch is never the guess: it would go into the workflows' branch filters.\n const detectedBranch = await this.deps.ci.detectDefaultBranchName();\n const defaultBranch = chooseInitDefaultBranch(detectedBranch, await this.currentBranchOr(''));\n\n // Workflows belong to the repository, not the workspace: GitHub only discovers them at\n // `<repo-root>/.github/workflows`, and a bit workspace may be a subdirectory.\n const repoRoot = await gitRepoRoot();\n const scaffoldRoot = repoRoot ?? this.deps.workspace.path;\n if (!repoRoot) {\n this.deps.logger.consoleWarning(\n `could not resolve the git repository root (\"git rev-parse --show-toplevel\" failed — is this a git ` +\n `repository?). Writing the workflow files under the workspace instead: ${scaffoldRoot}. If that is ` +\n `not the repository root, GitHub will not discover them — move .github/workflows there by hand.`\n );\n }\n\n // A workspace below the repository root: the actions must chdir into it (`ws-dir`).\n // Real paths: git reports the root with symlinks resolved (macOS `/tmp` is `/private/tmp`).\n const realPath = (p: string) => (fs.existsSync(p) ? fs.realpathSync(p) : p);\n const wsDir = path.relative(realPath(scaffoldRoot), realPath(this.deps.workspace.path)).split(path.sep).join('/');\n const fileOutcomes = scaffoldWorkflowFiles(\n scaffoldRoot,\n defaultBranch,\n wsDir && !wsDir.startsWith('..') ? wsDir : undefined\n );\n // Report the path relative to where the user is standing (`../../.github/...` from a nested\n // workspace), not to the workspace, so it is right to paste. Absolute only across drives.\n const displayPath = (abs: string) => {\n const fromCwd = path.relative(process.cwd(), abs);\n return fromCwd && !path.isAbsolute(fromCwd) ? fromCwd : abs;\n };\n const configAdded = await this.ensureSyncConfigBlock();\n // No commit yet: the first commit must take the whole workspace, not only the files --init wrote.\n const repoHasCommits = await git\n .raw(['rev-parse', '--verify', '--quiet', 'HEAD'])\n .then((out) => out.trim().length > 0)\n .catch(() => false);\n\n // What step 1 must stage: of the files --init handles, those git shows as new or changed. One that\n // .gitignore matches is listed apart, because `git add` refuses an ignored path named on the command line.\n const handled = [\n ...fileOutcomes.map((outcome) => path.join(scaffoldRoot, outcome.relativePath)),\n path.join(this.deps.workspace.path, 'workspace.jsonc'),\n ];\n const toStage: string[] = [];\n const ignored: string[] = [];\n if (repoRoot) {\n for (const abs of handled) {\n // Ignored first: `git status` hides an ignored file, so it would look unchanged. `check-ignore`\n // skips tracked files and prints the path only when it is ignored (it exits 1 otherwise). It\n // needs no commit, and the first commit's `git add -A` skips an ignored file too.\n // oxlint-disable-next-line no-await-in-loop\n const isIgnored = await git\n .raw(['check-ignore', '--', abs])\n .then((out) => out.trim().length > 0)\n .catch(() => false);\n if (isIgnored) {\n ignored.push(displayPath(abs));\n continue;\n }\n // the first commit stages everything with `git add -A`\n if (!repoHasCommits) continue;\n // oxlint-disable-next-line no-await-in-loop\n const changed = await git\n .raw(['status', '--porcelain', '--untracked-files=all', '--', abs])\n .then((out) => out.trim().length > 0)\n .catch(() => true);\n if (changed) toStage.push(displayPath(abs));\n }\n }\n\n // Returned, not logged: the command prints what `report()` returns.\n return renderInitReport({\n scopeId: this.deps.workspace.defaultScope,\n ownerRepo: deriveOwnerRepo(origin),\n originUrl: origin,\n defaultBranch,\n defaultBranchGuessed: !detectedBranch,\n // the workflows live at the repository root, which may be above the workspace\n repoRootFromCwd: path.relative(process.cwd(), scaffoldRoot) || '.',\n repoHasCommits,\n inGitRepo: Boolean(repoRoot),\n files: fileOutcomes.map((outcome) => ({\n ...outcome,\n displayPath: displayPath(path.join(scaffoldRoot, outcome.relativePath)),\n })),\n configDisplayPath: displayPath(path.join(this.deps.workspace.path, 'workspace.jsonc')),\n configAdded,\n ...(repoRoot ? { toStage, ignored } : {}),\n });\n }\n\n /** The checked-out branch when it is a usable name (not detached, not option-like), else `fallback`. */\n private async currentBranchOr(fallback: string): Promise<string> {\n const current = await git\n .raw(['branch', '--show-current'])\n .then((out) => out.trim())\n .catch(() => '');\n return current && isValidGitBranchName(current) ? current : fallback;\n }\n\n /**\n * Add `\"sync\": {}` under `\"teambit.git/ci\"` in workspace.jsonc if that key isn't there yet; returns\n * whether it wrote. The comment-preserving `WorkspaceConfig` API merges into existing\n * `teambit.git/ci` config rather than clobbering it.\n */\n private async ensureSyncConfigBlock(): Promise<boolean> {\n const wsConfig = this.deps.workspace.getWorkspaceConfig();\n const existing = wsConfig.extension(CiAspect.id, true) as CiWorkspaceConfig | undefined;\n if (existing?.sync) return false;\n wsConfig.setExtension(CiAspect.id, { sync: {} }, { mergeIntoExisting: true, ignoreVersion: true });\n await wsConfig.write({ reasonForChange: 'bit ci sync --init: add the sync config block' });\n return true;\n }\n\n /**\n * Why this lane name must not be handed to the lane executor, or undefined when it's syncable. The\n * mapped branch is checked too — the lane path must never write the two branches the main-scope\n * path owns.\n */\n private laneNotSyncableReason(\n laneName: string,\n cfg: Required<CiSyncConfig>,\n mainLaneName: string,\n defaultBranch: string\n ): string | undefined {\n if (laneName === mainLaneName) {\n return `\"${mainLaneName}\" is not a lane — reconcile the main scope with \"bit ci sync --main\"; nothing to do`;\n }\n const branch = laneNameToBranch(laneName, cfg);\n if (branch === defaultBranch) {\n return (\n `lane ${laneName} maps to the default branch ${branch} — reconcile it with \"bit ci sync --main\"; ` +\n `nothing to do`\n );\n }\n if (branch === cfg.mainSyncBranch) {\n return `lane ${laneName} maps to ${branch}, the main sync branch maintained by this command; nothing to do`;\n }\n if (!shouldSyncLane(laneName, cfg)) {\n return `lane ${laneName} is not matched by the sync config (lanes: ${JSON.stringify(cfg.lanes)}); nothing to do`;\n }\n return undefined;\n }\n\n /**\n * The lane names to reconcile on an `--all` run (sorted), plus one HALTED line per enumeration\n * failure. The list is the union of the remote's lanes AND the lane-mapped branches on `origin` —\n * a lane deleted on bit.cloud is gone from the first source, and only the branch side can make\n * `close-pr` fire for it. An enumeration failure is reported rather than thrown, so the half that\n * did enumerate is still reconciled while the run exits non-zero.\n */\n private async listLanesToSync(\n cfg: Required<CiSyncConfig>,\n mainLaneName: string,\n defaultBranch: string\n ): Promise<{ lanes: string[]; errors: string[] }> {\n if (!cfg.lanes.length) {\n this.deps.logger.console(\n formatWarningSummary('sync.lanes is empty — lane mirroring is disabled, reconciling the main scope only')\n );\n return { lanes: [], errors: [] };\n }\n const errors: string[] = [];\n const names = new Set<string>();\n const remote = this.deps.workspace.defaultScope;\n\n try {\n const lanes = await this.deps.lanes.getLanes({ remote });\n lanes.forEach((lane) => {\n const name = lane.id?.name ?? lane.name;\n if (name) names.add(name);\n });\n } catch (e: any) {\n const msg = e?.toString() ?? '';\n // A scope with no lanes at all: the remote answers \"not found\" rather than an empty list.\n if (msg.includes('was not found') || msg.includes('not found')) {\n this.deps.logger.console(\n formatWarningSummary(`No lanes found on ${remote} — reconciling lane-mapped branches and the main scope only`)\n );\n } else {\n errors.push(`${HALT_SUMMARY_PREFIX} lanes -> could not list the lanes of ${remote}: ${msg}`);\n }\n }\n\n try {\n for (const branch of await listRemoteBranches()) {\n // Reconciled by the main-scope path, never as lanes — under the default `branchPrefix: ''`\n // they would otherwise resolve to the bogus lanes \"main\" / \"bit-sync/main\".\n if (branch === defaultBranch || branch === cfg.mainSyncBranch) continue;\n // Ordinary developer branches are skipped at debug level, never as a summary line.\n const laneName = syncableLaneNameForBranch(branch, cfg);\n if (!laneName) {\n this.deps.logger.debug(\n `bit ci sync: branch \"${branch}\" does not map to a name any lane could have ` +\n `(mapped to \"${branchToLaneName(branch, cfg) ?? '<not lane-mapped>'}\") — skipping it`\n );\n continue;\n }\n names.add(laneName);\n }\n } catch (e: any) {\n errors.push(\n `${HALT_SUMMARY_PREFIX} lanes -> could not list the branches of \"origin\", so a lane deleted on ` +\n `bit.cloud may have kept an orphan branch and an open PR: ${e?.message || e}`\n );\n }\n\n const lanes = [...names]\n .filter((name) => name !== mainLaneName)\n .filter((name) => shouldSyncLane(name, cfg))\n .sort();\n return { lanes, errors };\n }\n\n /**\n * Join the per-target summary lines, and turn any halt into a non-zero exit — the executors never\n * throw, so this is the single place \"needs a human\" becomes visible to CI. `BitError` rather than\n * `Error`: bit reports a plain `Error` as an internal failure (stack trace, Sentry FATAL).\n */\n private summarizeSync(lines: string[]): string {\n const summary = lines.join('\\n');\n const halted = lines.filter((line) => line.startsWith(HALT_SUMMARY_PREFIX));\n if (halted.length) {\n throw new BitError(`bit ci sync could not reconcile ${halted.length} target(s):\\n${summary}`);\n }\n // A refusal is not a halt: the repository is healthy, the reconciler simply will not do what was\n // asked — exit non-zero saying that, rather than reporting a sync conflict.\n const refusals = lines.filter((line) => line.startsWith(REFUSED_SUMMARY_PREFIX));\n if (refusals.length) {\n throw new BitError(refusals.map((line) => line.slice(REFUSED_SUMMARY_PREFIX.length).trim()).join('\\n'));\n }\n return summary;\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"names":["_cli","data","require","_fs","_interopRequireDefault","path","_interopRequireWildcard","_bitError","_ci","_git","_syncConfig","_laneSyncExecutor","_mainSyncExecutor","_gitHostProvider","_gitOps","_initScaffold","_agentsMd","e","t","WeakMap","r","n","__esModule","o","i","f","__proto__","default","has","get","set","hasOwnProperty","call","Object","defineProperty","getOwnPropertyDescriptor","ownKeys","keys","getOwnPropertySymbols","filter","enumerable","push","apply","_objectSpread","arguments","length","forEach","_defineProperty","getOwnPropertyDescriptors","defineProperties","_toPropertyKey","value","configurable","writable","_toPrimitive","Symbol","toPrimitive","TypeError","String","Number","assertCleanForDryRun","dirtyFiles","named","slice","join","BitError","SyncOrchestrator","constructor","deps","sync","opts","init","lane","branch","all","main","dryRun","syncInit","narrower","undefined","selectors","selector","Boolean","winner","cfg","resolveSyncConfig","config","defaultScope","workspace","defaultBranch","ci","getDefaultBranchName","mainLaneName","lanes","getDefaultLaneId","name","statusAtStart","git","status","catch","files","map","file","isNonContentPath","logger","consoleWarning","remoteUrl","remote","provider","gitHost","reason","noGitHostReason","selectGitHostProvider","listGitHostProviders","trim","debug","laneSync","LaneSyncExecutor","mainSync","MainSyncExecutor","checkout","summarizeSync","syncMain","mainSyncBranch","laneName","syncableLaneNameForBranch","skipReason","laneNotSyncableReason","syncLane","hostScope","target","parseLaneTarget","explicitTarget","lines","lanesToSync","errors","listLanesToSync","console","formatTitle","origin","detectedBranch","detectDefaultBranchName","chooseInitDefaultBranch","currentBranchOr","repoRoot","gitRepoRoot","scaffoldRoot","realPath","p","fs","existsSync","realpathSync","wsDir","relative","split","sep","fileOutcomes","scaffoldWorkflowFiles","startsWith","displayPath","abs","fromCwd","process","cwd","isAbsolute","configAdded","ensureSyncConfigBlock","ownerRepo","deriveOwnerRepo","agentsOutcome","scaffoldAgentsMd","scope","repo","host","owner","UNKNOWN_REPO","repoHasCommits","raw","then","out","handled","outcome","relativePath","toStage","ignored","isIgnored","changed","renderInitReport","scopeId","originUrl","defaultBranchGuessed","repoRootFromCwd","inGitRepo","configDisplayPath","fallback","current","isValidGitBranchName","wsConfig","getWorkspaceConfig","existing","extension","CiAspect","id","setExtension","mergeIntoExisting","ignoreVersion","write","reasonForChange","laneNameToBranch","shouldSyncLane","JSON","stringify","formatWarningSummary","names","Set","getLanes","add","msg","toString","includes","HALT_SUMMARY_PREFIX","listRemoteBranches","branchToLaneName","message","sort","summary","halted","line","refusals","REFUSED_SUMMARY_PREFIX","exports"],"sources":["sync-orchestrator.ts"],"sourcesContent":["import { formatTitle, formatWarningSummary } from '@teambit/cli';\nimport fs from 'fs';\nimport * as path from 'path';\nimport { BitError } from '@teambit/bit-error';\nimport type { Logger } from '@teambit/logger';\nimport type { Workspace } from '@teambit/workspace';\nimport type { LanesMain } from '@teambit/lanes';\nimport type { CheckoutMain } from '@teambit/checkout';\nimport { CiAspect } from '../ci.aspect';\nimport type { CiMain, CiWorkspaceConfig } from '../ci.main.runtime';\nimport { git } from '../git';\nimport type { CiSyncConfig } from './sync-config';\nimport {\n branchToLaneName,\n isValidGitBranchName,\n laneNameToBranch,\n parseLaneTarget,\n resolveSyncConfig,\n shouldSyncLane,\n syncableLaneNameForBranch,\n} from './sync-config';\nimport { HALT_SUMMARY_PREFIX, REFUSED_SUMMARY_PREFIX, LaneSyncExecutor } from './lane-sync-executor';\nimport { MainSyncExecutor } from './main-sync-executor';\nimport { selectGitHostProvider } from './git-host-provider';\nimport { gitRepoRoot, isNonContentPath, listRemoteBranches } from './git-ops';\nimport { chooseInitDefaultBranch, deriveOwnerRepo, renderInitReport, scaffoldWorkflowFiles } from './init-scaffold';\nimport { UNKNOWN_REPO, scaffoldAgentsMd } from './agents-md';\n\n/**\n * Refuse a `--dry-run` whose plan would be computed by force-checking-out branches over uncommitted\n * work: the main-scope drift is a diff, so the tree IS written before the dry-run return. A dry run\n * promises to write nothing, so it may not discard either — with a clean tree the write-then-restore\n * loses nothing.\n */\nexport function assertCleanForDryRun(dirtyFiles: string[]): void {\n if (!dirtyFiles.length) return;\n const named = `${dirtyFiles.slice(0, 10).join(', ')}${dirtyFiles.length > 10 ? ', …' : ''}`;\n throw new BitError(\n `bit ci sync --dry-run refuses to run: the working tree has ${dirtyFiles.length} uncommitted change(s), ` +\n `and computing the plan force-checkouts branches and removes untracked files, which would discard ` +\n `them. Commit or stash them first: ${named}`\n );\n}\n\n/** Everything the sync orchestration needs from `CiMain`, passed explicitly. */\nexport type SyncOrchestratorDeps = {\n ci: CiMain;\n workspace: Workspace;\n logger: Logger;\n lanes: LanesMain;\n checkout: CheckoutMain;\n config: CiWorkspaceConfig;\n};\n\n/**\n * Routing and aggregation for `bit ci sync`: decides which targets a run visits and how their\n * summaries combine. What reconciling a target means lives in the two executors, both stateless and\n * idempotent, so the trigger only ever decides when the reconciler runs.\n */\nexport class SyncOrchestrator {\n constructor(private deps: SyncOrchestratorDeps) {}\n\n /**\n * `bit ci sync` — reconcile Bit lanes and the main scope with git branches and pull requests.\n * Returns the per-target summary lines; throws the joined summary after the loop when any target\n * halted or was refused, so CI exits non-zero while every other target was still attempted. A skip\n * is neither — it reports itself and leaves the run green.\n */\n async sync(\n opts: { lane?: string; branch?: string; all?: boolean; main?: boolean; dryRun?: boolean; init?: boolean } = {}\n ): Promise<string> {\n if (opts.init) {\n if (opts.lane || opts.branch || opts.all || opts.main || opts.dryRun) {\n throw new BitError(\n 'bit ci sync --init cannot be combined with a lane argument, --branch, --all, --main or ' +\n '--dry-run: it only scaffolds onboarding files (workflows + workspace.jsonc config) and exits ' +\n '— it never reconciles'\n );\n }\n return this.syncInit();\n }\n\n // Refuse contradictory flag combinations rather than silently letting one target win.\n const narrower = opts.lane\n ? `a lane argument (\"${opts.lane}\")`\n : (opts.branch && `--branch (\"${opts.branch}\")`) || (opts.main && '--main') || undefined;\n if (opts.all && narrower) {\n throw new BitError(\n `--all cannot be combined with ${narrower}: --all reconciles every mapped lane plus the main ` +\n `scope, and is what runs when no target is given`\n );\n }\n\n // A lane argument, `--branch` and `--main` each select the single target; any two contradict.\n const selectors = [\n opts.lane && `a lane argument (\"${opts.lane}\")`,\n opts.branch && `--branch (\"${opts.branch}\")`,\n opts.main && '--main',\n ].filter((selector): selector is string => Boolean(selector));\n if (selectors.length > 1) {\n const winner = opts.main ? '--main' : `--branch (\"${opts.branch}\")`;\n throw new BitError(\n `${selectors[0]} cannot be combined with ${selectors.slice(1).join(' or with ')}: each selects ` +\n `the single target this run reconciles, and only ${winner} would have run — the rest would be ` +\n `silently dropped, leaving a run that reports success while a target you named was never visited`\n );\n }\n\n const cfg = resolveSyncConfig(this.deps.config.sync);\n const defaultScope = this.deps.workspace.defaultScope;\n const defaultBranch = await this.deps.ci.getDefaultBranchName();\n const mainLaneName = this.deps.lanes.getDefaultLaneId().name;\n\n // The executors force-checkout branches and remove untracked files; warn up front, naming the\n // files at stake, before an interactive run discards anything.\n const statusAtStart = await git.status().catch(() => undefined);\n const dirtyFiles = (statusAtStart?.files ?? []).map((file) => file.path).filter((file) => !isNonContentPath(file));\n if (opts.dryRun) assertCleanForDryRun(dirtyFiles);\n if (dirtyFiles.length) {\n this.deps.logger.consoleWarning(\n `the working tree has ${dirtyFiles.length} uncommitted change(s). \"bit ci sync\" force-checkouts branches ` +\n `and removes untracked files (except .bit/ and node_modules/), so these will be discarded: ` +\n `${dirtyFiles.slice(0, 10).join(', ')}${dirtyFiles.length > 10 ? ', …' : ''}`\n );\n }\n\n const remoteUrl = await git.remote(['get-url', 'origin']).catch(() => undefined);\n const { provider: gitHost, reason: noGitHostReason } = selectGitHostProvider(\n this.deps.ci.listGitHostProviders(),\n typeof remoteUrl === 'string' ? remoteUrl.trim() : undefined\n );\n if (gitHost) this.deps.logger.debug(`bit ci sync: using the \"${gitHost.name}\" git host provider`);\n // Warn once, up front — the executors' per-action lines can only say PRs were skipped, not why.\n else if (noGitHostReason) this.deps.logger.consoleWarning(noGitHostReason);\n\n const laneSync = new LaneSyncExecutor({\n lanes: this.deps.lanes,\n ci: this.deps.ci,\n logger: this.deps.logger,\n gitHost,\n cfg,\n defaultScope,\n });\n const mainSync = new MainSyncExecutor({\n checkout: this.deps.checkout,\n lanes: this.deps.lanes,\n workspace: this.deps.workspace,\n ci: this.deps.ci,\n logger: this.deps.logger,\n gitHost,\n cfg,\n defaultBranch,\n defaultScope,\n });\n\n if (opts.main) {\n return this.summarizeSync([await mainSync.syncMain({ dryRun: opts.dryRun })]);\n }\n\n if (opts.branch) {\n const branch = opts.branch;\n // Under the default `branchPrefix: ''` these two would resolve to the bogus lanes \"main\" /\n // \"bit-sync/main\"; both are reconciled by the main-scope path, never as lanes.\n if (branch === defaultBranch) {\n return `branch ${branch} is the default branch — reconcile it with \"bit ci sync --main\"; nothing to do`;\n }\n if (branch === cfg.mainSyncBranch) {\n return `branch ${branch} is the main sync branch maintained by this command; nothing to do`;\n }\n const laneName = syncableLaneNameForBranch(branch, cfg);\n if (!laneName) return `branch ${branch} does not map to a valid lane name; nothing to do`;\n const skipReason = this.laneNotSyncableReason(laneName, cfg, mainLaneName, defaultBranch);\n if (skipReason) return `${skipReason} (branch ${branch})`;\n // A branch name carries no scope, so this path can only resolve the lane against `defaultScope`;\n // resolving a foreign-hosted lane to the wrong scope is safe (no-op, never a deletion).\n return this.summarizeSync([\n await laneSync.syncLane({ hostScope: defaultScope, name: laneName }, { dryRun: opts.dryRun }),\n ]);\n }\n\n if (opts.lane) {\n // Every guard below is asked about the NAME: \"main\" is not a lane whichever scope hosts it, and\n // the `lanes` patterns match lane names, not lane ids.\n const target = parseLaneTarget(opts.lane, defaultScope);\n const skipReason = this.laneNotSyncableReason(target.name, cfg, mainLaneName, defaultBranch);\n if (skipReason) return skipReason;\n return this.summarizeSync([await laneSync.syncLane(target, { dryRun: opts.dryRun, explicitTarget: true })]);\n }\n\n // `--all` (also the no-arguments default): every mapped lane, then the main scope. Sequential on\n // purpose — the lanes share one workspace and one git checkout.\n const lines: string[] = [];\n const { lanes: lanesToSync, errors } = await this.listLanesToSync(cfg, mainLaneName, defaultBranch);\n lines.push(...errors);\n this.deps.logger.console(\n formatTitle(\n `Reconciling ${lanesToSync.length} mapped lane(s) of ${defaultScope}` +\n `${lanesToSync.length ? `: ${lanesToSync.join(', ')}` : ''}`\n )\n );\n for (const laneName of lanesToSync) {\n // Every enumerated target is hosted on `defaultScope` by construction; foreign-hosted lanes are\n // explicit-target only.\n // oxlint-disable-next-line no-await-in-loop\n lines.push(await laneSync.syncLane({ hostScope: defaultScope, name: laneName }, { dryRun: opts.dryRun }));\n }\n lines.push(await mainSync.syncMain({ dryRun: opts.dryRun }));\n return this.summarizeSync(lines);\n }\n\n /**\n * `bit ci sync --init` — one-command onboarding: scaffolds the two workflow files, adds the sync\n * config block to workspace.jsonc if missing, puts the sync rules for coding agents into AGENTS.md,\n * and returns the report of the steps left. Safe to re-run: existing files are skipped, an existing\n * config block or AGENTS.md sync section is left alone; it never reconciles.\n */\n private async syncInit(): Promise<string> {\n const remoteUrl = await git.remote(['get-url', 'origin']).catch(() => undefined);\n const origin = typeof remoteUrl === 'string' ? remoteUrl.trim() : undefined;\n // The remote knows the default branch. When it can't answer (no origin, a repository not pushed\n // yet, a server out of reach), guess: the checked-out branch when it's main or master, else main.\n // A feature branch is never the guess: it would go into the workflows' branch filters.\n const detectedBranch = await this.deps.ci.detectDefaultBranchName();\n const defaultBranch = chooseInitDefaultBranch(detectedBranch, await this.currentBranchOr(''));\n\n // Workflows belong to the repository, not the workspace: GitHub only discovers them at\n // `<repo-root>/.github/workflows`, and a bit workspace may be a subdirectory.\n const repoRoot = await gitRepoRoot();\n const scaffoldRoot = repoRoot ?? this.deps.workspace.path;\n if (!repoRoot) {\n this.deps.logger.consoleWarning(\n `could not resolve the git repository root (\"git rev-parse --show-toplevel\" failed — is this a git ` +\n `repository?). Writing the workflow files under the workspace instead: ${scaffoldRoot}. If that is ` +\n `not the repository root, GitHub will not discover them — move .github/workflows there by hand.`\n );\n }\n\n // A workspace below the repository root: the actions must chdir into it (`ws-dir`).\n // Real paths: git reports the root with symlinks resolved (macOS `/tmp` is `/private/tmp`).\n const realPath = (p: string) => (fs.existsSync(p) ? fs.realpathSync(p) : p);\n const wsDir = path.relative(realPath(scaffoldRoot), realPath(this.deps.workspace.path)).split(path.sep).join('/');\n const fileOutcomes = scaffoldWorkflowFiles(\n scaffoldRoot,\n defaultBranch,\n wsDir && !wsDir.startsWith('..') ? wsDir : undefined\n );\n // Report the path relative to where the user is standing (`../../.github/...` from a nested\n // workspace), not to the workspace, so it is right to paste. Absolute only across drives.\n const displayPath = (abs: string) => {\n const fromCwd = path.relative(process.cwd(), abs);\n return fromCwd && !path.isAbsolute(fromCwd) ? fromCwd : abs;\n };\n const configAdded = await this.ensureSyncConfigBlock();\n // AGENTS.md belongs to the workspace, where agents run bit commands.\n const ownerRepo = deriveOwnerRepo(origin);\n const agentsOutcome = scaffoldAgentsMd(this.deps.workspace.path, {\n scope: this.deps.workspace.defaultScope ?? '<owner>.<scope>',\n repo: ownerRepo\n ? `${ownerRepo.host === 'github.com' ? '' : `${ownerRepo.host}/`}${ownerRepo.owner}/${ownerRepo.repo}`\n : UNKNOWN_REPO,\n defaultBranch,\n });\n // No commit yet: the first commit must take the whole workspace, not only the files --init wrote.\n const repoHasCommits = await git\n .raw(['rev-parse', '--verify', '--quiet', 'HEAD'])\n .then((out) => out.trim().length > 0)\n .catch(() => false);\n\n // What step 1 must stage: of the files --init handles, those git shows as new or changed. One that\n // .gitignore matches is listed apart, because `git add` refuses an ignored path named on the command line.\n const handled = [\n ...fileOutcomes.map((outcome) => path.join(scaffoldRoot, outcome.relativePath)),\n path.join(this.deps.workspace.path, 'workspace.jsonc'),\n path.join(this.deps.workspace.path, agentsOutcome.relativePath),\n ];\n const toStage: string[] = [];\n const ignored: string[] = [];\n if (repoRoot) {\n for (const abs of handled) {\n // Ignored first: `git status` hides an ignored file, so it would look unchanged. `check-ignore`\n // skips tracked files and prints the path only when it is ignored (it exits 1 otherwise). It\n // needs no commit, and the first commit's `git add -A` skips an ignored file too.\n // oxlint-disable-next-line no-await-in-loop\n const isIgnored = await git\n .raw(['check-ignore', '--', abs])\n .then((out) => out.trim().length > 0)\n .catch(() => false);\n if (isIgnored) {\n ignored.push(displayPath(abs));\n continue;\n }\n // the first commit stages everything with `git add -A`\n if (!repoHasCommits) continue;\n // oxlint-disable-next-line no-await-in-loop\n const changed = await git\n .raw(['status', '--porcelain', '--untracked-files=all', '--', abs])\n .then((out) => out.trim().length > 0)\n .catch(() => true);\n if (changed) toStage.push(displayPath(abs));\n }\n }\n\n // Returned, not logged: the command prints what `report()` returns.\n return renderInitReport({\n scopeId: this.deps.workspace.defaultScope,\n ownerRepo,\n originUrl: origin,\n defaultBranch,\n defaultBranchGuessed: !detectedBranch,\n // the workflows live at the repository root, which may be above the workspace\n repoRootFromCwd: path.relative(process.cwd(), scaffoldRoot) || '.',\n repoHasCommits,\n inGitRepo: Boolean(repoRoot),\n files: [\n ...fileOutcomes.map((outcome) => ({\n ...outcome,\n displayPath: displayPath(path.join(scaffoldRoot, outcome.relativePath)),\n })),\n { ...agentsOutcome, displayPath: displayPath(path.join(this.deps.workspace.path, agentsOutcome.relativePath)) },\n ],\n configDisplayPath: displayPath(path.join(this.deps.workspace.path, 'workspace.jsonc')),\n configAdded,\n ...(repoRoot ? { toStage, ignored } : {}),\n });\n }\n\n /** The checked-out branch when it is a usable name (not detached, not option-like), else `fallback`. */\n private async currentBranchOr(fallback: string): Promise<string> {\n const current = await git\n .raw(['branch', '--show-current'])\n .then((out) => out.trim())\n .catch(() => '');\n return current && isValidGitBranchName(current) ? current : fallback;\n }\n\n /**\n * Add `\"sync\": {}` under `\"teambit.git/ci\"` in workspace.jsonc if that key isn't there yet; returns\n * whether it wrote. The comment-preserving `WorkspaceConfig` API merges into existing\n * `teambit.git/ci` config rather than clobbering it.\n */\n private async ensureSyncConfigBlock(): Promise<boolean> {\n const wsConfig = this.deps.workspace.getWorkspaceConfig();\n const existing = wsConfig.extension(CiAspect.id, true) as CiWorkspaceConfig | undefined;\n if (existing?.sync) return false;\n wsConfig.setExtension(CiAspect.id, { sync: {} }, { mergeIntoExisting: true, ignoreVersion: true });\n await wsConfig.write({ reasonForChange: 'bit ci sync --init: add the sync config block' });\n return true;\n }\n\n /**\n * Why this lane name must not be handed to the lane executor, or undefined when it's syncable. The\n * mapped branch is checked too — the lane path must never write the two branches the main-scope\n * path owns.\n */\n private laneNotSyncableReason(\n laneName: string,\n cfg: Required<CiSyncConfig>,\n mainLaneName: string,\n defaultBranch: string\n ): string | undefined {\n if (laneName === mainLaneName) {\n return `\"${mainLaneName}\" is not a lane — reconcile the main scope with \"bit ci sync --main\"; nothing to do`;\n }\n const branch = laneNameToBranch(laneName, cfg);\n if (branch === defaultBranch) {\n return (\n `lane ${laneName} maps to the default branch ${branch} — reconcile it with \"bit ci sync --main\"; ` +\n `nothing to do`\n );\n }\n if (branch === cfg.mainSyncBranch) {\n return `lane ${laneName} maps to ${branch}, the main sync branch maintained by this command; nothing to do`;\n }\n if (!shouldSyncLane(laneName, cfg)) {\n return `lane ${laneName} is not matched by the sync config (lanes: ${JSON.stringify(cfg.lanes)}); nothing to do`;\n }\n return undefined;\n }\n\n /**\n * The lane names to reconcile on an `--all` run (sorted), plus one HALTED line per enumeration\n * failure. The list is the union of the remote's lanes AND the lane-mapped branches on `origin` —\n * a lane deleted on bit.cloud is gone from the first source, and only the branch side can make\n * `close-pr` fire for it. An enumeration failure is reported rather than thrown, so the half that\n * did enumerate is still reconciled while the run exits non-zero.\n */\n private async listLanesToSync(\n cfg: Required<CiSyncConfig>,\n mainLaneName: string,\n defaultBranch: string\n ): Promise<{ lanes: string[]; errors: string[] }> {\n if (!cfg.lanes.length) {\n this.deps.logger.console(\n formatWarningSummary('sync.lanes is empty — lane mirroring is disabled, reconciling the main scope only')\n );\n return { lanes: [], errors: [] };\n }\n const errors: string[] = [];\n const names = new Set<string>();\n const remote = this.deps.workspace.defaultScope;\n\n try {\n const lanes = await this.deps.lanes.getLanes({ remote });\n lanes.forEach((lane) => {\n const name = lane.id?.name ?? lane.name;\n if (name) names.add(name);\n });\n } catch (e: any) {\n const msg = e?.toString() ?? '';\n // A scope with no lanes at all: the remote answers \"not found\" rather than an empty list.\n if (msg.includes('was not found') || msg.includes('not found')) {\n this.deps.logger.console(\n formatWarningSummary(`No lanes found on ${remote} — reconciling lane-mapped branches and the main scope only`)\n );\n } else {\n errors.push(`${HALT_SUMMARY_PREFIX} lanes -> could not list the lanes of ${remote}: ${msg}`);\n }\n }\n\n try {\n for (const branch of await listRemoteBranches()) {\n // Reconciled by the main-scope path, never as lanes — under the default `branchPrefix: ''`\n // they would otherwise resolve to the bogus lanes \"main\" / \"bit-sync/main\".\n if (branch === defaultBranch || branch === cfg.mainSyncBranch) continue;\n // Ordinary developer branches are skipped at debug level, never as a summary line.\n const laneName = syncableLaneNameForBranch(branch, cfg);\n if (!laneName) {\n this.deps.logger.debug(\n `bit ci sync: branch \"${branch}\" does not map to a name any lane could have ` +\n `(mapped to \"${branchToLaneName(branch, cfg) ?? '<not lane-mapped>'}\") — skipping it`\n );\n continue;\n }\n names.add(laneName);\n }\n } catch (e: any) {\n errors.push(\n `${HALT_SUMMARY_PREFIX} lanes -> could not list the branches of \"origin\", so a lane deleted on ` +\n `bit.cloud may have kept an orphan branch and an open PR: ${e?.message || e}`\n );\n }\n\n const lanes = [...names]\n .filter((name) => name !== mainLaneName)\n .filter((name) => shouldSyncLane(name, cfg))\n .sort();\n return { lanes, errors };\n }\n\n /**\n * Join the per-target summary lines, and turn any halt into a non-zero exit — the executors never\n * throw, so this is the single place \"needs a human\" becomes visible to CI. `BitError` rather than\n * `Error`: bit reports a plain `Error` as an internal failure (stack trace, Sentry FATAL).\n */\n private summarizeSync(lines: string[]): string {\n const summary = lines.join('\\n');\n const halted = lines.filter((line) => line.startsWith(HALT_SUMMARY_PREFIX));\n if (halted.length) {\n throw new BitError(`bit ci sync could not reconcile ${halted.length} target(s):\\n${summary}`);\n }\n // A refusal is not a halt: the repository is healthy, the reconciler simply will not do what was\n // asked — exit non-zero saying that, rather than reporting a sync conflict.\n const refusals = lines.filter((line) => line.startsWith(REFUSED_SUMMARY_PREFIX));\n if (refusals.length) {\n throw new BitError(refusals.map((line) => line.slice(REFUSED_SUMMARY_PREFIX.length).trim()).join('\\n'));\n }\n return summary;\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teambit/ci",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.644",
|
|
4
4
|
"homepage": "https://bit.cloud/teambit/git/ci",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"componentId": {
|
|
7
7
|
"scope": "teambit.git",
|
|
8
8
|
"name": "ci",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.644"
|
|
10
10
|
},
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"chalk": "4.1.2",
|
|
@@ -18,32 +18,32 @@
|
|
|
18
18
|
"@teambit/harmony": "0.4.12",
|
|
19
19
|
"@teambit/cli": "0.0.1418",
|
|
20
20
|
"@teambit/logger": "0.0.1500",
|
|
21
|
+
"@teambit/workspace": "1.0.1240",
|
|
22
|
+
"@teambit/builder": "1.0.1240",
|
|
23
|
+
"@teambit/checkout": "1.0.1245",
|
|
21
24
|
"@teambit/component-id": "1.2.5",
|
|
22
25
|
"@teambit/component.modules.merge-helper": "0.0.131",
|
|
23
26
|
"@teambit/component.snap-distance": "0.0.188",
|
|
27
|
+
"@teambit/config-merger": "0.0.1107",
|
|
24
28
|
"@teambit/dependency-resolver": "1.0.1228",
|
|
29
|
+
"@teambit/export": "1.0.1242",
|
|
25
30
|
"@teambit/harmony.modules.concurrency": "0.0.51",
|
|
26
31
|
"@teambit/harmony.modules.runtimes": "0.0.4",
|
|
32
|
+
"@teambit/importer": "1.0.1240",
|
|
27
33
|
"@teambit/lane-id": "0.0.312",
|
|
34
|
+
"@teambit/lanes": "1.0.1266",
|
|
28
35
|
"@teambit/legacy.consumer-component": "0.0.188",
|
|
29
36
|
"@teambit/legacy.scope-api": "0.0.242",
|
|
30
37
|
"@teambit/objects": "0.0.721",
|
|
38
|
+
"@teambit/snapping": "1.0.1243",
|
|
39
|
+
"@teambit/status": "1.0.1270",
|
|
31
40
|
"@teambit/toolbox.promise.map-pool": "0.0.24",
|
|
32
41
|
"@teambit/toolbox.string.random": "0.0.22",
|
|
33
42
|
"@teambit/bit-error": "0.0.404",
|
|
34
43
|
"@teambit/legacy.constants": "0.0.50",
|
|
35
44
|
"@teambit/legacy.scope": "0.0.187",
|
|
36
45
|
"@teambit/legacy.bit-map": "0.0.244",
|
|
37
|
-
"@teambit/toolbox.crypto.sha1": "0.0.24"
|
|
38
|
-
"@teambit/workspace": "1.0.1240",
|
|
39
|
-
"@teambit/builder": "1.0.1240",
|
|
40
|
-
"@teambit/checkout": "1.0.1245",
|
|
41
|
-
"@teambit/config-merger": "0.0.1107",
|
|
42
|
-
"@teambit/export": "1.0.1242",
|
|
43
|
-
"@teambit/importer": "1.0.1240",
|
|
44
|
-
"@teambit/lanes": "1.0.1266",
|
|
45
|
-
"@teambit/snapping": "1.0.1243",
|
|
46
|
-
"@teambit/status": "1.0.1270"
|
|
46
|
+
"@teambit/toolbox.crypto.sha1": "0.0.24"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@types/lodash": "4.14.165",
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import { expect } from 'chai';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import os from 'os';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
import {
|
|
6
|
+
AGENTS_MD_RELATIVE_PATH,
|
|
7
|
+
AGENTS_SECTION_START,
|
|
8
|
+
UNKNOWN_REPO,
|
|
9
|
+
fillInRepo,
|
|
10
|
+
insertAgentsSection,
|
|
11
|
+
renderAgentsSection,
|
|
12
|
+
scaffoldAgentsMd,
|
|
13
|
+
} from './agents-md';
|
|
14
|
+
import { renderInitReport } from './init-scaffold';
|
|
15
|
+
|
|
16
|
+
const VALUES = { scope: 'acme.billing', repo: 'acme/billing', defaultBranch: 'trunk' };
|
|
17
|
+
const SECTION = '<!-- bit-ci-sync:start -->\n\n## Sync\n\nrules\n\n<!-- bit-ci-sync:end -->\n';
|
|
18
|
+
|
|
19
|
+
describe('agents-md', () => {
|
|
20
|
+
describe('renderAgentsSection', () => {
|
|
21
|
+
it('fills in every placeholder', () => {
|
|
22
|
+
const rendered = renderAgentsSection(VALUES);
|
|
23
|
+
expect(rendered).to.not.include('{{');
|
|
24
|
+
expect(rendered).to.include('this repository mirrors `acme.billing`');
|
|
25
|
+
expect(rendered).to.include('gh pr list -R acme/billing --head <lane-name>');
|
|
26
|
+
expect(rendered).to.include('Never push to `trunk`');
|
|
27
|
+
expect(rendered).to.not.include('`main` equals');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it('inserts a branch name with `$` in it verbatim', () => {
|
|
31
|
+
const rendered = renderAgentsSection({ ...VALUES, defaultBranch: "a$'b$&" });
|
|
32
|
+
expect(rendered).to.include("Never push to `a$'b$&`");
|
|
33
|
+
// in a command, the branch is one shell word: `$` does not expand and the quote does not end it
|
|
34
|
+
expect(rendered).to.include(`git switch 'a$'\\''b$&' && git pull`);
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('opens and closes with the markers', () => {
|
|
38
|
+
const rendered = renderAgentsSection(VALUES).trim();
|
|
39
|
+
expect(rendered.startsWith(AGENTS_SECTION_START)).to.equal(true);
|
|
40
|
+
expect(rendered.endsWith('<!-- bit-ci-sync:end -->')).to.equal(true);
|
|
41
|
+
});
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe('insertAgentsSection', () => {
|
|
45
|
+
it('goes after the title and the paragraph under it', () => {
|
|
46
|
+
const existing = '# Bit Workspace\n\nThis file teaches agents.\nRead it fully.\n\n## What is Bit?\n\nBit is…\n';
|
|
47
|
+
expect(insertAgentsSection(existing, SECTION)).to.equal(
|
|
48
|
+
`# Bit Workspace\n\nThis file teaches agents.\nRead it fully.\n\n${SECTION.trim()}\n\n---\n\n## What is Bit?\n\nBit is…\n`
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('goes right after the title when a heading follows it', () => {
|
|
53
|
+
const existing = '# Title\n\n## First\n\ntext\n';
|
|
54
|
+
expect(insertAgentsSection(existing, SECTION)).to.equal(
|
|
55
|
+
`# Title\n\n${SECTION.trim()}\n\n---\n\n## First\n\ntext\n`
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('goes before a numbered list under the title', () => {
|
|
60
|
+
const existing = '# Rules\n\n1. Always submit a change request.\n2. Tag on main.\n';
|
|
61
|
+
expect(insertAgentsSection(existing, SECTION)).to.equal(
|
|
62
|
+
`# Rules\n\n${SECTION.trim()}\n\n---\n\n1. Always submit a change request.\n2. Tag on main.\n`
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('goes before a list that follows the intro paragraph with no blank line', () => {
|
|
67
|
+
const existing = '# Rules\n\nFollow these:\n1) Submit a change request.\n+ Tag on main.\n';
|
|
68
|
+
expect(insertAgentsSection(existing, SECTION)).to.equal(
|
|
69
|
+
`# Rules\n\nFollow these:\n\n${SECTION.trim()}\n\n---\n\n1) Submit a change request.\n+ Tag on main.\n`
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
it('keeps a paragraph line that starts with `#` but is no heading in the intro', () => {
|
|
74
|
+
const existing = '# Rules\n\nTag the PR with\n#not-a-heading for triage.\n\n## More\n';
|
|
75
|
+
expect(insertAgentsSection(existing, SECTION)).to.equal(
|
|
76
|
+
`# Rules\n\nTag the PR with\n#not-a-heading for triage.\n\n${SECTION.trim()}\n\n---\n\n## More\n`
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('finds a title indented by up to three spaces', () => {
|
|
81
|
+
const existing = ' # Title\n\nIntro.\n\n## First\n';
|
|
82
|
+
expect(insertAgentsSection(existing, SECTION)).to.equal(
|
|
83
|
+
` # Title\n\nIntro.\n\n${SECTION.trim()}\n\n---\n\n## First\n`
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('goes at the top of a file with no title', () => {
|
|
88
|
+
const existing = '## Rules\n\n- one\n';
|
|
89
|
+
expect(insertAgentsSection(existing, SECTION)).to.equal(`${SECTION.trim()}\n\n---\n\n## Rules\n\n- one\n`);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it('keeps front matter first', () => {
|
|
93
|
+
const existing = '---\nalwaysApply: true\n---\n\n# Title\n\nIntro.\n';
|
|
94
|
+
expect(insertAgentsSection(existing, SECTION)).to.equal(
|
|
95
|
+
`---\nalwaysApply: true\n---\n\n# Title\n\nIntro.\n\n${SECTION.trim()}\n`
|
|
96
|
+
);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('keeps front matter that closes with `...` first', () => {
|
|
100
|
+
const existing = '---\nalwaysApply: true\n...\n\n# Title\n';
|
|
101
|
+
expect(insertAgentsSection(existing, SECTION)).to.equal(
|
|
102
|
+
`---\nalwaysApply: true\n...\n\n# Title\n\n${SECTION.trim()}\n`
|
|
103
|
+
);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it('fills an empty file', () => {
|
|
107
|
+
expect(insertAgentsSection('', SECTION)).to.equal(`${SECTION.trim()}\n`);
|
|
108
|
+
});
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
describe('fillInRepo', () => {
|
|
112
|
+
const doc = `before ${UNKNOWN_REPO}\n${AGENTS_SECTION_START} -->\nrun -R ${UNKNOWN_REPO}\n<!-- bit-ci-sync:end -->\nafter ${UNKNOWN_REPO}\n`;
|
|
113
|
+
|
|
114
|
+
it('replaces the placeholder inside the section only', () => {
|
|
115
|
+
expect(fillInRepo(doc, 'acme/billing')).to.equal(
|
|
116
|
+
`before ${UNKNOWN_REPO}\n${AGENTS_SECTION_START} -->\nrun -R acme/billing\n<!-- bit-ci-sync:end -->\nafter ${UNKNOWN_REPO}\n`
|
|
117
|
+
);
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
it('changes nothing while the repository is still unknown', () => {
|
|
121
|
+
expect(fillInRepo(doc, UNKNOWN_REPO)).to.equal(doc);
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
describe('scaffoldAgentsMd', () => {
|
|
126
|
+
let workspaceDir: string;
|
|
127
|
+
const agentsPath = () => path.join(workspaceDir, AGENTS_MD_RELATIVE_PATH);
|
|
128
|
+
|
|
129
|
+
beforeEach(() => {
|
|
130
|
+
workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'agents-md-'));
|
|
131
|
+
});
|
|
132
|
+
afterEach(() => {
|
|
133
|
+
fs.rmSync(workspaceDir, { recursive: true, force: true });
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it('creates AGENTS.md when there is none', () => {
|
|
137
|
+
expect(scaffoldAgentsMd(workspaceDir, VALUES)).to.deep.equal({
|
|
138
|
+
relativePath: AGENTS_MD_RELATIVE_PATH,
|
|
139
|
+
status: 'written',
|
|
140
|
+
});
|
|
141
|
+
const written = fs.readFileSync(agentsPath(), 'utf8');
|
|
142
|
+
expect(written.startsWith('# Agent instructions\n\n<!-- bit-ci-sync:start')).to.equal(true);
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
it('adds the section to the top of an existing AGENTS.md and keeps the rest', () => {
|
|
146
|
+
fs.writeFileSync(
|
|
147
|
+
agentsPath(),
|
|
148
|
+
'# Bit Workspace\n\nIntro.\n\n## Saving and Publishing Changes\n\nsubmit a change request\n'
|
|
149
|
+
);
|
|
150
|
+
expect(scaffoldAgentsMd(workspaceDir, VALUES).status).to.equal('updated');
|
|
151
|
+
const updated = fs.readFileSync(agentsPath(), 'utf8');
|
|
152
|
+
expect(updated.indexOf(AGENTS_SECTION_START)).to.be.lessThan(updated.indexOf('## Saving and Publishing'));
|
|
153
|
+
expect(updated).to.include('submit a change request');
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it('fills in the repository on a re-run once origin is known, and changes nothing else', () => {
|
|
157
|
+
scaffoldAgentsMd(workspaceDir, { ...VALUES, repo: UNKNOWN_REPO });
|
|
158
|
+
const first = fs.readFileSync(agentsPath(), 'utf8');
|
|
159
|
+
expect(first).to.include(`gh pr list -R ${UNKNOWN_REPO}`);
|
|
160
|
+
expect(scaffoldAgentsMd(workspaceDir, VALUES)).to.deep.equal({
|
|
161
|
+
relativePath: AGENTS_MD_RELATIVE_PATH,
|
|
162
|
+
status: 'updated',
|
|
163
|
+
note: 'filled in the repository in the sync rules',
|
|
164
|
+
});
|
|
165
|
+
const second = fs.readFileSync(agentsPath(), 'utf8');
|
|
166
|
+
expect(second).to.not.include(UNKNOWN_REPO);
|
|
167
|
+
expect(second).to.include('gh pr list -R acme/billing --head <lane-name>');
|
|
168
|
+
// the examples for other repositories keep their placeholder
|
|
169
|
+
expect(second).to.include('gh repo create <org>/<repo>');
|
|
170
|
+
expect(second.split(UNKNOWN_REPO).join('acme/billing')).to.equal(first.split(UNKNOWN_REPO).join('acme/billing'));
|
|
171
|
+
expect(scaffoldAgentsMd(workspaceDir, VALUES).status).to.equal('skipped');
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
it('leaves a file that already has the section unchanged on a re-run', () => {
|
|
175
|
+
scaffoldAgentsMd(workspaceDir, VALUES);
|
|
176
|
+
const edited = `${fs.readFileSync(agentsPath(), 'utf8')}\nhand edit\n`;
|
|
177
|
+
fs.writeFileSync(agentsPath(), edited);
|
|
178
|
+
expect(scaffoldAgentsMd(workspaceDir, { ...VALUES, scope: 'other.scope' }).status).to.equal('skipped');
|
|
179
|
+
expect(fs.readFileSync(agentsPath(), 'utf8')).to.equal(edited);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe('in the init report', () => {
|
|
184
|
+
const report = (status: 'written' | 'updated' | 'skipped', note?: string) =>
|
|
185
|
+
renderInitReport({
|
|
186
|
+
scopeId: 'acme.billing',
|
|
187
|
+
ownerRepo: { owner: 'acme', repo: 'billing', host: 'github.com' },
|
|
188
|
+
defaultBranch: 'main',
|
|
189
|
+
files: [{ relativePath: AGENTS_MD_RELATIVE_PATH, status, note, displayPath: 'AGENTS.md' }],
|
|
190
|
+
configAdded: true,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it('says what each outcome did', () => {
|
|
194
|
+
expect(report('written')).to.include('tells coding agents how the sync works in this repository');
|
|
195
|
+
expect(report('updated')).to.include('added the sync rules at the top');
|
|
196
|
+
expect(report('skipped')).to.include('already has the sync rules, left unchanged');
|
|
197
|
+
expect(report('updated', 'filled in the repository in the sync rules')).to.include(
|
|
198
|
+
'filled in the repository in the sync rules'
|
|
199
|
+
);
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
it('stages AGENTS.md with the other files', () => {
|
|
203
|
+
expect(report('written')).to.match(/git add -- .*AGENTS\.md/);
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
});
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import type { ScaffoldFileOutcome } from './init-scaffold';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `bit ci sync --init` writes the sync rules for coding agents into AGENTS.md. Agents that work in a
|
|
7
|
+
* mirror must know that review happens on the pull request, that the workflows own the default branch,
|
|
8
|
+
* and how a lane and a branch map to each other. The generic Bit instructions say otherwise (a bit.cloud
|
|
9
|
+
* change request, `bit tag` on main), so the section goes at the top and says that it wins.
|
|
10
|
+
*
|
|
11
|
+
* TEMPLATE SOURCE OF TRUTH: `agents-sync-section.md`, next to this file. The reference repository
|
|
12
|
+
* teambit/acme-modular-store carries the same section, rendered for its scope.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Where `--init` writes the agent instructions, relative to the workspace root. */
|
|
16
|
+
export const AGENTS_MD_RELATIVE_PATH = 'AGENTS.md';
|
|
17
|
+
|
|
18
|
+
/** The marker that opens the section. Its presence means the section is there: a re-run leaves the file alone. */
|
|
19
|
+
export const AGENTS_SECTION_START = '<!-- bit-ci-sync:start';
|
|
20
|
+
|
|
21
|
+
/** The marker that closes the section. */
|
|
22
|
+
export const AGENTS_SECTION_END = '<!-- bit-ci-sync:end -->';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The repository value when `--init` runs before origin is a GitHub remote. It differs from the
|
|
26
|
+
* `<org>/<repo>` examples in the section, so a later run can fill in this one and leave those alone.
|
|
27
|
+
*/
|
|
28
|
+
export const UNKNOWN_REPO = '<org>/<this-repo>';
|
|
29
|
+
|
|
30
|
+
/** The title of an AGENTS.md that `--init` creates. */
|
|
31
|
+
const NEW_FILE_TITLE = '# Agent instructions';
|
|
32
|
+
|
|
33
|
+
export interface AgentsSectionValues {
|
|
34
|
+
/** the scope this repository mirrors, e.g. `acme.billing` */
|
|
35
|
+
scope: string;
|
|
36
|
+
/** the repository as `gh -R` takes it: `owner/repo`, or `host/owner/repo` on GitHub Enterprise Server */
|
|
37
|
+
repo: string;
|
|
38
|
+
/** the repository's default branch, the one the workflows own */
|
|
39
|
+
defaultBranch: string;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The sync section, with the scope, the repository and the default branch filled in. `{{branch-sh}}`
|
|
44
|
+
* is the branch as a shell word, for commands: a git branch name can hold `$` or a quote.
|
|
45
|
+
*/
|
|
46
|
+
export function renderAgentsSection(values: AgentsSectionValues): string {
|
|
47
|
+
const raw = fs.readFileSync(path.join(__dirname, 'agents-sync-section.md'), 'utf8');
|
|
48
|
+
const byKey: Record<string, string> = {
|
|
49
|
+
scope: values.scope,
|
|
50
|
+
repo: values.repo,
|
|
51
|
+
branch: values.defaultBranch,
|
|
52
|
+
'branch-sh': shellWord(values.defaultBranch),
|
|
53
|
+
};
|
|
54
|
+
// A function replacement inserts the value verbatim: `$` is legal in a branch name.
|
|
55
|
+
return raw.replace(/\{\{(scope|repo|branch|branch-sh)\}\}/g, (_match, key: string) => byKey[key]);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* `value` as one POSIX shell word: plain names as they are, anything else single-quoted. The same
|
|
60
|
+
* rule as `shellQuote` in init-scaffold.ts, which imports this module, so it is not imported here.
|
|
61
|
+
*/
|
|
62
|
+
function shellWord(value: string): string {
|
|
63
|
+
return /^[\w./@:+-]+$/.test(value) ? value : `'${value.replace(/'/g, `'\\''`)}'`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Does `line` open a Markdown block other than a paragraph: a heading, a rule, a fence, a comment, a
|
|
68
|
+
* table, a quote, or a bulleted or numbered list item?
|
|
69
|
+
*/
|
|
70
|
+
function startsBlock(line: string): boolean {
|
|
71
|
+
return /^\s*(#{1,6}(\s|$)|---|```|~~~|<!--|\||>|[-*+](\s|$)|\d+[.)](\s|$))/.test(line);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Is `line` a level-one ATX heading? Markdown permits up to three spaces before the `#`. */
|
|
75
|
+
function isTitle(line: string): boolean {
|
|
76
|
+
return /^ {0,3}#(\s|$)/.test(line);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* `existing` with `section` placed after its title and the paragraph under the title, and before
|
|
81
|
+
* everything else. Front matter stays first. A file with no title gets the section at the top.
|
|
82
|
+
*/
|
|
83
|
+
export function insertAgentsSection(existing: string, section: string): string {
|
|
84
|
+
const lines = existing.split('\n');
|
|
85
|
+
let at = 0;
|
|
86
|
+
if (lines[0]?.trim() === '---') {
|
|
87
|
+
// YAML closes a document with `---` or `...`.
|
|
88
|
+
const end = lines.findIndex((line, i) => i > 0 && (line.trim() === '---' || line.trim() === '...'));
|
|
89
|
+
if (end > 0) at = end + 1;
|
|
90
|
+
}
|
|
91
|
+
let next = at;
|
|
92
|
+
while (next < lines.length && !lines[next].trim()) next++;
|
|
93
|
+
if (next < lines.length && isTitle(lines[next])) {
|
|
94
|
+
next++;
|
|
95
|
+
while (next < lines.length && !lines[next].trim()) next++;
|
|
96
|
+
// The paragraph under the title introduces the file; it stays with the title. A list, a heading or
|
|
97
|
+
// another block is content: the section goes before it, so the rules come first.
|
|
98
|
+
if (next < lines.length && !startsBlock(lines[next])) {
|
|
99
|
+
next++;
|
|
100
|
+
while (next < lines.length && lines[next].trim() && !startsBlock(lines[next])) next++;
|
|
101
|
+
}
|
|
102
|
+
at = next;
|
|
103
|
+
}
|
|
104
|
+
const before = lines.slice(0, at).join('\n').trimEnd();
|
|
105
|
+
const after = lines.slice(at).join('\n').trim();
|
|
106
|
+
const parts = [before, section.trim(), ...(after ? ['---', after] : [])].filter(Boolean);
|
|
107
|
+
return `${parts.join('\n\n')}\n`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Write the sync section into `<workspaceDir>/AGENTS.md`. A missing file is created, an existing file
|
|
112
|
+
* gets the section at the top, and a file that already has it is left unchanged, hand edits included.
|
|
113
|
+
* One exception: a section written before the repository was known gets the repository filled in.
|
|
114
|
+
*/
|
|
115
|
+
export function scaffoldAgentsMd(workspaceDir: string, values: AgentsSectionValues): ScaffoldFileOutcome {
|
|
116
|
+
const relativePath = AGENTS_MD_RELATIVE_PATH;
|
|
117
|
+
const absPath = path.join(workspaceDir, relativePath);
|
|
118
|
+
const section = renderAgentsSection(values);
|
|
119
|
+
if (!fs.existsSync(absPath)) {
|
|
120
|
+
fs.writeFileSync(absPath, `${NEW_FILE_TITLE}\n\n${section.trim()}\n`);
|
|
121
|
+
return { relativePath, status: 'written' };
|
|
122
|
+
}
|
|
123
|
+
const existing = fs.readFileSync(absPath, 'utf8');
|
|
124
|
+
if (existing.includes(AGENTS_SECTION_START)) {
|
|
125
|
+
const filled = fillInRepo(existing, values.repo);
|
|
126
|
+
if (filled === existing) return { relativePath, status: 'skipped' };
|
|
127
|
+
fs.writeFileSync(absPath, filled);
|
|
128
|
+
return { relativePath, status: 'updated', note: 'filled in the repository in the sync rules' };
|
|
129
|
+
}
|
|
130
|
+
fs.writeFileSync(absPath, insertAgentsSection(existing, section));
|
|
131
|
+
return { relativePath, status: 'updated' };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* `content` with `UNKNOWN_REPO` replaced by `repo` inside the sync section only. Unchanged when the
|
|
136
|
+
* repository is still unknown, or the section has no placeholder left.
|
|
137
|
+
*/
|
|
138
|
+
export function fillInRepo(content: string, repo: string): string {
|
|
139
|
+
if (repo === UNKNOWN_REPO) return content;
|
|
140
|
+
const start = content.indexOf(AGENTS_SECTION_START);
|
|
141
|
+
const end = content.indexOf(AGENTS_SECTION_END, start);
|
|
142
|
+
if (start < 0 || end < 0) return content;
|
|
143
|
+
const section = content.slice(start, end);
|
|
144
|
+
if (!section.includes(UNKNOWN_REPO)) return content;
|
|
145
|
+
return content.slice(0, start) + section.split(UNKNOWN_REPO).join(repo) + content.slice(end);
|
|
146
|
+
}
|