@forgeportal/plugin-argocd 1.3.0

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 (45) hide show
  1. package/.turbo/turbo-build.log +4 -0
  2. package/LICENSE +21 -0
  3. package/dist/ArgocdTab.d.ts +8 -0
  4. package/dist/ArgocdTab.d.ts.map +1 -0
  5. package/dist/ArgocdTab.js +69 -0
  6. package/dist/ArgocdTab.js.map +1 -0
  7. package/dist/__tests__/api-client.test.d.ts +2 -0
  8. package/dist/__tests__/api-client.test.d.ts.map +1 -0
  9. package/dist/__tests__/api-client.test.js +129 -0
  10. package/dist/__tests__/api-client.test.js.map +1 -0
  11. package/dist/actions.d.ts +23 -0
  12. package/dist/actions.d.ts.map +1 -0
  13. package/dist/actions.js +106 -0
  14. package/dist/actions.js.map +1 -0
  15. package/dist/api-client.d.ts +35 -0
  16. package/dist/api-client.d.ts.map +1 -0
  17. package/dist/api-client.js +73 -0
  18. package/dist/api-client.js.map +1 -0
  19. package/dist/index.d.ts +14 -0
  20. package/dist/index.d.ts.map +1 -0
  21. package/dist/index.js +34 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/routes.d.ts +13 -0
  24. package/dist/routes.d.ts.map +1 -0
  25. package/dist/routes.js +92 -0
  26. package/dist/routes.js.map +1 -0
  27. package/dist/types.d.ts +62 -0
  28. package/dist/types.d.ts.map +1 -0
  29. package/dist/types.js +3 -0
  30. package/dist/types.js.map +1 -0
  31. package/dist/ui.d.ts +11 -0
  32. package/dist/ui.d.ts.map +1 -0
  33. package/dist/ui.js +17 -0
  34. package/dist/ui.js.map +1 -0
  35. package/forgeportal-plugin.json +32 -0
  36. package/package.json +51 -0
  37. package/src/ArgocdTab.tsx +305 -0
  38. package/src/__tests__/api-client.test.ts +156 -0
  39. package/src/actions.ts +118 -0
  40. package/src/api-client.ts +90 -0
  41. package/src/index.ts +46 -0
  42. package/src/routes.ts +127 -0
  43. package/src/types.ts +65 -0
  44. package/src/ui.ts +18 -0
  45. package/tsconfig.json +11 -0
@@ -0,0 +1,4 @@
1
+
2
+ > @forgeportal/plugin-argocd@1.3.0 build /home/runner/work/forgeportal/forgeportal/packages/plugin-argocd
3
+ > tsc
4
+
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 bendaamerahmed
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import type { Entity } from '@forgeportal/plugin-sdk';
3
+ interface ArgocdTabProps {
4
+ entity: Entity;
5
+ }
6
+ export declare function ArgocdTab({ entity }: ArgocdTabProps): React.ReactElement;
7
+ export {};
8
+ //# sourceMappingURL=ArgocdTab.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArgocdTab.d.ts","sourceRoot":"","sources":["../src/ArgocdTab.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAgC,MAAM,OAAO,CAAC;AAErD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAkEtD,UAAU,cAAc;IAAG,MAAM,EAAE,MAAM,CAAA;CAAE;AAE3C,wBAAgB,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,cAAc,GAAG,KAAK,CAAC,YAAY,CA0OxE"}
@@ -0,0 +1,69 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState, useCallback } from 'react';
3
+ import { useApi } from '@forgeportal/plugin-sdk/react';
4
+ // ─── Badges ───────────────────────────────────────────────────────────────────
5
+ function SyncBadge({ status }) {
6
+ const colours = {
7
+ Synced: 'bg-green-100 text-green-800',
8
+ OutOfSync: 'bg-amber-100 text-amber-800',
9
+ Unknown: 'bg-gray-100 text-gray-600',
10
+ };
11
+ return (_jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${colours[status] ?? colours['Unknown']}`, children: status }));
12
+ }
13
+ function HealthBadge({ status }) {
14
+ const colours = {
15
+ Healthy: 'bg-green-100 text-green-800',
16
+ Degraded: 'bg-red-100 text-red-800',
17
+ Progressing: 'bg-blue-100 text-blue-800',
18
+ Suspended: 'bg-orange-100 text-orange-800',
19
+ Missing: 'bg-gray-100 text-gray-600',
20
+ Unknown: 'bg-gray-100 text-gray-600',
21
+ };
22
+ return (_jsx("span", { className: `inline-flex items-center rounded-full px-2 py-0.5 text-xs font-medium ${colours[status] ?? colours['Unknown']}`, children: status }));
23
+ }
24
+ export function ArgocdTab({ entity }) {
25
+ const [syncing, setSyncing] = useState(false);
26
+ const [syncMessage, setSyncMessage] = useState(null);
27
+ const annotations = entity.annotations ?? {};
28
+ const appName = annotations['forgeportal.dev/argocd-app-name'];
29
+ // Not configured state
30
+ if (!appName) {
31
+ return (_jsxs("div", { className: "rounded-lg border border-dashed border-gray-200 bg-gray-50 p-8 text-center", children: [_jsx("p", { className: "text-sm font-medium text-gray-700 mb-1", children: "ArgoCD not configured for this entity" }), _jsxs("p", { className: "text-xs text-gray-500 mb-4", children: ["Add the annotation", ' ', _jsx("code", { className: "rounded bg-gray-100 px-1 py-0.5", children: "forgeportal.dev/argocd-app-name" }), ' ', "to your ", _jsx("code", { className: "rounded bg-gray-100 px-1 py-0.5", children: "entity.yaml" }), " to see the ArgoCD status."] }), _jsx("pre", { className: "mx-auto max-w-md rounded bg-gray-800 p-3 text-left text-xs text-green-300", children: `metadata:\n annotations:\n forgeportal.dev/argocd-app-name: my-app-prod\n forgeportal.dev/argocd-project: platform # optional` })] }));
32
+ }
33
+ const { data: appData, isPending: appLoading, error: appError, refetch: refetchApp, } = useApi(`/api/v1/plugins/argocd/entities/${entity.id}/app?appName=${encodeURIComponent(appName)}`, { refetchInterval: 30_000 });
34
+ const { data: historyData, isPending: historyLoading, } = useApi(`/api/v1/plugins/argocd/entities/${entity.id}/history?appName=${encodeURIComponent(appName)}`);
35
+ const triggerSync = useCallback(async () => {
36
+ if (!appName || syncing)
37
+ return;
38
+ setSyncing(true);
39
+ try {
40
+ const res = await fetch(`/api/v1/plugins/argocd/entities/${entity.id}/sync`, {
41
+ method: 'POST',
42
+ credentials: 'include',
43
+ headers: { 'Content-Type': 'application/json' },
44
+ body: JSON.stringify({ appName }),
45
+ });
46
+ if (res.ok) {
47
+ const json = await res.json();
48
+ setSyncMessage(`Sync triggered at ${new Date(json.data.syncTriggeredAt).toLocaleTimeString()}`);
49
+ void refetchApp();
50
+ setTimeout(() => setSyncMessage(null), 5000);
51
+ }
52
+ }
53
+ finally {
54
+ setSyncing(false);
55
+ }
56
+ }, [appName, entity.id, syncing, refetchApp]);
57
+ const app = appData?.data;
58
+ const history = historyData?.data ?? [];
59
+ return (_jsxs("div", { className: "space-y-6", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("div", { className: "flex items-center gap-3", children: app && (_jsxs("span", { className: "text-xs text-gray-500", children: ["App: ", _jsx("strong", { children: app.metadata.name }), " \u00B7 Project: ", _jsx("strong", { children: app.spec.project })] })) }), _jsxs("div", { className: "flex items-center gap-2", children: [syncMessage && (_jsx("span", { className: "text-xs text-green-600 font-medium", children: syncMessage })), _jsx("button", { onClick: () => void triggerSync(), disabled: syncing || appLoading, className: "inline-flex items-center gap-1.5 rounded-md bg-indigo-600 px-3 py-1.5 text-xs font-medium text-white shadow-sm hover:bg-indigo-700 disabled:opacity-60 transition-colors", children: syncing ? (_jsxs(_Fragment, { children: [_jsxs("svg", { className: "h-3 w-3 animate-spin", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })] }), "Syncing\u2026"] })) : ('Sync Now') })] })] }), appLoading && (_jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-500", children: [_jsxs("svg", { className: "h-4 w-4 animate-spin text-indigo-500", fill: "none", viewBox: "0 0 24 24", children: [_jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }), _jsx("path", { className: "opacity-75", fill: "currentColor", d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4z" })] }), "Loading ArgoCD status\u2026"] })), appError && !appLoading && (_jsxs("div", { className: "rounded-md bg-red-50 border border-red-200 p-4 text-sm text-red-700", children: ["Failed to load ArgoCD data: ", appError instanceof Error ? appError.message : 'Unknown error'] })), app && (_jsxs("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-3", children: [_jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("p", { className: "text-xs font-medium text-gray-500 mb-2", children: "Sync Status" }), _jsx(SyncBadge, { status: app.status.sync.status }), app.status.sync.revision && (_jsx("p", { className: "mt-2 font-mono text-xs text-gray-500 truncate", title: app.status.sync.revision, children: app.status.sync.revision.slice(0, 8) }))] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("p", { className: "text-xs font-medium text-gray-500 mb-2", children: "Health" }), _jsx(HealthBadge, { status: app.status.health.status })] }), _jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("p", { className: "text-xs font-medium text-gray-500 mb-2", children: "Last Reconciled" }), _jsx("p", { className: "text-xs text-gray-700", children: app.status.reconciledAt
60
+ ? new Date(app.status.reconciledAt).toLocaleString()
61
+ : '—' })] })] })), app?.status.operationState && (_jsxs("div", { className: `rounded-md border p-3 text-xs ${app.status.operationState.phase === 'Succeeded'
62
+ ? 'border-green-200 bg-green-50 text-green-800'
63
+ : app.status.operationState.phase === 'Failed'
64
+ ? 'border-red-200 bg-red-50 text-red-800'
65
+ : 'border-blue-200 bg-blue-50 text-blue-800'}`, children: [_jsx("span", { className: "font-medium", children: "Last operation:" }), ' ', app.status.operationState.phase, app.status.operationState.message && ` — ${app.status.operationState.message}`] })), app?.spec.source && (_jsxs("div", { className: "rounded-lg border border-gray-200 bg-white p-4", children: [_jsx("h3", { className: "text-sm font-semibold text-gray-700 mb-3", children: "Source" }), _jsxs("dl", { className: "grid grid-cols-1 gap-y-2 text-xs sm:grid-cols-3", children: [_jsxs("div", { children: [_jsx("dt", { className: "text-gray-500", children: "Repository" }), _jsx("dd", { className: "font-mono text-gray-800 truncate", children: app.spec.source.repoURL })] }), _jsxs("div", { children: [_jsx("dt", { className: "text-gray-500", children: "Revision" }), _jsx("dd", { className: "font-mono text-gray-800", children: app.spec.source.targetRevision })] }), app.spec.source.path && (_jsxs("div", { children: [_jsx("dt", { className: "text-gray-500", children: "Path" }), _jsx("dd", { className: "font-mono text-gray-800", children: app.spec.source.path })] }))] })] })), _jsxs("div", { children: [_jsxs("h3", { className: "text-sm font-semibold text-gray-700 mb-3", children: ["Sync History", ' ', _jsx("span", { className: "rounded-full bg-gray-100 px-2 py-0.5 text-xs font-normal text-gray-500", children: history.length })] }), historyLoading ? (_jsx("p", { className: "text-xs text-gray-400", children: "Loading history\u2026" })) : history.length === 0 ? (_jsx("p", { className: "text-xs text-gray-400", children: "No sync history available." })) : (_jsx("div", { className: "overflow-x-auto rounded-lg border border-gray-200", children: _jsxs("table", { className: "min-w-full text-xs", children: [_jsx("thead", { children: _jsxs("tr", { className: "border-b border-gray-200 bg-gray-50", children: [_jsx("th", { className: "px-4 py-2 text-left font-medium text-gray-600", children: "Revision" }), _jsx("th", { className: "px-4 py-2 text-left font-medium text-gray-600", children: "Deployed At" }), _jsx("th", { className: "px-4 py-2 text-left font-medium text-gray-600", children: "By" })] }) }), _jsx("tbody", { className: "divide-y divide-gray-100 bg-white", children: history.slice(0, 5).map((item) => (_jsxs("tr", { className: "hover:bg-gray-50", children: [_jsx("td", { className: "px-4 py-2 font-mono text-gray-800", children: item.revision.slice(0, 8) }), _jsx("td", { className: "px-4 py-2 text-gray-600", children: new Date(item.deployedAt).toLocaleString() }), _jsx("td", { className: "px-4 py-2 text-gray-500", children: item.initiatedBy?.automated
66
+ ? 'Auto-sync'
67
+ : (item.initiatedBy?.username ?? '—') })] }, item.id))) })] }) }))] })] }));
68
+ }
69
+ //# sourceMappingURL=ArgocdTab.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ArgocdTab.js","sourceRoot":"","sources":["../src/ArgocdTab.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=api-client.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/api-client.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,129 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
2
+ import { ArgocdApiClient } from '../api-client.js';
3
+ // ── Fixtures ──────────────────────────────────────────────────────────────────
4
+ const CONFIG = {
5
+ url: 'https://argocd.test.internal',
6
+ token: 'test-token',
7
+ insecure: false,
8
+ };
9
+ const APP_FIXTURE = {
10
+ metadata: { name: 'payments-api', namespace: 'default' },
11
+ spec: { source: { repoURL: 'https://github.com/acme/payments', path: 'k8s', targetRevision: 'HEAD' } },
12
+ status: {
13
+ sync: { status: 'Synced', revision: 'abc1234' },
14
+ health: { status: 'Healthy' },
15
+ reconciledAt: '2026-02-20T10:00:00Z',
16
+ history: [
17
+ { id: 0, revision: 'old123', deployedAt: '2026-02-18T08:00:00Z' },
18
+ { id: 1, revision: 'abc1234', deployedAt: '2026-02-20T10:00:00Z' },
19
+ ],
20
+ },
21
+ };
22
+ // ── Helpers ───────────────────────────────────────────────────────────────────
23
+ function mockFetch(body, status = 200) {
24
+ const mock = vi.fn().mockResolvedValue({
25
+ ok: status >= 200 && status < 300,
26
+ status,
27
+ statusText: status === 200 ? 'OK' : 'Error',
28
+ json: () => Promise.resolve(body),
29
+ text: () => Promise.resolve(JSON.stringify(body)),
30
+ });
31
+ vi.stubGlobal('fetch', mock);
32
+ return mock;
33
+ }
34
+ beforeEach(() => vi.restoreAllMocks());
35
+ afterEach(() => vi.unstubAllGlobals());
36
+ // ── Constructor ───────────────────────────────────────────────────────────────
37
+ describe('ArgocdApiClient constructor', () => {
38
+ it('strips trailing slash from baseUrl', async () => {
39
+ const client = new ArgocdApiClient({ ...CONFIG, url: 'https://argocd.test.internal/' });
40
+ const fetchMock = mockFetch(APP_FIXTURE);
41
+ await client.getApp('payments-api');
42
+ const [url] = fetchMock.mock.calls[0];
43
+ expect(url).toBe('https://argocd.test.internal/api/v1/applications/payments-api');
44
+ });
45
+ });
46
+ // ── getApp ────────────────────────────────────────────────────────────────────
47
+ describe('ArgocdApiClient.getApp', () => {
48
+ const client = new ArgocdApiClient(CONFIG);
49
+ it('fetches app status and returns the response', async () => {
50
+ mockFetch(APP_FIXTURE);
51
+ const app = await client.getApp('payments-api');
52
+ expect(app.status.sync.status).toBe('Synced');
53
+ expect(app.status.health.status).toBe('Healthy');
54
+ });
55
+ it('URL-encodes the app name', async () => {
56
+ const fetchMock = mockFetch(APP_FIXTURE);
57
+ await client.getApp('my app/with spaces');
58
+ const [url] = fetchMock.mock.calls[0];
59
+ expect(url).toContain('my%20app%2Fwith%20spaces');
60
+ });
61
+ it('sends Bearer token in Authorization header', async () => {
62
+ const fetchMock = mockFetch(APP_FIXTURE);
63
+ await client.getApp('payments-api');
64
+ const [, init] = fetchMock.mock.calls[0];
65
+ expect(init.headers['Authorization']).toBe('Bearer test-token');
66
+ });
67
+ it('throws with status code on non-ok response', async () => {
68
+ mockFetch({ message: 'Not Found' }, 404);
69
+ await expect(client.getApp('ghost')).rejects.toThrow('404');
70
+ });
71
+ it('throws on 403 Forbidden', async () => {
72
+ mockFetch({ message: 'permission denied' }, 403);
73
+ await expect(client.getApp('payments-api')).rejects.toThrow('403');
74
+ });
75
+ });
76
+ // ── getHistory ────────────────────────────────────────────────────────────────
77
+ describe('ArgocdApiClient.getHistory', () => {
78
+ const client = new ArgocdApiClient(CONFIG);
79
+ it('returns history entries in reverse chronological order', async () => {
80
+ mockFetch(APP_FIXTURE);
81
+ const history = await client.getHistory('payments-api');
82
+ expect(history).toHaveLength(2);
83
+ // reversed — most recent first
84
+ expect(history[0]?.revision).toBe('abc1234');
85
+ expect(history[1]?.revision).toBe('old123');
86
+ });
87
+ it('returns empty array when history is absent', async () => {
88
+ const noHistory = { ...APP_FIXTURE, status: { ...APP_FIXTURE.status, history: undefined } };
89
+ mockFetch(noHistory);
90
+ const history = await client.getHistory('payments-api');
91
+ expect(history).toHaveLength(0);
92
+ });
93
+ it('limits history to 10 entries', async () => {
94
+ const manyHistory = Array.from({ length: 15 }, (_, i) => ({
95
+ id: i, revision: `rev${i}`, deployedAt: '2026-01-01T00:00:00Z',
96
+ }));
97
+ mockFetch({ ...APP_FIXTURE, status: { ...APP_FIXTURE.status, history: manyHistory } });
98
+ const history = await client.getHistory('payments-api');
99
+ expect(history).toHaveLength(10);
100
+ });
101
+ });
102
+ // ── syncApp ───────────────────────────────────────────────────────────────────
103
+ describe('ArgocdApiClient.syncApp', () => {
104
+ const client = new ArgocdApiClient(CONFIG);
105
+ it('sends a POST request to the sync endpoint', async () => {
106
+ const fetchMock = mockFetch({}, 200);
107
+ await client.syncApp('payments-api');
108
+ const [url, init] = fetchMock.mock.calls[0];
109
+ expect(url).toContain('/applications/payments-api/sync');
110
+ expect(init.method).toBe('POST');
111
+ });
112
+ it('throws on ArgoCD error response', async () => {
113
+ mockFetch({ message: 'application is being synced' }, 409);
114
+ await expect(client.syncApp('payments-api')).rejects.toThrow('409');
115
+ });
116
+ });
117
+ // ── rollbackApp ───────────────────────────────────────────────────────────────
118
+ describe('ArgocdApiClient.rollbackApp', () => {
119
+ const client = new ArgocdApiClient(CONFIG);
120
+ it('sends a POST request with the history ID', async () => {
121
+ const fetchMock = mockFetch({}, 200);
122
+ await client.rollbackApp('payments-api', 0);
123
+ const [url, init] = fetchMock.mock.calls[0];
124
+ expect(url).toContain('/applications/payments-api/rollback');
125
+ expect(init.method).toBe('POST');
126
+ expect(JSON.parse(init.body)).toEqual({ id: 0 });
127
+ });
128
+ });
129
+ //# sourceMappingURL=api-client.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.test.js","sourceRoot":"","sources":["../../src/__tests__/api-client.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { ActionProvider } from '@forgeportal/plugin-sdk';
2
+ import type { ArgocdConfig } from './types.js';
3
+ /**
4
+ * argocd.syncApp@v1
5
+ *
6
+ * Triggers a manual sync of an ArgoCD application.
7
+ * Usable in templates and scorecard fix actions.
8
+ *
9
+ * Input:
10
+ * - appName: string (required) — ArgoCD application name
11
+ */
12
+ export declare function createSyncAppAction(config: ArgocdConfig): ActionProvider;
13
+ /**
14
+ * argocd.rollbackApp@v1
15
+ *
16
+ * Rolls back an ArgoCD application to a specific history entry.
17
+ *
18
+ * Input:
19
+ * - appName: string (required)
20
+ * - historyId: number (required) — history entry ID from the app history
21
+ */
22
+ export declare function createRollbackAppAction(config: ArgocdConfig): ActionProvider;
23
+ //# sourceMappingURL=actions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAG/C;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CA2CxE;AAED;;;;;;;;GAQG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,YAAY,GAAG,cAAc,CAkD5E"}
@@ -0,0 +1,106 @@
1
+ import { ArgocdApiClient } from './api-client.js';
2
+ /**
3
+ * argocd.syncApp@v1
4
+ *
5
+ * Triggers a manual sync of an ArgoCD application.
6
+ * Usable in templates and scorecard fix actions.
7
+ *
8
+ * Input:
9
+ * - appName: string (required) — ArgoCD application name
10
+ */
11
+ export function createSyncAppAction(config) {
12
+ return {
13
+ id: 'argocd.syncApp',
14
+ version: 'v1',
15
+ schema: {
16
+ input: {
17
+ type: 'object',
18
+ required: ['appName'],
19
+ properties: {
20
+ appName: {
21
+ type: 'string',
22
+ title: 'Application Name',
23
+ description: 'Name of the ArgoCD application to sync.',
24
+ },
25
+ },
26
+ },
27
+ output: {
28
+ type: 'object',
29
+ properties: {
30
+ syncTriggeredAt: { type: 'string', description: 'ISO timestamp when sync was triggered.' },
31
+ },
32
+ },
33
+ },
34
+ async handler(ctx, input) {
35
+ const appName = input['appName'];
36
+ ctx.logger.info(`Triggering ArgoCD sync for application "${appName}"`);
37
+ const client = new ArgocdApiClient(config);
38
+ await client.syncApp(appName);
39
+ const syncTriggeredAt = new Date().toISOString();
40
+ ctx.logger.info(`Sync triggered for "${appName}" at ${syncTriggeredAt}`);
41
+ return {
42
+ status: 'success',
43
+ outputs: { syncTriggeredAt },
44
+ links: [
45
+ { title: `Open ${appName} in ArgoCD`, url: `${config.url}/applications/${appName}` },
46
+ ],
47
+ };
48
+ },
49
+ };
50
+ }
51
+ /**
52
+ * argocd.rollbackApp@v1
53
+ *
54
+ * Rolls back an ArgoCD application to a specific history entry.
55
+ *
56
+ * Input:
57
+ * - appName: string (required)
58
+ * - historyId: number (required) — history entry ID from the app history
59
+ */
60
+ export function createRollbackAppAction(config) {
61
+ return {
62
+ id: 'argocd.rollbackApp',
63
+ version: 'v1',
64
+ schema: {
65
+ input: {
66
+ type: 'object',
67
+ required: ['appName', 'historyId'],
68
+ properties: {
69
+ appName: {
70
+ type: 'string',
71
+ title: 'Application Name',
72
+ description: 'Name of the ArgoCD application to roll back.',
73
+ },
74
+ historyId: {
75
+ type: 'number',
76
+ title: 'History ID',
77
+ description: 'History entry ID to roll back to (from the sync history list).',
78
+ },
79
+ },
80
+ },
81
+ output: {
82
+ type: 'object',
83
+ properties: {
84
+ rolledBackAt: { type: 'string', description: 'ISO timestamp of the rollback trigger.' },
85
+ },
86
+ },
87
+ },
88
+ async handler(ctx, input) {
89
+ const appName = input['appName'];
90
+ const historyId = input['historyId'];
91
+ ctx.logger.info(`Rolling back ArgoCD application "${appName}" to history entry ${historyId}`);
92
+ const client = new ArgocdApiClient(config);
93
+ await client.rollbackApp(appName, historyId);
94
+ const rolledBackAt = new Date().toISOString();
95
+ ctx.logger.info(`Rollback triggered for "${appName}" at ${rolledBackAt}`);
96
+ return {
97
+ status: 'success',
98
+ outputs: { rolledBackAt },
99
+ links: [
100
+ { title: `Open ${appName} in ArgoCD`, url: `${config.url}/applications/${appName}` },
101
+ ],
102
+ };
103
+ },
104
+ };
105
+ }
106
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"actions.js","sourceRoot":"","sources":["../src/actions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ import type { ArgocdApp, ArgocdHistoryItem, ArgocdConfig, ArgocdResourceTree } from './types.js';
2
+ /**
3
+ * Thin HTTP client for the ArgoCD REST API v1.
4
+ * Authenticates with a Bearer token (service-account or user token).
5
+ */
6
+ export declare class ArgocdApiClient {
7
+ private readonly baseUrl;
8
+ private readonly token;
9
+ private readonly rejectUnauthorized;
10
+ constructor(config: ArgocdConfig);
11
+ private request;
12
+ /**
13
+ * GET /api/v1/applications/{appName}
14
+ */
15
+ getApp(appName: string): Promise<ArgocdApp>;
16
+ /**
17
+ * GET /api/v1/applications/{appName}/revisions
18
+ * Returns the last 10 sync history entries.
19
+ */
20
+ getHistory(appName: string): Promise<ArgocdHistoryItem[]>;
21
+ /**
22
+ * GET /api/v1/applications/{appName}/resource-tree
23
+ */
24
+ getResourceTree(appName: string): Promise<ArgocdResourceTree>;
25
+ /**
26
+ * POST /api/v1/applications/{appName}/sync
27
+ */
28
+ syncApp(appName: string): Promise<void>;
29
+ /**
30
+ * POST /api/v1/applications/{appName}/rollback
31
+ * Rolls back to a specific history entry by id.
32
+ */
33
+ rollbackApp(appName: string, historyId: number): Promise<void>;
34
+ }
35
+ //# sourceMappingURL=api-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.d.ts","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,SAAS,EACT,iBAAiB,EACjB,YAAY,EACZ,kBAAkB,EACnB,MAAM,YAAY,CAAC;AAEpB;;;GAGG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAW;IACjC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAU;gBAEjC,MAAM,EAAE,YAAY;YAMlB,OAAO;IAmBrB;;OAEG;IACG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC;IAIjD;;;OAGG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,EAAE,CAAC;IAQ/D;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAMnE;;OAEG;IACG,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO7C;;;OAGG;IACG,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAMrE"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Thin HTTP client for the ArgoCD REST API v1.
3
+ * Authenticates with a Bearer token (service-account or user token).
4
+ */
5
+ export class ArgocdApiClient {
6
+ baseUrl;
7
+ token;
8
+ rejectUnauthorized;
9
+ constructor(config) {
10
+ this.baseUrl = config.url.replace(/\/$/, '');
11
+ this.token = config.token;
12
+ this.rejectUnauthorized = !config.insecure;
13
+ }
14
+ async request(path, options = {}) {
15
+ const url = `${this.baseUrl}/api/v1${path}`;
16
+ const res = await fetch(url, {
17
+ ...options,
18
+ headers: {
19
+ Authorization: `Bearer ${this.token}`,
20
+ 'Content-Type': 'application/json',
21
+ ...options.headers,
22
+ },
23
+ });
24
+ if (!res.ok) {
25
+ const body = await res.text().catch(() => '');
26
+ throw new Error(`ArgoCD API ${res.status}: ${body || res.statusText}`);
27
+ }
28
+ return res.json();
29
+ }
30
+ /**
31
+ * GET /api/v1/applications/{appName}
32
+ */
33
+ async getApp(appName) {
34
+ return this.request(`/applications/${encodeURIComponent(appName)}`);
35
+ }
36
+ /**
37
+ * GET /api/v1/applications/{appName}/revisions
38
+ * Returns the last 10 sync history entries.
39
+ */
40
+ async getHistory(appName) {
41
+ const app = await this.getApp(appName);
42
+ // History is embedded in the application status
43
+ const history = app
44
+ .status?.history ?? [];
45
+ return history.slice(-10).reverse();
46
+ }
47
+ /**
48
+ * GET /api/v1/applications/{appName}/resource-tree
49
+ */
50
+ async getResourceTree(appName) {
51
+ return this.request(`/applications/${encodeURIComponent(appName)}/resource-tree`);
52
+ }
53
+ /**
54
+ * POST /api/v1/applications/{appName}/sync
55
+ */
56
+ async syncApp(appName) {
57
+ await this.request(`/applications/${encodeURIComponent(appName)}/sync`, {
58
+ method: 'POST',
59
+ body: JSON.stringify({}),
60
+ });
61
+ }
62
+ /**
63
+ * POST /api/v1/applications/{appName}/rollback
64
+ * Rolls back to a specific history entry by id.
65
+ */
66
+ async rollbackApp(appName, historyId) {
67
+ await this.request(`/applications/${encodeURIComponent(appName)}/rollback`, {
68
+ method: 'POST',
69
+ body: JSON.stringify({ id: historyId }),
70
+ });
71
+ }
72
+ }
73
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,MAAM,OAAO,eAAe;IACT,OAAO,CAAS;IAChB,KAAK,CAAW;IAChB,kBAAkB,CAAU;IAE7C,YAAY,MAAoB;QAC9B,IAAI,CAAC,OAAO,GAAe,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,KAAK,GAAiB,MAAM,CAAC,KAAK,CAAC;QACxC,IAAI,CAAC,kBAAkB,GAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;IAC9C,CAAC;IAEO,KAAK,CAAC,OAAO,CAAI,IAAY,EAAE,UAAuB,EAAE;QAC9D,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,OAAO,UAAU,IAAI,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,MAAO,KAA2E,CAAC,GAAG,EAAE;YAClG,GAAG,OAAO;YACV,OAAO,EAAE;gBACP,aAAa,EAAE,UAAU,IAAI,CAAC,KAAK,EAAE;gBACrC,cAAc,EAAE,kBAAkB;gBAClC,GAAI,OAAO,CAAC,OAA8C;aAC3D;SACF,CAAC,CAAC;QAEH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;YAC9C,MAAM,IAAI,KAAK,CAAC,cAAc,GAAG,CAAC,MAAM,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC,CAAC;QACzE,CAAC;QAED,OAAO,GAAG,CAAC,IAAI,EAAgB,CAAC;IAClC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,MAAM,CAAC,OAAe;QAC1B,OAAO,IAAI,CAAC,OAAO,CAAY,iBAAiB,kBAAkB,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjF,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU,CAAC,OAAe;QAC9B,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvC,gDAAgD;QAChD,MAAM,OAAO,GAAI,GAAgE;aAC9E,MAAM,EAAE,OAAO,IAAI,EAAE,CAAC;QACzB,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC;IACtC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CAAC,OAAe;QACnC,OAAO,IAAI,CAAC,OAAO,CACjB,iBAAiB,kBAAkB,CAAC,OAAO,CAAC,gBAAgB,CAC7D,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,OAAe;QAC3B,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,kBAAkB,CAAC,OAAO,CAAC,OAAO,EAAE;YACtE,MAAM,EAAE,MAAM;YACd,IAAI,EAAI,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;SAC3B,CAAC,CAAC;IACL,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,WAAW,CAAC,OAAe,EAAE,SAAiB;QAClD,MAAM,IAAI,CAAC,OAAO,CAAC,iBAAiB,kBAAkB,CAAC,OAAO,CAAC,WAAW,EAAE;YAC1E,MAAM,EAAE,MAAM;YACd,IAAI,EAAI,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC;SAC1C,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ import type { ForgeBackendPluginSDK } from '@forgeportal/plugin-sdk';
2
+ /**
3
+ * Backend entry point for the ArgoCD plugin.
4
+ * Called by the ForgePortal plugin loader at startup.
5
+ *
6
+ * Configuration (forgeportal.yaml -> plugins.argocd.config):
7
+ * url: string — ArgoCD server URL (e.g. https://argocd.internal)
8
+ * insecure: boolean — skip TLS verification (default: false)
9
+ *
10
+ * Token comes from the environment:
11
+ * FORGEPORTAL_PLUGIN_ARGOCD_TOKEN
12
+ */
13
+ export declare function registerBackendPlugin(sdk: ForgeBackendPluginSDK): void;
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAKrE;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,qBAAqB,GAAG,IAAI,CA6BtE"}
package/dist/index.js ADDED
@@ -0,0 +1,34 @@
1
+ import { createRoutes } from './routes.js';
2
+ import { createSyncAppAction, createRollbackAppAction } from './actions.js';
3
+ /**
4
+ * Backend entry point for the ArgoCD plugin.
5
+ * Called by the ForgePortal plugin loader at startup.
6
+ *
7
+ * Configuration (forgeportal.yaml -> plugins.argocd.config):
8
+ * url: string — ArgoCD server URL (e.g. https://argocd.internal)
9
+ * insecure: boolean — skip TLS verification (default: false)
10
+ *
11
+ * Token comes from the environment:
12
+ * FORGEPORTAL_PLUGIN_ARGOCD_TOKEN
13
+ */
14
+ export function registerBackendPlugin(sdk) {
15
+ const url = sdk.config.get('url');
16
+ const insecure = sdk.config.get('insecure') ?? false;
17
+ const token = process.env['FORGEPORTAL_PLUGIN_ARGOCD_TOKEN'] ?? '';
18
+ if (!url) {
19
+ sdk.logger.error('argocd plugin: "url" is required in plugins.argocd.config. Plugin disabled.');
20
+ return;
21
+ }
22
+ if (!token) {
23
+ sdk.logger.warn('argocd plugin: FORGEPORTAL_PLUGIN_ARGOCD_TOKEN env var is not set. API calls will fail.');
24
+ }
25
+ const config = { url, token, insecure };
26
+ sdk.logger.info(`argocd plugin: connected to ${url} (insecure=${insecure})`);
27
+ sdk.registerBackendRoute({
28
+ path: '',
29
+ handler: createRoutes(config),
30
+ });
31
+ sdk.registerActionProvider(createSyncAppAction(config));
32
+ sdk.registerActionProvider(createRollbackAppAction(config));
33
+ }
34
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAE5E;;;;;;;;;;GAUG;AACH,MAAM,UAAU,qBAAqB,CAAC,GAA0B;IAC9D,MAAM,GAAG,GAAQ,GAAG,CAAC,MAAM,CAAC,GAAG,CAAS,KAAK,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAU,UAAU,CAAC,IAAI,KAAK,CAAC;IAC9D,MAAM,KAAK,GAAM,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,IAAI,EAAE,CAAC;IAEtE,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,CAAC,MAAM,CAAC,KAAK,CACd,6EAA6E,CAC9E,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,GAAG,CAAC,MAAM,CAAC,IAAI,CACb,yFAAyF,CAC1F,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAiB,EAAE,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IAEtD,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,+BAA+B,GAAG,cAAc,QAAQ,GAAG,CAAC,CAAC;IAE7E,GAAG,CAAC,oBAAoB,CAAC;QACvB,IAAI,EAAK,EAAE;QACX,OAAO,EAAE,YAAY,CAAC,MAAM,CAAC;KAC9B,CAAC,CAAC;IAEH,GAAG,CAAC,sBAAsB,CAAC,mBAAmB,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,GAAG,CAAC,sBAAsB,CAAC,uBAAuB,CAAC,MAAM,CAAC,CAAC,CAAC;AAC9D,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import type { ArgocdConfig } from './types.js';
3
+ /**
4
+ * Creates Fastify route handlers for the ArgoCD plugin.
5
+ * All routes are mounted under /api/v1/plugins/argocd/ by the plugin loader.
6
+ *
7
+ * Routes:
8
+ * GET entities/:entityId/app — app summary (status, health, revision)
9
+ * GET entities/:entityId/history — last 10 sync operations
10
+ * POST entities/:entityId/sync — trigger sync
11
+ */
12
+ export declare function createRoutes(config: ArgocdConfig): (fastify: FastifyInstance) => Promise<void>;
13
+ //# sourceMappingURL=routes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../src/routes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAgC,MAAM,SAAS,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAU,YAAY,CAAC;AAMnD;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,IAGjB,SAAS,eAAe,KAAG,OAAO,CAAC,IAAI,CAAC,CA2GvE"}