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.
Files changed (47) hide show
  1. package/README.ja.md +1 -1
  2. package/README.ko.md +1 -1
  3. package/README.md +2 -2
  4. package/README.zh-CN.md +1 -1
  5. package/package.json +1 -1
  6. package/payload/scripts/messages.py +44 -6
  7. package/payload/scripts/version_manager.py +76 -3
  8. package/payload/version.yml.template +3 -2
  9. package/payload/workflows/common/PROJECT-COMMON-AI-PR-SUMMARY.yaml +7 -7
  10. package/payload/workflows/common/PROJECT-COMMON-AUTO-CHANGELOG-CONTROL.yaml +111 -57
  11. package/payload/workflows/common/PROJECT-COMMON-README-VERSION-UPDATE.yaml +10 -1
  12. package/payload/workflows/common/PROJECT-COMMON-RELEASE-PUBLISH.yaml +13 -3
  13. package/payload/workflows/common/PROJECT-COMMON-VERSION-CONTROL.yaml +10 -1
  14. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-PLAYSTORE-CICD.yaml +2 -2
  15. package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-TEST-APK.yaml +10 -10
  16. package/payload/workflows/flutter/PROJECT-FLUTTER-APP-BUILD-TRIGGER.yaml +10 -10
  17. package/payload/workflows/flutter/PROJECT-FLUTTER-CI.yaml +14 -12
  18. package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml +35 -18
  19. package/payload/workflows/go/PROJECT-GO-CI.yaml +3 -1
  20. package/payload/workflows/go/PROJECT-GO-PR-PREVIEW.yaml +81 -61
  21. package/payload/workflows/python/PROJECT-PYTHON-CI.yaml +3 -1
  22. package/payload/workflows/python/PROJECT-PYTHON-PR-PREVIEW.yaml +81 -61
  23. package/payload/workflows/react/PROJECT-REACT-CI.yaml +3 -2
  24. package/payload/workflows/spring/PROJECT-SPRING-CI.yml +4 -4
  25. package/payload/workflows/spring/server-deploy/PROJECT-SPRING-PR-PREVIEW.yaml +86 -68
  26. package/src/commands/doctor.js +14 -24
  27. package/src/commands/dry-run.js +4 -3
  28. package/src/commands/full.js +6 -6
  29. package/src/commands/interactive.js +5 -1
  30. package/src/commands/status.js +9 -2
  31. package/src/core/copy/gitignore.js +3 -3
  32. package/src/core/copy/readme.js +11 -10
  33. package/src/core/detect-fs.js +9 -4
  34. package/src/core/options.js +36 -0
  35. package/src/core/version-yml.js +37 -13
  36. package/src/i18n/catalog/en/cli.js +1 -0
  37. package/src/i18n/catalog/en/commands.js +4 -1
  38. package/src/i18n/catalog/en/core.js +1 -0
  39. package/src/i18n/catalog/en/core2.js +2 -0
  40. package/src/i18n/catalog/en/ui.js +3 -0
  41. package/src/i18n/catalog/ko/cli.js +1 -0
  42. package/src/i18n/catalog/ko/commands.js +4 -1
  43. package/src/i18n/catalog/ko/core.js +1 -0
  44. package/src/i18n/catalog/ko/core2.js +2 -0
  45. package/src/i18n/catalog/ko/ui.js +3 -0
  46. package/src/index.js +19 -7
  47. package/src/ui/summary.js +15 -6
@@ -121,10 +121,8 @@ jobs:
121
121
  rm -rf .paw-msg
122
122
  # The workspace root has no version.yml; pass the language resolved above to every later messages.py call
123
123
  export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
124
- {
125
- echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
126
- echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
127
- } >> "$GITHUB_ENV"
124
+ python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
125
+ echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
128
126
 
129
127
  - name: Add 👀 reaction to comment
130
128
  if: contains(github.event.comment.body, '/wizard') && contains(github.event.comment.body, 'server')
@@ -231,10 +229,8 @@ jobs:
231
229
  rm -rf .paw-msg
232
230
  # The workspace root has no version.yml; pass the language resolved above to every later messages.py call
233
231
  export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
234
- {
235
- echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
236
- echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
237
- } >> "$GITHUB_ENV"
232
+ python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
233
+ echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
238
234
  # The deploy script runs on the remote server, where messages.py does not exist:
239
235
  # ship the messages it needs as a small shell function (m KEY name=value ...)
240
236
  python3 - >> "$GITHUB_ENV" <<'PY'
@@ -279,7 +275,7 @@ jobs:
279
275
  uses: actions/github-script@v9
280
276
  with:
281
277
  script: |
282
- const M = JSON.parse(process.env.PAW_MSG);
278
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
283
279
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
284
280
 
285
281
  const prNumber = context.issue.number;
@@ -318,6 +314,7 @@ jobs:
318
314
 
319
315
  # 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
320
316
  - name: Deploy pre-check (Secrets and Dockerfile)
317
+ id: precheck
321
318
  working-directory: ${{ env.PROJECT_PATH }}
322
319
  env:
323
320
  DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
@@ -341,15 +338,21 @@ jobs:
341
338
  [ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
342
339
  fi
343
340
  FAILED=false
341
+ ITEMS=""
344
342
  if [ -n "$MISSING" ]; then
345
343
  echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
344
+ ITEMS="${MISSING# }"
345
+ ITEMS="${ITEMS// /, }"
346
346
  FAILED=true
347
347
  fi
348
348
  if [ ! -f "$DOCKERFILE" ]; then
349
349
  echo "::error title=$(m wf_preview.precheck_dockerfile_title)::$(m wf_preview.precheck_dockerfile_body path="${PROJECT_PATH}/${DOCKERFILE#./}")"
350
+ ITEMS="${ITEMS:+$ITEMS, }Dockerfile"
350
351
  FAILED=true
351
352
  fi
352
353
  if [ "$FAILED" = "true" ]; then
354
+ # The failure comment names what blocked the later steps instead of showing them as waiting
355
+ echo "missing=$ITEMS" >> "$GITHUB_OUTPUT"
353
356
  exit 1
354
357
  fi
355
358
  m wf_preview.precheck_ok
@@ -390,7 +393,7 @@ jobs:
390
393
  PAW_IN_STEPS_PROGRESS_OUTPUTS_DOCKER_START: ${{ steps.progress.outputs.docker_start }}
391
394
  with:
392
395
  script: |
393
- const M = JSON.parse(process.env.PAW_MSG);
396
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
394
397
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
395
398
 
396
399
  const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
@@ -579,7 +582,7 @@ jobs:
579
582
  PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START: ${{ steps.docker_progress.outputs.deploy_start }}
580
583
  with:
581
584
  script: |
582
- const M = JSON.parse(process.env.PAW_MSG);
585
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
583
586
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
584
587
 
585
588
  const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
@@ -659,9 +662,11 @@ jobs:
659
662
  env:
660
663
  PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
661
664
  PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
665
+ PAW_IN_STEPS_PRECHECK_OUTCOME: ${{ steps.precheck.outcome }}
666
+ PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING: ${{ steps.precheck.outputs.missing }}
662
667
  with:
663
668
  script: |
664
- const M = JSON.parse(process.env.PAW_MSG);
669
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
665
670
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
666
671
 
667
672
  const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
@@ -680,10 +685,13 @@ jobs:
680
685
  // Failed before the progress comment was created (initialization stage)
681
686
  dockerStatus = m('wf_preview.status_init_failed');
682
687
  deployStatus = '-';
688
+ } else if (process.env.PAW_IN_STEPS_PRECHECK_OUTCOME === 'failure') {
689
+ // The pre-check stopped the run before any build step: say why nothing ran
690
+ dockerStatus = deployStatus = m('wf_preview.status_precheck_blocked', { missing: process.env.PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING || '-' });
683
691
  } else if (!dockerDuration || dockerDuration === '') {
684
- // Failed at the Docker build stage
692
+ // Failed at the Docker build stage; the deploy step never ran
685
693
  dockerStatus = m('wf_preview.status_failed');
686
- deployStatus = m('wf_preview.status_waiting');
694
+ deployStatus = m('wf_preview.status_not_run');
687
695
  } else {
688
696
  // Failed at the deploy stage
689
697
  dockerStatus = m('wf_preview.status_done');
@@ -770,17 +778,15 @@ jobs:
770
778
  rm -rf .paw-msg
771
779
  # The workspace root has no version.yml; pass the language resolved above to every later messages.py call
772
780
  export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
773
- {
774
- echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
775
- echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
776
- } >> "$GITHUB_ENV"
781
+ python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
782
+ echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
777
783
 
778
784
  - name: Extract branch name from issue comment
779
785
  id: extract
780
786
  uses: actions/github-script@v9
781
787
  with:
782
788
  script: |
783
- const M = JSON.parse(process.env.PAW_MSG);
789
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
784
790
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
785
791
 
786
792
  const issueNumber = context.issue.number;
@@ -825,7 +831,7 @@ jobs:
825
831
  uses: actions/github-script@v9
826
832
  with:
827
833
  script: |
828
- const M = JSON.parse(process.env.PAW_MSG);
834
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
829
835
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
830
836
 
831
837
  const issueNumber = context.issue.number;
@@ -891,10 +897,8 @@ jobs:
891
897
  rm -rf .paw-msg
892
898
  # The workspace root has no version.yml; pass the language resolved above to every later messages.py call
893
899
  export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
894
- {
895
- echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
896
- echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
897
- } >> "$GITHUB_ENV"
900
+ python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
901
+ echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
898
902
  # The deploy script runs on the remote server, where messages.py does not exist:
899
903
  # ship the messages it needs as a small shell function (m KEY name=value ...)
900
904
  python3 - >> "$GITHUB_ENV" <<'PY'
@@ -927,7 +931,7 @@ jobs:
927
931
  PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
928
932
  with:
929
933
  script: |
930
- const M = JSON.parse(process.env.PAW_MSG);
934
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
931
935
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
932
936
 
933
937
  const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
@@ -1006,7 +1010,7 @@ jobs:
1006
1010
  PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
1007
1011
  with:
1008
1012
  script: |
1009
- const M = JSON.parse(process.env.PAW_MSG);
1013
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
1010
1014
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
1011
1015
 
1012
1016
  const issueNumber = parseInt(process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER, 10) || 0;
@@ -1049,6 +1053,7 @@ jobs:
1049
1053
 
1050
1054
  # 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
1051
1055
  - name: Deploy pre-check (Secrets and Dockerfile)
1056
+ id: precheck
1052
1057
  if: steps.check_branch.outputs.exists == 'true'
1053
1058
  working-directory: ${{ env.PROJECT_PATH }}
1054
1059
  env:
@@ -1073,15 +1078,21 @@ jobs:
1073
1078
  [ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
1074
1079
  fi
1075
1080
  FAILED=false
1081
+ ITEMS=""
1076
1082
  if [ -n "$MISSING" ]; then
1077
1083
  echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
1084
+ ITEMS="${MISSING# }"
1085
+ ITEMS="${ITEMS// /, }"
1078
1086
  FAILED=true
1079
1087
  fi
1080
1088
  if [ ! -f "$DOCKERFILE" ]; then
1081
1089
  echo "::error title=$(m wf_preview.precheck_dockerfile_title)::$(m wf_preview.precheck_dockerfile_body path="${PROJECT_PATH}/${DOCKERFILE#./}")"
1090
+ ITEMS="${ITEMS:+$ITEMS, }Dockerfile"
1082
1091
  FAILED=true
1083
1092
  fi
1084
1093
  if [ "$FAILED" = "true" ]; then
1094
+ # The failure comment names what blocked the later steps instead of showing them as waiting
1095
+ echo "missing=$ITEMS" >> "$GITHUB_OUTPUT"
1085
1096
  exit 1
1086
1097
  fi
1087
1098
  m wf_preview.precheck_ok
@@ -1128,7 +1139,7 @@ jobs:
1128
1139
  PAW_IN_STEPS_PROGRESS_OUTPUTS_DOCKER_START: ${{ steps.progress.outputs.docker_start }}
1129
1140
  with:
1130
1141
  script: |
1131
- const M = JSON.parse(process.env.PAW_MSG);
1142
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
1132
1143
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
1133
1144
 
1134
1145
  const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
@@ -1323,7 +1334,7 @@ jobs:
1323
1334
  PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
1324
1335
  with:
1325
1336
  script: |
1326
- const M = JSON.parse(process.env.PAW_MSG);
1337
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
1327
1338
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
1328
1339
 
1329
1340
  const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
@@ -1406,10 +1417,12 @@ jobs:
1406
1417
  PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
1407
1418
  PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
1408
1419
  PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
1420
+ PAW_IN_STEPS_PRECHECK_OUTCOME: ${{ steps.precheck.outcome }}
1421
+ PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING: ${{ steps.precheck.outputs.missing }}
1409
1422
  PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
1410
1423
  with:
1411
1424
  script: |
1412
- const M = JSON.parse(process.env.PAW_MSG);
1425
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
1413
1426
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
1414
1427
 
1415
1428
  const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
@@ -1426,9 +1439,13 @@ jobs:
1426
1439
  if (!commentId) {
1427
1440
  dockerStatus = m('wf_preview.status_init_failed');
1428
1441
  deployStatus = '-';
1442
+ } else if (process.env.PAW_IN_STEPS_PRECHECK_OUTCOME === 'failure') {
1443
+ // The pre-check stopped the run before any build step: say why nothing ran
1444
+ dockerStatus = deployStatus = m('wf_preview.status_precheck_blocked', { missing: process.env.PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING || '-' });
1429
1445
  } else if (!dockerDuration || dockerDuration === '') {
1446
+ // Failed at the Docker build stage; the deploy step never ran
1430
1447
  dockerStatus = m('wf_preview.status_failed');
1431
- deployStatus = m('wf_preview.status_waiting');
1448
+ deployStatus = m('wf_preview.status_not_run');
1432
1449
  } else {
1433
1450
  dockerStatus = m('wf_preview.status_done');
1434
1451
  deployStatus = m('wf_preview.status_failed');
@@ -1511,10 +1528,8 @@ jobs:
1511
1528
  rm -rf .paw-msg
1512
1529
  # The workspace root has no version.yml; pass the language resolved above to every later messages.py call
1513
1530
  export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
1514
- {
1515
- echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
1516
- echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
1517
- } >> "$GITHUB_ENV"
1531
+ python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
1532
+ echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
1518
1533
  # The deploy script runs on the remote server, where messages.py does not exist:
1519
1534
  # ship the messages it needs as a small shell function (m KEY name=value ...)
1520
1535
  python3 - >> "$GITHUB_ENV" <<'PY'
@@ -1646,7 +1661,7 @@ jobs:
1646
1661
  PAW_IN_STEPS_PR_NUMBER_OUTPUTS_NUMBER: ${{ steps.pr_number.outputs.number }}
1647
1662
  with:
1648
1663
  script: |
1649
- const M = JSON.parse(process.env.PAW_MSG);
1664
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
1650
1665
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
1651
1666
 
1652
1667
  const number = parseInt(process.env.PAW_IN_STEPS_PR_NUMBER_OUTPUTS_NUMBER, 10) || 0;
@@ -1703,10 +1718,8 @@ jobs:
1703
1718
  rm -rf .paw-msg
1704
1719
  # The workspace root has no version.yml; pass the language resolved above to every later messages.py call
1705
1720
  export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
1706
- {
1707
- echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
1708
- echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
1709
- } >> "$GITHUB_ENV"
1721
+ python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
1722
+ echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
1710
1723
  # The deploy script runs on the remote server, where messages.py does not exist:
1711
1724
  # ship the messages it needs as a small shell function (m KEY name=value ...)
1712
1725
  python3 - >> "$GITHUB_ENV" <<'PY'
@@ -1813,7 +1826,7 @@ jobs:
1813
1826
  PAW_IN_STEPS_CHECK_RUNNING_OUTCOME: ${{ steps.check_running.outcome }}
1814
1827
  with:
1815
1828
  script: |
1816
- const M = JSON.parse(process.env.PAW_MSG);
1829
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
1817
1830
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
1818
1831
 
1819
1832
  const number = context.issue.number;
@@ -1903,10 +1916,8 @@ jobs:
1903
1916
  rm -rf .paw-msg
1904
1917
  # The workspace root has no version.yml; pass the language resolved above to every later messages.py call
1905
1918
  export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
1906
- {
1907
- echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
1908
- echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
1909
- } >> "$GITHUB_ENV"
1919
+ python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
1920
+ echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
1910
1921
  # The deploy script runs on the remote server, where messages.py does not exist:
1911
1922
  # ship the messages it needs as a small shell function (m KEY name=value ...)
1912
1923
  python3 - >> "$GITHUB_ENV" <<'PY'
@@ -1938,7 +1949,7 @@ jobs:
1938
1949
  PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
1939
1950
  with:
1940
1951
  script: |
1941
- const M = JSON.parse(process.env.PAW_MSG);
1952
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
1942
1953
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
1943
1954
 
1944
1955
  const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
@@ -2030,7 +2041,7 @@ jobs:
2030
2041
  PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
2031
2042
  with:
2032
2043
  script: |
2033
- const M = JSON.parse(process.env.PAW_MSG);
2044
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
2034
2045
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
2035
2046
 
2036
2047
  const issueNumber = context.issue.number;
@@ -2073,6 +2084,7 @@ jobs:
2073
2084
 
2074
2085
  # 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
2075
2086
  - name: Deploy pre-check (Secrets and Dockerfile)
2087
+ id: precheck
2076
2088
  if: steps.branch_info.outputs.branch_exists == 'true'
2077
2089
  working-directory: ${{ env.PROJECT_PATH }}
2078
2090
  env:
@@ -2097,15 +2109,21 @@ jobs:
2097
2109
  [ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
2098
2110
  fi
2099
2111
  FAILED=false
2112
+ ITEMS=""
2100
2113
  if [ -n "$MISSING" ]; then
2101
2114
  echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
2115
+ ITEMS="${MISSING# }"
2116
+ ITEMS="${ITEMS// /, }"
2102
2117
  FAILED=true
2103
2118
  fi
2104
2119
  if [ ! -f "$DOCKERFILE" ]; then
2105
2120
  echo "::error title=$(m wf_preview.precheck_dockerfile_title)::$(m wf_preview.precheck_dockerfile_body path="${PROJECT_PATH}/${DOCKERFILE#./}")"
2121
+ ITEMS="${ITEMS:+$ITEMS, }Dockerfile"
2106
2122
  FAILED=true
2107
2123
  fi
2108
2124
  if [ "$FAILED" = "true" ]; then
2125
+ # The failure comment names what blocked the later steps instead of showing them as waiting
2126
+ echo "missing=$ITEMS" >> "$GITHUB_OUTPUT"
2109
2127
  exit 1
2110
2128
  fi
2111
2129
  m wf_preview.precheck_ok
@@ -2162,7 +2180,7 @@ jobs:
2162
2180
  PAW_IN_STEPS_PROGRESS_OUTPUTS_DOCKER_START: ${{ steps.progress.outputs.docker_start }}
2163
2181
  with:
2164
2182
  script: |
2165
- const M = JSON.parse(process.env.PAW_MSG);
2183
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
2166
2184
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
2167
2185
 
2168
2186
  const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
@@ -2351,7 +2369,7 @@ jobs:
2351
2369
  PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START: ${{ steps.docker_progress.outputs.deploy_start }}
2352
2370
  with:
2353
2371
  script: |
2354
- const M = JSON.parse(process.env.PAW_MSG);
2372
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
2355
2373
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
2356
2374
 
2357
2375
  const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
@@ -2434,9 +2452,11 @@ jobs:
2434
2452
  PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
2435
2453
  PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
2436
2454
  PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
2455
+ PAW_IN_STEPS_PRECHECK_OUTCOME: ${{ steps.precheck.outcome }}
2456
+ PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING: ${{ steps.precheck.outputs.missing }}
2437
2457
  with:
2438
2458
  script: |
2439
- const M = JSON.parse(process.env.PAW_MSG);
2459
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
2440
2460
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
2441
2461
 
2442
2462
  const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
@@ -2451,9 +2471,13 @@ jobs:
2451
2471
  if (!commentId) {
2452
2472
  dockerStatus = m('wf_preview.status_init_failed');
2453
2473
  deployStatus = '-';
2474
+ } else if (process.env.PAW_IN_STEPS_PRECHECK_OUTCOME === 'failure') {
2475
+ // The pre-check stopped the run before any build step: say why nothing ran
2476
+ dockerStatus = deployStatus = m('wf_preview.status_precheck_blocked', { missing: process.env.PAW_IN_STEPS_PRECHECK_OUTPUTS_MISSING || '-' });
2454
2477
  } else if (!dockerDuration || dockerDuration === '') {
2478
+ // Failed at the Docker build stage; the deploy step never ran
2455
2479
  dockerStatus = m('wf_preview.status_failed');
2456
- deployStatus = m('wf_preview.status_waiting');
2480
+ deployStatus = m('wf_preview.status_not_run');
2457
2481
  } else {
2458
2482
  dockerStatus = m('wf_preview.status_done');
2459
2483
  deployStatus = m('wf_preview.status_failed');
@@ -2536,10 +2560,8 @@ jobs:
2536
2560
  rm -rf .paw-msg
2537
2561
  # The workspace root has no version.yml; pass the language resolved above to every later messages.py call
2538
2562
  export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
2539
- {
2540
- echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
2541
- echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
2542
- } >> "$GITHUB_ENV"
2563
+ python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
2564
+ echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
2543
2565
  # The deploy script runs on the remote server, where messages.py does not exist:
2544
2566
  # ship the messages it needs as a small shell function (m KEY name=value ...)
2545
2567
  python3 - >> "$GITHUB_ENV" <<'PY'
@@ -2598,7 +2620,7 @@ jobs:
2598
2620
  PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
2599
2621
  with:
2600
2622
  script: |
2601
- const M = JSON.parse(process.env.PAW_MSG);
2623
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
2602
2624
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
2603
2625
 
2604
2626
  const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
@@ -2682,7 +2704,7 @@ jobs:
2682
2704
  PAW_IN_STEPS_CONTAINER_INFO_OUTPUTS_CONTAINER_NAME: ${{ steps.container_info.outputs.container_name }}
2683
2705
  with:
2684
2706
  script: |
2685
- const M = JSON.parse(process.env.PAW_MSG);
2707
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
2686
2708
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
2687
2709
 
2688
2710
  const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
@@ -2743,10 +2765,8 @@ jobs:
2743
2765
  rm -rf .paw-msg
2744
2766
  # The workspace root has no version.yml; pass the language resolved above to every later messages.py call
2745
2767
  export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
2746
- {
2747
- echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
2748
- echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
2749
- } >> "$GITHUB_ENV"
2768
+ python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview. > "$RUNNER_TEMP/paw-msg.json"
2769
+ echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE" >> "$GITHUB_ENV"
2750
2770
  # The deploy script runs on the remote server, where messages.py does not exist:
2751
2771
  # ship the messages it needs as a small shell function (m KEY name=value ...)
2752
2772
  python3 - >> "$GITHUB_ENV" <<'PY'
@@ -2867,7 +2887,7 @@ jobs:
2867
2887
  PAW_IN_STEPS_CONTAINER_INFO_OUTPUTS_CONTAINER_NAME: ${{ steps.container_info.outputs.container_name }}
2868
2888
  with:
2869
2889
  script: |
2870
- const M = JSON.parse(process.env.PAW_MSG);
2890
+ const M = JSON.parse(require('fs').readFileSync(`${process.env.RUNNER_TEMP}/paw-msg.json`, 'utf8'));
2871
2891
  const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
2872
2892
 
2873
2893
  const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
@@ -147,6 +147,8 @@ jobs:
147
147
  - name: Build verification complete
148
148
  env:
149
149
  PAW_REF_NAME: ${{ github.ref_name }}
150
+ # On a PR, github.sha is the temporary merge commit; show the PR head commit instead
151
+ PAW_COMMIT_SHA: ${{ github.event.pull_request.head.sha || github.sha }}
150
152
  run: |
151
153
  [ -f "$GITHUB_WORKSPACE/.github/scripts/messages.py" ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
152
154
  m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
@@ -155,7 +157,7 @@ jobs:
155
157
  m cibuild.info_title
156
158
  m cibuild.info_project project="${{ env.PROJECT_NAME }}"
157
159
  m cibuild.info_branch branch="$PAW_REF_NAME"
158
- m cibuild.info_commit sha="${{ github.sha }}"
160
+ m cibuild.info_commit sha="$(echo "$PAW_COMMIT_SHA" | cut -c1-7)"
159
161
  m cibuild.info_time time="$(date -u '+%Y-%m-%d %H:%M:%S UTC')"
160
162
 
161
163
  # CI Gate: the single job to register as a required check