CircleCI
CircleCI configuration for releasing Android apps with GPC. Store your service account JSON as a project environment variable or in a context.
Setup
Environment Variables
- Navigate to Project Settings > Environment Variables
- Add
GPC_SERVICE_ACCOUNTwith the full service account JSON content - Add
GPC_APPwith your package name
Using Contexts
For shared credentials across projects, create a context:
- Navigate to Organization Settings > Contexts
- Create a context named
gpc-credentials - Add
GPC_SERVICE_ACCOUNTandGPC_APPvariables
Reference the context in your workflow:
yaml
workflows:
release:
jobs:
- upload:
context: gpc-credentials1
2
3
4
5
2
3
4
5
Basic Release Job
Uploads an AAB to the internal track on tag push.
yaml
# .circleci/config.yml
version: 2.1
jobs:
build:
docker:
- image: cimg/android:2024.07
steps:
- checkout
- run:
name: Build release AAB
command: ./gradlew bundleRelease
- persist_to_workspace:
root: .
paths:
- app/build/outputs/bundle/release/app-release.aab
upload:
docker:
- image: cimg/node:20.0
environment:
GPC_APP: com.example.myapp
steps:
- attach_workspace:
at: .
- run:
name: Install GPC
command: npm install -g @gpc-cli/cli
- run:
name: Upload to Play Store
command: |
gpc releases upload \
app/build/outputs/bundle/release/app-release.aab \
--track internal \
--notes "CircleCI build ${CIRCLE_TAG}" \
--json
workflows:
release:
jobs:
- build:
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
- upload:
requires:
- build
context: gpc-credentials
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
Full Pipeline with Promotion
Multi-stage pipeline with manual approval gates for beta and production promotion.
yaml
# .circleci/config.yml
version: 2.1
jobs:
build:
docker:
- image: cimg/android:2024.07
steps:
- checkout
- run:
name: Build release AAB
command: ./gradlew bundleRelease
- persist_to_workspace:
root: .
paths:
- app/build/outputs/bundle/release/app-release.aab
upload:
docker:
- image: cimg/node:20.0
environment:
GPC_APP: com.example.myapp
steps:
- attach_workspace:
at: .
- run:
name: Install GPC
command: npm install -g @gpc-cli/cli
- run:
name: Upload to internal track
command: |
gpc releases upload \
app/build/outputs/bundle/release/app-release.aab \
--track internal \
--notes "Build ${CIRCLE_TAG}" \
--json
promote-beta:
docker:
- image: cimg/node:20.0
environment:
GPC_APP: com.example.myapp
steps:
- run:
name: Install GPC
command: npm install -g @gpc-cli/cli
- run:
name: Promote to beta
command: gpc releases promote --from internal --to beta --json
promote-production:
docker:
- image: cimg/node:20.0
environment:
GPC_APP: com.example.myapp
steps:
- run:
name: Install GPC
command: npm install -g @gpc-cli/cli
- run:
name: Check vitals before promotion
command: |
gpc vitals crashes --threshold 2.0 --json
gpc vitals anr --threshold 0.5 --json
- run:
name: Promote to production (staged)
command: |
gpc releases promote \
--from beta \
--to production \
--rollout 10 \
--json
vitals-check:
docker:
- image: cimg/node:20.0
environment:
GPC_APP: com.example.myapp
steps:
- run:
name: Install GPC
command: npm install -g @gpc-cli/cli
- run:
name: Check vitals
command: |
CRASH_RATE=$(gpc vitals crashes --json | jq -r '.data.crashRate')
ANR_RATE=$(gpc vitals anr --json | jq -r '.data.anrRate')
echo "Crash rate: ${CRASH_RATE}%"
echo "ANR rate: ${ANR_RATE}%"
if (( $(echo "$CRASH_RATE > 2.0" | bc -l) )); then
echo "Crash rate too high, halting rollout"
gpc releases rollout halt --track production --json
exit 1
fi
echo "Vitals healthy"
workflows:
release:
jobs:
- build:
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
- upload:
requires:
- build
context: gpc-credentials
filters:
tags:
only: /^v.*/
- hold-beta:
type: approval
requires:
- upload
filters:
tags:
only: /^v.*/
- promote-beta:
requires:
- hold-beta
context: gpc-credentials
filters:
tags:
only: /^v.*/
- hold-production:
type: approval
requires:
- promote-beta
filters:
tags:
only: /^v.*/
- promote-production:
requires:
- hold-production
context: gpc-credentials
filters:
tags:
only: /^v.*/
# Scheduled vitals monitoring
nightly-vitals:
triggers:
- schedule:
cron: "0 10 * * *"
filters:
branches:
only:
- main
jobs:
- vitals-check:
context: gpc-credentials1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
Reusable Commands
Define reusable commands to keep your config DRY.
yaml
# .circleci/config.yml
version: 2.1
commands:
install-gpc:
description: Install GPC CLI
steps:
- run:
name: Install GPC
command: npm install -g @gpc-cli/cli
gpc-upload:
description: Upload AAB to a track
parameters:
file:
type: string
track:
type: string
default: internal
notes:
type: string
default: ""
steps:
- install-gpc
- run:
name: Upload to << parameters.track >>
command: |
gpc releases upload "<< parameters.file >>" \
--track "<< parameters.track >>" \
--notes "<< parameters.notes >>" \
--json
gpc-promote:
description: Promote between tracks
parameters:
from:
type: string
to:
type: string
rollout:
type: integer
default: 0
steps:
- install-gpc
- run:
name: Promote from << parameters.from >> to << parameters.to >>
command: |
ROLLOUT_FLAG=""
if [ "<< parameters.rollout >>" -gt 0 ]; then
ROLLOUT_FLAG="--rollout << parameters.rollout >>"
fi
gpc releases promote \
--from "<< parameters.from >>" \
--to "<< parameters.to >>" \
$ROLLOUT_FLAG \
--json1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Use the commands in jobs:
yaml
jobs:
release:
docker:
- image: cimg/node:20.0
environment:
GPC_APP: com.example.myapp
steps:
- attach_workspace:
at: .
- gpc-upload:
file: app/build/outputs/bundle/release/app-release.aab
track: internal
notes: "Build ${CIRCLE_TAG}"1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
