Skip to content

Commit efaabe8

Browse files
authored
Merge pull request #4072 from nightscout/dev332
3.3.2.1
2 parents ba551ca + ce278af commit efaabe8

File tree

32 files changed

+1588
-432
lines changed

32 files changed

+1588
-432
lines changed

.circleci/config.yml

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Use the latest 2.1 version of CircleCI pipeline process engine.
1+
# Use the latest 2.1 version of CircleCI pipeline process engine.
22
# See: https://circleci.com/docs/2.0/configuration-reference
33
version: 2.1
44

@@ -19,21 +19,21 @@ jobs:
1919
- run:
2020
name: Create avd
2121
command: |
22-
echo "no" | /opt/android-sdk/cmdline-tools/latest/bin/avdmanager --verbose create avd -n citest -k "system-images;android-30;google_apis_playstore;x86" --force
22+
echo "no" | /usr/lib/android-sdk/cmdline-tools/13.0/bin/avdmanager --verbose create avd -n citest -k "system-images;android-31;google_apis_playstore;x86_64" --force
2323
2424
- run:
2525
name: Launch emulator
2626
command: |
27-
export ANDROID_SDK_ROOT=/opt/android-sdk
28-
export ANDROID_HOME=/opt/android-sdk
27+
export ANDROID_SDK_ROOT=/usr/lib/android-sdk
28+
export ANDROID_HOME=/usr/lib/android-sdk
2929
emulator -avd citest -delay-adb -verbose -no-window -gpu swiftshader_indirect -no-snapshot -noaudio -no-boot-anim
3030
background: true
3131

3232
- run:
3333
name: Run connectedFullDebugAndroidTest
3434
command: |
35-
export ANDROID_SDK_ROOT=/opt/android-sdk
36-
export ANDROID_HOME=/opt/android-sdk
35+
export ANDROID_SDK_ROOT=/usr/lib/android-sdk
36+
export ANDROID_HOME=/usr/lib/android-sdk
3737
env
3838
./gradlew -Dorg.gradle.jvmargs=-Xmx6g connectedFullDebugAndroidTest
3939
@@ -46,15 +46,15 @@ jobs:
4646
- run:
4747
name: Run testFullDebugUnitTest
4848
command: |
49-
export ANDROID_SDK_ROOT=/opt/android-sdk
50-
export ANDROID_HOME=/opt/android-sdk
49+
export ANDROID_SDK_ROOT=/usr/lib/android-sdk
50+
export ANDROID_HOME=/usr/lib/android-sdk
5151
./gradlew -Dorg.gradle.jvmargs=-Xmx6g testFullDebugUnitTest
5252
5353
- run:
5454
run: Run jacocoAllDebugReport
5555
command: |
56-
export ANDROID_SDK_ROOT=/opt/android-sdk
57-
export ANDROID_HOME=/opt/android-sdk
56+
export ANDROID_SDK_ROOT=/usr/lib/android-sdk
57+
export ANDROID_HOME=/usr/lib/android-sdk
5858
./gradlew --stacktrace jacocoAllDebugReport
5959
6060
- run:
@@ -73,6 +73,12 @@ jobs:
7373
- codecov/upload:
7474
file: './build/reports/jacoco/jacocoAllDebugReport/jacocoAllDebugReport.xml'
7575

76+
- run:
77+
name: Kill java processes
78+
command: |
79+
killall java
80+
when: always
81+
7682
workflows:
7783
# Below is the definition of your workflow.
7884
# Inside the workflow, you provide the jobs you want to run, e.g this workflow runs the build-and-test job above.

.github/workflows/aaps-ci.yml

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
name: AAPS CI
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
buildVariant:
7+
description: 'Select Build Variant'
8+
required: true
9+
default: 'fullRelease'
10+
type: choice
11+
options:
12+
- fullRelease
13+
- fullDebug
14+
- aapsclientRelease
15+
- aapsclientDebug
16+
- aapsclient2Release
17+
- aapsclient2Debug
18+
- pumpcontrolRelease
19+
- pumpcontrolDebug
20+
21+
jobs:
22+
build:
23+
name: Build AAPS
24+
runs-on: ubuntu-latest
25+
steps:
26+
- name: Decode Secrets Keystore Set and Oauth2 to Env
27+
run: |
28+
if [ -n "${{ secrets.KEYSTORE_SET }}" ]; then
29+
echo "🔐 Decoding KEYSTORE_SET..."
30+
DECODED=$(echo "${{ secrets.KEYSTORE_SET }}" | base64 -d)
31+
32+
KEYSTORE_BASE64=$(echo "$DECODED" | cut -d'|' -f1)
33+
KEYSTORE_PASSWORD=$(echo "$DECODED" | cut -d'|' -f2)
34+
KEY_ALIAS=$(echo "$DECODED" | cut -d'|' -f3)
35+
KEY_PASSWORD=$(echo "$DECODED" | cut -d'|' -f4)
36+
37+
echo "KEYSTORE_BASE64=$KEYSTORE_BASE64" >> $GITHUB_ENV
38+
echo "KEYSTORE_PASSWORD=$KEYSTORE_PASSWORD" >> $GITHUB_ENV
39+
echo "KEY_ALIAS=$KEY_ALIAS" >> $GITHUB_ENV
40+
echo "KEY_PASSWORD=$KEY_PASSWORD" >> $GITHUB_ENV
41+
42+
echo "::add-mask::$KEYSTORE_BASE64"
43+
echo "::add-mask::$KEYSTORE_PASSWORD"
44+
echo "::add-mask::$KEY_ALIAS"
45+
echo "::add-mask::$KEY_PASSWORD"
46+
47+
echo "✅ Keystore parameters extracted from KEYSTORE_SET"
48+
else
49+
echo "ℹ️ KEYSTORE_SET not provided, using separate secrets."
50+
echo "KEYSTORE_BASE64=${{ secrets.KEYSTORE_BASE64 }}" >> $GITHUB_ENV
51+
echo "KEYSTORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> $GITHUB_ENV
52+
echo "KEY_ALIAS=${{ secrets.KEY_ALIAS }}" >> $GITHUB_ENV
53+
echo "KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> $GITHUB_ENV
54+
fi
55+
echo "GDRIVE_OAUTH2=${{ secrets.GDRIVE_OAUTH2 }}" >> $GITHUB_ENV
56+
57+
- name: Check Secrets
58+
run: |
59+
echo "🔍 Checking required secrets..."
60+
MISSING=0
61+
62+
check_secret() {
63+
if [ -z "$1" ]; then
64+
echo "❌ Missing secret: $2"
65+
MISSING=1
66+
fi
67+
}
68+
69+
# Check secrets
70+
check_secret "$GDRIVE_OAUTH2" "GDRIVE_OAUTH2"
71+
72+
check_secret "$KEYSTORE_BASE64" "KEYSTORE_BASE64"
73+
check_secret "$KEYSTORE_PASSWORD" "KEYSTORE_PASSWORD"
74+
check_secret "$KEY_ALIAS" "KEY_ALIAS"
75+
check_secret "$KEY_PASSWORD" "KEY_PASSWORD"
76+
77+
if [ "$MISSING" -eq 1 ]; then
78+
echo "🛑 Missing required secrets. Stopping build."
79+
exit 1
80+
fi
81+
82+
echo "✅ All required secrets are present."
83+
84+
- name: Decode keystore file
85+
run: |
86+
mkdir -p "$RUNNER_TEMP/keystore"
87+
echo "$KEYSTORE_BASE64" | base64 -d > "$RUNNER_TEMP/keystore/keystore.jks"
88+
89+
- name: Validating keystore, alias and password
90+
run: |
91+
set -x
92+
echo "🔐 Validating keystore, alias and password"
93+
94+
# Create a dummy JAR file (quick method using zip)
95+
echo "test" > dummy.txt
96+
zip -q dummy.jar dummy.txt
97+
rm dummy.txt
98+
99+
# Attempt to validate using jarsigner
100+
JARSIGNER_LOG=$(mktemp)
101+
if ! jarsigner \
102+
-keystore "$RUNNER_TEMP/keystore/keystore.jks" \
103+
-storepass "$KEYSTORE_PASSWORD" \
104+
-keypass "$KEY_PASSWORD" \
105+
dummy.jar "$KEY_ALIAS" > "$JARSIGNER_LOG" 2>&1; then
106+
echo "❌ Either KEYSTORE_BASE64, KEYSTORE_PASSWORD, KEY_PASSWORD, or KEY_ALIAS is incorrect"
107+
echo "🔍 jarsigner error output:"
108+
cat "$JARSIGNER_LOG"
109+
rm -f "$JARSIGNER_LOG" dummy.jar
110+
exit 1
111+
fi
112+
rm -f "$JARSIGNER_LOG" dummy.jar
113+
echo "✅ Keystore, alias, and key password are valid."
114+
115+
rm -f "$KEYTOOL_LOG"
116+
echo "✅ Keystore and credentials validated."
117+
118+
- name: Decode GDrive OAuth2 secrets
119+
run: |
120+
echo "🔐 Decoding GDRIVE_OAUTH2..."
121+
DECODED=$(echo "${{ secrets.GDRIVE_OAUTH2 }}" | base64 -d)
122+
123+
GDRIVE_CLIENT_ID=$(echo "$DECODED" | cut -d'|' -f1)
124+
GDRIVE_REFRESH_TOKEN=$(echo "$DECODED" | cut -d'|' -f2)
125+
126+
echo "::add-mask::$GDRIVE_CLIENT_ID"
127+
echo "::add-mask::$GDRIVE_REFRESH_TOKEN"
128+
129+
echo "GDRIVE_CLIENT_ID=$GDRIVE_CLIENT_ID" >> $GITHUB_ENV
130+
echo "GDRIVE_REFRESH_TOKEN=$GDRIVE_REFRESH_TOKEN" >> $GITHUB_ENV
131+
132+
echo "✅ GDRIVE_CLIENT_ID and GDRIVE_REFRESH_TOKEN extracted from GDRIVE_OAUTH2"
133+
134+
- name: Retrieving Google Drive access token
135+
run: |
136+
echo "🔐 Getting Google OAuth2 access token..."
137+
TOKEN_RESPONSE=$(curl -s -X POST https://oauth2.googleapis.com/token \
138+
-d client_id="$GDRIVE_CLIENT_ID" \
139+
-d refresh_token="$GDRIVE_REFRESH_TOKEN" \
140+
-d grant_type=refresh_token)
141+
ACCESS_TOKEN=$(echo "$TOKEN_RESPONSE" | jq -r .access_token)
142+
echo "::add-mask::$ACCESS_TOKEN"
143+
if [ -z "$ACCESS_TOKEN" ] || [ "$ACCESS_TOKEN" = "null" ]; then
144+
echo "❌ Failed to get access token."
145+
echo "$TOKEN_RESPONSE"
146+
exit 1
147+
fi
148+
echo "ACCESS_TOKEN=$ACCESS_TOKEN" >> $GITHUB_ENV
149+
echo "✅ Access token obtained."
150+
151+
- name: Checkout source code
152+
uses: actions/checkout@v4
153+
154+
- name: Set BUILD_VARIANT
155+
run: |
156+
BUILD_VARIANT="${{ github.event.inputs.buildVariant }}"
157+
echo "BUILD_VARIANT=$BUILD_VARIANT" >> $GITHUB_ENV
158+
VARIANT_FLAVOR=$(echo "$BUILD_VARIANT" | sed -E 's/(Release|Debug)$//' | tr '[:upper:]' '[:lower:]')
159+
VARIANT_TYPE=$(echo "$BUILD_VARIANT" | grep -oE '(Release|Debug)$' | tr '[:upper:]' '[:lower:]')
160+
echo "VARIANT_FLAVOR=$VARIANT_FLAVOR" >> $GITHUB_ENV
161+
echo "VARIANT_TYPE=$VARIANT_TYPE" >> $GITHUB_ENV
162+
VERSION_SUFFIX=""
163+
if [[ "$VARIANT_FLAVOR" != "full" ]]; then VERSION_SUFFIX="$VARIANT_FLAVOR"; fi
164+
if [[ "$VARIANT_TYPE" == "debug" ]]; then VERSION_SUFFIX="$VERSION_SUFFIX-debug"; fi
165+
if [[ -n "$VERSION_SUFFIX" && "$VERSION_SUFFIX" != -* ]]; then VERSION_SUFFIX="-$VERSION_SUFFIX"; fi
166+
echo "VERSION_SUFFIX=$VERSION_SUFFIX" >> $GITHUB_ENV
167+
168+
- name: Extract VERSION
169+
run: |
170+
BRANCH_NAME=$(git rev-parse --abbrev-ref HEAD)
171+
if echo "$BRANCH_NAME" | grep -qE '^[0-9]+\.[0-9]+\.[0-9]+(\.[0-9]+)?$'; then
172+
VERSION="$BRANCH_NAME"
173+
else
174+
VERSION=$(grep 'val appVersion' buildSrc/src/main/kotlin/Versions.kt | awk -F '"' '{print $2}')
175+
fi
176+
echo "VERSION=$VERSION" >> $GITHUB_ENV
177+
178+
- name: Set up JDK
179+
uses: actions/setup-java@v4
180+
with:
181+
# When upgrading the JDK, please update this section accordingly as well.
182+
java-version: 21
183+
distribution: 'temurin'
184+
cache: gradle
185+
186+
- name: Grant execute permission for gradlew
187+
run: chmod +x gradlew
188+
189+
- name: Build APKs
190+
run: |
191+
./gradlew assemble${{ env.BUILD_VARIANT }} \
192+
-Pandroid.injected.signing.store.file="$RUNNER_TEMP/keystore/keystore.jks" \
193+
-Pandroid.injected.signing.store.password="$KEYSTORE_PASSWORD" \
194+
-Pandroid.injected.signing.key.alias="$KEY_ALIAS" \
195+
-Pandroid.injected.signing.key.password="$KEY_PASSWORD"
196+
197+
- name: Rename APKs with version
198+
run: |
199+
mv app/build/outputs/apk/${{ env.VARIANT_FLAVOR }}/${{ env.VARIANT_TYPE }}/*.apk aaps-${{ env.VERSION }}${{ env.VERSION_SUFFIX }}.apk
200+
mv wear/build/outputs/apk/${{ env.VARIANT_FLAVOR }}/${{ env.VARIANT_TYPE }}/*.apk aaps-wear-${{ env.VERSION }}${{ env.VERSION_SUFFIX }}.apk
201+
202+
- name: Upload APKs to Google Drive
203+
run: |
204+
set -e
205+
echo "🔐 Start uploading APKs to Google Drive..."
206+
207+
echo "📁 Checking or creating AAPS folder"
208+
AAPS_FOLDER_ID=$(curl -s -X GET \
209+
-H "Authorization: Bearer $ACCESS_TOKEN" \
210+
"https://www.googleapis.com/drive/v3/files?q=name='AAPS'+and+mimeType='application/vnd.google-apps.folder'+and+trashed=false" \
211+
| jq -r '.files[0].id')
212+
213+
if [ "$AAPS_FOLDER_ID" == "null" ] || [ -z "$AAPS_FOLDER_ID" ]; then
214+
AAPS_FOLDER_ID=$(curl -s -X POST \
215+
-H "Authorization: Bearer $ACCESS_TOKEN" \
216+
-H "Content-Type: application/json" \
217+
-d '{"name": "AAPS", "mimeType": "application/vnd.google-apps.folder"}' \
218+
"https://www.googleapis.com/drive/v3/files" | jq -r '.id')
219+
echo "📂 Created AAPS folder: $AAPS_FOLDER_ID"
220+
else
221+
echo "📂 Found AAPS folder: $AAPS_FOLDER_ID"
222+
fi
223+
224+
echo "📁 Checking or creating version folder: $VERSION"
225+
VERSION_FOLDER_ID=$(curl -s -X GET \
226+
-H "Authorization: Bearer $ACCESS_TOKEN" \
227+
"https://www.googleapis.com/drive/v3/files?q=name='${VERSION}'+and+mimeType='application/vnd.google-apps.folder'+and+'$AAPS_FOLDER_ID'+in+parents+and+trashed=false" \
228+
| jq -r '.files[0].id')
229+
230+
if [ "$VERSION_FOLDER_ID" == "null" ] || [ -z "$VERSION_FOLDER_ID" ]; then
231+
VERSION_FOLDER_ID=$(curl -s -X POST \
232+
-H "Authorization: Bearer $ACCESS_TOKEN" \
233+
-H "Content-Type: application/json" \
234+
-d "{\"name\": \"${VERSION}\", \"mimeType\": \"application/vnd.google-apps.folder\", \"parents\": [\"$AAPS_FOLDER_ID\"]}" \
235+
"https://www.googleapis.com/drive/v3/files" | jq -r '.id')
236+
echo "📂 Created version folder: $VERSION_FOLDER_ID"
237+
else
238+
echo "📂 Found version folder: $VERSION_FOLDER_ID"
239+
fi
240+
241+
upload_to_gdrive() {
242+
FILE=$1
243+
NAME=$2
244+
if [ ! -f "$FILE" ]; then
245+
echo "❌ File not found: $FILE"
246+
exit 26
247+
fi
248+
249+
echo "📄 Checking if file $NAME already exists in Google Drive..."
250+
QUERY="name='${NAME}' and '${VERSION_FOLDER_ID}' in parents and trashed=false"
251+
ENCODED_QUERY=$(python3 -c "import urllib.parse; print(urllib.parse.quote('''$QUERY'''))")
252+
FILE_ID=$(curl -s \
253+
-H "Authorization: Bearer $ACCESS_TOKEN" \
254+
"https://www.googleapis.com/drive/v3/files?q=${ENCODED_QUERY}&fields=files(id)" \
255+
| jq -r '.files[0].id')
256+
257+
if [[ -n "$FILE_ID" && "$FILE_ID" != "null" ]]; then
258+
echo "🗑️ Deleting existing file with ID: $FILE_ID"
259+
curl -s -X DELETE \
260+
-H "Authorization: Bearer $ACCESS_TOKEN" \
261+
"https://www.googleapis.com/drive/v3/files/${FILE_ID}"
262+
fi
263+
264+
echo "⬆️ Uploading $FILE as $NAME to Google Drive..."
265+
RESPONSE=$(curl -s -w "%{http_code}" -o /tmp/gdrive_response.json \
266+
-X POST \
267+
-H "Authorization: Bearer $ACCESS_TOKEN" \
268+
-F "metadata={\"name\":\"$NAME\", \"parents\":[\"$VERSION_FOLDER_ID\"]};type=application/json;charset=UTF-8" \
269+
-F "file=@$FILE;type=application/vnd.android.package-archive" \
270+
"https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart")
271+
272+
HTTP_CODE="${RESPONSE: -3}"
273+
if [[ "$HTTP_CODE" != "200" && "$HTTP_CODE" != "201" ]]; then
274+
echo "❌ Upload failed with HTTP status: $HTTP_CODE"
275+
cat /tmp/gdrive_response.json
276+
exit 1
277+
fi
278+
279+
echo "✅ Uploaded: $NAME"
280+
}
281+
282+
upload_to_gdrive "aaps-${VERSION}${VERSION_SUFFIX}.apk" "aaps-${VERSION}${VERSION_SUFFIX}.apk"
283+
upload_to_gdrive "aaps-wear-${VERSION}${VERSION_SUFFIX}.apk" "aaps-wear-${VERSION}${VERSION_SUFFIX}.apk"
284+
285+
echo "🎉 APKs successfully uploaded to Google Drive!"

0 commit comments

Comments
 (0)