1
+ /*
2
+ * Copyright 2002-2019 the original author or authors.
3
+ *
4
+ * Licensed under the Apache License, Version 2.0 (the "License");
5
+ * you may not use this file except in compliance with the License.
6
+ * You may obtain a copy of the License at
7
+ *
8
+ * https://www.apache.org/licenses/LICENSE-2.0
9
+ *
10
+ * Unless required by applicable law or agreed to in writing, software
11
+ * distributed under the License is distributed on an "AS IS" BASIS,
12
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ * See the License for the specific language governing permissions and
14
+ * limitations under the License.
15
+ */
16
+ package org .springframework .build .api ;
17
+
18
+ import java .io .File ;
19
+ import java .nio .file .Path ;
20
+ import java .nio .file .Paths ;
21
+ import java .util .Collections ;
22
+ import java .util .List ;
23
+
24
+ import me .champeau .gradle .japicmp .JapicmpPlugin ;
25
+ import me .champeau .gradle .japicmp .JapicmpTask ;
26
+ import org .gradle .api .Plugin ;
27
+ import org .gradle .api .Project ;
28
+ import org .gradle .api .artifacts .Configuration ;
29
+ import org .gradle .api .artifacts .Dependency ;
30
+ import org .gradle .api .plugins .JavaBasePlugin ;
31
+ import org .gradle .api .plugins .JavaPlugin ;
32
+ import org .gradle .api .tasks .TaskProvider ;
33
+ import org .gradle .jvm .tasks .Jar ;
34
+
35
+ /**
36
+ * {@link Plugin} that applies the {@code "japicmp-gradle-plugin"}
37
+ * and create tasks for all subprojects, diffing the public API one by one
38
+ * and creating the reports in {@code "build/reports/api-diff/$OLDVERSION_to_$NEWVERSION/"}.
39
+ * <p>{@code "./gradlew apiDiff -PbaselineVersion=5.1.0.RELEASE"} will output the
40
+ * reports for the API diff between the baseline version and the current one for all modules.
41
+ * You can limit the report to a single module with
42
+ * {@code "./gradlew :spring-core:apiDiff -PbaselineVersion=5.1.0.RELEASE"}.
43
+ *
44
+ * @author Brian Clozel
45
+ */
46
+ public class ApiDiffPlugin implements Plugin <Project > {
47
+
48
+ public static final String TASK_NAME = "apiDiff" ;
49
+
50
+ private static final String BASELINE_VERSION_PROPERTY = "baselineVersion" ;
51
+
52
+ private static final List <String > PACKAGE_INCLUDES = Collections .singletonList ("org.springframework.*" );
53
+
54
+ @ Override
55
+ public void apply (Project project ) {
56
+ if (project .hasProperty (BASELINE_VERSION_PROPERTY ) && project .equals (project .getRootProject ())) {
57
+ project .getPluginManager ().apply (JapicmpPlugin .class );
58
+ project .getPlugins ().withType (JapicmpPlugin .class ,
59
+ plugin -> applyApiDiffConventions (project ));
60
+ }
61
+ }
62
+
63
+ private void applyApiDiffConventions (Project project ) {
64
+ String baselineVersion = project .property (BASELINE_VERSION_PROPERTY ).toString ();
65
+ project .subprojects (subProject -> createApiDiffTask (baselineVersion , subProject ));
66
+ }
67
+
68
+ private void createApiDiffTask (String baselineVersion , Project project ) {
69
+ if (isProjectEligible (project )) {
70
+ JapicmpTask apiDiff = project .getTasks ().create (TASK_NAME , JapicmpTask .class );
71
+ apiDiff .setDescription ("Generates an API diff report with japicmp" );
72
+ apiDiff .setGroup (JavaBasePlugin .DOCUMENTATION_GROUP );
73
+
74
+ apiDiff .setOldClasspath (project .files (createBaselineConfiguration (baselineVersion , project )));
75
+ TaskProvider <Jar > jar = project .getTasks ().withType (Jar .class ).named ("jar" );
76
+ apiDiff .setNewArchives (project .getLayout ().files (jar .get ().getArchiveFile ().get ().getAsFile ()));
77
+ apiDiff .setNewClasspath (getRuntimeClassPath (project ));
78
+ apiDiff .setPackageIncludes (PACKAGE_INCLUDES );
79
+ apiDiff .setOnlyModified (true );
80
+ apiDiff .setIgnoreMissingClasses (true );
81
+ // Ignore Kotlin metadata annotations since they contain
82
+ // illegal HTML characters and fail the report generation
83
+ apiDiff .setAnnotationExcludes (Collections .singletonList ("@kotlin.Metadata" ));
84
+
85
+ apiDiff .setHtmlOutputFile (getOutputFile (baselineVersion , project ));
86
+
87
+ apiDiff .dependsOn (project .getTasks ().getByName ("jar" ));
88
+ }
89
+ }
90
+
91
+ private boolean isProjectEligible (Project project ) {
92
+ return project .getPlugins ().hasPlugin (JavaPlugin .class )
93
+ && !project .getName ().equals ("spring-core-coroutines" )
94
+ && !project .getName ().equals ("spring-framework-bom" );
95
+ }
96
+
97
+ private Configuration createBaselineConfiguration (String baselineVersion , Project project ) {
98
+ String baseline = String .join (":" ,
99
+ project .getGroup ().toString (), project .getName (), baselineVersion );
100
+ Dependency baselineDependency = project .getDependencies ().create (baseline + "@jar" );
101
+ return project .getRootProject ().getConfigurations ().detachedConfiguration (baselineDependency );
102
+ }
103
+
104
+ private Configuration getRuntimeClassPath (Project project ) {
105
+ return project .getConfigurations ().getByName (JavaPlugin .RUNTIME_CLASSPATH_CONFIGURATION_NAME );
106
+ }
107
+
108
+ private File getOutputFile (String baseLineVersion , Project project ) {
109
+ Path outDir = Paths .get (project .getRootProject ().getBuildDir ().getAbsolutePath (),
110
+ "reports" , "api-diff" ,
111
+ baseLineVersion + "_to_" + project .getRootProject ().getVersion ());
112
+ return project .file (outDir .resolve (project .getName () + ".html" ).toString ());
113
+ }
114
+
115
+ }
0 commit comments