Skip to content

Commit b9a228d

Browse files
authored
Lookup for sha in presubmit_guards if it is not found in ciStaging (#5013)
Lookup for sha in `presubmit_guards` if it is not found in `ciStaging` in `GetEngineArtifactsReady` api. Fix: flutter/flutter#184530
1 parent fe79f83 commit b9a228d

2 files changed

Lines changed: 137 additions & 7 deletions

File tree

app_dart/lib/src/request_handlers/get_engine_artifacts_ready.dart

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import '../../cocoon_service.dart';
88
import '../model/firestore/ci_staging.dart';
99
import '../request_handling/exceptions.dart';
1010
import '../request_handling/public_api_request_handler.dart';
11+
import '../service/firestore/unified_check_run.dart';
1112

1213
/// Query if engine artifacts are ready for a given commit SHA.
1314
///
@@ -40,28 +41,55 @@ final class GetEngineArtifactsReady extends PublicApiRequestHandler {
4041
throw const BadRequestException('Missing query parameter: "$_paramSha"');
4142
}
4243

43-
final CiStaging ciStaging;
44+
var failed = 0;
45+
var remaining = 0;
46+
var found = false;
4447
try {
45-
ciStaging = await CiStaging.fromFirestore(
48+
final ciStaging = await CiStaging.fromFirestore(
4649
firestoreService: _firestore,
4750
documentName: CiStaging.documentNameFor(
4851
slug: Config.flutterSlug,
4952
sha: commitSha,
5053
stage: CiStage.fusionEngineBuild,
5154
),
5255
);
56+
failed = ciStaging.failed;
57+
remaining = ciStaging.remaining;
58+
found = true;
5359
} on DetailedApiRequestError catch (e) {
54-
if (e.status == HttpStatus.notFound) {
55-
throw NotFoundException('No engine SHA found for "$commitSha"');
60+
if (e.status != HttpStatus.notFound) {
61+
rethrow;
5662
}
57-
rethrow;
63+
}
64+
// if not found in ciStaging document, check if there are any
65+
// presubmit guards for this sha. This is needed for unified check-run flow.
66+
if (!found) {
67+
final guards = await UnifiedCheckRun.getPresubmitGuardsForCommitSha(
68+
firestoreService: _firestore,
69+
slug: Config.flutterSlug,
70+
commitSha: commitSha,
71+
);
72+
if (guards.isNotEmpty) {
73+
found = true;
74+
// If Guard exists for `fusion` only consider that stage is successful
75+
// since empty guard is not stored for `engine` like it is in ciStaging.
76+
final engineGuard = guards
77+
.where((g) => g.stage == CiStage.fusionEngineBuild)
78+
.firstOrNull;
79+
remaining = engineGuard?.remainingJobs ?? 0;
80+
failed = engineGuard?.failedJobs ?? 0;
81+
}
82+
}
83+
84+
if (!found) {
85+
throw NotFoundException('No engine SHA found for "$commitSha"');
5886
}
5987

60-
if (ciStaging.failed > 0) {
88+
if (failed > 0) {
6189
return Response.json(_GetEngineArtifactsResponse.failed);
6290
}
6391

64-
if (ciStaging.remaining > 0) {
92+
if (remaining > 0) {
6593
return Response.json(_GetEngineArtifactsResponse.pending);
6694
}
6795

app_dart/test/request_handlers/get_engine_artifacts_ready_test.dart

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,106 @@ void main() {
131131
await expectLater(tester.get(handler), completes);
132132
await expectLater(decodeHandlerBody(), completion({'status': 'failed'}));
133133
});
134+
135+
group('when not found in ciStaging, checks presubmit guards', () {
136+
test(
137+
'returns "complete" when guard for fusionEngineBuild is successful',
138+
() async {
139+
tester.request.uri = tester.request.uri.replace(
140+
queryParameters: {'sha': 'abc123'},
141+
);
142+
143+
final guard = generatePresubmitGuard(
144+
slug: Config.flutterSlug,
145+
headSha: 'abc123',
146+
stage: CiStage.fusionEngineBuild,
147+
remainingJobs: 0,
148+
failedJobs: 0,
149+
);
150+
151+
firestore.putDocuments([guard]);
152+
153+
await expectLater(tester.get(handler), completes);
154+
await expectLater(
155+
decodeHandlerBody(),
156+
completion({'status': 'complete'}),
157+
);
158+
},
159+
);
160+
161+
test(
162+
'returns "pending" when guard for fusionEngineBuild is pending',
163+
() async {
164+
tester.request.uri = tester.request.uri.replace(
165+
queryParameters: {'sha': 'abc123'},
166+
);
167+
168+
final guard = generatePresubmitGuard(
169+
slug: Config.flutterSlug,
170+
headSha: 'abc123',
171+
stage: CiStage.fusionEngineBuild,
172+
remainingJobs: 1,
173+
failedJobs: 0,
174+
);
175+
176+
firestore.putDocuments([guard]);
177+
178+
await expectLater(tester.get(handler), completes);
179+
await expectLater(
180+
decodeHandlerBody(),
181+
completion({'status': 'pending'}),
182+
);
183+
},
184+
);
185+
186+
test(
187+
'returns "failed" when guard for fusionEngineBuild is failed',
188+
() async {
189+
tester.request.uri = tester.request.uri.replace(
190+
queryParameters: {'sha': 'abc123'},
191+
);
192+
193+
final guard = generatePresubmitGuard(
194+
slug: Config.flutterSlug,
195+
headSha: 'abc123',
196+
stage: CiStage.fusionEngineBuild,
197+
remainingJobs: 0,
198+
failedJobs: 1,
199+
);
200+
201+
firestore.putDocuments([guard]);
202+
203+
await expectLater(tester.get(handler), completes);
204+
await expectLater(
205+
decodeHandlerBody(),
206+
completion({'status': 'failed'}),
207+
);
208+
},
209+
);
210+
211+
test(
212+
'returns "complete" when guards exist but none for fusionEngineBuild',
213+
() async {
214+
tester.request.uri = tester.request.uri.replace(
215+
queryParameters: {'sha': 'abc123'},
216+
);
217+
218+
final guard = generatePresubmitGuard(
219+
slug: Config.flutterSlug,
220+
headSha: 'abc123',
221+
stage: CiStage.fusionTests,
222+
remainingJobs: 1,
223+
failedJobs: 0,
224+
);
225+
226+
firestore.putDocuments([guard]);
227+
228+
await expectLater(tester.get(handler), completes);
229+
await expectLater(
230+
decodeHandlerBody(),
231+
completion({'status': 'complete'}),
232+
);
233+
},
234+
);
235+
});
134236
}

0 commit comments

Comments
 (0)