project-auto-wizard 0.13.3 → 0.14.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.md +1 -1
- package/bin/project-auto-wizard.js +18 -4
- package/package.json +2 -2
- package/payload/config/breaking-changes.json +28 -14
- package/payload/config/wizard-prompts.yml +102 -46
- package/payload/flutter-app/android/fastlane/Fastfile.playstore +44 -32
- package/payload/flutter-app/ios/ExportOptions.plist +8 -8
- package/payload/flutter-app/ios/fastlane/Fastfile +57 -43
- package/payload/scripts/changelog_manager.py +296 -257
- package/payload/scripts/issue_helper.py +54 -50
- package/payload/scripts/messages.py +2279 -0
- package/payload/scripts/truncate_release_notes.py +7 -6
- package/payload/scripts/version_manager.py +64 -61
- package/payload/version.yml.template +2 -1
- package/payload/workflows/common/PROJECT-COMMON-AI-PR-SUMMARY.yaml +17 -12
- package/payload/workflows/common/PROJECT-COMMON-AUTO-CHANGELOG-CONTROL.yaml +59 -34
- package/payload/workflows/common/PROJECT-COMMON-ISSUE-HELPER.yaml +17 -15
- package/payload/workflows/common/PROJECT-COMMON-README-VERSION-UPDATE.yaml +17 -10
- package/payload/workflows/common/PROJECT-COMMON-RELEASE-PUBLISH.yaml +54 -44
- package/payload/workflows/common/PROJECT-COMMON-VERSION-CONTROL.yaml +24 -17
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-FIREBASE-CICD.yaml +194 -184
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-PLAYSTORE-CICD.yaml +226 -213
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-SELFHOSTED-CICD.yaml +46 -42
- package/payload/workflows/flutter/PROJECT-FLUTTER-ANDROID-TEST-APK.yaml +334 -241
- package/payload/workflows/flutter/PROJECT-FLUTTER-APP-BUILD-TRIGGER.yaml +152 -128
- package/payload/workflows/flutter/PROJECT-FLUTTER-CI.yaml +246 -188
- package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml +353 -238
- package/payload/workflows/flutter/PROJECT-FLUTTER-IOS-TESTFLIGHT.yaml +96 -85
- package/payload/workflows/go/PROJECT-GO-CI.yaml +47 -36
- package/payload/workflows/go/PROJECT-GO-PR-PREVIEW.yaml +945 -508
- package/payload/workflows/go/PROJECT-GO-SIMPLE-CICD.yaml +155 -133
- package/payload/workflows/next/PROJECT-NEXT-CI.yaml +76 -60
- package/payload/workflows/next/PROJECT-NEXT-CICD.yaml +97 -77
- package/payload/workflows/python/PROJECT-PYTHON-CI.yaml +62 -47
- package/payload/workflows/python/PROJECT-PYTHON-PR-PREVIEW.yaml +942 -505
- package/payload/workflows/python/PROJECT-PYTHON-SIMPLE-CICD.yaml +148 -126
- package/payload/workflows/react/PROJECT-REACT-CI.yaml +86 -70
- package/payload/workflows/react/PROJECT-REACT-CICD.yaml +112 -92
- package/payload/workflows/spring/PROJECT-SPRING-CI.yml +112 -82
- package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-NGINX-CICD.yaml +180 -150
- package/payload/workflows/spring/server-deploy/PROJECT-SPRING-NONSTOP-TRAEFIK-CICD.yaml +161 -131
- package/payload/workflows/spring/server-deploy/PROJECT-SPRING-PR-PREVIEW.yaml +970 -549
- package/payload/workflows/spring/server-deploy/PROJECT-SPRING-SIMPLE-CICD.yaml +193 -162
- package/src/cli/args.js +98 -52
- package/src/cli/help.js +8 -41
- package/src/commands/doctor.js +85 -89
- package/src/commands/dry-run.js +63 -43
- package/src/commands/full.js +79 -77
- package/src/commands/install-settings.js +16 -15
- package/src/commands/interactive-flutter.js +20 -19
- package/src/commands/interactive.js +135 -132
- package/src/commands/purge.js +47 -42
- package/src/commands/status.js +36 -36
- package/src/commands/uninstall.js +43 -41
- package/src/context.js +12 -11
- package/src/core/assets.js +12 -11
- package/src/core/baseline.js +27 -27
- package/src/core/branches.js +29 -27
- package/src/core/branding.js +7 -6
- package/src/core/breaking-check.js +22 -21
- package/src/core/breaking.js +15 -8
- package/src/core/copy/app-files.js +5 -4
- package/src/core/copy/flutter-app.js +8 -8
- package/src/core/copy/gitignore.js +58 -50
- package/src/core/copy/readme.js +45 -35
- package/src/core/copy/simple.js +16 -15
- package/src/core/copy/workflows.js +131 -124
- package/src/core/deploy-style.js +51 -48
- package/src/core/detect-fs.js +57 -57
- package/src/core/detect.js +67 -65
- package/src/core/errors.js +2 -2
- package/src/core/flutter-doctor.js +17 -16
- package/src/core/flutter-hooks.js +33 -32
- package/src/core/flutter-options.js +34 -33
- package/src/core/fsutil.js +12 -12
- package/src/core/installed-stores.js +4 -4
- package/src/core/logger.js +42 -40
- package/src/core/paths-resolve.js +88 -86
- package/src/core/paths.js +10 -10
- package/src/core/release-options.js +8 -8
- package/src/core/removal-exec.js +14 -13
- package/src/core/removal-plan.js +37 -37
- package/src/core/types.js +47 -47
- package/src/core/verify.js +44 -38
- package/src/core/version-yml.js +76 -68
- package/src/core/wizard-env.js +46 -46
- package/src/core/wizard-labels.js +63 -41
- package/src/i18n/catalog/en/cli.js +50 -0
- package/src/i18n/catalog/en/commands.js +187 -0
- package/src/i18n/catalog/en/copy.js +19 -0
- package/src/i18n/catalog/en/core.js +74 -0
- package/src/i18n/catalog/en/core2.js +15 -0
- package/src/i18n/catalog/en/ui.js +221 -0
- package/src/i18n/catalog/en.js +12 -0
- package/src/i18n/catalog/index.js +5 -0
- package/src/i18n/catalog/ko/cli.js +50 -0
- package/src/i18n/catalog/ko/commands.js +187 -0
- package/src/i18n/catalog/ko/copy.js +19 -0
- package/src/i18n/catalog/ko/core.js +74 -0
- package/src/i18n/catalog/ko/core2.js +15 -0
- package/src/i18n/catalog/ko/ui.js +221 -0
- package/src/i18n/catalog/ko.js +10 -0
- package/src/i18n/index.js +44 -0
- package/src/i18n/languages.js +9 -0
- package/src/index.js +128 -94
- package/src/ui/ansi.js +7 -7
- package/src/ui/banner.js +7 -6
- package/src/ui/env-plan.js +82 -81
- package/src/ui/prompts.js +97 -122
- package/src/ui/readline-engine.js +59 -58
- package/src/ui/status-cards.js +37 -31
- package/src/ui/summary.js +89 -88
|
@@ -69,7 +69,7 @@ permissions:
|
|
|
69
69
|
copilot-requests: write
|
|
70
70
|
|
|
71
71
|
env:
|
|
72
|
-
#
|
|
72
|
+
# Keep script imports from creating .github/scripts/__pycache__ so it never ends up in bot commits
|
|
73
73
|
PYTHONDONTWRITEBYTECODE: "1"
|
|
74
74
|
|
|
75
75
|
jobs:
|
|
@@ -96,9 +96,11 @@ jobs:
|
|
|
96
96
|
GH_REPO: ${{ github.repository }}
|
|
97
97
|
run: |
|
|
98
98
|
PR_NUMBER=${{ github.event.pull_request.number }}
|
|
99
|
-
#
|
|
100
|
-
# PR
|
|
101
|
-
#
|
|
99
|
+
# A push to {{DEVELOP_BRANCH}} mid-pipeline queues a run that later reprocesses the
|
|
100
|
+
# already-merged PR - an empty summary comment, duplicate CHANGELOG entries and a
|
|
101
|
+
# confirm commit that lands only on {{DEVELOP_BRANCH}}.
|
|
102
|
+
# Look at the current state, not the event-time state. If the lookup fails,
|
|
103
|
+
# do not block the release and carry on.
|
|
102
104
|
STATE=$(gh pr view "$PR_NUMBER" --json state -q .state 2>/dev/null || echo "UNKNOWN")
|
|
103
105
|
if [ "$STATE" = "MERGED" ] || [ "$STATE" = "CLOSED" ]; then
|
|
104
106
|
echo "open=false" >> "$GITHUB_OUTPUT"
|
|
@@ -152,8 +154,9 @@ jobs:
|
|
|
152
154
|
run: |
|
|
153
155
|
git fetch origin {{MAIN_BRANCH}}
|
|
154
156
|
git log --pretty=%s "origin/{{MAIN_BRANCH}}..HEAD" > commits.txt
|
|
155
|
-
#
|
|
156
|
-
#
|
|
157
|
+
# Body-footer BREAKING CHANGE: lines are appended after the subject list, one per
|
|
158
|
+
# line. The script reads each line as one entry, so passing the whole body (%B)
|
|
159
|
+
# would turn description lines into change entries.
|
|
157
160
|
git log --pretty=%b "origin/{{MAIN_BRANCH}}..HEAD" | grep -E '^BREAKING[ -]CHANGE[[:space:]]*:' >> commits.txt || true
|
|
158
161
|
git diff --stat "origin/{{MAIN_BRANCH}}...HEAD" > _full_diff_stat.txt
|
|
159
162
|
if [ "$(wc -l < _full_diff_stat.txt)" -gt 49 ]; then
|
|
@@ -170,6 +173,7 @@ jobs:
|
|
|
170
173
|
GH_TOKEN: ${{ github.token }}
|
|
171
174
|
GITHUB_TOKEN: ${{ github.token }}
|
|
172
175
|
run: |
|
|
176
|
+
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
173
177
|
git log --pretty=%H "origin/{{MAIN_BRANCH}}..HEAD" > commit_shas.txt
|
|
174
178
|
|
|
175
179
|
gh pr list --state merged --base {{DEVELOP_BRANCH}} \
|
|
@@ -177,7 +181,7 @@ jobs:
|
|
|
177
181
|
|
|
178
182
|
MERGED_PR_COUNT=$(python3 -c "import json; print(len(json.load(open('merged_prs.json'))))")
|
|
179
183
|
if [ "$MERGED_PR_COUNT" -ge 200 ]; then
|
|
180
|
-
echo "::warning
|
|
184
|
+
echo "::warning::$(m wf_changelog.pr_list_limit count="$MERGED_PR_COUNT")"
|
|
181
185
|
fi
|
|
182
186
|
|
|
183
187
|
ISSUE_NUMBERS=$(python3 .github/scripts/changelog_manager.py collect-issue-closes \
|
|
@@ -187,7 +191,7 @@ jobs:
|
|
|
187
191
|
rm -f commit_shas.txt merged_prs.json
|
|
188
192
|
|
|
189
193
|
if [ -z "$ISSUE_NUMBERS" ]; then
|
|
190
|
-
echo "
|
|
194
|
+
echo "$(m wf_changelog.no_issues)"
|
|
191
195
|
exit 0
|
|
192
196
|
fi
|
|
193
197
|
|
|
@@ -196,7 +200,7 @@ jobs:
|
|
|
196
200
|
--issue-numbers "$ISSUE_NUMBERS" \
|
|
197
201
|
--replace
|
|
198
202
|
|
|
199
|
-
echo "
|
|
203
|
+
echo "$(m wf_changelog.issues_linked issues="$ISSUE_NUMBERS")"
|
|
200
204
|
|
|
201
205
|
- name: Confirm release version (bump + sync)
|
|
202
206
|
id: bump
|
|
@@ -207,9 +211,11 @@ jobs:
|
|
|
207
211
|
GITHUB_TOKEN: ${{ github.token }}
|
|
208
212
|
COPILOT_AI: ${{ steps.copilot_options.outputs.copilot_ai }}
|
|
209
213
|
run: |
|
|
210
|
-
#
|
|
211
|
-
#
|
|
212
|
-
#
|
|
214
|
+
# Idempotency: never raise a version this PR already confirmed (not yet published).
|
|
215
|
+
# Looking only at the HEAD commit message lets the guard slip when more commits
|
|
216
|
+
# pile on top of the confirm commit (extra {{DEVELOP_BRANCH}} pushes, a
|
|
217
|
+
# {{MAIN_BRANCH}} back-merge) and an unpublished version appears, so decide by
|
|
218
|
+
# version and tag instead.
|
|
213
219
|
HEAD_MSG=$(git log -1 --pretty=%s)
|
|
214
220
|
HEAD_VERSION=$(python3 .github/scripts/version_manager.py get | tail -n 1)
|
|
215
221
|
MAIN_VERSION=$(git show "origin/{{MAIN_BRANCH}}:version.yml" 2>/dev/null | grep -m1 '^version:' | sed 's/version:[ \t]*"\{0,1\}\([0-9][0-9.]*\)"\{0,1\}.*/\1/' || true)
|
|
@@ -224,8 +230,10 @@ jobs:
|
|
|
224
230
|
echo "bump level: $BUMP"
|
|
225
231
|
|
|
226
232
|
if [ -n "$MAIN_VERSION" ] && [ -n "$HEAD_VERSION" ] && version_gt "$HEAD_VERSION" "$MAIN_VERSION" && ! is_tagged "$HEAD_VERSION"; then
|
|
227
|
-
#
|
|
228
|
-
#
|
|
233
|
+
# Already-confirmed version - recompute from the {{MAIN_BRANCH}} version and raise it
|
|
234
|
+
# only when the result is higher (e.g. a feat added after confirming).
|
|
235
|
+
# Versions are never skipped, and they never drop even if an AI-assisted
|
|
236
|
+
# classification differs between re-runs.
|
|
229
237
|
TARGET=$(python3 -c 'import sys; sys.path.insert(0, ".github/scripts"); from version_manager import increment_version; print(increment_version(sys.argv[1], sys.argv[2]))' "$MAIN_VERSION" "$BUMP")
|
|
230
238
|
if version_gt "$TARGET" "$HEAD_VERSION"; then
|
|
231
239
|
NEW_VERSION=$(python3 .github/scripts/version_manager.py set "$TARGET" | tail -n 1)
|
|
@@ -235,7 +243,7 @@ jobs:
|
|
|
235
243
|
echo "version already confirmed and not yet released — reusing $NEW_VERSION ({{MAIN_BRANCH}} is $MAIN_VERSION)"
|
|
236
244
|
fi
|
|
237
245
|
elif [ -z "$MAIN_VERSION" ] && printf '%s\n' "$HEAD_MSG" | grep -q "^chore(version): confirm v.* \[skip ci\]"; then
|
|
238
|
-
# {{MAIN_BRANCH}}
|
|
246
|
+
# Re-run of a first release where {{MAIN_BRANCH}} has no version.yml yet
|
|
239
247
|
NEW_VERSION="$HEAD_VERSION"
|
|
240
248
|
echo "version already confirmed by a previous run — reusing $NEW_VERSION (no re-increment)"
|
|
241
249
|
else
|
|
@@ -270,7 +278,7 @@ jobs:
|
|
|
270
278
|
--pr-title "$PR_TITLE" \
|
|
271
279
|
--diff-stat-file diff_stat.txt | tail -n 1)
|
|
272
280
|
ENGINE=$(python3 -c 'import json,sys; print(json.loads(sys.argv[1]).get("engine") or "unknown")' "$SUMMARY_RESULT" 2>/dev/null || echo "unknown")
|
|
273
|
-
# fallback
|
|
281
|
+
# On fallback, append the reason (the script also emits it as ::warning::) to the engine line so the cause is visible without opening the job log
|
|
274
282
|
FALLBACK_REASON=$(python3 -c 'import html,json,sys; print(html.escape((json.loads(sys.argv[1]).get("fallback_reason") or "")[:200]))' "$SUMMARY_RESULT" 2>/dev/null || echo "")
|
|
275
283
|
ENGINE_LINE="$ENGINE${FALLBACK_REASON:+ ($FALLBACK_REASON)}"
|
|
276
284
|
echo "summary engine: $ENGINE_LINE"
|
|
@@ -289,7 +297,7 @@ jobs:
|
|
|
289
297
|
GH_TOKEN: ${{ github.token }}
|
|
290
298
|
run: |
|
|
291
299
|
PR_NUMBER=${{ github.event.pull_request.number }}
|
|
292
|
-
#
|
|
300
|
+
# Find this bot's earlier summary comment by its marker and replace it so re-runs and re-syncs do not pile up comments
|
|
293
301
|
MARKER="<!-- project-auto-wizard:pr-summary -->"
|
|
294
302
|
|
|
295
303
|
{
|
|
@@ -343,17 +351,18 @@ jobs:
|
|
|
343
351
|
# Working files must not land in the repo
|
|
344
352
|
rm -f pr_body.md summary.md commits.txt diff_stat.txt comment_body.md comment_payload.json commit_shas.txt merged_prs.json
|
|
345
353
|
|
|
346
|
-
# "Re-run failed jobs"
|
|
347
|
-
#
|
|
354
|
+
# "Re-run failed jobs" reuses the precheck result - if the PR was merged or closed
|
|
355
|
+
# in the meantime, do not push the confirm commit (it would exist only on
|
|
356
|
+
# {{DEVELOP_BRANCH}} after the merge).
|
|
348
357
|
PR_STATE=$(gh pr view "${{ github.event.pull_request.number }}" --json state -q .state 2>/dev/null || echo "UNKNOWN")
|
|
349
358
|
if [ "$PR_STATE" = "MERGED" ] || [ "$PR_STATE" = "CLOSED" ]; then
|
|
350
359
|
echo "::notice::PR is already $PR_STATE — not pushing release docs"
|
|
351
360
|
exit 0
|
|
352
361
|
fi
|
|
353
362
|
|
|
354
|
-
# -A
|
|
355
|
-
#
|
|
356
|
-
#
|
|
363
|
+
# -A would also commit runner temp files and caches into the user's repo.
|
|
364
|
+
# Version files are already tracked, so -u is enough; only a CHANGELOG
|
|
365
|
+
# created by the first release is added separately (skipped if ignored).
|
|
357
366
|
git add -u
|
|
358
367
|
git ls-files -z --others --exclude-standard -- CHANGELOG.json CHANGELOG.md | xargs -0 -r git add --
|
|
359
368
|
|
|
@@ -399,6 +408,7 @@ jobs:
|
|
|
399
408
|
# (RELEASE-PUBLISH etc.); GITHUB_TOKEN merges do not.
|
|
400
409
|
GH_TOKEN: ${{ secrets.WORKFLOW_PAT || github.token }}
|
|
401
410
|
run: |
|
|
411
|
+
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
402
412
|
PR_NUMBER=${{ github.event.pull_request.number }}
|
|
403
413
|
VERSION="${{ steps.bump.outputs.new_version }}"
|
|
404
414
|
|
|
@@ -407,8 +417,9 @@ jobs:
|
|
|
407
417
|
SUBJECT="chore(release): v${VERSION} (PR #${PR_NUMBER})"
|
|
408
418
|
ERR_FILE="${RUNNER_TEMP:-/tmp}/merge_err.txt"
|
|
409
419
|
|
|
410
|
-
#
|
|
411
|
-
#
|
|
420
|
+
# Right after the confirm commit is pushed, GitHub may not have picked up the new PR
|
|
421
|
+
# head yet and intermittently fails with "Head branch is out of date" / "not
|
|
422
|
+
# mergeable". Retry with growing intervals.
|
|
412
423
|
MERGED=false
|
|
413
424
|
MAX_ATTEMPTS=4
|
|
414
425
|
for ATTEMPT in $(seq 1 $MAX_ATTEMPTS); do
|
|
@@ -430,11 +441,12 @@ jobs:
|
|
|
430
441
|
fi
|
|
431
442
|
cat "$ERR_FILE" >&2
|
|
432
443
|
[ "$ATTEMPT" -ge "$MAX_ATTEMPTS" ] && break
|
|
433
|
-
#
|
|
444
|
+
# A conflict never resolves by waiting
|
|
434
445
|
[ "$(gh pr view "$PR_NUMBER" --json mergeable -q .mergeable 2>/dev/null)" = "CONFLICTING" ] && break
|
|
435
446
|
if grep -qi "out of date" "$ERR_FILE"; then
|
|
436
|
-
#
|
|
437
|
-
#
|
|
447
|
+
# If the head really fell behind because of branch protection's "require up to
|
|
448
|
+
# date" rule, merge base into head to catch up (a mere propagation delay is
|
|
449
|
+
# rejected as "no new commits" and simply retried)
|
|
438
450
|
gh api -X PUT "repos/${GITHUB_REPOSITORY}/pulls/${PR_NUMBER}/update-branch" > /dev/null 2>&1 \
|
|
439
451
|
&& echo "head branch updated from base" || true
|
|
440
452
|
fi
|
|
@@ -448,10 +460,10 @@ jobs:
|
|
|
448
460
|
MERGEABLE=$(gh pr view "$PR_NUMBER" --json mergeable -q .mergeable 2>/dev/null || echo "unknown")
|
|
449
461
|
ALLOW_MERGE_COMMIT=$(gh api "repos/${GITHUB_REPOSITORY}" --jq '.allow_merge_commit' 2>/dev/null || echo "unknown")
|
|
450
462
|
if [ "$MERGEABLE" = "CONFLICTING" ]; then
|
|
451
|
-
#
|
|
452
|
-
echo "::error
|
|
463
|
+
# Mostly happens when a safety-net version bump after a direct {{MAIN_BRANCH}} push never reached {{DEVELOP_BRANCH}}
|
|
464
|
+
echo "::error::$(m wf_changelog.merge_conflict prod="{{MAIN_BRANCH}}" dev="{{DEVELOP_BRANCH}}")"
|
|
453
465
|
elif [ "$ALLOW_MERGE_COMMIT" = "false" ]; then
|
|
454
|
-
echo "::error
|
|
466
|
+
echo "::error::$(m wf_changelog.merge_commit_disabled)"
|
|
455
467
|
else
|
|
456
468
|
echo "::error::PR merge failed after $MAX_ATTEMPTS attempts (allow_merge_commit=$ALLOW_MERGE_COMMIT) — check branch protection rules, required checks, and token permissions"
|
|
457
469
|
fi
|
|
@@ -459,20 +471,32 @@ jobs:
|
|
|
459
471
|
fi
|
|
460
472
|
|
|
461
473
|
wait-for-merge-and-trigger-release:
|
|
462
|
-
name: Wait for merge and trigger RELEASE-PUBLISH (
|
|
474
|
+
name: Wait for merge and trigger RELEASE-PUBLISH (works without WORKFLOW_PAT)
|
|
463
475
|
needs: changelog-and-merge
|
|
464
476
|
runs-on: ubuntu-latest
|
|
465
477
|
timeout-minutes: 35
|
|
466
478
|
permissions:
|
|
479
|
+
# contents: read is needed for the sparse checkout that loads the message catalog
|
|
480
|
+
contents: read
|
|
467
481
|
pull-requests: read
|
|
468
482
|
actions: write
|
|
469
483
|
steps:
|
|
484
|
+
# Only the message catalog and version.yml (language) are needed here
|
|
485
|
+
- name: Checkout message catalog
|
|
486
|
+
uses: actions/checkout@v7
|
|
487
|
+
with:
|
|
488
|
+
sparse-checkout: |
|
|
489
|
+
.github/scripts/messages.py
|
|
490
|
+
version.yml
|
|
491
|
+
sparse-checkout-cone-mode: false
|
|
492
|
+
|
|
470
493
|
- name: Poll for merge completion
|
|
471
494
|
id: wait
|
|
472
495
|
env:
|
|
473
496
|
GH_TOKEN: ${{ github.token }}
|
|
474
497
|
GH_REPO: ${{ github.repository }}
|
|
475
498
|
run: |
|
|
499
|
+
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
476
500
|
PR_NUMBER=${{ github.event.pull_request.number }}
|
|
477
501
|
MAX_WAIT=1800
|
|
478
502
|
INTERVAL=20
|
|
@@ -483,7 +507,7 @@ jobs:
|
|
|
483
507
|
PR_STATE=$(gh pr view "$PR_NUMBER" --json state -q .state 2>/dev/null || echo "")
|
|
484
508
|
if [ "$PR_STATE" = "MERGED" ]; then
|
|
485
509
|
MERGED=true
|
|
486
|
-
echo "
|
|
510
|
+
echo "$(m wf_changelog.merge_confirmed pr="$PR_NUMBER" elapsed="$ELAPSED")"
|
|
487
511
|
break
|
|
488
512
|
fi
|
|
489
513
|
sleep $INTERVAL
|
|
@@ -491,7 +515,7 @@ jobs:
|
|
|
491
515
|
done
|
|
492
516
|
|
|
493
517
|
if [ "$MERGED" != "true" ]; then
|
|
494
|
-
echo "::warning
|
|
518
|
+
echo "::warning::$(m wf_changelog.merge_timeout pr="$PR_NUMBER" max="$MAX_WAIT")"
|
|
495
519
|
fi
|
|
496
520
|
|
|
497
521
|
echo "merged=$MERGED" >> "$GITHUB_OUTPUT"
|
|
@@ -503,5 +527,6 @@ jobs:
|
|
|
503
527
|
GH_TOKEN: ${{ github.token }}
|
|
504
528
|
GH_REPO: ${{ github.repository }}
|
|
505
529
|
run: |
|
|
530
|
+
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
506
531
|
gh workflow run PROJECT-COMMON-RELEASE-PUBLISH.yaml --ref {{MAIN_BRANCH}}
|
|
507
|
-
echo "
|
|
532
|
+
echo "$(m wf_changelog.release_publish_triggered)"
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
# project-auto-wizard:managed-workflow
|
|
2
2
|
# PROJECT-COMMON-ISSUE-HELPER.yaml
|
|
3
|
-
#
|
|
3
|
+
# Suggest a branch name and commit message as a comment when an issue is created or retitled
|
|
4
4
|
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
5
|
+
# When an issue is opened, or its title is edited (edited + title changed),
|
|
6
|
+
# the normalized branch name and commit message are posted (or updated) as an
|
|
7
|
+
# issue comment.
|
|
8
|
+
# Set ISSUE_HELPER_CREATE_BRANCH=true to also create the branch
|
|
9
|
+
# (default is false - opt-in, so a branch is not created automatically
|
|
10
|
+
# every time an issue is opened).
|
|
10
11
|
#
|
|
11
|
-
#
|
|
12
|
-
#
|
|
12
|
+
# The logic lives in .github/scripts/issue_helper.py (a Python rewrite of
|
|
13
|
+
# Chuseok22/github-issue-helper, same author).
|
|
13
14
|
|
|
14
15
|
name: PROJECT-ISSUE-HELPER
|
|
15
16
|
|
|
@@ -17,30 +18,31 @@ on:
|
|
|
17
18
|
issues:
|
|
18
19
|
types: [opened, edited]
|
|
19
20
|
|
|
20
|
-
# contents
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
# permissions
|
|
21
|
+
# contents is always fixed to write. Creating a branch through the git/refs API
|
|
22
|
+
# when ISSUE_HELPER_CREATE_BRANCH="true" needs write, and users can switch that
|
|
23
|
+
# value on themselves after install (via the wizard ask marker, without re-running the
|
|
24
|
+
# wizard), so there is no way to raise permissions conditionally at that point.
|
|
24
25
|
permissions:
|
|
25
26
|
issues: write
|
|
26
27
|
contents: write
|
|
27
28
|
|
|
28
29
|
jobs:
|
|
29
30
|
issue-helper:
|
|
30
|
-
name:
|
|
31
|
+
name: Branch name & commit message guide
|
|
31
32
|
if: github.event.action == 'opened' || (github.event.action == 'edited' && github.event.changes.title)
|
|
32
33
|
runs-on: ubuntu-latest
|
|
33
34
|
env:
|
|
34
35
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
35
36
|
ISSUE_HELPER_BRANCH_PREFIX: ""
|
|
36
37
|
ISSUE_HELPER_MAX_BRANCH_LENGTH: "100"
|
|
37
|
-
|
|
38
|
+
# Optional override of the commit message template (the default follows the workflow language):
|
|
39
|
+
# ISSUE_HELPER_COMMIT_TEMPLATE: "${issueTitle} : feat : {description of the change} ${issueUrl}"
|
|
38
40
|
ISSUE_HELPER_CREATE_BRANCH: "false" # @wizard ask:false
|
|
39
41
|
ISSUE_HELPER_BASE_BRANCH: "{{MAIN_BRANCH}}"
|
|
40
42
|
steps:
|
|
41
43
|
- name: Checkout repository
|
|
42
44
|
uses: actions/checkout@v7
|
|
43
45
|
|
|
44
|
-
- name:
|
|
46
|
+
- name: Generate branch name & commit message
|
|
45
47
|
id: issue-helper
|
|
46
48
|
run: python3 .github/scripts/issue_helper.py run
|
|
@@ -12,13 +12,12 @@
|
|
|
12
12
|
# 4. Commits and pushes the change ([skip ci])
|
|
13
13
|
#
|
|
14
14
|
# Supported version line formats (case-insensitive, flexible spacing):
|
|
15
|
-
# - ##
|
|
16
|
-
# - ## 최신버전 : v1.0.0 (2025-08-15)
|
|
15
|
+
# - ## <Korean "latest version", with or without a space> : v1.0.0 (2025-08-15)
|
|
17
16
|
# - ## Current Version : v1.0.0 (2025-08-15)
|
|
18
17
|
# - ## Recent Version : v1.0.0 (2025-08-15)
|
|
19
18
|
# - ## Latest Version : v1.0.0
|
|
20
19
|
# - ## Version : v1.0.0
|
|
21
|
-
# - ##
|
|
20
|
+
# - ## <Korean "version"> : v1.0.0
|
|
22
21
|
#
|
|
23
22
|
# The marker comment <!-- AUTO-VERSION-SECTION: DO NOT EDIT MANUALLY -->
|
|
24
23
|
# is added automatically above the version line.
|
|
@@ -51,7 +50,7 @@ name: README VERSION UPDATE
|
|
|
51
50
|
env:
|
|
52
51
|
# Whether to show the date next to the version (true/false)
|
|
53
52
|
SHOW_DATE: true
|
|
54
|
-
#
|
|
53
|
+
# Keep script imports from creating .github/scripts/__pycache__ so it never ends up in bot commits
|
|
55
54
|
PYTHONDONTWRITEBYTECODE: "1"
|
|
56
55
|
|
|
57
56
|
concurrency:
|
|
@@ -113,10 +112,16 @@ jobs:
|
|
|
113
112
|
- name: Update version line in README.md
|
|
114
113
|
if: steps.precheck.outputs.readme_exists == 'true'
|
|
115
114
|
run: |
|
|
115
|
+
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
116
116
|
LATEST_VERSION="${{ steps.version_info.outputs.latest_version }}"
|
|
117
117
|
RELEASE_DATE="${{ steps.version_info.outputs.release_date }}"
|
|
118
118
|
SHOW_DATE="${{ env.SHOW_DATE }}"
|
|
119
119
|
|
|
120
|
+
# Hangul in the Korean heading patterns below is written as UTF-8 byte escapes so
|
|
121
|
+
# this file stays ASCII-only; they match the same README headings byte for byte.
|
|
122
|
+
KO_LATEST=$'\354\265\234\354\213\240' # Korean "latest"
|
|
123
|
+
KO_VERSION=$'\353\262\204\354\240\204' # Korean "version"
|
|
124
|
+
|
|
120
125
|
# Error message helper
|
|
121
126
|
print_error_message() {
|
|
122
127
|
local error_type="$1"
|
|
@@ -132,7 +137,7 @@ jobs:
|
|
|
132
137
|
echo " new version text: $version_text"
|
|
133
138
|
echo ""
|
|
134
139
|
echo "Make sure the README version line matches one of:"
|
|
135
|
-
echo "
|
|
140
|
+
echo " $(m wf_readme.hint_first_example)"
|
|
136
141
|
echo " ## Current Version : v1.0.0"
|
|
137
142
|
echo " ## Version : v1.0.0"
|
|
138
143
|
echo "Notes:"
|
|
@@ -151,12 +156,12 @@ jobs:
|
|
|
151
156
|
|
|
152
157
|
# Patterns for recognized version lines (case-insensitive, flexible spacing)
|
|
153
158
|
VERSION_PATTERNS=(
|
|
154
|
-
"^##[[:space:]]
|
|
155
|
-
"^##[[:space:]]
|
|
159
|
+
"^##[[:space:]]*${KO_LATEST}[[:space:]]*${KO_VERSION}[[:space:]]*:"
|
|
160
|
+
"^##[[:space:]]*${KO_LATEST}${KO_VERSION}[[:space:]]*:"
|
|
156
161
|
"^##[[:space:]]*[Cc]urrent[[:space:]]*[Vv]ersion[[:space:]]*:"
|
|
157
162
|
"^##[[:space:]]*[Rr]ecent[[:space:]]*[Vv]ersion[[:space:]]*:"
|
|
158
163
|
"^##[[:space:]]*[Vv]ersion[[:space:]]*:"
|
|
159
|
-
"^##[[:space:]]
|
|
164
|
+
"^##[[:space:]]*${KO_VERSION}[[:space:]]*:"
|
|
160
165
|
"^##[[:space:]]*[Ll]atest[[:space:]]*[Vv]ersion[[:space:]]*:"
|
|
161
166
|
)
|
|
162
167
|
|
|
@@ -175,13 +180,15 @@ jobs:
|
|
|
175
180
|
# No version line yet — insert a default one
|
|
176
181
|
if [ -z "$VERSION_LINE" ]; then
|
|
177
182
|
echo "no version line found — inserting a new one"
|
|
183
|
+
# Heading wording follows the configured language; an existing line keeps its own wording
|
|
184
|
+
DEFAULT_HEADING=$(m wf_readme.default_heading)
|
|
178
185
|
|
|
179
186
|
if grep -q "^# " README.md; then
|
|
180
187
|
# right after the first title
|
|
181
|
-
sed -i '/^# /a\\n<!-- AUTO-VERSION-SECTION: DO NOT EDIT MANUALLY -->\n##
|
|
188
|
+
sed -i '/^# /a\\n<!-- AUTO-VERSION-SECTION: DO NOT EDIT MANUALLY -->\n## '"$DEFAULT_HEADING"' : '"$VERSION_TEXT" README.md
|
|
182
189
|
else
|
|
183
190
|
# at the very top of the file
|
|
184
|
-
sed -i '1i\<!-- AUTO-VERSION-SECTION: DO NOT EDIT MANUALLY -->\n##
|
|
191
|
+
sed -i '1i\<!-- AUTO-VERSION-SECTION: DO NOT EDIT MANUALLY -->\n## '"$DEFAULT_HEADING"' : '"$VERSION_TEXT"'\n' README.md
|
|
185
192
|
fi
|
|
186
193
|
echo "default version line inserted: $VERSION_TEXT"
|
|
187
194
|
else
|