Skip to content

Commit

Permalink
Merge pull request #1002 from rohit-gohri/gitlab-diff
Browse files Browse the repository at this point in the history
Add structured diff support to Gitlab
  • Loading branch information
orta committed Mar 14, 2020
2 parents 0ca95c5 + 13fe5eb commit 62a25ba
Show file tree
Hide file tree
Showing 18 changed files with 1,363 additions and 144 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ x
- Disable warning in Github Action if using DANGER_GITHUB_API_TOKEN - [@rohit-gohri]
- Update `parse-diff` library - [@417-72KI]
- Fix repository slug in Jenkins provider - [sandratatarevicova]
- Add Gitlab diff support - [@rohit-gohri]
- Fix Typos across danger-js Repo - [@yohix]
- Fix `@octokit/rest` deprecation warning when using `.issues.addLabels()` - [@sogame]

Expand Down
30 changes: 30 additions & 0 deletions source/dsl/GitLabDSL.ts
Original file line number Diff line number Diff line change
Expand Up @@ -225,3 +225,33 @@ export interface GitLabMRCommit {
committer_email: string
committed_date: string
}

export interface GitLabRepositoryFile {
file_name: string
file_path: string
size: number
encoding: "base64"
content: string
content_sha256: string
ref: string
blob_id: string
commit_id: string
last_commit_id: string
}

export interface GitLabCommit {
id: string
short_id: string
title: string
author_name: string
author_email: string
created_at: string
}

export interface GitLabRepositoryCompare {
commit: GitLabCommit
commits: GitLabCommit[]
diffs: GitLabMRChange[]
compare_timeout: boolean
compare_same_ref: boolean
}
100 changes: 0 additions & 100 deletions source/platforms/_tests/fixtures/gitlab_mr.json

This file was deleted.

38 changes: 27 additions & 11 deletions source/platforms/gitlab/GitLabAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import {
GitLabMRCommit,
GitLabNote,
GitLabUserProfile,
GitLabRepositoryFile,
GitLabRepositoryCompare,
} from "../../dsl/GitLabDSL"

import { Gitlab } from "gitlab"
Expand Down Expand Up @@ -52,7 +54,7 @@ export function getGitLabAPICredentialsFromEnv(env: Env): GitLabAPICredentials {

class GitLabAPI {
fetch: typeof fetch
private api: any
private api: InstanceType<typeof Gitlab>
private readonly hostURL: string
private readonly d = debug("GitLabAPI")

Expand All @@ -72,14 +74,17 @@ class GitLabAPI {

getUser = async (): Promise<GitLabUserProfile> => {
this.d("getUser")
const user: GitLabUserProfile = await this.api.Users.current()
const user = (await this.api.Users.current()) as GitLabUserProfile
this.d("getUser", user)
return user
}

getMergeRequestInfo = async (): Promise<GitLabMR> => {
this.d(`getMergeRequestInfo for repo: ${this.repoMetadata.repoSlug} pr: ${this.repoMetadata.pullRequestID}`)
const mr: GitLabMR = await this.api.MergeRequests.show(this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID)
const mr = (await this.api.MergeRequests.show(
this.repoMetadata.repoSlug,
Number(this.repoMetadata.pullRequestID)
)) as GitLabMR
this.d("getMergeRequestInfo", mr)
return mr
}
Expand All @@ -88,7 +93,7 @@ class GitLabAPI {
this.d(`getMergeRequestChanges for repo: ${this.repoMetadata.repoSlug} pr: ${this.repoMetadata.pullRequestID}`)
const mr = (await this.api.MergeRequests.changes(
this.repoMetadata.repoSlug,
this.repoMetadata.pullRequestID
Number(this.repoMetadata.pullRequestID)
)) as GitLabMRChanges

this.d("getMergeRequestChanges", mr.changes)
Expand All @@ -97,18 +102,18 @@ class GitLabAPI {

getMergeRequestCommits = async (): Promise<GitLabMRCommit[]> => {
this.d("getMergeRequestCommits", this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID)
const commits: GitLabMRCommit[] = await this.api.MergeRequests.commits(
const commits = (await this.api.MergeRequests.commits(
this.repoMetadata.repoSlug,
this.repoMetadata.pullRequestID
)
Number(this.repoMetadata.pullRequestID)
)) as GitLabMRCommit[]
this.d("getMergeRequestCommits", commits)
return commits
}

getMergeRequestNotes = async (): Promise<GitLabNote[]> => {
this.d("getMergeRequestNotes", this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID)
const api = this.api.MergeRequestNotes
const notes: GitLabNote[] = await api.all(this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID)
const notes = (await api.all(this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID)) as GitLabNote[]
this.d("getMergeRequestNotes", notes)
return notes
}
Expand All @@ -132,6 +137,7 @@ class GitLabAPI {
const api = this.api.MergeRequestDiscussions

try {
// @ts-ignore
const result: string = await api.create(this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID, content, {
position: position,
})
Expand All @@ -149,7 +155,7 @@ class GitLabAPI {

try {
this.d("createMergeRequestNote")
const note: GitLabNote = await api.create(this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID, body)
const note = (await api.create(this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID, body)) as GitLabNote
this.d("createMergeRequestNote", note)
return note
} catch (e) {
Expand All @@ -163,7 +169,7 @@ class GitLabAPI {
this.d("updateMergeRequestNote", this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID, id, body)
const api = this.api.MergeRequestNotes
try {
const note: GitLabNote = await api.edit(this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID, id, body)
const note = (await api.edit(this.repoMetadata.repoSlug, this.repoMetadata.pullRequestID, id, body)) as GitLabNote
this.d("updateMergeRequestNote", note)
return note
} catch (e) {
Expand Down Expand Up @@ -200,7 +206,7 @@ class GitLabAPI {

try {
this.d("getFileContents", projectId, path, ref)
const response = await api.show(projectId, path, ref)
const response = (await api.show(projectId, path, ref)) as GitLabRepositoryFile
const result: string = Buffer.from(response.content, "base64").toString()
this.d("getFileContents", result)
return result
Expand All @@ -213,6 +219,16 @@ class GitLabAPI {
throw e
}
}

getCompareChanges = async (base?: string, head?: string): Promise<GitLabMRChange[]> => {
if (!base || !head) {
return this.getMergeRequestChanges()
}
const api = this.api.Repositories
const projectId = this.repoMetadata.repoSlug
const compare = (await api.compare(projectId, base, head)) as GitLabRepositoryCompare
return compare.diffs
}
}

export default GitLabAPI
39 changes: 29 additions & 10 deletions source/platforms/gitlab/GitLabGit.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,45 @@
import { debug } from "../../debug"
import { GitLabDSL } from "../../dsl/GitLabDSL"
import { GitLabDSL, GitLabMRChange } from "../../dsl/GitLabDSL"
import { GitDSL, GitJSONDSL } from "../../dsl/GitDSL"
import { gitJSONToGitDSL, GitJSONToGitDSLConfig, GitStructuredDiff } from "../git/gitJSONToGitDSL"
import { gitJSONToGitDSL, GitJSONToGitDSLConfig } from "../git/gitJSONToGitDSL"
import GitLabAPI from "./GitLabAPI"

const d = debug("GitLabGit")

export const gitLabGitDSL = (gitlab: GitLabDSL, json: GitJSONDSL): GitDSL => {
export const gitLabGitDSL = (gitlab: GitLabDSL, json: GitJSONDSL, gitlabAPI: GitLabAPI): GitDSL => {
const config: GitJSONToGitDSLConfig = {
repo: `${gitlab.mr.project_id}`, // we don't get the repo slug, but `project_id` is equivalent in API calls
baseSHA: gitlab.mr.diff_refs.base_sha,
headSHA: gitlab.mr.diff_refs.head_sha,
getFileContents: gitlab.utils.fileContents,
// TODO: implement me when the API methods are in
getFullDiff: async (): Promise<string> => {
throw new Error("getFullDiff is not yet implemented")
},
// TODO: implement me when the API methods are in
getStructuredDiffForFile: async (): Promise<GitStructuredDiff> => {
throw new Error("getStructuredDiffForFile is not yet implemented")
getFullDiff: async (base: string, head: string) => {
const changes = await gitlabAPI.getCompareChanges(base, head)
return gitlabChangesToDiff(changes)
},
}

d("Setting up git DSL with: ", config)
return gitJSONToGitDSL(json, config)
}

export const gitlabChangesToDiff = (changes: GitLabMRChange[]): string => {
d("Converting GitLab Changes to Diff")
// Gitlab doesn't return full raw git diff, relevant issue: https://gitlab.com/gitlab-org/gitlab/issues/24913
return changes
.map(change => {
const { diff } = change
if (diff.startsWith("diff --git a/") || diff.startsWith("--- a/") || diff.startsWith("--- /dev/null")) {
return diff
}

return `\
diff --git a/${change.old_path} b/${change.new_path}
${change.new_file ? `new file mode ${change.b_mode}` : ""}\
${change.deleted_file ? `deleted file mode ${change.a_mode}` : ""}\
${change.renamed_file ? `rename from ${change.old_path}\nrename to ${change.new_path}` : ""}
--- ${change.new_file ? "/dev/null" : "a/" + change.old_path}
+++ ${change.deleted_file ? "/dev/null" : "b/" + change.new_path}
${diff}`
})
.join("\n")
}
Loading

0 comments on commit 62a25ba

Please sign in to comment.