-
Notifications
You must be signed in to change notification settings - Fork 626
add gradle tasks for metalava generation #671
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
Changes from 8 commits
8016d4b
48acad3
b68fd6b
a46fa94
1e291b6
393cb67
13279dd
af8901c
1e6c7ac
9023cd7
c998f48
6be28ef
6d334a9
82e2fe4
d8ed638
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,12 +15,19 @@ | |
package com.google.firebase.gradle.plugins; | ||
|
||
import com.android.build.gradle.LibraryExtension; | ||
import com.android.build.gradle.api.AndroidSourceSet; | ||
import com.google.common.collect.ImmutableList; | ||
import com.google.common.collect.ImmutableMap; | ||
import com.google.firebase.gradle.plugins.apiinfo.GenerateApiTxtFileTask; | ||
import com.google.firebase.gradle.plugins.apiinfo.ApiInformationTask; | ||
import com.google.firebase.gradle.plugins.ci.device.FirebaseTestServer; | ||
|
||
import org.gradle.api.Plugin; | ||
import org.gradle.api.Project; | ||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile; | ||
import java.io.File; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public class FirebaseLibraryPlugin implements Plugin<Project> { | ||
|
||
|
@@ -54,6 +61,40 @@ public void apply(Project project) { | |
} | ||
}); | ||
} | ||
if (System.getenv().containsKey("METALAVA_BINARY_PATH")) { | ||
String METALAVA_BINARY_PATH = System.getenv("METALAVA_BINARY_PATH"); | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
AndroidSourceSet mainSourceSet = android.getSourceSets().getByName("main"); | ||
List<String> sourcePaths = new ArrayList<>(); | ||
for (File directory : mainSourceSet.getJava().getSrcDirs()) { | ||
sourcePaths.add(directory.getAbsolutePath()); | ||
} | ||
String sourcePathArgument = String.join(",", sourcePaths); | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
project.getTasks().create("apiInformation", ApiInformationTask.class, task -> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You should prefer |
||
task.setProperty("apiTxt", project.getProjectDir() + "/api.txt"); | ||
task.setProperty("metalavaBinaryPath", METALAVA_BINARY_PATH); | ||
task.setProperty("sourcePath", sourcePathArgument); | ||
task.setProperty("outputPath", project.getRootProject().getBuildDir() + "/apiinfo/subproject" + project.getPath()); | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
task.setProperty("baselinePath", project.getProjectDir() + "/baseline.txt"); | ||
if (project.hasProperty("updateBaseline")) { | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
task.setProperty("updateBaseline", true); | ||
} else { | ||
task.setProperty("updateBaseline", false); | ||
} | ||
}); | ||
|
||
project.getTasks().create("generateApiTxtFile", GenerateApiTxtFileTask.class, task -> { | ||
task.setProperty("apiTxt", project.getProjectDir() + "/api.txt"); | ||
task.setProperty("metalavaBinaryPath", METALAVA_BINARY_PATH); | ||
task.setProperty("sourcePath", sourcePathArgument); | ||
task.setProperty("baselinePath", project.getProjectDir() + "/baseline.txt"); | ||
if (project.hasProperty("updateBaseline")) { | ||
task.setProperty("updateBaseline", true); | ||
} else { | ||
task.setProperty("updateBaseline", false); | ||
} | ||
}); | ||
} | ||
|
||
|
||
android.testServer(new FirebaseTestServer(project, firebaseLibrary.testLab)); | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
// Copyright 2019 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package com.google.firebase.gradle.plugins.apiinfo; | ||
|
||
import groovy.transform.CompileStatic; | ||
import jdk.nashorn.internal.objects.annotations.Property; | ||
import org.gradle.api.DefaultTask; | ||
import org.gradle.api.tasks.TaskAction; | ||
|
||
import java.io.BufferedReader; | ||
import java.io.BufferedWriter; | ||
import java.io.FileWriter; | ||
import java.io.IOException; | ||
import java.io.InputStreamReader; | ||
|
||
/** | ||
Task generates the api diff of the current source code against the api.txt file stored | ||
alongside the project's src directory. | ||
*/ | ||
@CompileStatic | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
public class ApiInformationTask extends DefaultTask { | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
@Property | ||
String metalavaBinaryPath; | ||
|
||
@Property | ||
String apiTxt; | ||
|
||
@Property | ||
String sourcePath; | ||
|
||
@Property | ||
String baselinePath; | ||
|
||
@Property | ||
boolean updateBaseline; | ||
|
||
@Property | ||
String outputPath; | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
|
||
private String getCmdOutput (String cmdToRun) { | ||
ProcessBuilder processBuilder = new ProcessBuilder(cmdToRun.split(" ")); | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
try { | ||
Process p = processBuilder.start(); | ||
BufferedReader reader = | ||
new BufferedReader(new InputStreamReader(p.getInputStream())); | ||
StringBuilder builder = new StringBuilder(); | ||
String line = null; | ||
while ( (line = reader.readLine()) != null) { | ||
builder.append(line); | ||
builder.append(System.getProperty("line.separator")); | ||
} | ||
return builder.toString(); | ||
} catch (IOException e) { | ||
e.printStackTrace(); | ||
return null; | ||
} | ||
|
||
} | ||
|
||
private void writeToFile(String output) { | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
try(BufferedWriter out = new BufferedWriter(new FileWriter(outputPath))) { | ||
out.write(output); | ||
} catch (IOException e) { | ||
System.err.println("Error: " + e.getMessage()); | ||
} | ||
} | ||
|
||
@TaskAction | ||
void execute() { | ||
String cmdTemplate = "%s --source-path %s --check-compatibility:api:current %s --format=v2 --baseline %s --no-color"; | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if(updateBaseline) { | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
cmdTemplate = "%s --source-path %s --check-compatibility:api:current %s --format=v2 --update-baseline %s --no-color"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. IMO, there is a lot of boilerplate here that comes down to 2 commands and their respective arguments.
I think we can remove some cruft by modelling this as // This task executes in 2 modes.
// 1. Generate api text mode
// 2. Compare api text mode
public abstract class MetalavaExecutionTask extends DefaultTask {
@Input
abstract String getMetalavaBinaryPath();
@InputFile
abstract File getApiTxt();
@Input
abstract String getSourcePath();
@InputFile
abstract File getBaselineFile();
@Input
abstract boolean getUpdateBaseline();
@Input
abstract enum getMode();
@OutputFile
abstract File getOutputFile();
abstract void setSourcePath(String value);
abstract void setBaselineFile(File value);
abstract void setUpdateBaseline(boolean value);
abstract void setMetalavaBinaryPath(String value);
abstract void setApiTxt(File value);
abstract void setOutputFile(File value);
abstract void setMode(Mode mode);
private static enum Mode {
GENERATE, COMPARE
}
@TaskAction
void execute() {
File outputFileDir = getOutputFile().getParentFile();
if(!outputFileDir.exists()) {
outputFileDir.mkdirs();
}
String cmd = mode == Mode.GENERATE ? "--check-compatibility:api:current %s" : "--api %s"
String baseline = "--baseline %s" : "--update-baseline %s"
String format = "--format=v2"
String sourcePath = "--source-path %s"
String cmdTemplate = ["%s", sourcePath, cmd, baselineArg, "--no-color"].join(" ")
String cmdToRun = String.format(cmdTemplate, getMetalavaBinaryPath(), getSourcePath(), getApiTxt().getAbsolutePath(), getBaselineFile().getAbsolutePath());
getProject().exec(spec-> {
spec.setCommandLine(Arrays.asList(cmdToRun.split(" ")));
try {
spec.setStandardOutput(new FileOutputStream(getOutputFile()));
} catch (FileNotFoundException e) {
getLogger().error(e.toString());
}
});
}
} There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. in the ci command we would need to run the task to getApiInformation There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. And there is no purpose of outputFile in the generateApiInformation Task There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The structure of the second task has changed now. It involves producing the api.txt file and then comparing the already existing api.txt with that. I feel now the structure of the two tasks are fairly different |
||
} | ||
String cmdToRun = String.format(cmdTemplate, metalavaBinaryPath, sourcePath, apiTxt, baselinePath); | ||
String cmdOutput = getCmdOutput(cmdToRun); | ||
if(cmdOutput == null ){ | ||
System.out.println("Unable to run the command " + cmdToRun); | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
else { | ||
writeToFile(cmdOutput); | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// Copyright 2019 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package com.google.firebase.gradle.plugins.apiinfo; | ||
|
||
import groovy.transform.CompileStatic; | ||
import org.gradle.api.DefaultTask; | ||
import org.gradle.api.tasks.Input; | ||
import org.gradle.api.tasks.TaskAction; | ||
|
||
import java.io.IOException; | ||
|
||
/** | ||
Task generates the api txt file for the current source code. | ||
*/ | ||
@CompileStatic | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
class GenerateApiTask extends DefaultTask { | ||
|
||
@Input | ||
private String metalavaBinaryPath; | ||
|
||
@Input | ||
private String apiTxt; | ||
|
||
@Input | ||
private String sourcePath; | ||
|
||
|
||
@TaskAction | ||
void execute() { | ||
String cmdTemplate = "%s --source-path %s --api %s --format=v2"; | ||
String cmdToRun = String.format(cmdTemplate, metalavaBinaryPath, sourcePath, apiTxt); | ||
try { | ||
Runtime.getRuntime().exec(cmdToRun); | ||
} catch (IOException e) { | ||
System.out.println("Failed to run command " + cmdToRun); | ||
System.out.println(e.toString()); | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// Copyright 2019 Google LLC | ||
// | ||
// Licensed under the Apache License, Version 2.0 (the "License"); | ||
// you may not use this file except in compliance with the License. | ||
// You may obtain a copy of the License at | ||
// | ||
// http://www.apache.org/licenses/LICENSE-2.0 | ||
// | ||
// Unless required by applicable law or agreed to in writing, software | ||
// distributed under the License is distributed on an "AS IS" BASIS, | ||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
// See the License for the specific language governing permissions and | ||
// limitations under the License. | ||
|
||
package com.google.firebase.gradle.plugins.apiinfo; | ||
|
||
|
||
|
||
import org.gradle.api.DefaultTask; | ||
import org.gradle.api.tasks.Input; | ||
import org.gradle.api.tasks.TaskAction; | ||
|
||
import java.io.IOException; | ||
|
||
import groovy.transform.CompileStatic; | ||
import jdk.nashorn.internal.objects.annotations.Property; | ||
|
||
@CompileStatic | ||
public class GenerateApiTxtFileTask extends DefaultTask { | ||
|
||
@Property | ||
String metalavaBinaryPath; | ||
|
||
@Property | ||
String apiTxt; | ||
|
||
@Property | ||
String sourcePath; | ||
|
||
@Property | ||
String baselinePath; | ||
|
||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
@Property | ||
boolean updateBaseline; | ||
|
||
|
||
|
||
@TaskAction | ||
void execute() { | ||
String cmdTemplate = "%s --source-path %s --api %s --format=v2 --baseline %s"; | ||
VinayGuthal marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if(updateBaseline) { | ||
cmdTemplate = "%s --source-path %s --api %s --format=v2 --update-baseline %s"; | ||
} | ||
String cmdToRun = String.format(cmdTemplate, metalavaBinaryPath, sourcePath, apiTxt, baselinePath); | ||
try { | ||
Process p = Runtime.getRuntime().exec(cmdToRun); | ||
System.out.println("Generated api txt file at " + apiTxt); | ||
} catch (IOException e) { | ||
System.out.println("Failed to run command " + cmdToRun); | ||
System.out.println(e.toString()); | ||
} | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
// Signature format: 2.0 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
// Baseline format: 1.0 |
Uh oh!
There was an error while loading. Please reload this page.