Add annotation @BehaviorChangeSince for behavior-change flags#1170
Add annotation @BehaviorChangeSince for behavior-change flags#1170eric-maynard wants to merge 14 commits intoapache:mainfrom
Conversation
polaris-core/src/main/java/org/apache/polaris/core/config/BehaviorChangeConfigurationSince.java
Outdated
Show resolved
Hide resolved
polaris-core/src/main/java/org/apache/polaris/core/config/BehaviorChangeConfiguration.java
Outdated
Show resolved
Hide resolved
polaris-core/src/main/java/org/apache/polaris/core/config/BehaviorChangeConfiguration.java
Show resolved
Hide resolved
| import java.lang.annotation.Target; | ||
|
|
||
| /** | ||
| * An annotation that should be applied to all BehaviorChangeConfiguration instances. The value here |
There was a problem hiding this comment.
Should we add validation for that to the spotless check too?
There was a problem hiding this comment.
Definitely. I looked into this a bit, but it seems like the "best" way would be via reflection (enumerating all instances of the BehaviorChangeConfiguration type) which feels hacky. At the very least, let me add a check so that no configs are created outside of the correct file.
There was a problem hiding this comment.
That can be done in a compile-time annotation processor (I think it has access to all elements, even if not annotated).
There was a problem hiding this comment.
Awesome, I'll look into that and update the PR. For now, I added a lint check to try and make sure the flags are contained within the one file.
There was a problem hiding this comment.
After some research, I have one doubt about the above approach. If we want to scan for BehaviorChangeConfiguration instances without the annotation, is an annotation processor really the right choice? I am wondering if this, too, needs to be done in the linter.
There was a problem hiding this comment.
Cross references are inevitable. For example, immutables generate code from annotations that is referenced by some other hand-written classes. @Overrides annotations relate to base classes, which do not have the annotation itself. I think it is quite normal for annotation processors to "look around" in the codebase.
By the way, the immutables lib can be a source of inspiration here, I guess 😉
There was a problem hiding this comment.
I tried adding a processor BehaviorChangeProcessor and registering it, but I don't think it actually runs based on my testing. If you're able to take a look and you see a problem, please do let me know
polaris-core/src/main/java/org/apache/polaris/core/config/BehaviorChangeConfigurationSince.java
Outdated
Show resolved
Hide resolved
| super(key, description, defaultValue, catalogConfig); | ||
| } | ||
|
|
||
| @BehaviorChangeConfigurationSince("1.0.0") |
There was a problem hiding this comment.
We need to coordinate setting this value with the new 0.10.0 release proposal: https://lists.apache.org/thread/8kc7xq3lp6pcc2w3jon3fv8qfxj3v9lk
There was a problem hiding this comment.
We need to fix the versions.txt to point to the actual version of the code, I think. These values should be set to whatever is there. Currently, that's 1.0.0
| */ | ||
| @Target(ElementType.FIELD) | ||
| @Retention(RetentionPolicy.RUNTIME) | ||
| public @interface BehaviorChangeConfigurationSince { |
There was a problem hiding this comment.
Side note: it would be great to consider this annotation in tools/config-docs/generator
There was a problem hiding this comment.
Do you mean to move it there?
There was a problem hiding this comment.
No, I mean auto-generated config docs should ideally consider this annotation
There was a problem hiding this comment.
I see, I've looked through the generator package but I'm not sure I fully understand what it would mean for the docs to consider the annotation. I guess the idea would be to have the docs about each BehaviorChangeConfiguration describe what version the configuration was created in, etc.? In fact, I don't know if we even want to document the BehaviorChangeConfigurations
There was a problem hiding this comment.
I believe, in an open source project all config that a user may want to change should be documented... but we can leave BehaviorChangeConfigurations for later, of course.
|
|
||
| override fun apply(input: String): String { | ||
| val versionRegex = | ||
| """@BehaviorChangeScope\s*\(\s*since\s*=\s*"(\d+\.\d+\.\d+)"(?:\s*,\s*expires\s*=\s*"(\d+\.\d+\.\d+)")?\s*\)""" |
There was a problem hiding this comment.
Will it work if the annotation is split across multiple lines?
There was a problem hiding this comment.
It more or less should work because of all the \s* -- but agreed that a lint check is relatively brittle here. We can always add another check later though
| val (majorA, minorA, patchA) = annotatedVersion.split(".").map { it.toInt() } | ||
| if (expiresVersion == null) { | ||
| val (majorB, minorB, _) = polarisVersion.split(".").map { it.toInt() } | ||
| return (majorB > majorA || (majorB == majorA && minorB > minorA + 1)) |
There was a problem hiding this comment.
Is it possible to have only on place for comparing versions, but derive the "expires" version from the "added" version automatically?
There was a problem hiding this comment.
I updated the PR to try this, but the logic might be less intuitive at first glance. Let me know what you think!
polaris-core/src/main/java/org/apache/polaris/core/config/BehaviorChangeConfiguration.java
Show resolved
Hide resolved
| Diagnostic.Kind.NOTE, | ||
| "Field " | ||
| + field.getSimpleName() | ||
| + " is correctly annotated with @BehaviorChange", |
There was a problem hiding this comment.
I think it's not, but I noticed the processor isn't working so I added this to debug -- see my comment here. If you have any tips on fixing this, that would be awesome. I think the annotation processor is a good suggestion
| public class BehaviorChangeProcessor extends AbstractProcessor { | ||
|
|
||
| @Override | ||
| public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { |
There was a problem hiding this comment.
Would it be possible to move version/expiry checks here? It think it would be nicer from the overall design POV.
Build scripts could probably inject "current version" into system properties. WDYT?
There was a problem hiding this comment.
I really prefer to do things like this in a linter. We can always do it in both, too.
There was a problem hiding this comment.
having both looks awkward to me... I'd prefer to move the logic and keep only one of them (up to you which one).
|
@eric-maynard : how about converting built-time checks to unit tests? I believe tests can scan pre-compiled classes for annotations and verity that all required constants are annotated. Also we can probably inject the current version number from gradle and validate expiry... as for me it looks simpler and easier to debug that build-time checks... WDYT? |
|
Good idea @dimas-b, I will try to do just that. Putting the PR in draft for now |
|
This PR is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 5 days. |
#1124 introduces "behavior change" flags, which are intended to guard contentious or risky behavior changes and to be removed after a short time. This PR codifies that intention by adding a new spotless rule
checkStaleBehaviorChangeFlagsthat will fail duringformatwhen a behavior change flag is detected to have been around for more than 2 minor release or for more than 1 major release.