Skip to content

Commit 673d336

Browse files
fix: resolve path error (#1739)
* fix: fix reviewer assignment logic Signed-off-by: allure <1550220889@qq.com> * fix: resolve logic error and test Signed-off-by: allure <1550220889@qq.com> * fix: resolve path error Signed-off-by: allure <1550220889@qq.com> --------- Signed-off-by: allure <1550220889@qq.com> Signed-off-by: Yao <1550220889@qq.com>
1 parent c836c47 commit 673d336

2 files changed

Lines changed: 59 additions & 87 deletions

File tree

ceres/src/pack/monorepo.rs

Lines changed: 51 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -710,14 +710,14 @@ impl MonoRepo {
710710
}
711711
};
712712

713-
// Cedar reviewer auto-assignment for new CL
713+
// Auto-assign reviewers for new CL
714714
if is_new_cl && let Err(e) = self.assign_system_reviewers().await {
715-
tracing::warn!("[Cedar Reviewer] Failed to assign reviewers: {}", e);
715+
tracing::warn!("Failed to assign Cedar reviewers: {}", e);
716716
}
717717

718718
// Resync reviewers when existing CL updates policy files
719719
if !is_new_cl && let Err(e) = self.resync_current_cl_reviewers_if_policy_changed().await {
720-
tracing::warn!("[Cedar Reviewer] Failed to resync reviewers: {}", e);
720+
tracing::warn!("Failed to resync Cedar reviewers: {}", e);
721721
}
722722

723723
Ok(())
@@ -728,22 +728,19 @@ impl MonoRepo {
728728
path.ends_with(".cedar/policies.cedar") || path.ends_with(".cedar\\policies.cedar")
729729
}
730730

731-
/// Resync reviewers for current CL when policy files are modified in the same push
731+
/// Resync reviewers when policy files are modified in an existing CL.
732732
async fn resync_current_cl_reviewers_if_policy_changed(&self) -> Result<(), MegaError> {
733733
let changed_files = self.get_changed_files().await?;
734734

735735
if !changed_files.iter().any(|f| Self::is_policy_file(f)) {
736736
return Ok(());
737737
}
738738

739-
tracing::info!("[Cedar Reviewer] Policy file modified in CL update, resyncing reviewers");
740-
741739
let link_guard = self.cl_link.read().await;
742740
let cl_link = link_guard
743741
.as_ref()
744742
.ok_or_else(|| MegaError::Other("CL link not available".to_string()))?;
745743

746-
// Collect policies from all changed file paths
747744
let policy_contents = self.collect_policy_contents(&changed_files).await;
748745
if policy_contents.is_empty() {
749746
return Ok(());
@@ -754,124 +751,119 @@ impl MonoRepo {
754751
.sync_system_reviewers(cl_link, &policy_contents, &changed_files)
755752
.await?;
756753

757-
tracing::info!("[Cedar Reviewer] Reviewers resynced for CL {}", cl_link);
758754
Ok(())
759755
}
760756

761-
/// Get list of files changed in this commit
757+
/// Get list of files changed between from_hash and to_hash commits.
758+
/// Returns paths relative to the CL root directory with forward slashes.
762759
async fn get_changed_files(&self) -> Result<Vec<String>, MegaError> {
763760
let mono_api_service: MonoApiService = self.into();
764761

765-
// Get file lists for both commits
766762
let old_files = mono_api_service.get_commit_blobs(&self.from_hash).await?;
767763
let new_files = mono_api_service.get_commit_blobs(&self.to_hash).await?;
768-
769-
// Compare and get changed files
770764
let changed = mono_api_service.cl_files_list(old_files, new_files).await?;
771765

772-
// Extract file paths as strings
766+
// Normalize CL root path to use forward slashes
767+
let cl_root = self.path.to_string_lossy().replace('\\', "/");
768+
let cl_root_normalized = cl_root.trim_start_matches('/');
769+
773770
let file_paths: Vec<String> = changed
774771
.iter()
775-
.map(|f| f.path().to_string_lossy().to_string())
772+
.map(|f| {
773+
let full_path = f.path().to_string_lossy().replace('\\', "/");
774+
let full_path_normalized = full_path.trim_start_matches('/');
775+
776+
// Strip CL root prefix to get relative path
777+
if let Some(rel) = full_path_normalized.strip_prefix(cl_root_normalized) {
778+
rel.trim_start_matches('/').to_string()
779+
} else {
780+
full_path.to_string()
781+
}
782+
})
776783
.collect();
777784

778785
Ok(file_paths)
779786
}
780787

781-
/// Collect policy files from CL directory and all changed file paths within the CL
782-
/// Returns list of (policy_path, content) tuples, ordered from CL root to leaf
783-
///
784-
/// # Arguments
785-
/// * `changed_files` - List of changed file paths relative to CL root
788+
/// Collect Cedar policy files from directories of all changed files.
789+
/// Returns list of (policy_path, content) tuples, ordered from root to leaf.
786790
async fn collect_policy_contents(&self, changed_files: &[String]) -> Vec<(PathBuf, String)> {
787791
let mono_api_service: MonoApiService = self.into();
788792
let mut all_policy_dirs: HashSet<PathBuf> = HashSet::new();
789793

790-
// 1. Always include the CL root directory itself
791-
all_policy_dirs.insert(self.path.clone());
794+
// Always include the CL root directory
795+
all_policy_dirs.insert(PathBuf::new());
792796

793-
// 2. Collect directories from all changed files within this CL
797+
// Collect ancestor directories from all changed files
794798
for file_path in changed_files {
795-
// Safety: ensure path is relative by removing any leading '/'
796-
let relative_path = file_path.trim_start_matches('/');
797-
let path = PathBuf::from(relative_path);
799+
let relative_path = file_path.trim_start_matches('/').replace('\\', "/");
800+
let path = PathBuf::from(&relative_path);
798801

799-
// Get the logical parent directory (skip .cedar directories)
800-
// For "servicea/.cedar/policies.cedar" -> we want "servicea"
801-
// For "servicea/core/mod.rs" -> we want "servicea/core" and "servicea"
802802
let parent = path.parent().unwrap_or(std::path::Path::new(""));
803803

804-
// If parent is .cedar directory, go up one more level
804+
// Skip .cedar directory itself, use its parent
805805
let logical_parent = if parent.file_name().map(|n| n == ".cedar").unwrap_or(false) {
806806
parent.parent().unwrap_or(std::path::Path::new(""))
807807
} else {
808808
parent
809809
};
810810

811-
// Add all ancestor directories of the logical parent (within CL scope)
812811
for ancestor in logical_parent.ancestors() {
813-
if ancestor.as_os_str().is_empty() {
814-
// Empty path is skipped because CL root (self.path) is already added in step 1
815-
continue;
816-
}
817-
818-
// Skip any path that contains .cedar component
819812
let ancestor_str = ancestor.to_string_lossy();
820813
if ancestor_str.contains(".cedar") {
821814
continue;
822815
}
823-
824-
// Join with CL path to get the full path within the repository
825-
let full_path = self.path.join(ancestor);
826-
all_policy_dirs.insert(full_path);
816+
let normalized = PathBuf::from(ancestor_str.replace('\\', "/"));
817+
all_policy_dirs.insert(normalized);
827818
}
828819
}
829820

830-
// 3. Sort directories by depth (CL root to leaf) for correct override semantics
821+
// Sort by depth for correct override semantics (root policies first)
831822
let mut sorted_dirs: Vec<PathBuf> = all_policy_dirs.into_iter().collect();
832823
sorted_dirs.sort_by_key(|p| p.components().count());
833824

834-
// 4. Collect policy contents from all directories
835825
let mut policy_contents: Vec<(PathBuf, String)> = Vec::new();
836-
let mut seen_policies: HashSet<PathBuf> = HashSet::new();
826+
let mut seen_policies: HashSet<String> = HashSet::new();
837827

838828
for dir in sorted_dirs {
839-
let policy_path = dir.join(".cedar/policies.cedar");
829+
let policy_relative_path = if dir.as_os_str().is_empty() {
830+
".cedar/policies.cedar".to_string()
831+
} else {
832+
let dir_str = dir.to_string_lossy().replace('\\', "/");
833+
format!("{}/.cedar/policies.cedar", dir_str)
834+
};
840835

841-
// Skip if we've already processed this policy file
842-
if seen_policies.contains(&policy_path) {
836+
if seen_policies.contains(&policy_relative_path) {
843837
continue;
844838
}
845839

840+
let lookup_path = PathBuf::from(&policy_relative_path);
841+
let self_path_str = self.path.to_string_lossy().replace('\\', "/");
842+
let full_policy_path_str = format!("{}/{}", self_path_str, policy_relative_path);
843+
let full_policy_path = PathBuf::from(&full_policy_path_str);
844+
846845
if let Ok(Some(content)) = mono_api_service
847-
.get_blob_as_string(policy_path.clone(), Some(&self.to_hash))
846+
.get_blob_as_string(lookup_path, Some(&self.to_hash))
848847
.await
849848
{
850-
tracing::debug!(
851-
"[Cedar Reviewer] Found policy file: {}",
852-
policy_path.display()
853-
);
854-
seen_policies.insert(policy_path.clone());
855-
policy_contents.push((policy_path, content));
849+
seen_policies.insert(policy_relative_path);
850+
policy_contents.push((full_policy_path, content));
856851
}
857852
}
858853

859854
policy_contents
860855
}
861856

862-
/// Auto-assign system required reviewers based on .cedar/policies.cedar
863-
/// Collects policies from all changed file paths, not just CL root ancestors
857+
/// Auto-assign system required reviewers based on Cedar policy files.
864858
async fn assign_system_reviewers(&self) -> Result<(), MegaError> {
865859
let link_guard = self.cl_link.read().await;
866860
let cl_link = link_guard
867861
.as_ref()
868862
.ok_or_else(|| MegaError::Other("CL link not available".to_string()))?;
869863

870-
// Get all changed files to match against policy rules
871-
let changed_files = self.get_changed_files().await.unwrap_or_default();
872-
873-
// Collect policies from all changed file paths
864+
let changed_files = self.get_changed_files().await?;
874865
let policy_contents = self.collect_policy_contents(&changed_files).await;
866+
875867
if policy_contents.is_empty() {
876868
return Ok(());
877869
}

jupiter/src/service/reviewer_service.rs

Lines changed: 8 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
//! Service for managing system required reviewers.
2-
//!
3-
//! This service handles automatic reviewer assignment based on Cedar policy files.
1+
//! Service for managing system required reviewers based on Cedar policy files.
42
53
use std::collections::HashSet;
64
use std::path::PathBuf;
@@ -11,10 +9,8 @@ use saturn::reviewer_parser::aggregate_reviewers;
119
use crate::storage::{base_storage::BaseStorage, cl_reviewer_storage::ClReviewerStorage};
1210

1311
/// Convert a file path to its logical directory path for Cedar policy matching.
14-
///
15-
/// For policy files (e.g., "servicea/.cedar/policies.cedar"), returns the parent
16-
/// directory path with trailing slash (e.g., "servicea/").
17-
/// For regular files, returns the path unchanged (as an owned String).
12+
/// For policy files, returns the parent directory with trailing slash.
13+
/// For regular files, returns the path unchanged.
1814
fn to_policy_match_path(file_path: &str) -> String {
1915
if file_path.ends_with(".cedar/policies.cedar") || file_path.ends_with(".cedar\\policies.cedar")
2016
{
@@ -75,18 +71,10 @@ impl ReviewerService {
7571
Self { reviewer_storage }
7672
}
7773

78-
/// Assign system required reviewers for multiple changed files
74+
/// Assign system required reviewers based on Cedar policies.
7975
///
80-
/// This method iterates through all changed files and aggregates reviewers
81-
/// from policy files that match each file path.
82-
///
83-
/// # Arguments
84-
/// * `cl_link` - The CL link identifier
85-
/// * `policy_contents` - List of (policy_path, content) tuples, from root to leaf
86-
/// * `changed_files` - List of changed file paths relative to CL root
87-
///
88-
/// # Returns
89-
/// List of assigned reviewer usernames
76+
/// Iterates through changed files and aggregates reviewers from matching policies.
77+
/// Returns list of assigned reviewer usernames.
9078
pub async fn assign_system_reviewers(
9179
&self,
9280
cl_link: &str,
@@ -130,17 +118,9 @@ impl ReviewerService {
130118
Ok(all_reviewers)
131119
}
132120

133-
/// Sync system required reviewers for multiple changed files
134-
///
135-
/// This method:
136-
/// 1. Removes all current system_required reviewers
137-
/// 2. Aggregates reviewers from hierarchical policy files for all changed files
138-
/// 3. Adds new reviewers as system_required
121+
/// Sync system required reviewers when policy files change.
139122
///
140-
/// # Arguments
141-
/// * `cl_link` - The CL link identifier
142-
/// * `policy_contents` - List of (policy_path, content) tuples, from root to leaf
143-
/// * `changed_files` - List of changed file paths relative to CL root
123+
/// Removes current system reviewers and re-assigns based on updated policies.
144124
pub async fn sync_system_reviewers(
145125
&self,
146126
cl_link: &str,

0 commit comments

Comments
 (0)