11package com .backend .domain .repository .service ;
22
33import com .backend .domain .repository .dto .response .RepositoryData ;
4- import com .backend .domain .repository .dto .response .github .RepoResponse ;
4+ import com .backend .domain .repository .dto .response .github .* ;
55import com .backend .domain .repository .entity .Language ;
66import com .backend .domain .repository .entity .Repositories ;
77import com .backend .domain .repository .repository .RepositoryJpaRepository ;
8- import com .backend .global .exception .BusinessException ;
9- import com .backend .global .exception .ErrorCode ;
108import com .backend .domain .repository .service .fetcher .GitHubDataFetcher ;
11- import com .backend .domain .repository .service .mapper .ReadmeInfoMapper ;
12- import com .backend .domain .repository .service .mapper .RepositoriesMapper ;
13- import com .backend .domain .repository .service .mapper .RepositoryInfoMapper ;
9+ import com .backend .domain .repository .service .mapper .*;
1410import com .backend .domain .user .entity .User ;
1511import com .backend .domain .user .repository .UserRepository ;
12+ import com .backend .global .exception .BusinessException ;
13+ import com .backend .global .exception .ErrorCode ;
1614import lombok .RequiredArgsConstructor ;
17- import lombok .extern .slf4j .Slf4j ;
1815import org .springframework .stereotype .Service ;
1916import org .springframework .transaction .annotation .Transactional ;
2017
18+ import java .time .ZoneOffset ;
19+ import java .time .ZonedDateTime ;
20+ import java .time .format .DateTimeFormatter ;
21+ import java .time .temporal .ChronoUnit ;
2122import java .util .List ;
23+ import java .util .Map ;
2224import java .util .Optional ;
2325
24- import static com .backend .global .exception .ErrorCode .GITHUB_REPO_NOT_FOUND ;
25-
26- @ Slf4j
2726@ Service
2827@ RequiredArgsConstructor
2928public class RepositoryService {
@@ -34,7 +33,13 @@ public class RepositoryService {
3433 private final GitHubDataFetcher gitHubDataFetcher ;
3534 private final RepositoriesMapper repositoriesMapper ;
3635 private final RepositoryInfoMapper repositoryInfoMapper ;
36+ private final CommitInfoMapper commitInfoMapper ;
3737 private final ReadmeInfoMapper readmeInfoMapper ;
38+ private final SecurityInfoMapper securityInfoMapper ;
39+ private final TestInfoMapper testInfoMapper ;
40+ private final CicdInfoMapper cicdInfoMapper ;
41+ private final IssueInfoMapper issueInfoMapper ;
42+ private final PullRequestInfoMapper pullRequestInfoMapper ;
3843 private final RepositoryJpaRepository repositoryJpaRepository ;
3944
4045 @ Transactional
@@ -43,12 +48,8 @@ public RepositoryData fetchAndSaveRepository(String owner, String repo) {
4348 return fetchCompleteRepositoryData (owner , repo );
4449 } catch (BusinessException e ) {
4550 String errorCode = (e .getErrorCode () != null ) ? e .getErrorCode ().getCode () : "UNKNOWN" ;
46- log .error ("Repository analysis failed for {}/{}: {} - {}" ,
47- owner , repo , errorCode , e .getMessage ());
4851 throw e ;
4952 } catch (Exception e ) {
50- log .error ("Unexpected error during repository analysis for {}/{}: {}" ,
51- owner , repo , e .getMessage (), e );
5253 throw new BusinessException (ErrorCode .INTERNAL_ERROR );
5354 }
5455 }
@@ -61,49 +62,60 @@ public RepositoryData fetchCompleteRepositoryData(String owner, String repo) {
6162 RepoResponse repoInfo = gitHubDataFetcher .fetchRepositoryInfo (owner , repo );
6263 repositoryInfoMapper .mapBasicInfo (data , repoInfo );
6364
64- // TODO: 커밋 데이터 수집 및 매핑
65-
65+ // 2. 커밋 데이터 수집 및 매핑
66+ ZonedDateTime ninetyDaysAgoUtc = ZonedDateTime .now (ZoneOffset .UTC ).minus (90 , ChronoUnit .DAYS );
67+ String sinceParam = ninetyDaysAgoUtc .format (DateTimeFormatter .ISO_INSTANT );
68+ List <CommitResponse > commitInfo = gitHubDataFetcher .fetchCommitInfo (owner , repo , sinceParam );
69+ commitInfoMapper .mapCommitInfo (data , commitInfo );
6670
67- // TODO: README 데이터 수집 및 매핑
71+ // 3. README 데이터 수집 및 매핑
6872 String readmeInfo = gitHubDataFetcher .fetchReadmeContent (owner , repo );
6973 readmeInfoMapper .mapReadmeInfo (data , readmeInfo );
7074
71- // TODO: 보안 관리 데이터 수집 및 매핑
75+ // 4. 보안 관리 데이터 수집 및 매핑
76+ TreeResponse securityInfo = gitHubDataFetcher .fetchRepositoryTreeInfo (owner , repo , repoInfo .defaultBranch ());
77+ securityInfoMapper .mapSecurityInfo (data , securityInfo );
7278
79+ // 5. 테스트 데이터 수집 및 매핑
80+ TreeResponse testInfo = gitHubDataFetcher .fetchRepositoryTreeInfo (owner , repo , repoInfo .defaultBranch ());
81+ testInfoMapper .mapTestInfo (data , testInfo );
7382
74- // TODO: 테스트 데이터 수집 및 매핑
83+ // 6. CI/CD 데이터 수집 및 매핑
84+ TreeResponse cicdInfo = gitHubDataFetcher .fetchRepositoryTreeInfo (owner , repo , repoInfo .defaultBranch ());
85+ cicdInfoMapper .mapCicdInfo (data , cicdInfo );
7586
87+ // 7. 커뮤니티 활성도 데이터 수집 및 매핑
88+ List <IssueResponse > issueInfo = gitHubDataFetcher .fetchIssueInfo (owner , repo );
89+ issueInfoMapper .mapIssueInfo (data , issueInfo );
7690
77- // TODO: CI/CD 데이터 수집 및 매핑
78-
79-
80- // TODO: 커뮤니티 활성도 데이터 수집 및 매핑
91+ List <PullRequestResponse > pullRequestInfo = gitHubDataFetcher .fetchPullRequestInfo (owner , repo );
92+ pullRequestInfoMapper .mapPullRequestInfo (data , pullRequestInfo );
8193
8294 // Entity 저장 로직
83- saveRepositoryEntity (repoInfo );
95+ Repositories savedRepository = saveOrUpdateRepository (repoInfo , owner , repo );
96+
8497
85- log .info ("✅ RepositoryData: {}" , data );
8698 return data ;
8799 }
88100
89- private void saveRepositoryEntity (RepoResponse repoInfo ) {
101+ private Repositories saveOrUpdateRepository (RepoResponse repoInfo , String owner , String repo ) {
90102 User defaultUser = userRepository .findAll ().stream ()
91103 .findFirst ()
92104 .orElseThrow (() -> new BusinessException (ErrorCode .INTERNAL_ERROR ));
93105
94- Repositories entity = repositoriesMapper . toEntity ( repoInfo , defaultUser );
95- repositoryJpaRepository
96- .findByHtmlUrl (entity . getHtmlUrl ())
106+ Map < String , Integer > languagesData = gitHubDataFetcher . fetchLanguages ( owner , repo );
107+
108+ return repositoryJpaRepository .findByHtmlUrl (repoInfo . htmlUrl ())
97109 .map (existing -> {
98- existing .updateFrom (repositoriesMapper .toEntity (repoInfo , defaultUser ));
110+ existing .updateFrom (repoInfo );
111+ existing .updateLanguagesFrom (languagesData );
99112 return existing ;
100113 })
101114 .orElseGet (() -> {
102- Repositories newEntity = repositoriesMapper .toEntity (repoInfo , defaultUser );
103- return repositoryJpaRepository .save (newEntity );
115+ Repositories newRepo = repositoriesMapper .toEntity (repoInfo , defaultUser );
116+ newRepo .updateLanguagesFrom (languagesData );
117+ return repositoryJpaRepository .save (newRepo );
104118 });
105-
106- log .info ("✅ Repositories: {}" , entity );
107119 }
108120
109121 // Repository에서 member로 리포지토리 찾기
@@ -116,7 +128,7 @@ public List<Language> findLanguagesByRepisotryId(Long gitRepositoryId){
116128 return repositoryJpaRepository .findLanguagesByRepositoryId (gitRepositoryId );
117129 }
118130
119- // repostiroy 삭제
131+ // repository 삭제
120132 public void delete (Long repositoriesId ){
121133 Optional <Repositories > optionalRepository = repositoryJpaRepository .findById (repositoriesId );
122134 if (optionalRepository .isPresent ()){
0 commit comments