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
|
@@ -108,6 +108,8 @@ jobs:
|
|
|
108
108
|
uses: actions/checkout@v7
|
|
109
109
|
with:
|
|
110
110
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
111
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
112
|
+
path: .paw-msg
|
|
111
113
|
sparse-checkout: |
|
|
112
114
|
.github/scripts/messages.py
|
|
113
115
|
version.yml
|
|
@@ -115,11 +117,16 @@ jobs:
|
|
|
115
117
|
|
|
116
118
|
- name: Load messages
|
|
117
119
|
run: |
|
|
118
|
-
# Keep a copy outside the workspace
|
|
120
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
119
121
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
120
|
-
|
|
122
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
123
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
124
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
125
|
+
rm -rf .paw-msg
|
|
126
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
127
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
121
128
|
{
|
|
122
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
129
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
123
130
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
124
131
|
} >> "$GITHUB_ENV"
|
|
125
132
|
|
|
@@ -210,18 +217,26 @@ jobs:
|
|
|
210
217
|
uses: actions/checkout@v7
|
|
211
218
|
with:
|
|
212
219
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
220
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
221
|
+
path: .paw-msg
|
|
213
222
|
sparse-checkout: |
|
|
214
223
|
.github/scripts/messages.py
|
|
215
224
|
version.yml
|
|
216
225
|
sparse-checkout-cone-mode: false
|
|
217
226
|
|
|
218
227
|
- name: Load messages
|
|
228
|
+
id: load_messages
|
|
219
229
|
run: |
|
|
220
|
-
# Keep a copy outside the workspace
|
|
230
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
221
231
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
222
|
-
|
|
232
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
233
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
234
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
235
|
+
rm -rf .paw-msg
|
|
236
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
237
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
223
238
|
{
|
|
224
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
239
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
225
240
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
226
241
|
} >> "$GITHUB_ENV"
|
|
227
242
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -399,13 +414,16 @@ jobs:
|
|
|
399
414
|
- name: Progress - build done
|
|
400
415
|
id: build_progress
|
|
401
416
|
uses: actions/github-script@v9
|
|
417
|
+
env:
|
|
418
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
419
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_START_TIME: ${{ steps.progress.outputs.start_time }}
|
|
402
420
|
with:
|
|
403
421
|
script: |
|
|
404
422
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
405
423
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
406
424
|
|
|
407
|
-
const commentId =
|
|
408
|
-
const startTime =
|
|
425
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
426
|
+
const startTime = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_START_TIME, 10) || Date.now();
|
|
409
427
|
const now = Date.now();
|
|
410
428
|
const elapsed = now - startTime;
|
|
411
429
|
const minutes = Math.floor(elapsed / 60000);
|
|
@@ -439,16 +457,16 @@ jobs:
|
|
|
439
457
|
core.setOutput('docker_start', now);
|
|
440
458
|
|
|
441
459
|
- name: Log in to Docker Hub
|
|
442
|
-
uses: docker/login-action@
|
|
460
|
+
uses: docker/login-action@v4
|
|
443
461
|
with:
|
|
444
462
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
445
463
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
446
464
|
|
|
447
465
|
- name: Set up Docker Buildx
|
|
448
|
-
uses: docker/setup-buildx-action@
|
|
466
|
+
uses: docker/setup-buildx-action@v4
|
|
449
467
|
|
|
450
468
|
- name: Build & push Docker image
|
|
451
|
-
uses: docker/build-push-action@
|
|
469
|
+
uses: docker/build-push-action@v7
|
|
452
470
|
with:
|
|
453
471
|
context: ${{ env.PROJECT_PATH }}
|
|
454
472
|
file: ${{ env.PROJECT_PATH }}/${{ env.DOCKERFILE_PATH }}
|
|
@@ -460,14 +478,18 @@ jobs:
|
|
|
460
478
|
- name: Progress - Docker done
|
|
461
479
|
id: docker_progress
|
|
462
480
|
uses: actions/github-script@v9
|
|
481
|
+
env:
|
|
482
|
+
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.build_progress.outputs.build_duration }}
|
|
483
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
484
|
+
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_DOCKER_START: ${{ steps.build_progress.outputs.docker_start }}
|
|
463
485
|
with:
|
|
464
486
|
script: |
|
|
465
487
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
466
488
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
467
489
|
|
|
468
|
-
const commentId =
|
|
469
|
-
const buildDuration =
|
|
470
|
-
const dockerStart =
|
|
490
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
491
|
+
const buildDuration = process.env.PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION;
|
|
492
|
+
const dockerStart = parseInt(process.env.PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_DOCKER_START, 10) || Date.now();
|
|
471
493
|
const now = Date.now();
|
|
472
494
|
const dockerElapsed = now - dockerStart;
|
|
473
495
|
const minutes = Math.floor(dockerElapsed / 60000);
|
|
@@ -645,29 +667,36 @@ jobs:
|
|
|
645
667
|
|
|
646
668
|
- name: Deploy complete comment
|
|
647
669
|
uses: actions/github-script@v9
|
|
670
|
+
env:
|
|
671
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.docker_progress.outputs.build_duration }}
|
|
672
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
673
|
+
PAW_IN_STEPS_PR_OUTPUTS_REF: ${{ steps.pr.outputs.ref }}
|
|
674
|
+
PAW_IN_STEPS_PR_OUTPUTS_SHA: ${{ steps.pr.outputs.sha }}
|
|
675
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
676
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START: ${{ steps.docker_progress.outputs.deploy_start }}
|
|
648
677
|
with:
|
|
649
678
|
script: |
|
|
650
679
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
651
680
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
652
681
|
|
|
653
|
-
const commentId =
|
|
654
|
-
const buildDuration =
|
|
655
|
-
const dockerDuration =
|
|
656
|
-
const deployStart =
|
|
682
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
683
|
+
const buildDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_BUILD_DURATION;
|
|
684
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
685
|
+
const deployStart = parseInt(process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START, 10) || Date.now();
|
|
657
686
|
const now = Date.now();
|
|
658
687
|
const deployElapsed = now - deployStart;
|
|
659
688
|
const minutes = Math.floor(deployElapsed / 60000);
|
|
660
689
|
const seconds = Math.floor((deployElapsed % 60000) / 1000);
|
|
661
690
|
const deployDuration = minutes > 0 ? m('wf_preview.dur_min_sec', {minutes, seconds}) : m('wf_preview.dur_sec', {seconds});
|
|
662
691
|
|
|
663
|
-
const projectName =
|
|
664
|
-
const domainSuffix =
|
|
665
|
-
const previewPort =
|
|
666
|
-
const apiDocsPath =
|
|
692
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
693
|
+
const domainSuffix = process.env.PREVIEW_DOMAIN_SUFFIX;
|
|
694
|
+
const previewPort = process.env.PREVIEW_PORT;
|
|
695
|
+
const apiDocsPath = process.env.API_DOCS_PATH;
|
|
667
696
|
const prNumber = context.issue.number;
|
|
668
697
|
const domain = `${projectName}-pr-${prNumber}.${domainSuffix}`;
|
|
669
698
|
const previewUrl = `http://${domain}:${previewPort}`;
|
|
670
|
-
const sha =
|
|
699
|
+
const sha = process.env.PAW_IN_STEPS_PR_OUTPUTS_SHA;
|
|
671
700
|
|
|
672
701
|
// Build the preview environment table (the API Docs row is added only when API_DOCS_PATH is set)
|
|
673
702
|
const envRows = [
|
|
@@ -679,7 +708,7 @@ jobs:
|
|
|
679
708
|
envRows.push(m('wf_preview.env_container_pr', {projectName, prNumber}));
|
|
680
709
|
envRows.push(m('wf_preview.env_commit', {sha}));
|
|
681
710
|
|
|
682
|
-
const branchName =
|
|
711
|
+
const branchName = process.env.PAW_IN_STEPS_PR_OUTPUTS_REF;
|
|
683
712
|
|
|
684
713
|
const body = [
|
|
685
714
|
m('wf_preview.title_pr_deployed'),
|
|
@@ -724,21 +753,25 @@ jobs:
|
|
|
724
753
|
});
|
|
725
754
|
|
|
726
755
|
- name: Build/deploy failure comment
|
|
727
|
-
if: failure()
|
|
756
|
+
if: failure() && steps.load_messages.outcome == 'success'
|
|
728
757
|
uses: actions/github-script@v9
|
|
758
|
+
env:
|
|
759
|
+
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.build_progress.outputs.build_duration }}
|
|
760
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
761
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
729
762
|
with:
|
|
730
763
|
script: |
|
|
731
764
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
732
765
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
733
766
|
|
|
734
|
-
const commentId =
|
|
735
|
-
const projectName =
|
|
767
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
768
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
736
769
|
const prNumber = context.issue.number;
|
|
737
770
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
|
|
738
771
|
|
|
739
772
|
// Show where it failed based on progress
|
|
740
|
-
const buildDuration =
|
|
741
|
-
const dockerDuration =
|
|
773
|
+
const buildDuration = process.env.PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION;
|
|
774
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
742
775
|
|
|
743
776
|
// Work out where it failed - early-stage failures are distinguished too
|
|
744
777
|
let buildStatus, dockerStatus, deployStatus;
|
|
@@ -832,6 +865,8 @@ jobs:
|
|
|
832
865
|
uses: actions/checkout@v7
|
|
833
866
|
with:
|
|
834
867
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
868
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
869
|
+
path: .paw-msg
|
|
835
870
|
sparse-checkout: |
|
|
836
871
|
.github/scripts/messages.py
|
|
837
872
|
version.yml
|
|
@@ -839,11 +874,16 @@ jobs:
|
|
|
839
874
|
|
|
840
875
|
- name: Load messages
|
|
841
876
|
run: |
|
|
842
|
-
# Keep a copy outside the workspace
|
|
877
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
843
878
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
844
|
-
|
|
879
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
880
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
881
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
882
|
+
rm -rf .paw-msg
|
|
883
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
884
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
845
885
|
{
|
|
846
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
886
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
847
887
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
848
888
|
} >> "$GITHUB_ENV"
|
|
849
889
|
|
|
@@ -856,7 +896,7 @@ jobs:
|
|
|
856
896
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
857
897
|
|
|
858
898
|
const issueNumber = context.issue.number;
|
|
859
|
-
const marker =
|
|
899
|
+
const marker = process.env.ISSUE_HELPER_MARKER;
|
|
860
900
|
|
|
861
901
|
console.log(m('wf_preview.log_search_branch', {issueNumber}));
|
|
862
902
|
console.log(m('wf_preview.log_marker', {marker}));
|
|
@@ -901,7 +941,7 @@ jobs:
|
|
|
901
941
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
902
942
|
|
|
903
943
|
const issueNumber = context.issue.number;
|
|
904
|
-
const marker =
|
|
944
|
+
const marker = process.env.ISSUE_HELPER_MARKER;
|
|
905
945
|
|
|
906
946
|
const body = [
|
|
907
947
|
m('wf_preview.title_branch_missing_warn'),
|
|
@@ -945,18 +985,26 @@ jobs:
|
|
|
945
985
|
uses: actions/checkout@v7
|
|
946
986
|
with:
|
|
947
987
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
988
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
989
|
+
path: .paw-msg
|
|
948
990
|
sparse-checkout: |
|
|
949
991
|
.github/scripts/messages.py
|
|
950
992
|
version.yml
|
|
951
993
|
sparse-checkout-cone-mode: false
|
|
952
994
|
|
|
953
995
|
- name: Load messages
|
|
996
|
+
id: load_messages
|
|
954
997
|
run: |
|
|
955
|
-
# Keep a copy outside the workspace
|
|
998
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
956
999
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
957
|
-
|
|
1000
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
1001
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
1002
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
1003
|
+
rm -rf .paw-msg
|
|
1004
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
1005
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
958
1006
|
{
|
|
959
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
1007
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
960
1008
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
961
1009
|
} >> "$GITHUB_ENV"
|
|
962
1010
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -986,13 +1034,16 @@ jobs:
|
|
|
986
1034
|
- name: Check branch exists
|
|
987
1035
|
id: check_branch
|
|
988
1036
|
uses: actions/github-script@v9
|
|
1037
|
+
env:
|
|
1038
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1039
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
989
1040
|
with:
|
|
990
1041
|
script: |
|
|
991
1042
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
992
1043
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
993
1044
|
|
|
994
|
-
const branchName =
|
|
995
|
-
const issueNumber =
|
|
1045
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
1046
|
+
const issueNumber = parseInt(process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER, 10) || 0;
|
|
996
1047
|
|
|
997
1048
|
console.log(m('wf_preview.log_check_exists', {branchName}));
|
|
998
1049
|
|
|
@@ -1049,23 +1100,28 @@ jobs:
|
|
|
1049
1100
|
- name: Set issue info
|
|
1050
1101
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1051
1102
|
id: issue
|
|
1103
|
+
env:
|
|
1104
|
+
PAW_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1052
1105
|
run: |
|
|
1053
|
-
echo "ref=$
|
|
1106
|
+
echo "ref=$PAW_BRANCH_NAME" >> $GITHUB_OUTPUT
|
|
1054
1107
|
echo "issue_number=${{ needs.get-branch-from-issue.outputs.issue_number }}" >> $GITHUB_OUTPUT
|
|
1055
1108
|
# Get the latest commit SHA of the branch
|
|
1056
|
-
echo "sha=$(git ls-remote https://github.com/${{ github.repository }}.git refs/heads/$
|
|
1109
|
+
echo "sha=$(git ls-remote https://github.com/${{ github.repository }}.git "refs/heads/$PAW_BRANCH_NAME" | cut -c1-7)" >> $GITHUB_OUTPUT
|
|
1057
1110
|
|
|
1058
1111
|
- name: Create progress comment
|
|
1059
1112
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1060
1113
|
id: progress
|
|
1061
1114
|
uses: actions/github-script@v9
|
|
1115
|
+
env:
|
|
1116
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1117
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
1062
1118
|
with:
|
|
1063
1119
|
script: |
|
|
1064
1120
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1065
1121
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1066
1122
|
|
|
1067
|
-
const issueNumber =
|
|
1068
|
-
const branchName =
|
|
1123
|
+
const issueNumber = parseInt(process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER, 10) || 0;
|
|
1124
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
1069
1125
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
|
|
1070
1126
|
const startTime = Date.now();
|
|
1071
1127
|
|
|
@@ -1173,14 +1229,18 @@ jobs:
|
|
|
1173
1229
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1174
1230
|
id: build_progress
|
|
1175
1231
|
uses: actions/github-script@v9
|
|
1232
|
+
env:
|
|
1233
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1234
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
1235
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_START_TIME: ${{ steps.progress.outputs.start_time }}
|
|
1176
1236
|
with:
|
|
1177
1237
|
script: |
|
|
1178
1238
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1179
1239
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1180
1240
|
|
|
1181
|
-
const commentId =
|
|
1182
|
-
const branchName =
|
|
1183
|
-
const startTime =
|
|
1241
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
1242
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
1243
|
+
const startTime = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_START_TIME, 10) || Date.now();
|
|
1184
1244
|
const now = Date.now();
|
|
1185
1245
|
const elapsed = now - startTime;
|
|
1186
1246
|
const minutes = Math.floor(elapsed / 60000);
|
|
@@ -1217,18 +1277,18 @@ jobs:
|
|
|
1217
1277
|
|
|
1218
1278
|
- name: Log in to Docker Hub
|
|
1219
1279
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1220
|
-
uses: docker/login-action@
|
|
1280
|
+
uses: docker/login-action@v4
|
|
1221
1281
|
with:
|
|
1222
1282
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
1223
1283
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
1224
1284
|
|
|
1225
1285
|
- name: Set up Docker Buildx
|
|
1226
1286
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1227
|
-
uses: docker/setup-buildx-action@
|
|
1287
|
+
uses: docker/setup-buildx-action@v4
|
|
1228
1288
|
|
|
1229
1289
|
- name: Build & push Docker image
|
|
1230
1290
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1231
|
-
uses: docker/build-push-action@
|
|
1291
|
+
uses: docker/build-push-action@v7
|
|
1232
1292
|
with:
|
|
1233
1293
|
context: ${{ env.PROJECT_PATH }}
|
|
1234
1294
|
file: ${{ env.PROJECT_PATH }}/${{ env.DOCKERFILE_PATH }}
|
|
@@ -1241,15 +1301,20 @@ jobs:
|
|
|
1241
1301
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1242
1302
|
id: docker_progress
|
|
1243
1303
|
uses: actions/github-script@v9
|
|
1304
|
+
env:
|
|
1305
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1306
|
+
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.build_progress.outputs.build_duration }}
|
|
1307
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
1308
|
+
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_DOCKER_START: ${{ steps.build_progress.outputs.docker_start }}
|
|
1244
1309
|
with:
|
|
1245
1310
|
script: |
|
|
1246
1311
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1247
1312
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1248
1313
|
|
|
1249
|
-
const commentId =
|
|
1250
|
-
const branchName =
|
|
1251
|
-
const buildDuration =
|
|
1252
|
-
const dockerStart =
|
|
1314
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
1315
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
1316
|
+
const buildDuration = process.env.PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION;
|
|
1317
|
+
const dockerStart = parseInt(process.env.PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_DOCKER_START, 10) || Date.now();
|
|
1253
1318
|
const now = Date.now();
|
|
1254
1319
|
const dockerElapsed = now - dockerStart;
|
|
1255
1320
|
const minutes = Math.floor(dockerElapsed / 60000);
|
|
@@ -1431,30 +1496,38 @@ jobs:
|
|
|
1431
1496
|
- name: Deploy complete comment
|
|
1432
1497
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1433
1498
|
uses: actions/github-script@v9
|
|
1499
|
+
env:
|
|
1500
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1501
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.docker_progress.outputs.build_duration }}
|
|
1502
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
1503
|
+
PAW_IN_STEPS_ISSUE_OUTPUTS_SHA: ${{ steps.issue.outputs.sha }}
|
|
1504
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
1505
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START: ${{ steps.docker_progress.outputs.deploy_start }}
|
|
1506
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
1434
1507
|
with:
|
|
1435
1508
|
script: |
|
|
1436
1509
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1437
1510
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1438
1511
|
|
|
1439
|
-
const commentId =
|
|
1440
|
-
const branchName =
|
|
1441
|
-
const buildDuration =
|
|
1442
|
-
const dockerDuration =
|
|
1443
|
-
const deployStart =
|
|
1512
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
1513
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
1514
|
+
const buildDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_BUILD_DURATION;
|
|
1515
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
1516
|
+
const deployStart = parseInt(process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START, 10) || Date.now();
|
|
1444
1517
|
const now = Date.now();
|
|
1445
1518
|
const deployElapsed = now - deployStart;
|
|
1446
1519
|
const minutes = Math.floor(deployElapsed / 60000);
|
|
1447
1520
|
const seconds = Math.floor((deployElapsed % 60000) / 1000);
|
|
1448
1521
|
const deployDuration = minutes > 0 ? m('wf_preview.dur_min_sec', {minutes, seconds}) : m('wf_preview.dur_sec', {seconds});
|
|
1449
1522
|
|
|
1450
|
-
const projectName =
|
|
1451
|
-
const domainSuffix =
|
|
1452
|
-
const previewPort =
|
|
1453
|
-
const apiDocsPath =
|
|
1454
|
-
const issueNumber =
|
|
1523
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
1524
|
+
const domainSuffix = process.env.PREVIEW_DOMAIN_SUFFIX;
|
|
1525
|
+
const previewPort = process.env.PREVIEW_PORT;
|
|
1526
|
+
const apiDocsPath = process.env.API_DOCS_PATH;
|
|
1527
|
+
const issueNumber = parseInt(process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER, 10) || 0;
|
|
1455
1528
|
const domain = `${projectName}-pr-${issueNumber}.${domainSuffix}`;
|
|
1456
1529
|
const previewUrl = `http://${domain}:${previewPort}`;
|
|
1457
|
-
const sha =
|
|
1530
|
+
const sha = process.env.PAW_IN_STEPS_ISSUE_OUTPUTS_SHA;
|
|
1458
1531
|
|
|
1459
1532
|
// Build the preview environment table (the API Docs row is added only when API_DOCS_PATH is set)
|
|
1460
1533
|
const envRows = [
|
|
@@ -1512,21 +1585,27 @@ jobs:
|
|
|
1512
1585
|
});
|
|
1513
1586
|
|
|
1514
1587
|
- name: Build/deploy failure comment
|
|
1515
|
-
if: failure() && steps.check_branch.outputs.exists == 'true'
|
|
1588
|
+
if: failure() && steps.load_messages.outcome == 'success' && steps.check_branch.outputs.exists == 'true'
|
|
1516
1589
|
uses: actions/github-script@v9
|
|
1590
|
+
env:
|
|
1591
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1592
|
+
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.build_progress.outputs.build_duration }}
|
|
1593
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
1594
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
1595
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
1517
1596
|
with:
|
|
1518
1597
|
script: |
|
|
1519
1598
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1520
1599
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1521
1600
|
|
|
1522
|
-
const commentId =
|
|
1523
|
-
const projectName =
|
|
1524
|
-
const issueNumber =
|
|
1525
|
-
const branchName =
|
|
1601
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
1602
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
1603
|
+
const issueNumber = parseInt(process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER, 10) || 0;
|
|
1604
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
1526
1605
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
|
|
1527
1606
|
|
|
1528
|
-
const buildDuration =
|
|
1529
|
-
const dockerDuration =
|
|
1607
|
+
const buildDuration = process.env.PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION;
|
|
1608
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
1530
1609
|
|
|
1531
1610
|
let buildStatus, dockerStatus, deployStatus;
|
|
1532
1611
|
let buildTime = '-', dockerTime = '-';
|
|
@@ -1612,6 +1691,8 @@ jobs:
|
|
|
1612
1691
|
uses: actions/checkout@v7
|
|
1613
1692
|
with:
|
|
1614
1693
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
1694
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
1695
|
+
path: .paw-msg
|
|
1615
1696
|
sparse-checkout: |
|
|
1616
1697
|
.github/scripts/messages.py
|
|
1617
1698
|
version.yml
|
|
@@ -1619,11 +1700,16 @@ jobs:
|
|
|
1619
1700
|
|
|
1620
1701
|
- name: Load messages
|
|
1621
1702
|
run: |
|
|
1622
|
-
# Keep a copy outside the workspace
|
|
1703
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
1623
1704
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
1624
|
-
|
|
1705
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
1706
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
1707
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
1708
|
+
rm -rf .paw-msg
|
|
1709
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
1710
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
1625
1711
|
{
|
|
1626
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
1712
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
1627
1713
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
1628
1714
|
} >> "$GITHUB_ENV"
|
|
1629
1715
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -1650,6 +1736,41 @@ jobs:
|
|
|
1650
1736
|
print("PAW_EOF")
|
|
1651
1737
|
PY
|
|
1652
1738
|
|
|
1739
|
+
# Without the deploy secrets no preview could have been deployed: on close events skip the cleanup quietly,
|
|
1740
|
+
# and on an explicit command report what is missing instead of surfacing a raw SSH action error
|
|
1741
|
+
- name: Deploy pre-check (Secrets)
|
|
1742
|
+
id: precheck
|
|
1743
|
+
env:
|
|
1744
|
+
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
1745
|
+
SERVER_HOST: ${{ secrets.SERVER_HOST }}
|
|
1746
|
+
SERVER_USER: ${{ secrets.SERVER_USER }}
|
|
1747
|
+
SERVER_PASSWORD: ${{ secrets.SERVER_PASSWORD }}
|
|
1748
|
+
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
1749
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
1750
|
+
run: |
|
|
1751
|
+
m() { python3 "$RUNNER_TEMP/paw/messages.py" get "$@"; }
|
|
1752
|
+
|
|
1753
|
+
MISSING=""
|
|
1754
|
+
for NAME in DOCKERHUB_USERNAME SERVER_HOST SERVER_USER; do
|
|
1755
|
+
[ -n "${!NAME}" ] || MISSING="$MISSING $NAME"
|
|
1756
|
+
done
|
|
1757
|
+
# SSH_KEY is required when SSH_AUTH_METHOD=key, otherwise SERVER_PASSWORD
|
|
1758
|
+
if [ "${SSH_AUTH_METHOD:-password}" = "key" ]; then
|
|
1759
|
+
[ -n "$SSH_KEY" ] || MISSING="$MISSING SSH_KEY"
|
|
1760
|
+
else
|
|
1761
|
+
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
1762
|
+
fi
|
|
1763
|
+
if [ -n "$MISSING" ]; then
|
|
1764
|
+
if [ "$EVENT_NAME" = "issue_comment" ]; then
|
|
1765
|
+
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
1766
|
+
exit 1
|
|
1767
|
+
fi
|
|
1768
|
+
echo "::warning title=$(m wf_preview.precheck_skip_title)::$(m wf_preview.precheck_skip_body missing="$MISSING")"
|
|
1769
|
+
echo "ready=false" >> "$GITHUB_OUTPUT"
|
|
1770
|
+
exit 0
|
|
1771
|
+
fi
|
|
1772
|
+
echo "ready=true" >> "$GITHUB_OUTPUT"
|
|
1773
|
+
|
|
1653
1774
|
- name: Get PR/issue number
|
|
1654
1775
|
id: pr_number
|
|
1655
1776
|
run: |
|
|
@@ -1665,6 +1786,7 @@ jobs:
|
|
|
1665
1786
|
fi
|
|
1666
1787
|
|
|
1667
1788
|
- name: Remove container & image
|
|
1789
|
+
if: steps.precheck.outputs.ready == 'true'
|
|
1668
1790
|
uses: appleboy/ssh-action@v1.0.3
|
|
1669
1791
|
with:
|
|
1670
1792
|
host: ${{ secrets.SERVER_HOST }}
|
|
@@ -1710,17 +1832,20 @@ jobs:
|
|
|
1710
1832
|
|
|
1711
1833
|
- name: Destroy complete comment
|
|
1712
1834
|
if: |
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1835
|
+
steps.precheck.outputs.ready == 'true' && (
|
|
1836
|
+
github.event_name == 'issue_comment' ||
|
|
1837
|
+
(github.event_name == 'pull_request' && github.event.action == 'closed') ||
|
|
1838
|
+
(github.event_name == 'issues' && github.event.action == 'closed'))
|
|
1716
1839
|
uses: actions/github-script@v9
|
|
1840
|
+
env:
|
|
1841
|
+
PAW_IN_STEPS_PR_NUMBER_OUTPUTS_NUMBER: ${{ steps.pr_number.outputs.number }}
|
|
1717
1842
|
with:
|
|
1718
1843
|
script: |
|
|
1719
1844
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1720
1845
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1721
1846
|
|
|
1722
|
-
const number =
|
|
1723
|
-
const projectName =
|
|
1847
|
+
const number = parseInt(process.env.PAW_IN_STEPS_PR_NUMBER_OUTPUTS_NUMBER, 10) || 0;
|
|
1848
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
1724
1849
|
|
|
1725
1850
|
const body = [
|
|
1726
1851
|
m('wf_preview.title_destroyed'),
|
|
@@ -1756,6 +1881,8 @@ jobs:
|
|
|
1756
1881
|
uses: actions/checkout@v7
|
|
1757
1882
|
with:
|
|
1758
1883
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
1884
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
1885
|
+
path: .paw-msg
|
|
1759
1886
|
sparse-checkout: |
|
|
1760
1887
|
.github/scripts/messages.py
|
|
1761
1888
|
version.yml
|
|
@@ -1763,11 +1890,16 @@ jobs:
|
|
|
1763
1890
|
|
|
1764
1891
|
- name: Load messages
|
|
1765
1892
|
run: |
|
|
1766
|
-
# Keep a copy outside the workspace
|
|
1893
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
1767
1894
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
1768
|
-
|
|
1895
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
1896
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
1897
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
1898
|
+
rm -rf .paw-msg
|
|
1899
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
1900
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
1769
1901
|
{
|
|
1770
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
1902
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
1771
1903
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
1772
1904
|
} >> "$GITHUB_ENV"
|
|
1773
1905
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -1794,6 +1926,32 @@ jobs:
|
|
|
1794
1926
|
print("PAW_EOF")
|
|
1795
1927
|
PY
|
|
1796
1928
|
|
|
1929
|
+
# Report the missing secrets by name instead of surfacing a raw SSH action error
|
|
1930
|
+
- name: Deploy pre-check (Secrets)
|
|
1931
|
+
id: precheck
|
|
1932
|
+
env:
|
|
1933
|
+
SERVER_HOST: ${{ secrets.SERVER_HOST }}
|
|
1934
|
+
SERVER_USER: ${{ secrets.SERVER_USER }}
|
|
1935
|
+
SERVER_PASSWORD: ${{ secrets.SERVER_PASSWORD }}
|
|
1936
|
+
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
1937
|
+
run: |
|
|
1938
|
+
m() { python3 "$RUNNER_TEMP/paw/messages.py" get "$@"; }
|
|
1939
|
+
|
|
1940
|
+
MISSING=""
|
|
1941
|
+
for NAME in SERVER_HOST SERVER_USER; do
|
|
1942
|
+
[ -n "${!NAME}" ] || MISSING="$MISSING $NAME"
|
|
1943
|
+
done
|
|
1944
|
+
# SSH_KEY is required when SSH_AUTH_METHOD=key, otherwise SERVER_PASSWORD
|
|
1945
|
+
if [ "${SSH_AUTH_METHOD:-password}" = "key" ]; then
|
|
1946
|
+
[ -n "$SSH_KEY" ] || MISSING="$MISSING SSH_KEY"
|
|
1947
|
+
else
|
|
1948
|
+
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
1949
|
+
fi
|
|
1950
|
+
if [ -n "$MISSING" ]; then
|
|
1951
|
+
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
1952
|
+
exit 1
|
|
1953
|
+
fi
|
|
1954
|
+
|
|
1797
1955
|
- name: Check container status
|
|
1798
1956
|
id: status
|
|
1799
1957
|
uses: appleboy/ssh-action@v1.0.3
|
|
@@ -1845,19 +2003,22 @@ jobs:
|
|
|
1845
2003
|
|
|
1846
2004
|
- name: Post status comment
|
|
1847
2005
|
uses: actions/github-script@v9
|
|
2006
|
+
env:
|
|
2007
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_IS_PR: ${{ needs.check-command.outputs.is_pr }}
|
|
2008
|
+
PAW_IN_STEPS_CHECK_RUNNING_OUTCOME: ${{ steps.check_running.outcome }}
|
|
1848
2009
|
with:
|
|
1849
2010
|
script: |
|
|
1850
2011
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1851
2012
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1852
2013
|
|
|
1853
2014
|
const number = context.issue.number;
|
|
1854
|
-
const projectName =
|
|
1855
|
-
const domainSuffix =
|
|
1856
|
-
const previewPort =
|
|
2015
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
2016
|
+
const domainSuffix = process.env.PREVIEW_DOMAIN_SUFFIX;
|
|
2017
|
+
const previewPort = process.env.PREVIEW_PORT;
|
|
1857
2018
|
const domain = `${projectName}-pr-${number}.${domainSuffix}`;
|
|
1858
2019
|
const previewUrl = `http://${domain}:${previewPort}`;
|
|
1859
|
-
const isRunning =
|
|
1860
|
-
const isPr =
|
|
2020
|
+
const isRunning = process.env.PAW_IN_STEPS_CHECK_RUNNING_OUTCOME === 'success';
|
|
2021
|
+
const isPr = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_IS_PR === 'true';
|
|
1861
2022
|
const contextType = isPr ? 'PR' : 'Issue';
|
|
1862
2023
|
|
|
1863
2024
|
let body;
|
|
@@ -1922,18 +2083,26 @@ jobs:
|
|
|
1922
2083
|
uses: actions/checkout@v7
|
|
1923
2084
|
with:
|
|
1924
2085
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
2086
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
2087
|
+
path: .paw-msg
|
|
1925
2088
|
sparse-checkout: |
|
|
1926
2089
|
.github/scripts/messages.py
|
|
1927
2090
|
version.yml
|
|
1928
2091
|
sparse-checkout-cone-mode: false
|
|
1929
2092
|
|
|
1930
2093
|
- name: Load messages
|
|
2094
|
+
id: load_messages
|
|
1931
2095
|
run: |
|
|
1932
|
-
# Keep a copy outside the workspace
|
|
2096
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
1933
2097
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
1934
|
-
|
|
2098
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
2099
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
2100
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
2101
|
+
rm -rf .paw-msg
|
|
2102
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
2103
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
1935
2104
|
{
|
|
1936
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
2105
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
1937
2106
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
1938
2107
|
} >> "$GITHUB_ENV"
|
|
1939
2108
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -1963,9 +2132,11 @@ jobs:
|
|
|
1963
2132
|
- name: Extract issue number from branch name
|
|
1964
2133
|
id: extract
|
|
1965
2134
|
uses: actions/github-script@v9
|
|
2135
|
+
env:
|
|
2136
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
1966
2137
|
with:
|
|
1967
2138
|
script: |
|
|
1968
|
-
const branchName =
|
|
2139
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
1969
2140
|
const issueMatch = branchName.match(/#(\d+)/);
|
|
1970
2141
|
|
|
1971
2142
|
if (issueMatch) {
|
|
@@ -1990,9 +2161,11 @@ jobs:
|
|
|
1990
2161
|
- name: Check branch exists
|
|
1991
2162
|
id: check_branch
|
|
1992
2163
|
uses: actions/github-script@v9
|
|
2164
|
+
env:
|
|
2165
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
1993
2166
|
with:
|
|
1994
2167
|
script: |
|
|
1995
|
-
const branchName =
|
|
2168
|
+
const branchName = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME;
|
|
1996
2169
|
try {
|
|
1997
2170
|
await github.rest.repos.getBranch({
|
|
1998
2171
|
owner: context.repo.owner,
|
|
@@ -2011,12 +2184,14 @@ jobs:
|
|
|
2011
2184
|
- name: Branch not found error comment
|
|
2012
2185
|
if: steps.check_branch.outputs.exists == 'false'
|
|
2013
2186
|
uses: actions/github-script@v9
|
|
2187
|
+
env:
|
|
2188
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
2014
2189
|
with:
|
|
2015
2190
|
script: |
|
|
2016
2191
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2017
2192
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2018
2193
|
|
|
2019
|
-
const branchName =
|
|
2194
|
+
const branchName = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME;
|
|
2020
2195
|
|
|
2021
2196
|
const body = [
|
|
2022
2197
|
m('wf_preview.title_branch_missing'),
|
|
@@ -2097,15 +2272,19 @@ jobs:
|
|
|
2097
2272
|
if: steps.check_branch.outputs.exists == 'true'
|
|
2098
2273
|
id: progress
|
|
2099
2274
|
uses: actions/github-script@v9
|
|
2275
|
+
env:
|
|
2276
|
+
PAW_IN_STEPS_COMMIT_OUTPUTS_SHA: ${{ steps.commit.outputs.sha }}
|
|
2277
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
2278
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX: ${{ steps.extract.outputs.container_suffix }}
|
|
2100
2279
|
with:
|
|
2101
2280
|
script: |
|
|
2102
2281
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2103
2282
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2104
2283
|
|
|
2105
|
-
const projectName =
|
|
2106
|
-
const containerSuffix =
|
|
2107
|
-
const branchName =
|
|
2108
|
-
const sha =
|
|
2284
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
2285
|
+
const containerSuffix = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX;
|
|
2286
|
+
const branchName = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME;
|
|
2287
|
+
const sha = process.env.PAW_IN_STEPS_COMMIT_OUTPUTS_SHA;
|
|
2109
2288
|
|
|
2110
2289
|
const body = [
|
|
2111
2290
|
m('wf_preview.title_custom_started'),
|
|
@@ -2166,16 +2345,21 @@ jobs:
|
|
|
2166
2345
|
if: steps.check_branch.outputs.exists == 'true'
|
|
2167
2346
|
id: build_progress
|
|
2168
2347
|
uses: actions/github-script@v9
|
|
2348
|
+
env:
|
|
2349
|
+
PAW_IN_STEPS_BUILD_OUTPUTS_DURATION: ${{ steps.build.outputs.duration }}
|
|
2350
|
+
PAW_IN_STEPS_COMMIT_OUTPUTS_SHA: ${{ steps.commit.outputs.sha }}
|
|
2351
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
2352
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2169
2353
|
with:
|
|
2170
2354
|
script: |
|
|
2171
2355
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2172
2356
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2173
2357
|
|
|
2174
|
-
const commentId =
|
|
2175
|
-
const projectName =
|
|
2176
|
-
const branchName =
|
|
2177
|
-
const sha =
|
|
2178
|
-
const buildDuration =
|
|
2358
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
2359
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
2360
|
+
const branchName = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME;
|
|
2361
|
+
const sha = process.env.PAW_IN_STEPS_COMMIT_OUTPUTS_SHA;
|
|
2362
|
+
const buildDuration = process.env.PAW_IN_STEPS_BUILD_OUTPUTS_DURATION;
|
|
2179
2363
|
|
|
2180
2364
|
const body = [
|
|
2181
2365
|
m('wf_preview.title_custom_started'),
|
|
@@ -2204,7 +2388,7 @@ jobs:
|
|
|
2204
2388
|
|
|
2205
2389
|
- name: Log in to Docker Hub
|
|
2206
2390
|
if: steps.check_branch.outputs.exists == 'true'
|
|
2207
|
-
uses: docker/login-action@
|
|
2391
|
+
uses: docker/login-action@v4
|
|
2208
2392
|
with:
|
|
2209
2393
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
2210
2394
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
@@ -2228,17 +2412,23 @@ jobs:
|
|
|
2228
2412
|
if: steps.check_branch.outputs.exists == 'true'
|
|
2229
2413
|
id: docker_progress
|
|
2230
2414
|
uses: actions/github-script@v9
|
|
2415
|
+
env:
|
|
2416
|
+
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.build_progress.outputs.build_duration }}
|
|
2417
|
+
PAW_IN_STEPS_COMMIT_OUTPUTS_SHA: ${{ steps.commit.outputs.sha }}
|
|
2418
|
+
PAW_IN_STEPS_DOCKER_OUTPUTS_DURATION: ${{ steps.docker.outputs.duration }}
|
|
2419
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
2420
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2231
2421
|
with:
|
|
2232
2422
|
script: |
|
|
2233
2423
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2234
2424
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2235
2425
|
|
|
2236
|
-
const commentId =
|
|
2237
|
-
const projectName =
|
|
2238
|
-
const branchName =
|
|
2239
|
-
const sha =
|
|
2240
|
-
const buildDuration =
|
|
2241
|
-
const dockerDuration =
|
|
2426
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
2427
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
2428
|
+
const branchName = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME;
|
|
2429
|
+
const sha = process.env.PAW_IN_STEPS_COMMIT_OUTPUTS_SHA;
|
|
2430
|
+
const buildDuration = process.env.PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION;
|
|
2431
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_OUTPUTS_DURATION;
|
|
2242
2432
|
|
|
2243
2433
|
const body = [
|
|
2244
2434
|
m('wf_preview.title_custom_started'),
|
|
@@ -2325,7 +2515,7 @@ jobs:
|
|
|
2325
2515
|
fi
|
|
2326
2516
|
|
|
2327
2517
|
m wf_preview.r_deploy_done
|
|
2328
|
-
|
|
2518
|
+
m wf_preview.r_preview_url url="http://${CONTAINER_NAME}.${DOMAIN_SUFFIX}:${PREVIEW_PORT}"
|
|
2329
2519
|
|
|
2330
2520
|
- name: Record deploy completion
|
|
2331
2521
|
if: steps.check_branch.outputs.exists == 'true'
|
|
@@ -2338,26 +2528,34 @@ jobs:
|
|
|
2338
2528
|
- name: Deploy complete comment
|
|
2339
2529
|
if: steps.check_branch.outputs.exists == 'true'
|
|
2340
2530
|
uses: actions/github-script@v9
|
|
2531
|
+
env:
|
|
2532
|
+
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.build_progress.outputs.build_duration }}
|
|
2533
|
+
PAW_IN_STEPS_COMMIT_OUTPUTS_SHA: ${{ steps.commit.outputs.sha }}
|
|
2534
|
+
PAW_IN_STEPS_DEPLOY_TIME_OUTPUTS_DURATION: ${{ steps.deploy_time.outputs.duration }}
|
|
2535
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
2536
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
2537
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX: ${{ steps.extract.outputs.container_suffix }}
|
|
2538
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2341
2539
|
with:
|
|
2342
2540
|
script: |
|
|
2343
2541
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2344
2542
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2345
2543
|
|
|
2346
|
-
const commentId =
|
|
2347
|
-
const projectName =
|
|
2348
|
-
const containerSuffix =
|
|
2349
|
-
const branchName =
|
|
2350
|
-
const sha =
|
|
2351
|
-
const domainSuffix =
|
|
2352
|
-
const previewPort =
|
|
2353
|
-
const apiDocsPath =
|
|
2544
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
2545
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
2546
|
+
const containerSuffix = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX;
|
|
2547
|
+
const branchName = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME;
|
|
2548
|
+
const sha = process.env.PAW_IN_STEPS_COMMIT_OUTPUTS_SHA;
|
|
2549
|
+
const domainSuffix = process.env.PREVIEW_DOMAIN_SUFFIX;
|
|
2550
|
+
const previewPort = process.env.PREVIEW_PORT;
|
|
2551
|
+
const apiDocsPath = process.env.API_DOCS_PATH;
|
|
2354
2552
|
|
|
2355
2553
|
const containerName = `${projectName}-${containerSuffix}`;
|
|
2356
2554
|
const previewUrl = `http://${containerName}.${domainSuffix}:${previewPort}`;
|
|
2357
2555
|
|
|
2358
|
-
const buildDuration =
|
|
2359
|
-
const dockerDuration =
|
|
2360
|
-
const deployDuration =
|
|
2556
|
+
const buildDuration = process.env.PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION;
|
|
2557
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
2558
|
+
const deployDuration = process.env.PAW_IN_STEPS_DEPLOY_TIME_OUTPUTS_DURATION;
|
|
2361
2559
|
|
|
2362
2560
|
const envRows = [
|
|
2363
2561
|
`| **Preview URL** | ${previewUrl} |`,
|
|
@@ -2404,20 +2602,25 @@ jobs:
|
|
|
2404
2602
|
});
|
|
2405
2603
|
|
|
2406
2604
|
- name: Build/deploy failure comment
|
|
2407
|
-
if: failure() && steps.check_branch.outputs.exists == 'true'
|
|
2605
|
+
if: failure() && steps.load_messages.outcome == 'success' && steps.check_branch.outputs.exists == 'true'
|
|
2408
2606
|
uses: actions/github-script@v9
|
|
2607
|
+
env:
|
|
2608
|
+
PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION: ${{ steps.build_progress.outputs.build_duration }}
|
|
2609
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
2610
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
2611
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2409
2612
|
with:
|
|
2410
2613
|
script: |
|
|
2411
2614
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2412
2615
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2413
2616
|
|
|
2414
|
-
const commentId =
|
|
2415
|
-
const projectName =
|
|
2416
|
-
const branchName =
|
|
2617
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
2618
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
2619
|
+
const branchName = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME;
|
|
2417
2620
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
|
|
2418
2621
|
|
|
2419
|
-
const buildDuration =
|
|
2420
|
-
const dockerDuration =
|
|
2622
|
+
const buildDuration = process.env.PAW_IN_STEPS_BUILD_PROGRESS_OUTPUTS_BUILD_DURATION;
|
|
2623
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
2421
2624
|
|
|
2422
2625
|
let buildStatus, dockerStatus, deployStatus;
|
|
2423
2626
|
let buildTime = '-', dockerTime = '-';
|
|
@@ -2498,6 +2701,8 @@ jobs:
|
|
|
2498
2701
|
uses: actions/checkout@v7
|
|
2499
2702
|
with:
|
|
2500
2703
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
2704
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
2705
|
+
path: .paw-msg
|
|
2501
2706
|
sparse-checkout: |
|
|
2502
2707
|
.github/scripts/messages.py
|
|
2503
2708
|
version.yml
|
|
@@ -2505,11 +2710,16 @@ jobs:
|
|
|
2505
2710
|
|
|
2506
2711
|
- name: Load messages
|
|
2507
2712
|
run: |
|
|
2508
|
-
# Keep a copy outside the workspace
|
|
2713
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
2509
2714
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
2510
|
-
|
|
2715
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
2716
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
2717
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
2718
|
+
rm -rf .paw-msg
|
|
2719
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
2720
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
2511
2721
|
{
|
|
2512
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
2722
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
2513
2723
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
2514
2724
|
} >> "$GITHUB_ENV"
|
|
2515
2725
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -2536,12 +2746,41 @@ jobs:
|
|
|
2536
2746
|
print("PAW_EOF")
|
|
2537
2747
|
PY
|
|
2538
2748
|
|
|
2749
|
+
# Report the missing secrets by name instead of surfacing a raw SSH action error
|
|
2750
|
+
- name: Deploy pre-check (Secrets)
|
|
2751
|
+
id: precheck
|
|
2752
|
+
env:
|
|
2753
|
+
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
2754
|
+
SERVER_HOST: ${{ secrets.SERVER_HOST }}
|
|
2755
|
+
SERVER_USER: ${{ secrets.SERVER_USER }}
|
|
2756
|
+
SERVER_PASSWORD: ${{ secrets.SERVER_PASSWORD }}
|
|
2757
|
+
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
2758
|
+
run: |
|
|
2759
|
+
m() { python3 "$RUNNER_TEMP/paw/messages.py" get "$@"; }
|
|
2760
|
+
|
|
2761
|
+
MISSING=""
|
|
2762
|
+
for NAME in DOCKERHUB_USERNAME SERVER_HOST SERVER_USER; do
|
|
2763
|
+
[ -n "${!NAME}" ] || MISSING="$MISSING $NAME"
|
|
2764
|
+
done
|
|
2765
|
+
# SSH_KEY is required when SSH_AUTH_METHOD=key, otherwise SERVER_PASSWORD
|
|
2766
|
+
if [ "${SSH_AUTH_METHOD:-password}" = "key" ]; then
|
|
2767
|
+
[ -n "$SSH_KEY" ] || MISSING="$MISSING SSH_KEY"
|
|
2768
|
+
else
|
|
2769
|
+
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
2770
|
+
fi
|
|
2771
|
+
if [ -n "$MISSING" ]; then
|
|
2772
|
+
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
2773
|
+
exit 1
|
|
2774
|
+
fi
|
|
2775
|
+
|
|
2539
2776
|
- name: Extract container suffix from branch name
|
|
2540
2777
|
id: extract
|
|
2541
2778
|
uses: actions/github-script@v9
|
|
2779
|
+
env:
|
|
2780
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
2542
2781
|
with:
|
|
2543
2782
|
script: |
|
|
2544
|
-
const branchName =
|
|
2783
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
2545
2784
|
const issueMatch = branchName.match(/#(\d+)/);
|
|
2546
2785
|
|
|
2547
2786
|
if (issueMatch) {
|
|
@@ -2593,14 +2832,17 @@ jobs:
|
|
|
2593
2832
|
|
|
2594
2833
|
- name: Destroy confirmation comment
|
|
2595
2834
|
uses: actions/github-script@v9
|
|
2835
|
+
env:
|
|
2836
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
2837
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX: ${{ steps.extract.outputs.container_suffix }}
|
|
2596
2838
|
with:
|
|
2597
2839
|
script: |
|
|
2598
2840
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2599
2841
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2600
2842
|
|
|
2601
|
-
const projectName =
|
|
2602
|
-
const containerSuffix =
|
|
2603
|
-
const branchName =
|
|
2843
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
2844
|
+
const containerSuffix = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX;
|
|
2845
|
+
const branchName = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME;
|
|
2604
2846
|
const containerName = `${projectName}-${containerSuffix}`;
|
|
2605
2847
|
|
|
2606
2848
|
const body = [
|
|
@@ -2639,6 +2881,8 @@ jobs:
|
|
|
2639
2881
|
uses: actions/checkout@v7
|
|
2640
2882
|
with:
|
|
2641
2883
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
2884
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
2885
|
+
path: .paw-msg
|
|
2642
2886
|
sparse-checkout: |
|
|
2643
2887
|
.github/scripts/messages.py
|
|
2644
2888
|
version.yml
|
|
@@ -2646,20 +2890,53 @@ jobs:
|
|
|
2646
2890
|
|
|
2647
2891
|
- name: Load messages
|
|
2648
2892
|
run: |
|
|
2649
|
-
# Keep a copy outside the workspace
|
|
2893
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
2650
2894
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
2651
|
-
|
|
2895
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
2896
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
2897
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
2898
|
+
rm -rf .paw-msg
|
|
2899
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
2900
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
2652
2901
|
{
|
|
2653
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
2902
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
2654
2903
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
2655
2904
|
} >> "$GITHUB_ENV"
|
|
2656
2905
|
|
|
2906
|
+
# Report the missing secrets by name instead of surfacing a raw SSH action error
|
|
2907
|
+
- name: Deploy pre-check (Secrets)
|
|
2908
|
+
id: precheck
|
|
2909
|
+
env:
|
|
2910
|
+
SERVER_HOST: ${{ secrets.SERVER_HOST }}
|
|
2911
|
+
SERVER_USER: ${{ secrets.SERVER_USER }}
|
|
2912
|
+
SERVER_PASSWORD: ${{ secrets.SERVER_PASSWORD }}
|
|
2913
|
+
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
2914
|
+
run: |
|
|
2915
|
+
m() { python3 "$RUNNER_TEMP/paw/messages.py" get "$@"; }
|
|
2916
|
+
|
|
2917
|
+
MISSING=""
|
|
2918
|
+
for NAME in SERVER_HOST SERVER_USER; do
|
|
2919
|
+
[ -n "${!NAME}" ] || MISSING="$MISSING $NAME"
|
|
2920
|
+
done
|
|
2921
|
+
# SSH_KEY is required when SSH_AUTH_METHOD=key, otherwise SERVER_PASSWORD
|
|
2922
|
+
if [ "${SSH_AUTH_METHOD:-password}" = "key" ]; then
|
|
2923
|
+
[ -n "$SSH_KEY" ] || MISSING="$MISSING SSH_KEY"
|
|
2924
|
+
else
|
|
2925
|
+
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
2926
|
+
fi
|
|
2927
|
+
if [ -n "$MISSING" ]; then
|
|
2928
|
+
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
2929
|
+
exit 1
|
|
2930
|
+
fi
|
|
2931
|
+
|
|
2657
2932
|
- name: Extract container suffix from branch name
|
|
2658
2933
|
id: extract
|
|
2659
2934
|
uses: actions/github-script@v9
|
|
2935
|
+
env:
|
|
2936
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
2660
2937
|
with:
|
|
2661
2938
|
script: |
|
|
2662
|
-
const branchName =
|
|
2939
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
2663
2940
|
const issueMatch = branchName.match(/#(\d+)/);
|
|
2664
2941
|
|
|
2665
2942
|
if (issueMatch) {
|
|
@@ -2698,20 +2975,24 @@ jobs:
|
|
|
2698
2975
|
|
|
2699
2976
|
- name: Post status comment
|
|
2700
2977
|
uses: actions/github-script@v9
|
|
2978
|
+
env:
|
|
2979
|
+
PAW_IN_STEPS_CHECK_RUNNING_OUTCOME: ${{ steps.check_running.outcome }}
|
|
2980
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME: ${{ steps.extract.outputs.branch_name }}
|
|
2981
|
+
PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX: ${{ steps.extract.outputs.container_suffix }}
|
|
2701
2982
|
with:
|
|
2702
2983
|
script: |
|
|
2703
2984
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2704
2985
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2705
2986
|
|
|
2706
|
-
const projectName =
|
|
2707
|
-
const containerSuffix =
|
|
2708
|
-
const branchName =
|
|
2709
|
-
const domainSuffix =
|
|
2710
|
-
const previewPort =
|
|
2987
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-spring' : process.env.PROJECT_NAME;
|
|
2988
|
+
const containerSuffix = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_CONTAINER_SUFFIX;
|
|
2989
|
+
const branchName = process.env.PAW_IN_STEPS_EXTRACT_OUTPUTS_BRANCH_NAME;
|
|
2990
|
+
const domainSuffix = process.env.PREVIEW_DOMAIN_SUFFIX;
|
|
2991
|
+
const previewPort = process.env.PREVIEW_PORT;
|
|
2711
2992
|
|
|
2712
2993
|
const containerName = `${projectName}-${containerSuffix}`;
|
|
2713
2994
|
const previewUrl = `http://${containerName}.${domainSuffix}:${previewPort}`;
|
|
2714
|
-
const isRunning =
|
|
2995
|
+
const isRunning = process.env.PAW_IN_STEPS_CHECK_RUNNING_OUTCOME === 'success';
|
|
2715
2996
|
|
|
2716
2997
|
let body;
|
|
2717
2998
|
if (isRunning) {
|