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,29 +1,29 @@
|
|
|
1
1
|
# project-auto-wizard:managed-workflow
|
|
2
|
-
# Flutter Android Play Store
|
|
2
|
+
# Flutter Android Play Store internal testing deploy workflow
|
|
3
3
|
#
|
|
4
|
-
# {{MAIN_BRANCH}}
|
|
5
|
-
# Play Store
|
|
4
|
+
# On a push to the {{MAIN_BRANCH}} branch, builds the Android AAB and
|
|
5
|
+
# deploys it to Play Store internal testing.
|
|
6
6
|
#
|
|
7
|
-
#
|
|
8
|
-
# ENV_FILE
|
|
9
|
-
# RELEASE_KEYSTORE_BASE64:
|
|
10
|
-
# RELEASE_KEYSTORE_PASSWORD: keystore
|
|
7
|
+
# Required GitHub Secrets
|
|
8
|
+
# ENV_FILE or ENV: contents of the .env file (either one; ENV_FILE takes precedence)
|
|
9
|
+
# RELEASE_KEYSTORE_BASE64: signing keystore (base64)
|
|
10
|
+
# RELEASE_KEYSTORE_PASSWORD: keystore password
|
|
11
11
|
# RELEASE_KEY_ALIAS: key alias
|
|
12
|
-
# RELEASE_KEY_PASSWORD: key
|
|
13
|
-
# GOOGLE_SERVICES_JSON (
|
|
14
|
-
# GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_BASE64: Play Console
|
|
15
|
-
# ANDROID_PACKAGE_NAME:
|
|
12
|
+
# RELEASE_KEY_PASSWORD: key password
|
|
13
|
+
# GOOGLE_SERVICES_JSON (optional): Firebase google-services.json
|
|
14
|
+
# GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_BASE64: Play Console service account (base64)
|
|
15
|
+
# ANDROID_PACKAGE_NAME: app package name (Secret first, otherwise Variable) - passed to fastlane as PACKAGE_NAME
|
|
16
16
|
|
|
17
17
|
name: PROJECT-FLUTTER-ANDROID-PLAYSTORE-INTERNAL-CICD
|
|
18
18
|
|
|
19
19
|
on:
|
|
20
20
|
push:
|
|
21
21
|
branches: ["{{MAIN_BRANCH}}"]
|
|
22
|
-
# @wizard paths-anchor (
|
|
22
|
+
# @wizard paths-anchor (in a monorepo the installer injects a paths filter here)
|
|
23
23
|
workflow_dispatch:
|
|
24
24
|
inputs:
|
|
25
25
|
deploy_mode:
|
|
26
|
-
description: "
|
|
26
|
+
description: "Deploy mode (store_only = up to internal / store_prepare = production draft / store_submit = auto-submit for review)"
|
|
27
27
|
required: false
|
|
28
28
|
default: "store_only" # @wizard auto:android-deploy-mode
|
|
29
29
|
type: choice
|
|
@@ -32,32 +32,32 @@ on:
|
|
|
32
32
|
- store_prepare
|
|
33
33
|
- store_submit
|
|
34
34
|
|
|
35
|
-
#
|
|
35
|
+
# Project settings (edit the values below)
|
|
36
36
|
env:
|
|
37
|
-
#
|
|
37
|
+
# Project name
|
|
38
38
|
APP_ARTIFACT_NAME: "__APP_ARTIFACT_NAME__" # @wizard ask:@repo
|
|
39
|
-
# Flutter/Java
|
|
40
|
-
# Flutter SDK
|
|
41
|
-
#
|
|
39
|
+
# Flutter/Java versions
|
|
40
|
+
# Flutter SDK version - leave empty to use the latest stable channel (matches the SDK constraint of a fresh flutter create project).
|
|
41
|
+
# To pin a version, write it like "3.38.9". It must satisfy the environment.sdk range in pubspec.yaml.
|
|
42
42
|
FLUTTER_VERSION: ""
|
|
43
43
|
JAVA_VERSION: "__JAVA_VERSION__" # @wizard ask:17
|
|
44
44
|
PROJECT_TYPE: "flutter"
|
|
45
|
-
# Flutter
|
|
46
|
-
#
|
|
45
|
+
# Flutter root path (relative to the repo root): "." for a single repo, "app" etc. for a monorepo.
|
|
46
|
+
# At integration time the integrator's flutter-root resolver substitutes the project_paths.flutter value once.
|
|
47
47
|
FLUTTER_PROJECT_DIR: "." # @wizard auto:flutter-root
|
|
48
|
-
#
|
|
48
|
+
# How env vars are passed (dart-define | dotenv) - set automatically from the install-time choice
|
|
49
49
|
ENV_MODE: "dart-define" # @wizard auto:flutter-env-mode
|
|
50
|
-
#
|
|
50
|
+
# Deploy mode (store_only | store_prepare | store_submit) - the last fallback is set from the install-time choice; the variable and manual input always take precedence
|
|
51
51
|
DEPLOY_MODE: ${{ github.event.inputs.deploy_mode || vars.ANDROID_DEPLOY_MODE || 'store_only' }} # @wizard fallback:android-deploy-mode
|
|
52
52
|
|
|
53
53
|
jobs:
|
|
54
54
|
prepare-build:
|
|
55
|
-
name:
|
|
55
|
+
name: Environment setup and preparation
|
|
56
56
|
runs-on: ubuntu-latest
|
|
57
57
|
defaults:
|
|
58
58
|
run:
|
|
59
59
|
working-directory: ${{ env.FLUTTER_PROJECT_DIR }}
|
|
60
|
-
#
|
|
60
|
+
# Run only when the CHANGELOG workflow succeeded
|
|
61
61
|
if: ${{ github.event.workflow_run.conclusion == 'success' || github.event_name != 'workflow_run' }}
|
|
62
62
|
|
|
63
63
|
outputs:
|
|
@@ -72,9 +72,9 @@ jobs:
|
|
|
72
72
|
ref: "{{MAIN_BRANCH}}"
|
|
73
73
|
fetch-depth: 0
|
|
74
74
|
|
|
75
|
-
#
|
|
76
|
-
# GOOGLE_SERVICES_JSON
|
|
77
|
-
- name:
|
|
75
|
+
# Without the signing/upload Secrets the run would only fail well into the build, so report all missing names first and stop
|
|
76
|
+
# GOOGLE_SERVICES_JSON is optional, so it is not checked
|
|
77
|
+
- name: Pre-deploy check (Secrets)
|
|
78
78
|
env:
|
|
79
79
|
RELEASE_KEYSTORE_BASE64: ${{ secrets.RELEASE_KEYSTORE_BASE64 }}
|
|
80
80
|
RELEASE_KEYSTORE_PASSWORD: ${{ secrets.RELEASE_KEYSTORE_PASSWORD }}
|
|
@@ -83,17 +83,18 @@ jobs:
|
|
|
83
83
|
GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_BASE64: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_BASE64 }}
|
|
84
84
|
ANDROID_PACKAGE_NAME: ${{ secrets.ANDROID_PACKAGE_NAME || vars.ANDROID_PACKAGE_NAME }}
|
|
85
85
|
run: |
|
|
86
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
86
87
|
MISSING=""
|
|
87
88
|
for NAME in RELEASE_KEYSTORE_BASE64 RELEASE_KEYSTORE_PASSWORD RELEASE_KEY_ALIAS RELEASE_KEY_PASSWORD GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_BASE64; do
|
|
88
89
|
[ -n "${!NAME}" ] || MISSING="$MISSING $NAME"
|
|
89
90
|
done
|
|
90
|
-
#
|
|
91
|
-
[ -n "$ANDROID_PACKAGE_NAME" ] || MISSING="$MISSING ANDROID_PACKAGE_NAME(Secret
|
|
91
|
+
# The package name may be registered as a Variable instead of a Secret
|
|
92
|
+
[ -n "$ANDROID_PACKAGE_NAME" ] || MISSING="$MISSING ANDROID_PACKAGE_NAME(Secret or Variable)"
|
|
92
93
|
if [ -n "$MISSING" ]; then
|
|
93
|
-
echo "::error title
|
|
94
|
+
echo "::error title=$(m flutter_a.precheck_missing_title)::$(m flutter_a.precheck_missing_body missing="$MISSING")"
|
|
94
95
|
exit 1
|
|
95
96
|
fi
|
|
96
|
-
|
|
97
|
+
m flutter_a.precheck_passed
|
|
97
98
|
|
|
98
99
|
- name: Pull latest changes
|
|
99
100
|
run: git pull origin {{MAIN_BRANCH}}
|
|
@@ -133,63 +134,65 @@ jobs:
|
|
|
133
134
|
dart run build_runner build --delete-conflicting-outputs
|
|
134
135
|
fi
|
|
135
136
|
|
|
136
|
-
- name:
|
|
137
|
+
- name: Get current version
|
|
137
138
|
id: current_version
|
|
138
|
-
working-directory: ${{ github.workspace }} # version_manager.py
|
|
139
|
+
working-directory: ${{ github.workspace }} # version_manager.py must read the repo-root version.yml
|
|
139
140
|
run: |
|
|
140
|
-
|
|
141
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
142
|
+
# Get VERSION (x.y.z format)
|
|
141
143
|
VERSION=$(python3 .github/scripts/version_manager.py get | tail -n 1)
|
|
142
144
|
|
|
143
|
-
# VERSION_CODE
|
|
145
|
+
# Get VERSION_CODE (a simple incrementing number managed in version.yml)
|
|
144
146
|
VERSION_CODE=$(python3 .github/scripts/version_manager.py get-code | tail -n 1)
|
|
145
147
|
|
|
146
|
-
#
|
|
148
|
+
# Print the result
|
|
147
149
|
echo "✅ VERSION: $VERSION"
|
|
148
150
|
echo "✅ VERSION_CODE: $VERSION_CODE"
|
|
149
|
-
|
|
151
|
+
m flutter_a.project_type project_type="${{ env.PROJECT_TYPE }}"
|
|
150
152
|
|
|
151
|
-
# GitHub outputs
|
|
153
|
+
# Set GitHub outputs
|
|
152
154
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
153
155
|
echo "version_code=$VERSION_CODE" >> $GITHUB_OUTPUT
|
|
154
156
|
echo "project_type=${{ env.PROJECT_TYPE }}" >> $GITHUB_OUTPUT
|
|
155
157
|
|
|
156
|
-
#
|
|
158
|
+
# Also set as environment variables (used by scripts)
|
|
157
159
|
echo "VERSION=$VERSION" >> $GITHUB_ENV
|
|
158
160
|
echo "VERSION_CODE=$VERSION_CODE" >> $GITHUB_ENV
|
|
159
161
|
echo "TODAY=$(date '+%Y-%m-%d')" >> $GITHUB_ENV
|
|
160
162
|
echo "TIMESTAMP=$(date '+%Y-%m-%d %H:%M:%S')" >> $GITHUB_ENV
|
|
161
163
|
echo "PROJECT_TYPE=${{ env.PROJECT_TYPE }}" >> $GITHUB_ENV
|
|
162
164
|
|
|
163
|
-
- name:
|
|
165
|
+
- name: Generate release notes
|
|
164
166
|
id: release_notes
|
|
165
|
-
working-directory: ${{ github.workspace }} # CHANGELOG.json
|
|
167
|
+
working-directory: ${{ github.workspace }} # CHANGELOG.json, changelog_manager.py and final_release_notes.txt (paired with the upload) are relative to the repo root
|
|
166
168
|
run: |
|
|
169
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
167
170
|
VERSION="${{ steps.current_version.outputs.version }}"
|
|
168
171
|
|
|
169
172
|
if [ -f "CHANGELOG.json" ]; then
|
|
170
|
-
|
|
171
|
-
# CHANGELOG.md
|
|
173
|
+
m flutter_a.extracting_v_release_notes_changelog version="$VERSION"
|
|
174
|
+
# Generate CHANGELOG.md
|
|
172
175
|
python3 ./.github/scripts/changelog_manager.py generate-md
|
|
173
176
|
|
|
174
|
-
# changelog_manager.py export
|
|
177
|
+
# Extract the release notes with changelog_manager.py export
|
|
175
178
|
python3 ./.github/scripts/changelog_manager.py export --version $VERSION --output final_release_notes.txt
|
|
176
179
|
|
|
177
180
|
if [ -s final_release_notes.txt ]; then
|
|
178
|
-
|
|
179
|
-
|
|
181
|
+
m flutter_a.release_notes_extracted
|
|
182
|
+
m flutter_a.extracted_release_notes
|
|
180
183
|
echo "----------------------------------------"
|
|
181
184
|
cat final_release_notes.txt
|
|
182
185
|
echo "----------------------------------------"
|
|
183
186
|
echo "RELEASE_NOTES_FOUND=true" >> $GITHUB_ENV
|
|
184
187
|
else
|
|
185
|
-
|
|
188
|
+
m flutter_a.failed_extract_release_notes
|
|
186
189
|
echo "RELEASE_NOTES_FOUND=false" >> $GITHUB_ENV
|
|
187
|
-
|
|
190
|
+
m flutter_a.default_release_note version="$VERSION" > final_release_notes.txt
|
|
188
191
|
fi
|
|
189
192
|
else
|
|
190
|
-
|
|
193
|
+
m flutter_a.changelog_json_not_found_using
|
|
191
194
|
echo "RELEASE_NOTES_FOUND=false" >> $GITHUB_ENV
|
|
192
|
-
|
|
195
|
+
m flutter_a.default_release_note version="$VERSION" > final_release_notes.txt
|
|
193
196
|
fi
|
|
194
197
|
|
|
195
198
|
- name: Upload release notes
|
|
@@ -200,8 +203,8 @@ jobs:
|
|
|
200
203
|
retention-days: 1
|
|
201
204
|
if-no-files-found: error
|
|
202
205
|
|
|
203
|
-
#
|
|
204
|
-
# .env
|
|
206
|
+
# Upload the project files as an artifact
|
|
207
|
+
# .env is not included in the artifact for security; each job recreates it from secrets
|
|
205
208
|
- name: Upload project files
|
|
206
209
|
uses: actions/upload-artifact@v7
|
|
207
210
|
with:
|
|
@@ -214,7 +217,7 @@ jobs:
|
|
|
214
217
|
if-no-files-found: error
|
|
215
218
|
|
|
216
219
|
build-android:
|
|
217
|
-
name: Android AAB
|
|
220
|
+
name: Build Android AAB
|
|
218
221
|
runs-on: ubuntu-latest
|
|
219
222
|
needs: prepare-build
|
|
220
223
|
defaults:
|
|
@@ -237,7 +240,7 @@ jobs:
|
|
|
237
240
|
name: project-files
|
|
238
241
|
path: ${{ env.FLUTTER_PROJECT_DIR }}
|
|
239
242
|
|
|
240
|
-
#
|
|
243
|
+
# Prepare env vars (created from secrets rather than the artifact, for security) - a .env file when ENV_MODE=dotenv, a temp file for dart-define
|
|
241
244
|
- name: Prepare env file
|
|
242
245
|
env:
|
|
243
246
|
ENV_CONTENT: ${{ secrets.ENV_FILE || secrets.ENV }}
|
|
@@ -259,35 +262,37 @@ jobs:
|
|
|
259
262
|
RELEASE_KEY_ALIAS: ${{ secrets.RELEASE_KEY_ALIAS }}
|
|
260
263
|
RELEASE_KEY_PASSWORD: ${{ secrets.RELEASE_KEY_PASSWORD }}
|
|
261
264
|
run: |
|
|
262
|
-
|
|
265
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
266
|
+
# An empty keystore built from an empty Secret leaves it unclear which key signed the build, or ends in a misleading error in a later step
|
|
263
267
|
MISSING=""
|
|
264
268
|
for name in RELEASE_KEYSTORE_BASE64 RELEASE_KEYSTORE_PASSWORD RELEASE_KEY_ALIAS RELEASE_KEY_PASSWORD; do
|
|
265
269
|
[ -n "${!name}" ] || MISSING="$MISSING $name"
|
|
266
270
|
done
|
|
267
271
|
if [ -n "$MISSING" ]; then
|
|
268
|
-
echo "::error
|
|
272
|
+
echo "::error::$(m flutter_a.signing_secrets_empty missing="$MISSING")"
|
|
269
273
|
exit 1
|
|
270
274
|
fi
|
|
271
275
|
mkdir -p android/app/keystore
|
|
272
276
|
printf '%s' "$RELEASE_KEYSTORE_BASE64" | base64 -d > android/app/keystore/key.jks
|
|
273
277
|
if [ ! -s android/app/keystore/key.jks ]; then
|
|
274
|
-
echo "::error
|
|
278
|
+
echo "::error::$(m flutter_a.keystore_decoded_empty)"
|
|
275
279
|
exit 1
|
|
276
280
|
fi
|
|
277
|
-
|
|
281
|
+
m flutter_a.release_keystore_created
|
|
278
282
|
ls -la android/app/keystore/
|
|
279
283
|
|
|
280
284
|
- name: Create key.properties
|
|
281
285
|
run: |
|
|
286
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
282
287
|
cat > android/key.properties << EOF
|
|
283
288
|
storeFile=app/keystore/key.jks
|
|
284
289
|
storePassword=${{ secrets.RELEASE_KEYSTORE_PASSWORD }}
|
|
285
290
|
keyAlias=${{ secrets.RELEASE_KEY_ALIAS }}
|
|
286
291
|
keyPassword=${{ secrets.RELEASE_KEY_PASSWORD }}
|
|
287
292
|
EOF
|
|
288
|
-
|
|
293
|
+
m flutter_a.key_properties_created
|
|
289
294
|
|
|
290
|
-
# google-services.json
|
|
295
|
+
# Create google-services.json (optional) - no empty file is written when the Secret is empty
|
|
291
296
|
- name: Create google-services.json
|
|
292
297
|
env:
|
|
293
298
|
GOOGLE_SERVICES_JSON: ${{ secrets.GOOGLE_SERVICES_JSON }}
|
|
@@ -339,55 +344,57 @@ jobs:
|
|
|
339
344
|
|
|
340
345
|
- name: Configure Android build for release
|
|
341
346
|
run: |
|
|
342
|
-
|
|
347
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
348
|
+
# Add the release signing config to build.gradle.kts if it is missing
|
|
343
349
|
if ! grep -q "signingConfigs" android/app/build.gradle.kts; then
|
|
344
|
-
|
|
345
|
-
#
|
|
350
|
+
m flutter_a.signing_config_must_added_build
|
|
351
|
+
# Assume signing is already configured (it must be set up manually beforehand)
|
|
346
352
|
fi
|
|
347
|
-
|
|
353
|
+
m flutter_a.android_build_config_check_complete
|
|
348
354
|
|
|
349
|
-
# pubspec.yaml
|
|
350
|
-
#
|
|
355
|
+
# Keep pubspec.yaml in the x.y.z format as is
|
|
356
|
+
# The --build-name and --build-number flags of flutter build override pubspec.yaml
|
|
351
357
|
|
|
352
358
|
- name: Build Android App Bundle (AAB)
|
|
353
359
|
run: |
|
|
360
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
354
361
|
VERSION_NAME="${{ needs.prepare-build.outputs.version }}"
|
|
355
362
|
VERSION_CODE="${{ needs.prepare-build.outputs.version_code }}"
|
|
356
363
|
|
|
357
364
|
echo "=========================================="
|
|
358
|
-
|
|
365
|
+
m flutter_a.starting_aab_build
|
|
359
366
|
echo "=========================================="
|
|
360
|
-
|
|
361
|
-
|
|
367
|
+
m flutter_a.build_version version_name="$VERSION_NAME"
|
|
368
|
+
m flutter_a.build_code version_code="$VERSION_CODE"
|
|
362
369
|
|
|
363
|
-
#
|
|
370
|
+
# Validate inputs
|
|
364
371
|
if [ -z "$VERSION_NAME" ] || [ -z "$VERSION_CODE" ]; then
|
|
365
|
-
|
|
372
|
+
m flutter_a.version_name_or_version_code
|
|
366
373
|
exit 1
|
|
367
374
|
fi
|
|
368
375
|
|
|
369
|
-
# Flutter
|
|
370
|
-
|
|
376
|
+
# Print Flutter environment info
|
|
377
|
+
m flutter_a.flutter_environment_info
|
|
371
378
|
flutter --version
|
|
372
379
|
flutter doctor -v | head -20
|
|
373
380
|
|
|
374
|
-
#
|
|
375
|
-
|
|
381
|
+
# Clean the build directory
|
|
382
|
+
m flutter_a.cleaning_previous_build_output
|
|
376
383
|
rm -rf build/app/outputs/bundle/release/
|
|
377
384
|
mkdir -p build/app/outputs/bundle/release/
|
|
378
385
|
|
|
379
|
-
# Flutter clean
|
|
380
|
-
|
|
386
|
+
# Flutter clean and pub get
|
|
387
|
+
m flutter_a.running_flutter_clean_reinstalling_dependencies
|
|
381
388
|
flutter clean
|
|
382
389
|
flutter pub get
|
|
383
390
|
if grep -q "build_runner" pubspec.yaml; then
|
|
384
391
|
dart run build_runner build --delete-conflicting-outputs
|
|
385
392
|
fi
|
|
386
393
|
|
|
387
|
-
# local.properties
|
|
388
|
-
|
|
394
|
+
# Add version info to local.properties (works around the Flutter flags being ignored)
|
|
395
|
+
m flutter_a.setting_version_info_local_properties
|
|
389
396
|
|
|
390
|
-
#
|
|
397
|
+
# Remove existing version info if local.properties exists
|
|
391
398
|
if [ -f "android/local.properties" ]; then
|
|
392
399
|
grep -v "flutter.versionName\|flutter.versionCode" android/local.properties > android/local.properties.tmp || true
|
|
393
400
|
mv android/local.properties.tmp android/local.properties
|
|
@@ -395,24 +402,24 @@ jobs:
|
|
|
395
402
|
touch android/local.properties
|
|
396
403
|
fi
|
|
397
404
|
|
|
398
|
-
#
|
|
405
|
+
# Add version info
|
|
399
406
|
echo "flutter.versionName=$VERSION_NAME" >> android/local.properties
|
|
400
407
|
echo "flutter.versionCode=$VERSION_CODE" >> android/local.properties
|
|
401
408
|
|
|
402
|
-
|
|
403
|
-
|
|
409
|
+
m flutter_a.local_properties_updated
|
|
410
|
+
m flutter_a.version_info_version_name_version version_name="$VERSION_NAME" version_code="$VERSION_CODE"
|
|
404
411
|
|
|
405
|
-
# Gradle
|
|
412
|
+
# Gradle performance tuning
|
|
406
413
|
export GRADLE_OPTS="-Dorg.gradle.daemon=false -Dorg.gradle.parallel=true -Dorg.gradle.workers.max=4"
|
|
407
414
|
export JAVA_OPTS="-Xmx4g"
|
|
408
|
-
|
|
415
|
+
m flutter_a.gradle_tuning_applied
|
|
409
416
|
|
|
410
|
-
#
|
|
411
|
-
# --build-name
|
|
412
|
-
# pubspec.yaml
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
417
|
+
# Pass the version info to the flutter build command
|
|
418
|
+
# The --build-name and --build-number flags override the version in pubspec.yaml
|
|
419
|
+
# pubspec.yaml stays in x.y.z format; VERSION_CODE is managed automatically in version.yml
|
|
420
|
+
m flutter_a.running_flutter_build
|
|
421
|
+
m flutter_a.command_flutter_build_appbundle_release version_name="$VERSION_NAME" version_code="$VERSION_CODE"
|
|
422
|
+
m flutter_a.build_start_time cmd1="$(date '+%Y-%m-%d %H:%M:%S')"
|
|
416
423
|
|
|
417
424
|
flutter build appbundle \
|
|
418
425
|
--release \
|
|
@@ -424,144 +431,144 @@ jobs:
|
|
|
424
431
|
BUILD_EXIT_CODE=$?
|
|
425
432
|
|
|
426
433
|
if [ $BUILD_EXIT_CODE -ne 0 ]; then
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
find build/ -name "*.aab" -o -name "*.apk" 2>/dev/null ||
|
|
434
|
+
m flutter_a.flutter_build_failed_exit_code build_exit_code="$BUILD_EXIT_CODE"
|
|
435
|
+
m flutter_a.build_directory_state
|
|
436
|
+
find build/ -name "*.aab" -o -name "*.apk" 2>/dev/null || m flutter_a.aab_apk_not_found
|
|
430
437
|
exit 1
|
|
431
438
|
fi
|
|
432
439
|
|
|
433
|
-
|
|
440
|
+
m flutter_a.flutter_build_succeeded
|
|
434
441
|
|
|
435
|
-
#
|
|
436
|
-
|
|
442
|
+
# Check the build result
|
|
443
|
+
m flutter_a.checking_build_result
|
|
437
444
|
ls -lah build/app/outputs/bundle/release/
|
|
438
445
|
|
|
439
|
-
# AAB
|
|
446
|
+
# Check that the AAB file exists
|
|
440
447
|
AAB_FILE="build/app/outputs/bundle/release/app-release.aab"
|
|
441
448
|
if [ ! -f "$AAB_FILE" ]; then
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
find build/ -type f -name "*.aab" -o -name "*.apk" 2>/dev/null ||
|
|
445
|
-
|
|
446
|
-
find build/app/outputs/ -type f 2>/dev/null ||
|
|
449
|
+
m flutter_a.aab_file_not_created
|
|
450
|
+
m flutter_a.full_build_directory_contents
|
|
451
|
+
find build/ -type f -name "*.aab" -o -name "*.apk" 2>/dev/null || m flutter_a.aab_apk_not_found
|
|
452
|
+
m flutter_a.outputs_directory_structure
|
|
453
|
+
find build/app/outputs/ -type f 2>/dev/null || m flutter_a.outputs_directory_does_not_exist
|
|
447
454
|
exit 1
|
|
448
455
|
fi
|
|
449
456
|
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
457
|
+
m flutter_a.aab_file_creation_confirmed
|
|
458
|
+
m flutter_a.aab_file_size cmd1="$(du -h "$AAB_FILE" | cut -f1)"
|
|
459
|
+
m flutter_a.aab_file_info cmd1="$(ls -lah "$AAB_FILE")"
|
|
453
460
|
|
|
454
|
-
#
|
|
455
|
-
|
|
461
|
+
# Download and install bundletool
|
|
462
|
+
m flutter_a.downloading_bundletool
|
|
456
463
|
BUNDLETOOL_VERSION="1.15.6"
|
|
457
464
|
BUNDLETOOL_URL="https://github.com/google/bundletool/releases/download/${BUNDLETOOL_VERSION}/bundletool-all-${BUNDLETOOL_VERSION}.jar"
|
|
458
465
|
|
|
459
|
-
|
|
466
|
+
m flutter_a.download_url bundletool_url="$BUNDLETOOL_URL"
|
|
460
467
|
wget -q "$BUNDLETOOL_URL" -O bundletool.jar
|
|
461
468
|
|
|
462
469
|
if [ ! -f "bundletool.jar" ]; then
|
|
463
|
-
|
|
464
|
-
|
|
470
|
+
m flutter_a.bundletool_download_failed
|
|
471
|
+
m flutter_a.retrying_fallback_url
|
|
465
472
|
wget -q "https://github.com/google/bundletool/releases/latest/download/bundletool-all-1.15.6.jar" -O bundletool.jar
|
|
466
473
|
|
|
467
474
|
if [ ! -f "bundletool.jar" ]; then
|
|
468
|
-
|
|
475
|
+
m flutter_a.bundletool_download_failed_completely
|
|
469
476
|
exit 1
|
|
470
477
|
fi
|
|
471
478
|
fi
|
|
472
479
|
|
|
473
|
-
|
|
474
|
-
|
|
480
|
+
m flutter_a.bundletool_downloaded
|
|
481
|
+
m flutter_a.bundletool_file_size cmd1="$(du -h bundletool.jar | cut -f1)"
|
|
475
482
|
|
|
476
|
-
# Java
|
|
477
|
-
|
|
483
|
+
# Check the Java environment
|
|
484
|
+
m flutter_a.checking_java_environment
|
|
478
485
|
java -version
|
|
479
486
|
|
|
480
|
-
#
|
|
481
|
-
# Flutter CLI
|
|
487
|
+
# Check the actual version info inside the AAB file
|
|
488
|
+
# Verify that the VERSION_CODE passed via the Flutter CLI flags was applied correctly
|
|
482
489
|
echo "=========================================="
|
|
483
|
-
|
|
490
|
+
m flutter_a.verifying_version_info_inside_aab
|
|
484
491
|
echo "=========================================="
|
|
485
492
|
|
|
486
|
-
# AndroidManifest.xml
|
|
487
|
-
|
|
488
|
-
|
|
493
|
+
# Extract the version info from AndroidManifest.xml
|
|
494
|
+
m flutter_a.extracting_actual_version_info_aab
|
|
495
|
+
m flutter_a.command_run_java_jar_bundletool aab_file="$AAB_FILE"
|
|
489
496
|
|
|
490
497
|
MANIFEST_OUTPUT=$(java -jar bundletool.jar dump manifest --bundle="$AAB_FILE" 2>&1)
|
|
491
498
|
MANIFEST_EXIT_CODE=$?
|
|
492
499
|
|
|
493
|
-
|
|
500
|
+
m flutter_a.bundletool_result_exit_code manifest_exit_code="$MANIFEST_EXIT_CODE"
|
|
494
501
|
echo "$MANIFEST_OUTPUT"
|
|
495
502
|
|
|
496
503
|
if [ $MANIFEST_EXIT_CODE -eq 0 ]; then
|
|
497
|
-
|
|
504
|
+
m flutter_a.manifest_extracted
|
|
498
505
|
|
|
499
|
-
#
|
|
506
|
+
# Extract the actual version code and version name
|
|
500
507
|
ACTUAL_VERSION_CODE=$(echo "$MANIFEST_OUTPUT" | grep -o 'android:versionCode="[0-9]*"' | grep -o '[0-9]*' | head -1)
|
|
501
508
|
ACTUAL_VERSION_NAME=$(echo "$MANIFEST_OUTPUT" | grep -o 'android:versionName="[^"]*"' | sed 's/android:versionName="//;s/"//' | head -1)
|
|
502
509
|
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
510
|
+
m flutter_a.version_info_comparison
|
|
511
|
+
m flutter_a.expected_version_code version_code="$VERSION_CODE"
|
|
512
|
+
m flutter_a.actual_version_code actual_version_code="$ACTUAL_VERSION_CODE"
|
|
513
|
+
m flutter_a.expected_version_name version_name="$VERSION_NAME"
|
|
514
|
+
m flutter_a.actual_version_name actual_version_name="$ACTUAL_VERSION_NAME"
|
|
508
515
|
|
|
509
|
-
# VERSION_CODE
|
|
516
|
+
# Verify VERSION_CODE - a simple incrementing number managed in version.yml
|
|
510
517
|
if [ -z "$ACTUAL_VERSION_CODE" ]; then
|
|
511
|
-
|
|
512
|
-
|
|
518
|
+
m flutter_a.fatal_error_version_code_could
|
|
519
|
+
m flutter_a.full_manifest_contents
|
|
513
520
|
echo "$MANIFEST_OUTPUT"
|
|
514
521
|
exit 1
|
|
515
522
|
elif [ "$ACTUAL_VERSION_CODE" != "$VERSION_CODE" ]; then
|
|
516
|
-
|
|
517
|
-
|
|
523
|
+
m flutter_a.fatal_error_version_code_aab
|
|
524
|
+
m flutter_a.google_play_would_reject_version
|
|
518
525
|
echo ""
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
526
|
+
m flutter_a.debugging_info
|
|
527
|
+
m flutter_a.version_code_version_yml version_code="$VERSION_CODE"
|
|
528
|
+
m flutter_a.version_code_inside_aab_file actual_version_code="$ACTUAL_VERSION_CODE"
|
|
522
529
|
echo ""
|
|
523
|
-
|
|
530
|
+
m flutter_a.flags_passed_flutter_build_command
|
|
524
531
|
echo " --build-name='$VERSION_NAME'"
|
|
525
532
|
echo " --build-number='$VERSION_CODE'"
|
|
526
533
|
echo ""
|
|
527
|
-
|
|
534
|
+
m flutter_a.full_manifest_contents_2
|
|
528
535
|
echo "$MANIFEST_OUTPUT" | grep -E "versionCode|versionName|package"
|
|
529
536
|
exit 1
|
|
530
537
|
else
|
|
531
|
-
|
|
538
|
+
m flutter_a.version_code_check_passed actual_version_code="$ACTUAL_VERSION_CODE"
|
|
532
539
|
fi
|
|
533
540
|
|
|
534
|
-
#
|
|
541
|
+
# Check the version name too (warning only)
|
|
535
542
|
if [ -z "$ACTUAL_VERSION_NAME" ]; then
|
|
536
|
-
|
|
543
|
+
m flutter_a.warning_version_name_could_not
|
|
537
544
|
elif [ "$ACTUAL_VERSION_NAME" != "$VERSION_NAME" ]; then
|
|
538
|
-
|
|
539
|
-
|
|
545
|
+
m flutter_a.warning_version_name_differs_expected
|
|
546
|
+
m flutter_a.expected_actual version_name="$VERSION_NAME" actual_version_name="$ACTUAL_VERSION_NAME"
|
|
540
547
|
else
|
|
541
|
-
|
|
548
|
+
m flutter_a.version_name_check_passed actual_version_name="$ACTUAL_VERSION_NAME"
|
|
542
549
|
fi
|
|
543
550
|
|
|
544
551
|
else
|
|
545
|
-
|
|
546
|
-
|
|
552
|
+
m flutter_a.failed_extract_manifest_bundletool
|
|
553
|
+
m flutter_a.trying_verify_another_way
|
|
547
554
|
|
|
548
|
-
#
|
|
549
|
-
|
|
555
|
+
# Try checking directly with unzip
|
|
556
|
+
m flutter_a.trying_direct_extraction_unzip
|
|
550
557
|
UNZIP_OUTPUT=$(unzip -p "$AAB_FILE" base/manifest/AndroidManifest.xml 2>/dev/null | strings | grep -E "versionCode|versionName")
|
|
551
558
|
|
|
552
559
|
if [ -n "$UNZIP_OUTPUT" ]; then
|
|
553
|
-
|
|
560
|
+
m flutter_a.version_info_extracted_unzip
|
|
554
561
|
echo "$UNZIP_OUTPUT"
|
|
555
562
|
else
|
|
556
|
-
|
|
557
|
-
|
|
563
|
+
m flutter_a.direct_extraction_unzip_failed_too
|
|
564
|
+
m flutter_a.skipping_aab_verification_continuing
|
|
558
565
|
fi
|
|
559
566
|
fi
|
|
560
567
|
|
|
561
568
|
echo "=========================================="
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
569
|
+
m flutter_a.aab_build_verification_complete
|
|
570
|
+
m flutter_a.final_aab aab_file="$AAB_FILE"
|
|
571
|
+
m flutter_a.file_size cmd1="$(du -h "$AAB_FILE" | cut -f1)"
|
|
565
572
|
echo "=========================================="
|
|
566
573
|
|
|
567
574
|
- name: Upload AAB artifact
|
|
@@ -573,7 +580,7 @@ jobs:
|
|
|
573
580
|
if-no-files-found: error
|
|
574
581
|
|
|
575
582
|
deploy-playstore:
|
|
576
|
-
name: Play Store
|
|
583
|
+
name: Deploy to Play Store internal testing
|
|
577
584
|
runs-on: ubuntu-latest
|
|
578
585
|
needs: [prepare-build, build-android]
|
|
579
586
|
defaults:
|
|
@@ -591,13 +598,14 @@ jobs:
|
|
|
591
598
|
env:
|
|
592
599
|
SERVICE_ACCOUNT_BASE64: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON_BASE64 }}
|
|
593
600
|
run: |
|
|
601
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
594
602
|
if [ -z "$SERVICE_ACCOUNT_BASE64" ]; then
|
|
595
|
-
echo "::error
|
|
603
|
+
echo "::error::$(m flutter_a.google_play_service_account_json)"
|
|
596
604
|
exit 1
|
|
597
605
|
fi
|
|
598
606
|
mkdir -p ~/.config/gcloud
|
|
599
607
|
printf '%s' "$SERVICE_ACCOUNT_BASE64" | base64 --decode > ~/.config/gcloud/service-account.json
|
|
600
|
-
|
|
608
|
+
m flutter_a.service_account_json_configured
|
|
601
609
|
|
|
602
610
|
- name: Download AAB artifact
|
|
603
611
|
uses: actions/download-artifact@v8
|
|
@@ -619,25 +627,27 @@ jobs:
|
|
|
619
627
|
- name: Install Fastlane
|
|
620
628
|
working-directory: ${{ env.FLUTTER_PROJECT_DIR }}/android
|
|
621
629
|
run: |
|
|
622
|
-
|
|
630
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
631
|
+
# If the repository Gemfile has fastlane, use it as is (committing Gemfile.lock is recommended). Otherwise create one.
|
|
623
632
|
if [ -f Gemfile ] && grep -Eq "['\"]fastlane['\"]" Gemfile; then
|
|
624
|
-
|
|
633
|
+
m flutter_a.using_repository_gemfile
|
|
625
634
|
else
|
|
626
|
-
# multi_json: google-apis transitive
|
|
635
|
+
# multi_json: works around an upstream bug where a google-apis transitive dependency is not declared (missing from the gemspec -> Gem::LoadError)
|
|
627
636
|
printf 'source "https://rubygems.org"\ngem "fastlane"\ngem "multi_json"\n' > Gemfile
|
|
628
637
|
fi
|
|
629
638
|
bundle install
|
|
630
|
-
|
|
639
|
+
m flutter_a.fastlane_installed_bundler
|
|
631
640
|
bundle exec fastlane --version
|
|
632
641
|
|
|
633
|
-
# Fastfile
|
|
634
|
-
# android/fastlane/Fastfile.playstore
|
|
642
|
+
# Copy the Fastfile (for Play Store deployment)
|
|
643
|
+
# Use android/fastlane/Fastfile.playstore to stay consistent
|
|
635
644
|
- name: Copy Fastfile for Play Store
|
|
636
645
|
run: |
|
|
646
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
637
647
|
mkdir -p android/fastlane
|
|
638
648
|
cp android/fastlane/Fastfile.playstore android/fastlane/Fastfile
|
|
639
|
-
|
|
640
|
-
|
|
649
|
+
m flutter_a.fastfile_copied_fastfile_playstore_fastfile
|
|
650
|
+
m flutter_a.fastfile_contents
|
|
641
651
|
cat android/fastlane/Fastfile
|
|
642
652
|
|
|
643
653
|
- name: Upload to Play Store Internal Testing
|
|
@@ -645,53 +655,54 @@ jobs:
|
|
|
645
655
|
DEPLOY_MODE: ${{ env.DEPLOY_MODE }}
|
|
646
656
|
PACKAGE_NAME: ${{ secrets.ANDROID_PACKAGE_NAME || vars.ANDROID_PACKAGE_NAME }}
|
|
647
657
|
run: |
|
|
658
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
648
659
|
echo "=========================================="
|
|
649
|
-
|
|
660
|
+
m flutter_a.starting_play_store_deployment
|
|
650
661
|
echo "=========================================="
|
|
651
|
-
|
|
662
|
+
m flutter_a.deploy_start_time cmd1="$(date '+%Y-%m-%d %H:%M:%S')"
|
|
652
663
|
echo "🔍 GitHub Run Number: ${{ github.run_number }}"
|
|
653
664
|
echo "🔍 GitHub SHA: ${{ github.sha }}"
|
|
654
665
|
|
|
655
|
-
#
|
|
666
|
+
# Initialize and validate environment variables
|
|
656
667
|
VERSION_CODE="${{ needs.prepare-build.outputs.version_code }}"
|
|
657
668
|
VERSION_NAME="${{ needs.prepare-build.outputs.version }}"
|
|
658
669
|
|
|
659
|
-
|
|
670
|
+
m flutter_a.version_info_deploy
|
|
660
671
|
echo " VERSION_NAME: '$VERSION_NAME'"
|
|
661
672
|
echo " VERSION_CODE: '$VERSION_CODE'"
|
|
662
673
|
|
|
663
|
-
#
|
|
674
|
+
# Validate inputs
|
|
664
675
|
if [ -z "$VERSION_NAME" ] || [ -z "$VERSION_CODE" ]; then
|
|
665
|
-
|
|
676
|
+
m flutter_a.fatal_error_version_name_or
|
|
666
677
|
echo "VERSION_NAME: '$VERSION_NAME'"
|
|
667
678
|
echo "VERSION_CODE: '$VERSION_CODE'"
|
|
668
|
-
|
|
679
|
+
m flutter_a.means_prepare_build_job_did
|
|
669
680
|
exit 1
|
|
670
681
|
fi
|
|
671
682
|
|
|
672
|
-
#
|
|
683
|
+
# Find the absolute path of the AAB file
|
|
673
684
|
AAB_PATH=$(realpath build/app/outputs/bundle/release/app-release.aab)
|
|
674
|
-
|
|
685
|
+
m flutter_a.aab_file_path aab_path="$AAB_PATH"
|
|
675
686
|
|
|
676
687
|
if [ ! -f "$AAB_PATH" ]; then
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
ls -la build/app/outputs/bundle/release/ ||
|
|
680
|
-
|
|
681
|
-
find build/ -name "*.aab" -o -name "*.apk" 2>/dev/null ||
|
|
688
|
+
m flutter_a.aab_file_not_found
|
|
689
|
+
m flutter_a.build_directory_contents
|
|
690
|
+
ls -la build/app/outputs/bundle/release/ || m flutter_a.directory_does_not_exist
|
|
691
|
+
m flutter_a.full_build_directory_structure
|
|
692
|
+
find build/ -name "*.aab" -o -name "*.apk" 2>/dev/null || m flutter_a.aab_apk_not_found
|
|
682
693
|
exit 1
|
|
683
694
|
fi
|
|
684
695
|
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
696
|
+
m flutter_a.aab_file_exists
|
|
697
|
+
m flutter_a.aab_file_info cmd1="$(ls -lah "$AAB_PATH")"
|
|
698
|
+
m flutter_a.aab_file_size cmd1="$(du -h "$AAB_PATH" | cut -f1)"
|
|
688
699
|
|
|
689
|
-
#
|
|
700
|
+
# Verify the AAB version before deploying
|
|
690
701
|
echo "=========================================="
|
|
691
|
-
|
|
702
|
+
m flutter_a.verifying_aab_version
|
|
692
703
|
echo "=========================================="
|
|
693
704
|
|
|
694
|
-
# bundletool
|
|
705
|
+
# Download bundletool
|
|
695
706
|
if [ ! -f "bundletool.jar" ]; then
|
|
696
707
|
wget -q "https://github.com/google/bundletool/releases/download/1.15.6/bundletool-all-1.15.6.jar" -O bundletool.jar
|
|
697
708
|
fi
|
|
@@ -703,52 +714,52 @@ jobs:
|
|
|
703
714
|
FINAL_VERSION_CODE=$(echo "$MANIFEST_OUTPUT" | grep -o 'android:versionCode="[0-9]*"' | grep -o '[0-9]*' | head -1)
|
|
704
715
|
FINAL_VERSION_NAME=$(echo "$MANIFEST_OUTPUT" | grep -o 'android:versionName="[^"]*"' | sed 's/android:versionName="//;s/"//' | head -1)
|
|
705
716
|
|
|
706
|
-
|
|
717
|
+
m flutter_a.aab_version_code final_version_name="$FINAL_VERSION_NAME" final_version_code="$FINAL_VERSION_CODE"
|
|
707
718
|
|
|
708
|
-
# VERSION_CODE
|
|
719
|
+
# Verify VERSION_CODE
|
|
709
720
|
if [ "$FINAL_VERSION_CODE" != "$VERSION_CODE" ]; then
|
|
710
|
-
|
|
721
|
+
m flutter_a.error_aab_version_code_not version_code="$VERSION_CODE" final_version_code="$FINAL_VERSION_CODE"
|
|
711
722
|
exit 1
|
|
712
723
|
fi
|
|
713
724
|
|
|
714
|
-
|
|
725
|
+
m flutter_a.version_check_passed
|
|
715
726
|
else
|
|
716
|
-
|
|
727
|
+
m flutter_a.version_check_failed_continuing_deployment
|
|
717
728
|
fi
|
|
718
729
|
fi
|
|
719
730
|
|
|
720
|
-
#
|
|
731
|
+
# Prepare the release notes
|
|
721
732
|
CHANGELOG_DIR="android/fastlane/metadata/android/ko-KR/changelogs"
|
|
722
733
|
mkdir -p "$CHANGELOG_DIR"
|
|
723
734
|
|
|
724
735
|
if [ -f "$GITHUB_WORKSPACE/final_release_notes.txt" ]; then
|
|
725
|
-
# Google Play release notes
|
|
726
|
-
# final_release_notes.txt
|
|
736
|
+
# Truncate to the Google Play release notes limit (500 characters) with some margin (480)
|
|
737
|
+
# final_release_notes.txt and the truncate script are relative to the repo root - working-directory is FLUTTER_PROJECT_DIR, so use absolute paths
|
|
727
738
|
python3 "$GITHUB_WORKSPACE/.github/scripts/truncate_release_notes.py" "$GITHUB_WORKSPACE/final_release_notes.txt" 480 char
|
|
728
739
|
cp "$GITHUB_WORKSPACE/final_release_notes.txt" "$CHANGELOG_DIR/${VERSION_CODE}.txt"
|
|
729
|
-
|
|
740
|
+
m flutter_a.changelog_ready_version_code version_code="$VERSION_CODE"
|
|
730
741
|
else
|
|
731
|
-
|
|
732
|
-
|
|
742
|
+
m flutter_a.default_release_note_name version_name="$VERSION_NAME" > "$CHANGELOG_DIR/${VERSION_CODE}.txt"
|
|
743
|
+
m flutter_a.created_default_changelog_version_code version_code="$VERSION_CODE"
|
|
733
744
|
fi
|
|
734
745
|
|
|
735
|
-
# Service Account JSON
|
|
746
|
+
# Check the Service Account JSON file
|
|
736
747
|
GOOGLE_PLAY_JSON_KEY="$HOME/.config/gcloud/service-account.json"
|
|
737
748
|
if [ ! -f "$GOOGLE_PLAY_JSON_KEY" ]; then
|
|
738
|
-
|
|
749
|
+
m flutter_a.service_account_json_file_not
|
|
739
750
|
exit 1
|
|
740
751
|
fi
|
|
741
752
|
|
|
742
|
-
#
|
|
753
|
+
# Set environment variables
|
|
743
754
|
export AAB_PATH="$AAB_PATH"
|
|
744
755
|
export GOOGLE_PLAY_JSON_KEY="$GOOGLE_PLAY_JSON_KEY"
|
|
745
756
|
export VERSION_NAME="$VERSION_NAME"
|
|
746
757
|
export VERSION_CODE="$VERSION_CODE"
|
|
747
758
|
|
|
748
|
-
#
|
|
759
|
+
# Run the deployment
|
|
749
760
|
echo "=========================================="
|
|
750
|
-
|
|
751
|
-
|
|
761
|
+
m flutter_a.running_play_store_deployment
|
|
762
|
+
m flutter_a.version_code version_name="$VERSION_NAME" version_code="$VERSION_CODE"
|
|
752
763
|
echo "=========================================="
|
|
753
764
|
|
|
754
765
|
cd android
|
|
@@ -757,17 +768,19 @@ jobs:
|
|
|
757
768
|
- name: Notify Play Store Upload Success
|
|
758
769
|
if: success()
|
|
759
770
|
run: |
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
771
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
772
|
+
m flutter_a.play_store_internal_testing_deployment
|
|
773
|
+
m flutter_a.version version="${{ needs.prepare-build.outputs.version }}" version_code="${{ needs.prepare-build.outputs.version_code }}"
|
|
774
|
+
m flutter_a.commit sha="${{ github.sha }}"
|
|
763
775
|
echo ""
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
# Play Console URL
|
|
776
|
+
m flutter_a.how_testers_check_build
|
|
777
|
+
m flutter_a.play_console_test_release_internal
|
|
778
|
+
m flutter_a.share_test_link_your_testers
|
|
779
|
+
# The Play Console URL differs per project, so it needs separate setup
|
|
768
780
|
|
|
769
781
|
- name: Notify on Failure
|
|
770
782
|
if: failure()
|
|
771
783
|
run: |
|
|
772
|
-
|
|
773
|
-
|
|
784
|
+
m() { (cd "$GITHUB_WORKSPACE" && python3 .github/scripts/messages.py get "$@"); }
|
|
785
|
+
m flutter_a.play_store_deployment_failed
|
|
786
|
+
m flutter_a.please_check_logs
|