Skip to content

Commit 2b49a7c

Browse files
committed
Get Delphi working with Labrinth
1 parent b6c4bcd commit 2b49a7c

File tree

5 files changed

+56
-26
lines changed

5 files changed

+56
-26
lines changed

apps/labrinth/migrations/20250810155316_delphi-reports.sql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,8 @@ CREATE TABLE delphi_report_issue_details (
3939
issue_id BIGINT NOT NULL REFERENCES delphi_report_issues (id)
4040
ON DELETE CASCADE
4141
ON UPDATE CASCADE,
42-
internal_class_name TEXT NOT NULL,
42+
key TEXT NOT NULL,
43+
file_path TEXT NOT NULL,
4344
decompiled_source TEXT,
4445
data JSONB NOT NULL,
4546
severity DELPHI_SEVERITY NOT NULL

apps/labrinth/src/database/models/delphi_report_item.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,8 +249,9 @@ impl DBDelphiReportIssue {
249249
#[derive(Debug, Deserialize, Serialize)]
250250
pub struct DBDelphiReportIssueDetails {
251251
pub id: DelphiReportIssueDetailsId,
252+
pub key: String,
252253
pub issue_id: DelphiReportIssueId,
253-
pub internal_class_name: InternalJavaClassName,
254+
pub file_path: String,
254255
pub decompiled_source: Option<DecompiledJavaClassSource>,
255256
pub data: Json<HashMap<String, serde_json::Value>>,
256257
pub severity: DelphiSeverity,
@@ -263,12 +264,13 @@ impl DBDelphiReportIssueDetails {
263264
) -> Result<DelphiReportIssueDetailsId, DatabaseError> {
264265
Ok(DelphiReportIssueDetailsId(sqlx::query_scalar!(
265266
"
266-
INSERT INTO delphi_report_issue_details (issue_id, internal_class_name, decompiled_source, data, severity)
267-
VALUES ($1, $2, $3, $4, $5)
267+
INSERT INTO delphi_report_issue_details (issue_id, key, file_path, decompiled_source, data, severity)
268+
VALUES ($1, $2, $3, $4, $5, $6)
268269
RETURNING id
269270
",
270271
self.issue_id as DelphiReportIssueId,
271-
self.internal_class_name.0,
272+
self.key,
273+
self.file_path,
272274
self.decompiled_source.as_ref().map(|decompiled_source| &decompiled_source.0),
273275
&self.data as &Json<HashMap<String, serde_json::Value>>,
274276
self.severity as DelphiSeverity,

apps/labrinth/src/routes/internal/delphi.rs

Lines changed: 35 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use reqwest::header::{HeaderMap, HeaderValue, USER_AGENT};
66
use serde::Deserialize;
77
use sqlx::PgPool;
88
use tokio::sync::Mutex;
9-
use tracing::info;
9+
use tracing::{info, warn};
1010

1111
use crate::{
1212
auth::check_is_moderator_from_headers,
@@ -18,7 +18,6 @@ use crate::{
1818
DBDelphiReport, DBDelphiReportIssue,
1919
DBDelphiReportIssueDetails, DecompiledJavaClassSource,
2020
DelphiReportIssueStatus, DelphiReportListOrder, DelphiSeverity,
21-
InternalJavaClassName,
2221
},
2322
},
2423
redis::RedisPool,
@@ -61,7 +60,8 @@ static DELPHI_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(|| {
6160

6261
#[derive(Deserialize)]
6362
struct DelphiReportIssueDetails {
64-
pub internal_class_name: InternalJavaClassName,
63+
pub file: String,
64+
pub key: String,
6565
pub decompiled_source: Option<DecompiledJavaClassSource>,
6666
pub data: HashMap<String, serde_json::Value>,
6767
pub severity: DelphiSeverity,
@@ -94,14 +94,14 @@ impl DelphiReport {
9494

9595
for (issue, trace) in &self.issues {
9696
for DelphiReportIssueDetails {
97-
internal_class_name,
97+
file,
9898
decompiled_source,
9999
..
100100
} in trace
101101
{
102102
write!(
103103
&mut message_header,
104-
"\n issue {issue} found at class `{internal_class_name}`:\n```\n{}\n```",
104+
"\n issue {issue} found at class `{file}`:\n```\n{}\n```",
105105
decompiled_source.as_ref().map_or(
106106
"No decompiled source available",
107107
|decompiled_source| &**decompiled_source
@@ -131,13 +131,21 @@ pub struct DelphiRunParameters {
131131
async fn ingest_report(
132132
pool: web::Data<PgPool>,
133133
redis: web::Data<RedisPool>,
134-
web::Json(report): web::Json<DelphiReport>,
135-
) -> Result<HttpResponse, ApiError> {
136-
tracing::error!("!! INGEST !!");
134+
report: web::Bytes,
135+
// web::Json(report): web::Json<DelphiReport>,
136+
) -> Result<(), ApiError> {
137+
info!(
138+
"Json: {}",
139+
serde_json::to_string_pretty(
140+
&serde_json::from_slice::<serde_json::Value>(&report).unwrap()
141+
)
142+
.unwrap()
143+
);
144+
let report = serde_json::from_slice::<DelphiReport>(&report).unwrap();
137145

138146
if report.issues.is_empty() {
139147
info!("No issues found for file {}", report.url);
140-
return Ok(HttpResponse::NoContent().finish());
148+
return Ok(());
141149
}
142150

143151
report.send_to_slack(&pool, &redis).await.ok();
@@ -155,6 +163,12 @@ async fn ingest_report(
155163
.upsert(&mut transaction)
156164
.await?;
157165

166+
warn!(
167+
"Delphi found {} issues in file {}",
168+
report.issues.len(),
169+
report.url
170+
);
171+
158172
for (issue_type, issue_details) in report.issues {
159173
let issue_id = DBDelphiReportIssue {
160174
id: DelphiReportIssueId(0), // This will be set by the database
@@ -176,7 +190,8 @@ async fn ingest_report(
176190
DBDelphiReportIssueDetails {
177191
id: DelphiReportIssueDetailsId(0), // This will be set by the database
178192
issue_id,
179-
internal_class_name: issue_detail.internal_class_name,
193+
key: issue_detail.key,
194+
file_path: issue_detail.file,
180195
decompiled_source: issue_detail.decompiled_source,
181196
data: issue_detail.data.into(),
182197
severity: issue_detail.severity,
@@ -188,7 +203,7 @@ async fn ingest_report(
188203

189204
transaction.commit().await?;
190205

191-
Ok(HttpResponse::NoContent().finish())
206+
Ok(())
192207
}
193208

194209
pub async fn run(
@@ -216,10 +231,18 @@ pub async fn run(
216231
run_parameters.file_id.0
217232
);
218233

234+
// fix for local file paths
235+
// TODO: should we fix this upstream in whatever inserts the files row?
236+
let url = if file_data.url.starts_with("/") {
237+
format!("file://{}", file_data.url)
238+
} else {
239+
file_data.url
240+
};
241+
219242
DELPHI_CLIENT
220243
.post(dotenvy::var("DELPHI_URL")?)
221244
.json(&serde_json::json!({
222-
"url": file_data.url,
245+
"url": url,
223246
"project_id": ProjectId(file_data.project_id.0 as u64),
224247
"version_id": VersionId(file_data.version_id.0 as u64),
225248
"file_id": run_parameters.file_id,

apps/labrinth/src/routes/internal/moderation/tech_review.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub struct SearchProjectsFilter {
6767
Deserialize,
6868
utoipa::ToSchema,
6969
)]
70+
#[serde(rename_all = "snake_case")]
7071
pub enum SearchProjectsSort {
7172
CreatedAsc,
7273
CreatedDesc,
@@ -153,8 +154,8 @@ pub struct FileIssue {
153154
/// Occurrence of a [`FileIssue`] in a specific class in a scanned JAR file.
154155
#[derive(Debug, Serialize, Deserialize, utoipa::ToSchema)]
155156
pub struct FileIssueDetail {
156-
/// Name of the Java class in which this issue was found.
157-
pub class_name: String,
157+
/// Name of the Java class path in which this issue was found.
158+
pub file_path: String,
158159
/// Decompiled, pretty-printed source of the Java class.
159160
pub decompiled_source: String,
160161
/// How important is this issue, as flagged by Delphi?
@@ -236,7 +237,7 @@ async fn search_projects(
236237
dri.status AS "issue_status!: DelphiReportIssueStatus",
237238
-- maybe null
238239
drid.id AS "issue_detail_id?: DelphiReportIssueDetailsId",
239-
drid.internal_class_name AS "issue_detail_class_name?",
240+
drid.file_path AS "issue_detail_file_path?",
240241
drid.decompiled_source AS "issue_detail_decompiled_source?",
241242
drid.severity AS "issue_detail_severity?: DelphiSeverity"
242243
FROM delphi_reports dr
@@ -322,12 +323,12 @@ async fn search_projects(
322323

323324
let (
324325
Some(issue_detail_id),
325-
Some(class_name),
326+
Some(file_path),
326327
Some(decompiled_source),
327328
Some(severity),
328329
) = (
329330
row.issue_detail_id,
330-
row.issue_detail_class_name,
331+
row.issue_detail_file_path,
331332
row.issue_detail_decompiled_source,
332333
row.issue_detail_severity,
333334
)
@@ -336,7 +337,7 @@ async fn search_projects(
336337
};
337338
issue.details.entry(issue_detail_id).or_insert_with(|| {
338339
FileIssueDetail {
339-
class_name,
340+
file_path,
340341
decompiled_source,
341342
severity,
342343
}
@@ -414,8 +415,7 @@ async fn search_projects(
414415
.into_iter()
415416
.map(|(_, detail)| {
416417
FileIssueDetail {
417-
class_name: detail
418-
.class_name,
418+
file_path: detail.file_path,
419419
decompiled_source: detail
420420
.decompiled_source,
421421
severity: detail.severity,

docker-compose.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ services:
117117
delphi:
118118
profiles:
119119
- with-delphi
120-
image: ghcr.io/modrinth/delphi:main
120+
image: ghcr.io/modrinth/delphi:feature-schema-rework
121121
container_name: labrinth-delphi
122122
ports:
123123
- '59999:59999'
@@ -130,6 +130,10 @@ services:
130130
interval: 3s
131131
timeout: 5s
132132
retries: 3
133+
volumes:
134+
# Labrinth deposits version files here;
135+
# Delphi reads them from here
136+
- /tmp/modrinth:/tmp/modrinth:ro
133137
extra_hosts:
134138
# Delphi must send a message on a webhook to our backend,
135139
# so it must have access to our local network

0 commit comments

Comments
 (0)