Migration 015 adds merge_commit_sha/squash_commit_sha to merge_requests (Gate 4/5 prerequisites), closes_issues_synced_for_updated_at watermark for incremental sync, and the missing idx_label_events_label index. The MR transformer and ingestion pipeline now populate commit SHAs during sync. The orchestrator uses watermark-based filtering for closes_issues jobs instead of re-enqueuing all MRs every sync. The Phase B PRD is updated to match the actual codebase: corrected migration numbering (011-015), documented nullable label/milestone fields (migration 012), watermark patterns (013), observability infrastructure (014), simplified source_method values, and updated entity_references schema to match implementation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
113 lines
3.5 KiB
Rust
113 lines
3.5 KiB
Rust
use crate::core::time::{iso_to_ms_opt_strict, iso_to_ms_strict, now_ms};
|
|
use crate::gitlab::types::GitLabMergeRequest;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct NormalizedMergeRequest {
|
|
pub gitlab_id: i64,
|
|
pub project_id: i64,
|
|
pub iid: i64,
|
|
pub title: String,
|
|
pub description: Option<String>,
|
|
pub state: String,
|
|
pub draft: bool,
|
|
pub author_username: String,
|
|
pub source_branch: String,
|
|
pub target_branch: String,
|
|
pub head_sha: Option<String>,
|
|
pub references_short: Option<String>,
|
|
pub references_full: Option<String>,
|
|
pub detailed_merge_status: Option<String>,
|
|
pub merge_user_username: Option<String>,
|
|
pub created_at: i64,
|
|
pub updated_at: i64,
|
|
pub merged_at: Option<i64>,
|
|
pub closed_at: Option<i64>,
|
|
pub last_seen_at: i64,
|
|
pub web_url: String,
|
|
pub merge_commit_sha: Option<String>,
|
|
pub squash_commit_sha: Option<String>,
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct MergeRequestWithMetadata {
|
|
pub merge_request: NormalizedMergeRequest,
|
|
pub label_names: Vec<String>,
|
|
pub assignee_usernames: Vec<String>,
|
|
pub reviewer_usernames: Vec<String>,
|
|
}
|
|
|
|
pub fn transform_merge_request(
|
|
gitlab_mr: &GitLabMergeRequest,
|
|
local_project_id: i64,
|
|
) -> Result<MergeRequestWithMetadata, String> {
|
|
let created_at = iso_to_ms_strict(&gitlab_mr.created_at)?;
|
|
let updated_at = iso_to_ms_strict(&gitlab_mr.updated_at)?;
|
|
|
|
let merged_at = iso_to_ms_opt_strict(&gitlab_mr.merged_at)?;
|
|
let closed_at = iso_to_ms_opt_strict(&gitlab_mr.closed_at)?;
|
|
|
|
let is_draft = gitlab_mr.draft || gitlab_mr.work_in_progress;
|
|
|
|
let detailed_merge_status = gitlab_mr
|
|
.detailed_merge_status
|
|
.clone()
|
|
.or_else(|| gitlab_mr.merge_status_legacy.clone());
|
|
|
|
let merge_user_username = gitlab_mr
|
|
.merge_user
|
|
.as_ref()
|
|
.map(|u| u.username.clone())
|
|
.or_else(|| gitlab_mr.merged_by.as_ref().map(|u| u.username.clone()));
|
|
|
|
let (references_short, references_full) = gitlab_mr
|
|
.references
|
|
.as_ref()
|
|
.map(|r| (Some(r.short.clone()), Some(r.full.clone())))
|
|
.unwrap_or((None, None));
|
|
|
|
let head_sha = gitlab_mr.sha.clone();
|
|
|
|
let assignee_usernames: Vec<String> = gitlab_mr
|
|
.assignees
|
|
.iter()
|
|
.map(|a| a.username.clone())
|
|
.collect();
|
|
|
|
let reviewer_usernames: Vec<String> = gitlab_mr
|
|
.reviewers
|
|
.iter()
|
|
.map(|r| r.username.clone())
|
|
.collect();
|
|
|
|
Ok(MergeRequestWithMetadata {
|
|
merge_request: NormalizedMergeRequest {
|
|
gitlab_id: gitlab_mr.id,
|
|
project_id: local_project_id,
|
|
iid: gitlab_mr.iid,
|
|
title: gitlab_mr.title.clone(),
|
|
description: gitlab_mr.description.clone(),
|
|
state: gitlab_mr.state.clone(),
|
|
draft: is_draft,
|
|
author_username: gitlab_mr.author.username.clone(),
|
|
source_branch: gitlab_mr.source_branch.clone(),
|
|
target_branch: gitlab_mr.target_branch.clone(),
|
|
head_sha,
|
|
references_short,
|
|
references_full,
|
|
detailed_merge_status,
|
|
merge_user_username,
|
|
created_at,
|
|
updated_at,
|
|
merged_at,
|
|
closed_at,
|
|
last_seen_at: now_ms(),
|
|
web_url: gitlab_mr.web_url.clone(),
|
|
merge_commit_sha: gitlab_mr.merge_commit_sha.clone(),
|
|
squash_commit_sha: gitlab_mr.squash_commit_sha.clone(),
|
|
},
|
|
label_names: gitlab_mr.labels.clone(),
|
|
assignee_usernames,
|
|
reviewer_usernames,
|
|
})
|
|
}
|