project-auto-wizard 0.15.0 → 0.16.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.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +2 -2
- package/README.zh-CN.md +1 -1
- package/package.json +1 -1
- package/payload/config/breaking-changes.json +31 -5
- package/payload/config/wizard-prompts.yml +0 -4
- package/payload/scripts/messages.py +162 -26
- package/payload/scripts/version_manager.py +69 -40
- package/payload/version.yml.template +6 -2
- package/payload/workflows/common/PROJECT-COMMON-AI-PR-SUMMARY.yaml +3 -0
- package/payload/workflows/common/PROJECT-COMMON-AUTO-CHANGELOG-CONTROL.yaml +64 -1
- package/payload/workflows/common/PROJECT-COMMON-README-VERSION-UPDATE.yaml +61 -12
- package/payload/workflows/common/PROJECT-COMMON-RELEASE-PUBLISH.yaml +46 -10
- package/payload/workflows/common/PROJECT-COMMON-VERSION-CONTROL.yaml +40 -11
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-FIREBASE-CICD.yaml +24 -8
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-PLAYSTORE-CICD.yaml +29 -10
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-SELFHOSTED-CICD.yaml +57 -23
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-TEST-APK.yaml +155 -72
- package/payload/workflows/flutter/PROJECT-FLUTTER-APP-BUILD-TRIGGER.yaml +49 -20
- package/payload/workflows/flutter/PROJECT-FLUTTER-CI.yaml +162 -62
- package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml +184 -87
- package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TESTFLIGHT.yaml +38 -15
- package/payload/workflows/go/PROJECT-GO-CI.yaml +14 -5
- package/payload/workflows/go/PROJECT-GO-PR-PREVIEW.yaml +375 -120
- package/payload/workflows/go/PROJECT-GO-SIMPLE-CICD.yaml +9 -4
- package/payload/workflows/python/PROJECT-PYTHON-CI.yaml +12 -4
- package/payload/workflows/python/PROJECT-PYTHON-PR-PREVIEW.yaml +375 -120
- package/payload/workflows/python/PROJECT-PYTHON-SIMPLE-CICD.yaml +9 -4
- package/payload/workflows/react/PROJECT-REACT-CI.yaml +38 -9
- package/payload/workflows/react/PROJECT-REACT-CICD.yaml +19 -5
- package/payload/workflows/spring/PROJECT-SPRING-CI.yml +71 -35
- package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-NGINX-CICD.yaml +9 -6
- package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-TRAEFIK-CICD.yaml +7 -4
- package/payload/workflows/spring/server-deploy/PROJECT-SPRING-PR-PREVIEW.yaml +425 -144
- package/payload/workflows/spring/server-deploy/PROJECT-SPRING-SIMPLE-CICD.yaml +7 -4
- package/src/cli/args.js +32 -22
- package/src/commands/doctor.js +20 -0
- package/src/commands/dry-run.js +9 -1
- package/src/commands/full.js +9 -4
- package/src/commands/interactive.js +29 -30
- package/src/commands/status.js +19 -5
- package/src/context.js +4 -2
- package/src/core/copy/simple.js +31 -0
- package/src/core/copy/workflows.js +2 -2
- package/src/core/deploy-style.js +1 -1
- package/src/core/detect.js +3 -2
- package/src/core/options.js +88 -0
- package/src/core/release-options.js +6 -23
- package/src/core/types.js +15 -8
- package/src/core/version-yml.js +68 -26
- package/src/i18n/catalog/en/cli.js +3 -1
- package/src/i18n/catalog/en/commands.js +15 -0
- package/src/i18n/catalog/en/core2.js +3 -0
- package/src/i18n/catalog/en/ui.js +1 -0
- package/src/i18n/catalog/ko/cli.js +3 -1
- package/src/i18n/catalog/ko/commands.js +15 -0
- package/src/i18n/catalog/ko/core2.js +3 -0
- package/src/i18n/catalog/ko/ui.js +1 -0
- package/src/index.js +7 -3
- package/src/ui/env-plan.js +1 -1
- package/src/ui/prompts.js +9 -5
- package/src/ui/status-cards.js +2 -2
- package/payload/workflows/next/PROJECT-NEXT-CI.yaml +0 -241
- package/payload/workflows/next/PROJECT-NEXT-CICD.yaml +0 -330
|
@@ -86,6 +86,7 @@ jobs:
|
|
|
86
86
|
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
87
87
|
DOCKERFILE: Dockerfile
|
|
88
88
|
run: |
|
|
89
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
89
90
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
90
91
|
MISSING=""
|
|
91
92
|
for NAME in DOCKERHUB_USERNAME DOCKERHUB_TOKEN SERVER_HOST SERVER_USER; do
|
|
@@ -113,6 +114,7 @@ jobs:
|
|
|
113
114
|
|
|
114
115
|
- name: Free up disk space
|
|
115
116
|
run: |
|
|
117
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
116
118
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
117
119
|
m cicd.disk_before
|
|
118
120
|
df -h
|
|
@@ -132,6 +134,7 @@ jobs:
|
|
|
132
134
|
- name: Create .env file
|
|
133
135
|
working-directory: ${{ env.PROJECT_PATH }}
|
|
134
136
|
run: |
|
|
137
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
135
138
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
136
139
|
cat > .env << 'EOF'
|
|
137
140
|
${{ secrets.ENV_FILE }}
|
|
@@ -139,16 +142,16 @@ jobs:
|
|
|
139
142
|
m cicd.dotenv_created
|
|
140
143
|
|
|
141
144
|
- name: Set up Docker Buildx
|
|
142
|
-
uses: docker/setup-buildx-action@
|
|
145
|
+
uses: docker/setup-buildx-action@v4
|
|
143
146
|
|
|
144
147
|
- name: Log in to DockerHub
|
|
145
|
-
uses: docker/login-action@
|
|
148
|
+
uses: docker/login-action@v4
|
|
146
149
|
with:
|
|
147
150
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
148
151
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
149
152
|
|
|
150
153
|
- name: Build and push Docker image
|
|
151
|
-
uses: docker/build-push-action@
|
|
154
|
+
uses: docker/build-push-action@v7
|
|
152
155
|
with:
|
|
153
156
|
context: ${{ env.PROJECT_PATH }}
|
|
154
157
|
file: ${{ env.PROJECT_PATH }}/Dockerfile
|
|
@@ -161,6 +164,7 @@ jobs:
|
|
|
161
164
|
- name: Clean up after build
|
|
162
165
|
if: always()
|
|
163
166
|
run: |
|
|
167
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
164
168
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
165
169
|
m cicd.post_build_cleanup
|
|
166
170
|
docker system prune -f || true
|
|
@@ -186,6 +190,7 @@ jobs:
|
|
|
186
190
|
|
|
187
191
|
- name: Load messages
|
|
188
192
|
run: |
|
|
193
|
+
[ -f .github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
189
194
|
python3 .github/scripts/messages.py dump cicd. | PYTHONIOENCODING=utf-8 python3 -c 'import json,sys; [print("PAW_M_" + k.replace(".", "_") + "=" + v) for k, v in json.load(sys.stdin).items()]' >> "$GITHUB_ENV"
|
|
190
195
|
|
|
191
196
|
- name: Deploy
|
|
@@ -364,6 +369,6 @@ jobs:
|
|
|
364
369
|
m "${{ env.PAW_M_cicd_summary_branch }}" branch="$BRANCH"
|
|
365
370
|
m "${{ env.PAW_M_cicd_summary_container }}" container="$CONTAINER_NAME"
|
|
366
371
|
m "${{ env.PAW_M_cicd_summary_port }}" port="$PORT"
|
|
367
|
-
m "${{ env.PAW_M_cicd_summary_time }}" time="$(date '+%Y-%m-%d %H:%M:%S')"
|
|
372
|
+
m "${{ env.PAW_M_cicd_summary_time }}" time="$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
|
368
373
|
echo ""
|
|
369
374
|
m "${{ env.PAW_M_cicd_summary_url }}" url="http://${{ secrets.SERVER_HOST }}:${PORT}/docs"
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# project-auto-wizard:managed-workflow
|
|
2
|
-
# React CI (build verification)
|
|
2
|
+
# React / Next.js CI (build verification)
|
|
3
3
|
# On push/PR to the {{DEVELOP_BRANCH}} branch, verifies with npm ci, npm test (when a test script exists) and npm run build. Caches node_modules and the build output.
|
|
4
4
|
#
|
|
5
5
|
# GitHub Secrets
|
|
@@ -73,6 +73,7 @@ jobs:
|
|
|
73
73
|
|
|
74
74
|
- name: Create environment file (${{ env.ENV_FILE }})
|
|
75
75
|
run: |
|
|
76
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
76
77
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
77
78
|
echo -e "${{ secrets.ENV_FILE || secrets.ENV }}" > ${{ env.ENV_FILE }}
|
|
78
79
|
m cicd.env_file_created file="${{ env.ENV_FILE }}"
|
|
@@ -106,6 +107,7 @@ jobs:
|
|
|
106
107
|
- name: Install dependencies
|
|
107
108
|
if: steps.node-modules-cache.outputs.cache-hit != 'true'
|
|
108
109
|
run: |
|
|
110
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
109
111
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
110
112
|
m cibuild.node_deps_installing
|
|
111
113
|
npm ci
|
|
@@ -125,6 +127,7 @@ jobs:
|
|
|
125
127
|
# Runs only when package.json has a test script (the npm init default "no test specified" counts as none)
|
|
126
128
|
- name: Run tests
|
|
127
129
|
run: |
|
|
130
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
128
131
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
129
132
|
TEST_SCRIPT=$(node -p "(require('./package.json').scripts || {}).test || ''")
|
|
130
133
|
if [ -z "$TEST_SCRIPT" ] || echo "$TEST_SCRIPT" | grep -q "no test specified"; then
|
|
@@ -139,6 +142,7 @@ jobs:
|
|
|
139
142
|
- name: Build project
|
|
140
143
|
id: build
|
|
141
144
|
run: |
|
|
145
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
142
146
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
143
147
|
m cibuild.node_build_start
|
|
144
148
|
m cibuild.node_build_project project="${{ env.PROJECT_NAME }}"
|
|
@@ -159,10 +163,19 @@ jobs:
|
|
|
159
163
|
echo "status=success" >> $GITHUB_OUTPUT
|
|
160
164
|
m cibuild.node_build_ok
|
|
161
165
|
|
|
166
|
+
# Only Next.js builds create .next; other React builds skip this block
|
|
167
|
+
if [ -d ".next" ]; then
|
|
168
|
+
echo ""
|
|
169
|
+
m cibuild.node_build_output
|
|
170
|
+
m cibuild.node_build_next_dir
|
|
171
|
+
du -sh .next/ || true
|
|
172
|
+
fi
|
|
173
|
+
|
|
162
174
|
# Runs only when the build failed
|
|
163
175
|
- name: Print build error log
|
|
164
176
|
if: steps.build.outputs.build_failed == 'true'
|
|
165
177
|
run: |
|
|
178
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
166
179
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
167
180
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
168
181
|
m cibuild.node_errlog_title
|
|
@@ -182,9 +195,9 @@ jobs:
|
|
|
182
195
|
# End the workflow because the build failed
|
|
183
196
|
exit 1
|
|
184
197
|
|
|
185
|
-
# Save the log regardless of build success or failure
|
|
198
|
+
# Save the log regardless of build success or failure (nothing to upload when the build step did not run, e.g. tests failed)
|
|
186
199
|
- name: Upload build log
|
|
187
|
-
if: always()
|
|
200
|
+
if: ${{ always() && steps.build.outcome != 'skipped' }}
|
|
188
201
|
uses: actions/upload-artifact@v7
|
|
189
202
|
with:
|
|
190
203
|
name: build-log
|
|
@@ -194,11 +207,17 @@ jobs:
|
|
|
194
207
|
# Summarize the workflow result for readability
|
|
195
208
|
- name: Build result summary
|
|
196
209
|
if: always()
|
|
210
|
+
# Values go through env (not inlined into the script). On a PR, github.head_ref is the PR branch (ref_name would be '<n>/merge')
|
|
211
|
+
env:
|
|
212
|
+
BUILD_STATUS: ${{ steps.build.outputs.status }}
|
|
213
|
+
BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
|
|
214
|
+
COMMIT_SHA: ${{ github.sha }}
|
|
197
215
|
run: |
|
|
216
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
198
217
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
199
218
|
echo ""
|
|
200
219
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
201
|
-
if [ "$
|
|
220
|
+
if [ "$BUILD_STATUS" = "success" ]; then
|
|
202
221
|
m cibuild.node_result_ok
|
|
203
222
|
else
|
|
204
223
|
m cibuild.node_result_fail
|
|
@@ -208,16 +227,25 @@ jobs:
|
|
|
208
227
|
m cibuild.node_result_title
|
|
209
228
|
m cibuild.node_result_project project="${{ env.PROJECT_NAME }}"
|
|
210
229
|
m cibuild.node_result_node node="${{ env.NODE_VERSION }}"
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
230
|
+
# An empty status means the build step never ran (an earlier step such as the tests failed)
|
|
231
|
+
if [ -z "$BUILD_STATUS" ]; then
|
|
232
|
+
m cibuild.node_result_status_not_run
|
|
233
|
+
else
|
|
234
|
+
m cibuild.node_result_status status="$BUILD_STATUS"
|
|
235
|
+
fi
|
|
236
|
+
m cibuild.node_result_branch branch="$BRANCH_NAME"
|
|
237
|
+
m cibuild.node_result_commit sha="$COMMIT_SHA"
|
|
238
|
+
m cibuild.node_result_time time="$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
|
215
239
|
echo ""
|
|
216
240
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
217
241
|
echo ""
|
|
218
242
|
|
|
219
|
-
if [ "$
|
|
243
|
+
if [ "$BUILD_STATUS" = "success" ]; then
|
|
220
244
|
m cibuild.node_all_ok
|
|
245
|
+
elif [ -z "$BUILD_STATUS" ]; then
|
|
246
|
+
# The build log artifact does not exist in this case, so do not point to it
|
|
247
|
+
m cibuild.node_build_not_run
|
|
248
|
+
m cibuild.node_build_not_run_hint
|
|
221
249
|
else
|
|
222
250
|
m cibuild.node_error_occurred
|
|
223
251
|
m cibuild.node_log_hint
|
|
@@ -243,6 +271,7 @@ jobs:
|
|
|
243
271
|
env:
|
|
244
272
|
RESULTS: ${{ toJSON(needs.*.result) }}
|
|
245
273
|
run: |
|
|
274
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
246
275
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
247
276
|
m cibuild.gate_results results="$RESULTS"
|
|
248
277
|
if echo "$RESULTS" | grep -Eq '"(failure|cancelled)"'; then
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# project-auto-wizard:managed-workflow
|
|
2
|
-
# React CI/CD deployment
|
|
2
|
+
# React / Next.js CI/CD deployment
|
|
3
3
|
# Builds a Docker image and deploys it when the {{MAIN_BRANCH}} branch is pushed.
|
|
4
4
|
#
|
|
5
5
|
# GitHub Secrets
|
|
@@ -68,6 +68,7 @@ jobs:
|
|
|
68
68
|
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
69
69
|
DOCKERFILE: Dockerfile
|
|
70
70
|
run: |
|
|
71
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
71
72
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
72
73
|
MISSING=""
|
|
73
74
|
for NAME in DOCKERHUB_USERNAME DOCKERHUB_TOKEN SERVER_HOST SERVER_USER; do
|
|
@@ -102,6 +103,7 @@ jobs:
|
|
|
102
103
|
|
|
103
104
|
- name: Create environment file (${{ env.ENV_FILE_NAME }})
|
|
104
105
|
run: |
|
|
106
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
105
107
|
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
106
108
|
cat << 'EOF' > ./${{ env.ENV_FILE_NAME }}
|
|
107
109
|
${{ secrets.ENV_FILE || secrets.ENV }}
|
|
@@ -142,10 +144,10 @@ jobs:
|
|
|
142
144
|
run: npm run build
|
|
143
145
|
|
|
144
146
|
- name: Set up Docker Buildx
|
|
145
|
-
uses: docker/setup-buildx-action@
|
|
147
|
+
uses: docker/setup-buildx-action@v4
|
|
146
148
|
|
|
147
149
|
- name: Log in to DockerHub
|
|
148
|
-
uses: docker/login-action@
|
|
150
|
+
uses: docker/login-action@v4
|
|
149
151
|
with:
|
|
150
152
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
151
153
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
@@ -159,7 +161,7 @@ jobs:
|
|
|
159
161
|
${{ runner.os }}-buildx-
|
|
160
162
|
|
|
161
163
|
- name: Build and push Docker image
|
|
162
|
-
uses: docker/build-push-action@
|
|
164
|
+
uses: docker/build-push-action@v7
|
|
163
165
|
with:
|
|
164
166
|
context: ${{ env.PROJECT_PATH }}
|
|
165
167
|
file: ${{ env.PROJECT_PATH }}/Dockerfile
|
|
@@ -191,6 +193,7 @@ jobs:
|
|
|
191
193
|
|
|
192
194
|
- name: Load messages
|
|
193
195
|
run: |
|
|
196
|
+
[ -f .github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
194
197
|
python3 .github/scripts/messages.py dump cicd. | PYTHONIOENCODING=utf-8 python3 -c 'import json,sys; [print("PAW_M_" + k.replace(".", "_") + "=" + v) for k, v in json.load(sys.stdin).items()]' >> "$GITHUB_ENV"
|
|
195
198
|
|
|
196
199
|
- name: Deploy
|
|
@@ -280,14 +283,25 @@ jobs:
|
|
|
280
283
|
m "${{ env.PAW_M_cicd_container_none }}" container="$CONTAINER_NAME"
|
|
281
284
|
fi
|
|
282
285
|
|
|
286
|
+
# Next.js projects used to deploy as <project>-nextjs[-deploy]. Those containers keep the same host port
|
|
287
|
+
# (--restart unless-stopped), so remove them before starting the new one. No-op when they do not exist.
|
|
288
|
+
for LEGACY_NAME in "${PROJECT_NAME}-nextjs-deploy" "${PROJECT_NAME}-nextjs"; do
|
|
289
|
+
if [ "$LEGACY_NAME" != "$CONTAINER_NAME" ]; then
|
|
290
|
+
SUDO docker rm -f "$LEGACY_NAME" >/dev/null 2>&1 || true
|
|
291
|
+
fi
|
|
292
|
+
done
|
|
293
|
+
|
|
283
294
|
# Start the new container
|
|
284
295
|
m "${{ env.PAW_M_cicd_container_run }}" container="$CONTAINER_NAME"
|
|
285
296
|
|
|
297
|
+
# NODE_ENV=production: Next.js (SSR) and most React servers expect it at runtime
|
|
286
298
|
SUDO docker run -d \
|
|
287
299
|
-p ${PORT}:3000 \
|
|
288
300
|
--name $CONTAINER_NAME \
|
|
289
301
|
-e TZ=Asia/Seoul \
|
|
302
|
+
-e NODE_ENV=production \
|
|
290
303
|
-v /etc/localtime:/etc/localtime:ro \
|
|
304
|
+
--restart unless-stopped \
|
|
291
305
|
${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}-${{ env.DOCKER_IMAGE_PREFIX }}:${BRANCH}
|
|
292
306
|
|
|
293
307
|
# Confirm the deployment
|
|
@@ -298,7 +312,7 @@ jobs:
|
|
|
298
312
|
m "${{ env.PAW_M_cicd_summary_branch }}" branch="$BRANCH"
|
|
299
313
|
m "${{ env.PAW_M_cicd_summary_container }}" container="$CONTAINER_NAME"
|
|
300
314
|
m "${{ env.PAW_M_cicd_summary_port }}" port="$PORT"
|
|
301
|
-
m "${{ env.PAW_M_cicd_summary_time }}" time="$(date '+%Y-%m-%d %H:%M:%S')"
|
|
315
|
+
m "${{ env.PAW_M_cicd_summary_time }}" time="$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
|
|
302
316
|
echo ""
|
|
303
317
|
m "${{ env.PAW_M_cicd_summary_url }}" url="http://${{ secrets.SERVER_HOST }}:${PORT}"
|
|
304
318
|
|
|
@@ -65,7 +65,10 @@ jobs:
|
|
|
65
65
|
fetch-depth: 0
|
|
66
66
|
|
|
67
67
|
- name: Load messages
|
|
68
|
-
|
|
68
|
+
id: load_messages
|
|
69
|
+
run: |
|
|
70
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
71
|
+
echo "PAW_MSG=$(python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" dump wf_spring_ci.)" >> "$GITHUB_ENV"
|
|
69
72
|
|
|
70
73
|
- name: Setup JDK
|
|
71
74
|
uses: actions/setup-java@v5
|
|
@@ -74,11 +77,11 @@ jobs:
|
|
|
74
77
|
distribution: 'temurin'
|
|
75
78
|
|
|
76
79
|
- name: Validate Gradle Wrapper
|
|
77
|
-
uses: gradle/wrapper-validation
|
|
80
|
+
uses: gradle/actions/wrapper-validation@v5
|
|
78
81
|
continue-on-error: true
|
|
79
82
|
|
|
80
83
|
- name: Setup Gradle
|
|
81
|
-
uses: gradle/actions/setup-gradle@
|
|
84
|
+
uses: gradle/actions/setup-gradle@v5
|
|
82
85
|
with:
|
|
83
86
|
gradle-version: wrapper
|
|
84
87
|
|
|
@@ -117,27 +120,38 @@ jobs:
|
|
|
117
120
|
|
|
118
121
|
- name: Generate Build Report
|
|
119
122
|
id: report
|
|
120
|
-
if: always()
|
|
123
|
+
if: always() && steps.load_messages.outcome == 'success'
|
|
121
124
|
run: |
|
|
125
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
122
126
|
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
123
127
|
STATUS_OK="$(m wf_spring_ci.status_ok)"
|
|
124
128
|
STATUS_FAIL="$(m wf_spring_ci.status_fail)"
|
|
129
|
+
STATUS_NOT_RUN="$(m wf_spring_ci.status_not_run)"
|
|
125
130
|
COMPILE_STATUS="$STATUS_OK"
|
|
126
131
|
TEST_STATUS="$STATUS_OK"
|
|
127
132
|
BUILD_STATUS="$STATUS_OK"
|
|
128
133
|
|
|
129
134
|
COMPILE_EXIT_CODE="${{ steps.compile.outputs.compile_exit_code }}"
|
|
130
|
-
|
|
135
|
+
TEST_EXIT_CODE="${{ steps.test.outputs.test_exit_code }}"
|
|
136
|
+
BUILD_EXIT_CODE="${{ steps.build.outputs.build_exit_code }}"
|
|
137
|
+
|
|
138
|
+
# An empty exit code means the step never ran; a failed compile means gradle never got to run the tests
|
|
139
|
+
# or package the jar, so their non-zero exit codes are not failures of those steps themselves
|
|
140
|
+
if [ -z "$COMPILE_EXIT_CODE" ]; then
|
|
141
|
+
COMPILE_STATUS="$STATUS_NOT_RUN"
|
|
142
|
+
elif [ "$COMPILE_EXIT_CODE" != "0" ]; then
|
|
131
143
|
COMPILE_STATUS="$STATUS_FAIL"
|
|
132
144
|
fi
|
|
133
|
-
|
|
134
|
-
TEST_EXIT_CODE
|
|
135
|
-
|
|
145
|
+
|
|
146
|
+
if [ -z "$TEST_EXIT_CODE" ] || { [ -n "$COMPILE_EXIT_CODE" ] && [ "$COMPILE_EXIT_CODE" != "0" ]; }; then
|
|
147
|
+
TEST_STATUS="$STATUS_NOT_RUN"
|
|
148
|
+
elif [ "$TEST_EXIT_CODE" != "0" ]; then
|
|
136
149
|
TEST_STATUS="$STATUS_FAIL"
|
|
137
150
|
fi
|
|
138
|
-
|
|
139
|
-
BUILD_EXIT_CODE
|
|
140
|
-
|
|
151
|
+
|
|
152
|
+
if [ -z "$BUILD_EXIT_CODE" ] || { [ -n "$COMPILE_EXIT_CODE" ] && [ "$COMPILE_EXIT_CODE" != "0" ]; }; then
|
|
153
|
+
BUILD_STATUS="$STATUS_NOT_RUN"
|
|
154
|
+
elif [ "$BUILD_EXIT_CODE" != "0" ]; then
|
|
141
155
|
BUILD_STATUS="$STATUS_FAIL"
|
|
142
156
|
fi
|
|
143
157
|
|
|
@@ -157,8 +171,9 @@ jobs:
|
|
|
157
171
|
|
|
158
172
|
- name: Extract Error Details
|
|
159
173
|
id: errors
|
|
160
|
-
if: always()
|
|
174
|
+
if: always() && steps.load_messages.outcome == 'success'
|
|
161
175
|
run: |
|
|
176
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
162
177
|
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
163
178
|
if [ -f compile_output.txt ] && [ "${{ steps.compile.outputs.compile_exit_code }}" != "0" ]; then
|
|
164
179
|
echo "compile_errors<<EOF" >> $GITHUB_OUTPUT
|
|
@@ -170,7 +185,7 @@ jobs:
|
|
|
170
185
|
echo "EOF" >> $GITHUB_OUTPUT
|
|
171
186
|
fi
|
|
172
187
|
|
|
173
|
-
if [ -f test_output.txt ] && [ "${{ steps.test.outputs.test_exit_code }}" != "0" ]; then
|
|
188
|
+
if [ -f test_output.txt ] && [ "${{ steps.test.outputs.test_exit_code }}" != "0" ] && [ "${{ steps.compile.outputs.compile_exit_code }}" = "0" ]; then
|
|
174
189
|
echo "test_errors<<EOF" >> $GITHUB_OUTPUT
|
|
175
190
|
m wf_spring_ci.err_test_header >> $GITHUB_OUTPUT
|
|
176
191
|
echo "" >> $GITHUB_OUTPUT
|
|
@@ -180,7 +195,7 @@ jobs:
|
|
|
180
195
|
echo "EOF" >> $GITHUB_OUTPUT
|
|
181
196
|
fi
|
|
182
197
|
|
|
183
|
-
if [ -f build_output.txt ] && [ "${{ steps.build.outputs.build_exit_code }}" != "0" ]; then
|
|
198
|
+
if [ -f build_output.txt ] && [ "${{ steps.build.outputs.build_exit_code }}" != "0" ] && [ "${{ steps.compile.outputs.compile_exit_code }}" = "0" ]; then
|
|
184
199
|
echo "build_errors<<EOF" >> $GITHUB_OUTPUT
|
|
185
200
|
m wf_spring_ci.err_build_header >> $GITHUB_OUTPUT
|
|
186
201
|
echo "" >> $GITHUB_OUTPUT
|
|
@@ -193,6 +208,11 @@ jobs:
|
|
|
193
208
|
- name: Comment on PR (Success)
|
|
194
209
|
if: github.event_name == 'pull_request' && steps.report.outputs.overall_ok == 'true'
|
|
195
210
|
uses: actions/github-script@v9
|
|
211
|
+
env:
|
|
212
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_BUILD_STATUS: ${{ steps.report.outputs.build_status }}
|
|
213
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_COMPILE_STATUS: ${{ steps.report.outputs.compile_status }}
|
|
214
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_OVERALL_STATUS: ${{ steps.report.outputs.overall_status }}
|
|
215
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_TEST_STATUS: ${{ steps.report.outputs.test_status }}
|
|
196
216
|
with:
|
|
197
217
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
198
218
|
script: |
|
|
@@ -217,14 +237,14 @@ jobs:
|
|
|
217
237
|
'',
|
|
218
238
|
m('table_header'),
|
|
219
239
|
'|------|------|',
|
|
220
|
-
m('row_compile', { status:
|
|
221
|
-
m('row_test', { status:
|
|
222
|
-
m('row_build', { status:
|
|
240
|
+
m('row_compile', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_COMPILE_STATUS }),
|
|
241
|
+
m('row_test', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_TEST_STATUS }),
|
|
242
|
+
m('row_build', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_BUILD_STATUS }),
|
|
223
243
|
'',
|
|
224
|
-
m('overall', { status:
|
|
244
|
+
m('overall', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_OVERALL_STATUS }),
|
|
225
245
|
'',
|
|
226
246
|
'---',
|
|
227
|
-
m('footer', { time: new Date().
|
|
247
|
+
m('footer', { time: new Date().toISOString().slice(0, 19).replace('T', ' ') + ' UTC' }),
|
|
228
248
|
].join('\n');
|
|
229
249
|
|
|
230
250
|
if (botComment) {
|
|
@@ -246,6 +266,15 @@ jobs:
|
|
|
246
266
|
- name: Comment on PR (Failure)
|
|
247
267
|
if: github.event_name == 'pull_request' && steps.report.outputs.overall_ok == 'false'
|
|
248
268
|
uses: actions/github-script@v9
|
|
269
|
+
# Pass multi-line error logs via env; inlining them into a JS string literal breaks the script
|
|
270
|
+
env:
|
|
271
|
+
PAW_IN_STEPS_ERRORS_OUTPUTS_BUILD_ERRORS: ${{ steps.errors.outputs.build_errors }}
|
|
272
|
+
PAW_IN_STEPS_ERRORS_OUTPUTS_COMPILE_ERRORS: ${{ steps.errors.outputs.compile_errors }}
|
|
273
|
+
PAW_IN_STEPS_ERRORS_OUTPUTS_TEST_ERRORS: ${{ steps.errors.outputs.test_errors }}
|
|
274
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_BUILD_STATUS: ${{ steps.report.outputs.build_status }}
|
|
275
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_COMPILE_STATUS: ${{ steps.report.outputs.compile_status }}
|
|
276
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_OVERALL_STATUS: ${{ steps.report.outputs.overall_status }}
|
|
277
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_TEST_STATUS: ${{ steps.report.outputs.test_status }}
|
|
249
278
|
with:
|
|
250
279
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
251
280
|
script: |
|
|
@@ -266,18 +295,18 @@ jobs:
|
|
|
266
295
|
let errorDetails = '';
|
|
267
296
|
|
|
268
297
|
// Append compile errors
|
|
269
|
-
if (
|
|
270
|
-
errorDetails +=
|
|
298
|
+
if (process.env.PAW_IN_STEPS_ERRORS_OUTPUTS_COMPILE_ERRORS) {
|
|
299
|
+
errorDetails += process.env.PAW_IN_STEPS_ERRORS_OUTPUTS_COMPILE_ERRORS + '\n\n';
|
|
271
300
|
}
|
|
272
301
|
|
|
273
302
|
// Append test errors
|
|
274
|
-
if (
|
|
275
|
-
errorDetails +=
|
|
303
|
+
if (process.env.PAW_IN_STEPS_ERRORS_OUTPUTS_TEST_ERRORS) {
|
|
304
|
+
errorDetails += process.env.PAW_IN_STEPS_ERRORS_OUTPUTS_TEST_ERRORS + '\n\n';
|
|
276
305
|
}
|
|
277
306
|
|
|
278
307
|
// Append build errors
|
|
279
|
-
if (
|
|
280
|
-
errorDetails +=
|
|
308
|
+
if (process.env.PAW_IN_STEPS_ERRORS_OUTPUTS_BUILD_ERRORS) {
|
|
309
|
+
errorDetails += process.env.PAW_IN_STEPS_ERRORS_OUTPUTS_BUILD_ERRORS + '\n\n';
|
|
281
310
|
}
|
|
282
311
|
|
|
283
312
|
const failureMessage = [
|
|
@@ -287,11 +316,11 @@ jobs:
|
|
|
287
316
|
'',
|
|
288
317
|
m('table_header'),
|
|
289
318
|
'|------|------|',
|
|
290
|
-
m('row_compile', { status:
|
|
291
|
-
m('row_test', { status:
|
|
292
|
-
m('row_build', { status:
|
|
319
|
+
m('row_compile', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_COMPILE_STATUS }),
|
|
320
|
+
m('row_test', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_TEST_STATUS }),
|
|
321
|
+
m('row_build', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_BUILD_STATUS }),
|
|
293
322
|
'',
|
|
294
|
-
m('overall', { status:
|
|
323
|
+
m('overall', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_OVERALL_STATUS }),
|
|
295
324
|
'',
|
|
296
325
|
m('details_header'),
|
|
297
326
|
'',
|
|
@@ -303,7 +332,7 @@ jobs:
|
|
|
303
332
|
m('fix_test'),
|
|
304
333
|
'',
|
|
305
334
|
'---',
|
|
306
|
-
m('footer', { time: new Date().
|
|
335
|
+
m('footer', { time: new Date().toISOString().slice(0, 19).replace('T', ' ') + ' UTC' }),
|
|
307
336
|
].join('\n');
|
|
308
337
|
|
|
309
338
|
if (botComment) {
|
|
@@ -323,14 +352,19 @@ jobs:
|
|
|
323
352
|
}
|
|
324
353
|
|
|
325
354
|
- name: Create Check Run
|
|
326
|
-
if: always()
|
|
355
|
+
if: always() && steps.load_messages.outcome == 'success'
|
|
327
356
|
uses: actions/github-script@v9
|
|
357
|
+
env:
|
|
358
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_BUILD_STATUS: ${{ steps.report.outputs.build_status }}
|
|
359
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_COMPILE_STATUS: ${{ steps.report.outputs.compile_status }}
|
|
360
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_OVERALL_OK: ${{ steps.report.outputs.overall_ok }}
|
|
361
|
+
PAW_IN_STEPS_REPORT_OUTPUTS_TEST_STATUS: ${{ steps.report.outputs.test_status }}
|
|
328
362
|
with:
|
|
329
363
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
330
364
|
script: |
|
|
331
365
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
332
366
|
const m = (k, p = {}) => M['wf_spring_ci.' + k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
333
|
-
const conclusion =
|
|
367
|
+
const conclusion = process.env.PAW_IN_STEPS_REPORT_OUTPUTS_OVERALL_OK === 'true' ? 'success' : 'failure';
|
|
334
368
|
const summary = m(conclusion === 'success' ? 'check_summary_success' : 'check_summary_failure');
|
|
335
369
|
|
|
336
370
|
await github.rest.checks.create({
|
|
@@ -343,9 +377,9 @@ jobs:
|
|
|
343
377
|
output: {
|
|
344
378
|
title: '🔧 CI Build Check',
|
|
345
379
|
summary: summary,
|
|
346
|
-
text: '\n ' + m('check_compile', { status:
|
|
347
|
-
'\n ' + m('check_test', { status:
|
|
348
|
-
'\n ' + m('check_build', { status:
|
|
380
|
+
text: '\n ' + m('check_compile', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_COMPILE_STATUS }) +
|
|
381
|
+
'\n ' + m('check_test', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_TEST_STATUS }) + ' ' +
|
|
382
|
+
'\n ' + m('check_build', { status: process.env.PAW_IN_STEPS_REPORT_OUTPUTS_BUILD_STATUS }) +
|
|
349
383
|
'\n '
|
|
350
384
|
}
|
|
351
385
|
});
|
|
@@ -353,6 +387,7 @@ jobs:
|
|
|
353
387
|
- name: Fail Job on Build Failure
|
|
354
388
|
if: steps.report.outputs.overall_ok == 'false'
|
|
355
389
|
run: |
|
|
390
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
356
391
|
python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get wf_spring_ci.build_failed
|
|
357
392
|
exit 1
|
|
358
393
|
|
|
@@ -376,6 +411,7 @@ jobs:
|
|
|
376
411
|
env:
|
|
377
412
|
RESULTS: ${{ toJSON(needs.*.result) }}
|
|
378
413
|
run: |
|
|
414
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
379
415
|
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
380
416
|
m wf_spring_ci.gate_results results="$RESULTS"
|
|
381
417
|
if echo "$RESULTS" | grep -Eq '"(failure|cancelled)"'; then
|
|
@@ -142,6 +142,7 @@ jobs:
|
|
|
142
142
|
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
143
143
|
DOCKERFILE: ${{ env.DOCKERFILE_PATH }}
|
|
144
144
|
run: |
|
|
145
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
145
146
|
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
146
147
|
MISSING=""
|
|
147
148
|
for NAME in DOCKERHUB_USERNAME DOCKERHUB_TOKEN SERVER_HOST SERVER_USER; do
|
|
@@ -180,6 +181,7 @@ jobs:
|
|
|
180
181
|
|
|
181
182
|
- name: Generate application-prod.yml
|
|
182
183
|
run: |
|
|
184
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
183
185
|
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
184
186
|
mkdir -p ${{ env.APPLICATION_YML_DIR }}
|
|
185
187
|
cat << 'EOF' > ./${{ env.APPLICATION_YML_DIR }}/application-prod.yml
|
|
@@ -192,10 +194,10 @@ jobs:
|
|
|
192
194
|
run: ./gradlew clean build -x test ${{ env.GRADLE_OPTS }}
|
|
193
195
|
|
|
194
196
|
- name: Set up Docker Buildx
|
|
195
|
-
uses: docker/setup-buildx-action@
|
|
197
|
+
uses: docker/setup-buildx-action@v4
|
|
196
198
|
|
|
197
199
|
- name: Log in to DockerHub
|
|
198
|
-
uses: docker/login-action@
|
|
200
|
+
uses: docker/login-action@v4
|
|
199
201
|
with:
|
|
200
202
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
201
203
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
@@ -209,7 +211,7 @@ jobs:
|
|
|
209
211
|
${{ runner.os }}-buildx-
|
|
210
212
|
|
|
211
213
|
- name: Build and push Docker image
|
|
212
|
-
uses: docker/build-push-action@
|
|
214
|
+
uses: docker/build-push-action@v7
|
|
213
215
|
with:
|
|
214
216
|
context: ${{ env.PROJECT_PATH }}
|
|
215
217
|
file: ${{ env.PROJECT_PATH }}/${{ env.DOCKERFILE_PATH }}
|
|
@@ -242,6 +244,7 @@ jobs:
|
|
|
242
244
|
|
|
243
245
|
- name: Load messages
|
|
244
246
|
run: |
|
|
247
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
245
248
|
MSGS="$(python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" dump wf_spring_deploy. \
|
|
246
249
|
| python3 -c 'import json, shlex, sys; d = json.load(sys.stdin); print("\n".join("M_%s=%s" % (k.replace(".", "_"), shlex.quote(v)) for k, v in d.items()))' \
|
|
247
250
|
| base64 | tr -d '\n')"
|
|
@@ -316,8 +319,8 @@ jobs:
|
|
|
316
319
|
m banner_project name="${PROJECT_NAME}"
|
|
317
320
|
m banner_domain domain="${SERVICE_DOMAIN}"
|
|
318
321
|
m banner_image image="${IMAGE}"
|
|
319
|
-
|
|
320
|
-
|
|
322
|
+
m nginx_colors blue="${BLUE_PORT}" green="${GREEN_PORT}"
|
|
323
|
+
m nginx_conf_path path="${NGINX_RP_CONF}"
|
|
321
324
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
322
325
|
|
|
323
326
|
# 1. Pull the latest image
|
|
@@ -485,7 +488,7 @@ jobs:
|
|
|
485
488
|
m nginx_test_ok
|
|
486
489
|
rm -f "${TMP_FILE}"
|
|
487
490
|
|
|
488
|
-
|
|
491
|
+
m nginx_reload
|
|
489
492
|
if ! (SUDO systemctl reload nginx); then
|
|
490
493
|
m nginx_reload_fail
|
|
491
494
|
if ! (SUDO systemctl restart nginx); then
|
|
@@ -134,6 +134,7 @@ jobs:
|
|
|
134
134
|
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
135
135
|
DOCKERFILE: ${{ env.DOCKERFILE_PATH }}
|
|
136
136
|
run: |
|
|
137
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
137
138
|
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
138
139
|
MISSING=""
|
|
139
140
|
for NAME in DOCKERHUB_USERNAME DOCKERHUB_TOKEN SERVER_HOST SERVER_USER; do
|
|
@@ -172,6 +173,7 @@ jobs:
|
|
|
172
173
|
|
|
173
174
|
- name: Generate application-prod.yml
|
|
174
175
|
run: |
|
|
176
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
175
177
|
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
176
178
|
mkdir -p ${{ env.APPLICATION_YML_DIR }}
|
|
177
179
|
cat << 'EOF' > ./${{ env.APPLICATION_YML_DIR }}/application-prod.yml
|
|
@@ -184,10 +186,10 @@ jobs:
|
|
|
184
186
|
run: ./gradlew clean build -x test ${{ env.GRADLE_OPTS }}
|
|
185
187
|
|
|
186
188
|
- name: Set up Docker Buildx
|
|
187
|
-
uses: docker/setup-buildx-action@
|
|
189
|
+
uses: docker/setup-buildx-action@v4
|
|
188
190
|
|
|
189
191
|
- name: Log in to DockerHub
|
|
190
|
-
uses: docker/login-action@
|
|
192
|
+
uses: docker/login-action@v4
|
|
191
193
|
with:
|
|
192
194
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
193
195
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
@@ -201,7 +203,7 @@ jobs:
|
|
|
201
203
|
${{ runner.os }}-buildx-
|
|
202
204
|
|
|
203
205
|
- name: Build and push Docker image
|
|
204
|
-
uses: docker/build-push-action@
|
|
206
|
+
uses: docker/build-push-action@v7
|
|
205
207
|
with:
|
|
206
208
|
context: ${{ env.PROJECT_PATH }}
|
|
207
209
|
file: ${{ env.PROJECT_PATH }}/${{ env.DOCKERFILE_PATH }}
|
|
@@ -234,6 +236,7 @@ jobs:
|
|
|
234
236
|
|
|
235
237
|
- name: Load messages
|
|
236
238
|
run: |
|
|
239
|
+
[ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
237
240
|
MSGS="$(python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" dump wf_spring_deploy. \
|
|
238
241
|
| python3 -c 'import json, shlex, sys; d = json.load(sys.stdin); print("\n".join("M_%s=%s" % (k.replace(".", "_"), shlex.quote(v)) for k, v in d.items()))' \
|
|
239
242
|
| base64 | tr -d '\n')"
|
|
@@ -333,7 +336,7 @@ jobs:
|
|
|
333
336
|
NEW_NAME="${PROJECT_NAME}-${NEW_COLOR}"
|
|
334
337
|
OLD_NAME="${PROJECT_NAME}-${OLD_COLOR}"
|
|
335
338
|
|
|
336
|
-
|
|
339
|
+
m traefik_active active="${ACTIVE:-none}" new="${NEW_NAME}" old="${OLD_NAME}"
|
|
337
340
|
|
|
338
341
|
# 3. Clean up a leftover container in the same (idle) slot
|
|
339
342
|
m idle_slot_cleanup name="${NEW_NAME}"
|