-
Notifications
You must be signed in to change notification settings - Fork 14
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
Facilitate using the plugin for custom reports #121
base: main
Are you sure you want to change the base?
Conversation
It provides a DependencyCheck.Reporter, which enables passing an arbitrary compatibility intention and previous module IDs, while still computing everything else from SBT. Then, versionPolicyFindDependencyIssues is refactored to use versionPolicyDependencyIssuesReporter, and only supply the compatibility intention and previous module IDs to it, based on SBT settings as before.
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.
Thank you for the PR @nafg !
I wonder why versionPolicyFindDependencyIssues
is not enough?
I believe what we should do is to introduce new tasks similar to what versionPolicyFindDependencyIssues
is to versionPolicyReportDependencyIssues
, but for the tasks versionPolicyMimaCheck
and versionPolicyCheck
. They could be named versionPolicyFindMimaIssues
, and versionPolicyFindIssues
, for instance?
Sorry if I wasn't clear. The goal is to be able to choose the mode on the fly. That is, If it already does that then I really missed the boat somehow. In that case I only need the If doesn't, but it's possible to refactor things so that I'm not sure I remember 100% why I wanted to expose the previous artifacts logic so I could specify it explicitly in my code. I can revisit whether that's really necessary. |
That would be nice to do, but it doesn't address the goal of this PR. Maybe the title of the PR is unclear (I just edited it but still), since it is broken into a few distinct commits, each of which could in theory be their own PR (but they all work towards the same goal). The commit messages explain better, perhaps. For instance, here's a relevant one:
I think in a way this comes back to what I said elsewhere, that providing functionality in an SBT-coupled way is very limiting. SBT is basically a functionally-implemented runtime (task engine) with an immutable AST (tasks and settings) for a language that strongly encourages global mutable state. The fact that the behavior of This is not a criticism of sbt-version-policy at all. It's the "default" that SBT effectively encourages. It definitely takes more work to do things differently. I'm just sharing how I see the thing that I'm struggling to achieve as part of a bigger picture. My solution was to introduce a "named partially applied function" -- that is, you get an object with some of the parameters filled out, and you can then pass in the rest yourself. I could have just make the I guess in a sense, in the context of an SBT plugin, settings can be divided into two categories. There are some which are a mechanism for introspecting the build (predefined settings), and some which are the knobs and levers for controlling the behavior of the plugin. Perhaps a pattern which could be helpful in general for plugins to solve this sort of issue, is to define two case classes, each of which combines the setting values of the respective category. Instances of these case classes would themselves be a convenience IOW, // A plugin
case class SbtInfoNeedByThisPlugin(x...)
case class PluginParams(...)
def taskImpl(sbtInfoNeedByThisPlugin: SbtInfoNeedByThisPlugin, params: PluginParams) = ???
...
sbtInfoNeedByThisPlugin := {
val x = xSetting.value
...
SbtInfoNeedByThisPlugin(x, ...)
},
pluginParams := ...,
task := {
taskImpl(sbtInfoNeedByThisPlugin.value, pluginParams.value)
}
// User build that wants to use `taskImpl` with different `PluginParams` than specified in the build
taskImpl(sbtInfoNeedByThisPlugin.value, pluginParams.value.copy(...)) Just a random thought... |
Maybe I should just forget this whole thing and accept that SBT's solution to "global state" is configurations and stick to my original version of the Slick PR which has to introduce a new configuration... |
A use case for specifying the artifacts or version on the fly is e.g. if I want to find out how a PR compares to its merge base. For example maybe I want to automatically label all the PRs that contain breaking changes. There can be many PRs in a breaking release, some of which don't contain breaking changes but running mima against the last release would indicate that breaking changes were found, but that doesn't tell me if there are breaking changes within the PR itself. |
Thank you for the thorough explanation. Now it’s clearer to me.
I agree. I would need more time to think about a better way to work with the design of sbt… I think the approach you found (with a separate config) is interesting. I don’t think we should merge your “reporter” proposal for now, however I am happy to add |
Are you saying that none of the 3 commits in this PR (not counting the one that updates versionPolicyIntetion) are changes you are willing to accept? Any of them individually would be helpful to me (and I believe a lot of people too, once they realize they no longer have to use mima filters as a crutch and that automatically generating the list of breaking changes in a breaking release is possible). Could you at least share why you reject them? |
@nafg Actually I am not sure. I agree that it would be very useful to expose the functionality of this sbt-plugin in a way that can be used outside of the usual sbt builds (including alternative build tools). I think we need to think a little bit about how to do it well.
Here, how would you classify the settings of sbt-version-policy? |
Now I'm worried that my philosophical "rant" made the objective of this PR, less clear, not more :( The goal of this PR has nothing to do with that. I only lamented that if SBT didn't encourage a very SBT-specific (global-state-like) way of doing things, this PR wouldn't even be necessary. But other than that "how to make this build-tool agnostic" is a distraction from the goal here, and I'm sorry for causing confusion.
I guess I was unclear again. :( If you look at the code of Then there are settings that the plugin defines, in its own What 7dc19ac does is to let you keep the "global" (within the SBT scope of course, but that's the one we're in) settings in place, and still give other queries (other intents and/or artifacts) on the fly (as parameters in code, not by what's effectively the side effect of reading mutable state set elsewhere). So I could define one custom task to get all changes since the last release by passing in BinaryAndSourceCompatible, and another custom task to check the breakingness of a single commit or PR by passing in custom artifacts, without needing something "outside" the task to set settings to different values with whatever ramifications that has. The other commits are just making some "business logic" available directly. |
Do you feel that any of these changes degrade the codebase quality? Or are you worried about the cost of maintaining additional public APIs? Or do you have some other concern? |
My main concern is maintaining additional public APIs. I think I understood well your goal, maybe I didn’t express myself clearly :) I think it would indeed be useful to be able to get an incompatibility report independent of an sbt build, not only to support alternative build tools, but also to produce incompatibilitiy logs like you would like to do. I both cases, we want to be able to call the logic of versionPolicyCheck with different parameters than those defined in an sbt build (at least some of them, not all of them, as you noticed). |
Ok so what's the plan? If I merge the Slick PR with the inelegant separate-SBT-configuration solution, I will feel a tiny bit disappointed but then probably have higher priorities than following up on this at all. Or I could leave it open, if there is a solution that can happen soon, and then update the PR to use it. Should I wait for something better to happen, or should I give up on this effort altogether?
Does that mean you don't feel my use case justifies additional APIs, or do you mean that these additional APIs aren't polished enough to go in? If the latter is there anything you would accept short of the huge refactor that we touched on? |
I would like to take a bit more time to think about it.
The latter. I think your use case makes a lot of sense, and we should support it in sbt-version-policy. I just need more time to think about it. |
Ok thanks. I'll leave the Slick PR open and work on other things meanwhile, until I hear an update on this (or it becomes necessary to move forward without this) |
Hi any update? |
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.
Hey, sorry for being silent for so long!
I am interested in merging this feature. Overall, I think the design is good, I have left minor comments.
Do you mind adding a bit more documentation in the code, and using more self-explanatory identifiers? (I know this is currently not the case everywhere but I would like to enforce this convention going forward)
Also, would you be interested in adding some documentation in the README?
Should we have something similar to report binary and source incompatibilities, BTW?
@@ -27,7 +27,7 @@ object SbtVersionPolicyMima extends AutoPlugin { | |||
private def moduleName(m: ModuleID, sv: String, sbv: String): String = | |||
moduleName(m.crossVersion, sv, sbv, m.name) | |||
|
|||
private lazy val previousVersionsFromRepo = Def.setting { | |||
lazy val previousVersionsFromRepo = Def.setting { |
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.
lazy val previousVersionsFromRepo = Def.setting { | |
private[sbtversionpolicy] lazy val previousVersionsFromRepo = Def.setting { |
versionPolicyPreviousArtifacts := versionPolicyPreviousArtifactsFromMima.value | ||
) | ||
|
||
def fromMimaArtifacts(artifacts: Set[sbt.ModuleID]) = { |
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.
def fromMimaArtifacts(artifacts: Set[sbt.ModuleID]) = { | |
private def fromMimaArtifacts(artifacts: Set[sbt.ModuleID]) = { |
currentDependencies: Map[(String, String), String], | ||
reconciliations: Seq[(ModuleMatchers, VersionCompatibility)], | ||
defaultReconciliation: VersionCompatibility, | ||
sv: String, |
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.
sv: String, | |
scalaVersion: String, |
sbt-version-policy/src/main/scala/sbtversionpolicy/internal/DependencyCheck.scala
Outdated
Show resolved
Hide resolved
@@ -75,6 +75,47 @@ object DependencyCheck { | |||
log | |||
) | |||
|
|||
class Reporter( |
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.
Would you mind adding some documentation?
…pendencyCheck.scala Co-authored-by: Julien Richard-Foy <[email protected]>
Hi I probably won't be able to look into this until after Passover. Also at this point I would have to rewrite the code in Slick in tandem. I will try to remember to do it then. |
Dale recently merged and released the PR that I opened in sbt-mima for that purpose If you have a vision of a more unified API go for it... |
FTR, we added several features that will facilitate the generation of compatibility reports, especially the task sbt-version-policy/sbt-version-policy/src/main/scala/sbtversionpolicy/CompatibilityReport.scala Lines 56 to 57 in 9cc7721
|
See #119
I think to avoid needing a special SBT configuration I would need to make similar changes in sbt-mima :(
But so far this PR enables the following diff to the Slick PR (again, see #119):