thepopebot 1.2.47 → 1.2.49
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/lib/chat/actions.js +0 -32
- package/lib/chat/components/swarm-page.js +14 -64
- package/lib/chat/components/swarm-page.jsx +15 -64
- package/lib/tools/github.js +0 -51
- package/package.json +1 -1
- package/templates/.github/workflows/rebuild-event-handler.yml +75 -9
- package/templates/.github/workflows/upgrade-event-handler.yml +19 -20
package/lib/chat/actions.js
CHANGED
|
@@ -264,35 +264,3 @@ export async function getSwarmConfig() {
|
|
|
264
264
|
return { crons, triggers };
|
|
265
265
|
}
|
|
266
266
|
|
|
267
|
-
/**
|
|
268
|
-
* Cancel a running swarm job.
|
|
269
|
-
* @param {number} runId - Workflow run ID
|
|
270
|
-
* @returns {Promise<object>}
|
|
271
|
-
*/
|
|
272
|
-
export async function cancelSwarmJob(runId) {
|
|
273
|
-
await requireAuth();
|
|
274
|
-
try {
|
|
275
|
-
const { cancelWorkflowRun } = await import('../tools/github.js');
|
|
276
|
-
return await cancelWorkflowRun(runId);
|
|
277
|
-
} catch (err) {
|
|
278
|
-
console.error('Failed to cancel workflow run:', err);
|
|
279
|
-
return { error: err.message || 'Failed to cancel workflow run' };
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
/**
|
|
284
|
-
* Rerun a swarm job (all or failed only).
|
|
285
|
-
* @param {number} runId - Workflow run ID
|
|
286
|
-
* @param {boolean} [failedOnly=false]
|
|
287
|
-
* @returns {Promise<object>}
|
|
288
|
-
*/
|
|
289
|
-
export async function rerunSwarmJob(runId, failedOnly = false) {
|
|
290
|
-
await requireAuth();
|
|
291
|
-
try {
|
|
292
|
-
const { rerunWorkflowRun } = await import('../tools/github.js');
|
|
293
|
-
return await rerunWorkflowRun(runId, !!failedOnly);
|
|
294
|
-
} catch (err) {
|
|
295
|
-
console.error('Failed to rerun workflow:', err);
|
|
296
|
-
return { error: err.message || 'Failed to rerun workflow' };
|
|
297
|
-
}
|
|
298
|
-
}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useEffect, useCallback } from "react";
|
|
4
4
|
import { PageLayout } from "./page-layout.js";
|
|
5
|
-
import {
|
|
6
|
-
import { getSwarmStatus
|
|
5
|
+
import { SpinnerIcon, RefreshIcon } from "./icons.js";
|
|
6
|
+
import { getSwarmStatus } from "../actions.js";
|
|
7
7
|
function formatDuration(seconds) {
|
|
8
8
|
if (seconds < 60) return `${seconds}s`;
|
|
9
9
|
const minutes = Math.floor(seconds / 60);
|
|
@@ -55,7 +55,7 @@ const conclusionBadgeStyles = {
|
|
|
55
55
|
cancelled: "bg-yellow-500/10 text-yellow-500",
|
|
56
56
|
skipped: "bg-muted text-muted-foreground"
|
|
57
57
|
};
|
|
58
|
-
function SwarmWorkflowList({ runs
|
|
58
|
+
function SwarmWorkflowList({ runs }) {
|
|
59
59
|
if (!runs || runs.length === 0) {
|
|
60
60
|
return /* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground py-4 text-center", children: "No workflow runs." });
|
|
61
61
|
}
|
|
@@ -76,43 +76,16 @@ function SwarmWorkflowList({ runs, onCancel, onRerun }) {
|
|
|
76
76
|
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium truncate", children: run.workflow_name || run.branch }),
|
|
77
77
|
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground shrink-0", children: isActive ? formatDuration(run.duration_seconds) : timeAgo(run.updated_at || run.started_at) }),
|
|
78
78
|
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
79
|
-
/* @__PURE__ */
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
),
|
|
90
|
-
isActive && /* @__PURE__ */ jsx(
|
|
91
|
-
"button",
|
|
92
|
-
{
|
|
93
|
-
onClick: () => onCancel(run.run_id),
|
|
94
|
-
className: "inline-flex items-center justify-center rounded-md p-1.5 text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
|
|
95
|
-
title: "Cancel",
|
|
96
|
-
children: /* @__PURE__ */ jsx(StopIcon, { size: 14 })
|
|
97
|
-
}
|
|
98
|
-
),
|
|
99
|
-
!isActive && /* @__PURE__ */ jsx(
|
|
100
|
-
"button",
|
|
101
|
-
{
|
|
102
|
-
onClick: () => onRerun(run.run_id, false),
|
|
103
|
-
className: "text-xs rounded-md px-2 py-1 border hover:bg-accent",
|
|
104
|
-
children: "Rerun"
|
|
105
|
-
}
|
|
106
|
-
),
|
|
107
|
-
!isActive && run.conclusion === "failure" && /* @__PURE__ */ jsx(
|
|
108
|
-
"button",
|
|
109
|
-
{
|
|
110
|
-
onClick: () => onRerun(run.run_id, true),
|
|
111
|
-
className: "text-xs rounded-md px-2 py-1 border text-red-500 hover:bg-red-500/10",
|
|
112
|
-
children: "Rerun failed"
|
|
113
|
-
}
|
|
114
|
-
)
|
|
115
|
-
] })
|
|
79
|
+
run.html_url && /* @__PURE__ */ jsx(
|
|
80
|
+
"a",
|
|
81
|
+
{
|
|
82
|
+
href: run.html_url,
|
|
83
|
+
target: "_blank",
|
|
84
|
+
rel: "noopener noreferrer",
|
|
85
|
+
className: "text-xs text-blue-500 hover:underline shrink-0",
|
|
86
|
+
children: "View"
|
|
87
|
+
}
|
|
88
|
+
)
|
|
116
89
|
] }, run.run_id);
|
|
117
90
|
}) });
|
|
118
91
|
}
|
|
@@ -173,22 +146,6 @@ function SwarmPage({ session }) {
|
|
|
173
146
|
}
|
|
174
147
|
setLoadingMore(false);
|
|
175
148
|
};
|
|
176
|
-
const handleCancel = async (runId) => {
|
|
177
|
-
try {
|
|
178
|
-
await cancelSwarmJob(runId);
|
|
179
|
-
await fetchStatus();
|
|
180
|
-
} catch (err) {
|
|
181
|
-
console.error("Failed to cancel job:", err);
|
|
182
|
-
}
|
|
183
|
-
};
|
|
184
|
-
const handleRerun = async (runId, failedOnly) => {
|
|
185
|
-
try {
|
|
186
|
-
await rerunSwarmJob(runId, failedOnly);
|
|
187
|
-
await fetchStatus();
|
|
188
|
-
} catch (err) {
|
|
189
|
-
console.error("Failed to rerun job:", err);
|
|
190
|
-
}
|
|
191
|
-
};
|
|
192
149
|
return /* @__PURE__ */ jsxs(PageLayout, { session, children: [
|
|
193
150
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between mb-6", children: [
|
|
194
151
|
/* @__PURE__ */ jsx("h1", { className: "text-2xl font-semibold", children: "Swarm" }),
|
|
@@ -212,14 +169,7 @@ function SwarmPage({ session }) {
|
|
|
212
169
|
/* @__PURE__ */ jsx(SwarmSummaryCards, { counts }),
|
|
213
170
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
214
171
|
/* @__PURE__ */ jsx("h2", { className: "text-sm font-medium text-muted-foreground uppercase tracking-wide mb-3", children: "Workflow Runs" }),
|
|
215
|
-
/* @__PURE__ */ jsx(
|
|
216
|
-
SwarmWorkflowList,
|
|
217
|
-
{
|
|
218
|
-
runs,
|
|
219
|
-
onCancel: handleCancel,
|
|
220
|
-
onRerun: handleRerun
|
|
221
|
-
}
|
|
222
|
-
),
|
|
172
|
+
/* @__PURE__ */ jsx(SwarmWorkflowList, { runs }),
|
|
223
173
|
hasMore && /* @__PURE__ */ jsx("div", { className: "flex justify-center mt-4", children: /* @__PURE__ */ jsx(
|
|
224
174
|
"button",
|
|
225
175
|
{
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useCallback } from 'react';
|
|
4
4
|
import { PageLayout } from './page-layout.js';
|
|
5
|
-
import {
|
|
6
|
-
import { getSwarmStatus
|
|
5
|
+
import { SpinnerIcon, RefreshIcon } from './icons.js';
|
|
6
|
+
import { getSwarmStatus } from '../actions.js';
|
|
7
7
|
|
|
8
8
|
// ─────────────────────────────────────────────────────────────────────────────
|
|
9
9
|
// Utilities
|
|
@@ -84,7 +84,7 @@ const conclusionBadgeStyles = {
|
|
|
84
84
|
skipped: 'bg-muted text-muted-foreground',
|
|
85
85
|
};
|
|
86
86
|
|
|
87
|
-
function SwarmWorkflowList({ runs
|
|
87
|
+
function SwarmWorkflowList({ runs }) {
|
|
88
88
|
if (!runs || runs.length === 0) {
|
|
89
89
|
return (
|
|
90
90
|
<div className="text-sm text-muted-foreground py-4 text-center">
|
|
@@ -134,44 +134,17 @@ function SwarmWorkflowList({ runs, onCancel, onRerun }) {
|
|
|
134
134
|
{/* Spacer */}
|
|
135
135
|
<div className="flex-1" />
|
|
136
136
|
|
|
137
|
-
{/*
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
)}
|
|
149
|
-
{isActive && (
|
|
150
|
-
<button
|
|
151
|
-
onClick={() => onCancel(run.run_id)}
|
|
152
|
-
className="inline-flex items-center justify-center rounded-md p-1.5 text-muted-foreground hover:bg-destructive/10 hover:text-destructive"
|
|
153
|
-
title="Cancel"
|
|
154
|
-
>
|
|
155
|
-
<StopIcon size={14} />
|
|
156
|
-
</button>
|
|
157
|
-
)}
|
|
158
|
-
{!isActive && (
|
|
159
|
-
<button
|
|
160
|
-
onClick={() => onRerun(run.run_id, false)}
|
|
161
|
-
className="text-xs rounded-md px-2 py-1 border hover:bg-accent"
|
|
162
|
-
>
|
|
163
|
-
Rerun
|
|
164
|
-
</button>
|
|
165
|
-
)}
|
|
166
|
-
{!isActive && run.conclusion === 'failure' && (
|
|
167
|
-
<button
|
|
168
|
-
onClick={() => onRerun(run.run_id, true)}
|
|
169
|
-
className="text-xs rounded-md px-2 py-1 border text-red-500 hover:bg-red-500/10"
|
|
170
|
-
>
|
|
171
|
-
Rerun failed
|
|
172
|
-
</button>
|
|
173
|
-
)}
|
|
174
|
-
</div>
|
|
137
|
+
{/* Link */}
|
|
138
|
+
{run.html_url && (
|
|
139
|
+
<a
|
|
140
|
+
href={run.html_url}
|
|
141
|
+
target="_blank"
|
|
142
|
+
rel="noopener noreferrer"
|
|
143
|
+
className="text-xs text-blue-500 hover:underline shrink-0"
|
|
144
|
+
>
|
|
145
|
+
View
|
|
146
|
+
</a>
|
|
147
|
+
)}
|
|
175
148
|
</div>
|
|
176
149
|
);
|
|
177
150
|
})}
|
|
@@ -246,24 +219,6 @@ export function SwarmPage({ session }) {
|
|
|
246
219
|
setLoadingMore(false);
|
|
247
220
|
};
|
|
248
221
|
|
|
249
|
-
const handleCancel = async (runId) => {
|
|
250
|
-
try {
|
|
251
|
-
await cancelSwarmJob(runId);
|
|
252
|
-
await fetchStatus();
|
|
253
|
-
} catch (err) {
|
|
254
|
-
console.error('Failed to cancel job:', err);
|
|
255
|
-
}
|
|
256
|
-
};
|
|
257
|
-
|
|
258
|
-
const handleRerun = async (runId, failedOnly) => {
|
|
259
|
-
try {
|
|
260
|
-
await rerunSwarmJob(runId, failedOnly);
|
|
261
|
-
await fetchStatus();
|
|
262
|
-
} catch (err) {
|
|
263
|
-
console.error('Failed to rerun job:', err);
|
|
264
|
-
}
|
|
265
|
-
};
|
|
266
|
-
|
|
267
222
|
return (
|
|
268
223
|
<PageLayout session={session}>
|
|
269
224
|
{/* Header */}
|
|
@@ -302,11 +257,7 @@ export function SwarmPage({ session }) {
|
|
|
302
257
|
<h2 className="text-sm font-medium text-muted-foreground uppercase tracking-wide mb-3">
|
|
303
258
|
Workflow Runs
|
|
304
259
|
</h2>
|
|
305
|
-
<SwarmWorkflowList
|
|
306
|
-
runs={runs}
|
|
307
|
-
onCancel={handleCancel}
|
|
308
|
-
onRerun={handleRerun}
|
|
309
|
-
/>
|
|
260
|
+
<SwarmWorkflowList runs={runs} />
|
|
310
261
|
{hasMore && (
|
|
311
262
|
<div className="flex justify-center mt-4">
|
|
312
263
|
<button
|
package/lib/tools/github.js
CHANGED
|
@@ -158,55 +158,6 @@ async function getSwarmStatus(page = 1) {
|
|
|
158
158
|
};
|
|
159
159
|
}
|
|
160
160
|
|
|
161
|
-
/**
|
|
162
|
-
* Cancel a workflow run
|
|
163
|
-
* @param {number} runId - Workflow run ID
|
|
164
|
-
*/
|
|
165
|
-
async function cancelWorkflowRun(runId) {
|
|
166
|
-
const { GH_OWNER, GH_REPO } = process.env;
|
|
167
|
-
const res = await fetch(
|
|
168
|
-
`https://api.github.com/repos/${GH_OWNER}/${GH_REPO}/actions/runs/${runId}/cancel`,
|
|
169
|
-
{
|
|
170
|
-
method: 'POST',
|
|
171
|
-
headers: {
|
|
172
|
-
'Authorization': `Bearer ${process.env.GH_TOKEN}`,
|
|
173
|
-
'Accept': 'application/vnd.github+json',
|
|
174
|
-
'X-GitHub-Api-Version': '2022-11-28',
|
|
175
|
-
},
|
|
176
|
-
}
|
|
177
|
-
);
|
|
178
|
-
if (!res.ok && res.status !== 202) {
|
|
179
|
-
const error = await res.text();
|
|
180
|
-
throw new Error(`GitHub API error: ${res.status} ${error}`);
|
|
181
|
-
}
|
|
182
|
-
return { success: true };
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Re-run a workflow run (all jobs or failed only)
|
|
187
|
-
* @param {number} runId - Workflow run ID
|
|
188
|
-
* @param {boolean} [failedOnly=false] - Only rerun failed jobs
|
|
189
|
-
*/
|
|
190
|
-
async function rerunWorkflowRun(runId, failedOnly = false) {
|
|
191
|
-
const { GH_OWNER, GH_REPO } = process.env;
|
|
192
|
-
const endpoint = failedOnly
|
|
193
|
-
? `https://api.github.com/repos/${GH_OWNER}/${GH_REPO}/actions/runs/${runId}/rerun-failed-jobs`
|
|
194
|
-
: `https://api.github.com/repos/${GH_OWNER}/${GH_REPO}/actions/runs/${runId}/rerun`;
|
|
195
|
-
const res = await fetch(endpoint, {
|
|
196
|
-
method: 'POST',
|
|
197
|
-
headers: {
|
|
198
|
-
'Authorization': `Bearer ${process.env.GH_TOKEN}`,
|
|
199
|
-
'Accept': 'application/vnd.github+json',
|
|
200
|
-
'X-GitHub-Api-Version': '2022-11-28',
|
|
201
|
-
},
|
|
202
|
-
});
|
|
203
|
-
if (!res.ok && res.status !== 201) {
|
|
204
|
-
const error = await res.text();
|
|
205
|
-
throw new Error(`GitHub API error: ${res.status} ${error}`);
|
|
206
|
-
}
|
|
207
|
-
return { success: true };
|
|
208
|
-
}
|
|
209
|
-
|
|
210
161
|
/**
|
|
211
162
|
* Trigger a workflow via workflow_dispatch
|
|
212
163
|
* @param {string} workflowId - Workflow file name (e.g., 'upgrade-event-handler.yml')
|
|
@@ -241,7 +192,5 @@ export {
|
|
|
241
192
|
getWorkflowRunJobs,
|
|
242
193
|
getJobStatus,
|
|
243
194
|
getSwarmStatus,
|
|
244
|
-
cancelWorkflowRun,
|
|
245
|
-
rerunWorkflowRun,
|
|
246
195
|
triggerWorkflowDispatch,
|
|
247
196
|
};
|
package/package.json
CHANGED
|
@@ -12,38 +12,104 @@ jobs:
|
|
|
12
12
|
deploy:
|
|
13
13
|
runs-on: self-hosted
|
|
14
14
|
steps:
|
|
15
|
-
- name:
|
|
15
|
+
- name: Pull latest and detect version change
|
|
16
|
+
id: pull
|
|
16
17
|
run: |
|
|
17
18
|
docker exec thepopebot-event-handler bash -c '
|
|
18
|
-
# Load GH_TOKEN and authenticate git via GitHub CLI
|
|
19
19
|
export GH_TOKEN=$(grep "^GH_TOKEN=" /app/.env | cut -d= -f2-)
|
|
20
20
|
echo "${GH_TOKEN}" | gh auth login --with-token
|
|
21
21
|
gh auth setup-git
|
|
22
22
|
|
|
23
|
-
# Check if there are code changes (not just logs)
|
|
24
23
|
git fetch origin main
|
|
25
24
|
CHANGED=$(git diff --name-only HEAD origin/main)
|
|
26
25
|
if ! echo "$CHANGED" | grep -qv "^logs/"; then
|
|
27
|
-
echo "
|
|
26
|
+
echo "SKIP" > /app/.rebuild-status
|
|
28
27
|
git reset --hard origin/main
|
|
29
28
|
exit 0
|
|
30
29
|
fi
|
|
31
30
|
|
|
32
|
-
#
|
|
31
|
+
# Detect thepopebot version change from package-lock.json in git
|
|
32
|
+
git show HEAD:package-lock.json > /tmp/old-lock.json 2>/dev/null || echo "{}" > /tmp/old-lock.json
|
|
33
|
+
git show origin/main:package-lock.json > /tmp/new-lock.json
|
|
34
|
+
OLD_TPB=$(node -p "try{require(\"/tmp/old-lock.json\").packages[\"node_modules/thepopebot\"]?.version||\"\"}catch(e){\"\"}")
|
|
35
|
+
NEW_TPB=$(node -p "try{require(\"/tmp/new-lock.json\").packages[\"node_modules/thepopebot\"]?.version||\"\"}catch(e){\"\"}")
|
|
36
|
+
rm -f /tmp/old-lock.json /tmp/new-lock.json
|
|
37
|
+
|
|
33
38
|
git reset --hard origin/main
|
|
34
|
-
npm install --omit=dev
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
if [ -n "$OLD_TPB" ] && [ "$OLD_TPB" != "$NEW_TPB" ]; then
|
|
41
|
+
# Version changed — run thepopebot init to scaffold new templates
|
|
42
|
+
npx thepopebot init
|
|
43
|
+
npm install --omit=dev
|
|
44
|
+
|
|
45
|
+
# Commit any template changes from init
|
|
46
|
+
git add -A
|
|
47
|
+
if ! git diff --cached --quiet; then
|
|
48
|
+
git commit -m "chore: apply thepopebot init after upgrade"
|
|
49
|
+
git push origin main
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
# Update THEPOPEBOT_VERSION in .env so docker compose pulls the right image
|
|
53
|
+
if grep -q "^THEPOPEBOT_VERSION=" /app/.env; then
|
|
54
|
+
sed -i "s/^THEPOPEBOT_VERSION=.*/THEPOPEBOT_VERSION=$NEW_TPB/" /app/.env
|
|
55
|
+
else
|
|
56
|
+
echo "THEPOPEBOT_VERSION=$NEW_TPB" >> /app/.env
|
|
57
|
+
fi
|
|
58
|
+
echo "VERSION_CHANGED" > /app/.rebuild-status
|
|
59
|
+
else
|
|
60
|
+
npm install --omit=dev
|
|
61
|
+
echo "REBUILD" > /app/.rebuild-status
|
|
62
|
+
fi
|
|
63
|
+
'
|
|
64
|
+
|
|
65
|
+
STATUS=$(docker exec thepopebot-event-handler cat /app/.rebuild-status)
|
|
66
|
+
docker exec thepopebot-event-handler rm -f /app/.rebuild-status
|
|
67
|
+
echo "status=$STATUS" >> $GITHUB_OUTPUT
|
|
68
|
+
|
|
69
|
+
- name: Rebuild (no version change)
|
|
70
|
+
if: steps.pull.outputs.status == 'REBUILD'
|
|
71
|
+
run: |
|
|
72
|
+
docker exec thepopebot-event-handler bash -c '
|
|
37
73
|
rm -rf .next-new .next-old
|
|
38
74
|
NEXT_BUILD_DIR=.next-new npm run build
|
|
39
75
|
|
|
40
|
-
# Atomic swap: old .next keeps serving until pm2 reload
|
|
41
76
|
mv .next .next-old 2>/dev/null || true
|
|
42
77
|
mv .next-new .next
|
|
43
78
|
|
|
44
79
|
echo "Rebuild complete, reloading Next.js..."
|
|
45
80
|
npx pm2 reload all
|
|
46
81
|
|
|
47
|
-
|
|
82
|
+
rm -rf .next-old
|
|
83
|
+
'
|
|
84
|
+
|
|
85
|
+
- name: Pull new image and restart container
|
|
86
|
+
if: steps.pull.outputs.status == 'VERSION_CHANGED'
|
|
87
|
+
run: |
|
|
88
|
+
cd /project
|
|
89
|
+
docker compose pull event-handler
|
|
90
|
+
docker compose up -d event-handler
|
|
91
|
+
|
|
92
|
+
- name: Rebuild in new container
|
|
93
|
+
if: steps.pull.outputs.status == 'VERSION_CHANGED'
|
|
94
|
+
run: |
|
|
95
|
+
echo "Waiting for new container..."
|
|
96
|
+
for i in $(seq 1 30); do
|
|
97
|
+
if docker exec thepopebot-event-handler echo "ready" 2>/dev/null; then
|
|
98
|
+
break
|
|
99
|
+
fi
|
|
100
|
+
sleep 2
|
|
101
|
+
done
|
|
102
|
+
|
|
103
|
+
docker exec thepopebot-event-handler bash -c '
|
|
104
|
+
npm install --omit=dev
|
|
105
|
+
|
|
106
|
+
rm -rf .next-new .next-old
|
|
107
|
+
NEXT_BUILD_DIR=.next-new npm run build
|
|
108
|
+
|
|
109
|
+
mv .next .next-old 2>/dev/null || true
|
|
110
|
+
mv .next-new .next
|
|
111
|
+
|
|
112
|
+
npx pm2 reload all
|
|
113
|
+
|
|
48
114
|
rm -rf .next-old
|
|
49
115
|
'
|
|
@@ -13,32 +13,31 @@ jobs:
|
|
|
13
13
|
steps:
|
|
14
14
|
- name: Upgrade thepopebot
|
|
15
15
|
run: |
|
|
16
|
-
# Phase 1: Update package and build (but don't swap yet)
|
|
17
16
|
docker exec thepopebot-event-handler bash -c '
|
|
18
17
|
export GH_TOKEN=$(grep "^GH_TOKEN=" /app/.env | cut -d= -f2-)
|
|
19
18
|
echo "${GH_TOKEN}" | gh auth login --with-token
|
|
20
19
|
gh auth setup-git
|
|
21
20
|
|
|
22
|
-
git
|
|
23
|
-
|
|
21
|
+
REPO_URL=$(git -C /app remote get-url origin)
|
|
22
|
+
WORK_DIR=$(mktemp -d)
|
|
23
|
+
git clone --depth 1 "$REPO_URL" "$WORK_DIR"
|
|
24
|
+
cd "$WORK_DIR"
|
|
24
25
|
|
|
26
|
+
npm install
|
|
25
27
|
npm update thepopebot
|
|
26
|
-
npx thepopebot init
|
|
27
|
-
npm install --omit=dev
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
rm -rf .next-old
|
|
29
|
+
git add -A
|
|
30
|
+
if ! git diff --cached --quiet; then
|
|
31
|
+
VERSION=$(node -p "require('./node_modules/thepopebot/package.json').version")
|
|
32
|
+
BRANCH="upgrade/thepopebot-${VERSION}-$(date +%s)"
|
|
33
|
+
git checkout -b "$BRANCH"
|
|
34
|
+
git commit -m "chore: upgrade thepopebot"
|
|
35
|
+
git push origin "$BRANCH"
|
|
36
|
+
gh pr create --title "chore: upgrade thepopebot" --body "Automated upgrade via upgrade-event-handler workflow." --base main --head "$BRANCH"
|
|
37
|
+
gh pr merge "$BRANCH" --squash --auto --delete-branch
|
|
38
|
+
else
|
|
39
|
+
echo "No changes — thepopebot is already up to date."
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
rm -rf "$WORK_DIR"
|
|
44
43
|
'
|