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
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
# project-auto-wizard:managed-workflow
|
|
2
|
-
# Flutter
|
|
2
|
+
# Flutter test app build trigger workflow
|
|
3
3
|
#
|
|
4
|
-
#
|
|
5
|
-
# Android
|
|
4
|
+
# When a build command is posted as a comment on a PR or issue, this workflow
|
|
5
|
+
# triggers the Android and iOS test app builds automatically.
|
|
6
6
|
#
|
|
7
|
-
#
|
|
8
|
-
# - PR
|
|
9
|
-
# -
|
|
10
|
-
# -
|
|
11
|
-
# -
|
|
12
|
-
# -
|
|
7
|
+
# Highlights:
|
|
8
|
+
# - Detects PR/issue comments: "/wizard app build / apk build / ios build" keywords (word order does not matter: "build app" works too)
|
|
9
|
+
# - Triggers the build workflows through repository_dispatch events
|
|
10
|
+
# - Builds a unique build number from the PR/issue number + build count (e.g. 38700, 38701...)
|
|
11
|
+
# - Extracts the issue number from the branch name automatically (YYYYMMDD_#issue-number_title format)
|
|
12
|
+
# - The test version is read dynamically from version.yml (production and test builds are told apart by build number)
|
|
13
13
|
#
|
|
14
|
-
#
|
|
15
|
-
# -
|
|
16
|
-
# -
|
|
17
|
-
# -
|
|
18
|
-
# -
|
|
19
|
-
# -
|
|
20
|
-
# -
|
|
21
|
-
#
|
|
22
|
-
#
|
|
14
|
+
# Usage:
|
|
15
|
+
# - Comment on a PR: "/wizard app build" (builds Android + iOS)
|
|
16
|
+
# - Comment on a PR: "/wizard apk build" (Android only)
|
|
17
|
+
# - Comment on a PR: "/wizard ios build" (iOS only)
|
|
18
|
+
# - Comment on an issue: same commands (an Issue Helper comment is required)
|
|
19
|
+
# - Word order does not matter: "build app" / "build apk" / "build ios" behave the same
|
|
20
|
+
# - To build a specific branch: "/wizard app build <branch-name>" (a branch name after the command builds that branch)
|
|
21
|
+
# e.g. "/wizard apk build 20260609_#12_feature" -> Android build of that branch
|
|
22
|
+
# If the branch name is omitted, the PR head or the branch in the issue's Issue Helper comment is used
|
|
23
23
|
#
|
|
24
|
-
#
|
|
24
|
+
# Workflows triggered:
|
|
25
25
|
# - PROJECT-FLUTTER-ANDROID-TEST-APK.yaml (event_type: build-android-app)
|
|
26
26
|
# - PROJECT-FLUTTER-IOS-TEST-TESTFLIGHT.yaml (event_type: build-ios-app)
|
|
27
27
|
|
|
@@ -38,8 +38,8 @@ permissions:
|
|
|
38
38
|
|
|
39
39
|
jobs:
|
|
40
40
|
trigger-builds:
|
|
41
|
-
name:
|
|
42
|
-
# /wizard app build / /wizard apk build / /wizard ios build
|
|
41
|
+
name: Trigger build workflows
|
|
42
|
+
# Detect the /wizard app build / /wizard apk build / /wizard ios build keywords (word order does not matter)
|
|
43
43
|
if: |
|
|
44
44
|
contains(github.event.comment.body, '/wizard') &&
|
|
45
45
|
(
|
|
@@ -50,11 +50,25 @@ jobs:
|
|
|
50
50
|
runs-on: ubuntu-latest
|
|
51
51
|
|
|
52
52
|
steps:
|
|
53
|
-
|
|
53
|
+
# Messages come from the default branch (issue_comment runs there); only the message catalog and version.yml are needed
|
|
54
|
+
- name: Checkout messages
|
|
55
|
+
uses: actions/checkout@v7
|
|
56
|
+
with:
|
|
57
|
+
sparse-checkout: |
|
|
58
|
+
.github/scripts/messages.py
|
|
59
|
+
version.yml
|
|
60
|
+
sparse-checkout-cone-mode: false
|
|
61
|
+
|
|
62
|
+
- name: Load messages
|
|
63
|
+
run: echo "PAW_MSG=$(python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" dump app_trigger.)" >> "$GITHUB_ENV"
|
|
64
|
+
|
|
65
|
+
- name: Add 👀 reaction to the comment
|
|
54
66
|
uses: actions/github-script@v9
|
|
55
67
|
with:
|
|
56
68
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
57
69
|
script: |
|
|
70
|
+
const M = JSON.parse(process.env.PAW_MSG);
|
|
71
|
+
const msg = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
58
72
|
const commentId = context.payload.comment.id;
|
|
59
73
|
|
|
60
74
|
await github.rest.reactions.createForIssueComment({
|
|
@@ -64,15 +78,17 @@ jobs:
|
|
|
64
78
|
content: 'eyes'
|
|
65
79
|
});
|
|
66
80
|
|
|
67
|
-
console.log('
|
|
81
|
+
console.log(msg('app_trigger.reaction_done'));
|
|
68
82
|
|
|
69
|
-
- name:
|
|
83
|
+
- name: Detect build type
|
|
70
84
|
id: build_type
|
|
71
85
|
uses: actions/github-script@v9
|
|
72
86
|
with:
|
|
73
87
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
74
88
|
script: |
|
|
75
|
-
|
|
89
|
+
const M = JSON.parse(process.env.PAW_MSG);
|
|
90
|
+
const msg = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
91
|
+
// Keywords are matched on the lower-cased text (case-insensitive); the branch name is captured from the original body (case preserved)
|
|
76
92
|
const comment = context.payload.comment.body.toLowerCase();
|
|
77
93
|
const rawComment = context.payload.comment.body;
|
|
78
94
|
|
|
@@ -82,29 +98,29 @@ jobs:
|
|
|
82
98
|
let customBranch = '';
|
|
83
99
|
let m;
|
|
84
100
|
|
|
85
|
-
//
|
|
86
|
-
// (
|
|
87
|
-
//
|
|
101
|
+
// Capture the same-line token after the command keyword as an optional branch argument
|
|
102
|
+
// (only same-line whitespace is allowed via [^\S\r\n]+ so a word on the next line is not mistaken for a branch)
|
|
103
|
+
// The branch name is extracted again from rawComment with the i flag -> uppercase branches such as Feature/MyBranch are preserved
|
|
88
104
|
//
|
|
89
|
-
//
|
|
90
|
-
//
|
|
91
|
-
// apk/ios
|
|
105
|
+
// Both word orders are supported: "{type} build" (app/apk/ios build) and "build {type}" (build app, etc.).
|
|
106
|
+
// The app token is cut at a \b word boundary so apk is not mistaken for app (apk and application are excluded).
|
|
107
|
+
// apk/ios are checked before app so "apk build" does not fall into the app branch.
|
|
92
108
|
if (comment.match(/\/wizard[^\S\r\n]+apk[^\S\r\n]+build/) || comment.match(/\/wizard[^\S\r\n]+build[^\S\r\n]+apk/)) {
|
|
93
|
-
// /wizard apk build [
|
|
109
|
+
// /wizard apk build [branch] (or build apk) -> Android only
|
|
94
110
|
buildAndroid = true;
|
|
95
111
|
buildType = 'apk';
|
|
96
112
|
m = rawComment.match(/\/wizard[^\S\r\n]+apk[^\S\r\n]+build(?:[^\S\r\n]+(\S+))?/i)
|
|
97
113
|
|| rawComment.match(/\/wizard[^\S\r\n]+build[^\S\r\n]+apk(?:[^\S\r\n]+(\S+))?/i);
|
|
98
114
|
customBranch = (m && m[1]) || '';
|
|
99
115
|
} else if (comment.match(/\/wizard[^\S\r\n]+ios[^\S\r\n]+build/) || comment.match(/\/wizard[^\S\r\n]+build[^\S\r\n]+ios/)) {
|
|
100
|
-
// /wizard ios build [
|
|
116
|
+
// /wizard ios build [branch] (or build ios) -> iOS only
|
|
101
117
|
buildIos = true;
|
|
102
118
|
buildType = 'ios';
|
|
103
119
|
m = rawComment.match(/\/wizard[^\S\r\n]+ios[^\S\r\n]+build(?:[^\S\r\n]+(\S+))?/i)
|
|
104
120
|
|| rawComment.match(/\/wizard[^\S\r\n]+build[^\S\r\n]+ios(?:[^\S\r\n]+(\S+))?/i);
|
|
105
121
|
customBranch = (m && m[1]) || '';
|
|
106
122
|
} else if (comment.match(/\/wizard[^\S\r\n]+app\b[^\S\r\n]+build/) || comment.match(/\/wizard[^\S\r\n]+build[^\S\r\n]+app\b/)) {
|
|
107
|
-
// /wizard app build [
|
|
123
|
+
// /wizard app build [branch] (or build app) -> Android + iOS
|
|
108
124
|
buildAndroid = true;
|
|
109
125
|
buildIos = true;
|
|
110
126
|
buildType = 'app';
|
|
@@ -118,12 +134,12 @@ jobs:
|
|
|
118
134
|
core.setOutput('buildType', buildType);
|
|
119
135
|
core.setOutput('customBranch', customBranch);
|
|
120
136
|
|
|
121
|
-
console.log(
|
|
137
|
+
console.log(msg('app_trigger.build_type', { type: buildType, android: buildAndroid, ios: buildIos }));
|
|
122
138
|
if (customBranch) {
|
|
123
|
-
console.log(
|
|
139
|
+
console.log(msg('app_trigger.branch_from_comment', { branch: customBranch }));
|
|
124
140
|
}
|
|
125
141
|
|
|
126
|
-
- name: PR
|
|
142
|
+
- name: Resolve PR/issue info
|
|
127
143
|
id: source_info
|
|
128
144
|
uses: actions/github-script@v9
|
|
129
145
|
env:
|
|
@@ -131,6 +147,8 @@ jobs:
|
|
|
131
147
|
with:
|
|
132
148
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
133
149
|
script: |
|
|
150
|
+
const M = JSON.parse(process.env.PAW_MSG);
|
|
151
|
+
const msg = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
134
152
|
const customBranch = (process.env.CUSTOM_BRANCH || '').trim();
|
|
135
153
|
const issueNumber = context.payload.issue.number;
|
|
136
154
|
let sourceType = '';
|
|
@@ -139,7 +157,7 @@ jobs:
|
|
|
139
157
|
let headSha = '';
|
|
140
158
|
let relatedIssueNumber = '';
|
|
141
159
|
|
|
142
|
-
// 1.
|
|
160
|
+
// 1. Check whether it is a PR first
|
|
143
161
|
try {
|
|
144
162
|
const pr = await github.rest.pulls.get({
|
|
145
163
|
owner: context.repo.owner,
|
|
@@ -153,34 +171,34 @@ jobs:
|
|
|
153
171
|
headSha = pr.data.head.sha;
|
|
154
172
|
|
|
155
173
|
if (customBranch) {
|
|
156
|
-
console.log(
|
|
174
|
+
console.log(msg('app_trigger.branch_override', { branch: customBranch, head: pr.data.head.ref }));
|
|
157
175
|
}
|
|
158
176
|
|
|
159
|
-
console.log(
|
|
160
|
-
console.log(
|
|
161
|
-
console.log(
|
|
177
|
+
console.log(msg('app_trigger.pr_confirmed', { number: sourceNumber }));
|
|
178
|
+
console.log(msg('app_trigger.branch_name', { branch: branchName }));
|
|
179
|
+
console.log(msg('app_trigger.commit_sha', { sha: headSha }));
|
|
162
180
|
|
|
163
|
-
//
|
|
181
|
+
// Extract the issue number from the branch name (`<date>_#<number>_...` format)
|
|
164
182
|
const issueMatch = branchName.match(/#(\d+)/);
|
|
165
183
|
relatedIssueNumber = issueMatch ? issueMatch[1] : '';
|
|
166
184
|
|
|
167
185
|
if (relatedIssueNumber) {
|
|
168
|
-
console.log(
|
|
186
|
+
console.log(msg('app_trigger.issue_extracted', { number: relatedIssueNumber }));
|
|
169
187
|
}
|
|
170
188
|
|
|
171
189
|
} catch (error) {
|
|
172
|
-
console.log('
|
|
190
|
+
console.log(msg('app_trigger.not_pr'));
|
|
173
191
|
|
|
174
|
-
// 2. PR
|
|
192
|
+
// 2. If it is not a PR, look for the "Issue Helper" comment on the issue
|
|
175
193
|
sourceType = 'ISSUE';
|
|
176
194
|
sourceNumber = issueNumber.toString();
|
|
177
195
|
relatedIssueNumber = issueNumber.toString();
|
|
178
196
|
|
|
179
|
-
//
|
|
197
|
+
// If the branch is given directly in the comment, skip searching for the Guide comment
|
|
180
198
|
if (customBranch) {
|
|
181
199
|
branchName = customBranch;
|
|
182
|
-
console.log(
|
|
183
|
-
console.log(
|
|
200
|
+
console.log(msg('app_trigger.custom_branch_used', { branch: branchName }));
|
|
201
|
+
console.log(msg('app_trigger.related_issue', { number: relatedIssueNumber }));
|
|
184
202
|
|
|
185
203
|
core.setOutput('found', 'true');
|
|
186
204
|
core.setOutput('sourceType', sourceType);
|
|
@@ -199,43 +217,44 @@ jobs:
|
|
|
199
217
|
per_page: 100
|
|
200
218
|
});
|
|
201
219
|
|
|
202
|
-
// "Issue Helper"
|
|
220
|
+
// Find the "Issue Helper" comment
|
|
203
221
|
const guideComment = comments.data.find(c =>
|
|
204
222
|
c.body.includes('<!-- project-auto-wizard issue helper -->')
|
|
205
223
|
);
|
|
206
224
|
|
|
207
225
|
if (!guideComment) {
|
|
208
|
-
console.log('
|
|
226
|
+
console.log(msg('app_trigger.helper_missing_log'));
|
|
209
227
|
core.setOutput('found', 'false');
|
|
210
|
-
core.setOutput('errorMessage', '
|
|
228
|
+
core.setOutput('errorMessage', msg('app_trigger.helper_missing_error'));
|
|
211
229
|
return;
|
|
212
230
|
}
|
|
213
231
|
|
|
214
|
-
console.log('
|
|
232
|
+
console.log(msg('app_trigger.helper_found'));
|
|
215
233
|
|
|
216
|
-
//
|
|
217
|
-
|
|
234
|
+
// Extract the branch name (content of the ``` block after the branch heading).
|
|
235
|
+
// The heading is matched in English and Korean (the Korean words are written as \u escapes) so comments written before a language change still parse.
|
|
236
|
+
const branchMatch = guideComment.body.match(/### (?:\uBE0C\uB79C\uCE58(?:\uBA85)?|Branch(?: name)?)\s*```\s*([\s\S]*?)\s*```/i);
|
|
218
237
|
|
|
219
238
|
if (!branchMatch) {
|
|
220
|
-
console.log('
|
|
239
|
+
console.log(msg('app_trigger.branch_parse_log'));
|
|
221
240
|
core.setOutput('found', 'false');
|
|
222
|
-
core.setOutput('errorMessage', '
|
|
241
|
+
core.setOutput('errorMessage', msg('app_trigger.branch_parse_error'));
|
|
223
242
|
return;
|
|
224
243
|
}
|
|
225
244
|
|
|
226
245
|
branchName = branchMatch[1].trim();
|
|
227
|
-
console.log(
|
|
228
|
-
console.log(
|
|
246
|
+
console.log(msg('app_trigger.branch_extracted', { branch: branchName }));
|
|
247
|
+
console.log(msg('app_trigger.build_info_extracted', { number: sourceNumber }));
|
|
229
248
|
|
|
230
249
|
} catch (commentError) {
|
|
231
|
-
console.log('
|
|
250
|
+
console.log(msg('app_trigger.comments_error_log'), commentError.message);
|
|
232
251
|
core.setOutput('found', 'false');
|
|
233
|
-
core.setOutput('errorMessage',
|
|
252
|
+
core.setOutput('errorMessage', msg('app_trigger.comments_error', { error: commentError.message }));
|
|
234
253
|
return;
|
|
235
254
|
}
|
|
236
255
|
}
|
|
237
256
|
|
|
238
|
-
//
|
|
257
|
+
// Publish the results
|
|
239
258
|
core.setOutput('found', 'true');
|
|
240
259
|
core.setOutput('sourceType', sourceType);
|
|
241
260
|
core.setOutput('sourceNumber', sourceNumber);
|
|
@@ -243,24 +262,18 @@ jobs:
|
|
|
243
262
|
core.setOutput('headSha', headSha);
|
|
244
263
|
core.setOutput('relatedIssueNumber', relatedIssueNumber);
|
|
245
264
|
|
|
246
|
-
- name:
|
|
265
|
+
- name: Post an error comment when the branch info is not found
|
|
247
266
|
if: steps.source_info.outputs.found != 'true'
|
|
248
267
|
uses: actions/github-script@v9
|
|
249
268
|
with:
|
|
250
269
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
251
270
|
script: |
|
|
271
|
+
const M = JSON.parse(process.env.PAW_MSG);
|
|
272
|
+
const msg = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
252
273
|
const issueNumber = context.payload.issue.number;
|
|
253
274
|
const errorMessage = '${{ steps.source_info.outputs.errorMessage }}';
|
|
254
275
|
|
|
255
|
-
const body =
|
|
256
|
-
|
|
257
|
-
${errorMessage}
|
|
258
|
-
|
|
259
|
-
**해결 방법:**
|
|
260
|
-
- PR에서 빌드하는 경우: PR 페이지에서 댓글을 작성해주세요.
|
|
261
|
-
- 이슈에서 빌드하는 경우: "Issue Helper" 댓글이 있어야 합니다.
|
|
262
|
-
- 댓글에 \`### 브랜치\` 섹션과 브랜치명이 포함되어 있어야 합니다.
|
|
263
|
-
- 또는 댓글에 브랜치명을 직접 지정할 수 있습니다: \`/wizard app build <브랜치명>\``;
|
|
276
|
+
const body = msg('app_trigger.trigger_failed_body', { error: errorMessage });
|
|
264
277
|
|
|
265
278
|
await github.rest.issues.createComment({
|
|
266
279
|
owner: context.repo.owner,
|
|
@@ -271,18 +284,20 @@ jobs:
|
|
|
271
284
|
|
|
272
285
|
core.setFailed(errorMessage);
|
|
273
286
|
|
|
274
|
-
- name:
|
|
287
|
+
- name: Check that the branch exists
|
|
275
288
|
id: check_branch
|
|
276
289
|
if: steps.source_info.outputs.found == 'true'
|
|
277
290
|
uses: actions/github-script@v9
|
|
278
291
|
with:
|
|
279
292
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
280
293
|
script: |
|
|
294
|
+
const M = JSON.parse(process.env.PAW_MSG);
|
|
295
|
+
const msg = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
281
296
|
const branchName = '${{ steps.source_info.outputs.branchName }}';
|
|
282
297
|
const runId = '${{ github.run_id }}';
|
|
283
298
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
|
|
284
299
|
|
|
285
|
-
console.log(
|
|
300
|
+
console.log(msg('app_trigger.branch_check_log', { branch: branchName }));
|
|
286
301
|
|
|
287
302
|
try {
|
|
288
303
|
await github.rest.repos.getBranch({
|
|
@@ -290,45 +305,47 @@ jobs:
|
|
|
290
305
|
repo: context.repo.repo,
|
|
291
306
|
branch: branchName
|
|
292
307
|
});
|
|
293
|
-
console.log(
|
|
308
|
+
console.log(msg('app_trigger.branch_exists_log', { branch: branchName }));
|
|
294
309
|
core.setOutput('exists', 'true');
|
|
295
310
|
} catch (error) {
|
|
296
311
|
if (error.status === 404) {
|
|
297
|
-
console.log(
|
|
312
|
+
console.log(msg('app_trigger.branch_not_found_log', { branch: branchName }));
|
|
298
313
|
core.setOutput('exists', 'false');
|
|
299
|
-
core.setOutput('errorMessage',
|
|
314
|
+
core.setOutput('errorMessage', msg('app_trigger.branch_not_found_error', { branch: branchName }));
|
|
300
315
|
} else {
|
|
301
|
-
console.log(
|
|
316
|
+
console.log(msg('app_trigger.branch_check_error_log', { error: error.message }));
|
|
302
317
|
core.setOutput('exists', 'false');
|
|
303
|
-
core.setOutput('errorMessage',
|
|
318
|
+
core.setOutput('errorMessage', msg('app_trigger.branch_check_error', { error: error.message }));
|
|
304
319
|
}
|
|
305
320
|
}
|
|
306
321
|
|
|
307
|
-
- name:
|
|
322
|
+
- name: Post an error comment when the branch does not exist
|
|
308
323
|
if: steps.source_info.outputs.found == 'true' && steps.check_branch.outputs.exists == 'false'
|
|
309
324
|
uses: actions/github-script@v9
|
|
310
325
|
with:
|
|
311
326
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
312
327
|
script: |
|
|
328
|
+
const M = JSON.parse(process.env.PAW_MSG);
|
|
329
|
+
const msg = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
313
330
|
const issueNumber = context.payload.issue.number;
|
|
314
331
|
const branchName = '${{ steps.source_info.outputs.branchName }}';
|
|
315
332
|
const runId = '${{ github.run_id }}';
|
|
316
333
|
const runUrl = `https://github.com/${context.repo.owner}/${context.repo.repo}/actions/runs/${runId}`;
|
|
317
334
|
|
|
318
335
|
const body = [
|
|
319
|
-
'
|
|
336
|
+
msg('app_trigger.branch_missing_title'),
|
|
320
337
|
'',
|
|
321
|
-
'
|
|
338
|
+
msg('app_trigger.table_head'),
|
|
322
339
|
'|------|-----|',
|
|
323
|
-
|
|
324
|
-
|
|
340
|
+
msg('app_trigger.row_requested_branch', { branch: branchName }),
|
|
341
|
+
msg('app_trigger.row_issue_pr', { number: issueNumber }),
|
|
325
342
|
'',
|
|
326
|
-
'
|
|
327
|
-
'
|
|
328
|
-
'
|
|
329
|
-
'
|
|
343
|
+
msg('app_trigger.hint_title'),
|
|
344
|
+
msg('app_trigger.hint_pushed'),
|
|
345
|
+
msg('app_trigger.hint_helper_branch'),
|
|
346
|
+
msg('app_trigger.hint_typo'),
|
|
330
347
|
'',
|
|
331
|
-
|
|
348
|
+
msg('app_trigger.workflow_log_link', { url: runUrl })
|
|
332
349
|
].join('\n');
|
|
333
350
|
|
|
334
351
|
await github.rest.issues.createComment({
|
|
@@ -338,23 +355,25 @@ jobs:
|
|
|
338
355
|
body: body
|
|
339
356
|
});
|
|
340
357
|
|
|
341
|
-
core.setFailed(
|
|
358
|
+
core.setFailed(msg('app_trigger.branch_not_found_fail', { branch: branchName }));
|
|
342
359
|
|
|
343
|
-
- name:
|
|
360
|
+
- name: Look up the build count and generate the build number
|
|
344
361
|
id: build_number_calc
|
|
345
362
|
if: steps.source_info.outputs.found == 'true' && steps.check_branch.outputs.exists == 'true'
|
|
346
363
|
uses: actions/github-script@v9
|
|
347
364
|
with:
|
|
348
365
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
349
366
|
script: |
|
|
367
|
+
const M = JSON.parse(process.env.PAW_MSG);
|
|
368
|
+
const msg = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
350
369
|
const sourceNumber = parseInt('${{ steps.source_info.outputs.sourceNumber }}');
|
|
351
370
|
const sourceType = '${{ steps.source_info.outputs.sourceType }}';
|
|
352
371
|
const buildType = '${{ steps.build_type.outputs.buildType }}';
|
|
353
372
|
|
|
354
|
-
console.log(
|
|
355
|
-
console.log(
|
|
373
|
+
console.log(msg('app_trigger.count_lookup', { type: sourceType, number: sourceNumber }));
|
|
374
|
+
console.log(msg('app_trigger.count_build_type', { type: buildType }));
|
|
356
375
|
|
|
357
|
-
//
|
|
376
|
+
// Fetch every comment on the PR/issue
|
|
358
377
|
const comments = await github.rest.issues.listComments({
|
|
359
378
|
owner: context.repo.owner,
|
|
360
379
|
repo: context.repo.repo,
|
|
@@ -362,35 +381,35 @@ jobs:
|
|
|
362
381
|
per_page: 100
|
|
363
382
|
});
|
|
364
383
|
|
|
365
|
-
//
|
|
366
|
-
//
|
|
367
|
-
// iOS:
|
|
368
|
-
// Android: apk
|
|
369
|
-
// App:
|
|
384
|
+
// Count the builds of the matching platform for the build type
|
|
385
|
+
// Order-independent counting: includes('build') && includes('{type}') catches both "ios build" and "build ios".
|
|
386
|
+
// iOS: ios builds + app (shared) builds combined (App Store Connect requires unique build numbers across the whole app)
|
|
387
|
+
// Android: apk builds + app (shared) builds combined (same for the Play Store)
|
|
388
|
+
// App: every build command counted together
|
|
370
389
|
let buildCount = 0;
|
|
371
390
|
|
|
372
391
|
if (buildType === 'ios') {
|
|
373
|
-
// iOS
|
|
392
|
+
// iOS build: count both ios builds and shared app builds (word order does not matter)
|
|
374
393
|
buildCount = comments.data.filter(c => {
|
|
375
394
|
const body = c.body.toLowerCase();
|
|
376
395
|
return body.includes('/wizard') && body.includes('build') && (
|
|
377
396
|
body.includes('ios') || body.includes('app')
|
|
378
397
|
);
|
|
379
398
|
}).length;
|
|
380
|
-
console.log(
|
|
399
|
+
console.log(msg('app_trigger.count_ios'));
|
|
381
400
|
|
|
382
401
|
} else if (buildType === 'apk') {
|
|
383
|
-
// Android
|
|
402
|
+
// Android build: count both apk builds and shared app builds (word order does not matter)
|
|
384
403
|
buildCount = comments.data.filter(c => {
|
|
385
404
|
const body = c.body.toLowerCase();
|
|
386
405
|
return body.includes('/wizard') && body.includes('build') && (
|
|
387
406
|
body.includes('apk') || body.includes('app')
|
|
388
407
|
);
|
|
389
408
|
}).length;
|
|
390
|
-
console.log(
|
|
409
|
+
console.log(msg('app_trigger.count_android'));
|
|
391
410
|
|
|
392
411
|
} else if (buildType === 'app') {
|
|
393
|
-
//
|
|
412
|
+
// Full app build: count every build command (word order does not matter)
|
|
394
413
|
buildCount = comments.data.filter(c => {
|
|
395
414
|
const body = c.body.toLowerCase();
|
|
396
415
|
return body.includes('/wizard') && body.includes('build') && (
|
|
@@ -399,19 +418,19 @@ jobs:
|
|
|
399
418
|
body.includes('app')
|
|
400
419
|
);
|
|
401
420
|
}).length;
|
|
402
|
-
console.log(
|
|
421
|
+
console.log(msg('app_trigger.count_app'));
|
|
403
422
|
}
|
|
404
423
|
|
|
405
|
-
//
|
|
424
|
+
// Build number: source number + 2-digit count (38800, 38801, 38802...)
|
|
406
425
|
const buildNumber = `${sourceNumber}${String(buildCount).padStart(2, '0')}`;
|
|
407
426
|
|
|
408
|
-
console.log(
|
|
409
|
-
console.log(
|
|
427
|
+
console.log(msg('app_trigger.count_result', { type: sourceType, number: sourceNumber, build_type: buildType, count: buildCount }));
|
|
428
|
+
console.log(msg('app_trigger.build_number_generated', { number: buildNumber }));
|
|
410
429
|
|
|
411
430
|
core.setOutput('buildCount', buildCount.toString());
|
|
412
431
|
core.setOutput('buildNumber', buildNumber);
|
|
413
432
|
|
|
414
|
-
- name: Android
|
|
433
|
+
- name: Trigger the Android build workflow
|
|
415
434
|
if: |
|
|
416
435
|
steps.source_info.outputs.found == 'true' &&
|
|
417
436
|
steps.check_branch.outputs.exists == 'true' &&
|
|
@@ -420,17 +439,19 @@ jobs:
|
|
|
420
439
|
with:
|
|
421
440
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
422
441
|
script: |
|
|
442
|
+
const M = JSON.parse(process.env.PAW_MSG);
|
|
443
|
+
const msg = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
423
444
|
const sourceType = '${{ steps.source_info.outputs.sourceType }}';
|
|
424
445
|
const sourceNumber = '${{ steps.source_info.outputs.sourceNumber }}';
|
|
425
446
|
const branchName = '${{ steps.source_info.outputs.branchName }}';
|
|
426
447
|
const relatedIssueNumber = '${{ steps.source_info.outputs.relatedIssueNumber }}';
|
|
427
448
|
const buildNumber = '${{ steps.build_number_calc.outputs.buildNumber }}';
|
|
428
449
|
|
|
429
|
-
console.log(
|
|
430
|
-
console.log(
|
|
431
|
-
console.log(
|
|
432
|
-
console.log(
|
|
433
|
-
console.log(
|
|
450
|
+
console.log(msg('app_trigger.dispatch_start', { platform: 'Android' }));
|
|
451
|
+
console.log(msg('app_trigger.dispatch_source_number', { type: sourceType, number: sourceNumber }));
|
|
452
|
+
console.log(msg('app_trigger.dispatch_build_number', { number: buildNumber }));
|
|
453
|
+
console.log(msg('app_trigger.dispatch_branch', { branch: branchName }));
|
|
454
|
+
console.log(msg('app_trigger.dispatch_related_issue', { issue: relatedIssueNumber || msg('app_trigger.none') }));
|
|
434
455
|
|
|
435
456
|
await github.rest.repos.createDispatchEvent({
|
|
436
457
|
owner: context.repo.owner,
|
|
@@ -447,9 +468,9 @@ jobs:
|
|
|
447
468
|
}
|
|
448
469
|
});
|
|
449
470
|
|
|
450
|
-
console.log('
|
|
471
|
+
console.log(msg('app_trigger.dispatch_done', { platform: 'Android' }));
|
|
451
472
|
|
|
452
|
-
- name: iOS
|
|
473
|
+
- name: Trigger the iOS build workflow
|
|
453
474
|
if: |
|
|
454
475
|
steps.source_info.outputs.found == 'true' &&
|
|
455
476
|
steps.check_branch.outputs.exists == 'true' &&
|
|
@@ -458,17 +479,19 @@ jobs:
|
|
|
458
479
|
with:
|
|
459
480
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
|
460
481
|
script: |
|
|
482
|
+
const M = JSON.parse(process.env.PAW_MSG);
|
|
483
|
+
const msg = (k, p = {}) => M[k].replace(/\{(\w+)\}/g, (s, n) => (n in p ? p[n] : s));
|
|
461
484
|
const sourceType = '${{ steps.source_info.outputs.sourceType }}';
|
|
462
485
|
const sourceNumber = '${{ steps.source_info.outputs.sourceNumber }}';
|
|
463
486
|
const branchName = '${{ steps.source_info.outputs.branchName }}';
|
|
464
487
|
const relatedIssueNumber = '${{ steps.source_info.outputs.relatedIssueNumber }}';
|
|
465
488
|
const buildNumber = '${{ steps.build_number_calc.outputs.buildNumber }}';
|
|
466
489
|
|
|
467
|
-
console.log(
|
|
468
|
-
console.log(
|
|
469
|
-
console.log(
|
|
470
|
-
console.log(
|
|
471
|
-
console.log(
|
|
490
|
+
console.log(msg('app_trigger.dispatch_start', { platform: 'iOS' }));
|
|
491
|
+
console.log(msg('app_trigger.dispatch_source_number', { type: sourceType, number: sourceNumber }));
|
|
492
|
+
console.log(msg('app_trigger.dispatch_build_number', { number: buildNumber }));
|
|
493
|
+
console.log(msg('app_trigger.dispatch_branch', { branch: branchName }));
|
|
494
|
+
console.log(msg('app_trigger.dispatch_related_issue', { issue: relatedIssueNumber || msg('app_trigger.none') }));
|
|
472
495
|
|
|
473
496
|
await github.rest.repos.createDispatchEvent({
|
|
474
497
|
owner: context.repo.owner,
|
|
@@ -485,13 +508,14 @@ jobs:
|
|
|
485
508
|
}
|
|
486
509
|
});
|
|
487
510
|
|
|
488
|
-
console.log('
|
|
511
|
+
console.log(msg('app_trigger.dispatch_done', { platform: 'iOS' }));
|
|
489
512
|
|
|
490
|
-
#
|
|
491
|
-
- name:
|
|
513
|
+
# The trigger-complete comment was removed - the per-platform progress comments (Android/iOS) take over that role
|
|
514
|
+
- name: Log trigger completion
|
|
492
515
|
if: steps.source_info.outputs.found == 'true' && steps.check_branch.outputs.exists == 'true'
|
|
493
516
|
run: |
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
517
|
+
m() { python3 "$GITHUB_WORKSPACE/.github/scripts/messages.py" get "$@"; }
|
|
518
|
+
m app_trigger.done_log
|
|
519
|
+
m app_trigger.done_build_number number="${{ steps.build_number_calc.outputs.buildNumber }}"
|
|
520
|
+
m app_trigger.done_branch branch="${{ steps.source_info.outputs.branchName }}"
|
|
521
|
+
m app_trigger.done_progress_note
|