History

feat(source-control): add Bitbucket & Azure Devops providers (#2473)

Julius Marminge committed 6 months agov0.0.22-nightly.20260504.196

Commit 91a03e01 parent d501ebe59 files · +5834 −2327Browse files

Showing the changes to apps/server/src/sourceControl/GitLabSourceControlProvider.ts (1 of 59 files). Show all

Unified · Split

apps/server/src/sourceControl/GitLabSourceControlProvider.ts+53−19
@@ -1,10 +1,14 @@
11 import { Effect, Layer, Option } from "effect";
22 import { SourceControlProviderError, type ChangeRequest } from "@t3tools/contracts";
33
4−import { GitLabCli, type GitLabCliError, type GitLabMergeRequestSummary } from "./GitLabCli.ts";
5−import { SourceControlProvider, type SourceControlRefSelector } from "./SourceControlProvider.ts";
4+import * as GitLabCli from "./GitLabCli.ts";
5+import * as SourceControlProvider from "./SourceControlProvider.ts";
6+import * as SourceControlProviderDiscovery from "./SourceControlProviderDiscovery.ts";
67
7−function providerError(operation: string, cause: GitLabCliError): SourceControlProviderError {
8+function providerError(
9+ operation: string,
10+ cause: GitLabCli.GitLabCliError,
11+): SourceControlProviderError {
812 return new SourceControlProviderError({
913 provider: "gitlab",
1014 operation,
@@ -13,7 +17,7 @@ function providerError(operation: string, cause: GitLabCliError): SourceControlP · 2 unmodified lines
1317 });
1418 }
1519
16−function toChangeRequest(summary: GitLabMergeRequestSummary): ChangeRequest {
20+function toChangeRequest(summary: GitLabCli.GitLabMergeRequestSummary): ChangeRequest {
1721 return {
1822 provider: "gitlab",
1923 number: summary.number,
@@ -35,27 +39,57 @@ function toChangeRequest(summary: GitLabMergeRequestSummary): ChangeRequest { · 15 unmodified lines
3539 };
3640 }
3741
38−function sourceFromInput(input: {
39− readonly headSelector: string;
40− readonly source?: SourceControlRefSelector;
41−}): SourceControlRefSelector | undefined {
42− if (input.source) {
43− return input.source;
42+function parseGitLabAuth(input: SourceControlProviderDiscovery.SourceControlAuthProbeInput) {
43+ const output = SourceControlProviderDiscovery.combinedAuthOutput(input);
44+ const account = SourceControlProviderDiscovery.matchFirst(output, [
45+ /Logged in to .* as\s+([^\s(]+)/iu,
46+ /Logged in to .* account\s+([^\s(]+)/iu,
47+ /account:\s*([^\s(]+)/iu,
48+ ]);
49+ const host = SourceControlProviderDiscovery.parseCliHost(output);
50+
51+ if (input.exitCode !== 0) {
52+ return SourceControlProviderDiscovery.providerAuth({
53+ status: "unauthenticated",
54+ host,
55+ detail:
56+ SourceControlProviderDiscovery.firstSafeAuthLine(output) ??
57+ "Run `glab auth login` to authenticate GitLab CLI.",
58+ });
59+ }
60+
61+ if (account) {
62+ return SourceControlProviderDiscovery.providerAuth({ status: "authenticated", account, host });
4463 }
4564
46− const match = /^([^:/\s]+):(.+)$/u.exec(input.headSelector.trim());
47− const owner = match?.[1]?.trim();
48− const refName = match?.[2]?.trim();
49− return owner && refName ? { owner, refName } : undefined;
65+ return SourceControlProviderDiscovery.providerAuth({
66+ status: "unknown",
67+ host,
68+ detail:
69+ SourceControlProviderDiscovery.firstSafeAuthLine(output) ??
70+ "GitLab CLI auth status could not be parsed.",
71+ });
5072 }
5173
74+export const discovery = {
75+ type: "cli",
76+ kind: "gitlab",
77+ label: "GitLab",
78+ executable: "glab",
79+ versionArgs: ["--version"],
80+ authArgs: ["auth", "status"],
81+ parseAuth: parseGitLabAuth,
82+ installHint:
83+ "Install the GitLab command-line tool (`glab`) from https://gitlab.com/gitlab-org/cli or your package manager (for example `brew install glab`).",
84+} satisfies SourceControlProviderDiscovery.SourceControlCliDiscoverySpec;
85+
5286 export const make = Effect.fn("makeGitLabSourceControlProvider")(function* () {
53− const gitlab = yield* GitLabCli;
87+ const gitlab = yield* GitLabCli.GitLabCli;
5488
55− return SourceControlProvider.of({
89+ return SourceControlProvider.SourceControlProvider.of({
5690 kind: "gitlab",
5791 listChangeRequests: (input) => {
58− const source = sourceFromInput(input);
92+ const source = SourceControlProvider.sourceControlRefFromInput(input);
5993 return gitlab
6094 .listMergeRequests({
6195 cwd: input.cwd,
@@ -75,7 +109,7 @@ export const make = Effect.fn("makeGitLabSourceControlProvider")(function* () { · 13 unmodified lines
75109 Effect.mapError((error) => providerError("getChangeRequest", error)),
76110 ),
77111 createChangeRequest: (input) => {
78− const source = sourceFromInput(input);
112+ const source = SourceControlProvider.sourceControlRefFromInput(input);
79113 return gitlab
80114 .createMergeRequest({
81115 cwd: input.cwd,
@@ -107,4 +141,4 @@ export const make = Effect.fn("makeGitLabSourceControlProvider")(function* () { · 25 unmodified lines
107141 });
108142 });
109143
110−export const layer = Layer.effect(SourceControlProvider, make());
144+export const layer = Layer.effect(SourceControlProvider.SourceControlProvider, make());