@orange-soft/strapi-deployment-trigger 1.1.2 → 1.2.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.
- package/README.md +34 -13
- package/admin/src/pages/HomePage.jsx +59 -32
- package/admin/src/pages/SettingsPage.jsx +136 -61
- package/dist/_chunks/{App-DRqMK_8x.mjs → App-k07qAAvE.mjs} +154 -82
- package/dist/_chunks/{App-CCbQMMHR.js → App-vIrt97zQ.js} +152 -80
- package/dist/_chunks/{index-vQ0KWcpU.mjs → index-BwZtnn__.mjs} +1 -1
- package/dist/_chunks/{index-SuWmJtOE.js → index-w-vQ80Px.js} +1 -1
- package/dist/admin/index.js +1 -1
- package/dist/admin/index.mjs +1 -1
- package/dist/server/index.js +91 -27
- package/dist/server/index.mjs +91 -27
- package/package.json +1 -1
- package/server/src/controllers/controller.js +73 -23
- package/server/src/services/service.js +39 -8
|
@@ -7,7 +7,7 @@ const react = require("react");
|
|
|
7
7
|
const reactIntl = require("react-intl");
|
|
8
8
|
const designSystem = require("@strapi/design-system");
|
|
9
9
|
const icons = require("@strapi/icons");
|
|
10
|
-
const index = require("./index-
|
|
10
|
+
const index = require("./index-w-vQ80Px.js");
|
|
11
11
|
const getTranslation = (id) => `${index.PLUGIN_ID}.${id}`;
|
|
12
12
|
const HomePage = () => {
|
|
13
13
|
const { formatMessage } = reactIntl.useIntl();
|
|
@@ -67,9 +67,18 @@ const HomePage = () => {
|
|
|
67
67
|
}
|
|
68
68
|
const settings = status?.settings || {};
|
|
69
69
|
const parsed = status?.parsed || {};
|
|
70
|
-
|
|
70
|
+
status?.configured;
|
|
71
71
|
const hasToken = status?.hasToken;
|
|
72
72
|
const targets = settings.targets || [];
|
|
73
|
+
const hasGitHubTargets = targets.some((t) => (t.type || "github") === "github");
|
|
74
|
+
targets.some((t) => t.type === "vercel");
|
|
75
|
+
const canTrigger = (target) => {
|
|
76
|
+
const targetType = target.type || "github";
|
|
77
|
+
if (targetType === "github") {
|
|
78
|
+
return hasToken && parsed.owner && parsed.repo;
|
|
79
|
+
}
|
|
80
|
+
return !!target.webhookUrl;
|
|
81
|
+
};
|
|
73
82
|
return /* @__PURE__ */ jsxRuntime.jsxs(admin.Layouts.Root, { children: [
|
|
74
83
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
75
84
|
admin.Layouts.Header,
|
|
@@ -105,8 +114,8 @@ const HomePage = () => {
|
|
|
105
114
|
] })
|
|
106
115
|
}
|
|
107
116
|
) }),
|
|
108
|
-
!hasToken && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { title: "Token Missing", variant: "danger", children: "GitHub Personal Access Token is not configured. Please add it in Settings." }) }),
|
|
109
|
-
!settings.repoUrl && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { title: "Configuration Required", variant: "warning", children: "Please configure your GitHub repository in the Settings page before triggering deployments." }) }),
|
|
117
|
+
hasGitHubTargets && !hasToken && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { title: "Token Missing", variant: "danger", children: "GitHub Personal Access Token is not configured. Please add it in Settings." }) }),
|
|
118
|
+
hasGitHubTargets && !settings.repoUrl && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingBottom: 4, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Alert, { title: "Configuration Required", variant: "warning", children: "Please configure your GitHub repository in the Settings page before triggering deployments." }) }),
|
|
110
119
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "stretch", gap: 4, children: [
|
|
111
120
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
112
121
|
designSystem.Box,
|
|
@@ -159,27 +168,34 @@ const HomePage = () => {
|
|
|
159
168
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "delta", tag: "h2", children: "Deployment Targets" }),
|
|
160
169
|
targets.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { children: [
|
|
161
170
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
171
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Type" }) }),
|
|
162
172
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Name" }) }),
|
|
163
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "
|
|
164
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Branch" }) }),
|
|
173
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Details" }) }),
|
|
165
174
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Action" }) })
|
|
166
175
|
] }) }),
|
|
167
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: targets.map((target) =>
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
designSystem.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
176
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: targets.map((target) => {
|
|
177
|
+
const targetType = target.type || "github";
|
|
178
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
179
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: targetType === "github" ? "neutral800" : "secondary600", children: targetType === "github" ? "GitHub" : "Vercel" }) }),
|
|
180
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: target.name }) }),
|
|
181
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: targetType === "github" ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", textColor: "neutral600", children: [
|
|
182
|
+
target.workflow,
|
|
183
|
+
" / ",
|
|
184
|
+
target.branch
|
|
185
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", children: "Webhook" }) }),
|
|
186
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
187
|
+
designSystem.Button,
|
|
188
|
+
{
|
|
189
|
+
onClick: () => handleDeploy(target.id, target.name),
|
|
190
|
+
loading: deployingTargetId === target.id,
|
|
191
|
+
disabled: !canTrigger(target) || deployingTargetId !== null,
|
|
192
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Rocket, {}),
|
|
193
|
+
size: "S",
|
|
194
|
+
children: deployingTargetId === target.id ? "Triggering..." : "Trigger"
|
|
195
|
+
}
|
|
196
|
+
) })
|
|
197
|
+
] }, target.id);
|
|
198
|
+
}) })
|
|
183
199
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "center", justifyContent: "center", gap: 3, padding: 6, children: [
|
|
184
200
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", textAlign: "center", children: "No deployment targets configured" }),
|
|
185
201
|
/* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: `/plugins/${index.PLUGIN_ID}/settings`, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "default", startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Cog, {}), children: "Add Targets in Settings" }) })
|
|
@@ -187,7 +203,7 @@ const HomePage = () => {
|
|
|
187
203
|
] })
|
|
188
204
|
}
|
|
189
205
|
),
|
|
190
|
-
|
|
206
|
+
hasGitHubTargets && (!hasToken || !parsed.owner || !parsed.repo) && /* @__PURE__ */ jsxRuntime.jsx(
|
|
191
207
|
designSystem.Box,
|
|
192
208
|
{
|
|
193
209
|
background: "neutral0",
|
|
@@ -198,8 +214,8 @@ const HomePage = () => {
|
|
|
198
214
|
paddingLeft: 7,
|
|
199
215
|
paddingRight: 7,
|
|
200
216
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", alignItems: "center", justifyContent: "center", gap: 3, children: [
|
|
201
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", textColor: "neutral600", textAlign: "center", children: "Setup Incomplete" }),
|
|
202
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", textAlign: "center", children: "Please ensure repository URL and GitHub token are configured in Settings." }),
|
|
217
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "beta", textColor: "neutral600", textAlign: "center", children: "GitHub Setup Incomplete" }),
|
|
218
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "epsilon", textColor: "neutral600", textAlign: "center", children: "Please ensure repository URL and GitHub token are configured in Settings for GitHub targets." }),
|
|
203
219
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Box, { paddingTop: 2, children: /* @__PURE__ */ jsxRuntime.jsx(reactRouterDom.Link, { to: `/plugins/${index.PLUGIN_ID}/settings`, children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Button, { variant: "default", startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Cog, {}), children: "Go to Settings" }) }) })
|
|
204
220
|
] })
|
|
205
221
|
}
|
|
@@ -211,6 +227,7 @@ const HomePage = () => {
|
|
|
211
227
|
const TOKEN_PATTERN = /^github_pat_[a-zA-Z0-9_]+$/;
|
|
212
228
|
const REPO_URL_PATTERN = /^https:\/\/github\.com\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+\/?$/;
|
|
213
229
|
const WORKFLOW_PATTERN = /^[a-zA-Z0-9_.-]+\.ya?ml$/;
|
|
230
|
+
const VERCEL_WEBHOOK_PATTERN = /^https:\/\/api\.vercel\.com\/v1\/integrations\/deploy\/.+$/;
|
|
214
231
|
const validateToken = (value) => {
|
|
215
232
|
if (!value) return null;
|
|
216
233
|
if (!TOKEN_PATTERN.test(value)) {
|
|
@@ -232,6 +249,13 @@ const validateWorkflow = (value) => {
|
|
|
232
249
|
}
|
|
233
250
|
return null;
|
|
234
251
|
};
|
|
252
|
+
const validateVercelWebhook = (value) => {
|
|
253
|
+
if (!value) return "Webhook URL is required";
|
|
254
|
+
if (!VERCEL_WEBHOOK_PATTERN.test(value)) {
|
|
255
|
+
return "Must be a valid Vercel deploy hook URL (https://api.vercel.com/v1/integrations/deploy/...)";
|
|
256
|
+
}
|
|
257
|
+
return null;
|
|
258
|
+
};
|
|
235
259
|
const SettingsPage = () => {
|
|
236
260
|
const navigate = reactRouterDom.useNavigate();
|
|
237
261
|
const { get, put, post, del } = admin.useFetchClient();
|
|
@@ -247,7 +271,7 @@ const SettingsPage = () => {
|
|
|
247
271
|
const [saving, setSaving] = react.useState(false);
|
|
248
272
|
const [notification, setNotification] = react.useState(null);
|
|
249
273
|
const [editingTarget, setEditingTarget] = react.useState(null);
|
|
250
|
-
const [targetForm, setTargetForm] = react.useState({ name: "", workflow: "", branch: "" });
|
|
274
|
+
const [targetForm, setTargetForm] = react.useState({ type: "github", name: "", workflow: "", branch: "", webhookUrl: "" });
|
|
251
275
|
const [targetErrors, setTargetErrors] = react.useState({});
|
|
252
276
|
const [showAddForm, setShowAddForm] = react.useState(false);
|
|
253
277
|
const [deleteDialogOpen, setDeleteDialogOpen] = react.useState(false);
|
|
@@ -311,7 +335,7 @@ const SettingsPage = () => {
|
|
|
311
335
|
}
|
|
312
336
|
};
|
|
313
337
|
const resetTargetForm = () => {
|
|
314
|
-
setTargetForm({ name: "", workflow: "deploy.yml", branch: "master" });
|
|
338
|
+
setTargetForm({ type: "github", name: "", workflow: "deploy.yml", branch: "master", webhookUrl: "" });
|
|
315
339
|
setTargetErrors({});
|
|
316
340
|
setEditingTarget(null);
|
|
317
341
|
setShowAddForm(false);
|
|
@@ -319,9 +343,14 @@ const SettingsPage = () => {
|
|
|
319
343
|
const validateTargetForm = () => {
|
|
320
344
|
const newErrors = {};
|
|
321
345
|
if (!targetForm.name.trim()) newErrors.name = "Name is required";
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
346
|
+
if (targetForm.type === "github") {
|
|
347
|
+
const workflowError = validateWorkflow(targetForm.workflow);
|
|
348
|
+
if (workflowError) newErrors.workflow = workflowError;
|
|
349
|
+
if (!targetForm.branch.trim()) newErrors.branch = "Branch is required";
|
|
350
|
+
} else if (targetForm.type === "vercel") {
|
|
351
|
+
const webhookError = validateVercelWebhook(targetForm.webhookUrl);
|
|
352
|
+
if (webhookError) newErrors.webhookUrl = webhookError;
|
|
353
|
+
}
|
|
325
354
|
setTargetErrors(newErrors);
|
|
326
355
|
return Object.keys(newErrors).length === 0;
|
|
327
356
|
};
|
|
@@ -342,7 +371,13 @@ const SettingsPage = () => {
|
|
|
342
371
|
};
|
|
343
372
|
const handleEditTarget = (target) => {
|
|
344
373
|
setEditingTarget(target.id);
|
|
345
|
-
setTargetForm({
|
|
374
|
+
setTargetForm({
|
|
375
|
+
type: target.type || "github",
|
|
376
|
+
name: target.name,
|
|
377
|
+
workflow: target.workflow || "deploy.yml",
|
|
378
|
+
branch: target.branch || "master",
|
|
379
|
+
webhookUrl: target.webhookUrl || ""
|
|
380
|
+
});
|
|
346
381
|
setShowAddForm(false);
|
|
347
382
|
};
|
|
348
383
|
const handleUpdateTarget = async () => {
|
|
@@ -484,7 +519,7 @@ const SettingsPage = () => {
|
|
|
484
519
|
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Plus, {}),
|
|
485
520
|
onClick: () => {
|
|
486
521
|
setShowAddForm(true);
|
|
487
|
-
setTargetForm({ name: "", workflow: "deploy.yml", branch: "master" });
|
|
522
|
+
setTargetForm({ type: "github", name: "", workflow: "deploy.yml", branch: "master", webhookUrl: "" });
|
|
488
523
|
},
|
|
489
524
|
size: "S",
|
|
490
525
|
children: "Add Target"
|
|
@@ -500,7 +535,21 @@ const SettingsPage = () => {
|
|
|
500
535
|
children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { direction: "column", gap: 4, children: [
|
|
501
536
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", children: editingTarget ? "Edit Target" : "Add New Target" }),
|
|
502
537
|
/* @__PURE__ */ jsxRuntime.jsxs(designSystem.Grid.Root, { gap: 4, children: [
|
|
503
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col:
|
|
538
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 3, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name: "targetType", required: true, children: [
|
|
539
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Type" }),
|
|
540
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
541
|
+
designSystem.SingleSelect,
|
|
542
|
+
{
|
|
543
|
+
value: targetForm.type,
|
|
544
|
+
onChange: (value) => setTargetForm((prev) => ({ ...prev, type: value })),
|
|
545
|
+
children: [
|
|
546
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "github", children: "GitHub" }),
|
|
547
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.SingleSelectOption, { value: "vercel", children: "Vercel" })
|
|
548
|
+
]
|
|
549
|
+
}
|
|
550
|
+
)
|
|
551
|
+
] }) }),
|
|
552
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 3, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name: "targetName", required: true, error: targetErrors.name, children: [
|
|
504
553
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Name" }),
|
|
505
554
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
506
555
|
designSystem.Field.Input,
|
|
@@ -512,26 +561,40 @@ const SettingsPage = () => {
|
|
|
512
561
|
),
|
|
513
562
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
|
|
514
563
|
] }) }),
|
|
515
|
-
|
|
516
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.
|
|
564
|
+
targetForm.type === "github" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
565
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 3, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name: "targetWorkflow", required: true, error: targetErrors.workflow, children: [
|
|
566
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Workflow File" }),
|
|
567
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
568
|
+
designSystem.Field.Input,
|
|
569
|
+
{
|
|
570
|
+
placeholder: "deploy.yml",
|
|
571
|
+
value: targetForm.workflow,
|
|
572
|
+
onChange: handleTargetFormChange("workflow")
|
|
573
|
+
}
|
|
574
|
+
),
|
|
575
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
|
|
576
|
+
] }) }),
|
|
577
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 3, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name: "targetBranch", required: true, error: targetErrors.branch, children: [
|
|
578
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Branch" }),
|
|
579
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
580
|
+
designSystem.Field.Input,
|
|
581
|
+
{
|
|
582
|
+
placeholder: "main",
|
|
583
|
+
value: targetForm.branch,
|
|
584
|
+
onChange: handleTargetFormChange("branch")
|
|
585
|
+
}
|
|
586
|
+
),
|
|
587
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
|
|
588
|
+
] }) })
|
|
589
|
+
] }),
|
|
590
|
+
targetForm.type === "vercel" && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Grid.Item, { col: 6, s: 12, children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Field.Root, { name: "targetWebhookUrl", required: true, error: targetErrors.webhookUrl, children: [
|
|
591
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Label, { children: "Webhook URL" }),
|
|
529
592
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
530
593
|
designSystem.Field.Input,
|
|
531
594
|
{
|
|
532
|
-
placeholder: "
|
|
533
|
-
value: targetForm.
|
|
534
|
-
onChange: handleTargetFormChange("
|
|
595
|
+
placeholder: "https://api.vercel.com/v1/integrations/deploy/...",
|
|
596
|
+
value: targetForm.webhookUrl,
|
|
597
|
+
onChange: handleTargetFormChange("webhookUrl")
|
|
535
598
|
}
|
|
536
599
|
),
|
|
537
600
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Field.Error, {})
|
|
@@ -553,39 +616,48 @@ const SettingsPage = () => {
|
|
|
553
616
|
),
|
|
554
617
|
settings.targets.length > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Table, { children: [
|
|
555
618
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Thead, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
619
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Type" }) }),
|
|
556
620
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Name" }) }),
|
|
557
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "
|
|
558
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Branch" }) }),
|
|
621
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Details" }) }),
|
|
559
622
|
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Th, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "sigma", children: "Actions" }) })
|
|
560
623
|
] }) }),
|
|
561
|
-
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: settings.targets.map((target) =>
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
624
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Tbody, { children: settings.targets.map((target) => {
|
|
625
|
+
const targetType = target.type || "github";
|
|
626
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Tr, { children: [
|
|
627
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", fontWeight: "bold", textColor: targetType === "github" ? "neutral800" : "secondary600", children: targetType === "github" ? "GitHub" : "Vercel" }) }),
|
|
628
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", children: target.name }) }),
|
|
629
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: targetType === "github" ? /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Typography, { variant: "omega", textColor: "neutral600", children: [
|
|
630
|
+
target.workflow,
|
|
631
|
+
" / ",
|
|
632
|
+
target.branch
|
|
633
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "omega", textColor: "neutral600", children: "Webhook configured" }) }),
|
|
634
|
+
/* @__PURE__ */ jsxRuntime.jsx(designSystem.Td, { children: /* @__PURE__ */ jsxRuntime.jsxs(designSystem.Flex, { gap: 2, children: [
|
|
635
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
636
|
+
designSystem.Button,
|
|
637
|
+
{
|
|
638
|
+
onClick: () => handleEditTarget(target),
|
|
639
|
+
variant: "tertiary",
|
|
640
|
+
size: "S",
|
|
641
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Pencil, {}),
|
|
642
|
+
children: "Edit"
|
|
643
|
+
}
|
|
644
|
+
),
|
|
645
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
646
|
+
designSystem.Button,
|
|
647
|
+
{
|
|
648
|
+
onClick: () => {
|
|
649
|
+
setTargetToDelete(target.id);
|
|
650
|
+
setDeleteDialogOpen(true);
|
|
651
|
+
},
|
|
652
|
+
variant: "danger-light",
|
|
653
|
+
size: "S",
|
|
654
|
+
startIcon: /* @__PURE__ */ jsxRuntime.jsx(icons.Trash, {}),
|
|
655
|
+
children: "Delete"
|
|
656
|
+
}
|
|
657
|
+
)
|
|
658
|
+
] }) })
|
|
659
|
+
] }, target.id);
|
|
660
|
+
}) })
|
|
589
661
|
] }) : !showAddForm && /* @__PURE__ */ jsxRuntime.jsx(designSystem.Typography, { variant: "pi", textColor: "neutral600", children: 'No deployment targets configured. Click "Add Target" to create one.' })
|
|
590
662
|
] })
|
|
591
663
|
}
|
|
@@ -37,7 +37,7 @@ const index = {
|
|
|
37
37
|
defaultMessage: PLUGIN_ID
|
|
38
38
|
},
|
|
39
39
|
Component: async () => {
|
|
40
|
-
const { App } = await Promise.resolve().then(() => require("./App-
|
|
40
|
+
const { App } = await Promise.resolve().then(() => require("./App-vIrt97zQ.js"));
|
|
41
41
|
return App;
|
|
42
42
|
}
|
|
43
43
|
});
|
package/dist/admin/index.js
CHANGED
package/dist/admin/index.mjs
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -69,6 +69,30 @@ const controller = ({ strapi }) => ({
|
|
|
69
69
|
},
|
|
70
70
|
// Trigger deployment for a specific target
|
|
71
71
|
async trigger(ctx) {
|
|
72
|
+
const service2 = getService(strapi);
|
|
73
|
+
const { targetId } = ctx.request.body || {};
|
|
74
|
+
let target;
|
|
75
|
+
if (targetId) {
|
|
76
|
+
target = await service2.getTarget(targetId);
|
|
77
|
+
if (!target) {
|
|
78
|
+
return ctx.badRequest("Target not found");
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
const settings = await service2.getSettings();
|
|
82
|
+
target = settings.targets?.[0];
|
|
83
|
+
if (!target) {
|
|
84
|
+
return ctx.badRequest("No deployment targets configured");
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
const targetType = target.type || "github";
|
|
88
|
+
if (targetType === "vercel") {
|
|
89
|
+
return this.triggerVercel(ctx, target);
|
|
90
|
+
} else {
|
|
91
|
+
return this.triggerGitHub(ctx, target);
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
// Trigger GitHub Actions deployment
|
|
95
|
+
async triggerGitHub(ctx, target) {
|
|
72
96
|
const service2 = getService(strapi);
|
|
73
97
|
const githubToken = await service2.getToken();
|
|
74
98
|
if (!githubToken) {
|
|
@@ -79,22 +103,9 @@ const controller = ({ strapi }) => ({
|
|
|
79
103
|
if (!owner || !repo) {
|
|
80
104
|
return ctx.badRequest("GitHub repository URL is not configured or invalid. Please configure it in Settings.");
|
|
81
105
|
}
|
|
82
|
-
const
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
const target = await service2.getTarget(targetId);
|
|
86
|
-
if (!target) {
|
|
87
|
-
return ctx.badRequest("Target not found");
|
|
88
|
-
}
|
|
89
|
-
workflow = overrideWorkflow || target.workflow;
|
|
90
|
-
branch = overrideBranch || target.branch;
|
|
91
|
-
targetName = target.name;
|
|
92
|
-
} else {
|
|
93
|
-
const firstTarget = settings.targets?.[0];
|
|
94
|
-
workflow = overrideWorkflow || firstTarget?.workflow || "deploy.yml";
|
|
95
|
-
branch = overrideBranch || firstTarget?.branch || "master";
|
|
96
|
-
targetName = firstTarget?.name || "Default";
|
|
97
|
-
}
|
|
106
|
+
const workflow = target.workflow || "deploy.yml";
|
|
107
|
+
const branch = target.branch || "master";
|
|
108
|
+
const targetName = target.name;
|
|
98
109
|
const url = `https://api.github.com/repos/${owner}/${repo}/actions/workflows/${workflow}/dispatches`;
|
|
99
110
|
try {
|
|
100
111
|
const response = await fetch(url, {
|
|
@@ -111,11 +122,12 @@ const controller = ({ strapi }) => ({
|
|
|
111
122
|
strapi.log.error(`GitHub API error: ${response.status} - ${errorText}`);
|
|
112
123
|
return ctx.badRequest(`GitHub API error: ${response.status} - ${errorText}`);
|
|
113
124
|
}
|
|
114
|
-
strapi.log.info(`
|
|
125
|
+
strapi.log.info(`GitHub deployment triggered for ${owner}/${repo} [${targetName}] on branch ${branch}`);
|
|
115
126
|
const actionsUrl = `https://github.com/${owner}/${repo}/actions`;
|
|
116
127
|
ctx.body = {
|
|
117
128
|
data: {
|
|
118
129
|
success: true,
|
|
130
|
+
type: "github",
|
|
119
131
|
message: `Deployment triggered successfully for ${owner}/${repo}`,
|
|
120
132
|
repository: `${owner}/${repo}`,
|
|
121
133
|
targetName,
|
|
@@ -125,9 +137,39 @@ const controller = ({ strapi }) => ({
|
|
|
125
137
|
}
|
|
126
138
|
};
|
|
127
139
|
} catch (error) {
|
|
128
|
-
strapi.log.error("Error triggering deployment:", error);
|
|
140
|
+
strapi.log.error("Error triggering GitHub deployment:", error);
|
|
129
141
|
return ctx.badRequest(`Failed to trigger deployment: ${error.message}`);
|
|
130
142
|
}
|
|
143
|
+
},
|
|
144
|
+
// Trigger Vercel deployment via webhook
|
|
145
|
+
async triggerVercel(ctx, target) {
|
|
146
|
+
const webhookUrl = target.webhookUrl;
|
|
147
|
+
const targetName = target.name;
|
|
148
|
+
if (!webhookUrl) {
|
|
149
|
+
return ctx.badRequest("Vercel webhook URL is not configured for this target.");
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
const response = await fetch(webhookUrl, {
|
|
153
|
+
method: "POST"
|
|
154
|
+
});
|
|
155
|
+
if (!response.ok) {
|
|
156
|
+
const errorText = await response.text();
|
|
157
|
+
strapi.log.error(`Vercel webhook error: ${response.status} - ${errorText}`);
|
|
158
|
+
return ctx.badRequest(`Vercel webhook error: ${response.status} - ${errorText}`);
|
|
159
|
+
}
|
|
160
|
+
strapi.log.info(`Vercel deployment triggered [${targetName}]`);
|
|
161
|
+
ctx.body = {
|
|
162
|
+
data: {
|
|
163
|
+
success: true,
|
|
164
|
+
type: "vercel",
|
|
165
|
+
message: "Vercel deployment triggered successfully",
|
|
166
|
+
targetName
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
} catch (error) {
|
|
170
|
+
strapi.log.error("Error triggering Vercel deployment:", error);
|
|
171
|
+
return ctx.badRequest(`Failed to trigger Vercel deployment: ${error.message}`);
|
|
172
|
+
}
|
|
131
173
|
}
|
|
132
174
|
});
|
|
133
175
|
const controllers = {
|
|
@@ -249,7 +291,14 @@ const service = ({ strapi }) => ({
|
|
|
249
291
|
migrateSettings(settings) {
|
|
250
292
|
if (!settings) return null;
|
|
251
293
|
if (Array.isArray(settings.targets)) {
|
|
252
|
-
|
|
294
|
+
const targetsWithType = settings.targets.map((target) => ({
|
|
295
|
+
...target,
|
|
296
|
+
type: target.type || "github"
|
|
297
|
+
}));
|
|
298
|
+
return {
|
|
299
|
+
...settings,
|
|
300
|
+
targets: targetsWithType
|
|
301
|
+
};
|
|
253
302
|
}
|
|
254
303
|
if (settings.workflow || settings.branch) {
|
|
255
304
|
return {
|
|
@@ -257,6 +306,7 @@ const service = ({ strapi }) => ({
|
|
|
257
306
|
githubToken: settings.githubToken || "",
|
|
258
307
|
targets: [{
|
|
259
308
|
id: generateId(),
|
|
309
|
+
type: "github",
|
|
260
310
|
name: "Default",
|
|
261
311
|
workflow: settings.workflow || "deploy.yml",
|
|
262
312
|
branch: settings.branch || "master"
|
|
@@ -313,12 +363,18 @@ const service = ({ strapi }) => ({
|
|
|
313
363
|
const store = strapi.store({ type: "plugin", name: PLUGIN_ID });
|
|
314
364
|
let settings = await store.get({ key: STORE_KEY }) || DEFAULT_SETTINGS;
|
|
315
365
|
settings = this.migrateSettings(settings) || DEFAULT_SETTINGS;
|
|
366
|
+
const targetType = target.type || "github";
|
|
316
367
|
const newTarget = {
|
|
317
368
|
id: generateId(),
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
branch: target.branch || "master"
|
|
369
|
+
type: targetType,
|
|
370
|
+
name: target.name || "New Target"
|
|
321
371
|
};
|
|
372
|
+
if (targetType === "github") {
|
|
373
|
+
newTarget.workflow = target.workflow || "deploy.yml";
|
|
374
|
+
newTarget.branch = target.branch || "master";
|
|
375
|
+
} else if (targetType === "vercel") {
|
|
376
|
+
newTarget.webhookUrl = target.webhookUrl || "";
|
|
377
|
+
}
|
|
322
378
|
settings.targets = [...settings.targets || [], newTarget];
|
|
323
379
|
await store.set({ key: STORE_KEY, value: settings });
|
|
324
380
|
return newTarget;
|
|
@@ -330,12 +386,20 @@ const service = ({ strapi }) => ({
|
|
|
330
386
|
if (!settings?.targets) return null;
|
|
331
387
|
const targetIndex = settings.targets.findIndex((t) => t.id === targetId);
|
|
332
388
|
if (targetIndex === -1) return null;
|
|
333
|
-
settings.targets[targetIndex]
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
id: targetId
|
|
337
|
-
|
|
389
|
+
const existingTarget = settings.targets[targetIndex];
|
|
390
|
+
const targetType = updates.type || existingTarget.type || "github";
|
|
391
|
+
const updatedTarget = {
|
|
392
|
+
id: targetId,
|
|
393
|
+
type: targetType,
|
|
394
|
+
name: updates.name !== void 0 ? updates.name : existingTarget.name
|
|
338
395
|
};
|
|
396
|
+
if (targetType === "github") {
|
|
397
|
+
updatedTarget.workflow = updates.workflow !== void 0 ? updates.workflow : existingTarget.workflow;
|
|
398
|
+
updatedTarget.branch = updates.branch !== void 0 ? updates.branch : existingTarget.branch;
|
|
399
|
+
} else if (targetType === "vercel") {
|
|
400
|
+
updatedTarget.webhookUrl = updates.webhookUrl !== void 0 ? updates.webhookUrl : existingTarget.webhookUrl;
|
|
401
|
+
}
|
|
402
|
+
settings.targets[targetIndex] = updatedTarget;
|
|
339
403
|
await store.set({ key: STORE_KEY, value: settings });
|
|
340
404
|
return settings.targets[targetIndex];
|
|
341
405
|
},
|