project-auto-wizard 0.14.0 → 0.15.1
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 +3 -1
- package/README.ko.md +3 -1
- package/README.md +4 -2
- package/README.zh-CN.md +3 -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/changelog_manager.py +8 -8
- package/payload/scripts/messages.py +460 -24
- package/payload/scripts/version_manager.py +102 -73
- package/payload/version.yml.template +2 -2
- package/payload/workflows/common/PROJECT-COMMON-AI-PR-SUMMARY.yaml +9 -4
- package/payload/workflows/common/PROJECT-COMMON-AUTO-CHANGELOG-CONTROL.yaml +62 -30
- package/payload/workflows/common/PROJECT-COMMON-README-VERSION-UPDATE.yaml +96 -44
- package/payload/workflows/common/PROJECT-COMMON-RELEASE-PUBLISH.yaml +79 -35
- package/payload/workflows/common/PROJECT-COMMON-VERSION-CONTROL.yaml +71 -35
- 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 +17 -7
- package/src/commands/doctor.js +16 -0
- package/src/commands/dry-run.js +10 -1
- package/src/commands/full.js +5 -2
- package/src/commands/interactive.js +4 -1
- package/src/commands/status.js +14 -1
- package/src/core/copy/readme.js +58 -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/types.js +15 -8
- package/src/core/version-yml.js +52 -6
- package/src/i18n/catalog/en/cli.js +1 -0
- package/src/i18n/catalog/en/commands.js +9 -0
- package/src/i18n/catalog/en/copy.js +1 -0
- package/src/i18n/catalog/en/core2.js +3 -0
- package/src/i18n/catalog/ko/cli.js +1 -0
- package/src/i18n/catalog/ko/commands.js +9 -0
- package/src/i18n/catalog/ko/copy.js +1 -0
- package/src/i18n/catalog/ko/core2.js +3 -0
- package/src/index.js +8 -4
- package/src/ui/env-plan.js +1 -1
- package/src/ui/prompts.js +7 -3
- package/src/ui/summary.js +1 -1
- package/payload/workflows/next/PROJECT-NEXT-CI.yaml +0 -241
- package/payload/workflows/next/PROJECT-NEXT-CICD.yaml +0 -330
|
@@ -104,6 +104,8 @@ jobs:
|
|
|
104
104
|
uses: actions/checkout@v7
|
|
105
105
|
with:
|
|
106
106
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
107
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
108
|
+
path: .paw-msg
|
|
107
109
|
sparse-checkout: |
|
|
108
110
|
.github/scripts/messages.py
|
|
109
111
|
version.yml
|
|
@@ -111,11 +113,16 @@ jobs:
|
|
|
111
113
|
|
|
112
114
|
- name: Load messages
|
|
113
115
|
run: |
|
|
114
|
-
# Keep a copy outside the workspace
|
|
116
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
115
117
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
116
|
-
|
|
118
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
119
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
120
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
121
|
+
rm -rf .paw-msg
|
|
122
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
123
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
117
124
|
{
|
|
118
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
125
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
119
126
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
120
127
|
} >> "$GITHUB_ENV"
|
|
121
128
|
|
|
@@ -206,18 +213,26 @@ jobs:
|
|
|
206
213
|
uses: actions/checkout@v7
|
|
207
214
|
with:
|
|
208
215
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
216
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
217
|
+
path: .paw-msg
|
|
209
218
|
sparse-checkout: |
|
|
210
219
|
.github/scripts/messages.py
|
|
211
220
|
version.yml
|
|
212
221
|
sparse-checkout-cone-mode: false
|
|
213
222
|
|
|
214
223
|
- name: Load messages
|
|
224
|
+
id: load_messages
|
|
215
225
|
run: |
|
|
216
|
-
# Keep a copy outside the workspace
|
|
226
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
217
227
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
218
|
-
|
|
228
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
229
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
230
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
231
|
+
rm -rf .paw-msg
|
|
232
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
233
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
219
234
|
{
|
|
220
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
235
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
221
236
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
222
237
|
} >> "$GITHUB_ENV"
|
|
223
238
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -349,16 +364,16 @@ jobs:
|
|
|
349
364
|
# [End of section 2] Create the environment file
|
|
350
365
|
|
|
351
366
|
- name: Log in to Docker Hub
|
|
352
|
-
uses: docker/login-action@
|
|
367
|
+
uses: docker/login-action@v4
|
|
353
368
|
with:
|
|
354
369
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
355
370
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
356
371
|
|
|
357
372
|
- name: Set up Docker Buildx
|
|
358
|
-
uses: docker/setup-buildx-action@
|
|
373
|
+
uses: docker/setup-buildx-action@v4
|
|
359
374
|
|
|
360
375
|
- name: Build & push Docker image
|
|
361
|
-
uses: docker/build-push-action@
|
|
376
|
+
uses: docker/build-push-action@v7
|
|
362
377
|
with:
|
|
363
378
|
context: ${{ env.PROJECT_PATH }}
|
|
364
379
|
file: ${{ env.PROJECT_PATH }}/${{ env.DOCKERFILE_PATH }}
|
|
@@ -370,13 +385,16 @@ jobs:
|
|
|
370
385
|
- name: Progress - Docker done
|
|
371
386
|
id: docker_progress
|
|
372
387
|
uses: actions/github-script@v9
|
|
388
|
+
env:
|
|
389
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
390
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_DOCKER_START: ${{ steps.progress.outputs.docker_start }}
|
|
373
391
|
with:
|
|
374
392
|
script: |
|
|
375
393
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
376
394
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
377
395
|
|
|
378
|
-
const commentId =
|
|
379
|
-
const dockerStart =
|
|
396
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
397
|
+
const dockerStart = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_DOCKER_START, 10) || Date.now();
|
|
380
398
|
const now = Date.now();
|
|
381
399
|
const dockerElapsed = now - dockerStart;
|
|
382
400
|
const minutes = Math.floor(dockerElapsed / 60000);
|
|
@@ -553,28 +571,34 @@ jobs:
|
|
|
553
571
|
|
|
554
572
|
- name: Deploy complete comment
|
|
555
573
|
uses: actions/github-script@v9
|
|
574
|
+
env:
|
|
575
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
576
|
+
PAW_IN_STEPS_PR_OUTPUTS_REF: ${{ steps.pr.outputs.ref }}
|
|
577
|
+
PAW_IN_STEPS_PR_OUTPUTS_SHA: ${{ steps.pr.outputs.sha }}
|
|
578
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
579
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START: ${{ steps.docker_progress.outputs.deploy_start }}
|
|
556
580
|
with:
|
|
557
581
|
script: |
|
|
558
582
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
559
583
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
560
584
|
|
|
561
|
-
const commentId =
|
|
562
|
-
const dockerDuration =
|
|
563
|
-
const deployStart =
|
|
585
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
586
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
587
|
+
const deployStart = parseInt(process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START, 10) || Date.now();
|
|
564
588
|
const now = Date.now();
|
|
565
589
|
const deployElapsed = now - deployStart;
|
|
566
590
|
const minutes = Math.floor(deployElapsed / 60000);
|
|
567
591
|
const seconds = Math.floor((deployElapsed % 60000) / 1000);
|
|
568
592
|
const deployDuration = minutes > 0 ? m('wf_preview.dur_min_sec', {minutes, seconds}) : m('wf_preview.dur_sec', {seconds});
|
|
569
593
|
|
|
570
|
-
const projectName =
|
|
571
|
-
const domainSuffix =
|
|
572
|
-
const previewPort =
|
|
573
|
-
const apiDocsPath =
|
|
594
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-go' : process.env.PROJECT_NAME;
|
|
595
|
+
const domainSuffix = process.env.PREVIEW_DOMAIN_SUFFIX;
|
|
596
|
+
const previewPort = process.env.PREVIEW_PORT;
|
|
597
|
+
const apiDocsPath = process.env.API_DOCS_PATH;
|
|
574
598
|
const prNumber = context.issue.number;
|
|
575
599
|
const domain = `${projectName}-pr-${prNumber}.${domainSuffix}`;
|
|
576
600
|
const previewUrl = `http://${domain}:${previewPort}`;
|
|
577
|
-
const sha =
|
|
601
|
+
const sha = process.env.PAW_IN_STEPS_PR_OUTPUTS_SHA;
|
|
578
602
|
|
|
579
603
|
// Build the preview environment table (the API Docs row is added only when API_DOCS_PATH is set)
|
|
580
604
|
const envRows = [
|
|
@@ -586,7 +610,7 @@ jobs:
|
|
|
586
610
|
envRows.push(m('wf_preview.env_container_pr', {projectName, prNumber}));
|
|
587
611
|
envRows.push(m('wf_preview.env_commit', {sha}));
|
|
588
612
|
|
|
589
|
-
const branchName =
|
|
613
|
+
const branchName = process.env.PAW_IN_STEPS_PR_OUTPUTS_REF;
|
|
590
614
|
|
|
591
615
|
const body = [
|
|
592
616
|
m('wf_preview.title_pr_deployed'),
|
|
@@ -630,20 +654,23 @@ jobs:
|
|
|
630
654
|
});
|
|
631
655
|
|
|
632
656
|
- name: Build/deploy failure comment
|
|
633
|
-
if: failure()
|
|
657
|
+
if: failure() && steps.load_messages.outcome == 'success'
|
|
634
658
|
uses: actions/github-script@v9
|
|
659
|
+
env:
|
|
660
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
661
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
635
662
|
with:
|
|
636
663
|
script: |
|
|
637
664
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
638
665
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
639
666
|
|
|
640
|
-
const commentId =
|
|
641
|
-
const projectName =
|
|
667
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
668
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-go' : process.env.PROJECT_NAME;
|
|
642
669
|
const prNumber = context.issue.number;
|
|
643
670
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
|
|
644
671
|
|
|
645
672
|
// Show where it failed based on progress
|
|
646
|
-
const dockerDuration =
|
|
673
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
647
674
|
|
|
648
675
|
// Work out where it failed - early-stage failures are distinguished too
|
|
649
676
|
let dockerStatus, deployStatus;
|
|
@@ -726,6 +753,8 @@ jobs:
|
|
|
726
753
|
uses: actions/checkout@v7
|
|
727
754
|
with:
|
|
728
755
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
756
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
757
|
+
path: .paw-msg
|
|
729
758
|
sparse-checkout: |
|
|
730
759
|
.github/scripts/messages.py
|
|
731
760
|
version.yml
|
|
@@ -733,11 +762,16 @@ jobs:
|
|
|
733
762
|
|
|
734
763
|
- name: Load messages
|
|
735
764
|
run: |
|
|
736
|
-
# Keep a copy outside the workspace
|
|
765
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
737
766
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
738
|
-
|
|
767
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
768
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
769
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
770
|
+
rm -rf .paw-msg
|
|
771
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
772
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
739
773
|
{
|
|
740
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
774
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
741
775
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
742
776
|
} >> "$GITHUB_ENV"
|
|
743
777
|
|
|
@@ -750,7 +784,7 @@ jobs:
|
|
|
750
784
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
751
785
|
|
|
752
786
|
const issueNumber = context.issue.number;
|
|
753
|
-
const marker =
|
|
787
|
+
const marker = process.env.ISSUE_HELPER_MARKER;
|
|
754
788
|
|
|
755
789
|
console.log(m('wf_preview.log_search_branch', {issueNumber}));
|
|
756
790
|
console.log(m('wf_preview.log_marker', {marker}));
|
|
@@ -795,7 +829,7 @@ jobs:
|
|
|
795
829
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
796
830
|
|
|
797
831
|
const issueNumber = context.issue.number;
|
|
798
|
-
const marker =
|
|
832
|
+
const marker = process.env.ISSUE_HELPER_MARKER;
|
|
799
833
|
|
|
800
834
|
const body = [
|
|
801
835
|
m('wf_preview.title_branch_missing_warn'),
|
|
@@ -839,18 +873,26 @@ jobs:
|
|
|
839
873
|
uses: actions/checkout@v7
|
|
840
874
|
with:
|
|
841
875
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
876
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
877
|
+
path: .paw-msg
|
|
842
878
|
sparse-checkout: |
|
|
843
879
|
.github/scripts/messages.py
|
|
844
880
|
version.yml
|
|
845
881
|
sparse-checkout-cone-mode: false
|
|
846
882
|
|
|
847
883
|
- name: Load messages
|
|
884
|
+
id: load_messages
|
|
848
885
|
run: |
|
|
849
|
-
# Keep a copy outside the workspace
|
|
886
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
850
887
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
851
|
-
|
|
888
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
889
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
890
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
891
|
+
rm -rf .paw-msg
|
|
892
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
893
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
852
894
|
{
|
|
853
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
895
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
854
896
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
855
897
|
} >> "$GITHUB_ENV"
|
|
856
898
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -880,13 +922,16 @@ jobs:
|
|
|
880
922
|
- name: Check branch exists
|
|
881
923
|
id: check_branch
|
|
882
924
|
uses: actions/github-script@v9
|
|
925
|
+
env:
|
|
926
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
927
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
883
928
|
with:
|
|
884
929
|
script: |
|
|
885
930
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
886
931
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
887
932
|
|
|
888
|
-
const branchName =
|
|
889
|
-
const issueNumber =
|
|
933
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
934
|
+
const issueNumber = parseInt(process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER, 10) || 0;
|
|
890
935
|
|
|
891
936
|
console.log(m('wf_preview.log_check_exists', {branchName}));
|
|
892
937
|
|
|
@@ -943,24 +988,29 @@ jobs:
|
|
|
943
988
|
- name: Set issue info
|
|
944
989
|
if: steps.check_branch.outputs.exists == 'true'
|
|
945
990
|
id: issue
|
|
991
|
+
env:
|
|
992
|
+
PAW_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
946
993
|
run: |
|
|
947
|
-
echo "ref=$
|
|
994
|
+
echo "ref=$PAW_BRANCH_NAME" >> $GITHUB_OUTPUT
|
|
948
995
|
echo "issue_number=${{ needs.get-branch-from-issue.outputs.issue_number }}" >> $GITHUB_OUTPUT
|
|
949
996
|
# Get the latest commit SHA of the branch
|
|
950
|
-
echo "sha=$(git ls-remote https://github.com/${{ github.repository }}.git refs/heads/$
|
|
997
|
+
echo "sha=$(git ls-remote https://github.com/${{ github.repository }}.git "refs/heads/$PAW_BRANCH_NAME" | cut -c1-7)" >> $GITHUB_OUTPUT
|
|
951
998
|
|
|
952
999
|
# Progress comment system
|
|
953
1000
|
- name: Create progress comment
|
|
954
1001
|
if: steps.check_branch.outputs.exists == 'true'
|
|
955
1002
|
id: progress
|
|
956
1003
|
uses: actions/github-script@v9
|
|
1004
|
+
env:
|
|
1005
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1006
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
957
1007
|
with:
|
|
958
1008
|
script: |
|
|
959
1009
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
960
1010
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
961
1011
|
|
|
962
|
-
const issueNumber =
|
|
963
|
-
const branchName =
|
|
1012
|
+
const issueNumber = parseInt(process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER, 10) || 0;
|
|
1013
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
964
1014
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
|
|
965
1015
|
const startTime = Date.now();
|
|
966
1016
|
|
|
@@ -1048,18 +1098,18 @@ jobs:
|
|
|
1048
1098
|
|
|
1049
1099
|
- name: Log in to Docker Hub
|
|
1050
1100
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1051
|
-
uses: docker/login-action@
|
|
1101
|
+
uses: docker/login-action@v4
|
|
1052
1102
|
with:
|
|
1053
1103
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
1054
1104
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
1055
1105
|
|
|
1056
1106
|
- name: Set up Docker Buildx
|
|
1057
1107
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1058
|
-
uses: docker/setup-buildx-action@
|
|
1108
|
+
uses: docker/setup-buildx-action@v4
|
|
1059
1109
|
|
|
1060
1110
|
- name: Build & push Docker image
|
|
1061
1111
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1062
|
-
uses: docker/build-push-action@
|
|
1112
|
+
uses: docker/build-push-action@v7
|
|
1063
1113
|
with:
|
|
1064
1114
|
context: ${{ env.PROJECT_PATH }}
|
|
1065
1115
|
file: ${{ env.PROJECT_PATH }}/${{ env.DOCKERFILE_PATH }}
|
|
@@ -1072,14 +1122,18 @@ jobs:
|
|
|
1072
1122
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1073
1123
|
id: docker_progress
|
|
1074
1124
|
uses: actions/github-script@v9
|
|
1125
|
+
env:
|
|
1126
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1127
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
1128
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_DOCKER_START: ${{ steps.progress.outputs.docker_start }}
|
|
1075
1129
|
with:
|
|
1076
1130
|
script: |
|
|
1077
1131
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1078
1132
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1079
1133
|
|
|
1080
|
-
const commentId =
|
|
1081
|
-
const branchName =
|
|
1082
|
-
const dockerStart =
|
|
1134
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
1135
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
1136
|
+
const dockerStart = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_DOCKER_START, 10) || Date.now();
|
|
1083
1137
|
const now = Date.now();
|
|
1084
1138
|
const dockerElapsed = now - dockerStart;
|
|
1085
1139
|
const minutes = Math.floor(dockerElapsed / 60000);
|
|
@@ -1260,29 +1314,36 @@ jobs:
|
|
|
1260
1314
|
- name: Deploy complete comment
|
|
1261
1315
|
if: steps.check_branch.outputs.exists == 'true'
|
|
1262
1316
|
uses: actions/github-script@v9
|
|
1317
|
+
env:
|
|
1318
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1319
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
1320
|
+
PAW_IN_STEPS_ISSUE_OUTPUTS_SHA: ${{ steps.issue.outputs.sha }}
|
|
1321
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
1322
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START: ${{ steps.docker_progress.outputs.deploy_start }}
|
|
1323
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
1263
1324
|
with:
|
|
1264
1325
|
script: |
|
|
1265
1326
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1266
1327
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1267
1328
|
|
|
1268
|
-
const commentId =
|
|
1269
|
-
const branchName =
|
|
1270
|
-
const dockerDuration =
|
|
1271
|
-
const deployStart =
|
|
1329
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
1330
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
1331
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
1332
|
+
const deployStart = parseInt(process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START, 10) || Date.now();
|
|
1272
1333
|
const now = Date.now();
|
|
1273
1334
|
const deployElapsed = now - deployStart;
|
|
1274
1335
|
const minutes = Math.floor(deployElapsed / 60000);
|
|
1275
1336
|
const seconds = Math.floor((deployElapsed % 60000) / 1000);
|
|
1276
1337
|
const deployDuration = minutes > 0 ? m('wf_preview.dur_min_sec', {minutes, seconds}) : m('wf_preview.dur_sec', {seconds});
|
|
1277
1338
|
|
|
1278
|
-
const projectName =
|
|
1279
|
-
const domainSuffix =
|
|
1280
|
-
const previewPort =
|
|
1281
|
-
const apiDocsPath =
|
|
1282
|
-
const issueNumber =
|
|
1339
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-go' : process.env.PROJECT_NAME;
|
|
1340
|
+
const domainSuffix = process.env.PREVIEW_DOMAIN_SUFFIX;
|
|
1341
|
+
const previewPort = process.env.PREVIEW_PORT;
|
|
1342
|
+
const apiDocsPath = process.env.API_DOCS_PATH;
|
|
1343
|
+
const issueNumber = parseInt(process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER, 10) || 0;
|
|
1283
1344
|
const domain = `${projectName}-pr-${issueNumber}.${domainSuffix}`;
|
|
1284
1345
|
const previewUrl = `http://${domain}:${previewPort}`;
|
|
1285
|
-
const sha =
|
|
1346
|
+
const sha = process.env.PAW_IN_STEPS_ISSUE_OUTPUTS_SHA;
|
|
1286
1347
|
|
|
1287
1348
|
// Build the preview environment table (the API Docs row is added only when API_DOCS_PATH is set)
|
|
1288
1349
|
const envRows = [
|
|
@@ -1339,20 +1400,25 @@ jobs:
|
|
|
1339
1400
|
});
|
|
1340
1401
|
|
|
1341
1402
|
- name: Build/deploy failure comment
|
|
1342
|
-
if: failure() && steps.check_branch.outputs.exists == 'true'
|
|
1403
|
+
if: failure() && steps.load_messages.outcome == 'success' && steps.check_branch.outputs.exists == 'true'
|
|
1343
1404
|
uses: actions/github-script@v9
|
|
1405
|
+
env:
|
|
1406
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME: ${{ needs.get-branch-from-issue.outputs.branch_name }}
|
|
1407
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
1408
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
1409
|
+
PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER: ${{ needs.get-branch-from-issue.outputs.issue_number }}
|
|
1344
1410
|
with:
|
|
1345
1411
|
script: |
|
|
1346
1412
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1347
1413
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1348
1414
|
|
|
1349
|
-
const commentId =
|
|
1350
|
-
const projectName =
|
|
1351
|
-
const issueNumber =
|
|
1352
|
-
const branchName =
|
|
1415
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
1416
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-go' : process.env.PROJECT_NAME;
|
|
1417
|
+
const issueNumber = parseInt(process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_ISSUE_NUMBER, 10) || 0;
|
|
1418
|
+
const branchName = process.env.PAW_IN_NEEDS_GET_BRANCH_FROM_ISSUE_OUTPUTS_BRANCH_NAME;
|
|
1353
1419
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
|
|
1354
1420
|
|
|
1355
|
-
const dockerDuration =
|
|
1421
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
1356
1422
|
|
|
1357
1423
|
let dockerStatus, deployStatus;
|
|
1358
1424
|
let dockerTime = '-';
|
|
@@ -1428,6 +1494,8 @@ jobs:
|
|
|
1428
1494
|
uses: actions/checkout@v7
|
|
1429
1495
|
with:
|
|
1430
1496
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
1497
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
1498
|
+
path: .paw-msg
|
|
1431
1499
|
sparse-checkout: |
|
|
1432
1500
|
.github/scripts/messages.py
|
|
1433
1501
|
version.yml
|
|
@@ -1435,11 +1503,16 @@ jobs:
|
|
|
1435
1503
|
|
|
1436
1504
|
- name: Load messages
|
|
1437
1505
|
run: |
|
|
1438
|
-
# Keep a copy outside the workspace
|
|
1506
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
1439
1507
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
1440
|
-
|
|
1508
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
1509
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
1510
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
1511
|
+
rm -rf .paw-msg
|
|
1512
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
1513
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
1441
1514
|
{
|
|
1442
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
1515
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
1443
1516
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
1444
1517
|
} >> "$GITHUB_ENV"
|
|
1445
1518
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -1466,6 +1539,41 @@ jobs:
|
|
|
1466
1539
|
print("PAW_EOF")
|
|
1467
1540
|
PY
|
|
1468
1541
|
|
|
1542
|
+
# Without the deploy secrets no preview could have been deployed: on close events skip the cleanup quietly,
|
|
1543
|
+
# and on an explicit command report what is missing instead of surfacing a raw SSH action error
|
|
1544
|
+
- name: Deploy pre-check (Secrets)
|
|
1545
|
+
id: precheck
|
|
1546
|
+
env:
|
|
1547
|
+
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
1548
|
+
SERVER_HOST: ${{ secrets.SERVER_HOST }}
|
|
1549
|
+
SERVER_USER: ${{ secrets.SERVER_USER }}
|
|
1550
|
+
SERVER_PASSWORD: ${{ secrets.SERVER_PASSWORD }}
|
|
1551
|
+
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
1552
|
+
EVENT_NAME: ${{ github.event_name }}
|
|
1553
|
+
run: |
|
|
1554
|
+
m() { python3 "$RUNNER_TEMP/paw/messages.py" get "$@"; }
|
|
1555
|
+
|
|
1556
|
+
MISSING=""
|
|
1557
|
+
for NAME in DOCKERHUB_USERNAME SERVER_HOST SERVER_USER; do
|
|
1558
|
+
[ -n "${!NAME}" ] || MISSING="$MISSING $NAME"
|
|
1559
|
+
done
|
|
1560
|
+
# SSH_KEY is required when SSH_AUTH_METHOD=key, otherwise SERVER_PASSWORD
|
|
1561
|
+
if [ "${SSH_AUTH_METHOD:-password}" = "key" ]; then
|
|
1562
|
+
[ -n "$SSH_KEY" ] || MISSING="$MISSING SSH_KEY"
|
|
1563
|
+
else
|
|
1564
|
+
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
1565
|
+
fi
|
|
1566
|
+
if [ -n "$MISSING" ]; then
|
|
1567
|
+
if [ "$EVENT_NAME" = "issue_comment" ]; then
|
|
1568
|
+
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
1569
|
+
exit 1
|
|
1570
|
+
fi
|
|
1571
|
+
echo "::warning title=$(m wf_preview.precheck_skip_title)::$(m wf_preview.precheck_skip_body missing="$MISSING")"
|
|
1572
|
+
echo "ready=false" >> "$GITHUB_OUTPUT"
|
|
1573
|
+
exit 0
|
|
1574
|
+
fi
|
|
1575
|
+
echo "ready=true" >> "$GITHUB_OUTPUT"
|
|
1576
|
+
|
|
1469
1577
|
- name: Get PR/issue number
|
|
1470
1578
|
id: pr_number
|
|
1471
1579
|
run: |
|
|
@@ -1481,6 +1589,7 @@ jobs:
|
|
|
1481
1589
|
fi
|
|
1482
1590
|
|
|
1483
1591
|
- name: Remove container & image
|
|
1592
|
+
if: steps.precheck.outputs.ready == 'true'
|
|
1484
1593
|
uses: appleboy/ssh-action@v1.0.3
|
|
1485
1594
|
env:
|
|
1486
1595
|
SSH_AUTH_METHOD: ${{ env.SSH_AUTH_METHOD }}
|
|
@@ -1528,17 +1637,20 @@ jobs:
|
|
|
1528
1637
|
|
|
1529
1638
|
- name: Destroy complete comment
|
|
1530
1639
|
if: |
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1640
|
+
steps.precheck.outputs.ready == 'true' && (
|
|
1641
|
+
github.event_name == 'issue_comment' ||
|
|
1642
|
+
(github.event_name == 'pull_request' && github.event.action == 'closed') ||
|
|
1643
|
+
(github.event_name == 'issues' && github.event.action == 'closed'))
|
|
1534
1644
|
uses: actions/github-script@v9
|
|
1645
|
+
env:
|
|
1646
|
+
PAW_IN_STEPS_PR_NUMBER_OUTPUTS_NUMBER: ${{ steps.pr_number.outputs.number }}
|
|
1535
1647
|
with:
|
|
1536
1648
|
script: |
|
|
1537
1649
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1538
1650
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1539
1651
|
|
|
1540
|
-
const number =
|
|
1541
|
-
const projectName =
|
|
1652
|
+
const number = parseInt(process.env.PAW_IN_STEPS_PR_NUMBER_OUTPUTS_NUMBER, 10) || 0;
|
|
1653
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-go' : process.env.PROJECT_NAME;
|
|
1542
1654
|
|
|
1543
1655
|
const body = [
|
|
1544
1656
|
m('wf_preview.title_destroyed'),
|
|
@@ -1574,6 +1686,8 @@ jobs:
|
|
|
1574
1686
|
uses: actions/checkout@v7
|
|
1575
1687
|
with:
|
|
1576
1688
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
1689
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
1690
|
+
path: .paw-msg
|
|
1577
1691
|
sparse-checkout: |
|
|
1578
1692
|
.github/scripts/messages.py
|
|
1579
1693
|
version.yml
|
|
@@ -1581,11 +1695,16 @@ jobs:
|
|
|
1581
1695
|
|
|
1582
1696
|
- name: Load messages
|
|
1583
1697
|
run: |
|
|
1584
|
-
# Keep a copy outside the workspace
|
|
1698
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
1585
1699
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
1586
|
-
|
|
1700
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
1701
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
1702
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
1703
|
+
rm -rf .paw-msg
|
|
1704
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
1705
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
1587
1706
|
{
|
|
1588
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
1707
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
1589
1708
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
1590
1709
|
} >> "$GITHUB_ENV"
|
|
1591
1710
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -1612,6 +1731,32 @@ jobs:
|
|
|
1612
1731
|
print("PAW_EOF")
|
|
1613
1732
|
PY
|
|
1614
1733
|
|
|
1734
|
+
# Report the missing secrets by name instead of surfacing a raw SSH action error
|
|
1735
|
+
- name: Deploy pre-check (Secrets)
|
|
1736
|
+
id: precheck
|
|
1737
|
+
env:
|
|
1738
|
+
SERVER_HOST: ${{ secrets.SERVER_HOST }}
|
|
1739
|
+
SERVER_USER: ${{ secrets.SERVER_USER }}
|
|
1740
|
+
SERVER_PASSWORD: ${{ secrets.SERVER_PASSWORD }}
|
|
1741
|
+
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
1742
|
+
run: |
|
|
1743
|
+
m() { python3 "$RUNNER_TEMP/paw/messages.py" get "$@"; }
|
|
1744
|
+
|
|
1745
|
+
MISSING=""
|
|
1746
|
+
for NAME in SERVER_HOST SERVER_USER; do
|
|
1747
|
+
[ -n "${!NAME}" ] || MISSING="$MISSING $NAME"
|
|
1748
|
+
done
|
|
1749
|
+
# SSH_KEY is required when SSH_AUTH_METHOD=key, otherwise SERVER_PASSWORD
|
|
1750
|
+
if [ "${SSH_AUTH_METHOD:-password}" = "key" ]; then
|
|
1751
|
+
[ -n "$SSH_KEY" ] || MISSING="$MISSING SSH_KEY"
|
|
1752
|
+
else
|
|
1753
|
+
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
1754
|
+
fi
|
|
1755
|
+
if [ -n "$MISSING" ]; then
|
|
1756
|
+
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
1757
|
+
exit 1
|
|
1758
|
+
fi
|
|
1759
|
+
|
|
1615
1760
|
- name: Check container status
|
|
1616
1761
|
id: status
|
|
1617
1762
|
uses: appleboy/ssh-action@v1.0.3
|
|
@@ -1663,19 +1808,22 @@ jobs:
|
|
|
1663
1808
|
|
|
1664
1809
|
- name: Post status comment
|
|
1665
1810
|
uses: actions/github-script@v9
|
|
1811
|
+
env:
|
|
1812
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_IS_PR: ${{ needs.check-command.outputs.is_pr }}
|
|
1813
|
+
PAW_IN_STEPS_CHECK_RUNNING_OUTCOME: ${{ steps.check_running.outcome }}
|
|
1666
1814
|
with:
|
|
1667
1815
|
script: |
|
|
1668
1816
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1669
1817
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1670
1818
|
|
|
1671
1819
|
const number = context.issue.number;
|
|
1672
|
-
const projectName =
|
|
1673
|
-
const domainSuffix =
|
|
1674
|
-
const previewPort =
|
|
1820
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-go' : process.env.PROJECT_NAME;
|
|
1821
|
+
const domainSuffix = process.env.PREVIEW_DOMAIN_SUFFIX;
|
|
1822
|
+
const previewPort = process.env.PREVIEW_PORT;
|
|
1675
1823
|
const domain = `${projectName}-pr-${number}.${domainSuffix}`;
|
|
1676
1824
|
const previewUrl = `http://${domain}:${previewPort}`;
|
|
1677
|
-
const isRunning =
|
|
1678
|
-
const isPr =
|
|
1825
|
+
const isRunning = process.env.PAW_IN_STEPS_CHECK_RUNNING_OUTCOME === 'success';
|
|
1826
|
+
const isPr = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_IS_PR === 'true';
|
|
1679
1827
|
const contextType = isPr ? 'PR' : 'Issue';
|
|
1680
1828
|
|
|
1681
1829
|
let body;
|
|
@@ -1737,18 +1885,26 @@ jobs:
|
|
|
1737
1885
|
uses: actions/checkout@v7
|
|
1738
1886
|
with:
|
|
1739
1887
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
1888
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
1889
|
+
path: .paw-msg
|
|
1740
1890
|
sparse-checkout: |
|
|
1741
1891
|
.github/scripts/messages.py
|
|
1742
1892
|
version.yml
|
|
1743
1893
|
sparse-checkout-cone-mode: false
|
|
1744
1894
|
|
|
1745
1895
|
- name: Load messages
|
|
1896
|
+
id: load_messages
|
|
1746
1897
|
run: |
|
|
1747
|
-
# Keep a copy outside the workspace
|
|
1898
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
1748
1899
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
1749
|
-
|
|
1900
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
1901
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
1902
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
1903
|
+
rm -rf .paw-msg
|
|
1904
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
1905
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
1750
1906
|
{
|
|
1751
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
1907
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
1752
1908
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
1753
1909
|
} >> "$GITHUB_ENV"
|
|
1754
1910
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -1778,12 +1934,14 @@ jobs:
|
|
|
1778
1934
|
- name: Check branch exists and extract info
|
|
1779
1935
|
id: branch_info
|
|
1780
1936
|
uses: actions/github-script@v9
|
|
1937
|
+
env:
|
|
1938
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
1781
1939
|
with:
|
|
1782
1940
|
script: |
|
|
1783
1941
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1784
1942
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1785
1943
|
|
|
1786
|
-
const branchName =
|
|
1944
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
1787
1945
|
const issueNumber = context.issue.number;
|
|
1788
1946
|
|
|
1789
1947
|
console.log(m('wf_preview.log_check_branch', {branchName}));
|
|
@@ -1858,21 +2016,25 @@ jobs:
|
|
|
1858
2016
|
- name: Get latest commit SHA of the branch
|
|
1859
2017
|
if: steps.branch_info.outputs.branch_exists == 'true'
|
|
1860
2018
|
id: get_sha
|
|
2019
|
+
env:
|
|
2020
|
+
PAW_BRANCH_NAME: ${{ needs.check-command.outputs.custom_branch }}
|
|
1861
2021
|
run: |
|
|
1862
|
-
SHA=$(git ls-remote https://github.com/${{ github.repository }}.git refs/heads/$
|
|
2022
|
+
SHA=$(git ls-remote https://github.com/${{ github.repository }}.git "refs/heads/$PAW_BRANCH_NAME" | cut -c1-7)
|
|
1863
2023
|
echo "sha=$SHA" >> $GITHUB_OUTPUT
|
|
1864
2024
|
|
|
1865
2025
|
- name: Create progress comment
|
|
1866
2026
|
if: steps.branch_info.outputs.branch_exists == 'true'
|
|
1867
2027
|
id: progress
|
|
1868
2028
|
uses: actions/github-script@v9
|
|
2029
|
+
env:
|
|
2030
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
1869
2031
|
with:
|
|
1870
2032
|
script: |
|
|
1871
2033
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
1872
2034
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
1873
2035
|
|
|
1874
2036
|
const issueNumber = context.issue.number;
|
|
1875
|
-
const branchName =
|
|
2037
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
1876
2038
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
|
|
1877
2039
|
const startTime = Date.now();
|
|
1878
2040
|
|
|
@@ -1958,14 +2120,14 @@ jobs:
|
|
|
1958
2120
|
|
|
1959
2121
|
- name: Log in to Docker Hub
|
|
1960
2122
|
if: steps.branch_info.outputs.branch_exists == 'true'
|
|
1961
|
-
uses: docker/login-action@
|
|
2123
|
+
uses: docker/login-action@v4
|
|
1962
2124
|
with:
|
|
1963
2125
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
1964
2126
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
1965
2127
|
|
|
1966
2128
|
- name: Set up Docker Buildx
|
|
1967
2129
|
if: steps.branch_info.outputs.branch_exists == 'true'
|
|
1968
|
-
uses: docker/setup-buildx-action@
|
|
2130
|
+
uses: docker/setup-buildx-action@v4
|
|
1969
2131
|
|
|
1970
2132
|
- name: Resolve container name
|
|
1971
2133
|
if: steps.branch_info.outputs.branch_exists == 'true'
|
|
@@ -1981,7 +2143,7 @@ jobs:
|
|
|
1981
2143
|
|
|
1982
2144
|
- name: Build & push Docker image
|
|
1983
2145
|
if: steps.branch_info.outputs.branch_exists == 'true'
|
|
1984
|
-
uses: docker/build-push-action@
|
|
2146
|
+
uses: docker/build-push-action@v7
|
|
1985
2147
|
with:
|
|
1986
2148
|
context: ${{ env.PROJECT_PATH }}
|
|
1987
2149
|
file: ${{ env.PROJECT_PATH }}/${{ env.DOCKERFILE_PATH }}
|
|
@@ -1994,14 +2156,18 @@ jobs:
|
|
|
1994
2156
|
if: steps.branch_info.outputs.branch_exists == 'true'
|
|
1995
2157
|
id: docker_progress
|
|
1996
2158
|
uses: actions/github-script@v9
|
|
2159
|
+
env:
|
|
2160
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
2161
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2162
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_DOCKER_START: ${{ steps.progress.outputs.docker_start }}
|
|
1997
2163
|
with:
|
|
1998
2164
|
script: |
|
|
1999
2165
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2000
2166
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2001
2167
|
|
|
2002
|
-
const commentId =
|
|
2003
|
-
const branchName =
|
|
2004
|
-
const dockerStart =
|
|
2168
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
2169
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
2170
|
+
const dockerStart = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_DOCKER_START, 10) || Date.now();
|
|
2005
2171
|
const now = Date.now();
|
|
2006
2172
|
const dockerElapsed = now - dockerStart;
|
|
2007
2173
|
const minutes = Math.floor(dockerElapsed / 60000);
|
|
@@ -2176,29 +2342,36 @@ jobs:
|
|
|
2176
2342
|
- name: Deploy complete comment
|
|
2177
2343
|
if: steps.branch_info.outputs.branch_exists == 'true'
|
|
2178
2344
|
uses: actions/github-script@v9
|
|
2345
|
+
env:
|
|
2346
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
2347
|
+
PAW_IN_STEPS_CONTAINER_OUTPUTS_NAME: ${{ steps.container.outputs.name }}
|
|
2348
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
2349
|
+
PAW_IN_STEPS_GET_SHA_OUTPUTS_SHA: ${{ steps.get_sha.outputs.sha }}
|
|
2350
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2351
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START: ${{ steps.docker_progress.outputs.deploy_start }}
|
|
2179
2352
|
with:
|
|
2180
2353
|
script: |
|
|
2181
2354
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2182
2355
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2183
2356
|
|
|
2184
|
-
const commentId =
|
|
2185
|
-
const branchName =
|
|
2186
|
-
const dockerDuration =
|
|
2187
|
-
const deployStart =
|
|
2357
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
2358
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
2359
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
2360
|
+
const deployStart = parseInt(process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DEPLOY_START, 10) || Date.now();
|
|
2188
2361
|
const now = Date.now();
|
|
2189
2362
|
const deployElapsed = now - deployStart;
|
|
2190
2363
|
const minutes = Math.floor(deployElapsed / 60000);
|
|
2191
2364
|
const seconds = Math.floor((deployElapsed % 60000) / 1000);
|
|
2192
2365
|
const deployDuration = minutes > 0 ? m('wf_preview.dur_min_sec', {minutes, seconds}) : m('wf_preview.dur_sec', {seconds});
|
|
2193
2366
|
|
|
2194
|
-
const projectName =
|
|
2195
|
-
const domainSuffix =
|
|
2196
|
-
const previewPort =
|
|
2197
|
-
const apiDocsPath =
|
|
2198
|
-
const containerName =
|
|
2367
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-go' : process.env.PROJECT_NAME;
|
|
2368
|
+
const domainSuffix = process.env.PREVIEW_DOMAIN_SUFFIX;
|
|
2369
|
+
const previewPort = process.env.PREVIEW_PORT;
|
|
2370
|
+
const apiDocsPath = process.env.API_DOCS_PATH;
|
|
2371
|
+
const containerName = process.env.PAW_IN_STEPS_CONTAINER_OUTPUTS_NAME;
|
|
2199
2372
|
const domain = `${containerName}.${domainSuffix}`;
|
|
2200
2373
|
const previewUrl = `http://${domain}:${previewPort}`;
|
|
2201
|
-
const sha =
|
|
2374
|
+
const sha = process.env.PAW_IN_STEPS_GET_SHA_OUTPUTS_SHA;
|
|
2202
2375
|
|
|
2203
2376
|
// Build the preview environment table
|
|
2204
2377
|
const envRows = [
|
|
@@ -2255,18 +2428,22 @@ jobs:
|
|
|
2255
2428
|
});
|
|
2256
2429
|
|
|
2257
2430
|
- name: Build/deploy failure comment
|
|
2258
|
-
if: failure() && steps.branch_info.outputs.branch_exists == 'true'
|
|
2431
|
+
if: failure() && steps.load_messages.outcome == 'success' && steps.branch_info.outputs.branch_exists == 'true'
|
|
2259
2432
|
uses: actions/github-script@v9
|
|
2433
|
+
env:
|
|
2434
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
2435
|
+
PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION: ${{ steps.docker_progress.outputs.docker_duration }}
|
|
2436
|
+
PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID: ${{ steps.progress.outputs.comment_id }}
|
|
2260
2437
|
with:
|
|
2261
2438
|
script: |
|
|
2262
2439
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2263
2440
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2264
2441
|
|
|
2265
|
-
const commentId =
|
|
2266
|
-
const branchName =
|
|
2442
|
+
const commentId = parseInt(process.env.PAW_IN_STEPS_PROGRESS_OUTPUTS_COMMENT_ID, 10) || 0;
|
|
2443
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
2267
2444
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${context.runId}`;
|
|
2268
2445
|
|
|
2269
|
-
const dockerDuration =
|
|
2446
|
+
const dockerDuration = process.env.PAW_IN_STEPS_DOCKER_PROGRESS_OUTPUTS_DOCKER_DURATION;
|
|
2270
2447
|
|
|
2271
2448
|
let dockerStatus, deployStatus;
|
|
2272
2449
|
let dockerTime = '-';
|
|
@@ -2342,6 +2519,8 @@ jobs:
|
|
|
2342
2519
|
uses: actions/checkout@v7
|
|
2343
2520
|
with:
|
|
2344
2521
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
2522
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
2523
|
+
path: .paw-msg
|
|
2345
2524
|
sparse-checkout: |
|
|
2346
2525
|
.github/scripts/messages.py
|
|
2347
2526
|
version.yml
|
|
@@ -2349,11 +2528,16 @@ jobs:
|
|
|
2349
2528
|
|
|
2350
2529
|
- name: Load messages
|
|
2351
2530
|
run: |
|
|
2352
|
-
# Keep a copy outside the workspace
|
|
2531
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
2353
2532
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
2354
|
-
|
|
2533
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
2534
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
2535
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
2536
|
+
rm -rf .paw-msg
|
|
2537
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
2538
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
2355
2539
|
{
|
|
2356
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
2540
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
2357
2541
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
2358
2542
|
} >> "$GITHUB_ENV"
|
|
2359
2543
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -2380,16 +2564,45 @@ jobs:
|
|
|
2380
2564
|
print("PAW_EOF")
|
|
2381
2565
|
PY
|
|
2382
2566
|
|
|
2567
|
+
# Report the missing secrets by name instead of surfacing a raw SSH action error
|
|
2568
|
+
- name: Deploy pre-check (Secrets)
|
|
2569
|
+
id: precheck
|
|
2570
|
+
env:
|
|
2571
|
+
DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }}
|
|
2572
|
+
SERVER_HOST: ${{ secrets.SERVER_HOST }}
|
|
2573
|
+
SERVER_USER: ${{ secrets.SERVER_USER }}
|
|
2574
|
+
SERVER_PASSWORD: ${{ secrets.SERVER_PASSWORD }}
|
|
2575
|
+
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
2576
|
+
run: |
|
|
2577
|
+
m() { python3 "$RUNNER_TEMP/paw/messages.py" get "$@"; }
|
|
2578
|
+
|
|
2579
|
+
MISSING=""
|
|
2580
|
+
for NAME in DOCKERHUB_USERNAME SERVER_HOST SERVER_USER; do
|
|
2581
|
+
[ -n "${!NAME}" ] || MISSING="$MISSING $NAME"
|
|
2582
|
+
done
|
|
2583
|
+
# SSH_KEY is required when SSH_AUTH_METHOD=key, otherwise SERVER_PASSWORD
|
|
2584
|
+
if [ "${SSH_AUTH_METHOD:-password}" = "key" ]; then
|
|
2585
|
+
[ -n "$SSH_KEY" ] || MISSING="$MISSING SSH_KEY"
|
|
2586
|
+
else
|
|
2587
|
+
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
2588
|
+
fi
|
|
2589
|
+
if [ -n "$MISSING" ]; then
|
|
2590
|
+
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
2591
|
+
exit 1
|
|
2592
|
+
fi
|
|
2593
|
+
|
|
2383
2594
|
- name: Extract container info from branch name
|
|
2384
2595
|
id: container_info
|
|
2385
2596
|
uses: actions/github-script@v9
|
|
2597
|
+
env:
|
|
2598
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
2386
2599
|
with:
|
|
2387
2600
|
script: |
|
|
2388
2601
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2389
2602
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2390
2603
|
|
|
2391
|
-
const branchName =
|
|
2392
|
-
const projectName =
|
|
2604
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
2605
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-go' : process.env.PROJECT_NAME;
|
|
2393
2606
|
|
|
2394
2607
|
// Extract the issue number from the branch name (#number pattern)
|
|
2395
2608
|
const issueMatch = branchName.match(/#(\d+)/);
|
|
@@ -2464,13 +2677,16 @@ jobs:
|
|
|
2464
2677
|
|
|
2465
2678
|
- name: Destroy complete comment
|
|
2466
2679
|
uses: actions/github-script@v9
|
|
2680
|
+
env:
|
|
2681
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
2682
|
+
PAW_IN_STEPS_CONTAINER_INFO_OUTPUTS_CONTAINER_NAME: ${{ steps.container_info.outputs.container_name }}
|
|
2467
2683
|
with:
|
|
2468
2684
|
script: |
|
|
2469
2685
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2470
2686
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2471
2687
|
|
|
2472
|
-
const branchName =
|
|
2473
|
-
const containerName =
|
|
2688
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
2689
|
+
const containerName = process.env.PAW_IN_STEPS_CONTAINER_INFO_OUTPUTS_CONTAINER_NAME;
|
|
2474
2690
|
|
|
2475
2691
|
const body = [
|
|
2476
2692
|
m('wf_preview.title_custom_destroyed'),
|
|
@@ -2510,6 +2726,8 @@ jobs:
|
|
|
2510
2726
|
uses: actions/checkout@v7
|
|
2511
2727
|
with:
|
|
2512
2728
|
ref: ${{ github.event_name == 'pull_request' && github.sha || github.event.repository.default_branch }}
|
|
2729
|
+
# Separate path: a sparse checkout at the workspace root would leave the later full checkout sparse too
|
|
2730
|
+
path: .paw-msg
|
|
2513
2731
|
sparse-checkout: |
|
|
2514
2732
|
.github/scripts/messages.py
|
|
2515
2733
|
version.yml
|
|
@@ -2517,11 +2735,16 @@ jobs:
|
|
|
2517
2735
|
|
|
2518
2736
|
- name: Load messages
|
|
2519
2737
|
run: |
|
|
2520
|
-
# Keep a copy outside the workspace
|
|
2738
|
+
# Keep a copy outside the workspace and drop the sparse clone so the later checkout sees a clean tree
|
|
2521
2739
|
mkdir -p "$RUNNER_TEMP/paw"
|
|
2522
|
-
|
|
2740
|
+
[ -f .paw-msg/.github/scripts/messages.py ] || { echo "::error::messages.py is missing; rerun \`npx project-auto-wizard --mode full --force\`"; exit 1; }
|
|
2741
|
+
cp .paw-msg/.github/scripts/messages.py "$RUNNER_TEMP/paw/messages.py"
|
|
2742
|
+
LANG_CODE=$(cd .paw-msg && python3 "$RUNNER_TEMP/paw/messages.py" lang)
|
|
2743
|
+
rm -rf .paw-msg
|
|
2744
|
+
# The workspace root has no version.yml; pass the language resolved above to every later messages.py call
|
|
2745
|
+
export PROJECT_AUTO_WIZARD_LANG="$LANG_CODE"
|
|
2523
2746
|
{
|
|
2524
|
-
echo "PROJECT_AUTO_WIZARD_LANG=$
|
|
2747
|
+
echo "PROJECT_AUTO_WIZARD_LANG=$LANG_CODE"
|
|
2525
2748
|
echo "PAW_MSG=$(python3 "$RUNNER_TEMP/paw/messages.py" dump wf_preview.)"
|
|
2526
2749
|
} >> "$GITHUB_ENV"
|
|
2527
2750
|
# The deploy script runs on the remote server, where messages.py does not exist:
|
|
@@ -2548,13 +2771,41 @@ jobs:
|
|
|
2548
2771
|
print("PAW_EOF")
|
|
2549
2772
|
PY
|
|
2550
2773
|
|
|
2774
|
+
# Report the missing secrets by name instead of surfacing a raw SSH action error
|
|
2775
|
+
- name: Deploy pre-check (Secrets)
|
|
2776
|
+
id: precheck
|
|
2777
|
+
env:
|
|
2778
|
+
SERVER_HOST: ${{ secrets.SERVER_HOST }}
|
|
2779
|
+
SERVER_USER: ${{ secrets.SERVER_USER }}
|
|
2780
|
+
SERVER_PASSWORD: ${{ secrets.SERVER_PASSWORD }}
|
|
2781
|
+
SSH_KEY: ${{ secrets.SSH_KEY }}
|
|
2782
|
+
run: |
|
|
2783
|
+
m() { python3 "$RUNNER_TEMP/paw/messages.py" get "$@"; }
|
|
2784
|
+
|
|
2785
|
+
MISSING=""
|
|
2786
|
+
for NAME in SERVER_HOST SERVER_USER; do
|
|
2787
|
+
[ -n "${!NAME}" ] || MISSING="$MISSING $NAME"
|
|
2788
|
+
done
|
|
2789
|
+
# SSH_KEY is required when SSH_AUTH_METHOD=key, otherwise SERVER_PASSWORD
|
|
2790
|
+
if [ "${SSH_AUTH_METHOD:-password}" = "key" ]; then
|
|
2791
|
+
[ -n "$SSH_KEY" ] || MISSING="$MISSING SSH_KEY"
|
|
2792
|
+
else
|
|
2793
|
+
[ -n "$SERVER_PASSWORD" ] || MISSING="$MISSING SERVER_PASSWORD"
|
|
2794
|
+
fi
|
|
2795
|
+
if [ -n "$MISSING" ]; then
|
|
2796
|
+
echo "::error title=$(m wf_preview.precheck_secret_title)::$(m wf_preview.precheck_secret_body missing="$MISSING")"
|
|
2797
|
+
exit 1
|
|
2798
|
+
fi
|
|
2799
|
+
|
|
2551
2800
|
- name: Extract container info from branch name
|
|
2552
2801
|
id: container_info
|
|
2553
2802
|
uses: actions/github-script@v9
|
|
2803
|
+
env:
|
|
2804
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
2554
2805
|
with:
|
|
2555
2806
|
script: |
|
|
2556
|
-
const branchName =
|
|
2557
|
-
const projectName =
|
|
2807
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
2808
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-go' : process.env.PROJECT_NAME;
|
|
2558
2809
|
|
|
2559
2810
|
// Extract the issue number from the branch name (#number pattern)
|
|
2560
2811
|
const issueMatch = branchName.match(/#(\d+)/);
|
|
@@ -2610,19 +2861,23 @@ jobs:
|
|
|
2610
2861
|
|
|
2611
2862
|
- name: Post status comment
|
|
2612
2863
|
uses: actions/github-script@v9
|
|
2864
|
+
env:
|
|
2865
|
+
PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH: ${{ needs.check-command.outputs.custom_branch }}
|
|
2866
|
+
PAW_IN_STEPS_CHECK_RUNNING_OUTCOME: ${{ steps.check_running.outcome }}
|
|
2867
|
+
PAW_IN_STEPS_CONTAINER_INFO_OUTPUTS_CONTAINER_NAME: ${{ steps.container_info.outputs.container_name }}
|
|
2613
2868
|
with:
|
|
2614
2869
|
script: |
|
|
2615
2870
|
const M = JSON.parse(process.env.PAW_MSG);
|
|
2616
2871
|
const m = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
2617
2872
|
|
|
2618
|
-
const branchName =
|
|
2619
|
-
const containerName =
|
|
2620
|
-
const projectName =
|
|
2621
|
-
const domainSuffix =
|
|
2622
|
-
const previewPort =
|
|
2873
|
+
const branchName = process.env.PAW_IN_NEEDS_CHECK_COMMAND_OUTPUTS_CUSTOM_BRANCH;
|
|
2874
|
+
const containerName = process.env.PAW_IN_STEPS_CONTAINER_INFO_OUTPUTS_CONTAINER_NAME;
|
|
2875
|
+
const projectName = process.env.PROJECT_PATH !== '.' ? process.env.PROJECT_NAME + '-go' : process.env.PROJECT_NAME;
|
|
2876
|
+
const domainSuffix = process.env.PREVIEW_DOMAIN_SUFFIX;
|
|
2877
|
+
const previewPort = process.env.PREVIEW_PORT;
|
|
2623
2878
|
const domain = `${containerName}.${domainSuffix}`;
|
|
2624
2879
|
const previewUrl = `http://${domain}:${previewPort}`;
|
|
2625
|
-
const isRunning =
|
|
2880
|
+
const isRunning = process.env.PAW_IN_STEPS_CHECK_RUNNING_OUTCOME === 'success';
|
|
2626
2881
|
|
|
2627
2882
|
let body;
|
|
2628
2883
|
if (isRunning) {
|