This commit is contained in:
2026-08-25 19:07:34 +08:00
parent 65c01f8b3d
commit 7d36759f3f
28 changed files with 613 additions and 16 deletions
+59
View File
@@ -0,0 +1,59 @@
{
"schemaVersion": 1,
"mode": "report-only",
"tools": {
"jacocoMavenPlugin": "0.8.12",
"spotbugsMavenPlugin": "4.9.8.5"
},
"topology": {
"modules": 22,
"codeModules": 21,
"services": 15
},
"openapi": {
"documents": 26,
"coveredServices": 7,
"codeFirstServices": 8
},
"reports": {
"jacocoPresent": 21,
"spotbugsPresent": 21,
"spotbugsFindings": 780,
"spotbugsByPriority": {
"1": 1,
"2": 779
},
"spotbugsByCategory": {
"BAD_PRACTICE": 10,
"CORRECTNESS": 3,
"EXPERIMENTAL": 4,
"MALICIOUS_CODE": 699,
"MT_CORRECTNESS": 2,
"PERFORMANCE": 18,
"STYLE": 44
}
},
"modules": [
{ "module": "common-core", "jacocoCovered": 32, "jacocoTotal": 78, "jacocoPercentage": 41.03, "spotbugsFindings": 6 },
{ "module": "common-web", "jacocoCovered": 164, "jacocoTotal": 188, "jacocoPercentage": 87.23, "spotbugsFindings": 1 },
{ "module": "common-security", "jacocoCovered": 109, "jacocoTotal": 202, "jacocoPercentage": 53.96, "spotbugsFindings": 6 },
{ "module": "common-openapi", "jacocoCovered": 17, "jacocoTotal": 37, "jacocoPercentage": 45.95, "spotbugsFindings": 0 },
{ "module": "common-audit", "jacocoCovered": 168, "jacocoTotal": 244, "jacocoPercentage": 68.85, "spotbugsFindings": 8 },
{ "module": "common-event-contract", "jacocoCovered": 146, "jacocoTotal": 164, "jacocoPercentage": 89.02, "spotbugsFindings": 18 },
{ "module": "gateway", "jacocoCovered": 110, "jacocoTotal": 156, "jacocoPercentage": 70.51, "spotbugsFindings": 4 },
{ "module": "gateway-overseas", "jacocoCovered": 134, "jacocoTotal": 272, "jacocoPercentage": 49.26, "spotbugsFindings": 2 },
{ "module": "auth", "jacocoCovered": 372, "jacocoTotal": 619, "jacocoPercentage": 60.10, "spotbugsFindings": 5 },
{ "module": "iam", "jacocoCovered": 1872, "jacocoTotal": 3032, "jacocoPercentage": 61.74, "spotbugsFindings": 60 },
{ "module": "order", "jacocoCovered": 1116, "jacocoTotal": 1605, "jacocoPercentage": 69.53, "spotbugsFindings": 47 },
{ "module": "firstleg", "jacocoCovered": 7891, "jacocoTotal": 11592, "jacocoPercentage": 68.07, "spotbugsFindings": 223 },
{ "module": "warehouse", "jacocoCovered": 1767, "jacocoTotal": 2922, "jacocoPercentage": 60.47, "spotbugsFindings": 64 },
{ "module": "warehouse-overseas-service", "jacocoCovered": 403, "jacocoTotal": 778, "jacocoPercentage": 51.80, "spotbugsFindings": 8 },
{ "module": "lastleg-service", "jacocoCovered": 5088, "jacocoTotal": 7832, "jacocoPercentage": 64.96, "spotbugsFindings": 162 },
{ "module": "file", "jacocoCovered": 1046, "jacocoTotal": 1614, "jacocoPercentage": 64.81, "spotbugsFindings": 33 },
{ "module": "print", "jacocoCovered": 596, "jacocoTotal": 695, "jacocoPercentage": 85.76, "spotbugsFindings": 12 },
{ "module": "audit-service", "jacocoCovered": 76, "jacocoTotal": 153, "jacocoPercentage": 49.67, "spotbugsFindings": 0 },
{ "module": "finance", "jacocoCovered": 1665, "jacocoTotal": 2236, "jacocoPercentage": 74.46, "spotbugsFindings": 97 },
{ "module": "integration-service", "jacocoCovered": 1040, "jacocoTotal": 1420, "jacocoPercentage": 73.24, "spotbugsFindings": 23 },
{ "module": "event-bridge-service", "jacocoCovered": 318, "jacocoTotal": 419, "jacocoPercentage": 75.89, "spotbugsFindings": 1 }
]
}
+1 -1
View File
@@ -5,7 +5,7 @@ import { fileURLToPath, pathToFileURL } from 'node:url'
export const repositoryRoot = path.resolve(fileURLToPath(new URL('..', import.meta.url)))
const normalize = (value) => value.replaceAll('\\', '/')
const attribute = (source, name) => source.match(new RegExp(`\\b${name}="([^"]*)"`))?.[1]
const attribute = (source, name) => source.match(new RegExp(`\\b${name}=(?:"([^"]*)"|'([^']*)')`))?.slice(1).find((value) => value !== undefined)
async function exists(file) {
try {
+10
View File
@@ -21,6 +21,11 @@ test('parses JaCoCo line coverage and SpotBugs findings without quality threshol
byPriority: { 1: 1, 2: 1 },
byCategory: { CORRECTNESS: 1, STYLE: 1 }
})
assert.deepEqual(parseSpotbugsReport("<BugCollection><BugInstance priority='2' category='MALICIOUS_CODE'/></BugCollection>"), {
findings: 1,
byPriority: { 2: 1 },
byCategory: { MALICIOUS_CODE: 1 }
})
assert.throws(() => parseJacocoReport('<report/>'), /not a JaCoCo report/)
assert.throws(() => parseSpotbugsReport('<BugCollection/>'), /not a SpotBugs report/)
})
@@ -58,10 +63,15 @@ test('aggregates code modules, report presence and the OpenAPI service matrix',
test('repository freezes the current topology and non-blocking aggregate summary wiring', async () => {
const summary = await buildQualitySummary(repositoryRoot)
const baseline = JSON.parse(await readFile(path.join(repositoryRoot, 'scripts', 'java-quality-baseline.json'), 'utf8'))
assert.deepEqual(summary.topology, { modules: 22, codeModules: 21, services: 15 })
assert.equal(summary.openapi.documents, 26)
assert.equal(summary.openapi.coveredServices.length, 7)
assert.equal(summary.openapi.codeFirstServices.length, 8)
assert.equal(baseline.mode, 'report-only')
assert.deepEqual(baseline.topology, summary.topology)
assert.equal(baseline.modules.length, 21)
assert.equal(baseline.modules.reduce((total, row) => total + row.spotbugsFindings, 0), baseline.reports.spotbugsFindings)
const gitlab = (await readFile(path.join(repositoryRoot, '.gitlab-ci.yml'), 'utf8')).replaceAll('\r\n', '\n')
const job = gitlab.match(/^质量摘要:\n([\s\S]*?)(?=^[^\s#].*:\n)/m)?.[1] ?? ''
+2 -1
View File
@@ -64,7 +64,8 @@ export const SYNCHRONOUS_CLIENTS = Object.freeze([
feign('firstleg/src/main/java/com/baiyue/firstleg/client/MeasurementImageClient.java',
'firstleg-service', 'file-service', ['REQUEST'], 'READ_WRITE', 'MIXED', '图片上传/作废非安全重放,查询可重复'),
feign('firstleg/src/main/java/com/baiyue/firstleg/client/OrderCargoClient.java',
'firstleg-service', 'order-service', ['REQUEST'], 'READ', 'SAFE_READ', '读取订单货物/来源快照'),
'firstleg-service', 'order-service', ['REQUEST', 'BACKGROUND'], 'READ', 'SAFE_READ',
'在线测量/箱号/排柜读取;Order 审核 Outbox 创建 Firstleg 入库及箱号时也会后台回读订单货物'),
feign('firstleg/src/main/java/com/baiyue/firstleg/client/OrderFulfillmentSplitClient.java',
'firstleg-service', 'order-service', ['REQUEST'], 'WRITE', 'IDEMPOTENCY_KEY', 'PDA 结算拆单携带 idempotencyKey/operationId'),
feign('firstleg/src/main/java/com/baiyue/firstleg/client/PriceBookFileClient.java',
@@ -54,6 +54,7 @@ const expectedBackgroundEdges = [
'firstleg-service->event-bridge-service',
'firstleg-service->finance-service',
'firstleg-service->integration-service',
'firstleg-service->order-service',
'iam-service->event-bridge-service',
'iam-service->firstleg-service',
'lastleg-service->event-bridge-service',
@@ -190,7 +191,7 @@ test('REQUEST, BACKGROUND and full graphs remain separate executable baselines',
['firstleg-service', 'order-service']
])
assert.deepEqual(stronglyConnectedComponents(graphEdges('BACKGROUND')), [[
'event-bridge-service', 'finance-service', 'firstleg-service', 'lastleg-service'
'event-bridge-service', 'finance-service', 'firstleg-service', 'lastleg-service', 'order-service'
]])
assert.deepEqual(stronglyConnectedComponents(graphEdges('ALL')), [[
'auth-service', 'event-bridge-service', 'file-service', 'finance-service',
@@ -204,6 +205,25 @@ test('overseas security projection stays in Lastleg infrastructure and backgroun
assert.ok(graphEdges('BACKGROUND').includes('event-bridge-service->lastleg-service'))
})
test('Order and Firstleg remain a bilateral REQUEST SCC until loading-complete timing is frozen', () => {
const requestClients = SYNCHRONOUS_CLIENTS.filter(client => client.contexts.includes('REQUEST'))
const orderToFirstleg = requestClients.filter(client =>
client.source === 'order-service' && client.target === 'firstleg-service')
const firstlegToOrder = requestClients.filter(client =>
client.source === 'firstleg-service' && client.target === 'order-service')
assert.deepEqual(orderToFirstleg.map(client => client.path).sort(), [
'order/src/main/java/com/baiyue/order/client/FirstlegInboundClient.java',
'order/src/main/java/com/baiyue/order/client/FirstlegPricingClient.java',
'order/src/main/java/com/baiyue/order/client/FirstlegUnifiedOrderClient.java'
])
assert.deepEqual(firstlegToOrder.map(client => client.path).sort(), [
'firstleg/src/main/java/com/baiyue/firstleg/client/OrderCargoClient.java',
'firstleg/src/main/java/com/baiyue/firstleg/client/OrderFulfillmentSplitClient.java'
])
assert.ok(stronglyConnectedComponents(graphEdges('REQUEST')).some(component =>
component.includes('firstleg-service') && component.includes('order-service')))
})
test('known user entries expose every longest simple REQUEST path over the two-hop budget', () => {
const summary = Object.fromEntries(USER_ENTRIES.map(entry => {
const paths = longestSimplePaths(entry.service)