Skip to content

Commit 922e528

Browse files
authored
176983 UI state (#4957)
Added every 30 seconds page refresh Fix: flutter/flutter#176983
1 parent 160f796 commit 922e528

19 files changed

Lines changed: 1422 additions & 626 deletions

File tree

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# Track refactor_presubmit_state_20260223 Context
2+
3+
- [Specification](./spec.md)
4+
- [Implementation Plan](./plan.md)
5+
- [Metadata](./metadata.json)
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"track_id": "refactor_presubmit_state_20260223",
3+
"type": "refactor",
4+
"status": "new",
5+
"created_at": "2026-02-23T10:00:00Z",
6+
"updated_at": "2026-02-23T10:00:00Z",
7+
"description": "For PreSubmitView move all state change logic to PresubmitState similarly to how BuildDashboardPage use BuildState"
8+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Implementation Plan - Refactor PreSubmitView State Management
2+
3+
## Phase 1: Foundation - Create PresubmitState [checkpoint: 584afaa]
4+
This phase focuses on creating the new `PresubmitState` class and migrating the core data fetching logic.
5+
6+
- [x] Task: Create `dashboard/lib/state/presubmit.dart` with `PresubmitState` class, including `repo`, `pr`, and `sha` properties.
7+
- [x] Task: Implement initialization and update methods for `repo`, `pr`, and `sha` in `PresubmitState`.
8+
- [x] Task: Implement `fetchAvailableShas` and `fetchGuardStatus` in `PresubmitState`.
9+
- [x] Task: Write unit tests for `PresubmitState` in `dashboard/test/state/presubmit_test.dart`.
10+
- [x] Task: Conductor - User Manual Verification 'Phase 1: Foundation' (Protocol in workflow.md)
11+
12+
## Phase 2: Refactor PreSubmitView
13+
This phase integrates `PresubmitState` into the main `PreSubmitView` widget and removes its local state.
14+
15+
- [x] Task: Update `dashboard/lib/main.dart` or the relevant state provider to instantiate and provide `PresubmitState`.
16+
- [~] Task: Refactor `_PreSubmitViewState` to use `PresubmitState` for context management (repo, pr, sha) and data fetching.
17+
- [ ] Task: Update `dashboard/test/views/presubmit_view_test.dart` to ensure compatibility with the new state management.
18+
- [ ] Task: Conductor - User Manual Verification 'Phase 2: Refactor PreSubmitView' (Protocol in workflow.md)
19+
20+
## Phase 3: Refactor LogViewerPane and Finalize
21+
This phase completes the migration by moving the check details logic and performing final verification.
22+
23+
- [ ] Task: Implement `fetchCheckDetails` and associated state (`selectedCheck`, `checks`) in `PresubmitState`.
24+
- [ ] Task: Refactor `_LogViewerPaneState` in `dashboard/lib/views/presubmit_view.dart` to use `PresubmitState`.
25+
- [ ] Task: Final verification of `PreSubmitView` functionality and test coverage.
26+
- [ ] Task: Conductor - User Manual Verification 'Phase 3: Refactor LogViewerPane and Finalize' (Protocol in workflow.md)
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Specification - Refactor PreSubmitView State Management
2+
3+
## Overview
4+
This track involves refactoring the `PreSubmitView` to move its state and logic into a dedicated `PresubmitState` class, following the pattern used by `BuildDashboardPage` and `BuildState`. This will improve code organization, testability, and consistency across the Cocoon dashboard.
5+
6+
## Goals
7+
- Extract all data fetching and processing logic from `PreSubmitView` into `PresubmitState`.
8+
- Centralize state management for PR summaries, guard statuses, and check details.
9+
- Align the architecture of `PreSubmitView` with the project's established patterns.
10+
11+
## Functional Requirements
12+
- **PresubmitState Class:**
13+
- Inherit from `ChangeNotifier`.
14+
- Hold context properties: `repo`, `pr`, and `sha`.
15+
- Handle fetching available SHAs for a PR (`fetchAvailableShas`).
16+
- Handle fetching guard status for a specific SHA (`fetchGuardStatus`).
17+
- Handle fetching check details/logs (`fetchCheckDetails`).
18+
- Expose state properties: `repo`, `pr`, `sha`, `guardResponse`, `isLoading`, `availableSummaries`, `selectedCheck`, `checks`.
19+
- **PreSubmitView Integration:**
20+
- Use `Provider.of<PresubmitState>` to access state and trigger actions.
21+
- Remove local state variables and direct `CocoonService` calls from `_PreSubmitViewState`.
22+
- **LogViewerPane Integration:**
23+
- Use `PresubmitState` for fetching and displaying check details.
24+
- Remove local state variables from `_LogViewerPaneState`.
25+
26+
## Non-Functional Requirements
27+
- **Consistency:** Follow the adaptive alignment with `BuildState`.
28+
- **Testability:** The new `PresubmitState` should be easily testable in isolation.
29+
30+
## Acceptance Criteria
31+
- `PreSubmitView` functions identically to its current implementation from a user perspective.
32+
- `PreSubmitView` and its sub-widgets do not hold local state for data fetched from the backend.
33+
- Existing tests for `PreSubmitView` pass after the refactor.
34+
- New unit tests for `PresubmitState` cover the migrated logic.
35+
36+
## Out of Scope
37+
- Changing the UI layout or design of `PreSubmitView`.
38+
- Implementing new features or fixing unrelated bugs in `PreSubmitView`.

conductor/tracks.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@
1515
- [x] **Track: Add sha to and show it on presubmit view of dashborad on a header along with PR and author**
1616
*Link: [./archive/presubmit_header_sha_20260217/](./archive/presubmit_header_sha_20260217/)*
1717

18+
---
19+
20+
- [x] **Track: For PreSubmitView move all state change logic to PresubmitState similarly to how BuildDashboardPage use BuildState**
21+
*Link: [./archive/refactor_presubmit_state_20260223/](./archive/refactor_presubmit_state_20260223/)*
22+

dashboard/lib/main.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import 'firebase_options.dart';
1414
import 'service/cocoon.dart';
1515
import 'service/firebase_auth.dart';
1616
import 'state/build.dart';
17+
import 'state/presubmit.dart';
1718
import 'views/build_dashboard_page.dart';
1819
import 'views/presubmit_view.dart';
1920
import 'views/tree_status_page.dart';
@@ -73,6 +74,10 @@ void main([List<String> args = const <String>[]]) async {
7374
authService: authService,
7475
cocoonService: cocoonService,
7576
),
77+
presubmitState: PresubmitState(
78+
authService: authService,
79+
cocoonService: cocoonService,
80+
),
7681
child: Now(child: const MyApp()),
7782
),
7883
);

dashboard/lib/service/dev_cocoon.dart

Lines changed: 131 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -182,46 +182,120 @@ class DevelopmentCocoonService implements CocoonService {
182182
required String repo,
183183
required String sha,
184184
}) async {
185-
// Extract a number from the SHA if it's a mock SHA to provide varied data.
186-
// Format: ..._#_mock_sha
187-
final parts = sha.split('_');
188-
final num = (sha.endsWith('_mock_sha') && parts.length > 2)
189-
? parts[parts.length - 3]
190-
: '1';
191-
final prNum = int.tryParse(num) ?? 123;
192-
193-
return CocoonResponse.data(
194-
PresubmitGuardResponse(
195-
prNum: prNum,
196-
checkRunId: 456,
197-
author: _authors[prNum % _authors.length],
198-
guardStatus: switch (num) {
199-
'1' => GuardStatus.succeeded,
200-
'2' => GuardStatus.failed,
201-
_ => GuardStatus.inProgress,
202-
},
203-
stages: [
204-
PresubmitGuardStage(
205-
name: 'Engine',
206-
createdAt: now.millisecondsSinceEpoch,
207-
builds: {
208-
'Mac mac_host_engine $num': TaskStatus.failed,
209-
'Mac mac_ios_engine $num': TaskStatus.waitingForBackfill,
210-
'Linux linux_android_aot_engine $num': TaskStatus.succeeded,
211-
},
212-
),
213-
PresubmitGuardStage(
214-
name: 'Framework',
215-
createdAt: now.millisecondsSinceEpoch,
216-
builds: {
217-
'Linux framework_tests $num': TaskStatus.inProgress,
218-
'Mac framework_tests $num': TaskStatus.cancelled,
219-
'Linux android framework_tests $num': TaskStatus.skipped,
220-
'Windows framework_tests $num': TaskStatus.infraFailure,
221-
},
222-
),
223-
],
224-
),
185+
if (sha == 'cafe5_1_mock_sha') {
186+
return CocoonResponse.data(
187+
PresubmitGuardResponse(
188+
prNum: 123,
189+
checkRunId: 456,
190+
author: _authors[0],
191+
guardStatus: GuardStatus.inProgress,
192+
stages: [
193+
PresubmitGuardStage(
194+
name: 'Engine',
195+
createdAt: now.millisecondsSinceEpoch,
196+
builds: {
197+
'Mac mac_host_engine': TaskStatus.infraFailure,
198+
'Mac mac_ios_engine': TaskStatus.cancelled,
199+
'Linux linux_android_aot_engine': TaskStatus.infraFailure,
200+
},
201+
),
202+
],
203+
),
204+
);
205+
} else if (sha == 'face5_2_mock_sha') {
206+
return CocoonResponse.data(
207+
PresubmitGuardResponse(
208+
prNum: 123,
209+
checkRunId: 789,
210+
author: _authors[1],
211+
guardStatus: GuardStatus.failed,
212+
stages: [
213+
PresubmitGuardStage(
214+
name: 'Engine',
215+
createdAt: now.millisecondsSinceEpoch,
216+
builds: {
217+
'Mac mac_host_engine': TaskStatus.succeeded,
218+
'Mac mac_ios_engine': TaskStatus.cancelled,
219+
'Linux linux_android_aot_engine': TaskStatus.succeeded,
220+
},
221+
),
222+
PresubmitGuardStage(
223+
name: 'Framework',
224+
createdAt: now.millisecondsSinceEpoch,
225+
builds: {
226+
'Linux framework_tests': TaskStatus.succeeded,
227+
'Mac framework_tests': TaskStatus.failed,
228+
'Linux android framework_tests': TaskStatus.skipped,
229+
'Windows framework_tests': TaskStatus.failed,
230+
},
231+
),
232+
],
233+
),
234+
);
235+
} else if (sha == 'decaf_3_mock_sha') {
236+
return CocoonResponse.data(
237+
PresubmitGuardResponse(
238+
prNum: 123,
239+
checkRunId: 1011,
240+
author: _authors[2],
241+
guardStatus: GuardStatus.failed,
242+
stages: [
243+
PresubmitGuardStage(
244+
name: 'Engine',
245+
createdAt: now.millisecondsSinceEpoch,
246+
builds: {
247+
'Mac mac_host_engine': TaskStatus.succeeded,
248+
'Mac mac_ios_engine': TaskStatus.cancelled,
249+
'Linux linux_android_aot_engine': TaskStatus.succeeded,
250+
},
251+
),
252+
PresubmitGuardStage(
253+
name: 'Framework',
254+
createdAt: now.millisecondsSinceEpoch,
255+
builds: {
256+
'Linux framework_tests': TaskStatus.succeeded,
257+
'Mac framework_tests': TaskStatus.waitingForBackfill,
258+
'Linux android framework_tests': TaskStatus.skipped,
259+
'Windows framework_tests': TaskStatus.inProgress,
260+
},
261+
),
262+
],
263+
),
264+
);
265+
} else if (sha == 'deafcab_mock_sha') {
266+
return CocoonResponse.data(
267+
PresubmitGuardResponse(
268+
prNum: 123,
269+
checkRunId: 369,
270+
author: _authors[3],
271+
guardStatus: GuardStatus.succeeded,
272+
stages: [
273+
PresubmitGuardStage(
274+
name: 'Engine',
275+
createdAt: now.millisecondsSinceEpoch,
276+
builds: {
277+
'Mac mac_host_engine': TaskStatus.succeeded,
278+
'Mac mac_ios_engine': TaskStatus.cancelled,
279+
'Linux linux_android_aot_engine': TaskStatus.succeeded,
280+
},
281+
),
282+
PresubmitGuardStage(
283+
name: 'Framework',
284+
createdAt: now.millisecondsSinceEpoch,
285+
builds: {
286+
'Linux framework_tests': TaskStatus.succeeded,
287+
'Mac framework_tests': TaskStatus.succeeded,
288+
'Linux android framework_tests': TaskStatus.skipped,
289+
'Windows framework_tests': TaskStatus.succeeded,
290+
},
291+
),
292+
],
293+
),
294+
);
295+
}
296+
return CocoonResponse.error(
297+
'No presubmit guard data for sha $sha',
298+
statusCode: 404,
225299
);
226300
}
227301

@@ -237,14 +311,21 @@ class DevelopmentCocoonService implements CocoonService {
237311
buildName: buildName,
238312
creationTime: now.millisecondsSinceEpoch - 10000,
239313
status: 'Succeeded',
314+
buildNumber: 12345,
240315
summary:
241-
'[INFO] Starting task $buildName...\n[SUCCESS] Dependencies installed.\n[INFO] Running build script...\n[SUCCESS] All tests passed (452/452)',
316+
'''
317+
[INFO] Starting task $buildName...
318+
[SUCCESS] Dependencies installed.
319+
[INFO] Running build script...
320+
[SUCCESS] All tests passed (452/452)
321+
''',
242322
),
243323
PresubmitCheckResponse(
244324
attemptNumber: 2,
245325
buildName: buildName,
246326
creationTime: now.millisecondsSinceEpoch,
247327
status: 'Failed',
328+
buildNumber: 67890,
248329
summary:
249330
'[INFO] Starting task $buildName...\n[ERROR] Test failed: Unit Tests',
250331
),
@@ -259,19 +340,24 @@ class DevelopmentCocoonService implements CocoonService {
259340
}) async {
260341
return CocoonResponse.data([
261342
PresubmitGuardSummary(
262-
commitSha: 'decaf_1_mock_sha',
343+
commitSha: 'decaf_3_mock_sha',
263344
creationTime: now.millisecondsSinceEpoch,
264-
guardStatus: GuardStatus.succeeded,
345+
guardStatus: GuardStatus.inProgress,
265346
),
266347
PresubmitGuardSummary(
267348
commitSha: 'face5_2_mock_sha',
268349
creationTime: now.millisecondsSinceEpoch - 100000,
269350
guardStatus: GuardStatus.failed,
270351
),
271352
PresubmitGuardSummary(
272-
commitSha: 'cafe5_3_mock_sha',
353+
commitSha: 'cafe5_1_mock_sha',
273354
creationTime: now.millisecondsSinceEpoch - 200000,
274-
guardStatus: GuardStatus.inProgress,
355+
guardStatus: GuardStatus.failed,
356+
),
357+
PresubmitGuardSummary(
358+
commitSha: 'deafcab_mock_sha',
359+
creationTime: now.millisecondsSinceEpoch - 300000,
360+
guardStatus: GuardStatus.succeeded,
275361
),
276362
]);
277363
}

dashboard/lib/state/build.dart

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -420,22 +420,6 @@ class BuildState extends ChangeNotifier {
420420
return true;
421421
}
422422

423-
/// Gets the presubmit guard summaries for a given [repo] and [pr].
424-
Future<List<PresubmitGuardSummary>?> fetchPresubmitGuardSummaries({
425-
required String repo,
426-
required String pr,
427-
}) async {
428-
final response = await cocoonService.fetchPresubmitGuardSummaries(
429-
repo: repo,
430-
pr: pr,
431-
);
432-
if (response.error != null) {
433-
_errors.send('Failed to fetch guard summaries: ${response.error}');
434-
return null;
435-
}
436-
return response.data;
437-
}
438-
439423
/// Updates the suppression status of a test.
440424
///
441425
/// Returns true if the update was successful.

0 commit comments

Comments
 (0)