Skip to content

Commit ff7eb9e

Browse files
committed
feat(repository): 정규식 패턴 개선 및 언어 중복 저장 해결
1 parent 8d0d278 commit ff7eb9e

File tree

4 files changed

+166
-95
lines changed

4 files changed

+166
-95
lines changed

backend/src/main/java/com/backend/domain/repository/entity/Repositories.java

Lines changed: 15 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.backend.domain.analysis.entity.AnalysisResult;
44
import com.backend.domain.repository.dto.response.github.RepoResponse;
5-
import com.backend.domain.repository.service.mapper.RepositoriesMapper;
65
import com.backend.domain.repository.util.LanguageUtils;
76
import com.backend.domain.user.entity.User;
87
import com.backend.global.entity.BaseEntity;
@@ -12,7 +11,10 @@
1211
import lombok.Getter;
1312
import lombok.NoArgsConstructor;
1413

15-
import java.util.*;
14+
import java.util.ArrayList;
15+
import java.util.List;
16+
import java.util.Map;
17+
import java.util.Set;
1618
import java.util.stream.Collectors;
1719

1820
@Entity
@@ -86,35 +88,25 @@ public void updatePublicFrom(Repositories other) {
8688
this.publicRepository = other.publicRepository;
8789
}
8890

89-
public static Repositories createOrUpdateRepositories(Optional<Repositories> existing,
90-
RepoResponse repoInfo,
91-
User user,
92-
RepositoriesMapper mapper) {
93-
return existing
94-
.map(repo -> {
95-
repo.updateFrom(repoInfo);
96-
return repo;
97-
})
98-
.orElseGet(() -> mapper.toEntity(repoInfo, user));
99-
}
100-
10191
public void updateLanguagesFrom(Map<String, Integer> newLanguagesData) {
102-
Set<String> newLanguageNames = newLanguagesData.keySet();
103-
Set<String> existingLanguageNames = this.languages.stream()
104-
.map(rl -> rl.getLanguage().name())
92+
Set<Language> newLanguages = newLanguagesData.keySet().stream()
93+
.map(LanguageUtils::fromGitHubName)
94+
.collect(Collectors.toSet());
95+
96+
Set<Language> existingLanguages = this.languages.stream()
97+
.map(RepositoryLanguage::getLanguage)
10598
.collect(Collectors.toSet());
10699

107-
if (newLanguageNames.equals(existingLanguageNames)) {
100+
if (newLanguages.equals(existingLanguages)) {
108101
return;
109102
}
110103

111104
this.languages.removeIf(repoLang ->
112-
!newLanguageNames.contains(repoLang.getLanguage().name()));
105+
!newLanguages.contains(repoLang.getLanguage()));
113106

114-
newLanguageNames.stream()
115-
.filter(langName -> !existingLanguageNames.contains(langName))
116-
.forEach(langName -> {
117-
Language language = LanguageUtils.fromGitHubName(langName);
107+
newLanguages.stream()
108+
.filter(language -> !existingLanguages.contains(language))
109+
.forEach(language -> {
118110
RepositoryLanguage repositoryLanguage = RepositoryLanguage.builder()
119111
.repositories(this)
120112
.language(language)

backend/src/main/java/com/backend/domain/repository/service/mapper/CicdInfoMapper.java

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,56 @@ public class CicdInfoMapper {
1414
private static final String GITHUB_WORKFLOWS_PATTERN = "^\\.github/workflows/.*\\.(yml|yaml)$";
1515

1616
private static final List<String> CICD_FILE_PATTERNS = List.of(
17-
"^\\.gitlab-ci\\.(yml|yaml)$", "^\\.travis\\.(yml|yaml)$", "^azure-pipelines\\.(yml|yaml)$",
18-
"^circle\\.(yml|yaml)$", "^\\.circleci/config\\.(yml|yaml)$", "^\\.drone\\.(yml|yaml)$",
19-
"^\\.bitbucket-pipelines\\.(yml|yaml)$", "^\\.buildkite\\/(pipeline\\.)?(yml|yaml)$", "^\\.teamcity\\.(settings|config)\\.(xml|kts|yaml)$",
20-
"^\\.appveyor\\.(yml|yaml)$", "^\\.github/actions/.*\\.(yml|yaml)$", "^\\.buddy/.*\\.(yml|yaml)$", "^\\.codefresh/.*\\.(yml|yaml)$",
21-
"^\\.bitrise\\.yml$", "^\\.wercker/.*\\.(yml|yaml)$", "^\\.buildkite/pipeline\\.(yml|yaml)$", "^\\.concourse/.*\\.(yml|yaml)$",
22-
"^\\.semaphore/.*\\.(yml|yaml)$", "^\\.harness/.*\\.(yml|yaml)$"
17+
// 주요 CI/CD 플랫폼
18+
"^\\.gitlab-ci\\.(yml|yaml)$",
19+
"^\\.travis\\.(yml|yaml)$",
20+
"^azure-pipelines\\.(yml|yaml)$",
21+
"^\\.circleci/config\\.(yml|yaml)$",
22+
"^\\.github/actions/.*\\.(yml|yaml)$",
23+
"^\\.bitbucket-pipelines\\.(yml|yaml)$",
24+
"^\\.appveyor\\.(yml|yaml)$"
2325
);
2426

25-
private static final List<String> JENKINSFILE_PATTERNS = List.of(".*/Jenkinsfile$|^Jenkinsfile$", ".*/Jenkinsfile(\\..*)?$|^Jenkinsfile(\\..*)?$");
27+
private static final List<String> JENKINSFILE_PATTERNS = List.of(
28+
".*/[Jj]enkinsfile$",
29+
"^[Jj]enkinsfile$",
30+
".*/[Jj]enkinsfile\\..+$",
31+
"^[Jj]enkinsfile\\..+$"
32+
);
2633

2734
private static final List<String> BUILD_FILE_PATTERNS = List.of(
28-
"^pom\\.xml$|.*/pom\\.xml$",
29-
"^build\\.gradle(\\.kts)?$|.*/build\\.gradle(\\.kts)?$", "^package\\.json$|.*/package\\.json$",
30-
"^Cargo\\.toml$|.*/Cargo\\.toml$", "^go\\.mod$|.*/go\\.mod$", "^requirements\\.txt$|.*/requirements\\.txt$",
31-
"^setup\\.py$|.*/setup\\.py$", "^CMakeLists\\.txt$|.*/CMakeLists\\.txt$", "^Makefile$|.*/Makefile$",
32-
"^gradlew(\\.bat)?$|.*/gradlew(\\.bat)?$", "^mvnw(\\.cmd)?$|.*/mvnw(\\.cmd)?$", "^Gemfile(\\.lock)?$|.*/Gemfile(\\.lock)?$",
33-
"^composer\\.(json|lock)$|.*/composer\\.(json|lock)$", "^yarn\\.lock$|.*/yarn\\.lock$", "^pnpm-lock\\.yaml$|.*/pnpm-lock\\.yaml$",
34-
"^package-lock\\.json$|.*/package-lock\\.json$", "^pyproject\\.toml$|.*/pyproject\\.toml$", "^setup\\.cfg$|.*/setup\\.cfg$",
35-
"^environment\\.yml$|.*/environment\\.yml$", "^mix\\.exs$|.*/mix\\.exs$", "^build\\.sbt$|.*/build\\.sbt$",
36-
"^Vagrantfile$|.*/Vagrantfile$", "^Chart\\.yaml$|.*/Chart\\.yaml$", "^values\\.yaml$|.*/values\\.yaml$",
37-
"^Taskfile\\.ya?ml$|.*/Taskfile\\.ya?ml$", "^Justfile$|.*/Justfile$", "^Brewfile$|.*/Brewfile$",
38-
"^Podfile(\\.lock)?$|.*/Podfile(\\.lock)?$", "^Fastfile$|.*/Fastfile$", "^Makefile\\.am$|.*/Makefile\\.am$", "^CMakeCache\\.txt$|.*/CMakeCache\\.txt$"
35+
// Java 빌드 도구
36+
".*pom\\.xml$",
37+
".*build\\.gradle(\\.kts)?$",
38+
".*gradlew(\\.bat)?$",
39+
".*mvnw(\\.cmd)?$",
40+
41+
// JavaScript/Node.js
42+
".*package\\.json$",
43+
".*(yarn\\.lock|pnpm-lock\\.yaml|package-lock\\.json)$",
44+
45+
// Python
46+
".*requirements\\.txt$",
47+
".*setup\\.py$",
48+
".*pyproject\\.toml$",
49+
".*setup\\.cfg$",
50+
51+
// 기타 주요 언어
52+
".*Cargo\\.toml$",
53+
".*go\\.mod$",
54+
".*Gemfile(\\.lock)?$",
55+
".*composer\\.(json|lock)$",
56+
57+
// C/C++ 및 범용
58+
".*CMakeLists\\.txt$",
59+
".*Makefile$",
60+
".*build\\.xml$"
3961
);
4062

4163
private static final List<String> DOCKERFILE_PATTERNS = List.of(
42-
"^Dockerfile.*$|.*/Dockerfile.*$",
43-
"^Dockerfile.*$|.*/Dockerfile.*$|.*\\.dockerfile$",
44-
"^docker-compose\\.ya?ml$|.*/docker-compose\\.ya?ml$",
45-
"^compose\\.ya?ml$|.*/compose\\.ya?ml$"
64+
".*(?i)dockerfile.*$",
65+
".*(?i)docker-compose.*\\.(yml|yaml)$",
66+
".*(?i)compose.*\\.(yml|yaml)$"
4667
);
4768

4869
public void mapCicdInfo(RepositoryData data, TreeResponse response) {

backend/src/main/java/com/backend/domain/repository/service/mapper/SecurityInfoMapper.java

Lines changed: 67 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,79 @@
1212
public class SecurityInfoMapper {
1313
// ResponseData 보안 [민감 파일, 빌드 파일 여부]
1414
private static final List<String> SENSITIVE_FILE_PATTERNS = List.of(
15-
".*\\.env$", ".*\\.(pem|key|p12|pfx|crt|cer)$", ".*/id_rsa$|^id_rsa$", ".*/id_dsa$|^id_dsa$",
16-
".*/authorized_keys$|^authorized_keys$", ".*credentials\\.(json|xml|yml|yaml|properties)$", ".*secret.*\\.(json|xml|yml|yaml|properties)$",
17-
".*\\.(keystore|jks|p12)$", ".*/\\.aws/credentials$", ".*/\\.ssh/.*$", ".*\\.env\\..*$",
18-
".*\\.aws/.*credentials.*", ".*\\.gcp/.*(key|credential).*", ".*service-account.*\\.json$", ".*firebase.*\\.json$",
19-
".*google.*credentials.*\\.json$", ".*config\\.json$", ".*application(-secret|-prod)?\\.ya?ml$", ".*token.*(\\.txt|\\.json|\\.yml|\\.yaml)$",
20-
".*apikey.*(\\.txt|\\.json|\\.env|\\.yml)$", ".*password.*(\\.txt|\\.json|\\.env|\\.yml)$", ".*oauth.*(\\.json|\\.yml|\\.yaml)$",
21-
".*client_secret.*(\\.json|\\.yml|\\.yaml)$", ".*private.*(\\.json|\\.pem|\\.key)$", ".*jwt.*(\\.json|\\.pem|\\.key)$",
22-
".*vault.*", ".*id_ecdsa$", ".*pgpass$", ".*\\.npmrc$", ".*\\.netrc$", ".*\\.bash_history$", ".*\\.zsh_history$",
23-
".*\\.docker/config\\.json$", ".*terraform.*\\.tfstate.*", ".*secrets?\\.json$", ".*\\.p8$", ".*\\.bak$", ".*\\.old$", ".*\\.swp$", ".*\\.DS_Store$"
15+
// 환경 변수 파일
16+
".*\\.env$",
17+
".*\\.env\\.prod(uction)?$",
18+
".*\\.env\\.local$",
19+
20+
// 인증서 및 키
21+
".*\\.(pem|key|p12|pfx|crt|cer|p8)$",
22+
".*/id_rsa$|^id_rsa$",
23+
".*/id_dsa$|^id_dsa$",
24+
".*/id_ecdsa$|^id_ecdsa$",
25+
".*/authorized_keys$|^authorized_keys$",
26+
".*\\.(keystore|jks)$",
27+
28+
// 민감한 설정
29+
".*application-secret\\.ya?ml$",
30+
".*application-prod\\.ya?ml$",
31+
".*credentials\\.(json|xml|yml|yaml|properties)$",
32+
".*secret.*\\.(json|xml|yml|yaml|properties)$",
33+
".*secrets?\\.json$",
34+
35+
// 클라우드 인증
36+
".*/\\.aws/credentials$",
37+
".*service-account.*\\.json$",
38+
".*firebase.*\\.json$",
39+
".*google.*credentials.*\\.json$",
40+
41+
// 토큰 / API 키
42+
".*token.*\\.txt$",
43+
".*apikey.*\\.txt$",
44+
".*password.*\\.txt$",
45+
".*client_secret.*\\.(json|yml|yaml)$",
46+
".*oauth.*\\.json$",
47+
48+
// SSH 관련
49+
".*/\\.ssh/id_.*$",
50+
".*/\\.ssh/config$",
51+
52+
// 기타 확실한 민감 파일
53+
".*pgpass$",
54+
".*\\.netrc$"
2455
);
2556

2657
private static final List<String> SAFE_FILE_PATTERNS = List.of(
27-
".*\\.env\\.(example|template|sample|dist)$", ".*credentials\\.(example|sample|template|dist)$",
28-
".*secret.*\\.(example|sample|template|dist)$", ".*\\.env\\.(example|sample|template|dist|local|dev|prod|staging)$",
29-
".*example.*credentials.*", ".*dummy.*(json|yaml|yml|env|properties)$",
30-
".*mock.*(json|yaml|yml|env|properties)$", ".*test.*(json|yaml|yml|env|properties)$",
31-
".*\\.example$", ".*\\.sample$", ".*\\.template$", ".*\\.default$", ".*/fixtures/.*", ".*/samples?/.*"
32-
58+
// 예시/템플릿 파일들
59+
".*\\.(example|template|sample|dist|default)$",
60+
".*\\.env\\.(example|template|sample|dist)$",
61+
".*credentials\\.(example|sample|template)$",
62+
".*secret.*\\.(example|sample|template)$",
63+
64+
// 테스트/더미 데이터
65+
".*test.*\\.(json|yaml|yml|env|properties)$",
66+
".*mock.*\\.(json|yaml|yml|env|properties)$",
67+
".*dummy.*\\.(json|yaml|yml|env|properties)$",
68+
69+
// 예시 디렉토리들
70+
".*/fixtures/.*",
71+
".*/samples?/.*",
72+
".*/examples?/.*"
3373
);
3474

3575
private static final List<String> BUILD_FILE_NAMES = List.of(
36-
"pom.xml", "build.gradle", "build.gradle.kts", "package.json", "Cargo.toml",
37-
"go.mod", "requirements.txt", "setup.py", "CMakeLists.txt", "Makefile", "Dockerfile",
38-
"gradlew", "gradlew.bat", "mvnw", "mvnw.cmd", "Gemfile", "Gemfile.lock", "composer.json", "composer.lock",
39-
"yarn.lock", "pnpm-lock.yaml", "package-lock.json", "mix.exs", "rebar.config",
40-
"build.sbt", "build.xml", "setup.cfg", "pyproject.toml", "environment.yml", "Procfile", "runtime.txt",
41-
"Vagrantfile", "Docker-compose.yml", "docker-compose.yml", "Chart.yaml", "values.yaml", "Makefile.am",
42-
"Brewfile", "Podfile", "Podfile.lock", "Fastfile", "Taskfile.yml", "taskfile.yml", "Justfile"
43-
76+
// 주요 빌드 파일들
77+
"pom.xml", "build.gradle", "build.gradle.kts",
78+
"package.json", "package-lock.json", "yarn.lock", "pnpm-lock.yaml",
79+
"Cargo.toml", "go.mod", "requirements.txt", "pyproject.toml", "setup.py",
80+
"CMakeLists.txt", "Makefile", "Dockerfile",
81+
82+
// 빌드 스크립트들
83+
"gradlew", "gradlew.bat", "mvnw", "mvnw.cmd",
84+
85+
// 언어별 의존성 파일들
86+
"Gemfile", "Gemfile.lock", "composer.json", "composer.lock",
87+
"mix.exs", "build.sbt"
4488
);
4589

4690
public void mapSecurityInfo(RepositoryData data, TreeResponse response) {

backend/src/main/java/com/backend/domain/repository/service/mapper/TestInfoMapper.java

Lines changed: 41 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,42 +11,56 @@
1111
@Component
1212
public class TestInfoMapper {
1313
// ResponseData 테스트 구성 [test 파일 여부 관련]
14+
// 테스트 디렉토리
1415
private static final List<String> TEST_DIRECTORY_PATTERNS = List.of(
1516
"^src/test/.*",
16-
"^test/.*",
17-
"^tests/.*",
18-
".*/__tests__/.*",
19-
".*/test/.*",
20-
".*/tests/.*",
21-
".*/spec/.*"
17+
".*/(test|tests|spec|specs|__tests__)/.*",
18+
".*/(integration-tests?|functional-tests?|acceptance-tests?|e2e|qa|itest|utest)/.*"
2219
);
2320

24-
// 테스트 파일 확장자 패턴
21+
// 테스트 파일
2522
private static final List<String> TEST_FILE_PATTERNS = List.of(
26-
".*Test\\.(java|kt|js|ts|py|rb|go|rs)$",
27-
".*Tests\\.(java|kt|js|ts|py|rb|go|rs)$", ".*TestCase\\.(java|kt|js|ts|py|rb|go|rs)$", ".*\\.test\\.(js|ts|jsx|tsx)$",
28-
".*\\.spec\\.(js|ts|jsx|tsx)$", ".*_test\\.(py|go|rs|rb)$", "^test_.*\\.py$",
29-
".*_spec\\.rb$", ".*IT\\.(java|kt)$", ".*[Tt]est.*\\.(c|cpp|cc|cxx)$",
30-
".*Integration.*Test\\.(java|kt)$", ".*End.*To.*End.*Test\\.(java|kt)$", ".*E2E.*Test\\.(java|kt)$",
31-
".*Unit.*Test\\.(java|kt)$", ".*Functional.*Test\\.(java|kt)$", ".*Contract.*Test\\.(java|kt)$",
32-
".*Performance.*Test\\.(java|kt)$", ".*Load.*Test\\.(java|kt)$", ".*Smoke.*Test\\.(java|kt)$",
33-
".*Acceptance.*Test\\.(java|kt)$", ".*TestBase\\.(java|kt)$", ".*TestUtils?\\.(java|kt)$",
34-
".*TestHelper\\.(java|kt)$", ".*TestData\\.(java|kt)$", ".*TestConfig\\.(java|kt)$",
35-
".*TestSuite\\.(java|kt)$", ".*ApplicationTests\\.(java|kt)$", ".*ContextTest\\.(java|kt)$",
36-
".*SliceTest\\.(java|kt)$", ".*\\.e2e-spec\\.(js|ts)$", ".*\\.integration\\.(js|ts)$",
37-
".*\\.unit\\.(js|ts)$", "^test.*\\.py$", ".*test.*\\.py$",
38-
".*_integration_test\\.go$", ".*_unit_test\\.go$", ".*_integration_test\\.rs$",
39-
".*/tests\\.rs$", ".*_feature_spec\\.rb$", ".*_integration_spec\\.rb$", ".*Test\\.(php)$", ".*_test\\.(php)$",
40-
".*Spec\\.(java|kt)$", ".*Specification\\.(java|kt)$", ".*Scenario\\.(java|kt|py|ts)$",
41-
".*Feature\\.(java|kt|py|rb)$", ".*Example\\.(java|kt|py)$", ".*Benchmark\\.(go|rs|py)$",
42-
".*MockTest\\.(java|kt|ts|py)$", ".*ValidatorTest\\.(java|kt|ts|py)$", ".*ControllerTest\\.(java|kt|ts)$",
43-
".*ServiceTest\\.(java|kt|ts)$", ".*RepositoryTest\\.(java|kt)$", ".*APITest\\.(java|kt|ts|py)$",
44-
".*UITest\\.(java|kt|ts)$", ".*BrowserTest\\.(js|ts|py)$", ".*Acceptance\\.(java|kt|py)$", ".*RegressionTest\\.(java|kt|py)$"
23+
// Java/Kotlin
24+
".*(Test|Tests|TestCase|IT|Spec|Feature|Scenario)\\.(java|kt)$",
25+
".*(Integration|Application|Unit|Functional|E2E|Performance|Load|Smoke|Acceptance|Regression|UITest).*Test\\.(java|kt)$",
26+
".*(TestBase|TestUtils?|TestHelper|TestData|TestConfig|TestSuite)\\.(java|kt)$",
27+
28+
// JavaScript/TypeScript
29+
".*\\.(test|spec|e2e-spec|integration|unit|browser)\\.(js|ts|jsx|tsx)$",
30+
31+
// Python
32+
"^test_.*\\.py$",
33+
".*_test\\.py$",
34+
35+
// Go
36+
".*_test\\.go$",
37+
".*_(integration|unit)_test\\.go$",
38+
39+
// Ruby
40+
".*_spec\\.rb$",
41+
42+
// Rust
43+
".*_test\\.rs$",
44+
".*/tests\\.rs$",
45+
46+
// C/C++
47+
".*[Tt]est.*\\.(c|cpp|cc|cxx|h|hpp)$",
48+
49+
// Dart
50+
".*_test\\.dart$",
51+
52+
// PHP / Swift / C#
53+
".*Test\\.(php|swift|cs)$",
54+
55+
// 기타 패턴
56+
".*(Mock|Validator|Controller|Service|Repository|API|UI)Test\\.(java|kt|ts|py|cs|php|swift)$"
4557
);
4658

4759
// 소스 파일 확장자
4860
private static final List<String> SOURCE_FILE_EXTENSIONS = List.of(
49-
".java", ".kt", ".js", ".ts", ".jsx", ".tsx", ".py", ".rb", ".go", ".rs", ".cpp", ".c", ".cs", ".php", ".swift"
61+
".java", ".kt", ".scala", ".js", ".ts", ".jsx", ".tsx",
62+
".py", ".rb", ".go", ".rs", ".cpp", ".c", ".cs",
63+
".php", ".swift", ".m", ".mm", ".dart", ".h", ".hpp"
5064
);
5165

5266
public void mapTestInfo(RepositoryData data, TreeResponse response) {

0 commit comments

Comments
 (0)