@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/dist/server/index.mjs
CHANGED
|
@@ -68,6 +68,30 @@ const controller = ({ strapi }) => ({
|
|
|
68
68
|
},
|
|
69
69
|
// Trigger deployment for a specific target
|
|
70
70
|
async trigger(ctx) {
|
|
71
|
+
const service2 = getService(strapi);
|
|
72
|
+
const { targetId } = ctx.request.body || {};
|
|
73
|
+
let target;
|
|
74
|
+
if (targetId) {
|
|
75
|
+
target = await service2.getTarget(targetId);
|
|
76
|
+
if (!target) {
|
|
77
|
+
return ctx.badRequest("Target not found");
|
|
78
|
+
}
|
|
79
|
+
} else {
|
|
80
|
+
const settings = await service2.getSettings();
|
|
81
|
+
target = settings.targets?.[0];
|
|
82
|
+
if (!target) {
|
|
83
|
+
return ctx.badRequest("No deployment targets configured");
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
const targetType = target.type || "github";
|
|
87
|
+
if (targetType === "vercel") {
|
|
88
|
+
return this.triggerVercel(ctx, target);
|
|
89
|
+
} else {
|
|
90
|
+
return this.triggerGitHub(ctx, target);
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
// Trigger GitHub Actions deployment
|
|
94
|
+
async triggerGitHub(ctx, target) {
|
|
71
95
|
const service2 = getService(strapi);
|
|
72
96
|
const githubToken = await service2.getToken();
|
|
73
97
|
if (!githubToken) {
|
|
@@ -78,22 +102,9 @@ const controller = ({ strapi }) => ({
|
|
|
78
102
|
if (!owner || !repo) {
|
|
79
103
|
return ctx.badRequest("GitHub repository URL is not configured or invalid. Please configure it in Settings.");
|
|
80
104
|
}
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const target = await service2.getTarget(targetId);
|
|
85
|
-
if (!target) {
|
|
86
|
-
return ctx.badRequest("Target not found");
|
|
87
|
-
}
|
|
88
|
-
workflow = overrideWorkflow || target.workflow;
|
|
89
|
-
branch = overrideBranch || target.branch;
|
|
90
|
-
targetName = target.name;
|
|
91
|
-
} else {
|
|
92
|
-
const firstTarget = settings.targets?.[0];
|
|
93
|
-
workflow = overrideWorkflow || firstTarget?.workflow || "deploy.yml";
|
|
94
|
-
branch = overrideBranch || firstTarget?.branch || "master";
|
|
95
|
-
targetName = firstTarget?.name || "Default";
|
|
96
|
-
}
|
|
105
|
+
const workflow = target.workflow || "deploy.yml";
|
|
106
|
+
const branch = target.branch || "master";
|
|
107
|
+
const targetName = target.name;
|
|
97
108
|
const url = `https://api.github.com/repos/${owner}/${repo}/actions/workflows/${workflow}/dispatches`;
|
|
98
109
|
try {
|
|
99
110
|
const response = await fetch(url, {
|
|
@@ -110,11 +121,12 @@ const controller = ({ strapi }) => ({
|
|
|
110
121
|
strapi.log.error(`GitHub API error: ${response.status} - ${errorText}`);
|
|
111
122
|
return ctx.badRequest(`GitHub API error: ${response.status} - ${errorText}`);
|
|
112
123
|
}
|
|
113
|
-
strapi.log.info(`
|
|
124
|
+
strapi.log.info(`GitHub deployment triggered for ${owner}/${repo} [${targetName}] on branch ${branch}`);
|
|
114
125
|
const actionsUrl = `https://github.com/${owner}/${repo}/actions`;
|
|
115
126
|
ctx.body = {
|
|
116
127
|
data: {
|
|
117
128
|
success: true,
|
|
129
|
+
type: "github",
|
|
118
130
|
message: `Deployment triggered successfully for ${owner}/${repo}`,
|
|
119
131
|
repository: `${owner}/${repo}`,
|
|
120
132
|
targetName,
|
|
@@ -124,9 +136,39 @@ const controller = ({ strapi }) => ({
|
|
|
124
136
|
}
|
|
125
137
|
};
|
|
126
138
|
} catch (error) {
|
|
127
|
-
strapi.log.error("Error triggering deployment:", error);
|
|
139
|
+
strapi.log.error("Error triggering GitHub deployment:", error);
|
|
128
140
|
return ctx.badRequest(`Failed to trigger deployment: ${error.message}`);
|
|
129
141
|
}
|
|
142
|
+
},
|
|
143
|
+
// Trigger Vercel deployment via webhook
|
|
144
|
+
async triggerVercel(ctx, target) {
|
|
145
|
+
const webhookUrl = target.webhookUrl;
|
|
146
|
+
const targetName = target.name;
|
|
147
|
+
if (!webhookUrl) {
|
|
148
|
+
return ctx.badRequest("Vercel webhook URL is not configured for this target.");
|
|
149
|
+
}
|
|
150
|
+
try {
|
|
151
|
+
const response = await fetch(webhookUrl, {
|
|
152
|
+
method: "POST"
|
|
153
|
+
});
|
|
154
|
+
if (!response.ok) {
|
|
155
|
+
const errorText = await response.text();
|
|
156
|
+
strapi.log.error(`Vercel webhook error: ${response.status} - ${errorText}`);
|
|
157
|
+
return ctx.badRequest(`Vercel webhook error: ${response.status} - ${errorText}`);
|
|
158
|
+
}
|
|
159
|
+
strapi.log.info(`Vercel deployment triggered [${targetName}]`);
|
|
160
|
+
ctx.body = {
|
|
161
|
+
data: {
|
|
162
|
+
success: true,
|
|
163
|
+
type: "vercel",
|
|
164
|
+
message: "Vercel deployment triggered successfully",
|
|
165
|
+
targetName
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
} catch (error) {
|
|
169
|
+
strapi.log.error("Error triggering Vercel deployment:", error);
|
|
170
|
+
return ctx.badRequest(`Failed to trigger Vercel deployment: ${error.message}`);
|
|
171
|
+
}
|
|
130
172
|
}
|
|
131
173
|
});
|
|
132
174
|
const controllers = {
|
|
@@ -248,7 +290,14 @@ const service = ({ strapi }) => ({
|
|
|
248
290
|
migrateSettings(settings) {
|
|
249
291
|
if (!settings) return null;
|
|
250
292
|
if (Array.isArray(settings.targets)) {
|
|
251
|
-
|
|
293
|
+
const targetsWithType = settings.targets.map((target) => ({
|
|
294
|
+
...target,
|
|
295
|
+
type: target.type || "github"
|
|
296
|
+
}));
|
|
297
|
+
return {
|
|
298
|
+
...settings,
|
|
299
|
+
targets: targetsWithType
|
|
300
|
+
};
|
|
252
301
|
}
|
|
253
302
|
if (settings.workflow || settings.branch) {
|
|
254
303
|
return {
|
|
@@ -256,6 +305,7 @@ const service = ({ strapi }) => ({
|
|
|
256
305
|
githubToken: settings.githubToken || "",
|
|
257
306
|
targets: [{
|
|
258
307
|
id: generateId(),
|
|
308
|
+
type: "github",
|
|
259
309
|
name: "Default",
|
|
260
310
|
workflow: settings.workflow || "deploy.yml",
|
|
261
311
|
branch: settings.branch || "master"
|
|
@@ -312,12 +362,18 @@ const service = ({ strapi }) => ({
|
|
|
312
362
|
const store = strapi.store({ type: "plugin", name: PLUGIN_ID });
|
|
313
363
|
let settings = await store.get({ key: STORE_KEY }) || DEFAULT_SETTINGS;
|
|
314
364
|
settings = this.migrateSettings(settings) || DEFAULT_SETTINGS;
|
|
365
|
+
const targetType = target.type || "github";
|
|
315
366
|
const newTarget = {
|
|
316
367
|
id: generateId(),
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
branch: target.branch || "master"
|
|
368
|
+
type: targetType,
|
|
369
|
+
name: target.name || "New Target"
|
|
320
370
|
};
|
|
371
|
+
if (targetType === "github") {
|
|
372
|
+
newTarget.workflow = target.workflow || "deploy.yml";
|
|
373
|
+
newTarget.branch = target.branch || "master";
|
|
374
|
+
} else if (targetType === "vercel") {
|
|
375
|
+
newTarget.webhookUrl = target.webhookUrl || "";
|
|
376
|
+
}
|
|
321
377
|
settings.targets = [...settings.targets || [], newTarget];
|
|
322
378
|
await store.set({ key: STORE_KEY, value: settings });
|
|
323
379
|
return newTarget;
|
|
@@ -329,12 +385,20 @@ const service = ({ strapi }) => ({
|
|
|
329
385
|
if (!settings?.targets) return null;
|
|
330
386
|
const targetIndex = settings.targets.findIndex((t) => t.id === targetId);
|
|
331
387
|
if (targetIndex === -1) return null;
|
|
332
|
-
settings.targets[targetIndex]
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
id: targetId
|
|
336
|
-
|
|
388
|
+
const existingTarget = settings.targets[targetIndex];
|
|
389
|
+
const targetType = updates.type || existingTarget.type || "github";
|
|
390
|
+
const updatedTarget = {
|
|
391
|
+
id: targetId,
|
|
392
|
+
type: targetType,
|
|
393
|
+
name: updates.name !== void 0 ? updates.name : existingTarget.name
|
|
337
394
|
};
|
|
395
|
+
if (targetType === "github") {
|
|
396
|
+
updatedTarget.workflow = updates.workflow !== void 0 ? updates.workflow : existingTarget.workflow;
|
|
397
|
+
updatedTarget.branch = updates.branch !== void 0 ? updates.branch : existingTarget.branch;
|
|
398
|
+
} else if (targetType === "vercel") {
|
|
399
|
+
updatedTarget.webhookUrl = updates.webhookUrl !== void 0 ? updates.webhookUrl : existingTarget.webhookUrl;
|
|
400
|
+
}
|
|
401
|
+
settings.targets[targetIndex] = updatedTarget;
|
|
338
402
|
await store.set({ key: STORE_KEY, value: settings });
|
|
339
403
|
return settings.targets[targetIndex];
|
|
340
404
|
},
|
package/package.json
CHANGED
|
@@ -70,6 +70,37 @@ const controller = ({ strapi }) => ({
|
|
|
70
70
|
|
|
71
71
|
// Trigger deployment for a specific target
|
|
72
72
|
async trigger(ctx) {
|
|
73
|
+
const service = getService(strapi);
|
|
74
|
+
const { targetId } = ctx.request.body || {};
|
|
75
|
+
|
|
76
|
+
// Get target
|
|
77
|
+
let target;
|
|
78
|
+
if (targetId) {
|
|
79
|
+
target = await service.getTarget(targetId);
|
|
80
|
+
if (!target) {
|
|
81
|
+
return ctx.badRequest('Target not found');
|
|
82
|
+
}
|
|
83
|
+
} else {
|
|
84
|
+
// Fallback for backwards compatibility - use first target
|
|
85
|
+
const settings = await service.getSettings();
|
|
86
|
+
target = settings.targets?.[0];
|
|
87
|
+
if (!target) {
|
|
88
|
+
return ctx.badRequest('No deployment targets configured');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const targetType = target.type || 'github';
|
|
93
|
+
|
|
94
|
+
// Branch by target type
|
|
95
|
+
if (targetType === 'vercel') {
|
|
96
|
+
return this.triggerVercel(ctx, target);
|
|
97
|
+
} else {
|
|
98
|
+
return this.triggerGitHub(ctx, target);
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
|
|
102
|
+
// Trigger GitHub Actions deployment
|
|
103
|
+
async triggerGitHub(ctx, target) {
|
|
73
104
|
const service = getService(strapi);
|
|
74
105
|
const githubToken = await service.getToken();
|
|
75
106
|
|
|
@@ -84,27 +115,9 @@ const controller = ({ strapi }) => ({
|
|
|
84
115
|
return ctx.badRequest('GitHub repository URL is not configured or invalid. Please configure it in Settings.');
|
|
85
116
|
}
|
|
86
117
|
|
|
87
|
-
|
|
88
|
-
const
|
|
89
|
-
|
|
90
|
-
let workflow, branch, targetName;
|
|
91
|
-
|
|
92
|
-
if (targetId) {
|
|
93
|
-
// Trigger specific target
|
|
94
|
-
const target = await service.getTarget(targetId);
|
|
95
|
-
if (!target) {
|
|
96
|
-
return ctx.badRequest('Target not found');
|
|
97
|
-
}
|
|
98
|
-
workflow = overrideWorkflow || target.workflow;
|
|
99
|
-
branch = overrideBranch || target.branch;
|
|
100
|
-
targetName = target.name;
|
|
101
|
-
} else {
|
|
102
|
-
// Fallback for backwards compatibility - use first target or provided values
|
|
103
|
-
const firstTarget = settings.targets?.[0];
|
|
104
|
-
workflow = overrideWorkflow || firstTarget?.workflow || 'deploy.yml';
|
|
105
|
-
branch = overrideBranch || firstTarget?.branch || 'master';
|
|
106
|
-
targetName = firstTarget?.name || 'Default';
|
|
107
|
-
}
|
|
118
|
+
const workflow = target.workflow || 'deploy.yml';
|
|
119
|
+
const branch = target.branch || 'master';
|
|
120
|
+
const targetName = target.name;
|
|
108
121
|
|
|
109
122
|
const url = `https://api.github.com/repos/${owner}/${repo}/actions/workflows/${workflow}/dispatches`;
|
|
110
123
|
|
|
@@ -125,13 +138,14 @@ const controller = ({ strapi }) => ({
|
|
|
125
138
|
return ctx.badRequest(`GitHub API error: ${response.status} - ${errorText}`);
|
|
126
139
|
}
|
|
127
140
|
|
|
128
|
-
strapi.log.info(`
|
|
141
|
+
strapi.log.info(`GitHub deployment triggered for ${owner}/${repo} [${targetName}] on branch ${branch}`);
|
|
129
142
|
|
|
130
143
|
const actionsUrl = `https://github.com/${owner}/${repo}/actions`;
|
|
131
144
|
|
|
132
145
|
ctx.body = {
|
|
133
146
|
data: {
|
|
134
147
|
success: true,
|
|
148
|
+
type: 'github',
|
|
135
149
|
message: `Deployment triggered successfully for ${owner}/${repo}`,
|
|
136
150
|
repository: `${owner}/${repo}`,
|
|
137
151
|
targetName,
|
|
@@ -141,10 +155,46 @@ const controller = ({ strapi }) => ({
|
|
|
141
155
|
},
|
|
142
156
|
};
|
|
143
157
|
} catch (error) {
|
|
144
|
-
strapi.log.error('Error triggering deployment:', error);
|
|
158
|
+
strapi.log.error('Error triggering GitHub deployment:', error);
|
|
145
159
|
return ctx.badRequest(`Failed to trigger deployment: ${error.message}`);
|
|
146
160
|
}
|
|
147
161
|
},
|
|
162
|
+
|
|
163
|
+
// Trigger Vercel deployment via webhook
|
|
164
|
+
async triggerVercel(ctx, target) {
|
|
165
|
+
const webhookUrl = target.webhookUrl;
|
|
166
|
+
const targetName = target.name;
|
|
167
|
+
|
|
168
|
+
if (!webhookUrl) {
|
|
169
|
+
return ctx.badRequest('Vercel webhook URL is not configured for this target.');
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
try {
|
|
173
|
+
const response = await fetch(webhookUrl, {
|
|
174
|
+
method: 'POST',
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (!response.ok) {
|
|
178
|
+
const errorText = await response.text();
|
|
179
|
+
strapi.log.error(`Vercel webhook error: ${response.status} - ${errorText}`);
|
|
180
|
+
return ctx.badRequest(`Vercel webhook error: ${response.status} - ${errorText}`);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
strapi.log.info(`Vercel deployment triggered [${targetName}]`);
|
|
184
|
+
|
|
185
|
+
ctx.body = {
|
|
186
|
+
data: {
|
|
187
|
+
success: true,
|
|
188
|
+
type: 'vercel',
|
|
189
|
+
message: 'Vercel deployment triggered successfully',
|
|
190
|
+
targetName,
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
} catch (error) {
|
|
194
|
+
strapi.log.error('Error triggering Vercel deployment:', error);
|
|
195
|
+
return ctx.badRequest(`Failed to trigger Vercel deployment: ${error.message}`);
|
|
196
|
+
}
|
|
197
|
+
},
|
|
148
198
|
});
|
|
149
199
|
|
|
150
200
|
export default controller;
|
|
@@ -39,9 +39,17 @@ const service = ({ strapi }) => ({
|
|
|
39
39
|
migrateSettings(settings) {
|
|
40
40
|
if (!settings) return null;
|
|
41
41
|
|
|
42
|
-
// Already in new format
|
|
42
|
+
// Already in new format with targets array
|
|
43
43
|
if (Array.isArray(settings.targets)) {
|
|
44
|
-
|
|
44
|
+
// Ensure all targets have a type field (backward compatibility)
|
|
45
|
+
const targetsWithType = settings.targets.map(target => ({
|
|
46
|
+
...target,
|
|
47
|
+
type: target.type || 'github',
|
|
48
|
+
}));
|
|
49
|
+
return {
|
|
50
|
+
...settings,
|
|
51
|
+
targets: targetsWithType,
|
|
52
|
+
};
|
|
45
53
|
}
|
|
46
54
|
|
|
47
55
|
// Old format detected - migrate
|
|
@@ -51,6 +59,7 @@ const service = ({ strapi }) => ({
|
|
|
51
59
|
githubToken: settings.githubToken || '',
|
|
52
60
|
targets: [{
|
|
53
61
|
id: generateId(),
|
|
62
|
+
type: 'github',
|
|
54
63
|
name: 'Default',
|
|
55
64
|
workflow: settings.workflow || 'deploy.yml',
|
|
56
65
|
branch: settings.branch || 'master',
|
|
@@ -124,13 +133,22 @@ const service = ({ strapi }) => ({
|
|
|
124
133
|
let settings = await store.get({ key: STORE_KEY }) || DEFAULT_SETTINGS;
|
|
125
134
|
settings = this.migrateSettings(settings) || DEFAULT_SETTINGS;
|
|
126
135
|
|
|
136
|
+
const targetType = target.type || 'github';
|
|
137
|
+
|
|
127
138
|
const newTarget = {
|
|
128
139
|
id: generateId(),
|
|
140
|
+
type: targetType,
|
|
129
141
|
name: target.name || 'New Target',
|
|
130
|
-
workflow: target.workflow || 'deploy.yml',
|
|
131
|
-
branch: target.branch || 'master',
|
|
132
142
|
};
|
|
133
143
|
|
|
144
|
+
// Add type-specific fields
|
|
145
|
+
if (targetType === 'github') {
|
|
146
|
+
newTarget.workflow = target.workflow || 'deploy.yml';
|
|
147
|
+
newTarget.branch = target.branch || 'master';
|
|
148
|
+
} else if (targetType === 'vercel') {
|
|
149
|
+
newTarget.webhookUrl = target.webhookUrl || '';
|
|
150
|
+
}
|
|
151
|
+
|
|
134
152
|
settings.targets = [...(settings.targets || []), newTarget];
|
|
135
153
|
await store.set({ key: STORE_KEY, value: settings });
|
|
136
154
|
|
|
@@ -147,12 +165,25 @@ const service = ({ strapi }) => ({
|
|
|
147
165
|
const targetIndex = settings.targets.findIndex(t => t.id === targetId);
|
|
148
166
|
if (targetIndex === -1) return null;
|
|
149
167
|
|
|
150
|
-
settings.targets[targetIndex]
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
168
|
+
const existingTarget = settings.targets[targetIndex];
|
|
169
|
+
const targetType = updates.type || existingTarget.type || 'github';
|
|
170
|
+
|
|
171
|
+
// Build updated target with type-specific fields
|
|
172
|
+
const updatedTarget = {
|
|
173
|
+
id: targetId,
|
|
174
|
+
type: targetType,
|
|
175
|
+
name: updates.name !== undefined ? updates.name : existingTarget.name,
|
|
154
176
|
};
|
|
155
177
|
|
|
178
|
+
if (targetType === 'github') {
|
|
179
|
+
updatedTarget.workflow = updates.workflow !== undefined ? updates.workflow : existingTarget.workflow;
|
|
180
|
+
updatedTarget.branch = updates.branch !== undefined ? updates.branch : existingTarget.branch;
|
|
181
|
+
} else if (targetType === 'vercel') {
|
|
182
|
+
updatedTarget.webhookUrl = updates.webhookUrl !== undefined ? updates.webhookUrl : existingTarget.webhookUrl;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
settings.targets[targetIndex] = updatedTarget;
|
|
186
|
+
|
|
156
187
|
await store.set({ key: STORE_KEY, value: settings });
|
|
157
188
|
return settings.targets[targetIndex];
|
|
158
189
|
},
|