project-auto-wizard 0.16.1 → 0.16.2
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/scripts/messages.py +44 -6
- package/payload/scripts/version_manager.py +76 -3
- package/payload/version.yml.template +3 -2
- package/payload/workflows/common/PROJECT-COMMON-AI-PR-SUMMARY.yaml +7 -7
- package/payload/workflows/common/PROJECT-COMMON-AUTO-CHANGELOG-CONTROL.yaml +111 -57
- package/payload/workflows/common/PROJECT-COMMON-README-VERSION-UPDATE.yaml +10 -1
- package/payload/workflows/common/PROJECT-COMMON-RELEASE-PUBLISH.yaml +13 -3
- package/payload/workflows/common/PROJECT-COMMON-VERSION-CONTROL.yaml +10 -1
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-PLAYSTORE-CICD.yaml +2 -2
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-TEST-APK.yaml +10 -10
- package/payload/workflows/flutter/PROJECT-FLUTTER-APP-BUILD-TRIGGER.yaml +10 -10
- package/payload/workflows/flutter/PROJECT-FLUTTER-CI.yaml +14 -12
- package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml +35 -18
- package/payload/workflows/go/PROJECT-GO-CI.yaml +3 -1
- package/payload/workflows/go/PROJECT-GO-PR-PREVIEW.yaml +81 -61
- package/payload/workflows/python/PROJECT-PYTHON-CI.yaml +3 -1
- package/payload/workflows/python/PROJECT-PYTHON-PR-PREVIEW.yaml +81 -61
- package/payload/workflows/react/PROJECT-REACT-CI.yaml +3 -2
- package/payload/workflows/spring/PROJECT-SPRING-CI.yml +4 -4
- package/payload/workflows/spring/server-deploy/PROJECT-SPRING-PR-PREVIEW.yaml +86 -68
- package/src/commands/doctor.js +14 -24
- package/src/commands/dry-run.js +4 -3
- package/src/commands/full.js +6 -6
- package/src/commands/interactive.js +5 -1
- package/src/commands/status.js +9 -2
- package/src/core/copy/gitignore.js +3 -3
- package/src/core/copy/readme.js +11 -10
- package/src/core/detect-fs.js +9 -4
- package/src/core/options.js +36 -0
- package/src/core/version-yml.js +37 -13
- package/src/i18n/catalog/en/cli.js +1 -0
- package/src/i18n/catalog/en/commands.js +4 -1
- package/src/i18n/catalog/en/core.js +1 -0
- package/src/i18n/catalog/en/core2.js +2 -0
- package/src/i18n/catalog/en/ui.js +3 -0
- package/src/i18n/catalog/ko/cli.js +1 -0
- package/src/i18n/catalog/ko/commands.js +4 -1
- package/src/i18n/catalog/ko/core.js +1 -0
- package/src/i18n/catalog/ko/core2.js +2 -0
- package/src/i18n/catalog/ko/ui.js +3 -0
- package/src/index.js +19 -7
- package/src/ui/summary.js +15 -6
|
@@ -125,10 +125,8 @@ jobs:
|
|
|
125
125
|
rm -rf .paw-msg
|
|
126
126
|
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
127
127
|
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
131
|
-
} >> "$GITHUB_ENV"
|
|
128
|
+
python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
|
|
129
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
|
|
132
130
|
|
|
133
131
|
- name: Add 👀 reaction to comment
|
|
134
132
|
if: contains(github.event.comment.body, '/wizard') && contains(github.event.comment.body, 'server')
|
|
@@ -235,10 +233,8 @@ jobs:
|
|
|
235
233
|
rm -rf .paw-msg
|
|
236
234
|
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
237
235
|
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
241
|
-
} >> "$GITHUB_ENV"
|
|
236
|
+
python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
|
|
237
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
|
|
242
238
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
243
239
|
# ship the messages it needs as a small shell function (m KEY name=value ...)
|
|
244
240
|
python3 - >> "$GITHUB_ENV" <<'PY'
|
|
@@ -283,7 +279,7 @@ jobs:
|
|
|
283
279
|
uses: actions/github-script@v9
|
|
284
280
|
with:
|
|
285
281
|
script: |
|
|
286
|
-
const M = JSON.parse(process.env.
|
|
282
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
287
283
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
288
284
|
|
|
289
285
|
const prNumber = context.issue.number;
|
|
@@ -322,6 +318,7 @@ jobs:
|
|
|
322
318
|
|
|
323
319
|
# If a required secret or the Dockerfile is missing, report the missing items and stop instead of surfacing a third-party error such as a docker login failure
|
|
324
320
|
- name: Deploy pre-check (Secrets and Dockerfile)
|
|
321
|
+
id: precheck
|
|
325
322
|
working-directory: ${{ env.PROJECT_PATH }}
|
|
326
323
|
env:
|
|
327
324
|
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
@@ -345,15 +342,21 @@ jobs:
|
|
|
345
342
|
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
346
343
|
fi
|
|
347
344
|
FAILED=false
|
|
345
|
+
ITEMS=""
|
|
348
346
|
if [ -n "$MISSING" ]; then
|
|
349
347
|
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
348
|
+
ITEMS="${MISSING# }"
|
|
349
|
+
ITEMS="${ITEMS// /, }"
|
|
350
350
|
FAILED=true
|
|
351
351
|
fi
|
|
352
352
|
if [ ! -f "$DOCKERFILE" ]; then
|
|
353
353
|
echo "::error title=$(m wf_preview.precheck_dockerfile_title)::$(m wf_preview.precheck_dockerfile_body path="${PROJECT_PATH}/${DOCKERFILE#./}")"
|
|
354
|
+
ITEMS="${ITEMS:+$ITEMS, }Dockerfile"
|
|
354
355
|
FAILED=true
|
|
355
356
|
fi
|
|
356
357
|
if [ "$FAILED" = "true" ]; then
|
|
358
|
+
# The failure comment names what blocked the later steps instead of showing them as waiting
|
|
359
|
+
echo "missing=$ITEMS" >> "$GITHUB_OUTPUT"
|
|
357
360
|
exit 1
|
|
358
361
|
fi
|
|
359
362
|
m wf_preview.precheck_ok
|
|
@@ -419,7 +422,7 @@ jobs:
|
|
|
419
422
|
PAW_IN_STEPS_PROGRESS_OUTPUTS_START_TIME: ${{ steps.progress.outputs.start_time }}
|
|
420
423
|
with:
|
|
421
424
|
script: |
|
|
422
|
-
const M = JSON.parse(process.env.
|
|
425
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
423
426
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
424
427
|
|
|
425
428
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -484,7 +487,7 @@ jobs:
|
|
|
484
487
|
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_DOCKER_START: ${{ steps.build_progress.outputs.docker_start }}
|
|
485
488
|
with:
|
|
486
489
|
script: |
|
|
487
|
-
const M = JSON.parse(process.env.
|
|
490
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
488
491
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
489
492
|
|
|
490
493
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -676,7 +679,7 @@ jobs:
|
|
|
676
679
|
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START: ${{ steps.docker_progress.outputs.deploy_start }}
|
|
677
680
|
with:
|
|
678
681
|
script: |
|
|
679
|
-
const M = JSON.parse(process.env.
|
|
682
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
680
683
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
681
684
|
|
|
682
685
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -759,9 +762,11 @@ jobs:
|
|
|
759
762
|
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.build_progress.outputs.build_duration }}
|
|
760
763
|
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
761
764
|
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
765
|
+
PAW_IN_STEPS_PRECHECK_OUTCOME: ${{ steps.precheck.outcome }}
|
|
766
|
+
PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING: ${{ steps.precheck.outputs.missing }}
|
|
762
767
|
with:
|
|
763
768
|
script: |
|
|
764
|
-
const M = JSON.parse(process.env.
|
|
769
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
765
770
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
766
771
|
|
|
767
772
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -782,16 +787,19 @@ jobs:
|
|
|
782
787
|
buildStatus = m('wf_preview.status_init_failed');
|
|
783
788
|
dockerStatus = '-';
|
|
784
789
|
deployStatus = '-';
|
|
790
|
+
} else if (process.env.PAW_IN_STEPS_PRECHECK_OUTCOME === 'failure') {
|
|
791
|
+
// The pre-check stopped the run before any build step: say why nothing ran
|
|
792
|
+
buildStatus = dockerStatus = deployStatus = m('wf_preview.status_precheck_blocked', { missing: process.env.PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING || '-' });
|
|
785
793
|
} else if (!buildDuration || buildDuration === '') {
|
|
786
794
|
// Failed at the build stage
|
|
787
795
|
buildStatus = m('wf_preview.status_failed');
|
|
788
|
-
dockerStatus = m('wf_preview.
|
|
789
|
-
deployStatus = m('wf_preview.
|
|
796
|
+
dockerStatus = m('wf_preview.status_not_run');
|
|
797
|
+
deployStatus = m('wf_preview.status_not_run');
|
|
790
798
|
} else if (!dockerDuration || dockerDuration === '') {
|
|
791
799
|
// Failed at the Docker stage
|
|
792
800
|
buildStatus = m('wf_preview.status_done');
|
|
793
801
|
dockerStatus = m('wf_preview.status_failed');
|
|
794
|
-
deployStatus = m('wf_preview.
|
|
802
|
+
deployStatus = m('wf_preview.status_not_run');
|
|
795
803
|
buildTime = buildDuration;
|
|
796
804
|
} else {
|
|
797
805
|
// Failed at the deploy stage
|
|
@@ -882,17 +890,15 @@ jobs:
|
|
|
882
890
|
rm -rf .paw-msg
|
|
883
891
|
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
884
892
|
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
888
|
-
} >> "$GITHUB_ENV"
|
|
893
|
+
python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
|
|
894
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
|
|
889
895
|
|
|
890
896
|
- name: Extract branch name from issue comment
|
|
891
897
|
id: extract
|
|
892
898
|
uses: actions/github-script@v9
|
|
893
899
|
with:
|
|
894
900
|
script: |
|
|
895
|
-
const M = JSON.parse(process.env.
|
|
901
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
896
902
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
897
903
|
|
|
898
904
|
const issueNumber = context.issue.number;
|
|
@@ -937,7 +943,7 @@ jobs:
|
|
|
937
943
|
uses: actions/github-script@v9
|
|
938
944
|
with:
|
|
939
945
|
script: |
|
|
940
|
-
const M = JSON.parse(process.env.
|
|
946
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
941
947
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
942
948
|
|
|
943
949
|
const issueNumber = context.issue.number;
|
|
@@ -1003,10 +1009,8 @@ jobs:
|
|
|
1003
1009
|
rm -rf .paw-msg
|
|
1004
1010
|
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
1005
1011
|
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
1009
|
-
} >> "$GITHUB_ENV"
|
|
1012
|
+
python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
|
|
1013
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
|
|
1010
1014
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
1011
1015
|
# ship the messages it needs as a small shell function (m KEY name=value ...)
|
|
1012
1016
|
python3 - >> "$GITHUB_ENV" <<'PY'
|
|
@@ -1039,7 +1043,7 @@ jobs:
|
|
|
1039
1043
|
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
1040
1044
|
with:
|
|
1041
1045
|
script: |
|
|
1042
|
-
const M = JSON.parse(process.env.
|
|
1046
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
1043
1047
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1044
1048
|
|
|
1045
1049
|
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
@@ -1117,7 +1121,7 @@ jobs:
|
|
|
1117
1121
|
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
1118
1122
|
with:
|
|
1119
1123
|
script: |
|
|
1120
|
-
const M = JSON.parse(process.env.
|
|
1124
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
1121
1125
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1122
1126
|
|
|
1123
1127
|
const issueNumber = parseInt(process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER, 10) || 0;
|
|
@@ -1160,6 +1164,7 @@ jobs:
|
|
|
1160
1164
|
|
|
1161
1165
|
# If a required secret or the Dockerfile is missing, report the missing items and stop instead of surfacing a third-party error such as a docker login failure
|
|
1162
1166
|
- name: Deploy pre-check (Secrets and Dockerfile)
|
|
1167
|
+
id: precheck
|
|
1163
1168
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1164
1169
|
working-directory: ${{ env.PROJECT_PATH }}
|
|
1165
1170
|
env:
|
|
@@ -1184,15 +1189,21 @@ jobs:
|
|
|
1184
1189
|
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
1185
1190
|
fi
|
|
1186
1191
|
FAILED=false
|
|
1192
|
+
ITEMS=""
|
|
1187
1193
|
if [ -n "$MISSING" ]; then
|
|
1188
1194
|
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
1195
|
+
ITEMS="${MISSING# }"
|
|
1196
|
+
ITEMS="${ITEMS// /, }"
|
|
1189
1197
|
FAILED=true
|
|
1190
1198
|
fi
|
|
1191
1199
|
if [ ! -f "$DOCKERFILE" ]; then
|
|
1192
1200
|
echo "::error title=$(m wf_preview.precheck_dockerfile_title)::$(m wf_preview.precheck_dockerfile_body path="${PROJECT_PATH}/${DOCKERFILE#./}")"
|
|
1201
|
+
ITEMS="${ITEMS:+$ITEMS, }Dockerfile"
|
|
1193
1202
|
FAILED=true
|
|
1194
1203
|
fi
|
|
1195
1204
|
if [ "$FAILED" = "true" ]; then
|
|
1205
|
+
# The failure comment names what blocked the later steps instead of showing them as waiting
|
|
1206
|
+
echo "missing=$ITEMS" >> "$GITHUB_OUTPUT"
|
|
1196
1207
|
exit 1
|
|
1197
1208
|
fi
|
|
1198
1209
|
m wf_preview.precheck_ok
|
|
@@ -1235,7 +1246,7 @@ jobs:
|
|
|
1235
1246
|
PAW_IN_STEPS_PROGRESS_OUTPUTS_START_TIME: ${{ steps.progress.outputs.start_time }}
|
|
1236
1247
|
with:
|
|
1237
1248
|
script: |
|
|
1238
|
-
const M = JSON.parse(process.env.
|
|
1249
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
1239
1250
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1240
1251
|
|
|
1241
1252
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -1308,7 +1319,7 @@ jobs:
|
|
|
1308
1319
|
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_DOCKER_START: ${{ steps.build_progress.outputs.docker_start }}
|
|
1309
1320
|
with:
|
|
1310
1321
|
script: |
|
|
1311
|
-
const M = JSON.parse(process.env.
|
|
1322
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
1312
1323
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1313
1324
|
|
|
1314
1325
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -1506,7 +1517,7 @@ jobs:
|
|
|
1506
1517
|
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
1507
1518
|
with:
|
|
1508
1519
|
script: |
|
|
1509
|
-
const M = JSON.parse(process.env.
|
|
1520
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
1510
1521
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1511
1522
|
|
|
1512
1523
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -1592,10 +1603,12 @@ jobs:
|
|
|
1592
1603
|
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.build_progress.outputs.build_duration }}
|
|
1593
1604
|
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
1594
1605
|
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
1606
|
+
PAW_IN_STEPS_PRECHECK_OUTCOME: ${{ steps.precheck.outcome }}
|
|
1607
|
+
PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING: ${{ steps.precheck.outputs.missing }}
|
|
1595
1608
|
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
1596
1609
|
with:
|
|
1597
1610
|
script: |
|
|
1598
|
-
const M = JSON.parse(process.env.
|
|
1611
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
1599
1612
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1600
1613
|
|
|
1601
1614
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -1614,14 +1627,17 @@ jobs:
|
|
|
1614
1627
|
buildStatus = m('wf_preview.status_init_failed');
|
|
1615
1628
|
dockerStatus = '-';
|
|
1616
1629
|
deployStatus = '-';
|
|
1630
|
+
} else if (process.env.PAW_IN_STEPS_PRECHECK_OUTCOME === 'failure') {
|
|
1631
|
+
// The pre-check stopped the run before any build step: say why nothing ran
|
|
1632
|
+
buildStatus = dockerStatus = deployStatus = m('wf_preview.status_precheck_blocked', { missing: process.env.PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING || '-' });
|
|
1617
1633
|
} else if (!buildDuration || buildDuration === '') {
|
|
1618
1634
|
buildStatus = m('wf_preview.status_failed');
|
|
1619
|
-
dockerStatus = m('wf_preview.
|
|
1620
|
-
deployStatus = m('wf_preview.
|
|
1635
|
+
dockerStatus = m('wf_preview.status_not_run');
|
|
1636
|
+
deployStatus = m('wf_preview.status_not_run');
|
|
1621
1637
|
} else if (!dockerDuration || dockerDuration === '') {
|
|
1622
1638
|
buildStatus = m('wf_preview.status_done');
|
|
1623
1639
|
dockerStatus = m('wf_preview.status_failed');
|
|
1624
|
-
deployStatus = m('wf_preview.
|
|
1640
|
+
deployStatus = m('wf_preview.status_not_run');
|
|
1625
1641
|
buildTime = buildDuration;
|
|
1626
1642
|
} else {
|
|
1627
1643
|
buildStatus = m('wf_preview.status_done');
|
|
@@ -1708,10 +1724,8 @@ jobs:
|
|
|
1708
1724
|
rm -rf .paw-msg
|
|
1709
1725
|
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
1710
1726
|
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
1714
|
-
} >> "$GITHUB_ENV"
|
|
1727
|
+
python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
|
|
1728
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
|
|
1715
1729
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
1716
1730
|
# ship the messages it needs as a small shell function (m KEY name=value ...)
|
|
1717
1731
|
python3 - >> "$GITHUB_ENV" <<'PY'
|
|
@@ -1841,7 +1855,7 @@ jobs:
|
|
|
1841
1855
|
PAW_IN_STEPS_PR_NUMBER_OUTPUTS_NUMBER: ${{ steps.pr_number.outputs.number }}
|
|
1842
1856
|
with:
|
|
1843
1857
|
script: |
|
|
1844
|
-
const M = JSON.parse(process.env.
|
|
1858
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
1845
1859
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1846
1860
|
|
|
1847
1861
|
const number = parseInt(process.env.PAW_IN_STEPS_PR_NUMBER_OUTPUTS_NUMBER, 10) || 0;
|
|
@@ -1898,10 +1912,8 @@ jobs:
|
|
|
1898
1912
|
rm -rf .paw-msg
|
|
1899
1913
|
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
1900
1914
|
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
1904
|
-
} >> "$GITHUB_ENV"
|
|
1915
|
+
python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
|
|
1916
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
|
|
1905
1917
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
1906
1918
|
# ship the messages it needs as a small shell function (m KEY name=value ...)
|
|
1907
1919
|
python3 - >> "$GITHUB_ENV" <<'PY'
|
|
@@ -2008,7 +2020,7 @@ jobs:
|
|
|
2008
2020
|
PAW_IN_STEPS_CHECK_RUNNING_OUTCOME: ${{ steps.check_running.outcome }}
|
|
2009
2021
|
with:
|
|
2010
2022
|
script: |
|
|
2011
|
-
const M = JSON.parse(process.env.
|
|
2023
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
2012
2024
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2013
2025
|
|
|
2014
2026
|
const number = context.issue.number;
|
|
@@ -2101,10 +2113,8 @@ jobs:
|
|
|
2101
2113
|
rm -rf .paw-msg
|
|
2102
2114
|
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
2103
2115
|
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
2107
|
-
} >> "$GITHUB_ENV"
|
|
2116
|
+
python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
|
|
2117
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
|
|
2108
2118
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
2109
2119
|
# ship the messages it needs as a small shell function (m KEY name=value ...)
|
|
2110
2120
|
python3 - >> "$GITHUB_ENV" <<'PY'
|
|
@@ -2188,7 +2198,7 @@ jobs:
|
|
|
2188
2198
|
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
2189
2199
|
with:
|
|
2190
2200
|
script: |
|
|
2191
|
-
const M = JSON.parse(process.env.
|
|
2201
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
2192
2202
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2193
2203
|
|
|
2194
2204
|
const branchName = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME;
|
|
@@ -2226,6 +2236,7 @@ jobs:
|
|
|
2226
2236
|
|
|
2227
2237
|
# If a required secret or the Dockerfile is missing, report the missing items and stop instead of surfacing a third-party error such as a docker login failure
|
|
2228
2238
|
- name: Deploy pre-check (Secrets and Dockerfile)
|
|
2239
|
+
id: precheck
|
|
2229
2240
|
if: steps.check_branch.outputs.exists == 'true'
|
|
2230
2241
|
working-directory: ${{ env.PROJECT_PATH }}
|
|
2231
2242
|
env:
|
|
@@ -2250,15 +2261,21 @@ jobs:
|
|
|
2250
2261
|
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
2251
2262
|
fi
|
|
2252
2263
|
FAILED=false
|
|
2264
|
+
ITEMS=""
|
|
2253
2265
|
if [ -n "$MISSING" ]; then
|
|
2254
2266
|
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
2267
|
+
ITEMS="${MISSING# }"
|
|
2268
|
+
ITEMS="${ITEMS// /, }"
|
|
2255
2269
|
FAILED=true
|
|
2256
2270
|
fi
|
|
2257
2271
|
if [ ! -f "$DOCKERFILE" ]; then
|
|
2258
2272
|
echo "::error title=$(m wf_preview.precheck_dockerfile_title)::$(m wf_preview.precheck_dockerfile_body path="${PROJECT_PATH}/${DOCKERFILE#./}")"
|
|
2273
|
+
ITEMS="${ITEMS:+$ITEMS, }Dockerfile"
|
|
2259
2274
|
FAILED=true
|
|
2260
2275
|
fi
|
|
2261
2276
|
if [ "$FAILED" = "true" ]; then
|
|
2277
|
+
# The failure comment names what blocked the later steps instead of showing them as waiting
|
|
2278
|
+
echo "missing=$ITEMS" >> "$GITHUB_OUTPUT"
|
|
2262
2279
|
exit 1
|
|
2263
2280
|
fi
|
|
2264
2281
|
m wf_preview.precheck_ok
|
|
@@ -2278,7 +2295,7 @@ jobs:
|
|
|
2278
2295
|
PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX: ${{ steps.extract.outputs.container_suffix }}
|
|
2279
2296
|
with:
|
|
2280
2297
|
script: |
|
|
2281
|
-
const M = JSON.parse(process.env.
|
|
2298
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
2282
2299
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2283
2300
|
|
|
2284
2301
|
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
@@ -2352,7 +2369,7 @@ jobs:
|
|
|
2352
2369
|
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2353
2370
|
with:
|
|
2354
2371
|
script: |
|
|
2355
|
-
const M = JSON.parse(process.env.
|
|
2372
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
2356
2373
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2357
2374
|
|
|
2358
2375
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -2420,7 +2437,7 @@ jobs:
|
|
|
2420
2437
|
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2421
2438
|
with:
|
|
2422
2439
|
script: |
|
|
2423
|
-
const M = JSON.parse(process.env.
|
|
2440
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
2424
2441
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2425
2442
|
|
|
2426
2443
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -2538,7 +2555,7 @@ jobs:
|
|
|
2538
2555
|
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2539
2556
|
with:
|
|
2540
2557
|
script: |
|
|
2541
|
-
const M = JSON.parse(process.env.
|
|
2558
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
2542
2559
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2543
2560
|
|
|
2544
2561
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -2609,9 +2626,11 @@ jobs:
|
|
|
2609
2626
|
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
2610
2627
|
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
2611
2628
|
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2629
|
+
PAW_IN_STEPS_PRECHECK_OUTCOME: ${{ steps.precheck.outcome }}
|
|
2630
|
+
PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING: ${{ steps.precheck.outputs.missing }}
|
|
2612
2631
|
with:
|
|
2613
2632
|
script: |
|
|
2614
|
-
const M = JSON.parse(process.env.
|
|
2633
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
2615
2634
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2616
2635
|
|
|
2617
2636
|
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
@@ -2629,14 +2648,17 @@ jobs:
|
|
|
2629
2648
|
buildStatus = m('wf_preview.status_init_failed');
|
|
2630
2649
|
dockerStatus = '-';
|
|
2631
2650
|
deployStatus = '-';
|
|
2651
|
+
} else if (process.env.PAW_IN_STEPS_PRECHECK_OUTCOME === 'failure') {
|
|
2652
|
+
// The pre-check stopped the run before any build step: say why nothing ran
|
|
2653
|
+
buildStatus = dockerStatus = deployStatus = m('wf_preview.status_precheck_blocked', { missing: process.env.PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING || '-' });
|
|
2632
2654
|
} else if (!buildDuration || buildDuration === '') {
|
|
2633
2655
|
buildStatus = m('wf_preview.status_failed');
|
|
2634
|
-
dockerStatus = m('wf_preview.
|
|
2635
|
-
deployStatus = m('wf_preview.
|
|
2656
|
+
dockerStatus = m('wf_preview.status_not_run');
|
|
2657
|
+
deployStatus = m('wf_preview.status_not_run');
|
|
2636
2658
|
} else if (!dockerDuration || dockerDuration === '') {
|
|
2637
2659
|
buildStatus = m('wf_preview.status_done');
|
|
2638
2660
|
dockerStatus = m('wf_preview.status_failed');
|
|
2639
|
-
deployStatus = m('wf_preview.
|
|
2661
|
+
deployStatus = m('wf_preview.status_not_run');
|
|
2640
2662
|
buildTime = buildDuration;
|
|
2641
2663
|
} else {
|
|
2642
2664
|
buildStatus = m('wf_preview.status_done');
|
|
@@ -2718,10 +2740,8 @@ jobs:
|
|
|
2718
2740
|
rm -rf .paw-msg
|
|
2719
2741
|
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
2720
2742
|
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
2724
|
-
} >> "$GITHUB_ENV"
|
|
2743
|
+
python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
|
|
2744
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
|
|
2725
2745
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
2726
2746
|
# ship the messages it needs as a small shell function (m KEY name=value ...)
|
|
2727
2747
|
python3 - >> "$GITHUB_ENV" <<'PY'
|
|
@@ -2837,7 +2857,7 @@ jobs:
|
|
|
2837
2857
|
PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX: ${{ steps.extract.outputs.container_suffix }}
|
|
2838
2858
|
with:
|
|
2839
2859
|
script: |
|
|
2840
|
-
const M = JSON.parse(process.env.
|
|
2860
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
2841
2861
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2842
2862
|
|
|
2843
2863
|
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
@@ -2898,10 +2918,8 @@ jobs:
|
|
|
2898
2918
|
rm -rf .paw-msg
|
|
2899
2919
|
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
2900
2920
|
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
2901
|
-
|
|
2902
|
-
|
|
2903
|
-
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
2904
|
-
} >> "$GITHUB_ENV"
|
|
2921
|
+
python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
|
|
2922
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
|
|
2905
2923
|
|
|
2906
2924
|
# Report the missing secrets by name instead of surfacing a raw SSH action error
|
|
2907
2925
|
- name: Deploy pre-check (Secrets)
|
|
@@ -2981,7 +2999,7 @@ jobs:
|
|
|
2981
2999
|
PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX: ${{ steps.extract.outputs.container_suffix }}
|
|
2982
3000
|
with:
|
|
2983
3001
|
script: |
|
|
2984
|
-
const M = JSON.parse(process.env.
|
|
3002
|
+
const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
|
|
2985
3003
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2986
3004
|
|
|
2987
3005
|
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
package/src/commands/doctor.js
CHANGED
|
@@ -18,6 +18,7 @@ import { findMissingScripts } from "../core/copy/simple.js";
|
|
|
18
18
|
import { resolvePayloadRoot } from "../core/assets.js";
|
|
19
19
|
import { parseExisting } from "../core/version-yml.js";
|
|
20
20
|
import { hooksFor } from "../core/types.js";
|
|
21
|
+
import { OPTIONS } from "../core/options.js";
|
|
21
22
|
import { t } from "../i18n/index.js";
|
|
22
23
|
|
|
23
24
|
const defaultExec = (cmd, args) => spawnSync(cmd, args, { encoding: "utf8" });
|
|
@@ -172,31 +173,20 @@ export function runDoctor(cwd = process.cwd(), { exec = defaultExec } = {}) {
|
|
|
172
173
|
}
|
|
173
174
|
|
|
174
175
|
// Show the actual setting: telling a user who turned it on that it is off would misrepresent the current state.
|
|
175
|
-
//
|
|
176
|
-
const
|
|
177
|
-
const
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
note: [
|
|
186
|
-
copilotState,
|
|
187
|
-
t(copilotAi === true ? "cmd.doctor.copilot.creditsOn" : "cmd.doctor.copilot.creditsOff"),
|
|
188
|
-
t("cmd.doctor.copilot.fallback"),
|
|
189
|
-
],
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
// release_automerge is on unless version.yml says false (a missing key also means on), so only an explicit false is reported as off.
|
|
193
|
-
// Without an install there is no saved setting to report, so the item is left out.
|
|
194
|
-
if (savedOptions) {
|
|
176
|
+
// One item per option that declares a `doctor` spec in the registry; version.yml is read once.
|
|
177
|
+
const savedParsed = installed ? parseExisting(readFileSync(join(cwd, "version.yml"), "utf8")) : null;
|
|
178
|
+
const savedOptions = savedParsed ? savedParsed.options : null;
|
|
179
|
+
for (const o of OPTIONS.filter((opt) => opt.doctor)) {
|
|
180
|
+
const { prefix, always, notes } = o.doctor;
|
|
181
|
+
// Without an install there is no saved setting to report
|
|
182
|
+
if (!savedOptions && !always) continue;
|
|
183
|
+
// An unrecognized value is a problem to fix (the workflow reads it as off), not just information.
|
|
184
|
+
const invalid = notes.invalid ? savedParsed?.invalidOptions.find((i) => i.key === o.key) : null;
|
|
185
|
+
const keys = invalid ? notes.invalid : notes[String(savedOptions?.[o.name] ?? null)];
|
|
195
186
|
add({
|
|
196
|
-
name: t(
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
: [t("cmd.doctor.automerge.on"), t("cmd.doctor.automerge.onHow")],
|
|
187
|
+
name: t(`${prefix}.name`), label: t(`${prefix}.name`), purpose: t(`${prefix}.purpose`),
|
|
188
|
+
status: invalid ? "WARN" : "INFO",
|
|
189
|
+
note: keys.map((k) => t(`${prefix}.${k}`, invalid ? { value: invalid.value } : {})),
|
|
200
190
|
});
|
|
201
191
|
}
|
|
202
192
|
|
package/src/commands/dry-run.js
CHANGED
|
@@ -23,11 +23,12 @@ function versionYmlPreview(context, payloadRoot, targetRoot) {
|
|
|
23
23
|
|
|
24
24
|
const vyPath = join(targetRoot, PATHS.versionFile);
|
|
25
25
|
const existingRaw = existsSync(vyPath) ? readFileSync(vyPath, "utf8") : null;
|
|
26
|
-
const
|
|
26
|
+
const prevParsed = existingRaw !== null ? parseExisting(existingRaw) : null;
|
|
27
|
+
const extraTopLevel = prevParsed ? prevParsed.extraTopLevel : [];
|
|
27
28
|
|
|
28
29
|
// Use the same render function as the real install; assembling separately drifts the preview whenever an option is added.
|
|
29
30
|
const wouldBe = renderVersionYml(context, readVersionYmlTemplate(payloadRoot), {
|
|
30
|
-
pathMarkers, extraTopLevel,
|
|
31
|
+
pathMarkers, extraTopLevel, lastUpdatedBy: prevParsed?.lastUpdatedBy || "",
|
|
31
32
|
});
|
|
32
33
|
// Compare by the same rule as the real install: if only the timestamp lines differ, the install does not rewrite the file either.
|
|
33
34
|
return { existed: existingRaw !== null, changed: existingRaw === null || !sameIgnoringTimestamps(existingRaw, wouldBe) };
|
|
@@ -63,7 +64,7 @@ export function planDryRun(mode, context, payloadRoot, targetRoot = ".") {
|
|
|
63
64
|
droppedPathLines: existingDroppedLines(targetRoot, context.paths),
|
|
64
65
|
// Files the real install also changes; scripts that overwrite existing files in particular must be shown in advance.
|
|
65
66
|
scripts: planScripts(payloadRoot, targetRoot),
|
|
66
|
-
readme: planVersionSection(targetRoot),
|
|
67
|
+
readme: planVersionSection(targetRoot, context.language),
|
|
67
68
|
baselineExists: existsSync(join(targetRoot, BASELINE_PATH)),
|
|
68
69
|
};
|
|
69
70
|
}
|
package/src/commands/full.js
CHANGED
|
@@ -6,7 +6,7 @@ import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
|
6
6
|
import { writeText, findUnwritable } from "../core/fsutil.js";
|
|
7
7
|
import { CliError } from "../core/errors.js";
|
|
8
8
|
import { PATHS } from "../core/paths.js";
|
|
9
|
-
import { renderVersionYml, parseExisting, sameIgnoringTimestamps, droppedPathLines } from "../core/version-yml.js";
|
|
9
|
+
import { renderVersionYml, parseExisting, sameIgnoringTimestamps, droppedPathLines, invalidOptionLines } from "../core/version-yml.js";
|
|
10
10
|
import { readVersionYmlTemplate } from "../core/assets.js";
|
|
11
11
|
import { existingMarkerInDir } from "../core/paths-resolve.js";
|
|
12
12
|
import { addVersionSectionToReadme, README_STATUS_LABEL } from "../core/copy/readme.js";
|
|
@@ -28,8 +28,7 @@ import { t } from "../i18n/index.js";
|
|
|
28
28
|
// payloadRoot: the package's payload/ root. targetRoot: the install target.
|
|
29
29
|
export function runFull(context, payloadRoot, targetRoot = ".", hooks = {}) {
|
|
30
30
|
const { version, types = [], paths = new Map(), branch = "main", versionCode = 1,
|
|
31
|
-
force = true, now, today, templateVersion = "unknown"
|
|
32
|
-
includeSemverAuto } = context;
|
|
31
|
+
force = true, now, today, templateVersion = "unknown" } = context;
|
|
33
32
|
|
|
34
33
|
// Check permissions before writing anything: stopping midway would leave a half-installed state.
|
|
35
34
|
const blocked = findUnwritable(targetRoot,
|
|
@@ -75,10 +74,11 @@ export function runFull(context, payloadRoot, targetRoot = ".", hooks = {}) {
|
|
|
75
74
|
const extraTopLevel = prevParsed ? prevParsed.extraTopLevel : [];
|
|
76
75
|
// Folders folded into one type entry are not managed after this rewrite; leave a trace in the install log.
|
|
77
76
|
for (const line of droppedPathLines(prevParsed?.droppedPaths, paths)) log.warn("version", "paths", line);
|
|
77
|
+
for (const line of invalidOptionLines(prevParsed?.invalidOptions)) log.warn("version", "options", line);
|
|
78
78
|
|
|
79
79
|
// 2. Generate version.yml (render payload/version.yml.template; full regeneration)
|
|
80
80
|
// A re-run where only the date lines differ does not rewrite it (idempotent).
|
|
81
|
-
const vyText = renderVersionYml(context, readVersionYmlTemplate(payloadRoot), { pathMarkers, deployValues, extraTopLevel });
|
|
81
|
+
const vyText = renderVersionYml(context, readVersionYmlTemplate(payloadRoot), { pathMarkers, deployValues, extraTopLevel, lastUpdatedBy: prevParsed?.lastUpdatedBy || "" });
|
|
82
82
|
if (prevVy == null || !sameIgnoringTimestamps(prevVy, vyText)) {
|
|
83
83
|
writeText(vyPath, vyText);
|
|
84
84
|
log.info("version", "write", `version.yml (v${version}, code=${versionCode})`);
|
|
@@ -87,7 +87,7 @@ export function runFull(context, payloadRoot, targetRoot = ".", hooks = {}) {
|
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
// 3. README version section
|
|
90
|
-
const readme = addVersionSectionToReadme(version, targetRoot);
|
|
90
|
+
const readme = addVersionSectionToReadme(version, targetRoot, context.language);
|
|
91
91
|
log.info("readme", readme === "added" ? "append" : "skip", README_STATUS_LABEL[readme] || readme);
|
|
92
92
|
|
|
93
93
|
// 4. scripts (payload/scripts/*.py -> .github/scripts/): always overwritten, so also record that user edits are lost.
|
|
@@ -123,7 +123,7 @@ export function runFull(context, payloadRoot, targetRoot = ".", hooks = {}) {
|
|
|
123
123
|
const gitignoreUpdated = gitignoreUpdated0 || cleanup.backedUp.length > 0 || storeCleanup.backedUp.length > 0
|
|
124
124
|
|| staleCleanup.backedUp.length > 0;
|
|
125
125
|
if (gitignoreUpdated) {
|
|
126
|
-
const gi = ensureGitignore(targetRoot);
|
|
126
|
+
const gi = ensureGitignore(targetRoot, context.language);
|
|
127
127
|
log.info("gitignore", gi.created ? "create" : gi.added.length ? "append" : "skip",
|
|
128
128
|
gi.added.length ? `.gitignore += ${gi.added.join(", ")}` : t("cmd.full.log.gitignoreExisting"));
|
|
129
129
|
}
|
|
@@ -6,7 +6,7 @@ import { join } from "node:path";
|
|
|
6
6
|
import { existsSync, readFileSync } from "node:fs";
|
|
7
7
|
import { resolvePayloadRoot, assertPayload, readTemplateVersion } from "../core/assets.js";
|
|
8
8
|
import { detectTypes, detectVersion, detectDefaultBranch, detectRepoName, makeResolvers, detectMarkers } from "../core/detect-fs.js";
|
|
9
|
-
import { parseExisting, droppedPathLines } from "../core/version-yml.js";
|
|
9
|
+
import { parseExisting, droppedPathLines, invalidOptionLines } from "../core/version-yml.js";
|
|
10
10
|
import { pickReleaseOptions, resolveReleaseOptions } from "../core/release-options.js";
|
|
11
11
|
import { OPTIONS, askableOptions, explicitFromContext } from "../core/options.js";
|
|
12
12
|
import { runBreakingCheck } from "../core/breaking-check.js";
|
|
@@ -292,6 +292,9 @@ export async function runInteractive(baseCtx, { cwd = process.cwd(), payloadRoot
|
|
|
292
292
|
// Announce merged folders only now: the message must follow the folders actually chosen, not the saved ones.
|
|
293
293
|
if (existing?.droppedPaths?.length) io.note?.(droppedPathLines(existing.droppedPaths, paths).join("\n"), t("core.versionYml.pathMergedTitle"));
|
|
294
294
|
|
|
295
|
+
// Option values that could not be read are rewritten as false by this run; tell the user before they confirm.
|
|
296
|
+
if (existing?.invalidOptions?.length) io.note?.(invalidOptionLines(existing.invalidOptions).join("\n"), t("core.versionYml.optionInvalidTitle"));
|
|
297
|
+
|
|
295
298
|
// In a monorepo the version/build-number files live inside the type folder - detect there now that paths are settled.
|
|
296
299
|
if (versionAutoDetected && [...paths.values()].some((p) => p && p !== ".")) {
|
|
297
300
|
version = detectVersion(cwd, { types, paths, warn: () => {} });
|
|
@@ -376,6 +379,7 @@ export async function runInteractive(baseCtx, { cwd = process.cwd(), payloadRoot
|
|
|
376
379
|
// Completion summary
|
|
377
380
|
io.summary?.({
|
|
378
381
|
mode, types, version, versionCode, branches, developMissing,
|
|
382
|
+
releaseAutomerge: ctx.includeReleaseAutomerge !== false,
|
|
379
383
|
copiedFiles: result?.workflows?.copiedFiles ?? [],
|
|
380
384
|
autoUpdated: result?.workflows?.autoUpdated ?? [],
|
|
381
385
|
gitignoreUpdated: result?.gitignoreUpdated === true,
|