@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
package/README.md
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
# Strapi Plugin: Deployment Trigger
|
|
2
2
|
|
|
3
|
-
A Strapi v5 plugin that allows you to trigger
|
|
3
|
+
A Strapi v5 plugin that allows you to trigger deployments directly from the Strapi admin panel. Supports both **GitHub Actions** and **Vercel** deployments.
|
|
4
4
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
|
-
- Trigger GitHub Actions `workflow_dispatch` events from the admin UI
|
|
8
|
-
-
|
|
9
|
-
-
|
|
7
|
+
- Trigger **GitHub Actions** `workflow_dispatch` events from the admin UI
|
|
8
|
+
- Trigger **Vercel** deployments via deploy hooks
|
|
9
|
+
- Configure multiple deployment targets (e.g., Production, Staging)
|
|
10
|
+
- Support for different trigger types per target
|
|
11
|
+
- Secure token storage in database
|
|
10
12
|
- Token masking for security
|
|
11
13
|
- Direct link to GitHub Actions to monitor deployment progress
|
|
12
14
|
|
|
@@ -41,12 +43,14 @@ export default () => ({
|
|
|
41
43
|
### 2. Configure via Admin UI
|
|
42
44
|
|
|
43
45
|
1. Go to **Plugins > Deployment Trigger > Settings** in your Strapi admin
|
|
44
|
-
2.
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
2. **For GitHub targets:**
|
|
47
|
+
- Enter your GitHub repository URL (e.g., `https://github.com/owner/repo`)
|
|
48
|
+
- Enter your GitHub Personal Access Token
|
|
49
|
+
- Add a target with type "GitHub", workflow filename, and branch
|
|
50
|
+
3. **For Vercel targets:**
|
|
51
|
+
- Add a target with type "Vercel" and paste your deploy hook URL
|
|
48
52
|
|
|
49
|
-
All settings including
|
|
53
|
+
All settings including tokens are stored securely in the Strapi database.
|
|
50
54
|
|
|
51
55
|
## GitHub Token Setup
|
|
52
56
|
|
|
@@ -77,12 +81,29 @@ jobs:
|
|
|
77
81
|
# ... your deployment steps
|
|
78
82
|
```
|
|
79
83
|
|
|
84
|
+
## Vercel Deploy Hook Setup
|
|
85
|
+
|
|
86
|
+
To trigger Vercel deployments, you need to create a Deploy Hook:
|
|
87
|
+
|
|
88
|
+
1. Go to your Vercel project dashboard
|
|
89
|
+
2. Navigate to **Settings** > **Git**
|
|
90
|
+
3. Scroll down to **Deploy Hooks**
|
|
91
|
+
4. Click **Create Hook**
|
|
92
|
+
5. Enter a name (e.g., "Strapi Trigger") and select the branch
|
|
93
|
+
6. Click **Create Hook**
|
|
94
|
+
7. Copy the generated webhook URL (starts with `https://api.vercel.com/v1/integrations/deploy/...`)
|
|
95
|
+
8. Paste this URL when adding a Vercel target in the plugin settings
|
|
96
|
+
|
|
80
97
|
## Usage
|
|
81
98
|
|
|
82
|
-
1. Navigate to **Plugins > Deployment Trigger** in your Strapi admin
|
|
83
|
-
2.
|
|
84
|
-
3.
|
|
85
|
-
|
|
99
|
+
1. Navigate to **Plugins > Deployment Trigger > Settings** in your Strapi admin
|
|
100
|
+
2. For GitHub targets: Configure repository URL and GitHub token
|
|
101
|
+
3. Add deployment targets:
|
|
102
|
+
- **GitHub**: Select type "GitHub", enter name, workflow file, and branch
|
|
103
|
+
- **Vercel**: Select type "Vercel", enter name and webhook URL
|
|
104
|
+
4. Go to the main **Deployment Trigger** page
|
|
105
|
+
5. Click **Trigger** on any configured target
|
|
106
|
+
6. For GitHub targets, click the provided link to monitor progress in GitHub Actions
|
|
86
107
|
|
|
87
108
|
## API
|
|
88
109
|
|
|
@@ -93,6 +93,20 @@ const HomePage = () => {
|
|
|
93
93
|
const hasToken = status?.hasToken;
|
|
94
94
|
const targets = settings.targets || [];
|
|
95
95
|
|
|
96
|
+
// Check if there are any GitHub targets that need configuration
|
|
97
|
+
const hasGitHubTargets = targets.some(t => (t.type || 'github') === 'github');
|
|
98
|
+
const hasVercelTargets = targets.some(t => t.type === 'vercel');
|
|
99
|
+
|
|
100
|
+
// Determine if trigger buttons should be enabled
|
|
101
|
+
// GitHub targets need repoUrl + token, Vercel targets are self-contained
|
|
102
|
+
const canTrigger = (target) => {
|
|
103
|
+
const targetType = target.type || 'github';
|
|
104
|
+
if (targetType === 'github') {
|
|
105
|
+
return hasToken && parsed.owner && parsed.repo;
|
|
106
|
+
}
|
|
107
|
+
return !!target.webhookUrl;
|
|
108
|
+
};
|
|
109
|
+
|
|
96
110
|
return (
|
|
97
111
|
<Layouts.Root>
|
|
98
112
|
<Layouts.Header
|
|
@@ -134,7 +148,7 @@ const HomePage = () => {
|
|
|
134
148
|
</Box>
|
|
135
149
|
)}
|
|
136
150
|
|
|
137
|
-
{!hasToken && (
|
|
151
|
+
{hasGitHubTargets && !hasToken && (
|
|
138
152
|
<Box paddingBottom={4}>
|
|
139
153
|
<Alert title="Token Missing" variant="danger">
|
|
140
154
|
GitHub Personal Access Token is not configured. Please add it in Settings.
|
|
@@ -142,7 +156,7 @@ const HomePage = () => {
|
|
|
142
156
|
</Box>
|
|
143
157
|
)}
|
|
144
158
|
|
|
145
|
-
{!settings.repoUrl && (
|
|
159
|
+
{hasGitHubTargets && !settings.repoUrl && (
|
|
146
160
|
<Box paddingBottom={4}>
|
|
147
161
|
<Alert title="Configuration Required" variant="warning">
|
|
148
162
|
Please configure your GitHub repository in the Settings page before triggering deployments.
|
|
@@ -211,37 +225,50 @@ const HomePage = () => {
|
|
|
211
225
|
<Table>
|
|
212
226
|
<Thead>
|
|
213
227
|
<Tr>
|
|
228
|
+
<Th><Typography variant="sigma">Type</Typography></Th>
|
|
214
229
|
<Th><Typography variant="sigma">Name</Typography></Th>
|
|
215
|
-
<Th><Typography variant="sigma">
|
|
216
|
-
<Th><Typography variant="sigma">Branch</Typography></Th>
|
|
230
|
+
<Th><Typography variant="sigma">Details</Typography></Th>
|
|
217
231
|
<Th><Typography variant="sigma">Action</Typography></Th>
|
|
218
232
|
</Tr>
|
|
219
233
|
</Thead>
|
|
220
234
|
<Tbody>
|
|
221
|
-
{targets.map((target) =>
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
<
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
<
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
235
|
+
{targets.map((target) => {
|
|
236
|
+
const targetType = target.type || 'github';
|
|
237
|
+
return (
|
|
238
|
+
<Tr key={target.id}>
|
|
239
|
+
<Td>
|
|
240
|
+
<Typography variant="omega" fontWeight="bold" textColor={targetType === 'github' ? 'neutral800' : 'secondary600'}>
|
|
241
|
+
{targetType === 'github' ? 'GitHub' : 'Vercel'}
|
|
242
|
+
</Typography>
|
|
243
|
+
</Td>
|
|
244
|
+
<Td>
|
|
245
|
+
<Typography variant="omega" fontWeight="bold">{target.name}</Typography>
|
|
246
|
+
</Td>
|
|
247
|
+
<Td>
|
|
248
|
+
{targetType === 'github' ? (
|
|
249
|
+
<Typography variant="omega" textColor="neutral600">
|
|
250
|
+
{target.workflow} / {target.branch}
|
|
251
|
+
</Typography>
|
|
252
|
+
) : (
|
|
253
|
+
<Typography variant="omega" textColor="neutral600">
|
|
254
|
+
Webhook
|
|
255
|
+
</Typography>
|
|
256
|
+
)}
|
|
257
|
+
</Td>
|
|
258
|
+
<Td>
|
|
259
|
+
<Button
|
|
260
|
+
onClick={() => handleDeploy(target.id, target.name)}
|
|
261
|
+
loading={deployingTargetId === target.id}
|
|
262
|
+
disabled={!canTrigger(target) || deployingTargetId !== null}
|
|
263
|
+
startIcon={<Rocket />}
|
|
264
|
+
size="S"
|
|
265
|
+
>
|
|
266
|
+
{deployingTargetId === target.id ? 'Triggering...' : 'Trigger'}
|
|
267
|
+
</Button>
|
|
268
|
+
</Td>
|
|
269
|
+
</Tr>
|
|
270
|
+
);
|
|
271
|
+
})}
|
|
245
272
|
</Tbody>
|
|
246
273
|
</Table>
|
|
247
274
|
) : (
|
|
@@ -259,8 +286,8 @@ const HomePage = () => {
|
|
|
259
286
|
</Flex>
|
|
260
287
|
</Box>
|
|
261
288
|
|
|
262
|
-
{/* Instructions Card - Show only when
|
|
263
|
-
{
|
|
289
|
+
{/* Instructions Card - Show only when GitHub targets need configuration */}
|
|
290
|
+
{hasGitHubTargets && (!hasToken || !parsed.owner || !parsed.repo) && (
|
|
264
291
|
<Box
|
|
265
292
|
background="neutral0"
|
|
266
293
|
hasRadius
|
|
@@ -272,10 +299,10 @@ const HomePage = () => {
|
|
|
272
299
|
>
|
|
273
300
|
<Flex direction="column" alignItems="center" justifyContent="center" gap={3}>
|
|
274
301
|
<Typography variant="beta" textColor="neutral600" textAlign="center">
|
|
275
|
-
Setup Incomplete
|
|
302
|
+
GitHub Setup Incomplete
|
|
276
303
|
</Typography>
|
|
277
304
|
<Typography variant="epsilon" textColor="neutral600" textAlign="center">
|
|
278
|
-
Please ensure repository URL and GitHub token are configured in Settings.
|
|
305
|
+
Please ensure repository URL and GitHub token are configured in Settings for GitHub targets.
|
|
279
306
|
</Typography>
|
|
280
307
|
<Box paddingTop={2}>
|
|
281
308
|
<Link to={`/plugins/${PLUGIN_ID}/settings`}>
|
|
@@ -15,9 +15,10 @@ import {
|
|
|
15
15
|
Tr,
|
|
16
16
|
Th,
|
|
17
17
|
Td,
|
|
18
|
-
IconButton,
|
|
19
18
|
Dialog,
|
|
20
19
|
Grid,
|
|
20
|
+
SingleSelect,
|
|
21
|
+
SingleSelectOption,
|
|
21
22
|
} from '@strapi/design-system';
|
|
22
23
|
import { Check, Plus, Pencil, Trash } from '@strapi/icons';
|
|
23
24
|
|
|
@@ -27,6 +28,7 @@ import { PLUGIN_ID } from '../pluginId';
|
|
|
27
28
|
const TOKEN_PATTERN = /^github_pat_[a-zA-Z0-9_]+$/;
|
|
28
29
|
const REPO_URL_PATTERN = /^https:\/\/github\.com\/[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+\/?$/;
|
|
29
30
|
const WORKFLOW_PATTERN = /^[a-zA-Z0-9_.-]+\.ya?ml$/;
|
|
31
|
+
const VERCEL_WEBHOOK_PATTERN = /^https:\/\/api\.vercel\.com\/v1\/integrations\/deploy\/.+$/;
|
|
30
32
|
|
|
31
33
|
const validateToken = (value) => {
|
|
32
34
|
if (!value) return null;
|
|
@@ -52,6 +54,14 @@ const validateWorkflow = (value) => {
|
|
|
52
54
|
return null;
|
|
53
55
|
};
|
|
54
56
|
|
|
57
|
+
const validateVercelWebhook = (value) => {
|
|
58
|
+
if (!value) return 'Webhook URL is required';
|
|
59
|
+
if (!VERCEL_WEBHOOK_PATTERN.test(value)) {
|
|
60
|
+
return 'Must be a valid Vercel deploy hook URL (https://api.vercel.com/v1/integrations/deploy/...)';
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
};
|
|
64
|
+
|
|
55
65
|
const SettingsPage = () => {
|
|
56
66
|
const navigate = useNavigate();
|
|
57
67
|
const { get, put, post, del } = useFetchClient();
|
|
@@ -69,7 +79,7 @@ const SettingsPage = () => {
|
|
|
69
79
|
|
|
70
80
|
// Target form state
|
|
71
81
|
const [editingTarget, setEditingTarget] = useState(null);
|
|
72
|
-
const [targetForm, setTargetForm] = useState({ name: '', workflow: '', branch: '' });
|
|
82
|
+
const [targetForm, setTargetForm] = useState({ type: 'github', name: '', workflow: '', branch: '', webhookUrl: '' });
|
|
73
83
|
const [targetErrors, setTargetErrors] = useState({});
|
|
74
84
|
const [showAddForm, setShowAddForm] = useState(false);
|
|
75
85
|
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
|
@@ -145,7 +155,7 @@ const SettingsPage = () => {
|
|
|
145
155
|
|
|
146
156
|
// Target management
|
|
147
157
|
const resetTargetForm = () => {
|
|
148
|
-
setTargetForm({ name: '', workflow: 'deploy.yml', branch: 'master' });
|
|
158
|
+
setTargetForm({ type: 'github', name: '', workflow: 'deploy.yml', branch: 'master', webhookUrl: '' });
|
|
149
159
|
setTargetErrors({});
|
|
150
160
|
setEditingTarget(null);
|
|
151
161
|
setShowAddForm(false);
|
|
@@ -154,9 +164,16 @@ const SettingsPage = () => {
|
|
|
154
164
|
const validateTargetForm = () => {
|
|
155
165
|
const newErrors = {};
|
|
156
166
|
if (!targetForm.name.trim()) newErrors.name = 'Name is required';
|
|
157
|
-
|
|
158
|
-
if (
|
|
159
|
-
|
|
167
|
+
|
|
168
|
+
if (targetForm.type === 'github') {
|
|
169
|
+
const workflowError = validateWorkflow(targetForm.workflow);
|
|
170
|
+
if (workflowError) newErrors.workflow = workflowError;
|
|
171
|
+
if (!targetForm.branch.trim()) newErrors.branch = 'Branch is required';
|
|
172
|
+
} else if (targetForm.type === 'vercel') {
|
|
173
|
+
const webhookError = validateVercelWebhook(targetForm.webhookUrl);
|
|
174
|
+
if (webhookError) newErrors.webhookUrl = webhookError;
|
|
175
|
+
}
|
|
176
|
+
|
|
160
177
|
setTargetErrors(newErrors);
|
|
161
178
|
return Object.keys(newErrors).length === 0;
|
|
162
179
|
};
|
|
@@ -180,7 +197,13 @@ const SettingsPage = () => {
|
|
|
180
197
|
|
|
181
198
|
const handleEditTarget = (target) => {
|
|
182
199
|
setEditingTarget(target.id);
|
|
183
|
-
setTargetForm({
|
|
200
|
+
setTargetForm({
|
|
201
|
+
type: target.type || 'github',
|
|
202
|
+
name: target.name,
|
|
203
|
+
workflow: target.workflow || 'deploy.yml',
|
|
204
|
+
branch: target.branch || 'master',
|
|
205
|
+
webhookUrl: target.webhookUrl || '',
|
|
206
|
+
});
|
|
184
207
|
setShowAddForm(false);
|
|
185
208
|
};
|
|
186
209
|
|
|
@@ -330,7 +353,7 @@ const SettingsPage = () => {
|
|
|
330
353
|
startIcon={<Plus />}
|
|
331
354
|
onClick={() => {
|
|
332
355
|
setShowAddForm(true);
|
|
333
|
-
setTargetForm({ name: '', workflow: 'deploy.yml', branch: 'master' });
|
|
356
|
+
setTargetForm({ type: 'github', name: '', workflow: 'deploy.yml', branch: 'master', webhookUrl: '' });
|
|
334
357
|
}}
|
|
335
358
|
size="S"
|
|
336
359
|
>
|
|
@@ -351,7 +374,19 @@ const SettingsPage = () => {
|
|
|
351
374
|
{editingTarget ? 'Edit Target' : 'Add New Target'}
|
|
352
375
|
</Typography>
|
|
353
376
|
<Grid.Root gap={4}>
|
|
354
|
-
<Grid.Item col={
|
|
377
|
+
<Grid.Item col={3} s={12}>
|
|
378
|
+
<Field.Root name="targetType" required>
|
|
379
|
+
<Field.Label>Type</Field.Label>
|
|
380
|
+
<SingleSelect
|
|
381
|
+
value={targetForm.type}
|
|
382
|
+
onChange={(value) => setTargetForm(prev => ({ ...prev, type: value }))}
|
|
383
|
+
>
|
|
384
|
+
<SingleSelectOption value="github">GitHub</SingleSelectOption>
|
|
385
|
+
<SingleSelectOption value="vercel">Vercel</SingleSelectOption>
|
|
386
|
+
</SingleSelect>
|
|
387
|
+
</Field.Root>
|
|
388
|
+
</Grid.Item>
|
|
389
|
+
<Grid.Item col={3} s={12}>
|
|
355
390
|
<Field.Root name="targetName" required error={targetErrors.name}>
|
|
356
391
|
<Field.Label>Name</Field.Label>
|
|
357
392
|
<Field.Input
|
|
@@ -362,28 +397,49 @@ const SettingsPage = () => {
|
|
|
362
397
|
<Field.Error />
|
|
363
398
|
</Field.Root>
|
|
364
399
|
</Grid.Item>
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
400
|
+
|
|
401
|
+
{/* GitHub-specific fields */}
|
|
402
|
+
{targetForm.type === 'github' && (
|
|
403
|
+
<>
|
|
404
|
+
<Grid.Item col={3} s={12}>
|
|
405
|
+
<Field.Root name="targetWorkflow" required error={targetErrors.workflow}>
|
|
406
|
+
<Field.Label>Workflow File</Field.Label>
|
|
407
|
+
<Field.Input
|
|
408
|
+
placeholder="deploy.yml"
|
|
409
|
+
value={targetForm.workflow}
|
|
410
|
+
onChange={handleTargetFormChange('workflow')}
|
|
411
|
+
/>
|
|
412
|
+
<Field.Error />
|
|
413
|
+
</Field.Root>
|
|
414
|
+
</Grid.Item>
|
|
415
|
+
<Grid.Item col={3} s={12}>
|
|
416
|
+
<Field.Root name="targetBranch" required error={targetErrors.branch}>
|
|
417
|
+
<Field.Label>Branch</Field.Label>
|
|
418
|
+
<Field.Input
|
|
419
|
+
placeholder="main"
|
|
420
|
+
value={targetForm.branch}
|
|
421
|
+
onChange={handleTargetFormChange('branch')}
|
|
422
|
+
/>
|
|
423
|
+
<Field.Error />
|
|
424
|
+
</Field.Root>
|
|
425
|
+
</Grid.Item>
|
|
426
|
+
</>
|
|
427
|
+
)}
|
|
428
|
+
|
|
429
|
+
{/* Vercel-specific fields */}
|
|
430
|
+
{targetForm.type === 'vercel' && (
|
|
431
|
+
<Grid.Item col={6} s={12}>
|
|
432
|
+
<Field.Root name="targetWebhookUrl" required error={targetErrors.webhookUrl}>
|
|
433
|
+
<Field.Label>Webhook URL</Field.Label>
|
|
434
|
+
<Field.Input
|
|
435
|
+
placeholder="https://api.vercel.com/v1/integrations/deploy/..."
|
|
436
|
+
value={targetForm.webhookUrl}
|
|
437
|
+
onChange={handleTargetFormChange('webhookUrl')}
|
|
438
|
+
/>
|
|
439
|
+
<Field.Error />
|
|
440
|
+
</Field.Root>
|
|
441
|
+
</Grid.Item>
|
|
442
|
+
)}
|
|
387
443
|
</Grid.Root>
|
|
388
444
|
<Flex gap={2} justifyContent="flex-end">
|
|
389
445
|
<Button variant="tertiary" onClick={resetTargetForm}>
|
|
@@ -405,41 +461,60 @@ const SettingsPage = () => {
|
|
|
405
461
|
<Table>
|
|
406
462
|
<Thead>
|
|
407
463
|
<Tr>
|
|
464
|
+
<Th><Typography variant="sigma">Type</Typography></Th>
|
|
408
465
|
<Th><Typography variant="sigma">Name</Typography></Th>
|
|
409
|
-
<Th><Typography variant="sigma">
|
|
410
|
-
<Th><Typography variant="sigma">Branch</Typography></Th>
|
|
466
|
+
<Th><Typography variant="sigma">Details</Typography></Th>
|
|
411
467
|
<Th><Typography variant="sigma">Actions</Typography></Th>
|
|
412
468
|
</Tr>
|
|
413
469
|
</Thead>
|
|
414
470
|
<Tbody>
|
|
415
|
-
{settings.targets.map((target) =>
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
<
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
<
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
471
|
+
{settings.targets.map((target) => {
|
|
472
|
+
const targetType = target.type || 'github';
|
|
473
|
+
return (
|
|
474
|
+
<Tr key={target.id}>
|
|
475
|
+
<Td>
|
|
476
|
+
<Typography variant="omega" fontWeight="bold" textColor={targetType === 'github' ? 'neutral800' : 'secondary600'}>
|
|
477
|
+
{targetType === 'github' ? 'GitHub' : 'Vercel'}
|
|
478
|
+
</Typography>
|
|
479
|
+
</Td>
|
|
480
|
+
<Td><Typography variant="omega">{target.name}</Typography></Td>
|
|
481
|
+
<Td>
|
|
482
|
+
{targetType === 'github' ? (
|
|
483
|
+
<Typography variant="omega" textColor="neutral600">
|
|
484
|
+
{target.workflow} / {target.branch}
|
|
485
|
+
</Typography>
|
|
486
|
+
) : (
|
|
487
|
+
<Typography variant="omega" textColor="neutral600">
|
|
488
|
+
Webhook configured
|
|
489
|
+
</Typography>
|
|
490
|
+
)}
|
|
491
|
+
</Td>
|
|
492
|
+
<Td>
|
|
493
|
+
<Flex gap={2}>
|
|
494
|
+
<Button
|
|
495
|
+
onClick={() => handleEditTarget(target)}
|
|
496
|
+
variant="tertiary"
|
|
497
|
+
size="S"
|
|
498
|
+
startIcon={<Pencil />}
|
|
499
|
+
>
|
|
500
|
+
Edit
|
|
501
|
+
</Button>
|
|
502
|
+
<Button
|
|
503
|
+
onClick={() => {
|
|
504
|
+
setTargetToDelete(target.id);
|
|
505
|
+
setDeleteDialogOpen(true);
|
|
506
|
+
}}
|
|
507
|
+
variant="danger-light"
|
|
508
|
+
size="S"
|
|
509
|
+
startIcon={<Trash />}
|
|
510
|
+
>
|
|
511
|
+
Delete
|
|
512
|
+
</Button>
|
|
513
|
+
</Flex>
|
|
514
|
+
</Td>
|
|
515
|
+
</Tr>
|
|
516
|
+
);
|
|
517
|
+
})}
|
|
443
518
|
</Tbody>
|
|
444
519
|
</Table>
|
|
445
520
|
) : (
|