Skip to content

Commit dedb570

Browse files
authored
Merge branch 'main' into bugfix/gh-noreply-merge-suggestions
2 parents 97e8688 + 0af8dc1 commit dedb570

9 files changed

Lines changed: 106 additions & 247 deletions

File tree

backend/src/api/public/v1/members/identities/createMemberIdentity.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,11 +72,19 @@ export async function createMemberIdentity(req: Request, res: Response): Promise
7272
error.constraint ?? error.original?.constraint ?? error.parent?.constraint
7373

7474
if (constraint === 'uix_memberIdentities_memberId_platform_value_type') {
75-
throw new ConflictError('Identity already exists on this member')
75+
throw new ConflictError('Identity already exists on this member', {
76+
platform: data.platform,
77+
value: data.value,
78+
type: data.type,
79+
})
7680
}
7781

7882
if (constraint === 'uix_memberIdentities_platform_value_type_verified') {
79-
throw new ConflictError('Identity already verified on another member')
83+
throw new ConflictError('Identity already verified on another member', {
84+
platform: data.platform,
85+
value: data.value,
86+
type: data.type,
87+
})
8088
}
8189

8290
throw error

backend/src/api/public/v1/members/identities/verifyMemberIdentity.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,11 @@ export async function verifyMemberIdentity(req: Request, res: Response): Promise
9696
error.constraint ?? error.original?.constraint ?? error.parent?.constraint
9797

9898
if (verified && constraint === 'uix_memberIdentities_platform_value_type_verified') {
99-
throw new ConflictError('Identity already verified on another member')
99+
throw new ConflictError('Identity already verified on another member', {
100+
platform: identity.platform,
101+
value: identity.value,
102+
type: identity.type,
103+
})
100104
}
101105

102106
throw error

services/apps/automatic_projects_discovery_worker/src/activities/activities.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ export async function listSources(): Promise<string[]> {
1919

2020
export async function listDatasets(sourceName: string): Promise<IDatasetDescriptor[]> {
2121
const source = getSource(sourceName)
22+
23+
log.info({ sourceName }, 'Listing datasets.')
24+
2225
const datasets = await source.listAvailableDatasets()
2326

2427
log.info({ sourceName, count: datasets.length, newest: datasets[0]?.id }, 'Datasets listed.')
@@ -36,7 +39,9 @@ export async function processDataset(
3639
log.info({ sourceName, datasetId: dataset.id, url: dataset.url }, 'Processing dataset...')
3740

3841
const source = getSource(sourceName)
42+
log.info({ sourceName, datasetId: dataset.id }, 'Opening dataset stream...')
3943
const stream = await source.fetchDatasetStream(dataset)
44+
log.info({ sourceName, datasetId: dataset.id }, 'Dataset stream opened.')
4045

4146
// For CSV sources: pipe through csv-parse to get Record<string, string> objects.
4247
// For JSON sources: the stream already emits pre-parsed objects in object mode.
@@ -103,6 +108,10 @@ export async function processDataset(
103108
// Flush remaining rows that didn't fill a complete batch
104109
if (batch.length > 0) {
105110
batchNumber++
111+
log.info(
112+
{ sourceName, datasetId: dataset.id, batchSize: batch.length },
113+
'Flushing final batch...',
114+
)
106115
await bulkUpsertProjectCatalog(qx, batch)
107116
totalProcessed += batch.length
108117
}

services/apps/automatic_projects_discovery_worker/src/sources/lf-criticality-score/source.ts

Lines changed: 63 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ import { IDatasetDescriptor, IDiscoverySource, IDiscoverySourceRow } from '../ty
88

99
const log = getServiceLogger()
1010

11-
const DEFAULT_API_URL = 'https://lf-criticality-score-api.example.com'
11+
const DEFAULT_API_HOST = 'lf-criticality-score-api.example.com'
12+
const DEFAULT_API_PORT = 443
1213
const PAGE_SIZE = 100
1314

1415
interface LfApiResponse {
@@ -20,30 +21,39 @@ interface LfApiResponse {
2021
}
2122

2223
interface LfApiRow {
23-
runDate: string
24-
repoUrl: string
24+
rundate: string
25+
repourl: string
2526
owner: string
26-
repoName: string
27+
reponame: string
2728
contributors: number
2829
organizations: number
29-
sizeSloc: number
30-
lastUpdated: number
30+
sizesloc: number
31+
lastupdated: number
3132
age: number
32-
commitFreq: number
33+
commitfreq: number
3334
score: number
3435
}
3536

3637
function getApiBaseUrl(): string {
37-
return (process.env.LF_CRITICALITY_SCORE_API_URL ?? DEFAULT_API_URL).replace(/\/$/, '')
38+
if (process.env.LF_CRITICALITY_SCORE_API_URL) {
39+
return process.env.LF_CRITICALITY_SCORE_API_URL.replace(/\/$/, '')
40+
}
41+
const host = (process.env.LF_CRITICALITY_SCORE_API_HOST ?? DEFAULT_API_HOST)
42+
.trim()
43+
.replace(/\/$/, '')
44+
const port = parseInt(process.env.LF_CRITICALITY_SCORE_API_PORT ?? String(DEFAULT_API_PORT), 10)
45+
const scheme = port === 443 ? 'https' : 'http'
46+
return `${scheme}://${host}:${port}`
3847
}
3948

4049
async function fetchPage(
4150
baseUrl: string,
42-
startDate: string,
43-
endDate: string,
4451
page: number,
52+
scoredAfter?: string,
4553
): Promise<LfApiResponse> {
46-
const url = `${baseUrl}/projects/scores?startDate=${startDate}&endDate=${endDate}&page=${page}&pageSize=${PAGE_SIZE}`
54+
const params = new URLSearchParams({ page: String(page), pageSize: String(PAGE_SIZE) })
55+
if (scoredAfter) params.set('scoredAfter', scoredAfter)
56+
const url = `${baseUrl}/projects?${params.toString()}`
4757

4858
return new Promise((resolve, reject) => {
4959
const client = url.startsWith('https://') ? https : http
@@ -72,88 +82,81 @@ async function fetchPage(
7282
})
7383
}
7484

75-
/**
76-
* Generates the first day and last day of a given month.
77-
* monthOffset = 0 → current month, -1 → previous month, etc.
78-
*/
79-
function monthRange(monthOffset: number): { startDate: string; endDate: string } {
80-
const now = new Date()
81-
const year = now.getUTCFullYear()
82-
const month = now.getUTCMonth() + monthOffset // can be negative; Date handles rollover
83-
84-
const first = new Date(Date.UTC(year, month, 1))
85-
const last = new Date(Date.UTC(year, month + 1, 0)) // last day of month
86-
87-
const pad = (n: number) => String(n).padStart(2, '0')
88-
const fmt = (d: Date) =>
89-
`${d.getUTCFullYear()}-${pad(d.getUTCMonth() + 1)}-${pad(d.getUTCDate())}`
90-
91-
return { startDate: fmt(first), endDate: fmt(last) }
92-
}
93-
9485
export class LfCriticalityScoreSource implements IDiscoverySource {
9586
public readonly name = 'lf-criticality-score'
9687
public readonly format = 'json' as const
9788

98-
async listAvailableDatasets(): Promise<IDatasetDescriptor[]> {
89+
async listAvailableDatasets(options?: { scoredAfter?: string }): Promise<IDatasetDescriptor[]> {
9990
const baseUrl = getApiBaseUrl()
100-
101-
// Return one dataset per month for the last 12 months (newest first)
102-
const datasets: IDatasetDescriptor[] = []
103-
104-
for (let offset = 0; offset >= -11; offset--) {
105-
const { startDate, endDate } = monthRange(offset)
106-
const id = startDate.slice(0, 7) // e.g. "2026-02"
107-
108-
datasets.push({
109-
id,
110-
date: startDate,
111-
url: `${baseUrl}/projects/scores?startDate=${startDate}&endDate=${endDate}`,
112-
})
113-
}
114-
115-
return datasets
91+
const today = new Date().toISOString().slice(0, 10)
92+
const { scoredAfter } = options ?? {}
93+
94+
const params = new URLSearchParams()
95+
if (scoredAfter) params.set('scoredAfter', scoredAfter)
96+
const qs = params.toString()
97+
98+
return [
99+
{
100+
id: scoredAfter ? `${today}-since-${scoredAfter}` : today,
101+
date: today,
102+
url: `${baseUrl}/projects${qs ? `?${qs}` : ''}`,
103+
},
104+
]
116105
}
117106

118-
/**
119-
* Returns an object-mode Readable that fetches all pages from the API
120-
* and pushes each row as a plain object. Activities.ts iterates this
121-
* directly (no csv-parse) because format === 'json'.
122-
*/
123107
async fetchDatasetStream(dataset: IDatasetDescriptor): Promise<Readable> {
124108
const baseUrl = getApiBaseUrl()
109+
const scoredAfter = new URL(dataset.url).searchParams.get('scoredAfter') ?? undefined
125110

126-
// Extract startDate and endDate from the stored URL
127-
const parsed = new URL(dataset.url)
128-
const startDate = parsed.searchParams.get('startDate') ?? ''
129-
const endDate = parsed.searchParams.get('endDate') ?? ''
111+
log.info(
112+
{ datasetId: dataset.id, baseUrl, scoredAfter: scoredAfter ?? 'none (full fetch)' },
113+
'LF Criticality Score: starting stream fetch.',
114+
)
130115

131116
async function* pages() {
132117
let page = 1
133118
let totalPages = 1
134119

135120
do {
136-
const response = await fetchPage(baseUrl, startDate, endDate, page)
121+
log.info(
122+
{ datasetId: dataset.id, page, totalPages },
123+
'LF Criticality Score: fetching page...',
124+
)
125+
const response = await fetchPage(baseUrl, page, scoredAfter)
137126
totalPages = response.totalPages
138127

128+
if (page === 1) {
129+
log.info(
130+
{
131+
datasetId: dataset.id,
132+
total: response.total,
133+
totalPages,
134+
pageSize: response.pageSize,
135+
},
136+
'LF Criticality Score: first page received — total records available.',
137+
)
138+
}
139+
139140
for (const row of response.data) {
140141
yield row
141142
}
142143

143-
log.debug(
144+
log.info(
144145
{ datasetId: dataset.id, page, totalPages, rowsInPage: response.data.length },
145-
'LF Criticality Score page fetched.',
146+
'LF Criticality Score: page fetched.',
146147
)
147148

148149
page++
149150
} while (page <= totalPages)
151+
152+
log.info({ datasetId: dataset.id, totalPages }, 'LF Criticality Score: all pages fetched.')
150153
}
151154

152155
return Readable.from(pages(), { objectMode: true })
153156
}
154157

155158
parseRow(rawRow: Record<string, unknown>): IDiscoverySourceRow | null {
156-
const repoUrl = rawRow['repoUrl'] as string | undefined
159+
const repoUrl = (rawRow['repourl'] ?? rawRow['repoUrl']) as string | undefined
157160
if (!repoUrl) {
158161
return null
159162
}

services/apps/automatic_projects_discovery_worker/src/sources/ossf-criticality-score/bucketClient.ts

Lines changed: 0 additions & 96 deletions
This file was deleted.

0 commit comments

Comments
 (0)