-
Notifications
You must be signed in to change notification settings - Fork 28
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
Add pipeline support #7
Conversation
Codecov Report
@@ Coverage Diff @@
## master #7 +/- ##
============================================
+ Coverage 83.33% 90.87% +7.54%
- Complexity 49 69 +20
============================================
Files 10 11 +1
Lines 210 274 +64
Branches 6 6
============================================
+ Hits 175 249 +74
+ Misses 35 23 -12
- Partials 0 2 +2
Continue to review full report at Codecov.
|
private final String rawDetails; | ||
@SuppressFBWarnings(value = "NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR", | ||
justification = "Empty constructor used by stapler") | ||
public class ChecksAnnotation extends AbstractDescribableImpl<ChecksAnnotation> implements Serializable { |
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.
Is it worth separating our pipeline models from our API models?
So that they don't get polluted with all the setters etc required by stapler?
private ChecksConclusion conclusion; | ||
private LocalDateTime startedAt = LocalDateTime.now(); | ||
private LocalDateTime completedAt = LocalDateTime.now(); | ||
private ChecksOutput output; |
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 really think we should flatten this down so that users don't have to do:
publishChecks(
name: "check",
detailsURL: "ci.jenkins.io",
status: "COMPLETED",
conclusion: "SUCCESS",
output: [
title: "output",
summary: "summary",
text: "text",
annotations: [
[path: "src/main/foo.java", startLine: 0, endLine: 0, annotationLevel: "WARNING", message: "foo test"],
[path: "src/main/bar.java", startLine: 1, endLine: 1, annotationLevel: "WARNING", message: "bar test"]
],
images: [
[alt: "foo alt", imageUrl: "foo url", caption: "foo image"],
[alt: "foo alt", imageUrl: "foo url", caption: "foo image"]
]
],
)
instead a simple usage would be;
publishChecks(
name: "MyCheck",
conclusion: "success",
summary: "Everything is OK!"
)
i.e. it would be good to start from a users perspective, and look at some scenarios of what they want to use it for.
Most users probably won't user annotations / images
They will just want to set a status, with some messaging I would expect
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 didn't consider the user scenarios and afraid too many fields will explode this class, so just flattened the first level checks ChecksDetails
.
After your example, one pipeline usage I can come up with now is that users may want to publish checks to more precisely indicate the stages (especially for their customized ones).
For now, I think it's ok we do not need to provide annotations and images, but I think it would be better to provide a new |
Hmm not sure if actions is too useful it sends a webhook event to the app, and in order to do anything with it you need a Jenkins plugin... |
But we'll need to handle the webhook event for the re-run request anyway, there is a identifier for each kind of action, so we can tell the users to use the re-run identifier if they want to add the action. |
if there's nothing we can do about the webhook event we'd just have to ignore it. We could have another step which is wait for github checks event, where you pass the identifier and we attach a pauseaction to the build... but that's more than a v1, I would add than in a follow up, if we could get an MVP first that would be great |
Joining the discussion here via Gitter, I'll briefly summarize some of the stuff I ran into since posting on JENKINS-51225.
Our implementation of this is centered around uploading annotations in the structure that GitHub expects; this general-purpose function enforces the naming (PR or not PR) and prioritization of annotations based on source file and severity. We then have a supplementary set of functions to translate from common report formats (eslint, rubocop, hadolint, etc) into GitHub format -- each of which accepts a closure for adjusting the severity of an annotation entry. With that, we have everything we need to support a lot of interesting use cases. So with that said, I really like the flexibility being proposed here: publishChecks(
name: "check",
detailsURL: "ci.jenkins.io",
status: "COMPLETED",
conclusion: "SUCCESS",
output: [
title: "output",
summary: "summary",
text: "text",
annotations: [
[path: "src/main/foo.java", startLine: 0, endLine: 0, annotationLevel: "WARNING", message: "foo test"],
[path: "src/main/bar.java", startLine: 1, endLine: 1, annotationLevel: "WARNING", message: "bar test"]
],
images: [
[alt: "foo alt", imageUrl: "foo url", caption: "foo image"],
[alt: "foo alt", imageUrl: "foo url", caption: "foo image"]
]
],
) Although the Sorry this was long, and I accept in advance that my use cases very likely don't represent "most users" 😄 Ask me anything about how this is working for our team so far! |
@ianfixes Thanks for sharing the issues you met on your implementation and feedback very much! 👏 Many of your problems we have met as well, here are some of our solutions we implemented: For the true commit of PR, our implementation is based on GitHub Branch Source Plugin which is an implementation of the Branch API, so resolving the true commit of PR isn't a hard problem after that. For the limit of annotations, our depending library did that for us: https://github.com/hub4j/github-api/blob/master/src/main/java/org/kohsuke/github/GHCheckRunBuilder.java#L138 For test and static warnings report, we have implemented the consumers in other plugins, you can find them in our blog post: https://www.jenkins.io/blog/2020/08/03/github-checks-api-plugin-coding-phase-2/. We only reported the new issues of the PR comparing with the target branch, so resolving the problem about "files that were not actually part of the pull request". |
Thanks XiongKezhi! I figured that you would have run into a few of these and resolved them. After thinking about it, I like the idea of this syntax: // specify everything manually
publishChecks(
name: "my check",
conclusion: "SUCCESS",
output: [
title: "output",
summary: "summary",
text: "text",
annotations: [
[path: "src/main/foo.java", startLine: 0, endLine: 0, annotationLevel: "WARNING", message: "foo test"],
[path: "src/main/bar.java", startLine: 1, endLine: 1, annotationLevel: "WARNING", message: "bar test"]
],
images: [
[alt: "foo alt", imageUrl: "foo url", caption: "foo image"],
[alt: "foo alt", imageUrl: "foo url", caption: "foo image"]
]
]
) Or for using a built-in converter/tool to read a report from a different format (if I'm reading the page you referred to correctly): // "formatIssues" style borrowed from "recordIssues"
publishChecks(
name: "my check",
conclusion: "SUCCESS",
output: formatIssues(tools: [checkStyle(pattern: 'target/checkstyle-result.xml'),
spotBugs(pattern: 'target/spotbugsXml.xml'),
pmdParser(pattern: 'target/pmd.xml'),
cpd(pattern: 'target/cpd.xml')],
qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]])
)
|
@ianfixes Is there any reason that you don't want to use warnings-ng to help publish tool reports but want to convert them by hand? |
Strange, the PR passes my local tests while the CI says
And there is no line#79 at all in |
Perhaps the biggest reason is that we've found working with plugins to be terrible, especially for scripted pipeline. (We have to wait for 3rd parties to fix bugs or implement issues, the experience may not work in Blue Ocean, there is no guarantee that the plugin won't be abandoned, etc). And in many cases, the functionality is trivial enough for us to just implement ourselves in a script library -- such that we have full control over it. So the tendency is to choose plugins that "do one thing and do it well", then wrap them to suit our needs. In the case of publishing reports specifically, as I mentioned above sometimes we want to adjust the severity of the annotations that a tool provides. For example, we may want to soft-launch some style guidelines such that the errors are reduced to warnings for some grace period. Or we want to test out a proposed linting tool, in much the same way. Or we want an ability to introduce our own logic to mute certain errors. Our feeling is that the tools are there to help us, and not the other way around. So we leave room to tailor the reports to our own needs. |
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 it would help if we add the help texts (and the Snippet Generator configuration).
I think it would be also helpful to have a real integration test that creates a sample pipeline using the step. Then we can see in the console log if the null publisher is correctly invoked in the API plugin.
Examples: https://github.com/jenkinsci/warnings-ng-plugin/blob/master/plugin/src/test/java/io/jenkins/plugins/analysis/warnings/steps/StepsITest.java
(If this is too much work for now we can also add such a test to the GitHub checks plugin).
} | ||
|
||
@DataBoundSetter | ||
public void setTitle(final String title) { |
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 it would make sense to add config.jelly
and *-help.html
files for the fields (you already have the text in the JavaDoc of the ChecksOutput
classes). Then the online documentation (Snippet Generator and Online Reference) has some more details. You can open the Snippet Generator using the "Pipeline Syntax" link on a job page.
@NonNull | ||
@Override | ||
public String getDisplayName() { // it's pipeline step, so where does the name shown? | ||
return "Publish customized checks to SCM platforms"; |
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.
The text is shown in the Snippet Generator and Online Reference (and should be part of Messages)
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.
Optional (since we have no I18n yet in the whole project): it would make sense to create a Messages.properties
file and add all UI labels (example: https://github.com/jenkinsci/forensics-api-plugin/blob/master/src/main/resources/io/jenkins/plugins/forensics/miner/Messages.properties). Then you can replace these strings with the constant in the generated Messages
class (example: https://github.com/jenkinsci/forensics-api-plugin/blob/master/src/main/java/io/jenkins/plugins/forensics/miner/ForensicsJobAction.java#L34).
But we can postpone that part to the after GSoC work.
src/main/java/io/jenkins/plugins/checks/steps/PublishChecksStep.java
Outdated
Show resolved
Hide resolved
src/test/java/io/jenkins/plugins/checks/steps/PublishChecksStepTest.java
Outdated
Show resolved
Hide resolved
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.
Looks good to me! Just some minor things.
src/main/java/io/jenkins/plugins/checks/steps/PublishChecksStep.java
Outdated
Show resolved
Hide resolved
@NonNull | ||
@Override | ||
public String getDisplayName() { // it's pipeline step, so where does the name shown? | ||
return "Publish customized checks to SCM platforms"; |
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.
Optional (since we have no I18n yet in the whole project): it would make sense to create a Messages.properties
file and add all UI labels (example: https://github.com/jenkinsci/forensics-api-plugin/blob/master/src/main/resources/io/jenkins/plugins/forensics/miner/Messages.properties). Then you can replace these strings with the constant in the generated Messages
class (example: https://github.com/jenkinsci/forensics-api-plugin/blob/master/src/main/java/io/jenkins/plugins/forensics/miner/ForensicsJobAction.java#L34).
But we can postpone that part to the after GSoC work.
src/main/resources/io/jenkins/plugins/checks/steps/PublishChecksStep/conclusion.html
Outdated
Show resolved
Hide resolved
src/main/resources/io/jenkins/plugins/checks/steps/PublishChecksStep/status.html
Outdated
Show resolved
Hide resolved
…s/cache-v2.1.0 Bump actions/cache from v1 to v2.1.0
Target pipeline: