@@ -4,7 +4,7 @@ import debugLib from 'debug'
4
4
import { isEqual } from 'lodash'
5
5
6
6
import type { DataContext } from '../DataContext'
7
- import type { CloudSpecStatus , Query , RelevantRun , CurrentProjectRelevantRunSpecs , CloudSpecRun , CloudRun } from '../gen/graphcache-config.gen'
7
+ import type { Query , RelevantRun , CurrentProjectRelevantRunSpecs , CloudRun } from '../gen/graphcache-config.gen'
8
8
import { Poller } from '../polling'
9
9
import type { CloudRunStatus } from '@packages/graphql/src/gen/cloud-source-types.gen'
10
10
@@ -15,6 +15,8 @@ const RELEVANT_RUN_SPEC_OPERATION_DOC = gql`
15
15
id
16
16
runNumber
17
17
status
18
+ completedInstanceCount
19
+ totalInstanceCount
18
20
specs {
19
21
id
20
22
status
@@ -55,8 +57,6 @@ export const SPECS_EMPTY_RETURN: RunSpecReturn = {
55
57
statuses : { } ,
56
58
}
57
59
58
- const INCOMPLETE_STATUSES : CloudSpecStatus [ ] = [ 'RUNNING' , 'UNCLAIMED' ]
59
-
60
60
export type RunSpecReturn = {
61
61
runSpecs : CurrentProjectRelevantRunSpecs
62
62
statuses : {
@@ -86,23 +86,9 @@ export class RelevantRunSpecsDataSource {
86
86
return this . #cached. runSpecs
87
87
}
88
88
89
- #calculateSpecMetadata ( specs : CloudSpecRun [ ] ) {
90
- //mimic logic in Cloud to sum up the count of groups per spec to give the total spec counts
91
- const countGroupsForSpec = ( specs : CloudSpecRun [ ] ) => {
92
- return specs . map ( ( spec ) => spec . groupIds ?. length || 0 ) . reduce ( ( acc , curr ) => acc += curr , 0 )
93
- }
94
-
95
- return {
96
- totalSpecs : countGroupsForSpec ( specs ) ,
97
- completedSpecs : countGroupsForSpec ( specs . filter ( ( spec ) => ! INCOMPLETE_STATUSES . includes ( spec . status || 'UNCLAIMED' ) ) ) ,
98
- }
99
- }
100
-
101
89
/**
102
- * Pulls runs from the current Cypress Cloud account and determines which runs are considered:
103
- * - "current" the most recent completed run, or if not found, the most recent running run
104
- * - "next" the most recent running run if a completed run is found
105
- * @param shas list of Git commit shas to query the Cloud with for matching runs
90
+ * Pulls the specs that match the relevant run.
91
+ * @param runs - the current and (optionally) next relevant run
106
92
*/
107
93
async getRelevantRunSpecs ( runs : RelevantRun ) : Promise < RunSpecReturn > {
108
94
const projectSlug = await this . ctx . project . projectId ( )
@@ -147,28 +133,40 @@ export class RelevantRunSpecsDataSource {
147
133
}
148
134
}
149
135
136
+ function isValidNumber ( value : unknown ) : value is number {
137
+ return Number . isFinite ( value )
138
+ }
139
+
150
140
if ( cloudProject ?. __typename === 'CloudProject' ) {
151
141
const runSpecsToReturn : RunSpecReturn = {
152
142
runSpecs : { } ,
153
143
statuses : { } ,
154
144
}
155
145
156
- if ( cloudProject . current && cloudProject . current . runNumber && cloudProject . current . status ) {
157
- runSpecsToReturn . runSpecs . current = {
158
- ...this . #calculateSpecMetadata( cloudProject . current . specs || [ ] ) ,
159
- runNumber : cloudProject . current . runNumber ,
146
+ const { current, next } = cloudProject
147
+
148
+ const formatCloudRunInfo = ( cloudRunDetails : Partial < CloudRun > ) => {
149
+ const { runNumber, totalInstanceCount, completedInstanceCount } = cloudRunDetails
150
+
151
+ if ( runNumber && isValidNumber ( totalInstanceCount ) && isValidNumber ( completedInstanceCount ) ) {
152
+ return {
153
+ totalSpecs : totalInstanceCount ,
154
+ completedSpecs : completedInstanceCount ,
155
+ runNumber,
156
+ }
160
157
}
161
158
162
- runSpecsToReturn . statuses . current = cloudProject . current . status
159
+ return undefined
163
160
}
164
161
165
- if ( cloudProject . next && cloudProject . next . runNumber && cloudProject . next . status ) {
166
- runSpecsToReturn . runSpecs . next = {
167
- ...this . #calculateSpecMetadata( cloudProject . next . specs || [ ] ) ,
168
- runNumber : cloudProject . next . runNumber ,
169
- }
162
+ if ( current && current . status ) {
163
+ runSpecsToReturn . runSpecs . current = formatCloudRunInfo ( current )
164
+ runSpecsToReturn . statuses . current = current . status
165
+ }
170
166
171
- runSpecsToReturn . statuses . next = cloudProject . next . status
167
+ if ( next && next . status ) {
168
+ runSpecsToReturn . runSpecs . next = formatCloudRunInfo ( next )
169
+ runSpecsToReturn . statuses . next = next . status
172
170
}
173
171
174
172
return runSpecsToReturn
@@ -193,6 +191,7 @@ export class RelevantRunSpecsDataSource {
193
191
194
192
debug ( `Spec data is ` , specs )
195
193
194
+ const wasWatchingCurrentProject = this . #cached. statuses . current === 'RUNNING'
196
195
const specCountsChanged = ! isEqual ( specs . runSpecs , this . #cached. runSpecs )
197
196
const statusesChanged = ! isEqual ( specs . statuses , this . #cached. statuses )
198
197
@@ -208,7 +207,7 @@ export class RelevantRunSpecsDataSource {
208
207
debug ( 'Run statuses changed' )
209
208
const projectSlug = await this . ctx . project . projectId ( )
210
209
211
- if ( projectSlug ) {
210
+ if ( projectSlug && wasWatchingCurrentProject ) {
212
211
debug ( `Invalidate cloudProjectBySlug ${ projectSlug } ` )
213
212
await this . ctx . cloud . invalidate ( 'Query' , 'cloudProjectBySlug' , { slug : projectSlug } )
214
213
}
0 commit comments