Skip to content

Commit

Permalink
WIP checks
Browse files Browse the repository at this point in the history
  • Loading branch information
orta committed May 11, 2018
1 parent 05cd72d commit fb39be0
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 9 deletions.
6 changes: 3 additions & 3 deletions source/platforms/GitHub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ import gitDSLForGitHub from "./github/GitHubGit"
import * as NodeGitHub from "@octokit/rest"
import { Platform } from "./platform"

import { GitHubIssueCommenter } from "./github/issueCommenter"
import { GitHubIssueCommenter } from "./github/comms/issueCommenter"
import { GitHubChecksCommenter } from "./github/comms/checksCommenter"

/** Handles conforming to the Platform Interface for GitHub, API work is handle by GitHubAPI */

export type GitHubType = Platform & { api: GitHubAPI; findPositionForInlineComment: any }

export const GitHub = (api: GitHubAPI) => {
// In the future this could also be a commenter for the new checks API
const commenter = GitHubIssueCommenter(api)

const commenter = GitHubChecksCommenter(api) || GitHubIssueCommenter(api)
/**
* Converts the PR JSON into something easily used by the Github API client.
*/
Expand Down
166 changes: 166 additions & 0 deletions source/platforms/github/comms/checksCommenter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
import { GitDSL } from "../../../dsl/GitDSL"
import { GitHubAPI } from "../GitHubAPI"
import * as debug from "debug"
import { Comment, PlatformCommunicator } from "../../platform"

// See https://github.com/auth0/node-jsonwebtoken/issues/162
const JWT_REGEX = /^[a-zA-Z0-9\-_]+?\.[a-zA-Z0-9\-_]+?\.([a-zA-Z0-9\-_]+)?$/

const d = debug("danger:GitHub::Checks")

export const getCheckAuthFromEnv = () => {
const appID = process.env.DANGER_GITHUB_APP_ID || process.env.PERIL_INTEGRATION_ID
const key = process.env.DANGER_GITHUB_APP_PRIVATE_SIGNING_KEY || process.env.PRIVATE_GITHUB_SIGNING_KEY
const installID = process.env.DANGER_GITHUB_APP_INSTALL_ID || process.env.PERIL_ORG_INSTALLATION_ID

return {
appID,
key,
installID,
}
}

const canUseChecks = (token: string | undefined) => {
// Is it a JWT from Peril, basically?
if (token && token.match(JWT_REGEX)) {
return true
} else {
const auth = getCheckAuthFromEnv()
return auth.appID && auth.key && auth.installID
}
}

/**
* An object whose responsibility is to handle commenting on an issue
* @param api
*/
export const GitHubChecksCommenter = (api: GitHubAPI): PlatformCommunicator | undefined => {
if (!canUseChecks(api.token)) {
return undefined
}

return {
supportsCommenting: () => true,
supportsInlineComments: () => true,

/**
* Fails the current build, if status setting succeeds
* then return true.
*/

updateStatus: async (passed: boolean | "pending", message: string, url?: string): Promise<boolean> => {
const ghAPI = api.getExternalAPI()

const prJSON = await api.getPullRequestInfo()
// const ref = prJSON.head
// try {
// await ghAPI.repos.createStatus({
// repo: ref.repo.name,
// owner: ref.repo.owner.login,
// sha: ref.sha,
// state: passed ? "success" : "failure",
// context: process.env["PERIL_INTEGRATION_ID"] ? "Peril" : "Danger",
// target_url: url || "http://danger.systems/js",
// description: message,
// })
// return true
// } catch (error) {
// return false
// }
// await ghAPI.checks.
},

/**
* Gets inline comments for current PR
*/
getInlineComments: async (dangerID: string): Promise<Comment[]> => () => null,

/**
* Returns the response for the new comment
*
* @param {string} comment you want to post
* @returns {Promise<any>} JSON response of new comment
*/
createComment: (comment: string) => api.postPRComment(comment),

/**
* Makes an inline comment if possible. If platform can't make an inline comment with given arguments,
* it returns a promise rejection. (e.g. platform doesn't support inline comments or line was out of diff).
*
* @returns {Promise<any>} JSON response of new comment
*/
createInlineComment: (git: GitDSL, comment: string, path: string, line: number): Promise<any> => {
let commitId = git.commits[git.commits.length - 1].sha
d("Creating inline comment. Commit: " + commitId)
return findPositionForInlineComment(git, line, path).then(position => {
return api.postInlinePRComment(comment, commitId, path, position)
})
},

/**
* Updates an inline comment if possible. If platform can't update an inline comment,
* it returns a promise rejection. (e.g. platform doesn't support inline comments or line was out of diff).
*
* @returns {Promise<any>} JSON response of new comment
*/
updateInlineComment: (comment: string, commentId: string): Promise<any> => {
d("Updating inline comment. CommentId: " + commentId + "comment: " + comment)
return api.updateInlinePRComment(comment, commentId)
},

/**
* Deletes the main Danger comment, used when you have
* fixed all your failures.
*
* @returns {Promise<boolean>} did it work?
*/
deleteMainComment: async (dangerID: string): Promise<boolean> => {
const commentIDs = await api.getDangerCommentIDs(dangerID)
for (let commentID of commentIDs) {
d(`Deleting comment ${commentID}`)
await api.deleteCommentWithID(commentID)
}

return commentIDs.length > 0
},

/**
* Deletes an inline comment, used when you have
* fixed all your failures.
*
* @returns {Promise<boolean>} did it work?
*/
deleteInlineComment: async (id: string): Promise<boolean> => api.deleteInlineCommentWithID(id),

/**
* Either updates an existing comment, or makes a new one
*
* @param {string} newComment string value of comment
* @returns {Promise<boolean>} success of posting comment
*/
updateOrCreateComment: async (dangerID: string, newComment: string): Promise<string | undefined> => {
const commentIDs = await api.getDangerCommentIDs(dangerID)
let issue = null

if (commentIDs.length) {
// Edit the first comment
d(`Updating comment ${commentIDs[0]}`)
issue = await api.updateCommentWithID(commentIDs[0], newComment)

// Delete any dupes
for (let commentID of commentIDs) {
if (commentID !== commentIDs[0]) {
d(`Deleting comment ${commentID}`)
await api.deleteCommentWithID(commentID)
}
}
} else {
d(`Creating new comment`)
issue = await api.postPRComment(newComment)
}

return issue && issue.html_url
},
findPositionForInlineComment,
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { GitDSL } from "../../dsl/GitDSL"
import { GitHubAPI } from "./GitHubAPI"
import { GitDSL } from "../../../dsl/GitDSL"
import { GitHubAPI } from "../GitHubAPI"
import * as debug from "debug"
import { Comment } from "../platform"
import { Comment } from "../../platform"

const d = debug("danger:GitHub::Issue")

Expand Down
9 changes: 6 additions & 3 deletions source/platforms/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,18 @@ export type Comment = {
ownedByDanger: boolean
}

export interface Platform {
export interface Platform extends PlatformCommunicator {
/** Mainly for logging and error reporting */
readonly name: string
/** Pulls in the platform specific metadata for inspection */
getPlatformDSLRepresentation: () => Promise<any>
/** Pulls in the Code Review Diff, and offers a succinct user-API for it */
getPlatformGitRepresentation: () => Promise<GitJSONDSL>
/** Get the contents of a file at a path */
getFileContents: (path: string, slug?: string, ref?: string) => Promise<string>
}

export interface PlatformCommunicator {
/** Gets inline comments for current PR */
getInlineComments: (dangerID: string) => Promise<Comment[]>
/** Can it update comments? */
Expand All @@ -57,8 +62,6 @@ export interface Platform {
updateOrCreateComment: (dangerID: string, newComment: string) => Promise<string | undefined>
/** Sets the current PR's status */
updateStatus: (passed: boolean | "pending", message: string, url?: string) => Promise<boolean>
/** Get the contents of a file at a path */
getFileContents: (path: string, slug?: string, ref?: string) => Promise<string>
}

/**
Expand Down

0 comments on commit fb39be0

Please sign in to comment.