Skip to content

Commit 73d7cb4

Browse files
authored
validate-pr: report diff instead of current status (#4642)
* validate-pr: report diff instead of current status * Introduce a few errors on purpose * Revert "Introduce a few errors on purpose" This reverts commit 3e5d7e1.
1 parent 4ecbec7 commit 73d7cb4

File tree

1 file changed

+70
-28
lines changed

1 file changed

+70
-28
lines changed

.github/validate-pr/index.js

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import * as core from '@actions/core'
2727
import { copyFile } from 'fs/promises'
2828
import * as github from '@actions/github'
2929
import specification from '../../output/schema/schema.json' with { type: 'json' }
30+
import baselineValidation from '../../../clients-flight-recorder/recordings/types-validation/types-validation.json' with { type: 'json' }
3031
import { run as getReport } from '../../../clients-flight-recorder/scripts/types-validator/index.js'
3132
import {
3233
getNamespace,
@@ -81,7 +82,7 @@ async function run() {
8182
const specFiles = files.filter(
8283
(file) => file.includes('specification') && !file.includes('compiler/test')
8384
)
84-
const table = []
85+
const reports = new Map()
8586

8687
cd(tsValidationPath)
8788

@@ -109,37 +110,47 @@ async function run() {
109110
ci: false,
110111
verbose: false
111112
})
112-
table.push(buildTableLine(api, report))
113+
const [namespace, _method] = api.split('.')
114+
// Asked to validate a specific API, so we only store that one
115+
reports.set(api, report.get(namespace)[0])
113116
}
114117
} else {
118+
const api = getApi(file)
115119
const report = await getReport({
116-
api: getApi(file),
120+
api,
117121
'generate-report': false,
118122
request: true,
119123
response: true,
120124
ci: false,
121125
verbose: false
122126
})
123-
table.push(buildTableLine(getApi(file), report))
127+
128+
const [namespace, _method] = api.split('.')
129+
// Asked to validate a specific API, so we only store that one
130+
reports.set(api, report.get(namespace)[0])
124131
}
125132
}
126133

127134
cd(path.join(__dirname, '..', '..'))
128135

129-
table.sort((a, b) => {
130-
if (a < b) return -1
131-
if (a > b) return 1
132-
return 0
133-
})
136+
// Compare current reports with baseline and find changes
137+
const changedApis = []
138+
for (const [apiName, report] of reports) {
139+
const baselineReport = findBaselineReport(apiName, baselineValidation)
140+
if (baselineReport && hasChanges(baselineReport, report, apiName)) {
141+
changedApis.push({ api: apiName, baseline: baselineReport, current: report })
142+
}
143+
}
144+
changedApis.sort((a, b) => a.api.localeCompare(b.api))
134145

135-
if (table.length > 0) {
136-
let comment = `Following you can find the validation results for the API${table.length === 1 ? '' : 's'} you have changed.\n\n`
146+
if (changedApis.length > 0) {
147+
let comment = `Following you can find the validation changes for the API${changedApis.length === 1 ? '' : 's'} you have modified.\n\n`
137148
comment += '| API | Status | Request | Response |\n'
138149
comment += '| --- | --- | --- | --- |\n'
139-
for (const line of [...new Set(table)]) {
140-
comment += line
150+
for (const change of changedApis) {
151+
comment += buildDiffTableLine(change)
141152
}
142-
comment += `\nYou can validate ${table.length === 1 ? 'this' : 'these'} API${table.length === 1 ? '' : 's'} yourself by using the ${tick}make validate${tick} target.\n`
153+
comment += `\nYou can validate ${changedApis.length === 1 ? 'this' : 'these'} API${changedApis.length === 1 ? '' : 's'} yourself by using the ${tick}make validate${tick} target.\n`
143154

144155
core.setOutput('has_results', 'true')
145156
core.setOutput('comment_body', comment)
@@ -154,39 +165,70 @@ function getApi (file) {
154165
return file.split('/').slice(1, 3).filter(s => !privateNames.includes(s)).filter(Boolean).join('.')
155166
}
156167

157-
function buildTableLine (api, report) {
158-
const apiReport = report.get(getNamespace(api)).find(r => r.api === getName(api))
159-
return `| ${tick}${api}${tick} | ${generateStatus(apiReport)} | ${generateRequest(apiReport)} | ${generateResponse(apiReport)} |\n`
168+
169+
function findBaselineReport(apiName, baselineValidation) {
170+
const [namespace, method] = apiName.split('.')
171+
172+
if (!baselineValidation.namespaces[namespace]) {
173+
return null
174+
}
175+
176+
return baselineValidation.namespaces[namespace].apis.find(api => api.api === method)
160177
}
161178

162-
function generateStatus (report) {
163-
if (!report.diagnostics.hasRequestType || !report.diagnostics.hasResponseType) {
179+
function hasChanges(baselineReport, report) {
180+
if (!report) return false
181+
182+
return baselineReport.status !== report.status ||
183+
baselineReport.passingRequest !== report.passingRequest ||
184+
baselineReport.passingResponse !== report.passingResponse
185+
}
186+
187+
function buildDiffTableLine(change) {
188+
const { api, baseline, current } = change
189+
190+
const status = generateStatus(current.status)
191+
const request = generateRequest(current)
192+
const response = generateResponse(current)
193+
194+
const baselineStatus = generateStatus(baseline.status)
195+
const baselineRequest = generateRequest(baseline)
196+
const baselineResponse = generateResponse(baseline)
197+
198+
const statusDiff = status !== baselineStatus ? `${baselineStatus}${status}` : status
199+
const requestDiff = request !== baselineRequest ? `${baselineRequest}${request}` : request
200+
const responseDiff = response !== baselineResponse ? `${baselineResponse}${response}` : response
201+
202+
return `| ${tick}${api}${tick} | ${statusDiff} | ${requestDiff} | ${responseDiff} |\n`
203+
}
204+
205+
206+
function generateStatus (status) {
207+
if (status === 'missing_types' || status === 'missing_request_type' || status === 'missing_response_type') {
164208
return ':orange_circle:'
165209
}
166-
if (report.totalRequest <= 0 || report.totalResponse <= 0) {
210+
if (status === 'missing_test') {
167211
return ':white_circle:'
168212
}
169-
if (report.diagnostics.request.length === 0 && report.diagnostics.response.length === 0) {
213+
if (status === 'passing') {
170214
return ':green_circle:'
171215
}
172216
return ':red_circle:'
173217
}
174218

175219
function generateRequest (r) {
176-
if (r.totalRequest === -1) return 'Missing recording'
177-
if (!r.diagnostics.hasRequestType) return 'Missing type'
178-
if (r.totalRequest === 0) return 'Missing test'
220+
if (r.status === 'missing_test') return 'Missing test'
221+
if (r.status === 'missing_types' || r.status == 'missing_request_type') return 'Missing type'
179222
return `${r.passingRequest}/${r.totalRequest}`
180223
}
181224

182225
function generateResponse (r) {
183-
if (r.totalResponse === -1) return 'Missing recording'
184-
if (!r.diagnostics.hasResponseType) return 'Missing type'
185-
if (r.totalResponse === 0) return 'Missing test'
226+
if (r.status === 'missing_test') return 'Missing test'
227+
if (r.status === 'missing_types' || r.status == 'missing_response_type') return 'Missing type'
186228
return `${r.passingResponse}/${r.totalResponse}`
187229
}
188230

189231
run().catch((err) => {
190232
core.error(err)
191233
process.exit(1)
192-
})
234+
})

0 commit comments

Comments
 (0)