@serve.zone/gitops 2.13.1

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.
Files changed (258) hide show
  1. package/.smartconfig.json +114 -0
  2. package/binary/gitops.ts +4 -0
  3. package/changelog.md +185 -0
  4. package/cli.child.js +4 -0
  5. package/cli.js +4 -0
  6. package/cli.ts.js +5 -0
  7. package/deno.json +10 -0
  8. package/dist_serve/bundle.js +36362 -0
  9. package/dist_serve/index.html +33 -0
  10. package/dist_ts/00_commitinfo_data.d.ts +8 -0
  11. package/dist_ts/00_commitinfo_data.js +9 -0
  12. package/dist_ts/cache/classes.cache.cleaner.d.ts +23 -0
  13. package/dist_ts/cache/classes.cache.cleaner.js +61 -0
  14. package/dist_ts/cache/classes.cached.document.d.ts +30 -0
  15. package/dist_ts/cache/classes.cached.document.js +101 -0
  16. package/dist_ts/cache/classes.cachedb.d.ts +22 -0
  17. package/dist_ts/cache/classes.cachedb.js +58 -0
  18. package/dist_ts/cache/classes.secrets.scan.service.d.ts +51 -0
  19. package/dist_ts/cache/classes.secrets.scan.service.js +237 -0
  20. package/dist_ts/cache/documents/classes.cached.project.d.ts +13 -0
  21. package/dist_ts/cache/documents/classes.cached.project.js +101 -0
  22. package/dist_ts/cache/documents/classes.cached.secret.d.ts +24 -0
  23. package/dist_ts/cache/documents/classes.cached.secret.js +158 -0
  24. package/dist_ts/cache/documents/index.d.ts +2 -0
  25. package/dist_ts/cache/documents/index.js +3 -0
  26. package/dist_ts/cache/index.d.ts +7 -0
  27. package/dist_ts/cache/index.js +6 -0
  28. package/dist_ts/classes/actionlog.d.ts +19 -0
  29. package/dist_ts/classes/actionlog.js +44 -0
  30. package/dist_ts/classes/connectionmanager.d.ts +57 -0
  31. package/dist_ts/classes/connectionmanager.js +247 -0
  32. package/dist_ts/classes/gitopsapp.d.ts +30 -0
  33. package/dist_ts/classes/gitopsapp.js +101 -0
  34. package/dist_ts/classes/jobmanager.d.ts +47 -0
  35. package/dist_ts/classes/jobmanager.js +301 -0
  36. package/dist_ts/classes/jobrunners/autobookstackdocs.runner.d.ts +29 -0
  37. package/dist_ts/classes/jobrunners/autobookstackdocs.runner.js +361 -0
  38. package/dist_ts/classes/jobrunners/base.jobrunner.d.ts +14 -0
  39. package/dist_ts/classes/jobrunners/base.jobrunner.js +3 -0
  40. package/dist_ts/classes/jobrunners/index.d.ts +5 -0
  41. package/dist_ts/classes/jobrunners/index.js +14 -0
  42. package/dist_ts/classes/managedsecrets.manager.d.ts +47 -0
  43. package/dist_ts/classes/managedsecrets.manager.js +247 -0
  44. package/dist_ts/classes/syncmanager.d.ts +189 -0
  45. package/dist_ts/classes/syncmanager.js +1787 -0
  46. package/dist_ts/index.d.ts +6 -0
  47. package/dist_ts/index.js +32 -0
  48. package/dist_ts/logging.d.ts +49 -0
  49. package/dist_ts/logging.js +134 -0
  50. package/dist_ts/opsserver/classes.opsserver.d.ts +25 -0
  51. package/dist_ts/opsserver/classes.opsserver.js +70 -0
  52. package/dist_ts/opsserver/handlers/actionlog.handler.d.ts +9 -0
  53. package/dist_ts/opsserver/handlers/actionlog.handler.js +24 -0
  54. package/dist_ts/opsserver/handlers/actions.handler.d.ts +9 -0
  55. package/dist_ts/opsserver/handlers/actions.handler.js +38 -0
  56. package/dist_ts/opsserver/handlers/admin.handler.d.ts +19 -0
  57. package/dist_ts/opsserver/handlers/admin.handler.js +96 -0
  58. package/dist_ts/opsserver/handlers/connections.handler.d.ts +10 -0
  59. package/dist_ts/opsserver/handlers/connections.handler.js +109 -0
  60. package/dist_ts/opsserver/handlers/groups.handler.d.ts +9 -0
  61. package/dist_ts/opsserver/handlers/groups.handler.js +24 -0
  62. package/dist_ts/opsserver/handlers/index.d.ts +13 -0
  63. package/dist_ts/opsserver/handlers/index.js +14 -0
  64. package/dist_ts/opsserver/handlers/jobs.handler.d.ts +16 -0
  65. package/dist_ts/opsserver/handlers/jobs.handler.js +146 -0
  66. package/dist_ts/opsserver/handlers/logs.handler.d.ts +9 -0
  67. package/dist_ts/opsserver/handlers/logs.handler.js +21 -0
  68. package/dist_ts/opsserver/handlers/managedsecrets.handler.d.ts +11 -0
  69. package/dist_ts/opsserver/handlers/managedsecrets.handler.js +110 -0
  70. package/dist_ts/opsserver/handlers/pipelines.handler.d.ts +31 -0
  71. package/dist_ts/opsserver/handlers/pipelines.handler.js +204 -0
  72. package/dist_ts/opsserver/handlers/projects.handler.d.ts +9 -0
  73. package/dist_ts/opsserver/handlers/projects.handler.js +24 -0
  74. package/dist_ts/opsserver/handlers/secrets.handler.d.ts +10 -0
  75. package/dist_ts/opsserver/handlers/secrets.handler.js +171 -0
  76. package/dist_ts/opsserver/handlers/sync.handler.d.ts +16 -0
  77. package/dist_ts/opsserver/handlers/sync.handler.js +166 -0
  78. package/dist_ts/opsserver/handlers/webhook.handler.d.ts +7 -0
  79. package/dist_ts/opsserver/handlers/webhook.handler.js +55 -0
  80. package/dist_ts/opsserver/helpers/guards.d.ts +5 -0
  81. package/dist_ts/opsserver/helpers/guards.js +12 -0
  82. package/dist_ts/opsserver/index.d.ts +1 -0
  83. package/dist_ts/opsserver/index.js +2 -0
  84. package/dist_ts/paths.d.ts +9 -0
  85. package/dist_ts/paths.js +13 -0
  86. package/dist_ts/plugins.d.ts +25 -0
  87. package/dist_ts/plugins.js +32 -0
  88. package/dist_ts/providers/classes.baseprovider.d.ts +51 -0
  89. package/dist_ts/providers/classes.baseprovider.js +17 -0
  90. package/dist_ts/providers/classes.giteaprovider.d.ts +40 -0
  91. package/dist_ts/providers/classes.giteaprovider.js +224 -0
  92. package/dist_ts/providers/classes.gitlabprovider.d.ts +39 -0
  93. package/dist_ts/providers/classes.gitlabprovider.js +207 -0
  94. package/dist_ts/providers/index.d.ts +3 -0
  95. package/dist_ts/providers/index.js +4 -0
  96. package/dist_ts/storage/classes.storagemanager.d.ts +33 -0
  97. package/dist_ts/storage/classes.storagemanager.js +135 -0
  98. package/dist_ts/storage/index.d.ts +2 -0
  99. package/dist_ts/storage/index.js +2 -0
  100. package/dist_ts/timers.d.ts +4 -0
  101. package/dist_ts/timers.js +24 -0
  102. package/dist_ts_bundled/bundle.d.ts +4 -0
  103. package/dist_ts_bundled/bundle.js +12 -0
  104. package/dist_ts_interfaces/data/actionlog.d.ts +12 -0
  105. package/dist_ts_interfaces/data/actionlog.js +2 -0
  106. package/dist_ts_interfaces/data/branch.d.ts +8 -0
  107. package/dist_ts_interfaces/data/branch.js +2 -0
  108. package/dist_ts_interfaces/data/connection.d.ts +12 -0
  109. package/dist_ts_interfaces/data/connection.js +2 -0
  110. package/dist_ts_interfaces/data/group.d.ts +10 -0
  111. package/dist_ts_interfaces/data/group.js +2 -0
  112. package/dist_ts_interfaces/data/identity.d.ts +7 -0
  113. package/dist_ts_interfaces/data/identity.js +2 -0
  114. package/dist_ts_interfaces/data/index.d.ts +11 -0
  115. package/dist_ts_interfaces/data/index.js +12 -0
  116. package/dist_ts_interfaces/data/job.d.ts +37 -0
  117. package/dist_ts_interfaces/data/job.js +2 -0
  118. package/dist_ts_interfaces/data/managedsecret.d.ts +37 -0
  119. package/dist_ts_interfaces/data/managedsecret.js +2 -0
  120. package/dist_ts_interfaces/data/pipeline.d.ts +22 -0
  121. package/dist_ts_interfaces/data/pipeline.js +2 -0
  122. package/dist_ts_interfaces/data/project.d.ts +12 -0
  123. package/dist_ts_interfaces/data/project.js +2 -0
  124. package/dist_ts_interfaces/data/secret.d.ts +11 -0
  125. package/dist_ts_interfaces/data/secret.js +2 -0
  126. package/dist_ts_interfaces/data/sync.d.ts +34 -0
  127. package/dist_ts_interfaces/data/sync.js +2 -0
  128. package/dist_ts_interfaces/index.d.ts +5 -0
  129. package/dist_ts_interfaces/index.js +8 -0
  130. package/dist_ts_interfaces/plugins.d.ts +2 -0
  131. package/dist_ts_interfaces/plugins.js +4 -0
  132. package/dist_ts_interfaces/requests/actionlog.d.ts +15 -0
  133. package/dist_ts_interfaces/requests/actionlog.js +3 -0
  134. package/dist_ts_interfaces/requests/actions.d.ts +31 -0
  135. package/dist_ts_interfaces/requests/actions.js +3 -0
  136. package/dist_ts_interfaces/requests/admin.d.ts +31 -0
  137. package/dist_ts_interfaces/requests/admin.js +3 -0
  138. package/dist_ts_interfaces/requests/connections.d.ts +71 -0
  139. package/dist_ts_interfaces/requests/connections.js +3 -0
  140. package/dist_ts_interfaces/requests/groups.d.ts +14 -0
  141. package/dist_ts_interfaces/requests/groups.js +3 -0
  142. package/dist_ts_interfaces/requests/index.d.ts +13 -0
  143. package/dist_ts_interfaces/requests/index.js +14 -0
  144. package/dist_ts_interfaces/requests/jobs.d.ts +86 -0
  145. package/dist_ts_interfaces/requests/jobs.js +3 -0
  146. package/dist_ts_interfaces/requests/logs.d.ts +14 -0
  147. package/dist_ts_interfaces/requests/logs.js +3 -0
  148. package/dist_ts_interfaces/requests/managedsecrets.d.ts +84 -0
  149. package/dist_ts_interfaces/requests/managedsecrets.js +3 -0
  150. package/dist_ts_interfaces/requests/pipelines.d.ts +55 -0
  151. package/dist_ts_interfaces/requests/pipelines.js +3 -0
  152. package/dist_ts_interfaces/requests/projects.d.ts +14 -0
  153. package/dist_ts_interfaces/requests/projects.js +3 -0
  154. package/dist_ts_interfaces/requests/secrets.d.ts +72 -0
  155. package/dist_ts_interfaces/requests/secrets.js +3 -0
  156. package/dist_ts_interfaces/requests/sync.d.ts +120 -0
  157. package/dist_ts_interfaces/requests/sync.js +3 -0
  158. package/dist_ts_interfaces/requests/webhook.d.ts +13 -0
  159. package/dist_ts_interfaces/requests/webhook.js +3 -0
  160. package/license +21 -0
  161. package/package.json +81 -0
  162. package/readme.md +177 -0
  163. package/readme.todo.md +3 -0
  164. package/ts/00_commitinfo_data.ts +8 -0
  165. package/ts/cache/classes.cache.cleaner.ts +69 -0
  166. package/ts/cache/classes.cached.document.ts +57 -0
  167. package/ts/cache/classes.cachedb.ts +72 -0
  168. package/ts/cache/classes.secrets.scan.service.ts +267 -0
  169. package/ts/cache/documents/classes.cached.project.ts +32 -0
  170. package/ts/cache/documents/classes.cached.secret.ts +81 -0
  171. package/ts/cache/documents/index.ts +2 -0
  172. package/ts/cache/index.ts +7 -0
  173. package/ts/classes/actionlog.ts +57 -0
  174. package/ts/classes/connectionmanager.ts +263 -0
  175. package/ts/classes/gitopsapp.ts +128 -0
  176. package/ts/classes/jobmanager.ts +337 -0
  177. package/ts/classes/jobrunners/autobookstackdocs.runner.ts +435 -0
  178. package/ts/classes/jobrunners/base.jobrunner.ts +16 -0
  179. package/ts/classes/jobrunners/index.ts +17 -0
  180. package/ts/classes/managedsecrets.manager.ts +322 -0
  181. package/ts/classes/syncmanager.ts +2117 -0
  182. package/ts/index.ts +37 -0
  183. package/ts/logging.ts +162 -0
  184. package/ts/opsserver/classes.opsserver.ts +86 -0
  185. package/ts/opsserver/handlers/actionlog.handler.ts +30 -0
  186. package/ts/opsserver/handlers/actions.handler.ts +50 -0
  187. package/ts/opsserver/handlers/admin.handler.ts +122 -0
  188. package/ts/opsserver/handlers/connections.handler.ts +162 -0
  189. package/ts/opsserver/handlers/groups.handler.ts +32 -0
  190. package/ts/opsserver/handlers/index.ts +13 -0
  191. package/ts/opsserver/handlers/jobs.handler.ts +189 -0
  192. package/ts/opsserver/handlers/logs.handler.ts +29 -0
  193. package/ts/opsserver/handlers/managedsecrets.handler.ts +158 -0
  194. package/ts/opsserver/handlers/pipelines.handler.ts +281 -0
  195. package/ts/opsserver/handlers/projects.handler.ts +32 -0
  196. package/ts/opsserver/handlers/secrets.handler.ts +224 -0
  197. package/ts/opsserver/handlers/sync.handler.ts +224 -0
  198. package/ts/opsserver/handlers/webhook.handler.ts +62 -0
  199. package/ts/opsserver/helpers/guards.ts +16 -0
  200. package/ts/opsserver/index.ts +1 -0
  201. package/ts/paths.ts +19 -0
  202. package/ts/plugins.ts +38 -0
  203. package/ts/providers/classes.baseprovider.ts +99 -0
  204. package/ts/providers/classes.giteaprovider.ts +279 -0
  205. package/ts/providers/classes.gitlabprovider.ts +265 -0
  206. package/ts/providers/index.ts +3 -0
  207. package/ts/storage/classes.storagemanager.ts +144 -0
  208. package/ts/storage/index.ts +2 -0
  209. package/ts/timers.ts +34 -0
  210. package/ts_interfaces/data/actionlog.ts +13 -0
  211. package/ts_interfaces/data/branch.ts +9 -0
  212. package/ts_interfaces/data/connection.ts +13 -0
  213. package/ts_interfaces/data/group.ts +10 -0
  214. package/ts_interfaces/data/identity.ts +7 -0
  215. package/ts_interfaces/data/index.ts +11 -0
  216. package/ts_interfaces/data/job.ts +42 -0
  217. package/ts_interfaces/data/managedsecret.ts +41 -0
  218. package/ts_interfaces/data/pipeline.ts +32 -0
  219. package/ts_interfaces/data/project.ts +12 -0
  220. package/ts_interfaces/data/secret.ts +11 -0
  221. package/ts_interfaces/data/sync.ts +37 -0
  222. package/ts_interfaces/index.ts +9 -0
  223. package/ts_interfaces/plugins.ts +6 -0
  224. package/ts_interfaces/requests/actionlog.ts +19 -0
  225. package/ts_interfaces/requests/actions.ts +39 -0
  226. package/ts_interfaces/requests/admin.ts +43 -0
  227. package/ts_interfaces/requests/connections.ts +95 -0
  228. package/ts_interfaces/requests/groups.ts +18 -0
  229. package/ts_interfaces/requests/index.ts +13 -0
  230. package/ts_interfaces/requests/jobs.ts +118 -0
  231. package/ts_interfaces/requests/logs.ts +18 -0
  232. package/ts_interfaces/requests/managedsecrets.ts +112 -0
  233. package/ts_interfaces/requests/pipelines.ts +71 -0
  234. package/ts_interfaces/requests/projects.ts +18 -0
  235. package/ts_interfaces/requests/secrets.ts +92 -0
  236. package/ts_interfaces/requests/sync.ts +157 -0
  237. package/ts_interfaces/requests/webhook.ts +18 -0
  238. package/ts_web/00_commitinfo_data.ts +8 -0
  239. package/ts_web/appstate.ts +1251 -0
  240. package/ts_web/elements/gitops-dashboard.ts +350 -0
  241. package/ts_web/elements/index.ts +10 -0
  242. package/ts_web/elements/shared/css.ts +29 -0
  243. package/ts_web/elements/shared/index.ts +1 -0
  244. package/ts_web/elements/views/actionlog/index.ts +101 -0
  245. package/ts_web/elements/views/actions/index.ts +209 -0
  246. package/ts_web/elements/views/buildlog/index.ts +196 -0
  247. package/ts_web/elements/views/connections/index.ts +260 -0
  248. package/ts_web/elements/views/groups/index.ts +134 -0
  249. package/ts_web/elements/views/jobs/index.ts +424 -0
  250. package/ts_web/elements/views/managedsecrets/index.ts +502 -0
  251. package/ts_web/elements/views/overview/index.ts +86 -0
  252. package/ts_web/elements/views/pipelines/index.ts +561 -0
  253. package/ts_web/elements/views/projects/index.ts +149 -0
  254. package/ts_web/elements/views/secrets/index.ts +310 -0
  255. package/ts_web/elements/views/sync/index.ts +512 -0
  256. package/ts_web/index.ts +7 -0
  257. package/ts_web/plugins.ts +15 -0
  258. package/tsconfig.json +15 -0
@@ -0,0 +1,99 @@
1
+ import type * as interfaces from '../../ts_interfaces/index.js';
2
+
3
+ export interface ITestConnectionResult {
4
+ ok: boolean;
5
+ error?: string;
6
+ }
7
+
8
+ export interface IListOptions {
9
+ search?: string;
10
+ page?: number;
11
+ perPage?: number;
12
+ }
13
+
14
+ export interface IPipelineListOptions extends IListOptions {
15
+ status?: string;
16
+ ref?: string;
17
+ source?: string;
18
+ }
19
+
20
+ /**
21
+ * Abstract base class for Git provider implementations.
22
+ * Subclasses implement Gitea API v1 or GitLab API v4.
23
+ */
24
+ export abstract class BaseProvider {
25
+ public readonly groupFilterId?: string;
26
+
27
+ constructor(
28
+ public readonly connectionId: string,
29
+ public readonly baseUrl: string,
30
+ protected readonly token: string,
31
+ groupFilterId?: string,
32
+ ) {
33
+ this.groupFilterId = groupFilterId;
34
+ }
35
+
36
+ // Connection
37
+ abstract testConnection(): Promise<ITestConnectionResult>;
38
+
39
+ // Projects
40
+ abstract getProjects(opts?: IListOptions): Promise<interfaces.data.IProject[]>;
41
+
42
+ // Groups / Orgs
43
+ abstract getGroups(opts?: IListOptions): Promise<interfaces.data.IGroup[]>;
44
+
45
+ // Group Projects
46
+ abstract getGroupProjects(groupId: string, opts?: IListOptions): Promise<interfaces.data.IProject[]>;
47
+
48
+ // Secrets — project scope
49
+ abstract getProjectSecrets(projectId: string): Promise<interfaces.data.ISecret[]>;
50
+ abstract createProjectSecret(
51
+ projectId: string,
52
+ key: string,
53
+ value: string,
54
+ ): Promise<interfaces.data.ISecret>;
55
+ abstract updateProjectSecret(
56
+ projectId: string,
57
+ key: string,
58
+ value: string,
59
+ ): Promise<interfaces.data.ISecret>;
60
+ abstract deleteProjectSecret(projectId: string, key: string): Promise<void>;
61
+
62
+ // Secrets — group scope
63
+ abstract getGroupSecrets(groupId: string): Promise<interfaces.data.ISecret[]>;
64
+ abstract createGroupSecret(
65
+ groupId: string,
66
+ key: string,
67
+ value: string,
68
+ ): Promise<interfaces.data.ISecret>;
69
+ abstract updateGroupSecret(
70
+ groupId: string,
71
+ key: string,
72
+ value: string,
73
+ ): Promise<interfaces.data.ISecret>;
74
+ abstract deleteGroupSecret(groupId: string, key: string): Promise<void>;
75
+
76
+ // Branches / Tags
77
+ abstract getBranches(projectFullPath: string, opts?: IListOptions): Promise<interfaces.data.IBranch[]>;
78
+ abstract getTags(projectFullPath: string, opts?: IListOptions): Promise<interfaces.data.ITag[]>;
79
+
80
+ // Pipelines / CI
81
+ abstract getPipelines(
82
+ projectId: string,
83
+ opts?: IPipelineListOptions,
84
+ ): Promise<interfaces.data.IPipeline[]>;
85
+ abstract getPipelineJobs(
86
+ projectId: string,
87
+ pipelineId: string,
88
+ ): Promise<interfaces.data.IPipelineJob[]>;
89
+ abstract getJobLog(projectId: string, jobId: string): Promise<string>;
90
+ abstract retryPipeline(projectId: string, pipelineId: string): Promise<void>;
91
+ abstract cancelPipeline(projectId: string, pipelineId: string): Promise<void>;
92
+
93
+ // File content
94
+ abstract getFileContent(projectFullPath: string, filePath: string, ref?: string): Promise<string | null>;
95
+
96
+ // Directory listing
97
+ abstract getDirectoryContents(projectFullPath: string, dirPath: string, ref?: string): Promise<{ name: string; path: string; type: string }[] | null>;
98
+
99
+ }
@@ -0,0 +1,279 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type * as interfaces from '../../ts_interfaces/index.js';
3
+ import { BaseProvider, type ITestConnectionResult, type IListOptions, type IPipelineListOptions } from './classes.baseprovider.js';
4
+
5
+ /**
6
+ * Gitea API v1 provider implementation
7
+ */
8
+ export class GiteaProvider extends BaseProvider {
9
+ private client: plugins.giteaClient.GiteaClient;
10
+
11
+ constructor(connectionId: string, baseUrl: string, token: string, groupFilterId?: string) {
12
+ super(connectionId, baseUrl, token, groupFilterId);
13
+ this.client = new plugins.giteaClient.GiteaClient(baseUrl, token);
14
+ }
15
+
16
+ async testConnection(): Promise<ITestConnectionResult> {
17
+ return this.client.testConnection();
18
+ }
19
+
20
+ async getProjects(opts?: IListOptions): Promise<interfaces.data.IProject[]> {
21
+ const repos = this.groupFilterId
22
+ ? await (await this.client.getOrg(this.groupFilterId)).getRepos(opts)
23
+ : await this.client.getRepos(opts);
24
+ return repos.map((r) => this.mapProject(r));
25
+ }
26
+
27
+ async getGroups(opts?: IListOptions): Promise<interfaces.data.IGroup[]> {
28
+ if (this.groupFilterId) {
29
+ const org = await this.client.getOrg(this.groupFilterId);
30
+ return [this.mapGroup(org)];
31
+ }
32
+ const orgs = await this.client.getOrgs(opts);
33
+ return orgs.map((o) => this.mapGroup(o));
34
+ }
35
+
36
+ async getGroupProjects(groupId: string, opts?: IListOptions): Promise<interfaces.data.IProject[]> {
37
+ const org = await this.client.getOrg(groupId);
38
+ const repos = await org.getRepos(opts);
39
+ return repos.map((r) => this.mapProject(r));
40
+ }
41
+
42
+ // --- Branches / Tags ---
43
+
44
+ async getBranches(projectFullPath: string, opts?: IListOptions): Promise<interfaces.data.IBranch[]> {
45
+ const repo = await this.client.getRepo(projectFullPath);
46
+ const branches = await repo.getBranches(opts);
47
+ return branches.map((b) => ({ name: b.name, commitSha: b.commitSha }));
48
+ }
49
+
50
+ async getTags(projectFullPath: string, opts?: IListOptions): Promise<interfaces.data.ITag[]> {
51
+ const repo = await this.client.getRepo(projectFullPath);
52
+ const tags = await repo.getTags(opts);
53
+ return tags.map((t) => ({ name: t.name, commitSha: t.commitSha }));
54
+ }
55
+
56
+ // --- Project Secrets ---
57
+
58
+ async getProjectSecrets(projectId: string): Promise<interfaces.data.ISecret[]> {
59
+ const repo = await this.client.getRepo(projectId);
60
+ const secrets = await repo.getSecrets();
61
+ return secrets.map((s) => this.mapSecret(s, 'project', projectId));
62
+ }
63
+
64
+ async createProjectSecret(
65
+ projectId: string,
66
+ key: string,
67
+ value: string,
68
+ ): Promise<interfaces.data.ISecret> {
69
+ const repo = await this.client.getRepo(projectId);
70
+ await repo.setSecret(key, value);
71
+ return { key, value: '***', protected: false, masked: true, scope: 'project', scopeId: projectId, scopeName: projectId, connectionId: this.connectionId, environment: '*' };
72
+ }
73
+
74
+ async updateProjectSecret(
75
+ projectId: string,
76
+ key: string,
77
+ value: string,
78
+ ): Promise<interfaces.data.ISecret> {
79
+ return this.createProjectSecret(projectId, key, value);
80
+ }
81
+
82
+ async deleteProjectSecret(projectId: string, key: string): Promise<void> {
83
+ const repo = await this.client.getRepo(projectId);
84
+ await repo.deleteSecret(key);
85
+ }
86
+
87
+ // --- Group Secrets ---
88
+
89
+ async getGroupSecrets(groupId: string): Promise<interfaces.data.ISecret[]> {
90
+ const org = await this.client.getOrg(groupId);
91
+ const secrets = await org.getSecrets();
92
+ return secrets.map((s) => this.mapSecret(s, 'group', groupId));
93
+ }
94
+
95
+ async createGroupSecret(
96
+ groupId: string,
97
+ key: string,
98
+ value: string,
99
+ ): Promise<interfaces.data.ISecret> {
100
+ const org = await this.client.getOrg(groupId);
101
+ await org.setSecret(key, value);
102
+ return { key, value: '***', protected: false, masked: true, scope: 'group', scopeId: groupId, scopeName: groupId, connectionId: this.connectionId, environment: '*' };
103
+ }
104
+
105
+ async updateGroupSecret(
106
+ groupId: string,
107
+ key: string,
108
+ value: string,
109
+ ): Promise<interfaces.data.ISecret> {
110
+ return this.createGroupSecret(groupId, key, value);
111
+ }
112
+
113
+ async deleteGroupSecret(groupId: string, key: string): Promise<void> {
114
+ const org = await this.client.getOrg(groupId);
115
+ await org.deleteSecret(key);
116
+ }
117
+
118
+ // --- Pipelines (Action Runs) ---
119
+
120
+ async getPipelines(
121
+ projectId: string,
122
+ opts?: IPipelineListOptions,
123
+ ): Promise<interfaces.data.IPipeline[]> {
124
+ const repo = await this.client.getRepo(projectId);
125
+ const runs = await repo.getActionRuns({
126
+ page: opts?.page,
127
+ perPage: opts?.perPage,
128
+ status: opts?.status,
129
+ branch: opts?.ref,
130
+ event: opts?.source,
131
+ });
132
+ return runs.map((r) => this.mapPipeline(r, projectId));
133
+ }
134
+
135
+ async getPipelineJobs(
136
+ projectId: string,
137
+ pipelineId: string,
138
+ ): Promise<interfaces.data.IPipelineJob[]> {
139
+ // Use the client's internal method directly to avoid an extra getRepo call
140
+ const jobs = await this.client.requestGetActionRunJobs(projectId, Number(pipelineId));
141
+ return jobs.map((j) => {
142
+ const resolvedStatus = plugins.giteaClient.resolveGiteaStatus(j.status, j.conclusion);
143
+ return this.mapJob(resolvedStatus, j, pipelineId);
144
+ });
145
+ }
146
+
147
+ async getJobLog(projectId: string, jobId: string): Promise<string> {
148
+ return this.client.requestGetJobLog(projectId, Number(jobId));
149
+ }
150
+
151
+ async retryPipeline(projectId: string, pipelineId: string): Promise<void> {
152
+ // Fetch the run to get its workflow path, then dispatch
153
+ const run = await this.client.requestGetActionRun(projectId, Number(pipelineId));
154
+ const wfId = plugins.giteaClient.extractWorkflowIdFromPath(run.path);
155
+ const ref = run.head_branch || 'main';
156
+ if (!wfId) {
157
+ throw new Error(`Cannot retry: no workflow ID found in path "${run.path}"`);
158
+ }
159
+ await this.client.requestDispatchWorkflow(projectId, wfId, ref);
160
+ }
161
+
162
+ async cancelPipeline(_projectId: string, _pipelineId: string): Promise<void> {
163
+ throw new Error('Cancel is not supported by Gitea 1.25');
164
+ }
165
+
166
+ // --- File Content ---
167
+
168
+ async getFileContent(projectFullPath: string, filePath: string, ref?: string): Promise<string | null> {
169
+ try {
170
+ const query = ref ? `?ref=${encodeURIComponent(ref)}` : '';
171
+ return await this.client.requestText('GET', `/api/v1/repos/${projectFullPath}/raw/${encodeURIComponent(filePath)}${query}`);
172
+ } catch {
173
+ return null;
174
+ }
175
+ }
176
+
177
+ // --- Directory Listing ---
178
+
179
+ async getDirectoryContents(projectFullPath: string, dirPath: string, ref?: string): Promise<{ name: string; path: string; type: string }[] | null> {
180
+ try {
181
+ const query = ref ? `?ref=${encodeURIComponent(ref)}` : '';
182
+ const result = await this.client.request<any[]>('GET', `/api/v1/repos/${projectFullPath}/contents/${encodeURIComponent(dirPath)}${query}`);
183
+ if (!Array.isArray(result)) return null;
184
+ return result.map((entry: any) => ({
185
+ name: entry.name,
186
+ path: entry.path,
187
+ type: entry.type, // "file" or "dir"
188
+ }));
189
+ } catch {
190
+ return null;
191
+ }
192
+ }
193
+
194
+ // --- Mappers ---
195
+
196
+ private mapProject(r: plugins.giteaClient.GiteaRepository): interfaces.data.IProject {
197
+ return {
198
+ id: r.fullName || String(r.id),
199
+ name: r.name,
200
+ fullPath: r.fullName,
201
+ description: r.description,
202
+ defaultBranch: r.defaultBranch,
203
+ webUrl: r.htmlUrl,
204
+ connectionId: this.connectionId,
205
+ visibility: r.isPrivate ? 'private' : 'public',
206
+ topics: r.topics,
207
+ lastActivity: r.updatedAt,
208
+ };
209
+ }
210
+
211
+ private mapGroup(o: plugins.giteaClient.GiteaOrganization): interfaces.data.IGroup {
212
+ return {
213
+ id: o.name || String(o.id),
214
+ name: o.name,
215
+ fullPath: o.name,
216
+ description: o.description,
217
+ webUrl: `${this.baseUrl}/${o.name}`,
218
+ connectionId: this.connectionId,
219
+ visibility: o.visibility || 'public',
220
+ projectCount: o.repoCount,
221
+ };
222
+ }
223
+
224
+ private mapSecret(s: plugins.giteaClient.GiteaSecret, scope: 'project' | 'group', scopeId: string): interfaces.data.ISecret {
225
+ return {
226
+ key: s.name,
227
+ value: '***',
228
+ protected: false,
229
+ masked: true,
230
+ scope,
231
+ scopeId,
232
+ scopeName: scopeId,
233
+ connectionId: this.connectionId,
234
+ environment: '*',
235
+ };
236
+ }
237
+
238
+ private mapPipeline(r: plugins.giteaClient.GiteaActionRun, projectId: string): interfaces.data.IPipeline {
239
+ return {
240
+ id: String(r.id),
241
+ projectId,
242
+ projectName: projectId,
243
+ connectionId: this.connectionId,
244
+ status: this.mapStatus(r.resolvedStatus),
245
+ ref: r.ref,
246
+ sha: r.headSha,
247
+ webUrl: r.htmlUrl,
248
+ duration: r.duration,
249
+ createdAt: r.startedAt,
250
+ source: r.event || 'push',
251
+ };
252
+ }
253
+
254
+ private mapJob(resolvedStatus: string, j: plugins.giteaClient.IGiteaActionRunJob, pipelineId: string): interfaces.data.IPipelineJob {
255
+ return {
256
+ id: String(j.id),
257
+ pipelineId,
258
+ name: j.name || '',
259
+ stage: j.name || 'default',
260
+ status: this.mapStatus(resolvedStatus),
261
+ duration: plugins.giteaClient.computeDuration(j.started_at, j.completed_at),
262
+ };
263
+ }
264
+
265
+ private mapStatus(status: string): interfaces.data.TPipelineStatus {
266
+ const map: Record<string, interfaces.data.TPipelineStatus> = {
267
+ success: 'success',
268
+ completed: 'success',
269
+ failure: 'failed',
270
+ cancelled: 'canceled',
271
+ waiting: 'waiting',
272
+ running: 'running',
273
+ queued: 'pending',
274
+ in_progress: 'running',
275
+ skipped: 'skipped',
276
+ };
277
+ return map[status?.toLowerCase()] || 'pending';
278
+ }
279
+ }
@@ -0,0 +1,265 @@
1
+ import * as plugins from '../plugins.js';
2
+ import type * as interfaces from '../../ts_interfaces/index.js';
3
+ import { BaseProvider, type ITestConnectionResult, type IListOptions, type IPipelineListOptions } from './classes.baseprovider.js';
4
+
5
+ /**
6
+ * GitLab API v4 provider implementation
7
+ */
8
+ export class GitLabProvider extends BaseProvider {
9
+ private client: plugins.gitlabClient.GitLabClient;
10
+
11
+ constructor(connectionId: string, baseUrl: string, token: string, groupFilterId?: string) {
12
+ super(connectionId, baseUrl, token, groupFilterId);
13
+ this.client = new plugins.gitlabClient.GitLabClient(baseUrl, token);
14
+ }
15
+
16
+ async testConnection(): Promise<ITestConnectionResult> {
17
+ return this.client.testConnection();
18
+ }
19
+
20
+ async getProjects(opts?: IListOptions): Promise<interfaces.data.IProject[]> {
21
+ const projects = this.groupFilterId
22
+ ? await (await this.client.getGroup(this.groupFilterId)).getProjects(opts)
23
+ : await this.client.getProjects(opts);
24
+ return projects.map((p) => this.mapProject(p));
25
+ }
26
+
27
+ async getGroups(opts?: IListOptions): Promise<interfaces.data.IGroup[]> {
28
+ if (this.groupFilterId) {
29
+ const group = await this.client.getGroup(this.groupFilterId);
30
+ const descendants = await group.getDescendantGroups(opts);
31
+ return descendants.map((g) => this.mapGroup(g));
32
+ }
33
+ const groups = await this.client.getGroups(opts);
34
+ return groups.map((g) => this.mapGroup(g));
35
+ }
36
+
37
+ async getGroupProjects(groupId: string, opts?: IListOptions): Promise<interfaces.data.IProject[]> {
38
+ const group = await this.client.getGroup(groupId);
39
+ const projects = await group.getProjects(opts);
40
+ return projects.map((p) => this.mapProject(p));
41
+ }
42
+
43
+ // --- Branches / Tags ---
44
+
45
+ async getBranches(projectFullPath: string, opts?: IListOptions): Promise<interfaces.data.IBranch[]> {
46
+ const project = await this.client.getProject(projectFullPath);
47
+ const branches = await project.getBranches(opts);
48
+ return branches.map((b) => ({ name: b.name, commitSha: b.commitSha }));
49
+ }
50
+
51
+ async getTags(projectFullPath: string, opts?: IListOptions): Promise<interfaces.data.ITag[]> {
52
+ const project = await this.client.getProject(projectFullPath);
53
+ const tags = await project.getTags(opts);
54
+ return tags.map((t) => ({ name: t.name, commitSha: t.commitSha }));
55
+ }
56
+
57
+ // --- Project Secrets (CI/CD Variables) ---
58
+
59
+ async getProjectSecrets(projectId: string): Promise<interfaces.data.ISecret[]> {
60
+ const project = await this.client.getProject(projectId);
61
+ const vars = await project.getVariables();
62
+ return vars.map((v) => this.mapVariable(v, 'project', projectId));
63
+ }
64
+
65
+ async createProjectSecret(
66
+ projectId: string,
67
+ key: string,
68
+ value: string,
69
+ ): Promise<interfaces.data.ISecret> {
70
+ const project = await this.client.getProject(projectId);
71
+ const v = await project.createVariable(key, value);
72
+ return this.mapVariable(v, 'project', projectId);
73
+ }
74
+
75
+ async updateProjectSecret(
76
+ projectId: string,
77
+ key: string,
78
+ value: string,
79
+ ): Promise<interfaces.data.ISecret> {
80
+ const project = await this.client.getProject(projectId);
81
+ const v = await project.updateVariable(key, value);
82
+ return this.mapVariable(v, 'project', projectId);
83
+ }
84
+
85
+ async deleteProjectSecret(projectId: string, key: string): Promise<void> {
86
+ const project = await this.client.getProject(projectId);
87
+ await project.deleteVariable(key);
88
+ }
89
+
90
+ // --- Group Secrets (CI/CD Variables) ---
91
+
92
+ async getGroupSecrets(groupId: string): Promise<interfaces.data.ISecret[]> {
93
+ const group = await this.client.getGroup(groupId);
94
+ const vars = await group.getVariables();
95
+ return vars.map((v) => this.mapVariable(v, 'group', groupId));
96
+ }
97
+
98
+ async createGroupSecret(
99
+ groupId: string,
100
+ key: string,
101
+ value: string,
102
+ ): Promise<interfaces.data.ISecret> {
103
+ const group = await this.client.getGroup(groupId);
104
+ const v = await group.createVariable(key, value);
105
+ return this.mapVariable(v, 'group', groupId);
106
+ }
107
+
108
+ async updateGroupSecret(
109
+ groupId: string,
110
+ key: string,
111
+ value: string,
112
+ ): Promise<interfaces.data.ISecret> {
113
+ const group = await this.client.getGroup(groupId);
114
+ const v = await group.updateVariable(key, value);
115
+ return this.mapVariable(v, 'group', groupId);
116
+ }
117
+
118
+ async deleteGroupSecret(groupId: string, key: string): Promise<void> {
119
+ const group = await this.client.getGroup(groupId);
120
+ await group.deleteVariable(key);
121
+ }
122
+
123
+ // --- Pipelines ---
124
+
125
+ async getPipelines(
126
+ projectId: string,
127
+ opts?: IPipelineListOptions,
128
+ ): Promise<interfaces.data.IPipeline[]> {
129
+ const project = await this.client.getProject(projectId);
130
+ const pipelines = await project.getPipelines({
131
+ page: opts?.page,
132
+ perPage: opts?.perPage,
133
+ status: opts?.status,
134
+ ref: opts?.ref,
135
+ source: opts?.source,
136
+ });
137
+ return pipelines.map((p) => this.mapPipeline(p, projectId));
138
+ }
139
+
140
+ async getPipelineJobs(
141
+ projectId: string,
142
+ pipelineId: string,
143
+ ): Promise<interfaces.data.IPipelineJob[]> {
144
+ const jobs = await this.client.requestGetPipelineJobs(projectId, Number(pipelineId));
145
+ return jobs.map((j) => this.mapJob(j, pipelineId));
146
+ }
147
+
148
+ async getJobLog(projectId: string, jobId: string): Promise<string> {
149
+ return this.client.requestGetJobLog(projectId, Number(jobId));
150
+ }
151
+
152
+ async retryPipeline(projectId: string, pipelineId: string): Promise<void> {
153
+ await this.client.requestRetryPipeline(projectId, Number(pipelineId));
154
+ }
155
+
156
+ async cancelPipeline(projectId: string, pipelineId: string): Promise<void> {
157
+ await this.client.requestCancelPipeline(projectId, Number(pipelineId));
158
+ }
159
+
160
+ // --- File Content ---
161
+
162
+ async getFileContent(projectFullPath: string, filePath: string, ref?: string): Promise<string | null> {
163
+ try {
164
+ const encodedPath = encodeURIComponent(projectFullPath);
165
+ const encodedFile = encodeURIComponent(filePath);
166
+ const refParam = ref ? `?ref=${encodeURIComponent(ref)}` : '?ref=HEAD';
167
+ return await this.client.requestText('GET', `/api/v4/projects/${encodedPath}/repository/files/${encodedFile}/raw${refParam}`);
168
+ } catch {
169
+ return null;
170
+ }
171
+ }
172
+
173
+ // --- Directory Listing ---
174
+
175
+ async getDirectoryContents(projectFullPath: string, dirPath: string, ref?: string): Promise<{ name: string; path: string; type: string }[] | null> {
176
+ try {
177
+ const encodedPath = encodeURIComponent(projectFullPath);
178
+ const refParam = ref ? `&ref=${encodeURIComponent(ref)}` : '&ref=HEAD';
179
+ const result = await this.client.request<any[]>('GET', `/api/v4/projects/${encodedPath}/repository/tree?path=${encodeURIComponent(dirPath)}${refParam}`);
180
+ if (!Array.isArray(result)) return null;
181
+ return result.map((entry: any) => ({
182
+ name: entry.name,
183
+ path: entry.path,
184
+ type: entry.type === 'blob' ? 'file' : 'dir',
185
+ }));
186
+ } catch {
187
+ return null;
188
+ }
189
+ }
190
+
191
+ // --- Mappers ---
192
+
193
+ private mapProject(p: plugins.gitlabClient.GitLabProject): interfaces.data.IProject {
194
+ return {
195
+ id: String(p.id),
196
+ name: p.name,
197
+ fullPath: p.fullPath,
198
+ description: p.description,
199
+ defaultBranch: p.defaultBranch,
200
+ webUrl: p.webUrl,
201
+ connectionId: this.connectionId,
202
+ visibility: p.visibility,
203
+ topics: p.topics,
204
+ lastActivity: p.lastActivityAt,
205
+ };
206
+ }
207
+
208
+ private mapGroup(g: plugins.gitlabClient.GitLabGroup): interfaces.data.IGroup {
209
+ return {
210
+ id: String(g.id),
211
+ name: g.name,
212
+ fullPath: g.fullPath,
213
+ description: g.description,
214
+ webUrl: g.webUrl,
215
+ connectionId: this.connectionId,
216
+ visibility: g.visibility,
217
+ projectCount: 0,
218
+ };
219
+ }
220
+
221
+ private mapVariable(
222
+ v: plugins.gitlabClient.GitLabVariable,
223
+ scope: 'project' | 'group',
224
+ scopeId: string,
225
+ ): interfaces.data.ISecret {
226
+ return {
227
+ key: v.key,
228
+ value: v.value || '***',
229
+ protected: v.protected,
230
+ masked: v.masked,
231
+ scope,
232
+ scopeId,
233
+ scopeName: scopeId,
234
+ connectionId: this.connectionId,
235
+ environment: v.environmentScope,
236
+ };
237
+ }
238
+
239
+ private mapPipeline(p: plugins.gitlabClient.GitLabPipeline, projectId: string): interfaces.data.IPipeline {
240
+ return {
241
+ id: String(p.id),
242
+ projectId,
243
+ projectName: projectId,
244
+ connectionId: this.connectionId,
245
+ status: (p.status || 'pending') as interfaces.data.TPipelineStatus,
246
+ ref: p.ref,
247
+ sha: p.sha,
248
+ webUrl: p.webUrl,
249
+ duration: p.duration,
250
+ createdAt: p.createdAt,
251
+ source: p.source || 'push',
252
+ };
253
+ }
254
+
255
+ private mapJob(j: plugins.gitlabClient.IGitLabJob, pipelineId: string): interfaces.data.IPipelineJob {
256
+ return {
257
+ id: String(j.id),
258
+ pipelineId: String(pipelineId),
259
+ name: j.name || '',
260
+ stage: j.stage || '',
261
+ status: (j.status || 'pending') as interfaces.data.TPipelineStatus,
262
+ duration: j.duration || 0,
263
+ };
264
+ }
265
+ }
@@ -0,0 +1,3 @@
1
+ export { BaseProvider } from './classes.baseprovider.js';
2
+ export { GiteaProvider } from './classes.giteaprovider.js';
3
+ export { GitLabProvider } from './classes.gitlabprovider.js';