-
Notifications
You must be signed in to change notification settings - Fork 105
[vscode] Azure DevOps URL 파싱 지원 및 getRepo 함수 개선 #801
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,121 @@ | ||
| import { getRepo } from "../../utils/git.util"; | ||
|
|
||
| describe("getRepo", () => { | ||
| describe("Valid Git URL formats", () => { | ||
| it("HTTPS URL with .git extension should parse correctly", () => { | ||
| const url = "https://github.com/owner/repo.git"; | ||
| const result = getRepo(url); | ||
|
|
||
| expect(result).toEqual({ | ||
| owner: "owner", | ||
| repo: "repo", | ||
| }); | ||
| }); | ||
|
|
||
|
Comment on lines
+6
to
+14
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (사소) Test case에서도 동일한 logic들은 (stateless하다면) 밖으로 빼도 괜찮을 것 같습니다 👍
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 아, URL(input)만 딱 다르고, 다른 부분이 모두 동일하다면 TC의 입력값을 다르게 하는 해당 건 이슈로 등록해주셔도 좋을 것 같습니다!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 의견 너무 감사드립니다!!!
vscode extention 에서는
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 그러고보니 vscode 쪽은 거의 tc 가 없긴하네요. *.spec.ts를 mocha 안쓰고 jest로 변경해주셔도 괜찮습니다!!!
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 넵! mocha 걷어내는 작업 따로 Issue 파서 진행하도록 하겠습니다ㅎㅎ |
||
| it("SSH URL with .git extension should parse correctly", () => { | ||
| const url = "git@github.com:owner/repo.git"; | ||
| const result = getRepo(url); | ||
|
|
||
| expect(result).toEqual({ | ||
| owner: "owner", | ||
| repo: "repo", | ||
| }); | ||
| }); | ||
|
|
||
| it("HTTPS URL without .git extension should parse correctly", () => { | ||
| const url = "https://github.com/owner/repo"; | ||
| const result = getRepo(url); | ||
|
|
||
| expect(result).toEqual({ | ||
| owner: "owner", | ||
| repo: "repo", | ||
| }); | ||
| }); | ||
|
|
||
| it("SSH URL without .git extension should parse correctly", () => { | ||
| const url = "git@github.com:owner/repo"; | ||
| const result = getRepo(url); | ||
|
|
||
| expect(result).toEqual({ | ||
| owner: "owner", | ||
| repo: "repo", | ||
| }); | ||
| }); | ||
|
|
||
| it("HTTPS URL with username should parse correctly", () => { | ||
| const url = "https://username@github.com/owner/repo.git"; | ||
| const result = getRepo(url); | ||
|
|
||
| expect(result).toEqual({ | ||
| owner: "owner", | ||
| repo: "repo", | ||
| }); | ||
| }); | ||
|
|
||
| it("URL with trailing slash should parse correctly", () => { | ||
| const url = "https://github.com/owner/repo/"; | ||
| const result = getRepo(url); | ||
|
|
||
| expect(result).toEqual({ | ||
| owner: "owner", | ||
| repo: "repo", | ||
| }); | ||
| }); | ||
|
|
||
| it("Complex repo name with hyphens should parse correctly", () => { | ||
| const url = "https://github.com/githru/githru-vscode-ext.git"; | ||
| const result = getRepo(url); | ||
|
|
||
| expect(result).toEqual({ | ||
| owner: "githru", | ||
| repo: "githru-vscode-ext", | ||
| }); | ||
| }); | ||
|
|
||
| it("Azure DevOps URL should parse correctly", () => { | ||
| const url = "https://organization@dev.azure.com/organization/organization-sub-name/_git/repository-name"; | ||
| const result = getRepo(url); | ||
|
|
||
| expect(result).toEqual({ | ||
| owner: "organization", | ||
| repo: "repository-name", | ||
| }); | ||
| }); | ||
|
|
||
| it("Azure DevOps URL without username should parse correctly", () => { | ||
| const url = "https://dev.azure.com/organization/organization-sub-name/_git/repository-name"; | ||
|
Comment on lines
+75
to
+86
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 저희는 사내에서
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. github에 .net으로 끝나는 도메인도 있는지는 몰랐네요ㅎㅎ 정책이 정해진다면 해당 케이스도 추가하도록 하겠습니다!
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. samsung.net 입니다 👿 |
||
| const result = getRepo(url); | ||
|
|
||
| expect(result).toEqual({ | ||
| owner: "organization", | ||
| repo: "repository-name", | ||
| }); | ||
| }); | ||
| }); | ||
|
|
||
| describe("Invalid Git URL formats", () => { | ||
| it("should throw error for invalid URL format", () => { | ||
| const invalidUrl = "invalid-url-format"; | ||
|
|
||
| expect(() => getRepo(invalidUrl)).toThrow( | ||
| 'Invalid Git remote config format: "invalid-url-format". Expected format: [https?://|git@]github.com/owner/repo[.git] or https://organization@dev.azure.com/organization/project/_git/repository-name' | ||
|
Comment on lines
+96
to
+101
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Negative case 까지!! 완벽하네요! |
||
| ); | ||
| }); | ||
|
|
||
| it("should throw error for non-GitHub URL", () => { | ||
| const nonGithubUrl = "https://gitlab.com/owner/repo.git"; | ||
|
|
||
| expect(() => getRepo(nonGithubUrl)).toThrow( | ||
| 'Invalid Git remote config format: "https://gitlab.com/owner/repo.git". Expected format: [https?://|git@]github.com/owner/repo[.git] or https://organization@dev.azure.com/organization/project/_git/repository-name' | ||
| ); | ||
| }); | ||
|
|
||
| it("should throw error for URL without owner/repo", () => { | ||
| const incompleteUrl = "https://github.com/"; | ||
|
|
||
| expect(() => getRepo(incompleteUrl)).toThrow( | ||
| 'Invalid Git remote config format: "https://github.com/". Expected format: [https?://|git@]github.com/owner/repo[.git] or https://organization@dev.azure.com/organization/project/_git/repository-name' | ||
| ); | ||
| }); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -113,7 +113,7 @@ | |
| if (await isExecutable(file)) { | ||
| try { | ||
| return await getGitExecutable(file); | ||
| } catch (_) {} | ||
| } | ||
| } | ||
| return Promise.reject<GitExecutable>(); | ||
|
|
@@ -149,7 +149,7 @@ | |
| for (let i = 0; i < paths.length; i++) { | ||
| try { | ||
| return await getGitExecutable(paths[i]); | ||
| } catch (_) {} | ||
| } | ||
| throw new Error("None of the provided paths are a Git executable"); | ||
| } | ||
|
|
@@ -288,19 +288,33 @@ | |
| } | ||
|
|
||
| export const getRepo = (gitRemoteConfig: string) => { | ||
| const gitRemoteConfigPattern = | ||
| /(?:https?|git)(?::\/\/(?:\w+@)?|@)(?:github\.com)(?:\/|:)(?:(?<owner>[^/]+?)\/(?<repo>[^/.]+))(?:\.git|\/)?(\S*)$/m; | ||
| const gitRemote = gitRemoteConfig.match(gitRemoteConfigPattern)?.groups; | ||
| if (!gitRemote) { | ||
| throw new Error("git remote config should be: [https?://|git@]${domain}/${owner}/${repo}.git"); | ||
| const gitHubPattern = | ||
| /(?:https?|git)(?::\/\/(?:\w+@)?|@)(?:github\.com)(?:\/|:)(?:(?<owner>[^/]+?)\/(?<repo>[^/]+?))(?:\.git|\/)?$/m; | ||
| const azureDevOpsPattern = | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (사소, 추후에..) azure 말고 다른 형태의 url이 들어오면 어떻게 대응하면 좋을까요?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 정책적으로도 좀 얘기해봐도 좋을 것 같긴 합니다 : )
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. domain, owner, repo가 remote url에 할당되어있는 방법이 저마다 달라서 말씀주신대로 public repo에 한해서만 대응하면 좋을 것 같습니다! 정책적으로 정해진다면 사용자에게 다음 액션을 유도하는 것도 사용성을 높일 수 있는 방법이라고 생각됩니다ㅎㅎ (
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
넵 이 내용에 대해서는 정책이나 지식 정도로 지정해서, 다른 contributor들도 알 수 있게 하면 좋을 것 같습니다.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이슈 생성해서 공유하겠습니다! 감사합니다ㅎㅎ |
||
| /https:\/\/(?:\w+@)?dev\.azure\.com\/(?<owner>[^/]+?)\/(?<project>[^/]+?)\/_git\/(?<repo>[^/]+?)(?:\/)?$/m; | ||
| const patterns = [gitHubPattern, azureDevOpsPattern]; | ||
|
|
||
| let gitRemote: { owner: string; repo: string } | null = null; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (궁금) null 을 굳이 넣으신 이유는 무엇일까용?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
에러 발생 조건으로 위 내용은 의견 주시는대로 변경해도 괜찮습니다ㅎㅎ
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 오. 넵. 그렇군요
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. gitRemote 의 변수에 값을 할당하지 않는(undefined) 상황을 가정해서 말씀하시는게 맞을까요??
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
아 특별히 null과 undefined를 엄격하게 나누는 기준이 있을까 해서 여쭤봤습니다 : ) |
||
|
|
||
| for (const pattern of patterns) { | ||
| const match = gitRemoteConfig.match(pattern); | ||
| if (!match?.groups) continue; | ||
|
|
||
| const { owner, repo } = match.groups; | ||
| if (owner && repo) { | ||
| const repoWithoutGit = repo.replace(/\.git$/, ""); | ||
| gitRemote = { owner, repo: repoWithoutGit }; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| const { owner, repo } = gitRemote; | ||
| if (!owner || !repo) { | ||
| throw new Error("no owner/repo"); | ||
| if (!gitRemote) { | ||
| throw new Error( | ||
| `Invalid Git remote config format: "${gitRemoteConfig}". Expected format: [https?://|git@]github.com/owner/repo[.git] or https://organization@dev.azure.com/organization/project/_git/repository-name` | ||
| ); | ||
| } | ||
|
|
||
| return { owner, repo }; | ||
| return gitRemote; | ||
| }; | ||
|
|
||
| export async function getBranches( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오우.. 감동입니다 😭 첫 PR부터 Test case 가 포함되어 있네요!!!