-
-
Notifications
You must be signed in to change notification settings - Fork 371
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
Inline mode. #529
Inline mode. #529
Conversation
…e_line_api # Conflicts: # source/platforms/GitHub.ts # source/runner/Executor.ts
const dslFiles = fs.readdirSync("source/dsl").map(f => `source/dsl/${f}`) | ||
const dslFiles = fs | ||
.readdirSync("source/dsl") | ||
.filter(f => !f.startsWith("_tests")) |
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.
nice call
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.
Great progress
source/danger.d.ts
Outdated
/** Git diff chunks */ | ||
// Not sure if this is the right place for this one, but few methods needs both chunks & text diffs and I didn't want to parse two times the same file | ||
// We could rename the interface, but couldn't find a good one | ||
chunks: any[] |
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.
interesting, I wonder if the object still has the same shape with the bitbucket support
source/danger.d.ts
Outdated
} | ||
|
||
export function isInline(violation: Violation): boolean { | ||
return violation.file !== undefined || violation.line !== undefined |
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.
I wonder if outright enforcing both is probably the right call here, then you can make safe assumptions inside the inline side of the code, which is already gonna be complex
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.
I agree, this is like the first line I wrote and after the whole PR I definitely think this is a right call. Gonna fix.
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.
Fixed!
source/danger.d.ts
Outdated
|
||
/** | ||
* Adds a message to the Danger table, the only difference between this | ||
* and warn is the emoji which shows in the table. | ||
* | ||
* @param {MarkdownString} message the String to output | ||
*/ | ||
function message(message: MarkdownString): void | ||
function message(message: MarkdownString, file?: string, line?: number): void |
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.
any chance you can add the @params
- something like:
* @param {MarkdownString} message the String to output
* @param {number | undefined} file a file which this message should be attached to
* @param {number | undefined} line the line which this message should be attached to
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.
Fixed!
@@ -26,7 +25,7 @@ export interface DangerResults { | |||
/** | |||
* Markdown messages to attach at the bottom of the comment | |||
*/ | |||
markdowns: MarkdownString[] | |||
markdowns: Violation[] |
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.
yeah, I should have done that from the start - thanks
} | ||
} | ||
} | ||
Object.keys(results).forEach(violationsIntoInlineResults) |
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.
does this do something?
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.
Oh, yeah. So this line does iterate through results
keys (warnings
, fails
, messages
, markdowns
) and for each kind it generates violations for inline results and appends to a variable initialized before. This whole function is a tough one, I needed to transform DangerResults
into DangerInlineResults[]
and I couldn't find a nicer way. Basically a transformation from:
{
fails: Violation[],
warnings: Violation[],
messages: Violation[],
markdowns: Violation[]
}
to
{
file: string,
line: number,
fails: string[],
warnings: string[],
messages: string[],
markdowns: string[]
}
I'm all ears if you have something better-looking in mind 😅
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.
Ah, I guess you have to mutate the results object? Yeah, that's a bit of a toughie, maybe it just needs a comment saying what's happening
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.
Added a comment - let me know how it looks!
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.
Yep, that's good
source/runner/Executor.ts
Outdated
const inline = inlineResults(results) | ||
const inlineLeftovers = await this.sendInlineComments(inline, git) | ||
const regular = regularResults(results) | ||
const mergedResults = sortResults(mergeResults(regular, inlineLeftovers)) |
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.
great work on handling the leftovers, thought I would have this bring this up 👍
Also, @orta, I would need an advice on what should be a default behavior for inline comments after each commit. Should we delete all of them and create new ones in it's place? Should we update existing ones? Should we only remove the ones that are not present in the newest commit? Oh, and how about the template that we use for inline comments? Right now I'm using the one for main comment, but it seems kinda stacked (maybe remove headers?) |
I'm not too worried about the template for the inlines, every time I've seen someone use it, it's been with However, a smaller version could just be a markdown list instead:
I'd be fine with it skipping the "posted by danger" too. So you could definitely improve that. |
Re: comments, yeah, ideally edit, I know it's a bunch of work but it triggers a lot of emails when comments are deleted and re-created. Perhaps you could extend the current danger-id to include file and line per message. This means lookups in the existing comments list should be pretty simple:
|
@orta that's a great point, didn't think about the emails. It's gonna take more time, but I think it's worth the cause. Oh, and found a few secs to update the inline comment template with tests. Simple bullet points are even better than a table with rows, should look much cleaner. Edit: Forgot about BitbucketServer comments, gonna add them as well in a few (even though we won't support it in the beginning, no problem adding a core prepared for implementing api endpoints) Edit2: BitbucketServer inline comments template added as well |
@orta I think I’m kinda satisfied with it, should be ready for the final check. I refactored The only thing I’m not sure about is that passing I would also love some help with docs, not sure where to even start 😅
Update: I've tested it on Harvey, as the problem was fixed a few minutes ago, and it seems like removing/updating comments is working correctly! 🎉 |
OK, this is cool - I'll handle all the docs side, but I'm on a deadline (for tomorrow) so will take a serious look at the weekend and update this PR. 👍 Awesome |
let processName = subprocessName[0] | ||
let args = subprocessName | ||
let results = {} as any | ||
args.shift() // mutate and remove the first element | ||
|
||
const processDisplayName = path.basename(processName) | ||
const dslJSONString = prepareDangerDSL(dslJSON) | ||
d(`Running subprocess: ${processDisplayName} - ${args}`) |
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.
cool, - this makes sense!
source/danger.d.ts
Outdated
markdowns: string[] | ||
} | ||
|
||
export const emptyDangerResults = { |
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.
These are in the danger.d.ts - will need to remove these for prod
source/platforms/github/GitHubAPI.ts
Outdated
const prID = this.repoMetadata.pullRequestID | ||
return await this.getAllOfResource(`repos/${repo}/pulls/${prID}/comments`).then(v => { | ||
return v.map((i: any) => { | ||
return { id: i.id, ownedByDanger: i.user.id == userID, body: i.body } |
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.
I think this will want to also have a danger-id check (could be reasonable to imagine many dangers posting inline)
source/runner/Executor.ts
Outdated
@@ -162,7 +181,8 @@ export class Executor { | |||
* | |||
* @param {DangerResults} results a JSON representation of the end-state for a Danger run | |||
*/ | |||
async handleResultsPostingToPlatform(results: DangerResults) { | |||
// TODO: Instead of danger, pass gitDSL |
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.
this got did - I think?
resolve(dangerResults.reduce((acc, r) => mergeResults(acc, r), emptyDangerResults)) | ||
}) | ||
}) | ||
} |
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.
this is some 👍 code
expect(platform.updateInlineComment).not.toBeCalled() | ||
expect(platform.createInlineComment).toHaveBeenCalledTimes(2) | ||
expect(platform.deleteInlineComment).toHaveBeenCalledTimes(2) | ||
}) |
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.
solid tests
${results.messages.map(printViolation("book"))} | ||
${results.markdowns.map(v => v.message).join("\n\n")} | ||
` | ||
} |
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.
Yep
Conceptually, this is basically good to go 👍 ! Code-wise and architecture-wise I'm happy, but I've run out of time this evening and haven't managed to successfully get an inline message to appear. So good in theory, but doesn't look to be fully hooked up in practice yet. I'm reasonably sure that my changes won't have broke it anyway 👯♂️ |
Okay, I'm investigating. Added logging to the PR, gonna remove it after the investigation.
@orta found the issue, fixed it, fixed tests. Basically this one. When creating a new |
Yeah, the case of different repo is particularly common for my projects as I nearly always do same-repo PRs 👍 |
Going to give it one more audit, then I'll get this shipped |
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.
Heh, this sneaked in an extra root export: Fixed with a49c379 |
@orta I just figured out what you meant with the emoji and it's awesome 😄 |
(Because this is basing off of #516, I'm currently targeting it's branch to see actual changes, when it's merged I'm gonna switch it back)Live demo: Harvey#17
Todo: