@teambit/ci 1.0.485 → 1.0.487
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/ci.docs.mdx +344 -83
- package/commands/sync.cmd.ts +77 -0
- package/dist/ci.docs.mdx +344 -83
- package/dist/ci.main.runtime.d.ts +67 -6
- package/dist/ci.main.runtime.js +152 -25
- package/dist/ci.main.runtime.js.map +1 -1
- package/dist/commands/sync.cmd.d.ts +34 -0
- package/dist/commands/sync.cmd.js +57 -0
- package/dist/commands/sync.cmd.js.map +1 -0
- package/dist/git.d.ts +11 -1
- package/dist/git.js +11 -1
- package/dist/git.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.js +26 -1
- package/dist/index.js.map +1 -1
- package/dist/{preview-1785858957533.js → preview-1785883495880.js} +1 -1
- package/dist/sync/git-host-provider.d.ts +47 -0
- package/dist/sync/git-host-provider.js +54 -0
- package/dist/sync/git-host-provider.js.map +1 -0
- package/dist/sync/git-host-provider.spec.d.ts +1 -0
- package/dist/sync/git-host-provider.spec.js +171 -0
- package/dist/sync/git-host-provider.spec.js.map +1 -0
- package/dist/sync/git-ops.d.ts +171 -0
- package/dist/sync/git-ops.js +354 -0
- package/dist/sync/git-ops.js.map +1 -0
- package/dist/sync/git-ops.spec.d.ts +1 -0
- package/dist/sync/git-ops.spec.js +476 -0
- package/dist/sync/git-ops.spec.js.map +1 -0
- package/dist/sync/github-client.d.ts +79 -0
- package/dist/sync/github-client.js +198 -0
- package/dist/sync/github-client.js.map +1 -0
- package/dist/sync/github-client.spec.d.ts +1 -0
- package/dist/sync/github-client.spec.js +205 -0
- package/dist/sync/github-client.spec.js.map +1 -0
- package/dist/sync/init-scaffold.d.ts +40 -0
- package/dist/sync/init-scaffold.js +326 -0
- package/dist/sync/init-scaffold.js.map +1 -0
- package/dist/sync/init-scaffold.spec.d.ts +1 -0
- package/dist/sync/init-scaffold.spec.js +169 -0
- package/dist/sync/init-scaffold.spec.js.map +1 -0
- package/dist/sync/lane-sync-executor.d.ts +256 -0
- package/dist/sync/lane-sync-executor.js +1249 -0
- package/dist/sync/lane-sync-executor.js.map +1 -0
- package/dist/sync/lane-sync-executor.spec.d.ts +1 -0
- package/dist/sync/lane-sync-executor.spec.js +416 -0
- package/dist/sync/lane-sync-executor.spec.js.map +1 -0
- package/dist/sync/main-sync-executor.d.ts +62 -0
- package/dist/sync/main-sync-executor.js +305 -0
- package/dist/sync/main-sync-executor.js.map +1 -0
- package/dist/sync/sync-config.d.ts +83 -0
- package/dist/sync/sync-config.js +187 -0
- package/dist/sync/sync-config.js.map +1 -0
- package/dist/sync/sync-config.spec.d.ts +1 -0
- package/dist/sync/sync-config.spec.js +254 -0
- package/dist/sync/sync-config.spec.js.map +1 -0
- package/dist/sync/sync-orchestrator.d.ts +76 -0
- package/dist/sync/sync-orchestrator.js +396 -0
- package/dist/sync/sync-orchestrator.js.map +1 -0
- package/dist/sync/sync-orchestrator.spec.d.ts +1 -0
- package/dist/sync/sync-orchestrator.spec.js +155 -0
- package/dist/sync/sync-orchestrator.spec.js.map +1 -0
- package/dist/sync/sync-planner.d.ts +60 -0
- package/dist/sync/sync-planner.js +114 -0
- package/dist/sync/sync-planner.js.map +1 -0
- package/dist/sync/sync-planner.spec.d.ts +1 -0
- package/dist/sync/sync-planner.spec.js +210 -0
- package/dist/sync/sync-planner.spec.js.map +1 -0
- package/dist/sync/sync-state.d.ts +94 -0
- package/dist/sync/sync-state.js +178 -0
- package/dist/sync/sync-state.js.map +1 -0
- package/dist/sync/sync-state.spec.d.ts +1 -0
- package/dist/sync/sync-state.spec.js +271 -0
- package/dist/sync/sync-state.spec.js.map +1 -0
- package/dist/sync/workspace-lane.d.ts +13 -0
- package/dist/sync/workspace-lane.js +27 -0
- package/dist/sync/workspace-lane.js.map +1 -0
- package/package.json +20 -15
- package/sync/git-host-provider.spec.ts +197 -0
- package/sync/git-host-provider.ts +89 -0
- package/sync/git-ops.spec.ts +506 -0
- package/sync/git-ops.ts +334 -0
- package/sync/github-client.spec.ts +174 -0
- package/sync/github-client.ts +209 -0
- package/sync/init-scaffold.spec.ts +142 -0
- package/sync/init-scaffold.ts +340 -0
- package/sync/lane-sync-executor.spec.ts +389 -0
- package/sync/lane-sync-executor.ts +1363 -0
- package/sync/main-sync-executor.ts +321 -0
- package/sync/sync-config.spec.ts +283 -0
- package/sync/sync-config.ts +214 -0
- package/sync/sync-orchestrator.spec.ts +120 -0
- package/sync/sync-orchestrator.ts +386 -0
- package/sync/sync-planner.spec.ts +126 -0
- package/sync/sync-planner.ts +99 -0
- package/sync/sync-state.spec.ts +263 -0
- package/sync/sync-state.ts +176 -0
- package/sync/workspace-lane.ts +20 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { Command, CommandOptions } from '@teambit/cli';
|
|
2
|
+
import type { Logger } from '@teambit/logger';
|
|
3
|
+
import { type Workspace } from '@teambit/workspace';
|
|
4
|
+
import type { CiMain } from '../ci.main.runtime';
|
|
5
|
+
type Options = {
|
|
6
|
+
branch?: string;
|
|
7
|
+
all?: boolean;
|
|
8
|
+
main?: boolean;
|
|
9
|
+
dryRun?: boolean;
|
|
10
|
+
init?: boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare class CiSyncCmd implements Command {
|
|
13
|
+
private workspace;
|
|
14
|
+
private logger;
|
|
15
|
+
private ci;
|
|
16
|
+
name: string;
|
|
17
|
+
arguments: {
|
|
18
|
+
name: string;
|
|
19
|
+
description: string;
|
|
20
|
+
}[];
|
|
21
|
+
description: string;
|
|
22
|
+
extendedDescription: string;
|
|
23
|
+
group: string;
|
|
24
|
+
/**
|
|
25
|
+
* Changing any user-facing text on this command requires regenerating the CLI reference (the
|
|
26
|
+
* `generate-cli-reference*` npm scripts), or the `check_generated_reference` CI job fails. The
|
|
27
|
+
* scripts invoke whatever `bit` is on PATH — put `<repo>/bin/bit.js` first — and a local workspace
|
|
28
|
+
* may register extra commands, so inspect the generated diff and keep only the text that changed.
|
|
29
|
+
*/
|
|
30
|
+
options: CommandOptions;
|
|
31
|
+
constructor(workspace: Workspace, logger: Logger, ci: CiMain);
|
|
32
|
+
report([lane]: [string], options: Options): Promise<string>;
|
|
33
|
+
}
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.CiSyncCmd = void 0;
|
|
7
|
+
function _workspace() {
|
|
8
|
+
const data = require("@teambit/workspace");
|
|
9
|
+
_workspace = function () {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
|
|
15
|
+
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
|
|
16
|
+
function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
|
|
17
|
+
class CiSyncCmd {
|
|
18
|
+
constructor(workspace, logger, ci) {
|
|
19
|
+
this.workspace = workspace;
|
|
20
|
+
this.logger = logger;
|
|
21
|
+
this.ci = ci;
|
|
22
|
+
_defineProperty(this, "name", 'sync [lane]');
|
|
23
|
+
_defineProperty(this, "arguments", [{
|
|
24
|
+
name: 'lane',
|
|
25
|
+
description: 'the lane to reconcile: either a lane name (hosted on the workspace\'s defaultScope) or a scope-qualified lane id, "other-org.other-scope/my-lane", for a lane hosted on another scope. Its components must still all live in this workspace\'s defaultScope'
|
|
26
|
+
}]);
|
|
27
|
+
_defineProperty(this, "description", 'Reconciles Bit lanes and the main scope with git branches and pull requests.');
|
|
28
|
+
_defineProperty(this, "extendedDescription", `Stateless reconciler: compares each mapped lane's remote head against the state the branch itself records, and converges — importing lane changes onto the branch, exporting dev commits to the lane, or opening/closing PRs. That state comes from bit's own data: the .bitmap committed on the branch, which records the lane the branch mirrors and the exact version of every component on it. The "chore(bit-sync)" subject, "Bit-Lane-Head" trailer and "[bit-sync]" marker on sync commits are annotations for humans and triggers; the only decision that consults one is branch deletion, which additionally requires the marker to prove the reconciler wrote the branch tip. The main scope is reconciled by checking the workspace out to its latest exported versions and proposing the result as a sync PR. Triggers (webhook, push, cron) only decide when it runs, never what it does. Safe to re-run at any time; converged state is a no-op. A lane whose components are not all in this workspace's defaultScope is a cross-scope lane: no branch is created for it (it would leak another repository's components into this one) — enumerated runs skip it and stay green, an explicitly named one is refused, and a lane that became cross-scope after its branch existed is halted for a human. Configure mapping under \`"teambit.git/ci": { "sync": { ... } }\` in workspace.jsonc.`);
|
|
29
|
+
_defineProperty(this, "group", 'collaborate');
|
|
30
|
+
/**
|
|
31
|
+
* Changing any user-facing text on this command requires regenerating the CLI reference (the
|
|
32
|
+
* `generate-cli-reference*` npm scripts), or the `check_generated_reference` CI job fails. The
|
|
33
|
+
* scripts invoke whatever `bit` is on PATH — put `<repo>/bin/bit.js` first — and a local workspace
|
|
34
|
+
* may register extra commands, so inspect the generated diff and keep only the text that changed.
|
|
35
|
+
*/
|
|
36
|
+
_defineProperty(this, "options", [['', 'branch <branch>', 'Resolve the lane from this git branch name using the sync mapping config (cannot be combined with --all)'], ['', 'all', 'Reconcile every mapped lane plus the main scope (the default when no target is given; cannot be combined with a lane argument, --branch or --main)'], ['', 'main', 'Reconcile only the main scope against the default branch, opening a sync PR on drift (conflicts resolve in favour of the scope)'], ['', 'dry-run', 'Print the planned action per target. Nothing is pushed and no pull request is created or modified; the working tree is still written and then restored, so a dirty tree is refused rather than discarded'], ['', 'init', 'One-command onboarding: scaffold .github/workflows/bit-sync.yml + bit-release.yml (with this repository\'s actual default branch substituted), add the `"teambit.git/ci": { "sync": {} }` config block to workspace.jsonc if absent, and print the remaining manual-steps checklist (secrets + bit.cloud webhook). Writes nothing else and never overwrites an existing workflow file. Cannot be combined with a lane argument or any other flag.']]);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// `[lane]: [string]` rather than `[string?]`: `CLIArgs` does not admit an undefined-carrying tuple.
|
|
40
|
+
// The argument is genuinely optional at runtime, hence the `|| undefined` below.
|
|
41
|
+
async report([lane], options) {
|
|
42
|
+
this.logger.console('\n\n');
|
|
43
|
+
this.logger.console('Initializing sync command');
|
|
44
|
+
if (!this.workspace) throw new (_workspace().OutsideWorkspaceError)();
|
|
45
|
+
return this.ci.sync({
|
|
46
|
+
lane: lane || undefined,
|
|
47
|
+
branch: options.branch,
|
|
48
|
+
all: options.all,
|
|
49
|
+
main: options.main,
|
|
50
|
+
dryRun: options.dryRun,
|
|
51
|
+
init: options.init
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.CiSyncCmd = CiSyncCmd;
|
|
56
|
+
|
|
57
|
+
//# sourceMappingURL=sync.cmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_workspace","data","require","_defineProperty","e","r","t","_toPropertyKey","Object","defineProperty","value","enumerable","configurable","writable","i","_toPrimitive","Symbol","toPrimitive","call","TypeError","String","Number","CiSyncCmd","constructor","workspace","logger","ci","name","description","report","lane","options","console","OutsideWorkspaceError","sync","undefined","branch","all","main","dryRun","init","exports"],"sources":["sync.cmd.ts"],"sourcesContent":["import type { Command, CommandOptions } from '@teambit/cli';\nimport type { Logger } from '@teambit/logger';\nimport { OutsideWorkspaceError, type Workspace } from '@teambit/workspace';\nimport type { CiMain } from '../ci.main.runtime';\n\ntype Options = { branch?: string; all?: boolean; main?: boolean; dryRun?: boolean; init?: boolean };\n\nexport class CiSyncCmd implements Command {\n name = 'sync [lane]';\n arguments = [\n {\n name: 'lane',\n description:\n 'the lane to reconcile: either a lane name (hosted on the workspace\\'s defaultScope) or a scope-qualified lane id, \"other-org.other-scope/my-lane\", for a lane hosted on another scope. Its components must still all live in this workspace\\'s defaultScope',\n },\n ];\n description = 'Reconciles Bit lanes and the main scope with git branches and pull requests.';\n extendedDescription = `Stateless reconciler: compares each mapped lane's remote head against the state the branch itself records, and converges — importing lane changes onto the branch, exporting dev commits to the lane, or opening/closing PRs. That state comes from bit's own data: the .bitmap committed on the branch, which records the lane the branch mirrors and the exact version of every component on it. The \"chore(bit-sync)\" subject, \"Bit-Lane-Head\" trailer and \"[bit-sync]\" marker on sync commits are annotations for humans and triggers; the only decision that consults one is branch deletion, which additionally requires the marker to prove the reconciler wrote the branch tip. The main scope is reconciled by checking the workspace out to its latest exported versions and proposing the result as a sync PR. Triggers (webhook, push, cron) only decide when it runs, never what it does. Safe to re-run at any time; converged state is a no-op. A lane whose components are not all in this workspace's defaultScope is a cross-scope lane: no branch is created for it (it would leak another repository's components into this one) — enumerated runs skip it and stay green, an explicitly named one is refused, and a lane that became cross-scope after its branch existed is halted for a human. Configure mapping under \\`\"teambit.git/ci\": { \"sync\": { ... } }\\` in workspace.jsonc.`;\n group = 'collaborate';\n\n /**\n * Changing any user-facing text on this command requires regenerating the CLI reference (the\n * `generate-cli-reference*` npm scripts), or the `check_generated_reference` CI job fails. The\n * scripts invoke whatever `bit` is on PATH — put `<repo>/bin/bit.js` first — and a local workspace\n * may register extra commands, so inspect the generated diff and keep only the text that changed.\n */\n options: CommandOptions = [\n [\n '',\n 'branch <branch>',\n 'Resolve the lane from this git branch name using the sync mapping config (cannot be combined with --all)',\n ],\n [\n '',\n 'all',\n 'Reconcile every mapped lane plus the main scope (the default when no target is given; cannot be combined with a lane argument, --branch or --main)',\n ],\n [\n '',\n 'main',\n 'Reconcile only the main scope against the default branch, opening a sync PR on drift (conflicts resolve in favour of the scope)',\n ],\n [\n '',\n 'dry-run',\n 'Print the planned action per target. Nothing is pushed and no pull request is created or modified; the working tree is still written and then restored, so a dirty tree is refused rather than discarded',\n ],\n [\n '',\n 'init',\n 'One-command onboarding: scaffold .github/workflows/bit-sync.yml + bit-release.yml (with this repository\\'s actual default branch substituted), add the `\"teambit.git/ci\": { \"sync\": {} }` config block to workspace.jsonc if absent, and print the remaining manual-steps checklist (secrets + bit.cloud webhook). Writes nothing else and never overwrites an existing workflow file. Cannot be combined with a lane argument or any other flag.',\n ],\n ];\n\n constructor(\n private workspace: Workspace,\n private logger: Logger,\n private ci: CiMain\n ) {}\n\n // `[lane]: [string]` rather than `[string?]`: `CLIArgs` does not admit an undefined-carrying tuple.\n // The argument is genuinely optional at runtime, hence the `|| undefined` below.\n async report([lane]: [string], options: Options) {\n this.logger.console('\\n\\n');\n this.logger.console('Initializing sync command');\n if (!this.workspace) throw new OutsideWorkspaceError();\n\n return this.ci.sync({\n lane: lane || undefined,\n branch: options.branch,\n all: options.all,\n main: options.main,\n dryRun: options.dryRun,\n init: options.init,\n });\n }\n}\n"],"mappings":";;;;;;AAEA,SAAAA,WAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,UAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAA2E,SAAAE,gBAAAC,CAAA,EAAAC,CAAA,EAAAC,CAAA,YAAAD,CAAA,GAAAE,cAAA,CAAAF,CAAA,MAAAD,CAAA,GAAAI,MAAA,CAAAC,cAAA,CAAAL,CAAA,EAAAC,CAAA,IAAAK,KAAA,EAAAJ,CAAA,EAAAK,UAAA,MAAAC,YAAA,MAAAC,QAAA,UAAAT,CAAA,CAAAC,CAAA,IAAAC,CAAA,EAAAF,CAAA;AAAA,SAAAG,eAAAD,CAAA,QAAAQ,CAAA,GAAAC,YAAA,CAAAT,CAAA,uCAAAQ,CAAA,GAAAA,CAAA,GAAAA,CAAA;AAAA,SAAAC,aAAAT,CAAA,EAAAD,CAAA,2BAAAC,CAAA,KAAAA,CAAA,SAAAA,CAAA,MAAAF,CAAA,GAAAE,CAAA,CAAAU,MAAA,CAAAC,WAAA,kBAAAb,CAAA,QAAAU,CAAA,GAAAV,CAAA,CAAAc,IAAA,CAAAZ,CAAA,EAAAD,CAAA,uCAAAS,CAAA,SAAAA,CAAA,YAAAK,SAAA,yEAAAd,CAAA,GAAAe,MAAA,GAAAC,MAAA,EAAAf,CAAA;AAKpE,MAAMgB,SAAS,CAAoB;EA+CxCC,WAAWA,CACDC,SAAoB,EACpBC,MAAc,EACdC,EAAU,EAClB;IAAA,KAHQF,SAAoB,GAApBA,SAAoB;IAAA,KACpBC,MAAc,GAAdA,MAAc;IAAA,KACdC,EAAU,GAAVA,EAAU;IAAAvB,eAAA,eAjDb,aAAa;IAAAA,eAAA,oBACR,CACV;MACEwB,IAAI,EAAE,MAAM;MACZC,WAAW,EACT;IACJ,CAAC,CACF;IAAAzB,eAAA,sBACa,8EAA8E;IAAAA,eAAA,8BACtE,60CAA60C;IAAAA,eAAA,gBAC31C,aAAa;IAErB;AACF;AACA;AACA;AACA;AACA;IALEA,eAAA,kBAM0B,CACxB,CACE,EAAE,EACF,iBAAiB,EACjB,0GAA0G,CAC3G,EACD,CACE,EAAE,EACF,KAAK,EACL,oJAAoJ,CACrJ,EACD,CACE,EAAE,EACF,MAAM,EACN,iIAAiI,CAClI,EACD,CACE,EAAE,EACF,SAAS,EACT,0MAA0M,CAC3M,EACD,CACE,EAAE,EACF,MAAM,EACN,mbAAmb,CACpb,CACF;EAME;;EAEH;EACA;EACA,MAAM0B,MAAMA,CAAC,CAACC,IAAI,CAAW,EAAEC,OAAgB,EAAE;IAC/C,IAAI,CAACN,MAAM,CAACO,OAAO,CAAC,MAAM,CAAC;IAC3B,IAAI,CAACP,MAAM,CAACO,OAAO,CAAC,2BAA2B,CAAC;IAChD,IAAI,CAAC,IAAI,CAACR,SAAS,EAAE,MAAM,KAAIS,kCAAqB,EAAC,CAAC;IAEtD,OAAO,IAAI,CAACP,EAAE,CAACQ,IAAI,CAAC;MAClBJ,IAAI,EAAEA,IAAI,IAAIK,SAAS;MACvBC,MAAM,EAAEL,OAAO,CAACK,MAAM;MACtBC,GAAG,EAAEN,OAAO,CAACM,GAAG;MAChBC,IAAI,EAAEP,OAAO,CAACO,IAAI;MAClBC,MAAM,EAAER,OAAO,CAACQ,MAAM;MACtBC,IAAI,EAAET,OAAO,CAACS;IAChB,CAAC,CAAC;EACJ;AACF;AAACC,OAAA,CAAAnB,SAAA,GAAAA,SAAA","ignoreList":[]}
|
package/dist/git.d.ts
CHANGED
|
@@ -1 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The shared git client for the `bit ci` commands. No `baseDir` is passed, so every command runs in
|
|
3
|
+
* `process.cwd()` — the workspace root for a `bit ci` invocation.
|
|
4
|
+
*
|
|
5
|
+
* Do NOT chain a task onto this (as in the previous `simpleGit().clean(CleanOptions.FORCE)`):
|
|
6
|
+
* simple-git's task methods queue and *run* their command, and the chainable they return only looks
|
|
7
|
+
* like configuration. That form executed `git clean -f` in `process.cwd()` at module-import time — on
|
|
8
|
+
* any bit command that loaded this aspect — silently deleting untracked files. Verified empirically
|
|
9
|
+
* before removal. Cleaning is done deliberately, and scoped, in `sync/git-ops.ts`.
|
|
10
|
+
*/
|
|
11
|
+
export declare const git: import("simple-git").SimpleGit;
|
package/dist/git.js
CHANGED
|
@@ -11,6 +11,16 @@ function _simpleGit() {
|
|
|
11
11
|
};
|
|
12
12
|
return data;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
/**
|
|
15
|
+
* The shared git client for the `bit ci` commands. No `baseDir` is passed, so every command runs in
|
|
16
|
+
* `process.cwd()` — the workspace root for a `bit ci` invocation.
|
|
17
|
+
*
|
|
18
|
+
* Do NOT chain a task onto this (as in the previous `simpleGit().clean(CleanOptions.FORCE)`):
|
|
19
|
+
* simple-git's task methods queue and *run* their command, and the chainable they return only looks
|
|
20
|
+
* like configuration. That form executed `git clean -f` in `process.cwd()` at module-import time — on
|
|
21
|
+
* any bit command that loaded this aspect — silently deleting untracked files. Verified empirically
|
|
22
|
+
* before removal. Cleaning is done deliberately, and scoped, in `sync/git-ops.ts`.
|
|
23
|
+
*/
|
|
24
|
+
const git = exports.git = (0, _simpleGit().simpleGit)();
|
|
15
25
|
|
|
16
26
|
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_simpleGit","data","require","git","exports","simpleGit"
|
|
1
|
+
{"version":3,"names":["_simpleGit","data","require","git","exports","simpleGit"],"sources":["git.ts"],"sourcesContent":["import { simpleGit } from 'simple-git';\n\n/**\n * The shared git client for the `bit ci` commands. No `baseDir` is passed, so every command runs in\n * `process.cwd()` — the workspace root for a `bit ci` invocation.\n *\n * Do NOT chain a task onto this (as in the previous `simpleGit().clean(CleanOptions.FORCE)`):\n * simple-git's task methods queue and *run* their command, and the chainable they return only looks\n * like configuration. That form executed `git clean -f` in `process.cwd()` at module-import time — on\n * any bit command that loaded this aspect — silently deleting untracked files. Verified empirically\n * before removal. Cleaning is done deliberately, and scoped, in `sync/git-ops.ts`.\n */\nexport const git = simpleGit();\n"],"mappings":";;;;;;AAAA,SAAAA,WAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,UAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAME,GAAG,GAAAC,OAAA,CAAAD,GAAA,GAAG,IAAAE,sBAAS,EAAC,CAAC","ignoreList":[]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,7 @@
|
|
|
1
1
|
import { CiAspect } from './ci.aspect';
|
|
2
2
|
export default CiAspect;
|
|
3
3
|
export { CiAspect };
|
|
4
|
+
export type { CiSyncConfig } from './sync/sync-config';
|
|
5
|
+
export type { GitHostProvider, PrInfo } from './sync/git-host-provider';
|
|
6
|
+
export type { CiMain, GitHostProviderSlot } from './ci.main.runtime';
|
|
7
|
+
export { SYNC_COMMIT_MARKER, hasSyncMarker } from './sync/sync-state';
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,19 @@ Object.defineProperty(exports, "CiAspect", {
|
|
|
9
9
|
return _ci().CiAspect;
|
|
10
10
|
}
|
|
11
11
|
});
|
|
12
|
+
Object.defineProperty(exports, "SYNC_COMMIT_MARKER", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _syncState().SYNC_COMMIT_MARKER;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
12
18
|
exports.default = void 0;
|
|
19
|
+
Object.defineProperty(exports, "hasSyncMarker", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () {
|
|
22
|
+
return _syncState().hasSyncMarker;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
13
25
|
function _ci() {
|
|
14
26
|
const data = require("./ci.aspect");
|
|
15
27
|
_ci = function () {
|
|
@@ -17,6 +29,19 @@ function _ci() {
|
|
|
17
29
|
};
|
|
18
30
|
return data;
|
|
19
31
|
}
|
|
20
|
-
|
|
32
|
+
function _syncState() {
|
|
33
|
+
const data = require("./sync/sync-state");
|
|
34
|
+
_syncState = function () {
|
|
35
|
+
return data;
|
|
36
|
+
};
|
|
37
|
+
return data;
|
|
38
|
+
}
|
|
39
|
+
var _default = exports.default = _ci().CiAspect; // The git-host contract `bit ci sync` runs on. A provider aspect (gitlab, bitbucket, …) depends on
|
|
40
|
+
// CiAspect, implements `GitHostProvider`, and registers it from its own `provider()`:
|
|
41
|
+
// import type { CiMain, GitHostProvider } from '@teambit/ci';
|
|
42
|
+
// ci.registerGitHostProvider(new GitLabHostProvider());
|
|
43
|
+
// The marker `bit ci sync` stamps on its own commits, and the predicate for it. Exported so a trigger —
|
|
44
|
+
// a git hook, a webhook router, another aspect deciding whether a push was machine-generated — can share
|
|
45
|
+
// the one definition instead of re-spelling the literal and drifting from it.
|
|
21
46
|
|
|
22
47
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_ci","data","require","_default","exports","default","CiAspect"],"sources":["index.ts"],"sourcesContent":["import { CiAspect } from './ci.aspect';\n\nexport default CiAspect;\nexport { CiAspect };\n"],"mappings":"
|
|
1
|
+
{"version":3,"names":["_ci","data","require","_syncState","_default","exports","default","CiAspect"],"sources":["index.ts"],"sourcesContent":["import { CiAspect } from './ci.aspect';\n\nexport default CiAspect;\nexport { CiAspect };\nexport type { CiSyncConfig } from './sync/sync-config';\n// The git-host contract `bit ci sync` runs on. A provider aspect (gitlab, bitbucket, …) depends on\n// CiAspect, implements `GitHostProvider`, and registers it from its own `provider()`:\n// import type { CiMain, GitHostProvider } from '@teambit/ci';\n// ci.registerGitHostProvider(new GitLabHostProvider());\nexport type { GitHostProvider, PrInfo } from './sync/git-host-provider';\nexport type { CiMain, GitHostProviderSlot } from './ci.main.runtime';\n// The marker `bit ci sync` stamps on its own commits, and the predicate for it. Exported so a trigger —\n// a git hook, a webhook router, another aspect deciding whether a push was machine-generated — can share\n// the one definition instead of re-spelling the literal and drifting from it.\nexport { SYNC_COMMIT_MARKER, hasSyncMarker } from './sync/sync-state';\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAAA,IAAA;EAAA,MAAAC,IAAA,GAAAC,OAAA;EAAAF,GAAA,YAAAA,CAAA;IAAA,OAAAC,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAcA,SAAAE,WAAA;EAAA,MAAAF,IAAA,GAAAC,OAAA;EAAAC,UAAA,YAAAA,CAAA;IAAA,OAAAF,IAAA;EAAA;EAAA,OAAAA,IAAA;AAAA;AAAsE,IAAAG,QAAA,GAAAC,OAAA,CAAAC,OAAA,GAZvDC,cAAQ,EAGvB;AACA;AACA;AACA;AAGA;AACA;AACA","ignoreList":[]}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
;
|
|
2
|
-
import * as overview_0 from '/home/circleci/Library/Caches/Bit/capsules/8891be5ad/teambit.git_ci@1.0.
|
|
2
|
+
import * as overview_0 from '/home/circleci/Library/Caches/Bit/capsules/8891be5ad/teambit.git_ci@1.0.487/dist/ci.docs.mdx';
|
|
3
3
|
|
|
4
4
|
export const compositions = [];
|
|
5
5
|
export const overview = [overview_0];
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The git-host (pull request) contract `bit ci sync` is written against; nothing in the engine may
|
|
3
|
+
* reach past it. Other hosts register via `ci.registerGitHostProvider(...)`. Adding a method is a
|
|
4
|
+
* breaking change for out-of-tree providers.
|
|
5
|
+
*/
|
|
6
|
+
export type PrInfo = {
|
|
7
|
+
number: number;
|
|
8
|
+
state: 'open' | 'closed';
|
|
9
|
+
labels: string[];
|
|
10
|
+
headRef: string;
|
|
11
|
+
htmlUrl: string;
|
|
12
|
+
};
|
|
13
|
+
export interface GitHostProvider {
|
|
14
|
+
/** Stable identifier, used in logs and to tell registered providers apart. E.g. `'github'`. */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Does this provider serve the repository at `remoteUrl`? A host test, not a credentials test. */
|
|
17
|
+
matchesRemote(remoteUrl: string): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Token and repository resolvable? Must not throw (unconfigured is a normal state — the engine
|
|
20
|
+
* degrades to git-only sync), must be cheap and idempotent, and must never perform network I/O.
|
|
21
|
+
*/
|
|
22
|
+
isConfigured(remoteUrl?: string): boolean;
|
|
23
|
+
findPrByBranch(branch: string): Promise<PrInfo | undefined>;
|
|
24
|
+
createPr(opts: {
|
|
25
|
+
head: string;
|
|
26
|
+
base: string;
|
|
27
|
+
title: string;
|
|
28
|
+
body: string;
|
|
29
|
+
}): Promise<PrInfo>;
|
|
30
|
+
closePr(prNumber: number, comment?: string): Promise<void>;
|
|
31
|
+
comment(prNumber: number, body: string): Promise<void>;
|
|
32
|
+
addLabel(prNumber: number, label: string): Promise<void>;
|
|
33
|
+
}
|
|
34
|
+
/** The git host to use this run, or nothing plus the reason PR operations are being skipped. */
|
|
35
|
+
export type GitHostSelection = {
|
|
36
|
+
/** The host to use. undefined => PR-less (git-only) sync. */
|
|
37
|
+
provider?: GitHostProvider;
|
|
38
|
+
/** Set exactly when `provider` is undefined; surfaced once per run so PR-less is never silent. */
|
|
39
|
+
reason?: string;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Pick the provider that serves `remoteUrl`, or nothing (PR-less sync) plus the reason why.
|
|
43
|
+
* A claim is exclusive: configuration never overrides `matchesRemote`, because routing to whichever
|
|
44
|
+
* provider holds a token would act on the wrong host's PRs. A sole configured provider is the fallback
|
|
45
|
+
* only when no provider claims the remote; two or more unclaimed-but-configured is too ambiguous.
|
|
46
|
+
*/
|
|
47
|
+
export declare function selectGitHostProvider(providers: GitHostProvider[], remoteUrl: string | undefined): GitHostSelection;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.selectGitHostProvider = selectGitHostProvider;
|
|
7
|
+
/**
|
|
8
|
+
* The git-host (pull request) contract `bit ci sync` is written against; nothing in the engine may
|
|
9
|
+
* reach past it. Other hosts register via `ci.registerGitHostProvider(...)`. Adding a method is a
|
|
10
|
+
* breaking change for out-of-tree providers.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/** The git host to use this run, or nothing plus the reason PR operations are being skipped. */
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Pick the provider that serves `remoteUrl`, or nothing (PR-less sync) plus the reason why.
|
|
17
|
+
* A claim is exclusive: configuration never overrides `matchesRemote`, because routing to whichever
|
|
18
|
+
* provider holds a token would act on the wrong host's PRs. A sole configured provider is the fallback
|
|
19
|
+
* only when no provider claims the remote; two or more unclaimed-but-configured is too ambiguous.
|
|
20
|
+
*/
|
|
21
|
+
function selectGitHostProvider(providers, remoteUrl) {
|
|
22
|
+
if (!providers.length) {
|
|
23
|
+
return {
|
|
24
|
+
reason: 'no git host provider is registered — skipping all pull request operations'
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const claimants = remoteUrl ? providers.filter(provider => provider.matchesRemote(remoteUrl)) : [];
|
|
28
|
+
if (claimants.length) {
|
|
29
|
+
const configured = claimants.find(provider => provider.isConfigured(remoteUrl));
|
|
30
|
+
if (configured) return {
|
|
31
|
+
provider: configured
|
|
32
|
+
};
|
|
33
|
+
return {
|
|
34
|
+
reason: `the ${listNames(claimants)} git host provider${claimants.length > 1 ? 's' : ''} serve${claimants.length > 1 ? '' : 's'} this repository's "origin" remote but ${claimants.length > 1 ? 'none is' : 'is not'} configured ` + `(missing credentials or repository) — skipping all pull request operations. No other provider is ` + `used in its place: that would act on the wrong host.`
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const configured = providers.filter(provider => provider.isConfigured(remoteUrl));
|
|
38
|
+
if (configured.length === 1) return {
|
|
39
|
+
provider: configured[0]
|
|
40
|
+
};
|
|
41
|
+
if (configured.length > 1) {
|
|
42
|
+
return {
|
|
43
|
+
reason: `no git host provider claims this repository's "origin" remote, and ${configured.length} are ` + `configured (${listNames(configured)}) — too ambiguous to pick one, skipping all pull request operations`
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
reason: `no git host provider is configured${remoteUrl ? '' : ' (and the "origin" remote could not be read)'} — ` + `skipping all pull request operations`
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function listNames(providers) {
|
|
51
|
+
return providers.map(provider => `"${provider.name}"`).join(', ');
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=git-host-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["selectGitHostProvider","providers","remoteUrl","length","reason","claimants","filter","provider","matchesRemote","configured","find","isConfigured","listNames","map","name","join"],"sources":["git-host-provider.ts"],"sourcesContent":["/**\n * The git-host (pull request) contract `bit ci sync` is written against; nothing in the engine may\n * reach past it. Other hosts register via `ci.registerGitHostProvider(...)`. Adding a method is a\n * breaking change for out-of-tree providers.\n */\nexport type PrInfo = {\n number: number;\n state: 'open' | 'closed';\n labels: string[];\n headRef: string;\n htmlUrl: string;\n};\n\nexport interface GitHostProvider {\n /** Stable identifier, used in logs and to tell registered providers apart. E.g. `'github'`. */\n name: string;\n\n /** Does this provider serve the repository at `remoteUrl`? A host test, not a credentials test. */\n matchesRemote(remoteUrl: string): boolean;\n\n /**\n * Token and repository resolvable? Must not throw (unconfigured is a normal state — the engine\n * degrades to git-only sync), must be cheap and idempotent, and must never perform network I/O.\n */\n isConfigured(remoteUrl?: string): boolean;\n\n findPrByBranch(branch: string): Promise<PrInfo | undefined>;\n\n createPr(opts: { head: string; base: string; title: string; body: string }): Promise<PrInfo>;\n\n closePr(prNumber: number, comment?: string): Promise<void>;\n\n comment(prNumber: number, body: string): Promise<void>;\n\n addLabel(prNumber: number, label: string): Promise<void>;\n}\n\n/** The git host to use this run, or nothing plus the reason PR operations are being skipped. */\nexport type GitHostSelection = {\n /** The host to use. undefined => PR-less (git-only) sync. */\n provider?: GitHostProvider;\n /** Set exactly when `provider` is undefined; surfaced once per run so PR-less is never silent. */\n reason?: string;\n};\n\n/**\n * Pick the provider that serves `remoteUrl`, or nothing (PR-less sync) plus the reason why.\n * A claim is exclusive: configuration never overrides `matchesRemote`, because routing to whichever\n * provider holds a token would act on the wrong host's PRs. A sole configured provider is the fallback\n * only when no provider claims the remote; two or more unclaimed-but-configured is too ambiguous.\n */\nexport function selectGitHostProvider(providers: GitHostProvider[], remoteUrl: string | undefined): GitHostSelection {\n if (!providers.length) {\n return { reason: 'no git host provider is registered — skipping all pull request operations' };\n }\n\n const claimants = remoteUrl ? providers.filter((provider) => provider.matchesRemote(remoteUrl)) : [];\n if (claimants.length) {\n const configured = claimants.find((provider) => provider.isConfigured(remoteUrl));\n if (configured) return { provider: configured };\n return {\n reason:\n `the ${listNames(claimants)} git host provider${claimants.length > 1 ? 's' : ''} serve${\n claimants.length > 1 ? '' : 's'\n } this repository's \"origin\" remote but ${claimants.length > 1 ? 'none is' : 'is not'} configured ` +\n `(missing credentials or repository) — skipping all pull request operations. No other provider is ` +\n `used in its place: that would act on the wrong host.`,\n };\n }\n\n const configured = providers.filter((provider) => provider.isConfigured(remoteUrl));\n if (configured.length === 1) return { provider: configured[0] };\n if (configured.length > 1) {\n return {\n reason:\n `no git host provider claims this repository's \"origin\" remote, and ${configured.length} are ` +\n `configured (${listNames(configured)}) — too ambiguous to pick one, skipping all pull request operations`,\n };\n }\n return {\n reason:\n `no git host provider is configured${remoteUrl ? '' : ' (and the \"origin\" remote could not be read)'} — ` +\n `skipping all pull request operations`,\n };\n}\n\nfunction listNames(providers: GitHostProvider[]): string {\n return providers.map((provider) => `\"${provider.name}\"`).join(', ');\n}\n"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;;AAiCA;;AAQA;AACA;AACA;AACA;AACA;AACA;AACO,SAASA,qBAAqBA,CAACC,SAA4B,EAAEC,SAA6B,EAAoB;EACnH,IAAI,CAACD,SAAS,CAACE,MAAM,EAAE;IACrB,OAAO;MAAEC,MAAM,EAAE;IAA4E,CAAC;EAChG;EAEA,MAAMC,SAAS,GAAGH,SAAS,GAAGD,SAAS,CAACK,MAAM,CAAEC,QAAQ,IAAKA,QAAQ,CAACC,aAAa,CAACN,SAAS,CAAC,CAAC,GAAG,EAAE;EACpG,IAAIG,SAAS,CAACF,MAAM,EAAE;IACpB,MAAMM,UAAU,GAAGJ,SAAS,CAACK,IAAI,CAAEH,QAAQ,IAAKA,QAAQ,CAACI,YAAY,CAACT,SAAS,CAAC,CAAC;IACjF,IAAIO,UAAU,EAAE,OAAO;MAAEF,QAAQ,EAAEE;IAAW,CAAC;IAC/C,OAAO;MACLL,MAAM,EACJ,OAAOQ,SAAS,CAACP,SAAS,CAAC,qBAAqBA,SAAS,CAACF,MAAM,GAAG,CAAC,GAAG,GAAG,GAAG,EAAE,SAC7EE,SAAS,CAACF,MAAM,GAAG,CAAC,GAAG,EAAE,GAAG,GAAG,0CACSE,SAAS,CAACF,MAAM,GAAG,CAAC,GAAG,SAAS,GAAG,QAAQ,cAAc,GACnG,mGAAmG,GACnG;IACJ,CAAC;EACH;EAEA,MAAMM,UAAU,GAAGR,SAAS,CAACK,MAAM,CAAEC,QAAQ,IAAKA,QAAQ,CAACI,YAAY,CAACT,SAAS,CAAC,CAAC;EACnF,IAAIO,UAAU,CAACN,MAAM,KAAK,CAAC,EAAE,OAAO;IAAEI,QAAQ,EAAEE,UAAU,CAAC,CAAC;EAAE,CAAC;EAC/D,IAAIA,UAAU,CAACN,MAAM,GAAG,CAAC,EAAE;IACzB,OAAO;MACLC,MAAM,EACJ,sEAAsEK,UAAU,CAACN,MAAM,OAAO,GAC9F,eAAeS,SAAS,CAACH,UAAU,CAAC;IACxC,CAAC;EACH;EACA,OAAO;IACLL,MAAM,EACJ,qCAAqCF,SAAS,GAAG,EAAE,GAAG,8CAA8C,KAAK,GACzG;EACJ,CAAC;AACH;AAEA,SAASU,SAASA,CAACX,SAA4B,EAAU;EACvD,OAAOA,SAAS,CAACY,GAAG,CAAEN,QAAQ,IAAK,IAAIA,QAAQ,CAACO,IAAI,GAAG,CAAC,CAACC,IAAI,CAAC,IAAI,CAAC;AACrE","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
function _chai() {
|
|
4
|
+
const data = require("chai");
|
|
5
|
+
_chai = function () {
|
|
6
|
+
return data;
|
|
7
|
+
};
|
|
8
|
+
return data;
|
|
9
|
+
}
|
|
10
|
+
function _gitHostProvider() {
|
|
11
|
+
const data = require("./git-host-provider");
|
|
12
|
+
_gitHostProvider = function () {
|
|
13
|
+
return data;
|
|
14
|
+
};
|
|
15
|
+
return data;
|
|
16
|
+
}
|
|
17
|
+
function _githubClient() {
|
|
18
|
+
const data = require("./github-client");
|
|
19
|
+
_githubClient = function () {
|
|
20
|
+
return data;
|
|
21
|
+
};
|
|
22
|
+
return data;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* A provider stub: only `name`, `matchesRemote` and `isConfigured` participate in selection, so the
|
|
26
|
+
* PR methods reject — reaching them from `selectGitHostProvider` would be a bug worth failing on.
|
|
27
|
+
*/
|
|
28
|
+
function fakeProvider(opts) {
|
|
29
|
+
const unreachable = () => Promise.reject(new Error(`${opts.name}: selection must not call PR methods`));
|
|
30
|
+
return {
|
|
31
|
+
name: opts.name,
|
|
32
|
+
matchesRemote: remoteUrl => opts.hostPattern.test(remoteUrl),
|
|
33
|
+
isConfigured: remoteUrl => typeof opts.configured === 'function' ? opts.configured(remoteUrl) : opts.configured,
|
|
34
|
+
findPrByBranch: unreachable,
|
|
35
|
+
createPr: unreachable,
|
|
36
|
+
closePr: unreachable,
|
|
37
|
+
comment: unreachable,
|
|
38
|
+
addLabel: unreachable
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
const github = (configured = true) => fakeProvider({
|
|
42
|
+
name: 'github',
|
|
43
|
+
hostPattern: /github\.com/,
|
|
44
|
+
configured
|
|
45
|
+
});
|
|
46
|
+
const gitlab = (configured = true) => fakeProvider({
|
|
47
|
+
name: 'gitlab',
|
|
48
|
+
hostPattern: /gitlab\.com/,
|
|
49
|
+
configured
|
|
50
|
+
});
|
|
51
|
+
const GH = 'https://github.com/acme/shop';
|
|
52
|
+
const UNCLAIMED = 'git@git.acme.internal:acme/shop.git';
|
|
53
|
+
const claimants = (...names) => names.map(name => fakeProvider({
|
|
54
|
+
name,
|
|
55
|
+
hostPattern: /git\.acme/,
|
|
56
|
+
configured: false
|
|
57
|
+
}));
|
|
58
|
+
const tied = (...names) => names.map(name => fakeProvider({
|
|
59
|
+
name,
|
|
60
|
+
hostPattern: /github\.com/,
|
|
61
|
+
configured: true
|
|
62
|
+
}));
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A claimed remote is NEVER routed to a different provider: acting on the wrong host's PRs is worse
|
|
66
|
+
* than degrading to git-only sync. The sole-configured fallback applies only when no provider claims
|
|
67
|
+
* the remote at all. Every selection of nothing must explain itself; a successful one must stay quiet.
|
|
68
|
+
*
|
|
69
|
+
* [case, providers, remote url, selected provider name, reason fragments].
|
|
70
|
+
*/
|
|
71
|
+
const SELECTION = [['by matching host', [github(), gitlab()], 'git@gitlab.com:acme/shop.git', 'gitlab'], ['by matching host, the other way round', [github(), gitlab()], GH, 'github'], ['nothing when the claimant is unconfigured but another is', [github(false), gitlab(true)], GH, undefined, ['"github"', 'not configured']], ['nothing regardless of registration order', [gitlab(true), github(false)], GH, undefined, ['"github"']], ['nothing when nothing at all is configured', [github(false), gitlab(false)], GH, undefined, ['"github"']], ['nothing, naming every claimant when several claim and none is configured', claimants('ghe-a', 'ghe-b'), 'https://git.acme.com/acme/shop', undefined, ['"ghe-a"', '"ghe-b"']], ['the sole configured provider when no remote url is known', [github(true)], undefined, 'github'], ['the sole configured of several when no remote url is known', [github(false), gitlab(true)], undefined, 'gitlab'],
|
|
72
|
+
// e.g. a self-hosted GitLab on a custom domain, or an `insteadOf` rewrite of the origin url
|
|
73
|
+
['the sole configured provider for a remote no provider claims', [github(false), gitlab(true)], UNCLAIMED, 'gitlab'], ['nothing when two configured providers both fail to claim', [github(true), gitlab(true)], UNCLAIMED, undefined, ['ambiguous']], ['nothing when two are configured and there is no remote url', [github(true), gitlab(true)], undefined, undefined, ['ambiguous']], ['nothing when nothing is registered', [], GH, undefined, ['no git host provider is registered']], ['nothing when nothing is configured and there is no remote', [github(false), gitlab(false)], undefined, undefined, ['no git host provider is configured']], ['the first registered when two configured providers claim the same remote', tied('first', 'second'), GH, 'first']];
|
|
74
|
+
describe('selectGitHostProvider', () => {
|
|
75
|
+
SELECTION.forEach(([name, providers, remote, picks, reason]) => {
|
|
76
|
+
it(`selects ${name}`, () => {
|
|
77
|
+
const selection = (0, _gitHostProvider().selectGitHostProvider)(providers, remote);
|
|
78
|
+
(0, _chai().expect)(selection.provider?.name, name).to.equal(picks);
|
|
79
|
+
if (picks) {
|
|
80
|
+
(0, _chai().expect)(selection.reason, 'a successful selection stays quiet').to.equal(undefined);
|
|
81
|
+
} else {
|
|
82
|
+
(0, _chai().expect)((selection.reason ?? '').length, 'a skipped run must never be silent').to.be.greaterThan(0);
|
|
83
|
+
(reason ?? []).forEach(fragment => (0, _chai().expect)(selection.reason).to.contain(fragment));
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
it('passes the remote url to isConfigured, so a host can derive its repo from it', () => {
|
|
88
|
+
const seen = [];
|
|
89
|
+
const derivesRepoFromRemote = fakeProvider({
|
|
90
|
+
name: 'github',
|
|
91
|
+
hostPattern: /github\.com/,
|
|
92
|
+
configured: remoteUrl => {
|
|
93
|
+
seen.push(remoteUrl);
|
|
94
|
+
return Boolean(remoteUrl?.includes('github.com'));
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
(0, _chai().expect)((0, _gitHostProvider().selectGitHostProvider)([derivesRepoFromRemote], GH).provider?.name).to.equal('github');
|
|
98
|
+
(0, _chai().expect)(seen).to.deep.equal([GH]);
|
|
99
|
+
(0, _chai().expect)((0, _gitHostProvider().selectGitHostProvider)([derivesRepoFromRemote], undefined).provider).to.equal(undefined);
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
// The built-in provider, exercised through the interface it is registered as — the GitHub *client*
|
|
104
|
+
// (API shapes, auth headers, remote parsing) is covered by github-client.spec.ts.
|
|
105
|
+
describe('GitHubHostProvider', () => {
|
|
106
|
+
const envKeys = ['GITHUB_TOKEN', 'BIT_GITHUB_TOKEN', 'GITHUB_REPOSITORY'];
|
|
107
|
+
const saved = {};
|
|
108
|
+
beforeEach(() => {
|
|
109
|
+
envKeys.forEach(key => {
|
|
110
|
+
saved[key] = process.env[key];
|
|
111
|
+
delete process.env[key];
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
afterEach(() => {
|
|
115
|
+
envKeys.forEach(key => {
|
|
116
|
+
if (saved[key] === undefined) delete process.env[key];else process.env[key] = saved[key];
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
it('is registrable without credentials: constructing it never throws and it reports unconfigured', () => {
|
|
120
|
+
const provider = new (_githubClient().GitHubHostProvider)();
|
|
121
|
+
(0, _chai().expect)(provider.name).to.equal('github');
|
|
122
|
+
(0, _chai().expect)(provider.isConfigured(GH)).to.equal(false);
|
|
123
|
+
const selection = (0, _gitHostProvider().selectGitHostProvider)([provider], GH);
|
|
124
|
+
(0, _chai().expect)(selection.provider).to.equal(undefined);
|
|
125
|
+
(0, _chai().expect)(selection.reason).to.contain('"github"');
|
|
126
|
+
});
|
|
127
|
+
it('is configured once a token is present, deriving the repo from the remote url', () => {
|
|
128
|
+
process.env.BIT_GITHUB_TOKEN = 'tok';
|
|
129
|
+
(0, _chai().expect)(new (_githubClient().GitHubHostProvider)().isConfigured('git@github.com:acme/shop.git')).to.equal(true);
|
|
130
|
+
// no repo resolvable (no GITHUB_REPOSITORY, no parseable remote) => still unconfigured
|
|
131
|
+
(0, _chai().expect)(new (_githubClient().GitHubHostProvider)().isConfigured(undefined)).to.equal(false);
|
|
132
|
+
// a look-alike host must not be parsed into a repo aimed at api.github.com
|
|
133
|
+
(0, _chai().expect)(new (_githubClient().GitHubHostProvider)().isConfigured('https://mygithub.com/acme/shop')).to.equal(false);
|
|
134
|
+
});
|
|
135
|
+
it('remembers the remote url it was asked about, and only if that remote was ours', () => {
|
|
136
|
+
process.env.BIT_GITHUB_TOKEN = 'tok';
|
|
137
|
+
const ours = new (_githubClient().GitHubHostProvider)();
|
|
138
|
+
(0, _chai().expect)(ours.matchesRemote('git@github.com:acme/shop.git')).to.equal(true);
|
|
139
|
+
(0, _chai().expect)(ours.isConfigured()).to.equal(true);
|
|
140
|
+
// without that hint the same call cannot resolve a repository
|
|
141
|
+
(0, _chai().expect)(new (_githubClient().GitHubHostProvider)().isConfigured()).to.equal(false);
|
|
142
|
+
// …and a non-github remote must not poison the hint
|
|
143
|
+
const theirs = new (_githubClient().GitHubHostProvider)();
|
|
144
|
+
(0, _chai().expect)(theirs.matchesRemote('https://gitlab.com/acme/shop.git')).to.equal(false);
|
|
145
|
+
(0, _chai().expect)(theirs.isConfigured()).to.equal(false);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// On Actions the env is always set, so answering "configured" for an unclaimed remote would make
|
|
149
|
+
// this the sole-configured fallback and aim PRs at whatever GITHUB_REPOSITORY named.
|
|
150
|
+
it('is NOT configured or selected for a remote it does not claim, however complete the environment', () => {
|
|
151
|
+
process.env.BIT_GITHUB_TOKEN = 'tok';
|
|
152
|
+
process.env.GITHUB_REPOSITORY = 'acme/shop';
|
|
153
|
+
(0, _chai().expect)(new (_githubClient().GitHubHostProvider)().isConfigured('https://gitlab.com/acme/shop.git')).to.equal(false);
|
|
154
|
+
// non-vacuous: the very same environment DOES configure it for a github remote, and for no remote
|
|
155
|
+
(0, _chai().expect)(new (_githubClient().GitHubHostProvider)().isConfigured(GH)).to.equal(true);
|
|
156
|
+
(0, _chai().expect)(new (_githubClient().GitHubHostProvider)().isConfigured()).to.equal(true);
|
|
157
|
+
const selection = (0, _gitHostProvider().selectGitHostProvider)([new (_githubClient().GitHubHostProvider)()], 'https://gitlab.com/acme/shop.git');
|
|
158
|
+
(0, _chai().expect)(selection.provider).to.equal(undefined);
|
|
159
|
+
(0, _chai().expect)(selection.reason).to.contain('no git host provider is configured');
|
|
160
|
+
});
|
|
161
|
+
it('reports what is missing rather than failing obscurely when a PR call happens unconfigured', async () => {
|
|
162
|
+
let message = '';
|
|
163
|
+
await new (_githubClient().GitHubHostProvider)().findPrByBranch('lane-x').catch(err => {
|
|
164
|
+
message = err.message;
|
|
165
|
+
});
|
|
166
|
+
(0, _chai().expect)(message).to.contain('GITHUB_TOKEN');
|
|
167
|
+
(0, _chai().expect)(message).to.contain('GITHUB_REPOSITORY');
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
//# sourceMappingURL=git-host-provider.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["_chai","data","require","_gitHostProvider","_githubClient","fakeProvider","opts","unreachable","Promise","reject","Error","name","matchesRemote","remoteUrl","hostPattern","test","isConfigured","configured","findPrByBranch","createPr","closePr","comment","addLabel","github","gitlab","GH","UNCLAIMED","claimants","names","map","tied","SELECTION","undefined","describe","forEach","providers","remote","picks","reason","it","selection","selectGitHostProvider","expect","provider","to","equal","length","be","greaterThan","fragment","contain","seen","derivesRepoFromRemote","push","Boolean","includes","deep","envKeys","saved","beforeEach","key","process","env","afterEach","GitHubHostProvider","BIT_GITHUB_TOKEN","ours","theirs","GITHUB_REPOSITORY","message","catch","err"],"sources":["git-host-provider.spec.ts"],"sourcesContent":["import { expect } from 'chai';\nimport type { GitHostProvider, PrInfo } from './git-host-provider';\nimport { selectGitHostProvider } from './git-host-provider';\nimport { GitHubHostProvider } from './github-client';\n\n/**\n * A provider stub: only `name`, `matchesRemote` and `isConfigured` participate in selection, so the\n * PR methods reject — reaching them from `selectGitHostProvider` would be a bug worth failing on.\n */\nfunction fakeProvider(opts: {\n name: string;\n hostPattern: RegExp;\n configured: boolean | ((remoteUrl?: string) => boolean);\n}): GitHostProvider {\n const unreachable = () => Promise.reject(new Error(`${opts.name}: selection must not call PR methods`));\n return {\n name: opts.name,\n matchesRemote: (remoteUrl: string) => opts.hostPattern.test(remoteUrl),\n isConfigured: (remoteUrl?: string) =>\n typeof opts.configured === 'function' ? opts.configured(remoteUrl) : opts.configured,\n findPrByBranch: unreachable as () => Promise<PrInfo | undefined>,\n createPr: unreachable as () => Promise<PrInfo>,\n closePr: unreachable,\n comment: unreachable,\n addLabel: unreachable,\n };\n}\n\nconst github = (configured = true) => fakeProvider({ name: 'github', hostPattern: /github\\.com/, configured });\nconst gitlab = (configured = true) => fakeProvider({ name: 'gitlab', hostPattern: /gitlab\\.com/, configured });\nconst GH = 'https://github.com/acme/shop';\nconst UNCLAIMED = 'git@git.acme.internal:acme/shop.git';\n\nconst claimants = (...names: string[]) =>\n names.map((name) => fakeProvider({ name, hostPattern: /git\\.acme/, configured: false }));\nconst tied = (...names: string[]) =>\n names.map((name) => fakeProvider({ name, hostPattern: /github\\.com/, configured: true }));\n\n/**\n * A claimed remote is NEVER routed to a different provider: acting on the wrong host's PRs is worse\n * than degrading to git-only sync. The sole-configured fallback applies only when no provider claims\n * the remote at all. Every selection of nothing must explain itself; a successful one must stay quiet.\n *\n * [case, providers, remote url, selected provider name, reason fragments].\n */\nconst SELECTION: Array<[string, GitHostProvider[], string | undefined, string | undefined, string[]?]> = [\n ['by matching host', [github(), gitlab()], 'git@gitlab.com:acme/shop.git', 'gitlab'],\n ['by matching host, the other way round', [github(), gitlab()], GH, 'github'],\n [\n 'nothing when the claimant is unconfigured but another is',\n [github(false), gitlab(true)],\n GH,\n undefined,\n ['\"github\"', 'not configured'],\n ],\n ['nothing regardless of registration order', [gitlab(true), github(false)], GH, undefined, ['\"github\"']],\n ['nothing when nothing at all is configured', [github(false), gitlab(false)], GH, undefined, ['\"github\"']],\n [\n 'nothing, naming every claimant when several claim and none is configured',\n claimants('ghe-a', 'ghe-b'),\n 'https://git.acme.com/acme/shop',\n undefined,\n ['\"ghe-a\"', '\"ghe-b\"'],\n ],\n ['the sole configured provider when no remote url is known', [github(true)], undefined, 'github'],\n ['the sole configured of several when no remote url is known', [github(false), gitlab(true)], undefined, 'gitlab'],\n // e.g. a self-hosted GitLab on a custom domain, or an `insteadOf` rewrite of the origin url\n ['the sole configured provider for a remote no provider claims', [github(false), gitlab(true)], UNCLAIMED, 'gitlab'],\n [\n 'nothing when two configured providers both fail to claim',\n [github(true), gitlab(true)],\n UNCLAIMED,\n undefined,\n ['ambiguous'],\n ],\n [\n 'nothing when two are configured and there is no remote url',\n [github(true), gitlab(true)],\n undefined,\n undefined,\n ['ambiguous'],\n ],\n ['nothing when nothing is registered', [], GH, undefined, ['no git host provider is registered']],\n [\n 'nothing when nothing is configured and there is no remote',\n [github(false), gitlab(false)],\n undefined,\n undefined,\n ['no git host provider is configured'],\n ],\n ['the first registered when two configured providers claim the same remote', tied('first', 'second'), GH, 'first'],\n];\n\ndescribe('selectGitHostProvider', () => {\n SELECTION.forEach(([name, providers, remote, picks, reason]) => {\n it(`selects ${name}`, () => {\n const selection = selectGitHostProvider(providers, remote);\n expect(selection.provider?.name, name).to.equal(picks);\n if (picks) {\n expect(selection.reason, 'a successful selection stays quiet').to.equal(undefined);\n } else {\n expect((selection.reason ?? '').length, 'a skipped run must never be silent').to.be.greaterThan(0);\n (reason ?? []).forEach((fragment) => expect(selection.reason).to.contain(fragment));\n }\n });\n });\n\n it('passes the remote url to isConfigured, so a host can derive its repo from it', () => {\n const seen: Array<string | undefined> = [];\n const derivesRepoFromRemote = fakeProvider({\n name: 'github',\n hostPattern: /github\\.com/,\n configured: (remoteUrl) => {\n seen.push(remoteUrl);\n return Boolean(remoteUrl?.includes('github.com'));\n },\n });\n expect(selectGitHostProvider([derivesRepoFromRemote], GH).provider?.name).to.equal('github');\n expect(seen).to.deep.equal([GH]);\n expect(selectGitHostProvider([derivesRepoFromRemote], undefined).provider).to.equal(undefined);\n });\n});\n\n// The built-in provider, exercised through the interface it is registered as — the GitHub *client*\n// (API shapes, auth headers, remote parsing) is covered by github-client.spec.ts.\ndescribe('GitHubHostProvider', () => {\n const envKeys = ['GITHUB_TOKEN', 'BIT_GITHUB_TOKEN', 'GITHUB_REPOSITORY'] as const;\n const saved: Record<string, string | undefined> = {};\n\n beforeEach(() => {\n envKeys.forEach((key) => {\n saved[key] = process.env[key];\n delete process.env[key];\n });\n });\n\n afterEach(() => {\n envKeys.forEach((key) => {\n if (saved[key] === undefined) delete process.env[key];\n else process.env[key] = saved[key];\n });\n });\n\n it('is registrable without credentials: constructing it never throws and it reports unconfigured', () => {\n const provider = new GitHubHostProvider();\n expect(provider.name).to.equal('github');\n expect(provider.isConfigured(GH)).to.equal(false);\n const selection = selectGitHostProvider([provider], GH);\n expect(selection.provider).to.equal(undefined);\n expect(selection.reason).to.contain('\"github\"');\n });\n\n it('is configured once a token is present, deriving the repo from the remote url', () => {\n process.env.BIT_GITHUB_TOKEN = 'tok';\n expect(new GitHubHostProvider().isConfigured('git@github.com:acme/shop.git')).to.equal(true);\n // no repo resolvable (no GITHUB_REPOSITORY, no parseable remote) => still unconfigured\n expect(new GitHubHostProvider().isConfigured(undefined)).to.equal(false);\n // a look-alike host must not be parsed into a repo aimed at api.github.com\n expect(new GitHubHostProvider().isConfigured('https://mygithub.com/acme/shop')).to.equal(false);\n });\n\n it('remembers the remote url it was asked about, and only if that remote was ours', () => {\n process.env.BIT_GITHUB_TOKEN = 'tok';\n const ours = new GitHubHostProvider();\n expect(ours.matchesRemote('git@github.com:acme/shop.git')).to.equal(true);\n expect(ours.isConfigured()).to.equal(true);\n // without that hint the same call cannot resolve a repository\n expect(new GitHubHostProvider().isConfigured()).to.equal(false);\n // …and a non-github remote must not poison the hint\n const theirs = new GitHubHostProvider();\n expect(theirs.matchesRemote('https://gitlab.com/acme/shop.git')).to.equal(false);\n expect(theirs.isConfigured()).to.equal(false);\n });\n\n // On Actions the env is always set, so answering \"configured\" for an unclaimed remote would make\n // this the sole-configured fallback and aim PRs at whatever GITHUB_REPOSITORY named.\n it('is NOT configured or selected for a remote it does not claim, however complete the environment', () => {\n process.env.BIT_GITHUB_TOKEN = 'tok';\n process.env.GITHUB_REPOSITORY = 'acme/shop';\n expect(new GitHubHostProvider().isConfigured('https://gitlab.com/acme/shop.git')).to.equal(false);\n // non-vacuous: the very same environment DOES configure it for a github remote, and for no remote\n expect(new GitHubHostProvider().isConfigured(GH)).to.equal(true);\n expect(new GitHubHostProvider().isConfigured()).to.equal(true);\n const selection = selectGitHostProvider([new GitHubHostProvider()], 'https://gitlab.com/acme/shop.git');\n expect(selection.provider).to.equal(undefined);\n expect(selection.reason).to.contain('no git host provider is configured');\n });\n\n it('reports what is missing rather than failing obscurely when a PR call happens unconfigured', async () => {\n let message = '';\n await new GitHubHostProvider().findPrByBranch('lane-x').catch((err) => {\n message = err.message;\n });\n expect(message).to.contain('GITHUB_TOKEN');\n expect(message).to.contain('GITHUB_REPOSITORY');\n });\n});\n"],"mappings":"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","ignoreList":[]}
|