Skip to content

Commit fe9a83c

Browse files
Copilotjjoonleo
andauthored
chore: merge main and resolve workflow conflict
Co-authored-by: jjoonleo <67417817+jjoonleo@users.noreply.github.com>
2 parents 7d5a9b6 + ea0fd15 commit fe9a83c

40 files changed

Lines changed: 1066 additions & 392 deletions

File tree

.github/workflows/android-play-internal.yml

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
name: Android Play Internal Deploy
22

33
on:
4+
push:
5+
branches:
6+
- main
47
workflow_dispatch:
58
inputs:
69
release_notes:
@@ -15,7 +18,7 @@ jobs:
1518
deploy_internal:
1619
name: Build and upload internal testing draft
1720
runs-on: ubuntu-latest
18-
environment: release
21+
environment: staging
1922
env:
2023
ANDROID_KEYSTORE_PASSWORD: ${{ secrets.ANDROID_KEYSTORE_PASSWORD }}
2124
ANDROID_KEY_ALIAS: ${{ secrets.ANDROID_KEY_ALIAS }}
@@ -103,11 +106,26 @@ jobs:
103106
- name: Test
104107
run: flutter test
105108

109+
- name: Derive Android build name
110+
run: |
111+
app_version="$(sed -n 's/^version: *//p' pubspec.yaml | head -n 1)"
112+
build_name="${app_version%%+*}"
113+
if [ -z "$build_name" ]; then
114+
echo "Unable to derive Android build name from pubspec.yaml version." >&2
115+
exit 1
116+
fi
117+
echo "ANDROID_BUILD_NAME=$build_name" >> "$GITHUB_ENV"
118+
106119
- name: Build Android app bundle
107-
run: flutter build appbundle --release --dart-define=REST_API_URL="$REST_API_URL"
120+
run: |
121+
flutter build appbundle --release \
122+
--build-name="$ANDROID_BUILD_NAME" \
123+
--build-number="${{ github.run_number }}" \
124+
--dart-define=ENV=staging \
125+
--dart-define=REST_API_URL="$REST_API_URL"
108126
109127
- name: Prepare Play release notes
110-
if: ${{ inputs.release_notes != '' }}
128+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.release_notes != '' }}
111129
env:
112130
RELEASE_NOTES: ${{ inputs.release_notes }}
113131
run: |
@@ -123,7 +141,7 @@ jobs:
123141
retention-days: 14
124142

125143
- name: Upload internal testing draft with release notes
126-
if: ${{ inputs.release_notes != '' }}
144+
if: ${{ github.event_name == 'workflow_dispatch' && inputs.release_notes != '' }}
127145
uses: r0adkll/upload-google-play@v1
128146
with:
129147
serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}
@@ -134,7 +152,7 @@ jobs:
134152
whatsNewDirectory: distribution/whatsnew
135153

136154
- name: Upload internal testing draft
137-
if: ${{ inputs.release_notes == '' }}
155+
if: ${{ github.event_name != 'workflow_dispatch' || inputs.release_notes == '' }}
138156
uses: r0adkll/upload-google-play@v1
139157
with:
140158
serviceAccountJsonPlainText: ${{ secrets.GOOGLE_PLAY_SERVICE_ACCOUNT_JSON }}

.github/workflows/firebase-hosting-merge.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ permissions:
1313
jobs:
1414
build_and_deploy:
1515
runs-on: ubuntu-latest
16-
environment: release
16+
environment: staging
1717
steps:
1818
- uses: actions/checkout@v3
1919
- uses: actions/setup-java@v1
@@ -35,7 +35,10 @@ jobs:
3535
- name: Build Web
3636
env:
3737
REST_API_URL: ${{ vars.REST_API_URL }}
38-
run: flutter build web --release --dart-define=REST_API_URL=$REST_API_URL
38+
run: |
39+
flutter build web --release \
40+
--dart-define=ENV=staging \
41+
--dart-define=REST_API_URL=$REST_API_URL
3942
4043
- uses: FirebaseExtended/action-hosting-deploy@v0
4144
with:

.github/workflows/firebase-hosting-pull-request.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ jobs:
3636
- name: Build Web
3737
env:
3838
REST_API_URL: ${{ vars.REST_API_URL }}
39-
run: flutter build web --release --dart-define=REST_API_URL=$REST_API_URL
39+
run: |
40+
flutter build web --release \
41+
--dart-define=ENV=dev \
42+
--dart-define=REST_API_URL=$REST_API_URL
4043
4144
- uses: FirebaseExtended/action-hosting-deploy@v0
4245
with:

.github/workflows/flutter_test.yml

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,34 @@ name: Flutter Testing
22
on:
33
workflow_dispatch:
44
pull_request:
5-
branches: [main]
5+
branches:
6+
- main
7+
- "release/**"
8+
- "hotfix/**"
9+
push:
10+
branches:
11+
- main
12+
- "release/**"
13+
- "hotfix/**"
614
jobs:
715
test:
816
runs-on: ubuntu-latest
917
steps:
10-
- uses: actions/checkout@v3
18+
- uses: actions/checkout@v4
1119
- uses: subosito/flutter-action@v2
1220
with:
13-
channel: 'stable'
21+
flutter-version: "3.32.6"
22+
channel: stable
23+
cache: true
1424
- name: install sql
1525
run: sudo apt-get install sqlite3 libsqlite3-dev
1626
- name: Install packages
1727
run: flutter pub get
1828
- name: Check Flutter version
1929
run: flutter --version
2030
- name: Run generator
21-
run: flutter pub run build_runner build
31+
run: dart run build_runner build --delete-conflicting-outputs
32+
- name: Analyze
33+
run: flutter analyze
2234
- name: Run test
23-
run: flutter test test
35+
run: flutter test

README.md

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ The app reads compile-time values from Dart defines in `lib/core/constants/envir
8181

8282
| Define | Required | Used for |
8383
| --- | --- | --- |
84+
| `ENV` | Optional | App environment label. Use `dev`, `staging`, or `prod`; defaults to `dev`. |
8485
| `REST_API_URL` | Yes | Base URL for Dio API calls. |
8586
| `REST_AUTH_TOKEN` | Optional | Static auth token override for development/test scenarios. |
8687
| `GOOGLE_RESERVED_CLIENT_ID_IOS` | iOS release/archive only | Reversed iOS Google client ID used as the iOS URL scheme for Google Sign-In. |
@@ -89,16 +90,19 @@ Pass defines directly on Flutter commands:
8990

9091
```sh
9192
flutter run -d chrome \
93+
--dart-define=ENV=dev \
9294
--dart-define=REST_API_URL=<api-base-url>
9395

9496
flutter build web --release \
97+
--dart-define=ENV=staging \
9598
--dart-define=REST_API_URL=<api-base-url>
9699
```
97100

98101
For iOS release and archive builds, include the Google URL scheme define:
99102

100103
```sh
101104
flutter build ios --release \
105+
--dart-define=ENV=prod \
102106
--dart-define=REST_API_URL=<api-base-url> \
103107
--dart-define=GOOGLE_RESERVED_CLIENT_ID_IOS=<reversed-ios-client-id>
104108
```
@@ -165,19 +169,41 @@ flutter test --coverage
165169
Run the web app locally:
166170

167171
```sh
168-
flutter run -d chrome --dart-define=REST_API_URL=<api-base-url>
172+
flutter run -d chrome \
173+
--dart-define=ENV=dev \
174+
--dart-define=REST_API_URL=<api-base-url>
169175
```
170176

171177
Do not use `npm test`; the root `package.json` script is a placeholder that intentionally fails.
172178

173179
## Build and Release
174180

181+
This repository uses trunk-based development with release branches:
182+
183+
```text
184+
main = always test-deployable
185+
release/* = store candidate
186+
v* tag = production release source of truth
187+
hotfix/* = emergency production repair
188+
```
189+
190+
Normal changes should land through short-lived `feature/*` or `fix/*` branches
191+
into `main`. Create `release/x.y.z` from `main` for final store QA, cut
192+
`vX.Y.Z` tags from approved release branches, then merge the release branch back
193+
to `main`. See [docs/Git.md](docs/Git.md) for the full branch and deployment
194+
flow.
195+
175196
### Web
176197

177-
Preview and production web deployments are handled by GitHub Actions and Firebase Hosting. CI uses the `REST_API_URL` GitHub environment variable and builds with:
198+
Preview and staging web deployments are handled by GitHub Actions and Firebase
199+
Hosting. Pull requests build with `ENV=dev`; merges to `main` build with
200+
`ENV=staging`. CI uses the `REST_API_URL` GitHub environment variable and builds
201+
with:
178202

179203
```sh
180-
flutter build web --release --dart-define=REST_API_URL=<api-base-url>
204+
flutter build web --release \
205+
--dart-define=ENV=staging \
206+
--dart-define=REST_API_URL=<api-base-url>
181207
```
182208

183209
Firebase Hosting deploys `build/web` to project `ontime-c63f1`.
@@ -188,13 +214,15 @@ Build a release APK:
188214

189215
```sh
190216
flutter build apk --release \
217+
--dart-define=ENV=staging \
191218
--dart-define=REST_API_URL=<api-base-url>
192219
```
193220

194221
Build an app bundle for Play Console upload:
195222

196223
```sh
197224
flutter build appbundle --release \
225+
--dart-define=ENV=prod \
198226
--dart-define=REST_API_URL=<api-base-url>
199227
```
200228

@@ -206,6 +234,7 @@ Build locally:
206234

207235
```sh
208236
flutter build ios --release \
237+
--dart-define=ENV=prod \
209238
--dart-define=REST_API_URL=<api-base-url> \
210239
--dart-define=GOOGLE_RESERVED_CLIENT_ID_IOS=<reversed-ios-client-id>
211240
```

docs/Android-Release-Configuration.md

Lines changed: 29 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@ The release verification workflow decodes this secret to `android/app/src/releas
1212

1313
Use the `Android Play Internal Deploy` GitHub Actions workflow to build a signed
1414
Android App Bundle and upload it to the Google Play Internal Testing track as a
15-
draft release. The workflow is manual-only and must be dispatched from `main`.
15+
draft release. The workflow runs automatically on pushes to `main` and can also
16+
be dispatched manually from `main`.
1617

17-
Configure a GitHub environment named `release` with required reviewers before
18-
using the workflow. Store these environment secrets there:
18+
Configure a GitHub environment named `staging` for internal test distribution.
19+
Store these environment secrets there:
1920

2021
- `ANDROID_GOOGLE_SERVICES_JSON_B64`: base64-encoded production Android
2122
Firebase config.
@@ -26,21 +27,33 @@ using the workflow. Store these environment secrets there:
2627
- `GOOGLE_PLAY_SERVICE_ACCOUNT_JSON`: raw service-account JSON for the Google
2728
Play Developer API.
2829

29-
Store this environment variable in `release`:
30+
Store this environment variable in `staging`:
3031

31-
- `REST_API_URL`: production API base URL passed to Flutter with
32-
`--dart-define`.
32+
- `REST_API_URL`: target API base URL passed to Flutter with `--dart-define`.
3333

3434
The deploy workflow runs package install, code generation, generated-file drift
3535
checking, analysis, tests, and then `flutter build appbundle --release`. It
36-
uploads the signed `.aab` as a 14-day GitHub Actions artifact and creates a
36+
derives Android `versionName` from the `pubspec.yaml` version name and supplies
37+
`${{ github.run_number }}` as Android `versionCode`:
38+
39+
```sh
40+
flutter build appbundle --release \
41+
--build-name=<version name from pubspec.yaml> \
42+
--build-number=${{ github.run_number }} \
43+
--dart-define=ENV=staging \
44+
--dart-define=REST_API_URL="$REST_API_URL"
45+
```
46+
47+
It uploads the signed `.aab` as a 14-day GitHub Actions artifact and creates a
3748
draft release on Google Play Internal Testing. If the optional release notes
3849
input is empty, the workflow uploads without custom release notes.
3950

40-
`pubspec.yaml` remains the source of truth for `version: major.minor.patch+build`.
41-
Before dispatching the workflow, bump the build number so it is greater than
42-
every previously uploaded Google Play build for `club.devkor.ontime`. Duplicate
43-
build numbers fail during the Google Play upload step.
51+
Keep `pubspec.yaml` as the source of truth for the manually managed public
52+
version name, such as `version: 1.0.0+1`. Android CI ignores the checked-in
53+
build suffix for Play uploads, so do not open PRs only to bump `+2`, `+3`, and
54+
similar build numbers. The generated `github.run_number` must still be greater
55+
than every previously uploaded Google Play build for `club.devkor.ontime`;
56+
duplicate or lower build numbers fail during the Google Play upload step.
4457

4558
## Local Release Build
4659

@@ -49,7 +62,11 @@ Create the release source-set config before building:
4962
```sh
5063
mkdir -p android/app/src/release
5164
base64 --decode android-google-services.json.b64 > android/app/src/release/google-services.json
52-
flutter build appbundle --release --dart-define=REST_API_URL=<api-url>
65+
flutter build appbundle --release \
66+
--build-name=<version name from pubspec.yaml> \
67+
--build-number=<monotonic Android versionCode> \
68+
--dart-define=ENV=prod \
69+
--dart-define=REST_API_URL=<api-url>
5370
```
5471

5572
On macOS, use `base64 -D` instead of `base64 --decode`.

docs/Android-Release-Signing.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,9 @@ export ANDROID_KEYSTORE_PASSWORD=<keystore-password>
4949
export ANDROID_KEY_ALIAS=<release-key-alias>
5050
export ANDROID_KEY_PASSWORD=<release-key-password>
5151

52-
flutter build appbundle --release
52+
flutter build appbundle --release \
53+
--build-name=<version name from pubspec.yaml> \
54+
--build-number=<monotonic Android versionCode>
5355
```
5456

5557
## How Validation Works

docs/Android-Signing-Setup.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ and exports `ANDROID_KEYSTORE_PATH` to that temporary file. Do not create
8282
Google Play prefers Android App Bundles:
8383

8484
```sh
85-
flutter build appbundle --release
85+
flutter build appbundle --release \
86+
--build-name=<version name from pubspec.yaml> \
87+
--build-number=<monotonic Android versionCode>
8688
```
8789

8890
For APK validation outside Play:
@@ -120,8 +122,12 @@ Run these checks before handing a release build to QA or Play Console:
120122
```sh
121123
flutter analyze
122124
flutter test
123-
flutter build appbundle --release
125+
flutter build appbundle --release \
126+
--build-name=<version name from pubspec.yaml> \
127+
--build-number=<monotonic Android versionCode>
124128
```
125129

126-
Confirm that `pubspec.yaml` has the intended `version` and that the build number
127-
is greater than every previous Play Console upload for `club.devkor.ontime`.
130+
Confirm that `pubspec.yaml` has the intended public version name. In GitHub
131+
Actions deploys, Android `versionCode` comes from `github.run_number`; for any
132+
manual Play upload, provide a build number greater than every previous Play
133+
Console upload for `club.devkor.ontime`.

0 commit comments

Comments
 (0)