From e6d8d435ffb70951fdb4438c4121e4c3897059a7 Mon Sep 17 00:00:00 2001 From: lkasso Date: Sun, 19 Jul 2026 20:52:35 -0700 Subject: [PATCH 1/2] CI runs the app-target tests; retire the dead LoggingPill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The entire app-side test net — the group-capture E2E suite against the demo fleet, history grouping, foreign-log decisions, export filenames — was invisible to CI, which ran only the SPM suites. New app-tests job runs MetaWearAppTests on an iOS 26 simulator (the app's floor), on the newer runner image that carries Xcode 26. LoggingPill was mounted nowhere (its removal is documented in RootView) and filtered on the pre-multi-device activeDeviceID — deleted, and the three comments that still described it as live now reference the real surfaces (pending-log badges, the Logging screen's status row). Co-Authored-By: Claude Fable 5 --- .github/workflows/ci.yml | 15 ++++++ Apps/MetaWear/MetaWear/App/RootView.swift | 4 +- .../Features/Logging/LogSessionView.swift | 2 +- .../Features/Logging/LoggingPill.swift | 53 ------------------- .../ViewModels/LogSessionViewModel.swift | 2 +- 5 files changed, 19 insertions(+), 57 deletions(-) delete mode 100644 Apps/MetaWear/MetaWear/Features/Logging/LoggingPill.swift diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3ddfc2f..58b5593 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,3 +7,18 @@ jobs: - uses: actions/checkout@v4 - run: swift build --build-tests - run: swift test --filter MetaWearTests # skip hardware tests in CI + # The app target's unit tests (coordinator E2E against the demo fleet, + # history grouping, foreign-log decisions, …) were invisible to CI — + # only the SPM suites ran. The app requires the iOS 26 SDK, hence the + # newer runner image. + app-tests: + runs-on: macos-26 + steps: + - uses: actions/checkout@v4 + - run: > + xcodebuild test + -project Apps/MetaWear/MetaWearApp.xcodeproj + -scheme MetaWearApp + -destination 'platform=iOS Simulator,name=iPhone 17' + -only-testing:MetaWearAppTests + CODE_SIGNING_ALLOWED=NO diff --git a/Apps/MetaWear/MetaWear/App/RootView.swift b/Apps/MetaWear/MetaWear/App/RootView.swift index 51e0315..0c289c5 100644 --- a/Apps/MetaWear/MetaWear/App/RootView.swift +++ b/Apps/MetaWear/MetaWear/App/RootView.swift @@ -145,8 +145,8 @@ private struct ErrorAndOrphanAlerts: ViewModifier { // so the user can decide what to do with it. The alert only // fires when LOG_LENGTH > 0 *and* we have no matching local // pending session — the in-app logging flow has its own UI - // for sessions it already knows about (LoggingPill, - // DownloadView). + // for sessions it already knows about (the Logging + // screen's status row, DownloadView). .alert( "Logging in progress", isPresented: Binding( diff --git a/Apps/MetaWear/MetaWear/Features/Logging/LogSessionView.swift b/Apps/MetaWear/MetaWear/Features/Logging/LogSessionView.swift index 5e8b896..51c8b9e 100644 --- a/Apps/MetaWear/MetaWear/Features/Logging/LogSessionView.swift +++ b/Apps/MetaWear/MetaWear/Features/Logging/LogSessionView.swift @@ -197,7 +197,7 @@ struct LogSessionView: View { Task { await viewModel?.start(selections) // Refresh the AppStore's pending-sessions cache so the - // global `LoggingPill` becomes visible immediately. + // pending-log badges appear immediately. appStore.refreshPendingLogSessions() } } diff --git a/Apps/MetaWear/MetaWear/Features/Logging/LoggingPill.swift b/Apps/MetaWear/MetaWear/Features/Logging/LoggingPill.swift deleted file mode 100644 index fab2999..0000000 --- a/Apps/MetaWear/MetaWear/Features/Logging/LoggingPill.swift +++ /dev/null @@ -1,53 +0,0 @@ -import SwiftUI - -/// Top-of-screen pill that surfaces an active logging session on the connected -/// device. Only shown while a session is *actually recording* (`status == .running`); -/// `.stopped` sessions (data captured, awaiting download) show up as the -/// remembered-device row badge instead, so the pill doesn't keep ticking after -/// the user has stopped the session. -struct LoggingPill: View { - @Environment(AppStore.self) private var appStore - @State private var now: Date = .now - - private var runningSessions: [LogSessionRecord] { - appStore.pendingLogSessions.filter { - $0.deviceID == appStore.activeDeviceID && $0.status == .running - } - } - - private var earliestStart: Date? { - runningSessions.map(\.startDate).min() - } - - var body: some View { - if let start = earliestStart { - HStack(spacing: 8) { - Image(systemName: "record.circle.fill") - .foregroundStyle(Palette.danger) - .symbolEffect(.pulse, options: .repeating) - .accessibilityHidden(true) - Text("Logging · \(elapsed(from: start))") - .font(.subheadline.weight(.medium)) - .monospacedDigit() - } - .glassPill(tint: Palette.danger.opacity(0.25)) - .task { - while !Task.isCancelled { - now = .now - try? await Task.sleep(for: .seconds(1)) - } - } - .accessibilityLabel("Logging in progress, \(elapsed(from: start)) elapsed") - } - } - - private func elapsed(from start: Date) -> String { - let elapsed = Int(now.timeIntervalSince(start)) - let m = elapsed / 60, s = elapsed % 60 - return "\(twoDigits(m)):\(twoDigits(s))" - } - - private func twoDigits(_ value: Int) -> String { - value < 10 ? "0\(value)" : "\(value)" - } -} diff --git a/Apps/MetaWear/MetaWear/ViewModels/LogSessionViewModel.swift b/Apps/MetaWear/MetaWear/ViewModels/LogSessionViewModel.swift index 59375c1..3be2cc9 100644 --- a/Apps/MetaWear/MetaWear/ViewModels/LogSessionViewModel.swift +++ b/Apps/MetaWear/MetaWear/ViewModels/LogSessionViewModel.swift @@ -167,7 +167,7 @@ final class LogSessionViewModel { // Per-record try/catch — a single failed `stopOne` (BLE hiccup, // unexpected board state) used to abort the loop, leaving the // remaining records' `status` stuck at `.running` and the global - // `LoggingPill` ticking forever. We always flip the status to + // pending-log badges stuck forever. We always flip the status to // `.stopped` even when the BLE command threw, because: // - the user explicitly asked the session to stop, and // - the captured data is still on the board for download. From f15f266cac8b8895370ee4b68ef2d1f6689a330d Mon Sep 17 00:00:00 2001 From: Laura Kassovic Date: Sun, 19 Jul 2026 20:57:37 -0700 Subject: [PATCH 2/2] Potential fix for pull request finding 'CodeQL / Workflow does not contain permissions' Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 58b5593..c0e5fb2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,5 +1,7 @@ name: CI on: [pull_request] +permissions: + contents: read jobs: build-and-test: runs-on: macos-15