@teambit/ci 1.0.632 → 1.0.634

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.
@@ -298,12 +298,14 @@ function scaffoldWorkflowFiles(workspaceDir, defaultBranch) {
298
298
  function deriveOwnerRepo(remoteUrl) {
299
299
  if (!remoteUrl || !(0, _githubClient().isGitHubRemote)(remoteUrl)) return undefined;
300
300
  const ownerSlashRepo = (0, _githubClient().parseGitHubRepo)(remoteUrl);
301
- if (!ownerSlashRepo) return undefined;
301
+ const host = (0, _githubClient().remoteHost)(remoteUrl);
302
+ if (!ownerSlashRepo || !host) return undefined;
302
303
  const [owner, repo] = ownerSlashRepo.split('/');
303
304
  if (!owner || !repo) return undefined;
304
305
  return {
305
306
  owner,
306
- repo
307
+ repo,
308
+ host
307
309
  };
308
310
  }
309
311
 
@@ -319,8 +321,9 @@ const WEBHOOK_PAYLOAD_TEMPLATE = '{"event_type":"bit-export","client_payload":{"
319
321
  */
320
322
  function renderInitChecklist(ownerRepo) {
321
323
  const repoSegment = ownerRepo ? `${ownerRepo.owner}/${ownerRepo.repo}` : '<owner>/<repo>';
322
- const dispatchUrl = `https://api.github.com/repos/${repoSegment}/dispatches`;
323
- return ['', 'Remaining manual steps (bit ci sync --init only scaffolds files -- these need a human):', '', '1. Secrets -- add in the repository (or org) Settings > Secrets and variables > Actions:', ' - BIT_CONFIG_ACCESS_TOKEN (required): a bit.cloud service-account token with export rights on', " this scope. This account must also be exempt from the org's", ' change-request/merge block -- it is the only identity that merges lanes.', ' - BIT_SYNC_GH_TOKEN (optional): a GitHub PAT or App token. Without it, sync pushes/PRs use the', ' default GITHUB_TOKEN, which does NOT trigger downstream workflow runs (loop-safe, but the', ' sync PR then gets no CI checks).', '', '2. Permissions -- both scaffolded workflows already declare `contents: write` and', ' `pull-requests: write`. Nothing to change unless an org-wide policy overrides workflow-level', ' permissions (e.g. a default of "Read repository contents permission" for the GITHUB_TOKEN).', '', '3. bit.cloud webhook -- create ONE webhook (org Settings > Webhooks) on the "Components > Export', ' succeeded" event:', ` URL: ${dispatchUrl}`, ' Headers: Authorization: Bearer <PAT>', ' Accept: application/vnd.github+json', ' Custom payload template:', ` ${WEBHOOK_PAYLOAD_TEMPLATE}`, ' WARNING: create this webhook fresh -- editing an existing webhook drops its custom headers', ' (known bit.cloud platform bug, verified 2026-07-29). If the URL, headers or template need to', ' change later, delete the webhook and create a new one rather than editing it.', '', '4. Checkout depth -- both scaffolded workflows already check out with `fetch-depth: 0`. This is', ' required: the reconciler reads full git history, and a shallow (--depth=1) clone fails sync', ' safely but uselessly (HALTED, no writes). Keep `fetch-depth: 0` if you customize the workflow.', ' Narrowing the REFSPEC is fine, though -- a single-branch clone is supported, because every', ' fetch sync performs names +refs/heads/*:refs/remotes/origin/* explicitly.', ''].join('\n');
324
+ const api = (0, _githubClient().gitHubApiUrl)(ownerRepo?.host);
325
+ const dispatchUrl = `${'error' in api ? '<GitHub API URL>' : api.url}/repos/${repoSegment}/dispatches`;
326
+ return ['', 'Remaining manual steps (bit ci sync --init only scaffolds files -- these need a human):', '', '1. Secrets -- add in the repository (or org) Settings > Secrets and variables > Actions:', ' - BIT_CONFIG_ACCESS_TOKEN (required): a bit.cloud service-account token with export rights on', " this scope. This account must also be exempt from the org's", ' change-request/merge block -- it is the only identity that merges lanes.', ' - BIT_SYNC_GH_TOKEN (optional): a GitHub PAT or App token. Without it, sync pushes/PRs use the', ' default GITHUB_TOKEN, which does NOT trigger downstream workflow runs (loop-safe, but the', ' sync PR then gets no CI checks).', '', '2. Permissions -- both scaffolded workflows already declare `contents: write` and', ' `pull-requests: write`. Nothing to change unless an org-wide policy overrides workflow-level', ' permissions (e.g. a default of "Read repository contents permission" for the GITHUB_TOKEN).', '', '3. bit.cloud webhook -- create ONE webhook (org Settings > Webhooks) on the "Components > Export', ' succeeded" event:', ` URL: ${dispatchUrl}`, ...('error' in api ? [` (${api.error})`] : []), ' Headers: Authorization: Bearer <PAT>', ' Accept: application/vnd.github+json', ' Custom payload template:', ` ${WEBHOOK_PAYLOAD_TEMPLATE}`, ' WARNING: create this webhook fresh -- editing an existing webhook drops its custom headers', ' (known bit.cloud platform bug, verified 2026-07-29). If the URL, headers or template need to', ' change later, delete the webhook and create a new one rather than editing it.', '', '4. Checkout depth -- both scaffolded workflows already check out with `fetch-depth: 0`. This is', ' required: the reconciler reads full git history, and a shallow (--depth=1) clone fails sync', ' safely but uselessly (HALTED, no writes). Keep `fetch-depth: 0` if you customize the workflow.', ' Narrowing the REFSPEC is fine, though -- a single-branch clone is supported, because every', ' fetch sync performs names +refs/heads/*:refs/remotes/origin/* explicitly.', ''].join('\n');
324
327
  }
325
328
 
326
329
  //# sourceMappingURL=init-scaffold.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_fs","data","_interopRequireDefault","require","_path","_githubClient","e","__esModule","default","WORKFLOW_RELATIVE_PATHS","exports","sync","path","join","release","BIT_SYNC_WORKFLOW_RAW","BIT_RELEASE_WORKFLOW_RAW","DEFAULT_BRANCH_MARKER","yamlSingleQuoted","value","replace","substituteDefaultBranch","raw","marker","defaultBranch","includes","Error","substitutedMarker","renderBitSyncWorkflow","renderBitReleaseWorkflow","writeIfAbsent","workspaceDir","relativePath","content","absPath","fs","existsSync","status","mkdirSync","dirname","recursive","writeFileSync","scaffoldWorkflowFiles","deriveOwnerRepo","remoteUrl","isGitHubRemote","undefined","ownerSlashRepo","parseGitHubRepo","owner","repo","split","WEBHOOK_PAYLOAD_TEMPLATE","renderInitChecklist","ownerRepo","repoSegment","dispatchUrl"],"sources":["init-scaffold.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport { parseGitHubRepo, isGitHubRemote } from './github-client';\n\n/**\n * `bit ci sync --init` — pure scaffolding logic, unit-testable without a live workspace/git checkout.\n *\n * TEMPLATE SOURCE OF TRUTH: `BIT_SYNC_WORKFLOW_RAW` / `BIT_RELEASE_WORKFLOW_RAW` are byte-for-byte\n * copies of the canonical templates in the `bit-git-sync` action workspace\n * (git-sync/git-sync/workflows/templates/) and MUST be kept in sync with them. The ONLY departure is\n * the two `DEFAULT_BRANCH_MARKER` substitution points; everything else — CHANGE-ME comments, the\n * placeholder action ref, `bit-sync/main` config defaults — stays untouched.\n */\n\n/** Where `scaffoldWorkflowFiles` writes each file, relative to the workspace root. */\nexport const WORKFLOW_RELATIVE_PATHS = {\n sync: path.join('.github', 'workflows', 'bit-sync.yml'),\n release: path.join('.github', 'workflows', 'bit-release.yml'),\n} as const;\n\nconst BIT_SYNC_WORKFLOW_RAW = `# Copy this file into your repository at \\`.github/workflows/bit-sync.yml\\`,\n# then review every line marked \\`CHANGE-ME\\` below -- the defaults assume a\n# repository whose default branch is \\`main\\` and a workspace at the repo root.\n#\n# See the \\`workflows.docs.mdx\\` customer setup guide (component\n# bitdev.git-sync/git-sync/workflows) for the full walk-through: the\n# bit.cloud webhook wiring that drives \\`repository_dispatch\\`, the required\n# secrets, and the \\`teambit.git/ci\\`.\\`sync\\` workspace config this workflow\n# acts on.\nname: bit-sync\non:\n repository_dispatch:\n # 'bit-export' is the real, empirically-verified bit.cloud webhook\n # contract: a single dispatch type discriminated by\n # client_payload.laneId (non-empty 'scope/lane' -> lane export, empty ->\n # main export). The other three types are forward-compat aliases the\n # event router also accepts, in case a webhook is configured to send the\n # originally-assumed, more granular dispatch types instead.\n types: [bit-export, bit-lane-export, bit-main-export, bit-lane-removed]\n schedule:\n # Scheduled reconcile. This is also the ONLY mechanism that picks up\n # lane deletions -- bit.cloud has no \"lane removed\" webhook event.\n - cron: '*/30 * * * *'\n push:\n # CHANGE-ME: \\`main\\` must be your repository's DEFAULT branch, and\n # \\`bit-sync/**\\` must cover your configured \\`sync.mainSyncBranch\\`. Pushes\n # to either are bit-sync's own output and must not re-trigger a sync.\n branches-ignore: [main, 'bit-sync/**']\n workflow_dispatch:\n inputs:\n lane: { description: Lane to sync (empty = all), required: false }\n\n# The default GITHUB_TOKEN is READ-ONLY on repositories and organizations\n# created after Feb 2023, and anywhere the org/repo default is set to\n# \"Read repository contents permission\". Sync pushes branches and\n# opens/updates PRs, so both scopes must be declared explicitly -- without\n# this block the sync fails with a 403 on its first write.\npermissions:\n contents: write\n pull-requests: write\n\nconcurrency:\n # Serializes one lane's syncs so two runs never race on the same branch/PR.\n #\n # Each trigger needs a different expression, because the lane identity\n # arrives in a different place every time:\n # - repository_dispatch -> client_payload.laneId ('scope/lane'), or\n # client_payload.lane for the alias types\n # - push -> github.ref_name (the branch)\n # - workflow_dispatch -> the \\`lane\\` input\n # - schedule -> nothing lane-shaped; it reconciles everything\n #\n # github.ref_name is populated on schedule runs too (it is the default\n # branch there), so it may only be consulted AFTER the event name has been\n # checked. Reading it first -- as a bare \\`... || github.ref_name || 'all'\\`\n # chain does -- makes the final fallback unreachable and lumps every cron\n # run into the same group as pushes to the default branch.\n #\n # RESIDUAL RACE (accepted, by design): a webhook run groups as\n # 'scope/my-lane' while a push to that lane's branch groups as 'my-lane', so\n # two runs for the same lane can still overlap across those two triggers.\n # GitHub expressions have no substring/split function, and bit.cloud's\n # webhook payload template exposes only the full laneId, so the two keys\n # cannot be normalized into one here. This is safe rather than merely\n # tolerated: the reconciler is idempotent and the sync executor diffs\n # against converged state, so a second overlapping run finds nothing left to\n # do and no-ops. The concurrency group is an efficiency measure; it is not\n # what makes the sync correct.\n group: >-\n bit-sync-\\${{\n github.event_name == 'repository_dispatch' && (github.event.client_payload.laneId || github.event.client_payload.lane || 'main-export')\n || github.event_name == 'push' && github.ref_name\n || github.event_name == 'workflow_dispatch' && (github.event.inputs.lane || 'reconcile-all')\n || 'reconcile-all' }}\n # Never cancel a sync mid-flight: it may already have pushed a branch and be\n # partway through opening or updating its PR.\n cancel-in-progress: false\n\njobs:\n sync:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n with:\n fetch-depth: 0\n # A PAT/App token so that pushes this workflow makes (e.g. a sync\n # PR branch) can themselves trigger CI. Pushes authenticated with\n # the default GITHUB_TOKEN do NOT trigger other workflow runs.\n token: \\${{ secrets.BIT_SYNC_GH_TOKEN || secrets.GITHUB_TOKEN }}\n - uses: bit-tasks/init@v2\n # Pinned to a commit SHA on purpose: this job holds write permission, and\n # a tag can move. Bump the SHA to take a new version of the action.\n - uses: teambit/bit-git-sync@66c0fdf9e34e45f70b4f397b38b2b01f79dd1f41\n with:\n # CHANGE-ME: keep this in sync with\n # \\`teambit.git/ci\\`.\\`sync.mainSyncBranch\\` in your workspace.jsonc\n # (the action's own default is shown here).\n main-sync-branch: bit-sync/main\n # Uncomment if your workspace.jsonc is NOT at the repository root --\n # the action chdirs here before running anything.\n # ws-dir: packages/my-workspace\n env:\n # Service account token. This account must be EXEMPT from the\n # org's change-request/merge block, or bit.cloud rejects the\n # sync-driven writes.\n BIT_CONFIG_ACCESS_TOKEN: \\${{ secrets.BIT_CONFIG_ACCESS_TOKEN }}\n GITHUB_TOKEN: \\${{ secrets.BIT_SYNC_GH_TOKEN || secrets.GITHUB_TOKEN }}\n # Optional: git identity for the commits the sync creates. Defaults\n # to bit-sync[bot] / bit-sync[bot]@users.noreply.github.com.\n # GIT_USER_NAME: bit-sync[bot]\n # GIT_USER_EMAIL: bit-sync[bot]@users.noreply.github.com\n`;\n\nconst BIT_RELEASE_WORKFLOW_RAW = `# Copy this file into your repository at \\`.github/workflows/bit-release.yml\\`,\n# then review every line marked \\`CHANGE-ME\\` below.\n#\n# See the \\`workflows.docs.mdx\\` customer setup guide (component\n# bitdev.git-sync/git-sync/workflows) for the full walk-through.\nname: bit-release\non:\n pull_request:\n types: [closed]\n # CHANGE-ME: your repository's DEFAULT branch. \\`bit ci merge\\` releases\n # from the default branch, so only PRs merged INTO it should trigger a\n # release -- a stacked PR landing on another feature branch has not\n # reached the default branch yet. The action's event router enforces the\n # same rule from \\`pull_request.base.ref\\`; this filter means a run is never\n # even queued for a non-default base.\n branches: [main]\n\n# The default GITHUB_TOKEN is READ-ONLY on repositories and organizations\n# created after Feb 2023, and anywhere the org/repo default is set to\n# \"Read repository contents permission\". The release run pushes commits/tags\n# and updates PRs, so both scopes must be declared explicitly.\npermissions:\n contents: write\n pull-requests: write\n\nconcurrency:\n group: bit-release-\\${{ github.event.pull_request.number }}\n # Never cancel a release mid-flight.\n cancel-in-progress: false\n\njobs:\n release:\n runs-on: ubuntu-latest\n # Merged main-sync PRs must NOT trigger a release: the scope is already\n # ahead of this merge, there is nothing new to release. The event\n # router also skips this case (routePullRequest checks\n # prHeadRef === mainSyncBranch) -- this \\`if:\\` is defense in depth so the\n # job doesn't even start.\n # CHANGE-ME: the branch literal below MUST match your workspace's\n # configured \\`teambit.git/ci\\`.\\`sync.mainSyncBranch\\`.\n if: github.event.pull_request.merged == true && github.event.pull_request.head.ref != 'bit-sync/main'\n steps:\n - uses: actions/checkout@v4\n with:\n fetch-depth: 0\n token: \\${{ secrets.BIT_SYNC_GH_TOKEN || secrets.GITHUB_TOKEN }}\n - uses: bit-tasks/init@v2\n # Pinned to a commit SHA on purpose: this job holds write permission, and\n # a tag can move. Bump the SHA to take a new version of the action.\n - uses: teambit/bit-git-sync@66c0fdf9e34e45f70b4f397b38b2b01f79dd1f41\n with:\n # CHANGE-ME: keep this in sync with\n # \\`teambit.git/ci\\`.\\`sync.mainSyncBranch\\` AND with the \\`if:\\`\n # condition above.\n main-sync-branch: bit-sync/main\n # Uncomment if your workspace.jsonc is NOT at the repository root --\n # the action chdirs here before running anything.\n # ws-dir: packages/my-workspace\n env:\n BIT_CONFIG_ACCESS_TOKEN: \\${{ secrets.BIT_CONFIG_ACCESS_TOKEN }}\n GITHUB_TOKEN: \\${{ secrets.BIT_SYNC_GH_TOKEN || secrets.GITHUB_TOKEN }}\n # Optional: git identity for the commits the release creates.\n # Defaults to bit-sync[bot] / bit-sync[bot]@users.noreply.github.com.\n # GIT_USER_NAME: bit-sync[bot]\n # GIT_USER_EMAIL: bit-sync[bot]@users.noreply.github.com\n`;\n\n/**\n * The exact substring in each template that encodes the repository's default branch. Exact substring,\n * never a blanket `main` regex — that would also corrupt `bit-main-export` and `bit-sync/main`.\n */\nconst DEFAULT_BRANCH_MARKER = {\n sync: \"branches-ignore: [main, 'bit-sync/**']\",\n release: 'branches: [main]',\n} as const;\n\n/**\n * A YAML single-quoted scalar of `value` (the only escape inside single quotes is a doubled `''`).\n * Both substitution points land inside a YAML flow sequence, where `,` and `]` are structural — and a\n * branch name may legally contain both, so quoting is unconditional.\n */\nfunction yamlSingleQuoted(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`;\n}\n\n/**\n * Replace the default-branch literal inside `marker` with `defaultBranch`, inside `raw`. Throws when\n * the marker has drifted out of the template — a reworded canonical workflow must fail loudly, not\n * ship a scaffold that still says `main`.\n */\nfunction substituteDefaultBranch(raw: string, marker: string, defaultBranch: string): string {\n if (!raw.includes(marker)) {\n throw new Error(\n `init-scaffold: expected marker \"${marker}\" not found in its workflow template — the canonical ` +\n `template (bitdev.git-sync/git-sync/workflows) has drifted from BIT_SYNC_WORKFLOW_RAW / ` +\n `BIT_RELEASE_WORKFLOW_RAW; update the copy and this substitution point together`\n );\n }\n // Function replacements, not strings: `$&`/`$'`/`$$` are special in string replacements and `$` is\n // git-legal in a branch name. A function replacement is inserted verbatim.\n const substitutedMarker = marker.replace('main', () => yamlSingleQuoted(defaultBranch));\n return raw.replace(marker, () => substitutedMarker);\n}\n\n/** Render `bit-sync.yml` with the repository's actual default branch substituted. */\nexport function renderBitSyncWorkflow(defaultBranch: string): string {\n return substituteDefaultBranch(BIT_SYNC_WORKFLOW_RAW, DEFAULT_BRANCH_MARKER.sync, defaultBranch);\n}\n\n/** Render `bit-release.yml` with the repository's actual default branch substituted. */\nexport function renderBitReleaseWorkflow(defaultBranch: string): string {\n return substituteDefaultBranch(BIT_RELEASE_WORKFLOW_RAW, DEFAULT_BRANCH_MARKER.release, defaultBranch);\n}\n\nexport interface ScaffoldFileOutcome {\n /** relative to the workspace root, e.g. `.github/workflows/bit-sync.yml` */\n relativePath: string;\n status: 'written' | 'skipped';\n}\n\n// Never overwrites an existing file — `--init` must be safe to re-run after hand-edits.\nfunction writeIfAbsent(workspaceDir: string, relativePath: string, content: string): ScaffoldFileOutcome {\n const absPath = path.join(workspaceDir, relativePath);\n if (fs.existsSync(absPath)) {\n return { relativePath, status: 'skipped' };\n }\n fs.mkdirSync(path.dirname(absPath), { recursive: true });\n fs.writeFileSync(absPath, content);\n return { relativePath, status: 'written' };\n}\n\n/** Scaffold both workflow files under `workspaceDir`. Never overwrites; creates `.github/workflows/` as needed. */\nexport function scaffoldWorkflowFiles(workspaceDir: string, defaultBranch: string): ScaffoldFileOutcome[] {\n return [\n writeIfAbsent(workspaceDir, WORKFLOW_RELATIVE_PATHS.sync, renderBitSyncWorkflow(defaultBranch)),\n writeIfAbsent(workspaceDir, WORKFLOW_RELATIVE_PATHS.release, renderBitReleaseWorkflow(defaultBranch)),\n ];\n}\n\nexport interface OwnerRepo {\n owner: string;\n repo: string;\n}\n\n/**\n * Derive `{owner, repo}` from the `origin` remote when it is a parseable GitHub remote, else\n * undefined (the checklist falls back to a placeholder). Reuses `github-client.ts`'s parsing so the\n * two never disagree.\n */\nexport function deriveOwnerRepo(remoteUrl: string | undefined): OwnerRepo | undefined {\n if (!remoteUrl || !isGitHubRemote(remoteUrl)) return undefined;\n const ownerSlashRepo = parseGitHubRepo(remoteUrl);\n if (!ownerSlashRepo) return undefined;\n const [owner, repo] = ownerSlashRepo.split('/');\n if (!owner || !repo) return undefined;\n return { owner, repo };\n}\n\n/**\n * The bit.cloud custom webhook payload template, verified byte-perfect against a live delivery.\n * Lane vs. main export is discriminated by whether `laneId` is empty.\n */\nconst WEBHOOK_PAYLOAD_TEMPLATE =\n '{\"event_type\":\"bit-export\",\"client_payload\":{\"laneId\":\"{{laneId}}\",\"componentIds\":\"{{componentIds}}\",\"owner\":\"{{owner}}\",\"actor\":\"{{username}}\"}}';\n\n/**\n * The manual-steps checklist `bit ci sync --init` prints: everything the command itself cannot do\n * (secrets live in GitHub settings; the webhook lives on bit.cloud).\n */\nexport function renderInitChecklist(ownerRepo: OwnerRepo | undefined): string {\n const repoSegment = ownerRepo ? `${ownerRepo.owner}/${ownerRepo.repo}` : '<owner>/<repo>';\n const dispatchUrl = `https://api.github.com/repos/${repoSegment}/dispatches`;\n return [\n '',\n 'Remaining manual steps (bit ci sync --init only scaffolds files -- these need a human):',\n '',\n '1. Secrets -- add in the repository (or org) Settings > Secrets and variables > Actions:',\n ' - BIT_CONFIG_ACCESS_TOKEN (required): a bit.cloud service-account token with export rights on',\n \" this scope. This account must also be exempt from the org's\",\n ' change-request/merge block -- it is the only identity that merges lanes.',\n ' - BIT_SYNC_GH_TOKEN (optional): a GitHub PAT or App token. Without it, sync pushes/PRs use the',\n ' default GITHUB_TOKEN, which does NOT trigger downstream workflow runs (loop-safe, but the',\n ' sync PR then gets no CI checks).',\n '',\n '2. Permissions -- both scaffolded workflows already declare `contents: write` and',\n ' `pull-requests: write`. Nothing to change unless an org-wide policy overrides workflow-level',\n ' permissions (e.g. a default of \"Read repository contents permission\" for the GITHUB_TOKEN).',\n '',\n '3. bit.cloud webhook -- create ONE webhook (org Settings > Webhooks) on the \"Components > Export',\n ' succeeded\" event:',\n ` URL: ${dispatchUrl}`,\n ' Headers: Authorization: Bearer <PAT>',\n ' Accept: application/vnd.github+json',\n ' Custom payload template:',\n ` ${WEBHOOK_PAYLOAD_TEMPLATE}`,\n ' WARNING: create this webhook fresh -- editing an existing webhook drops its custom headers',\n ' (known bit.cloud platform bug, verified 2026-07-29). If the URL, headers or template need to',\n ' change later, delete the webhook and create a new one rather than editing it.',\n '',\n '4. Checkout depth -- both scaffolded workflows already check out with `fetch-depth: 0`. This is',\n ' required: the reconciler reads full git history, and a shallow (--depth=1) clone fails sync',\n ' safely but uselessly (HALTED, no writes). Keep `fetch-depth: 0` if you customize the workflow.',\n ' Narrowing the REFSPEC is fine, though -- a single-branch clone is supported, because every',\n ' fetch sync performs names +refs/heads/*:refs/remotes/origin/* explicitly.',\n '',\n ].join('\\n');\n}\n"],"mappings":";;;;;;;;;;;AAAA,SAAAA,IAAA;EAAA,MAAAC,IAAA,GAAAC,sBAAA,CAAAC,OAAA;EAAAH,GAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAG,MAAA;EAAA,MAAAH,IAAA,GAAAC,sBAAA,CAAAC,OAAA;EAAAC,KAAA,YAAAA,CAAA;IAAA,OAAAH,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAI,cAAA;EAAA,MAAAJ,IAAA,GAAAE,OAAA;EAAAE,aAAA,YAAAA,CAAA;IAAA,OAAAJ,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAAkE,SAAAC,uBAAAI,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAElE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACO,MAAMG,uBAAuB,GAAAC,OAAA,CAAAD,uBAAA,GAAG;EACrCE,IAAI,EAAEC,eAAI,CAACC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,cAAc,CAAC;EACvDC,OAAO,EAAEF,eAAI,CAACC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,iBAAiB;AAC9D,CAAU;AAEV,MAAME,qBAAqB,GAAG;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAED,MAAMC,wBAAwB,GAAG;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMC,qBAAqB,GAAG;EAC5BN,IAAI,EAAE,wCAAwC;EAC9CG,OAAO,EAAE;AACX,CAAU;;AAEV;AACA;AACA;AACA;AACA;AACA,SAASI,gBAAgBA,CAACC,KAAa,EAAU;EAC/C,OAAO,IAAIA,KAAK,CAACC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA,SAASC,uBAAuBA,CAACC,GAAW,EAAEC,MAAc,EAAEC,aAAqB,EAAU;EAC3F,IAAI,CAACF,GAAG,CAACG,QAAQ,CAACF,MAAM,CAAC,EAAE;IACzB,MAAM,IAAIG,KAAK,CACb,mCAAmCH,MAAM,uDAAuD,GAC9F,yFAAyF,GACzF,gFACJ,CAAC;EACH;EACA;EACA;EACA,MAAMI,iBAAiB,GAAGJ,MAAM,CAACH,OAAO,CAAC,MAAM,EAAE,MAAMF,gBAAgB,CAACM,aAAa,CAAC,CAAC;EACvF,OAAOF,GAAG,CAACF,OAAO,CAACG,MAAM,EAAE,MAAMI,iBAAiB,CAAC;AACrD;;AAEA;AACO,SAASC,qBAAqBA,CAACJ,aAAqB,EAAU;EACnE,OAAOH,uBAAuB,CAACN,qBAAqB,EAAEE,qBAAqB,CAACN,IAAI,EAAEa,aAAa,CAAC;AAClG;;AAEA;AACO,SAASK,wBAAwBA,CAACL,aAAqB,EAAU;EACtE,OAAOH,uBAAuB,CAACL,wBAAwB,EAAEC,qBAAqB,CAACH,OAAO,EAAEU,aAAa,CAAC;AACxG;AAQA;AACA,SAASM,aAAaA,CAACC,YAAoB,EAAEC,YAAoB,EAAEC,OAAe,EAAuB;EACvG,MAAMC,OAAO,GAAGtB,eAAI,CAACC,IAAI,CAACkB,YAAY,EAAEC,YAAY,CAAC;EACrD,IAAIG,aAAE,CAACC,UAAU,CAACF,OAAO,CAAC,EAAE;IAC1B,OAAO;MAAEF,YAAY;MAAEK,MAAM,EAAE;IAAU,CAAC;EAC5C;EACAF,aAAE,CAACG,SAAS,CAAC1B,eAAI,CAAC2B,OAAO,CAACL,OAAO,CAAC,EAAE;IAAEM,SAAS,EAAE;EAAK,CAAC,CAAC;EACxDL,aAAE,CAACM,aAAa,CAACP,OAAO,EAAED,OAAO,CAAC;EAClC,OAAO;IAAED,YAAY;IAAEK,MAAM,EAAE;EAAU,CAAC;AAC5C;;AAEA;AACO,SAASK,qBAAqBA,CAACX,YAAoB,EAAEP,aAAqB,EAAyB;EACxG,OAAO,CACLM,aAAa,CAACC,YAAY,EAAEtB,uBAAuB,CAACE,IAAI,EAAEiB,qBAAqB,CAACJ,aAAa,CAAC,CAAC,EAC/FM,aAAa,CAACC,YAAY,EAAEtB,uBAAuB,CAACK,OAAO,EAAEe,wBAAwB,CAACL,aAAa,CAAC,CAAC,CACtG;AACH;AAOA;AACA;AACA;AACA;AACA;AACO,SAASmB,eAAeA,CAACC,SAA6B,EAAyB;EACpF,IAAI,CAACA,SAAS,IAAI,CAAC,IAAAC,8BAAc,EAACD,SAAS,CAAC,EAAE,OAAOE,SAAS;EAC9D,MAAMC,cAAc,GAAG,IAAAC,+BAAe,EAACJ,SAAS,CAAC;EACjD,IAAI,CAACG,cAAc,EAAE,OAAOD,SAAS;EACrC,MAAM,CAACG,KAAK,EAAEC,IAAI,CAAC,GAAGH,cAAc,CAACI,KAAK,CAAC,GAAG,CAAC;EAC/C,IAAI,CAACF,KAAK,IAAI,CAACC,IAAI,EAAE,OAAOJ,SAAS;EACrC,OAAO;IAAEG,KAAK;IAAEC;EAAK,CAAC;AACxB;;AAEA;AACA;AACA;AACA;AACA,MAAME,wBAAwB,GAC5B,mJAAmJ;;AAErJ;AACA;AACA;AACA;AACO,SAASC,mBAAmBA,CAACC,SAAgC,EAAU;EAC5E,MAAMC,WAAW,GAAGD,SAAS,GAAG,GAAGA,SAAS,CAACL,KAAK,IAAIK,SAAS,CAACJ,IAAI,EAAE,GAAG,gBAAgB;EACzF,MAAMM,WAAW,GAAG,gCAAgCD,WAAW,aAAa;EAC5E,OAAO,CACL,EAAE,EACF,yFAAyF,EACzF,EAAE,EACF,0FAA0F,EAC1F,kGAAkG,EAClG,kEAAkE,EAClE,+EAA+E,EAC/E,mGAAmG,EACnG,gGAAgG,EAChG,uCAAuC,EACvC,EAAE,EACF,mFAAmF,EACnF,iGAAiG,EACjG,gGAAgG,EAChG,EAAE,EACF,kGAAkG,EAClG,sBAAsB,EACtB,eAAeC,WAAW,EAAE,EAC5B,yCAAyC,EACzC,iDAAiD,EACjD,6BAA6B,EAC7B,MAAMJ,wBAAwB,EAAE,EAChC,+FAA+F,EAC/F,iGAAiG,EACjG,kFAAkF,EAClF,EAAE,EACF,iGAAiG,EACjG,gGAAgG,EAChG,mGAAmG,EACnG,+FAA+F,EAC/F,8EAA8E,EAC9E,EAAE,CACH,CAACvC,IAAI,CAAC,IAAI,CAAC;AACd","ignoreList":[]}
1
+ {"version":3,"names":["_fs","data","_interopRequireDefault","require","_path","_githubClient","e","__esModule","default","WORKFLOW_RELATIVE_PATHS","exports","sync","path","join","release","BIT_SYNC_WORKFLOW_RAW","BIT_RELEASE_WORKFLOW_RAW","DEFAULT_BRANCH_MARKER","yamlSingleQuoted","value","replace","substituteDefaultBranch","raw","marker","defaultBranch","includes","Error","substitutedMarker","renderBitSyncWorkflow","renderBitReleaseWorkflow","writeIfAbsent","workspaceDir","relativePath","content","absPath","fs","existsSync","status","mkdirSync","dirname","recursive","writeFileSync","scaffoldWorkflowFiles","deriveOwnerRepo","remoteUrl","isGitHubRemote","undefined","ownerSlashRepo","parseGitHubRepo","host","remoteHost","owner","repo","split","WEBHOOK_PAYLOAD_TEMPLATE","renderInitChecklist","ownerRepo","repoSegment","api","gitHubApiUrl","dispatchUrl","url","error"],"sources":["init-scaffold.ts"],"sourcesContent":["import fs from 'fs';\nimport path from 'path';\nimport { parseGitHubRepo, isGitHubRemote, gitHubApiUrl, remoteHost } from './github-client';\n\n/**\n * `bit ci sync --init` — pure scaffolding logic, unit-testable without a live workspace/git checkout.\n *\n * TEMPLATE SOURCE OF TRUTH: `BIT_SYNC_WORKFLOW_RAW` / `BIT_RELEASE_WORKFLOW_RAW` are byte-for-byte\n * copies of the canonical templates in the `bit-git-sync` action workspace\n * (git-sync/git-sync/workflows/templates/) and MUST be kept in sync with them. The ONLY departure is\n * the two `DEFAULT_BRANCH_MARKER` substitution points; everything else — CHANGE-ME comments, the\n * placeholder action ref, `bit-sync/main` config defaults — stays untouched.\n */\n\n/** Where `scaffoldWorkflowFiles` writes each file, relative to the workspace root. */\nexport const WORKFLOW_RELATIVE_PATHS = {\n sync: path.join('.github', 'workflows', 'bit-sync.yml'),\n release: path.join('.github', 'workflows', 'bit-release.yml'),\n} as const;\n\nconst BIT_SYNC_WORKFLOW_RAW = `# Copy this file into your repository at \\`.github/workflows/bit-sync.yml\\`,\n# then review every line marked \\`CHANGE-ME\\` below -- the defaults assume a\n# repository whose default branch is \\`main\\` and a workspace at the repo root.\n#\n# See the \\`workflows.docs.mdx\\` customer setup guide (component\n# bitdev.git-sync/git-sync/workflows) for the full walk-through: the\n# bit.cloud webhook wiring that drives \\`repository_dispatch\\`, the required\n# secrets, and the \\`teambit.git/ci\\`.\\`sync\\` workspace config this workflow\n# acts on.\nname: bit-sync\non:\n repository_dispatch:\n # 'bit-export' is the real, empirically-verified bit.cloud webhook\n # contract: a single dispatch type discriminated by\n # client_payload.laneId (non-empty 'scope/lane' -> lane export, empty ->\n # main export). The other three types are forward-compat aliases the\n # event router also accepts, in case a webhook is configured to send the\n # originally-assumed, more granular dispatch types instead.\n types: [bit-export, bit-lane-export, bit-main-export, bit-lane-removed]\n schedule:\n # Scheduled reconcile. This is also the ONLY mechanism that picks up\n # lane deletions -- bit.cloud has no \"lane removed\" webhook event.\n - cron: '*/30 * * * *'\n push:\n # CHANGE-ME: \\`main\\` must be your repository's DEFAULT branch, and\n # \\`bit-sync/**\\` must cover your configured \\`sync.mainSyncBranch\\`. Pushes\n # to either are bit-sync's own output and must not re-trigger a sync.\n branches-ignore: [main, 'bit-sync/**']\n workflow_dispatch:\n inputs:\n lane: { description: Lane to sync (empty = all), required: false }\n\n# The default GITHUB_TOKEN is READ-ONLY on repositories and organizations\n# created after Feb 2023, and anywhere the org/repo default is set to\n# \"Read repository contents permission\". Sync pushes branches and\n# opens/updates PRs, so both scopes must be declared explicitly -- without\n# this block the sync fails with a 403 on its first write.\npermissions:\n contents: write\n pull-requests: write\n\nconcurrency:\n # Serializes one lane's syncs so two runs never race on the same branch/PR.\n #\n # Each trigger needs a different expression, because the lane identity\n # arrives in a different place every time:\n # - repository_dispatch -> client_payload.laneId ('scope/lane'), or\n # client_payload.lane for the alias types\n # - push -> github.ref_name (the branch)\n # - workflow_dispatch -> the \\`lane\\` input\n # - schedule -> nothing lane-shaped; it reconciles everything\n #\n # github.ref_name is populated on schedule runs too (it is the default\n # branch there), so it may only be consulted AFTER the event name has been\n # checked. Reading it first -- as a bare \\`... || github.ref_name || 'all'\\`\n # chain does -- makes the final fallback unreachable and lumps every cron\n # run into the same group as pushes to the default branch.\n #\n # RESIDUAL RACE (accepted, by design): a webhook run groups as\n # 'scope/my-lane' while a push to that lane's branch groups as 'my-lane', so\n # two runs for the same lane can still overlap across those two triggers.\n # GitHub expressions have no substring/split function, and bit.cloud's\n # webhook payload template exposes only the full laneId, so the two keys\n # cannot be normalized into one here. This is safe rather than merely\n # tolerated: the reconciler is idempotent and the sync executor diffs\n # against converged state, so a second overlapping run finds nothing left to\n # do and no-ops. The concurrency group is an efficiency measure; it is not\n # what makes the sync correct.\n group: >-\n bit-sync-\\${{\n github.event_name == 'repository_dispatch' && (github.event.client_payload.laneId || github.event.client_payload.lane || 'main-export')\n || github.event_name == 'push' && github.ref_name\n || github.event_name == 'workflow_dispatch' && (github.event.inputs.lane || 'reconcile-all')\n || 'reconcile-all' }}\n # Never cancel a sync mid-flight: it may already have pushed a branch and be\n # partway through opening or updating its PR.\n cancel-in-progress: false\n\njobs:\n sync:\n runs-on: ubuntu-latest\n steps:\n - uses: actions/checkout@v4\n with:\n fetch-depth: 0\n # A PAT/App token so that pushes this workflow makes (e.g. a sync\n # PR branch) can themselves trigger CI. Pushes authenticated with\n # the default GITHUB_TOKEN do NOT trigger other workflow runs.\n token: \\${{ secrets.BIT_SYNC_GH_TOKEN || secrets.GITHUB_TOKEN }}\n - uses: bit-tasks/init@v2\n # Pinned to a commit SHA on purpose: this job holds write permission, and\n # a tag can move. Bump the SHA to take a new version of the action.\n - uses: teambit/bit-git-sync@66c0fdf9e34e45f70b4f397b38b2b01f79dd1f41\n with:\n # CHANGE-ME: keep this in sync with\n # \\`teambit.git/ci\\`.\\`sync.mainSyncBranch\\` in your workspace.jsonc\n # (the action's own default is shown here).\n main-sync-branch: bit-sync/main\n # Uncomment if your workspace.jsonc is NOT at the repository root --\n # the action chdirs here before running anything.\n # ws-dir: packages/my-workspace\n env:\n # Service account token. This account must be EXEMPT from the\n # org's change-request/merge block, or bit.cloud rejects the\n # sync-driven writes.\n BIT_CONFIG_ACCESS_TOKEN: \\${{ secrets.BIT_CONFIG_ACCESS_TOKEN }}\n GITHUB_TOKEN: \\${{ secrets.BIT_SYNC_GH_TOKEN || secrets.GITHUB_TOKEN }}\n # Optional: git identity for the commits the sync creates. Defaults\n # to bit-sync[bot] / bit-sync[bot]@users.noreply.github.com.\n # GIT_USER_NAME: bit-sync[bot]\n # GIT_USER_EMAIL: bit-sync[bot]@users.noreply.github.com\n`;\n\nconst BIT_RELEASE_WORKFLOW_RAW = `# Copy this file into your repository at \\`.github/workflows/bit-release.yml\\`,\n# then review every line marked \\`CHANGE-ME\\` below.\n#\n# See the \\`workflows.docs.mdx\\` customer setup guide (component\n# bitdev.git-sync/git-sync/workflows) for the full walk-through.\nname: bit-release\non:\n pull_request:\n types: [closed]\n # CHANGE-ME: your repository's DEFAULT branch. \\`bit ci merge\\` releases\n # from the default branch, so only PRs merged INTO it should trigger a\n # release -- a stacked PR landing on another feature branch has not\n # reached the default branch yet. The action's event router enforces the\n # same rule from \\`pull_request.base.ref\\`; this filter means a run is never\n # even queued for a non-default base.\n branches: [main]\n\n# The default GITHUB_TOKEN is READ-ONLY on repositories and organizations\n# created after Feb 2023, and anywhere the org/repo default is set to\n# \"Read repository contents permission\". The release run pushes commits/tags\n# and updates PRs, so both scopes must be declared explicitly.\npermissions:\n contents: write\n pull-requests: write\n\nconcurrency:\n group: bit-release-\\${{ github.event.pull_request.number }}\n # Never cancel a release mid-flight.\n cancel-in-progress: false\n\njobs:\n release:\n runs-on: ubuntu-latest\n # Merged main-sync PRs must NOT trigger a release: the scope is already\n # ahead of this merge, there is nothing new to release. The event\n # router also skips this case (routePullRequest checks\n # prHeadRef === mainSyncBranch) -- this \\`if:\\` is defense in depth so the\n # job doesn't even start.\n # CHANGE-ME: the branch literal below MUST match your workspace's\n # configured \\`teambit.git/ci\\`.\\`sync.mainSyncBranch\\`.\n if: github.event.pull_request.merged == true && github.event.pull_request.head.ref != 'bit-sync/main'\n steps:\n - uses: actions/checkout@v4\n with:\n fetch-depth: 0\n token: \\${{ secrets.BIT_SYNC_GH_TOKEN || secrets.GITHUB_TOKEN }}\n - uses: bit-tasks/init@v2\n # Pinned to a commit SHA on purpose: this job holds write permission, and\n # a tag can move. Bump the SHA to take a new version of the action.\n - uses: teambit/bit-git-sync@66c0fdf9e34e45f70b4f397b38b2b01f79dd1f41\n with:\n # CHANGE-ME: keep this in sync with\n # \\`teambit.git/ci\\`.\\`sync.mainSyncBranch\\` AND with the \\`if:\\`\n # condition above.\n main-sync-branch: bit-sync/main\n # Uncomment if your workspace.jsonc is NOT at the repository root --\n # the action chdirs here before running anything.\n # ws-dir: packages/my-workspace\n env:\n BIT_CONFIG_ACCESS_TOKEN: \\${{ secrets.BIT_CONFIG_ACCESS_TOKEN }}\n GITHUB_TOKEN: \\${{ secrets.BIT_SYNC_GH_TOKEN || secrets.GITHUB_TOKEN }}\n # Optional: git identity for the commits the release creates.\n # Defaults to bit-sync[bot] / bit-sync[bot]@users.noreply.github.com.\n # GIT_USER_NAME: bit-sync[bot]\n # GIT_USER_EMAIL: bit-sync[bot]@users.noreply.github.com\n`;\n\n/**\n * The exact substring in each template that encodes the repository's default branch. Exact substring,\n * never a blanket `main` regex — that would also corrupt `bit-main-export` and `bit-sync/main`.\n */\nconst DEFAULT_BRANCH_MARKER = {\n sync: \"branches-ignore: [main, 'bit-sync/**']\",\n release: 'branches: [main]',\n} as const;\n\n/**\n * A YAML single-quoted scalar of `value` (the only escape inside single quotes is a doubled `''`).\n * Both substitution points land inside a YAML flow sequence, where `,` and `]` are structural — and a\n * branch name may legally contain both, so quoting is unconditional.\n */\nfunction yamlSingleQuoted(value: string): string {\n return `'${value.replace(/'/g, \"''\")}'`;\n}\n\n/**\n * Replace the default-branch literal inside `marker` with `defaultBranch`, inside `raw`. Throws when\n * the marker has drifted out of the template — a reworded canonical workflow must fail loudly, not\n * ship a scaffold that still says `main`.\n */\nfunction substituteDefaultBranch(raw: string, marker: string, defaultBranch: string): string {\n if (!raw.includes(marker)) {\n throw new Error(\n `init-scaffold: expected marker \"${marker}\" not found in its workflow template — the canonical ` +\n `template (bitdev.git-sync/git-sync/workflows) has drifted from BIT_SYNC_WORKFLOW_RAW / ` +\n `BIT_RELEASE_WORKFLOW_RAW; update the copy and this substitution point together`\n );\n }\n // Function replacements, not strings: `$&`/`$'`/`$$` are special in string replacements and `$` is\n // git-legal in a branch name. A function replacement is inserted verbatim.\n const substitutedMarker = marker.replace('main', () => yamlSingleQuoted(defaultBranch));\n return raw.replace(marker, () => substitutedMarker);\n}\n\n/** Render `bit-sync.yml` with the repository's actual default branch substituted. */\nexport function renderBitSyncWorkflow(defaultBranch: string): string {\n return substituteDefaultBranch(BIT_SYNC_WORKFLOW_RAW, DEFAULT_BRANCH_MARKER.sync, defaultBranch);\n}\n\n/** Render `bit-release.yml` with the repository's actual default branch substituted. */\nexport function renderBitReleaseWorkflow(defaultBranch: string): string {\n return substituteDefaultBranch(BIT_RELEASE_WORKFLOW_RAW, DEFAULT_BRANCH_MARKER.release, defaultBranch);\n}\n\nexport interface ScaffoldFileOutcome {\n /** relative to the workspace root, e.g. `.github/workflows/bit-sync.yml` */\n relativePath: string;\n status: 'written' | 'skipped';\n}\n\n// Never overwrites an existing file — `--init` must be safe to re-run after hand-edits.\nfunction writeIfAbsent(workspaceDir: string, relativePath: string, content: string): ScaffoldFileOutcome {\n const absPath = path.join(workspaceDir, relativePath);\n if (fs.existsSync(absPath)) {\n return { relativePath, status: 'skipped' };\n }\n fs.mkdirSync(path.dirname(absPath), { recursive: true });\n fs.writeFileSync(absPath, content);\n return { relativePath, status: 'written' };\n}\n\n/** Scaffold both workflow files under `workspaceDir`. Never overwrites; creates `.github/workflows/` as needed. */\nexport function scaffoldWorkflowFiles(workspaceDir: string, defaultBranch: string): ScaffoldFileOutcome[] {\n return [\n writeIfAbsent(workspaceDir, WORKFLOW_RELATIVE_PATHS.sync, renderBitSyncWorkflow(defaultBranch)),\n writeIfAbsent(workspaceDir, WORKFLOW_RELATIVE_PATHS.release, renderBitReleaseWorkflow(defaultBranch)),\n ];\n}\n\nexport interface OwnerRepo {\n owner: string;\n repo: string;\n /** The remote's host — github.com or the GITHUB_SERVER_URL one — which picks the API the checklist names. */\n host: string;\n}\n\n/**\n * Derive `{owner, repo}` from the `origin` remote when it is a parseable GitHub remote, else\n * undefined (the checklist falls back to a placeholder). Reuses `github-client.ts`'s parsing so the\n * two never disagree.\n */\nexport function deriveOwnerRepo(remoteUrl: string | undefined): OwnerRepo | undefined {\n if (!remoteUrl || !isGitHubRemote(remoteUrl)) return undefined;\n const ownerSlashRepo = parseGitHubRepo(remoteUrl);\n const host = remoteHost(remoteUrl);\n if (!ownerSlashRepo || !host) return undefined;\n const [owner, repo] = ownerSlashRepo.split('/');\n if (!owner || !repo) return undefined;\n return { owner, repo, host };\n}\n\n/**\n * The bit.cloud custom webhook payload template, verified byte-perfect against a live delivery.\n * Lane vs. main export is discriminated by whether `laneId` is empty.\n */\nconst WEBHOOK_PAYLOAD_TEMPLATE =\n '{\"event_type\":\"bit-export\",\"client_payload\":{\"laneId\":\"{{laneId}}\",\"componentIds\":\"{{componentIds}}\",\"owner\":\"{{owner}}\",\"actor\":\"{{username}}\"}}';\n\n/**\n * The manual-steps checklist `bit ci sync --init` prints: everything the command itself cannot do\n * (secrets live in GitHub settings; the webhook lives on bit.cloud).\n */\nexport function renderInitChecklist(ownerRepo: OwnerRepo | undefined): string {\n const repoSegment = ownerRepo ? `${ownerRepo.owner}/${ownerRepo.repo}` : '<owner>/<repo>';\n const api = gitHubApiUrl(ownerRepo?.host);\n const dispatchUrl = `${'error' in api ? '<GitHub API URL>' : api.url}/repos/${repoSegment}/dispatches`;\n return [\n '',\n 'Remaining manual steps (bit ci sync --init only scaffolds files -- these need a human):',\n '',\n '1. Secrets -- add in the repository (or org) Settings > Secrets and variables > Actions:',\n ' - BIT_CONFIG_ACCESS_TOKEN (required): a bit.cloud service-account token with export rights on',\n \" this scope. This account must also be exempt from the org's\",\n ' change-request/merge block -- it is the only identity that merges lanes.',\n ' - BIT_SYNC_GH_TOKEN (optional): a GitHub PAT or App token. Without it, sync pushes/PRs use the',\n ' default GITHUB_TOKEN, which does NOT trigger downstream workflow runs (loop-safe, but the',\n ' sync PR then gets no CI checks).',\n '',\n '2. Permissions -- both scaffolded workflows already declare `contents: write` and',\n ' `pull-requests: write`. Nothing to change unless an org-wide policy overrides workflow-level',\n ' permissions (e.g. a default of \"Read repository contents permission\" for the GITHUB_TOKEN).',\n '',\n '3. bit.cloud webhook -- create ONE webhook (org Settings > Webhooks) on the \"Components > Export',\n ' succeeded\" event:',\n ` URL: ${dispatchUrl}`,\n ...('error' in api ? [` (${api.error})`] : []),\n ' Headers: Authorization: Bearer <PAT>',\n ' Accept: application/vnd.github+json',\n ' Custom payload template:',\n ` ${WEBHOOK_PAYLOAD_TEMPLATE}`,\n ' WARNING: create this webhook fresh -- editing an existing webhook drops its custom headers',\n ' (known bit.cloud platform bug, verified 2026-07-29). If the URL, headers or template need to',\n ' change later, delete the webhook and create a new one rather than editing it.',\n '',\n '4. Checkout depth -- both scaffolded workflows already check out with `fetch-depth: 0`. This is',\n ' required: the reconciler reads full git history, and a shallow (--depth=1) clone fails sync',\n ' safely but uselessly (HALTED, no writes). Keep `fetch-depth: 0` if you customize the workflow.',\n ' Narrowing the REFSPEC is fine, though -- a single-branch clone is supported, because every',\n ' fetch sync performs names +refs/heads/*:refs/remotes/origin/* explicitly.',\n '',\n ].join('\\n');\n}\n"],"mappings":";;;;;;;;;;;AAAA,SAAAA,IAAA;EAAA,MAAAC,IAAA,GAAAC,sBAAA,CAAAC,OAAA;EAAAH,GAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAG,MAAA;EAAA,MAAAH,IAAA,GAAAC,sBAAA,CAAAC,OAAA;EAAAC,KAAA,YAAAA,CAAA;IAAA,OAAAH,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AACA,SAAAI,cAAA;EAAA,MAAAJ,IAAA,GAAAE,OAAA;EAAAE,aAAA,YAAAA,CAAA;IAAA,OAAAJ,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAA4F,SAAAC,uBAAAI,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAE5F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACO,MAAMG,uBAAuB,GAAAC,OAAA,CAAAD,uBAAA,GAAG;EACrCE,IAAI,EAAEC,eAAI,CAACC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,cAAc,CAAC;EACvDC,OAAO,EAAEF,eAAI,CAACC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,iBAAiB;AAC9D,CAAU;AAEV,MAAME,qBAAqB,GAAG;AAC9B;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;AAED,MAAMC,wBAAwB,GAAG;AACjC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,CAAC;;AAED;AACA;AACA;AACA;AACA,MAAMC,qBAAqB,GAAG;EAC5BN,IAAI,EAAE,wCAAwC;EAC9CG,OAAO,EAAE;AACX,CAAU;;AAEV;AACA;AACA;AACA;AACA;AACA,SAASI,gBAAgBA,CAACC,KAAa,EAAU;EAC/C,OAAO,IAAIA,KAAK,CAACC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,GAAG;AACzC;;AAEA;AACA;AACA;AACA;AACA;AACA,SAASC,uBAAuBA,CAACC,GAAW,EAAEC,MAAc,EAAEC,aAAqB,EAAU;EAC3F,IAAI,CAACF,GAAG,CAACG,QAAQ,CAACF,MAAM,CAAC,EAAE;IACzB,MAAM,IAAIG,KAAK,CACb,mCAAmCH,MAAM,uDAAuD,GAC9F,yFAAyF,GACzF,gFACJ,CAAC;EACH;EACA;EACA;EACA,MAAMI,iBAAiB,GAAGJ,MAAM,CAACH,OAAO,CAAC,MAAM,EAAE,MAAMF,gBAAgB,CAACM,aAAa,CAAC,CAAC;EACvF,OAAOF,GAAG,CAACF,OAAO,CAACG,MAAM,EAAE,MAAMI,iBAAiB,CAAC;AACrD;;AAEA;AACO,SAASC,qBAAqBA,CAACJ,aAAqB,EAAU;EACnE,OAAOH,uBAAuB,CAACN,qBAAqB,EAAEE,qBAAqB,CAACN,IAAI,EAAEa,aAAa,CAAC;AAClG;;AAEA;AACO,SAASK,wBAAwBA,CAACL,aAAqB,EAA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","ignoreList":[]}
@@ -133,16 +133,12 @@ describe('init-scaffold', () => {
133
133
  });
134
134
  });
135
135
  describe('deriveOwnerRepo', () => {
136
- const REMOTES = [['git@github.com:acme/shop.git', {
136
+ const SHOP = {
137
137
  owner: 'acme',
138
- repo: 'shop'
139
- }], ['https://github.com/acme/shop.git', {
140
- owner: 'acme',
141
- repo: 'shop'
142
- }], ['https://github.com/acme/shop', {
143
- owner: 'acme',
144
- repo: 'shop'
145
- }], ['https://gitlab.com/acme/shop.git', undefined],
138
+ repo: 'shop',
139
+ host: 'github.com'
140
+ };
141
+ const REMOTES = [['git@github.com:acme/shop.git', SHOP], ['https://github.com/acme/shop.git', SHOP], ['https://github.com/acme/shop', SHOP], ['https://gitlab.com/acme/shop.git', undefined],
146
142
  // a local/bare remote has no host at all
147
143
  ['/path/to/bare.git', undefined], ['file:///path/to/bare.git', undefined], [undefined, undefined]];
148
144
  it('parses a GitHub remote in either form, and nothing else', () => {
@@ -153,12 +149,62 @@ describe('init-scaffold', () => {
153
149
  it('renders a real dispatch URL when owner/repo were derived, a placeholder when not', () => {
154
150
  const derived = (0, _initScaffold().renderInitChecklist)({
155
151
  owner: 'acme',
156
- repo: 'shop'
152
+ repo: 'shop',
153
+ host: 'github.com'
157
154
  });
158
155
  (0, _chai().expect)(derived).to.contain('https://api.github.com/repos/acme/shop/dispatches');
159
156
  (0, _chai().expect)(derived).to.not.contain('<owner>/<repo>');
160
157
  (0, _chai().expect)((0, _initScaffold().renderInitChecklist)(undefined)).to.contain('https://api.github.com/repos/<owner>/<repo>/dispatches');
161
158
  });
159
+ it('derives the repository and the dispatch URL from a GitHub Enterprise Server remote', () => {
160
+ const saved = {
161
+ api: process.env.GITHUB_API_URL,
162
+ server: process.env.GITHUB_SERVER_URL
163
+ };
164
+ process.env.GITHUB_API_URL = 'https://ghe.corp.example/api/v3';
165
+ process.env.GITHUB_SERVER_URL = 'https://ghe.corp.example';
166
+ try {
167
+ const ownerRepo = (0, _initScaffold().deriveOwnerRepo)('git@ghe.corp.example:acme/store.git');
168
+ (0, _chai().expect)(ownerRepo).to.deep.equal({
169
+ owner: 'acme',
170
+ repo: 'store',
171
+ host: 'ghe.corp.example'
172
+ });
173
+ (0, _chai().expect)((0, _initScaffold().renderInitChecklist)(ownerRepo)).to.contain('https://ghe.corp.example/api/v3/repos/acme/store/dispatches');
174
+ } finally {
175
+ if (saved.api === undefined) delete process.env.GITHUB_API_URL;else process.env.GITHUB_API_URL = saved.api;
176
+ if (saved.server === undefined) delete process.env.GITHUB_SERVER_URL;else process.env.GITHUB_SERVER_URL = saved.server;
177
+ }
178
+ });
179
+ describe('on a GHES-configured runner', () => {
180
+ const saved = {};
181
+ beforeEach(() => {
182
+ saved.api = process.env.GITHUB_API_URL;
183
+ saved.server = process.env.GITHUB_SERVER_URL;
184
+ process.env.GITHUB_SERVER_URL = 'https://ghe.corp.example';
185
+ });
186
+ afterEach(() => {
187
+ if (saved.api === undefined) delete process.env.GITHUB_API_URL;else process.env.GITHUB_API_URL = saved.api;
188
+ if (saved.server === undefined) delete process.env.GITHUB_SERVER_URL;else process.env.GITHUB_SERVER_URL = saved.server;
189
+ });
190
+ it('names api.github.com for a github.com origin', () => {
191
+ process.env.GITHUB_API_URL = 'https://ghe.corp.example/api/v3';
192
+ const checklist = (0, _initScaffold().renderInitChecklist)((0, _initScaffold().deriveOwnerRepo)('git@github.com:acme/shop.git'));
193
+ (0, _chai().expect)(checklist).to.contain('https://api.github.com/repos/acme/shop/dispatches');
194
+ (0, _chai().expect)(checklist).to.not.contain('ghe.corp.example');
195
+ });
196
+ it('derives <server>/api/v3 for an enterprise origin when GITHUB_API_URL is unset', () => {
197
+ delete process.env.GITHUB_API_URL;
198
+ (0, _chai().expect)((0, _initScaffold().renderInitChecklist)((0, _initScaffold().deriveOwnerRepo)('https://ghe.corp.example/acme/store.git'))).to.contain('https://ghe.corp.example/api/v3/repos/acme/store/dispatches');
199
+ });
200
+ it('names no API for an enterprise origin whose GITHUB_API_URL is on another host', () => {
201
+ process.env.GITHUB_API_URL = 'https://api.github.com';
202
+ const checklist = (0, _initScaffold().renderInitChecklist)((0, _initScaffold().deriveOwnerRepo)('https://ghe.corp.example/acme/store.git'));
203
+ (0, _chai().expect)(checklist).to.contain('<GitHub API URL>/repos/acme/store/dispatches');
204
+ (0, _chai().expect)(checklist).to.contain('GITHUB_API_URL "https://api.github.com"');
205
+ (0, _chai().expect)(checklist).to.not.contain('https://api.github.com/repos');
206
+ });
207
+ });
162
208
  it('always includes the secrets, permissions, webhook and fetch-depth checklist items', () => {
163
209
  const checklist = (0, _initScaffold().renderInitChecklist)(undefined);
164
210
  ['BIT_CONFIG_ACCESS_TOKEN', 'BIT_SYNC_GH_TOKEN', 'contents: write', 'Components > Export', 'Authorization: Bearer <PAT>', 'Accept: application/vnd.github+json', '"event_type":"bit-export"', '{{laneId}}', 'drops its custom headers', 'fetch-depth: 0'].forEach(item => (0, _chai().expect)(checklist, item).to.contain(item));
@@ -1 +1 @@
1
- {"version":3,"names":["_chai","data","require","_fs","_interopRequireDefault","_os","_path","_yaml","_initScaffold","e","__esModule","default","yamlLoad","src","YAML","parse","onSection","rendered","doc","on","BRANCHES","describe","it","forEach","branch","expect","renderBitSyncWorkflow","push","to","deep","equal","renderBitReleaseWorkflow","pull_request","branches","sync","release","contain","jobs","be","an","workspaceDir","beforeEach","fs","mkdtempSync","path","join","os","tmpdir","afterEach","rmSync","recursive","force","scaffoldWorkflowFiles","relativePath","WORKFLOW_RELATIVE_PATHS","status","read","rel","readFileSync","syncAbsPath","mkdirSync","dirname","writeFileSync","REMOTES","owner","repo","undefined","remote","expected","deriveOwnerRepo","String","derived","renderInitChecklist","not","checklist","item"],"sources":["init-scaffold.spec.ts"],"sourcesContent":["import { expect } from 'chai';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport YAML from 'yaml';\nimport {\n WORKFLOW_RELATIVE_PATHS,\n renderBitSyncWorkflow,\n renderBitReleaseWorkflow,\n scaffoldWorkflowFiles,\n deriveOwnerRepo,\n renderInitChecklist,\n} from './init-scaffold';\n\nconst yamlLoad = (src: string) => YAML.parse(src);\n\n/** YAML 1.1-schema parsers resolve the plain scalar key `on` to `true`, so accept either key. */\nfunction onSection(rendered: string): any {\n const doc = yamlLoad(rendered) as any;\n return doc.on ?? doc[true as any];\n}\n\n/**\n * Parsed, not substring-matched: the substitution point sits inside a YAML flow sequence, where `,` and\n * `]` are structural and a substring match is blind to exactly the damage an unquoted value does. `$` is\n * git-legal and `$&`/`$'`/`$$` are special in a string replacement, so those must arrive verbatim too.\n */\nconst BRANCHES = ['main', 'develop', 'release/2026', 'release/main', 'a,b]c', \"it's/a-branch\", \"a$'b\", 'a$&b', 'a$$b', 'a$`b']; // prettier-ignore\n\ndescribe('init-scaffold', () => {\n describe('the rendered workflows', () => {\n it('put the default branch in as exactly one element of each template’s branch filter', () => {\n BRANCHES.forEach((branch) => {\n expect(onSection(renderBitSyncWorkflow(branch)).push['branches-ignore'], branch).to.deep.equal([\n branch,\n 'bit-sync/**',\n ]);\n expect(onSection(renderBitReleaseWorkflow(branch)).pull_request.branches, branch).to.deep.equal([branch]);\n });\n });\n\n it('quote the value rather than escape it, and touch nothing else in the document', () => {\n const sync = renderBitSyncWorkflow('develop');\n const release = renderBitReleaseWorkflow('develop');\n expect(sync).to.contain(\"branches-ignore: ['develop', 'bit-sync/**']\");\n expect(release).to.contain(\"branches: ['develop']\");\n // a naive replace-all of \"main\" would rewrite every one of these\n expect(sync).to.contain('main-sync-branch: bit-sync/main');\n expect(sync).to.contain('bit-main-export');\n expect(sync).to.contain('main export)');\n expect(sync).to.contain('${{ secrets.BIT_CONFIG_ACCESS_TOKEN }}');\n expect(release).to.contain(\"github.event.pull_request.head.ref != 'bit-sync/main'\");\n expect(release).to.contain('main-sync-branch: bit-sync/main');\n // YAML single-quote escaping, and the rest of the document intact\n expect(renderBitSyncWorkflow(\"it's/a-branch\")).to.contain(\"'it''s/a-branch'\");\n expect(yamlLoad(renderBitSyncWorkflow('release/main')).jobs).to.be.an('object');\n });\n });\n\n describe('scaffoldWorkflowFiles', () => {\n let workspaceDir: string;\n\n beforeEach(() => {\n workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'init-scaffold-'));\n });\n\n afterEach(() => {\n fs.rmSync(workspaceDir, { recursive: true, force: true });\n });\n\n it('writes both workflow files with the default branch substituted, creating .github/workflows/', () => {\n expect(scaffoldWorkflowFiles(workspaceDir, 'develop')).to.deep.equal([\n { relativePath: WORKFLOW_RELATIVE_PATHS.sync, status: 'written' },\n { relativePath: WORKFLOW_RELATIVE_PATHS.release, status: 'written' },\n ]);\n const read = (rel: string) => fs.readFileSync(path.join(workspaceDir, rel), 'utf8');\n expect(read(WORKFLOW_RELATIVE_PATHS.sync)).to.contain(\"branches-ignore: ['develop', 'bit-sync/**']\");\n expect(read(WORKFLOW_RELATIVE_PATHS.release)).to.contain(\"branches: ['develop']\");\n });\n\n it('is idempotent: a second run skips both files rather than overwriting them', () => {\n scaffoldWorkflowFiles(workspaceDir, 'develop');\n expect(scaffoldWorkflowFiles(workspaceDir, 'develop')).to.deep.equal([\n { relativePath: WORKFLOW_RELATIVE_PATHS.sync, status: 'skipped' },\n { relativePath: WORKFLOW_RELATIVE_PATHS.release, status: 'skipped' },\n ]);\n });\n\n it('skips only the file that already exists, writing the other one', () => {\n const syncAbsPath = path.join(workspaceDir, WORKFLOW_RELATIVE_PATHS.sync);\n fs.mkdirSync(path.dirname(syncAbsPath), { recursive: true });\n fs.writeFileSync(syncAbsPath, 'hand-edited content, do not touch\\n');\n expect(scaffoldWorkflowFiles(workspaceDir, 'develop')).to.deep.equal([\n { relativePath: WORKFLOW_RELATIVE_PATHS.sync, status: 'skipped' },\n { relativePath: WORKFLOW_RELATIVE_PATHS.release, status: 'written' },\n ]);\n expect(fs.readFileSync(syncAbsPath, 'utf8')).to.equal('hand-edited content, do not touch\\n');\n });\n });\n\n describe('deriveOwnerRepo', () => {\n const REMOTES: Array<[string | undefined, { owner: string; repo: string } | undefined]> = [\n ['git@github.com:acme/shop.git', { owner: 'acme', repo: 'shop' }],\n ['https://github.com/acme/shop.git', { owner: 'acme', repo: 'shop' }],\n ['https://github.com/acme/shop', { owner: 'acme', repo: 'shop' }],\n ['https://gitlab.com/acme/shop.git', undefined],\n // a local/bare remote has no host at all\n ['/path/to/bare.git', undefined],\n ['file:///path/to/bare.git', undefined],\n [undefined, undefined],\n ];\n\n it('parses a GitHub remote in either form, and nothing else', () => {\n REMOTES.forEach(([remote, expected]) => expect(deriveOwnerRepo(remote), String(remote)).to.deep.equal(expected));\n });\n });\n\n describe('renderInitChecklist', () => {\n it('renders a real dispatch URL when owner/repo were derived, a placeholder when not', () => {\n const derived = renderInitChecklist({ owner: 'acme', repo: 'shop' });\n expect(derived).to.contain('https://api.github.com/repos/acme/shop/dispatches');\n expect(derived).to.not.contain('<owner>/<repo>');\n expect(renderInitChecklist(undefined)).to.contain('https://api.github.com/repos/<owner>/<repo>/dispatches');\n });\n\n it('always includes the secrets, permissions, webhook and fetch-depth checklist items', () => {\n const checklist = renderInitChecklist(undefined);\n [\n 'BIT_CONFIG_ACCESS_TOKEN',\n 'BIT_SYNC_GH_TOKEN',\n 'contents: write',\n 'Components > Export',\n 'Authorization: Bearer <PAT>',\n 'Accept: application/vnd.github+json',\n '\"event_type\":\"bit-export\"',\n '{{laneId}}',\n 'drops its custom headers',\n 'fetch-depth: 0',\n ].forEach((item) => expect(checklist, item).to.contain(item));\n });\n });\n});\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_chai","data","require","_fs","_interopRequireDefault","_os","_path","_yaml","_initScaffold","e","__esModule","default","yamlLoad","src","YAML","parse","onSection","rendered","doc","on","BRANCHES","describe","it","forEach","branch","expect","renderBitSyncWorkflow","push","to","deep","equal","renderBitReleaseWorkflow","pull_request","branches","sync","release","contain","jobs","be","an","workspaceDir","beforeEach","fs","mkdtempSync","path","join","os","tmpdir","afterEach","rmSync","recursive","force","scaffoldWorkflowFiles","relativePath","WORKFLOW_RELATIVE_PATHS","status","read","rel","readFileSync","syncAbsPath","mkdirSync","dirname","writeFileSync","SHOP","owner","repo","host","REMOTES","undefined","remote","expected","deriveOwnerRepo","String","derived","renderInitChecklist","not","saved","api","process","env","GITHUB_API_URL","server","GITHUB_SERVER_URL","ownerRepo","checklist","item"],"sources":["init-scaffold.spec.ts"],"sourcesContent":["import { expect } from 'chai';\nimport fs from 'fs';\nimport os from 'os';\nimport path from 'path';\nimport YAML from 'yaml';\nimport {\n WORKFLOW_RELATIVE_PATHS,\n renderBitSyncWorkflow,\n renderBitReleaseWorkflow,\n scaffoldWorkflowFiles,\n deriveOwnerRepo,\n renderInitChecklist,\n} from './init-scaffold';\nimport type { OwnerRepo } from './init-scaffold';\n\nconst yamlLoad = (src: string) => YAML.parse(src);\n\n/** YAML 1.1-schema parsers resolve the plain scalar key `on` to `true`, so accept either key. */\nfunction onSection(rendered: string): any {\n const doc = yamlLoad(rendered) as any;\n return doc.on ?? doc[true as any];\n}\n\n/**\n * Parsed, not substring-matched: the substitution point sits inside a YAML flow sequence, where `,` and\n * `]` are structural and a substring match is blind to exactly the damage an unquoted value does. `$` is\n * git-legal and `$&`/`$'`/`$$` are special in a string replacement, so those must arrive verbatim too.\n */\nconst BRANCHES = ['main', 'develop', 'release/2026', 'release/main', 'a,b]c', \"it's/a-branch\", \"a$'b\", 'a$&b', 'a$$b', 'a$`b']; // prettier-ignore\n\ndescribe('init-scaffold', () => {\n describe('the rendered workflows', () => {\n it('put the default branch in as exactly one element of each template’s branch filter', () => {\n BRANCHES.forEach((branch) => {\n expect(onSection(renderBitSyncWorkflow(branch)).push['branches-ignore'], branch).to.deep.equal([\n branch,\n 'bit-sync/**',\n ]);\n expect(onSection(renderBitReleaseWorkflow(branch)).pull_request.branches, branch).to.deep.equal([branch]);\n });\n });\n\n it('quote the value rather than escape it, and touch nothing else in the document', () => {\n const sync = renderBitSyncWorkflow('develop');\n const release = renderBitReleaseWorkflow('develop');\n expect(sync).to.contain(\"branches-ignore: ['develop', 'bit-sync/**']\");\n expect(release).to.contain(\"branches: ['develop']\");\n // a naive replace-all of \"main\" would rewrite every one of these\n expect(sync).to.contain('main-sync-branch: bit-sync/main');\n expect(sync).to.contain('bit-main-export');\n expect(sync).to.contain('main export)');\n expect(sync).to.contain('${{ secrets.BIT_CONFIG_ACCESS_TOKEN }}');\n expect(release).to.contain(\"github.event.pull_request.head.ref != 'bit-sync/main'\");\n expect(release).to.contain('main-sync-branch: bit-sync/main');\n // YAML single-quote escaping, and the rest of the document intact\n expect(renderBitSyncWorkflow(\"it's/a-branch\")).to.contain(\"'it''s/a-branch'\");\n expect(yamlLoad(renderBitSyncWorkflow('release/main')).jobs).to.be.an('object');\n });\n });\n\n describe('scaffoldWorkflowFiles', () => {\n let workspaceDir: string;\n\n beforeEach(() => {\n workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), 'init-scaffold-'));\n });\n\n afterEach(() => {\n fs.rmSync(workspaceDir, { recursive: true, force: true });\n });\n\n it('writes both workflow files with the default branch substituted, creating .github/workflows/', () => {\n expect(scaffoldWorkflowFiles(workspaceDir, 'develop')).to.deep.equal([\n { relativePath: WORKFLOW_RELATIVE_PATHS.sync, status: 'written' },\n { relativePath: WORKFLOW_RELATIVE_PATHS.release, status: 'written' },\n ]);\n const read = (rel: string) => fs.readFileSync(path.join(workspaceDir, rel), 'utf8');\n expect(read(WORKFLOW_RELATIVE_PATHS.sync)).to.contain(\"branches-ignore: ['develop', 'bit-sync/**']\");\n expect(read(WORKFLOW_RELATIVE_PATHS.release)).to.contain(\"branches: ['develop']\");\n });\n\n it('is idempotent: a second run skips both files rather than overwriting them', () => {\n scaffoldWorkflowFiles(workspaceDir, 'develop');\n expect(scaffoldWorkflowFiles(workspaceDir, 'develop')).to.deep.equal([\n { relativePath: WORKFLOW_RELATIVE_PATHS.sync, status: 'skipped' },\n { relativePath: WORKFLOW_RELATIVE_PATHS.release, status: 'skipped' },\n ]);\n });\n\n it('skips only the file that already exists, writing the other one', () => {\n const syncAbsPath = path.join(workspaceDir, WORKFLOW_RELATIVE_PATHS.sync);\n fs.mkdirSync(path.dirname(syncAbsPath), { recursive: true });\n fs.writeFileSync(syncAbsPath, 'hand-edited content, do not touch\\n');\n expect(scaffoldWorkflowFiles(workspaceDir, 'develop')).to.deep.equal([\n { relativePath: WORKFLOW_RELATIVE_PATHS.sync, status: 'skipped' },\n { relativePath: WORKFLOW_RELATIVE_PATHS.release, status: 'written' },\n ]);\n expect(fs.readFileSync(syncAbsPath, 'utf8')).to.equal('hand-edited content, do not touch\\n');\n });\n });\n\n describe('deriveOwnerRepo', () => {\n const SHOP = { owner: 'acme', repo: 'shop', host: 'github.com' };\n const REMOTES: Array<[string | undefined, OwnerRepo | undefined]> = [\n ['git@github.com:acme/shop.git', SHOP],\n ['https://github.com/acme/shop.git', SHOP],\n ['https://github.com/acme/shop', SHOP],\n ['https://gitlab.com/acme/shop.git', undefined],\n // a local/bare remote has no host at all\n ['/path/to/bare.git', undefined],\n ['file:///path/to/bare.git', undefined],\n [undefined, undefined],\n ];\n\n it('parses a GitHub remote in either form, and nothing else', () => {\n REMOTES.forEach(([remote, expected]) => expect(deriveOwnerRepo(remote), String(remote)).to.deep.equal(expected));\n });\n });\n\n describe('renderInitChecklist', () => {\n it('renders a real dispatch URL when owner/repo were derived, a placeholder when not', () => {\n const derived = renderInitChecklist({ owner: 'acme', repo: 'shop', host: 'github.com' });\n expect(derived).to.contain('https://api.github.com/repos/acme/shop/dispatches');\n expect(derived).to.not.contain('<owner>/<repo>');\n expect(renderInitChecklist(undefined)).to.contain('https://api.github.com/repos/<owner>/<repo>/dispatches');\n });\n\n it('derives the repository and the dispatch URL from a GitHub Enterprise Server remote', () => {\n const saved = { api: process.env.GITHUB_API_URL, server: process.env.GITHUB_SERVER_URL };\n process.env.GITHUB_API_URL = 'https://ghe.corp.example/api/v3';\n process.env.GITHUB_SERVER_URL = 'https://ghe.corp.example';\n try {\n const ownerRepo = deriveOwnerRepo('git@ghe.corp.example:acme/store.git');\n expect(ownerRepo).to.deep.equal({ owner: 'acme', repo: 'store', host: 'ghe.corp.example' });\n expect(renderInitChecklist(ownerRepo)).to.contain(\n 'https://ghe.corp.example/api/v3/repos/acme/store/dispatches'\n );\n } finally {\n if (saved.api === undefined) delete process.env.GITHUB_API_URL;\n else process.env.GITHUB_API_URL = saved.api;\n if (saved.server === undefined) delete process.env.GITHUB_SERVER_URL;\n else process.env.GITHUB_SERVER_URL = saved.server;\n }\n });\n\n describe('on a GHES-configured runner', () => {\n const saved: Record<string, string | undefined> = {};\n beforeEach(() => {\n saved.api = process.env.GITHUB_API_URL;\n saved.server = process.env.GITHUB_SERVER_URL;\n process.env.GITHUB_SERVER_URL = 'https://ghe.corp.example';\n });\n afterEach(() => {\n if (saved.api === undefined) delete process.env.GITHUB_API_URL;\n else process.env.GITHUB_API_URL = saved.api;\n if (saved.server === undefined) delete process.env.GITHUB_SERVER_URL;\n else process.env.GITHUB_SERVER_URL = saved.server;\n });\n\n it('names api.github.com for a github.com origin', () => {\n process.env.GITHUB_API_URL = 'https://ghe.corp.example/api/v3';\n const checklist = renderInitChecklist(deriveOwnerRepo('git@github.com:acme/shop.git'));\n expect(checklist).to.contain('https://api.github.com/repos/acme/shop/dispatches');\n expect(checklist).to.not.contain('ghe.corp.example');\n });\n\n it('derives <server>/api/v3 for an enterprise origin when GITHUB_API_URL is unset', () => {\n delete process.env.GITHUB_API_URL;\n expect(renderInitChecklist(deriveOwnerRepo('https://ghe.corp.example/acme/store.git'))).to.contain(\n 'https://ghe.corp.example/api/v3/repos/acme/store/dispatches'\n );\n });\n\n it('names no API for an enterprise origin whose GITHUB_API_URL is on another host', () => {\n process.env.GITHUB_API_URL = 'https://api.github.com';\n const checklist = renderInitChecklist(deriveOwnerRepo('https://ghe.corp.example/acme/store.git'));\n expect(checklist).to.contain('<GitHub API URL>/repos/acme/store/dispatches');\n expect(checklist).to.contain('GITHUB_API_URL \"https://api.github.com\"');\n expect(checklist).to.not.contain('https://api.github.com/repos');\n });\n });\n\n it('always includes the secrets, permissions, webhook and fetch-depth checklist items', () => {\n const checklist = renderInitChecklist(undefined);\n [\n 'BIT_CONFIG_ACCESS_TOKEN',\n 'BIT_SYNC_GH_TOKEN',\n 'contents: write',\n 'Components > Export',\n 'Authorization: Bearer <PAT>',\n 'Accept: application/vnd.github+json',\n '\"event_type\":\"bit-export\"',\n '{{laneId}}',\n 'drops its custom headers',\n 'fetch-depth: 0',\n ].forEach((item) => expect(checklist, item).to.contain(item));\n });\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.632",
3
+ "version": "1.0.634",
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.632"
9
+ "version": "1.0.634"
10
10
  },
11
11
  "dependencies": {
12
12
  "chalk": "4.1.2",
@@ -35,15 +35,15 @@
35
35
  "@teambit/legacy.scope": "0.0.184",
36
36
  "@teambit/legacy.bit-map": "0.0.241",
37
37
  "@teambit/toolbox.crypto.sha1": "0.0.24",
38
- "@teambit/workspace": "1.0.1231",
39
- "@teambit/builder": "1.0.1231",
40
- "@teambit/checkout": "1.0.1235",
41
- "@teambit/config-merger": "0.0.1098",
42
- "@teambit/export": "1.0.1233",
43
- "@teambit/importer": "1.0.1231",
44
- "@teambit/lanes": "1.0.1256",
45
- "@teambit/snapping": "1.0.1233",
46
- "@teambit/status": "1.0.1260"
38
+ "@teambit/workspace": "1.0.1232",
39
+ "@teambit/builder": "1.0.1232",
40
+ "@teambit/checkout": "1.0.1236",
41
+ "@teambit/config-merger": "0.0.1099",
42
+ "@teambit/export": "1.0.1234",
43
+ "@teambit/importer": "1.0.1232",
44
+ "@teambit/lanes": "1.0.1257",
45
+ "@teambit/snapping": "1.0.1234",
46
+ "@teambit/status": "1.0.1261"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@types/lodash": "4.14.165",
@@ -186,6 +186,35 @@ describe('GitHubHostProvider', () => {
186
186
  expect(selection.reason).to.contain('no git host provider is configured');
187
187
  });
188
188
 
189
+ // GitHub Enterprise Server: Actions names the instance in GITHUB_SERVER_URL, and that host's remotes
190
+ // must select this provider exactly as github.com remotes do — or the run degrades to git-only.
191
+ it('claims, configures and is selected for a GitHub Enterprise Server remote', () => {
192
+ const ghesKeys = ['GITHUB_API_URL', 'GITHUB_SERVER_URL'];
193
+ const savedGhes = ghesKeys.map((key) => process.env[key]);
194
+ process.env.GITHUB_API_URL = 'https://ghe.corp.example/api/v3';
195
+ process.env.GITHUB_SERVER_URL = 'https://ghe.corp.example';
196
+ process.env.BIT_GITHUB_TOKEN = 'tok';
197
+ try {
198
+ ['https://ghe.corp.example/acme/store.git', 'git@ghe.corp.example:acme/store.git'].forEach((remote) => {
199
+ const provider = new GitHubHostProvider();
200
+ expect(provider.matchesRemote(remote), remote).to.equal(true);
201
+ expect(provider.isConfigured(remote), remote).to.equal(true);
202
+ expect(selectGitHostProvider([new GitHubHostProvider()], remote).provider?.name, remote).to.equal('github');
203
+ });
204
+ ['https://evil.example/ghe.corp.example/x.git', 'https://ghe.corp.example.evil.com/x.git'].forEach((remote) => {
205
+ expect(new GitHubHostProvider().matchesRemote(remote), remote).to.equal(false);
206
+ expect(new GitHubHostProvider().isConfigured(remote), remote).to.equal(false);
207
+ });
208
+ } finally {
209
+ ghesKeys.forEach((key, i) => {
210
+ if (savedGhes[i] === undefined) delete process.env[key];
211
+ else process.env[key] = savedGhes[i];
212
+ });
213
+ }
214
+ // without GITHUB_SERVER_URL the same host is nobody's
215
+ expect(new GitHubHostProvider().matchesRemote('https://ghe.corp.example/acme/store.git')).to.equal(false);
216
+ });
217
+
189
218
  it('reports what is missing rather than failing obscurely when a PR call happens unconfigured', async () => {
190
219
  let message = '';
191
220
  await new GitHubHostProvider().findPrByBranch('lane-x').catch((err) => {