Skip to content

Commit 05a3433

Browse files
authored
3.4.2.3
2 parents 0205225 + 5b46cea commit 05a3433

29 files changed

Lines changed: 1397 additions & 61 deletions

File tree

.github/workflows/aaps-ci.yml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@ on:
66
tagName:
77
description: 'Select AAPS Version'
88
required: true
9-
default: '3.4.2.2'
9+
default: '3.4.2.3'
1010
type: choice
1111
options:
1212
# ── 3.4.x (JDK 21) ──────────────────────────────
13+
- 3.4.2.3
1314
- 3.4.2.2
1415
- 3.4.2.1
1516
- 3.4.2.0

.github/workflows/branch-ci.yml

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,4 +293,19 @@ jobs:
293293
upload_to_gdrive "aaps-${VERSION}${VERSION_SUFFIX}.apk" "aaps-${VERSION}${VERSION_SUFFIX}.apk"
294294
upload_to_gdrive "aaps-wear-${VERSION}${VERSION_SUFFIX}.apk" "aaps-wear-${VERSION}${VERSION_SUFFIX}.apk"
295295
296-
echo "🎉 APKs successfully uploaded to Google Drive!"
296+
echo "🎉 APKs successfully uploaded to Google Drive!"
297+
298+
299+
# Configuration: Threshold-based cleanup
300+
# Cleanup only occurs when total runs exceed: keep_runs + keep_threshold (e.g., 30 + 10 = 40)
301+
cleanup:
302+
name: Cleanup Old Workflow Runs
303+
needs: build
304+
if: always()
305+
uses: ./.github/workflows/cleanup-workflow-runs.yml
306+
with:
307+
workflow_name: 'Branch CI'
308+
keep_runs: 30
309+
keep_threshold: 10
310+
311+

.github/workflows/claude-code-review.yml

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,22 @@ jobs:
2222
permissions:
2323
contents: read
2424
pull-requests: write
25-
issues: write
26-
id-token: write
2725

2826
steps:
29-
- name: Checkout repository
30-
uses: actions/checkout@v4
27+
# Check out the base ref (trusted code), NOT the PR head. The action reads
28+
# the PR diff via `gh pr diff` (API-based), so it does not need the PR's
29+
# files in the workspace. Using head.sha here would let an external PR
30+
# inject files (e.g. CLAUDE.md) that the action then reads under
31+
# pull_request_target — i.e. with repo secrets in scope.
32+
- name: Checkout repository (base ref — trusted)
33+
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
3134
with:
3235
fetch-depth: 1
33-
ref: ${{ github.event.pull_request.head.sha }}
36+
ref: ${{ github.event.pull_request.base.sha }}
3437

3538
- name: Run Claude Code Review
3639
id: claude-review
37-
uses: anthropics/claude-code-action@v1
40+
uses: anthropics/claude-code-action@24492741e0ccfdef4c1d19da8e11e0f373d07494 # v1
3841
with:
3942
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
4043
prompt: |
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: Cleanup Workflow Runs
2+
3+
on:
4+
workflow_call:
5+
inputs:
6+
workflow_name:
7+
required: true
8+
type: string
9+
description: 'Name of the workflow to cleanup runs for'
10+
keep_runs:
11+
required: false
12+
type: number
13+
default: 50
14+
description: 'Target number of recent runs to keep after cleanup'
15+
keep_threshold:
16+
required: false
17+
type: number
18+
default: 10
19+
description: 'Buffer threshold - cleanup only starts when runs exceed keep_runs + keep_threshold'
20+
21+
jobs:
22+
cleanup:
23+
name: Cleanup Old Workflow Runs
24+
runs-on: ubuntu-latest
25+
permissions:
26+
actions: write
27+
steps:
28+
- name: Cleanup old workflow runs
29+
uses: actions/github-script@v7
30+
env:
31+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: true # Ensure we're using Node 24 for GitHub Script'
32+
with:
33+
script: |
34+
const workflowName = '${{ inputs.workflow_name }}';
35+
const keepRuns = ${{ inputs.keep_runs }};
36+
const keepThreshold = ${{ inputs.keep_threshold }};
37+
const cleanupThreshold = keepRuns + keepThreshold;
38+
39+
console.log(`🧹 Starting cleanup check for workflow: "${workflowName}"`);
40+
console.log(`📌 Configuration: keep ${keepRuns} runs, threshold ${cleanupThreshold} (keep_runs + keep_threshold)`);
41+
42+
// Get the current workflow ID
43+
const workflows = await github.rest.actions.listRepoWorkflows({
44+
owner: context.repo.owner,
45+
repo: context.repo.repo,
46+
});
47+
48+
const workflow = workflows.data.workflows.find(w => w.name === workflowName);
49+
if (!workflow) {
50+
console.log(`❌ Workflow "${workflowName}" not found`);
51+
return;
52+
}
53+
54+
console.log(`✅ Found workflow: ${workflow.name} (ID: ${workflow.id})`);
55+
56+
// Get all runs for this workflow
57+
const runs = await github.rest.actions.listWorkflowRuns({
58+
owner: context.repo.owner,
59+
repo: context.repo.repo,
60+
workflow_id: workflow.id,
61+
per_page: 100, // Get up to 100 runs
62+
});
63+
64+
const totalRuns = runs.data.workflow_runs.length;
65+
console.log(`📊 Total runs found: ${totalRuns}`);
66+
67+
// Check if cleanup is needed
68+
if (totalRuns <= cleanupThreshold) {
69+
console.log(`✅ No cleanup needed (${totalRuns} runs ≤ ${cleanupThreshold} threshold)`);
70+
return;
71+
}
72+
73+
console.log(`⚠️ Cleanup threshold reached! (${totalRuns} runs > ${cleanupThreshold} threshold)`);
74+
console.log(`🧹 Starting cleanup: will keep ${keepRuns} runs, deleting ${totalRuns - keepRuns} runs`);
75+
76+
// Sort runs by creation date (newest first)
77+
const sortedRuns = runs.data.workflow_runs.sort(
78+
(a, b) => new Date(b.created_at) - new Date(a.created_at)
79+
);
80+
81+
// Keep only the most recent runs
82+
const runsToDelete = sortedRuns.slice(keepRuns);
83+
84+
console.log(`📌 Keeping ${keepRuns} most recent runs, deleting ${runsToDelete.length} older runs`);
85+
86+
// Delete old runs
87+
for (const run of runsToDelete) {
88+
try {
89+
await github.rest.actions.deleteWorkflowRun({
90+
owner: context.repo.owner,
91+
repo: context.repo.repo,
92+
run_id: run.id,
93+
});
94+
console.log(`🗑️ Deleted run: ${run.id} (created: ${run.created_at})`);
95+
} catch (error) {
96+
console.error(`❌ Failed to delete run ${run.id}: ${error.message}`);
97+
}
98+
}
99+
100+
console.log(`✅ Workflow cleanup completed`);

app/src/main/kotlin/app/aaps/implementations/ConfigImpl.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ class ConfigImpl @Inject constructor(
4444
private var ignoreNightscoutV3Errors: Boolean? = null
4545
private var doNotSendSmsOnProfileChange: Boolean? = null
4646
private var enableAutotune: Boolean? = null
47+
private var enableOmnipodDriftCompensation: Boolean? = null
4748
private var disableLeakCanary: Boolean? = null
4849

4950
override fun isEngineeringModeOrRelease(): Boolean = if (!APS) true else isEngineeringMode() || !isDev()
@@ -54,5 +55,6 @@ class ConfigImpl @Inject constructor(
5455
override fun ignoreNightscoutV3Errors(): Boolean = ignoreNightscoutV3Errors ?: (fileListProvider.get().ensureExtraDirExists()?.findFile("ignore_nightscout_v3_errors") != null).also { ignoreNightscoutV3Errors = it }
5556
override fun doNotSendSmsOnProfileChange(): Boolean = doNotSendSmsOnProfileChange ?: (fileListProvider.get().ensureExtraDirExists()?.findFile("do_not_send_sms_on_profile_change") != null).also { doNotSendSmsOnProfileChange = it }
5657
override fun enableAutotune(): Boolean = enableAutotune ?: (fileListProvider.get().ensureExtraDirExists()?.findFile("enable_autotune") != null).also { enableAutotune = it }
58+
override fun enableOmnipodDriftCompensation(): Boolean = enableOmnipodDriftCompensation ?: (fileListProvider.get().ensureExtraDirExists()?.findFile("omnipod_drift_compensation") != null).also { enableOmnipodDriftCompensation = it }
5759
override fun disableLeakCanary(): Boolean = disableLeakCanary ?: (fileListProvider.get().ensureExtraDirExists()?.findFile("disable_leakcanary") != null).also { disableLeakCanary = it }
5860
}

buildSrc/src/main/kotlin/Versions.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ import org.jetbrains.kotlin.gradle.dsl.JvmTarget
44
@Suppress("ConstPropertyName")
55
object Versions {
66

7-
const val appVersion = "3.4.2.2"
7+
// On change edit aaps-ci.yml
8+
const val appVersion = "3.4.2.3"
89
const val versionCode = 1500
910

1011
const val compileSdk = 36

core/interfaces/src/main/kotlin/app/aaps/core/interfaces/configuration/Config.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ interface Config {
3434
fun ignoreNightscoutV3Errors(): Boolean
3535
fun doNotSendSmsOnProfileChange(): Boolean
3636
fun enableAutotune(): Boolean
37+
fun enableOmnipodDriftCompensation(): Boolean
3738

3839
/**
3940
* Disable LeakCanary (memory leaks detection). By default it's enabled in DEBUG builds.

database/impl/src/main/kotlin/app/aaps/database/transactions/SyncPumpTemporaryBasalTransaction.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class SyncPumpTemporaryBasalTransaction(
3434
}
3535
} else {
3636
val running = database.temporaryBasalDao.getTemporaryBasalActiveAtLegacy(temporaryBasal.timestamp)
37-
if (running != null) {
37+
if (running != null && temporaryBasal.timestamp > running.timestamp) {
3838
val old = running.copy()
3939
running.end = temporaryBasal.timestamp
4040
running.interfaceIDs.endId = temporaryBasal.interfaceIDs.pumpId

database/impl/src/test/kotlin/app/aaps/database/transactions/SyncPumpTemporaryBasalTransactionTest.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,22 @@ class SyncPumpTemporaryBasalTransactionTest {
9393
assertThat(running.interfaceIDs.endId).isEqualTo(100L)
9494
}
9595

96+
@Test
97+
fun `skips ending running TBR when it has the same start timestamp as the new TBR`() {
98+
val tb = createTemporaryBasal(pumpId = 100L, timestamp = 1000L, rate = 2.0, duration = 30_000L)
99+
val running = createTemporaryBasal(pumpId = 50L, timestamp = 1000L, rate = 1.5, duration = 60_000L)
100+
101+
whenever(temporaryBasalDao.findByPumpIds(100L, InterfaceIDs.PumpType.DANA_I, "ABC123")).thenReturn(null)
102+
whenever(temporaryBasalDao.getTemporaryBasalActiveAtLegacy(1000L)).thenReturn(running)
103+
104+
val transaction = SyncPumpTemporaryBasalTransaction(tb, null)
105+
transaction.database = database
106+
val result = transaction.run()
107+
108+
assertThat(result.updated).isEmpty()
109+
assertThat(result.inserted).hasSize(1)
110+
}
111+
96112
@Test
97113
fun `updates type when provided`() {
98114
val tb = createTemporaryBasal(pumpId = 100L, timestamp = 1000L, rate = 1.5, duration = 60_000L, type = TemporaryBasal.Type.NORMAL)

plugins/automation/src/main/kotlin/app/aaps/plugins/automation/actions/Action.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ abstract class Action(val injector: HasAndroidInjector) {
6868
ActionRunAutotune::class.java.simpleName -> ActionRunAutotune(injector).fromJSON(data.toString())
6969
ActionSendSMS::class.java.simpleName -> ActionSendSMS(injector).fromJSON(data.toString())
7070
ActionStartTempTarget::class.java.simpleName -> ActionStartTempTarget(injector).fromJSON(data.toString())
71+
ActionStopProcessing::class.java.simpleName -> ActionStopProcessing(injector).fromJSON(data.toString())
7172
ActionStopTempTarget::class.java.simpleName -> ActionStopTempTarget(injector).fromJSON(data.toString())
7273
else -> throw ClassNotFoundException(type)
7374
}

0 commit comments

Comments
 (0)