Skip to content

Commit 9e98fd6

Browse files
committed
Add MultiProjectReleasePlugin
1 parent ce5e01b commit 9e98fd6

File tree

3 files changed

+394
-0
lines changed

3 files changed

+394
-0
lines changed

alternative-root-project.gradle

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
import com.google.firebase.gradle.MultiProjectReleasePlugin
16+
17+
// Top-level build file where you can add configuration options common to all sub-projects/modules.
18+
19+
buildscript {
20+
ext.kotlinVersion = '1.3.72'
21+
repositories {
22+
google()
23+
jcenter()
24+
mavenCentral()
25+
maven {
26+
url "https://plugins.gradle.org/m2/"
27+
}
28+
maven {
29+
url 'https://storage.googleapis.com/android-ci/mvn/'
30+
}
31+
}
32+
33+
dependencies {
34+
classpath 'com.android.tools.build:gradle:3.4.3'
35+
classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.14'
36+
classpath 'net.ltgt.gradle:gradle-errorprone-plugin:1.2.1'
37+
classpath 'org.jsoup:jsoup:1.11.2'
38+
classpath 'gradle.plugin.com.github.sherter.google-java-format:google-java-format-gradle-plugin:0.8'
39+
classpath 'com.google.gms:google-services:4.3.0'
40+
classpath 'me.tatarka:gradle-retrolambda:3.7.1'
41+
classpath 'digital.wup:android-maven-publish:3.6.2'
42+
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion"
43+
classpath 'org.jlleitschuh.gradle:ktlint-gradle:7.1.0'
44+
}
45+
}
46+
47+
ext {
48+
playServicesVersion = '16.0.1'
49+
supportAnnotationsVersion = '28.0.0'
50+
gMavenRoot = 'https://dl.google.com/dl/android/maven2'
51+
firebaseDefaultPreguardFile='oss/default-preguard.txt'
52+
errorproneVersion = '2.3.2'
53+
errorproneJavacVersion = '9+181-r4173-1'
54+
googleTruthVersion = '0.40'
55+
56+
}
57+
58+
apply from: 'build.gradle'
59+
60+
configure(subprojects) {
61+
afterEvaluate {
62+
tasks.verifyGoogleJavaFormat {
63+
exclude '**/build/classes/**'
64+
}
65+
}
66+
}
67+
68+
apply plugin: MultiProjectReleasePlugin

alternative-settings.gradle

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
rootProject.name = 'com.google.firebase'
16+
//Note: do not add subprojects to this file. Instead add them to subprojects.gradle
17+
18+
apply from: 'gradle/projectSettings.gradle'
19+
20+
discoverSubprojects(file('subprojects.cfg')).each {
21+
include ":$it"
22+
}
23+
24+
apply from: new File(settingsDir, 'gradle/buildCache.gradle')
25+
26+
rootProject.buildFileName = 'alternative-root-project.gradle'
Lines changed: 300 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,300 @@
1+
// Copyright 2021 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
package com.google.firebase.gradle;
15+
16+
import static com.google.firebase.gradle.plugins.ProjectUtilsKt.toBoolean;
17+
18+
import com.google.common.collect.ImmutableList;
19+
import com.google.common.collect.ImmutableMap;
20+
import com.google.firebase.gradle.bomgenerator.BomGeneratorTask;
21+
import com.google.firebase.gradle.plugins.FireEscapeArtifactPlugin;
22+
import com.google.firebase.gradle.plugins.FirebaseLibraryExtension;
23+
import com.google.firebase.gradle.plugins.JavadocPlugin;
24+
import com.google.firebase.gradle.plugins.TasksKt;
25+
import com.google.firebase.gradle.plugins.publish.PublishingPlugin;
26+
import java.io.File;
27+
import java.io.IOException;
28+
import java.nio.file.Files;
29+
import java.util.Set;
30+
import java.util.stream.Collectors;
31+
import org.gradle.api.GradleException;
32+
import org.gradle.api.Plugin;
33+
import org.gradle.api.Project;
34+
import org.gradle.api.Task;
35+
import org.gradle.api.tasks.Delete;
36+
import org.gradle.api.tasks.bundling.Zip;
37+
38+
/**
39+
* Orchestrates the release process by automating validations, documentation and prebuilts
40+
* generation.
41+
*
42+
* <ul>
43+
* <li>Pre-release validations:
44+
* <ul>
45+
* <li>Build maven artifacts.
46+
* </ul>
47+
* <li>Documentation:
48+
* <ul>
49+
* <li>Generates javadoc for all SDKs being released.
50+
* </ul>
51+
* <li>Artifact generation:
52+
* <ul>
53+
* <li>Releases artifacts into a maven repo in build/m2repository.
54+
* <li>Bundles all artifacts into a distributable .zip file.
55+
* </ul>
56+
* </ul>
57+
*/
58+
public class MultiProjectReleasePlugin implements Plugin<Project> {
59+
60+
@Override
61+
public void apply(Project project) {
62+
project.apply(ImmutableMap.of("plugin", PublishingPlugin.class));
63+
64+
boolean releaseJavadocs = toBoolean(System.getProperty("releaseJavadocs", "true"));
65+
66+
File firebaseDevsiteJavadoc = new File(project.getBuildDir(), "firebase-javadocs/");
67+
firebaseDevsiteJavadoc.mkdirs();
68+
File gmsDevsiteJavadoc = new File(project.getBuildDir(), "gms-javadocs/");
69+
gmsDevsiteJavadoc.mkdirs();
70+
File firebaseClientBuildDest = new File(firebaseDevsiteJavadoc, "client/");
71+
firebaseClientBuildDest.mkdirs();
72+
File gmsClientBuildDest = new File(gmsDevsiteJavadoc, "client/");
73+
gmsClientBuildDest.mkdirs();
74+
75+
project.subprojects(
76+
sub -> {
77+
sub.afterEvaluate(
78+
p -> {
79+
sub.apply(ImmutableMap.of("plugin", JavadocPlugin.class));
80+
sub.apply(ImmutableMap.of("plugin", FireEscapeArtifactPlugin.class));
81+
});
82+
});
83+
84+
project
85+
.getTasks()
86+
.create(
87+
"buildBomZip",
88+
Zip.class,
89+
task -> {
90+
task.dependsOn(project.getTasks().create("generateBom", BomGeneratorTask.class));
91+
task.from("bom");
92+
task.getArchiveFileName().set("bom.zip");
93+
task.getDestinationDirectory().set(project.getRootDir());
94+
});
95+
96+
project
97+
.getGradle()
98+
.projectsEvaluated(
99+
gradle -> {
100+
Set<FirebaseLibraryExtension> librariesToPublish =
101+
(Set<FirebaseLibraryExtension>)
102+
project.getExtensions().getExtraProperties().get("projectsToPublish");
103+
104+
Set<Project> projectsToPublish =
105+
librariesToPublish.stream().map(lib -> lib.project).collect(Collectors.toSet());
106+
107+
Task validateProjectsToPublish =
108+
project.task(
109+
"validateProjectsToPublish",
110+
task ->
111+
task.doLast(
112+
t -> {
113+
if (projectsToPublish.isEmpty()) {
114+
throw new GradleException(
115+
"Required projectsToPublish parameter missing.");
116+
}
117+
}));
118+
Task firebasePublish = project.getTasks().findByName("firebasePublish");
119+
firebasePublish.dependsOn(validateProjectsToPublish);
120+
121+
Task generateAllJavadocs =
122+
project.task(
123+
"generateAllJavadocs",
124+
task -> {
125+
for (Project p : projectsToPublish) {
126+
task.dependsOn(p.getPath() + ":" + TasksKt.JAVADOC_TASK_NAME);
127+
128+
task.doLast(
129+
t -> {
130+
for (Project publishableProject : projectsToPublish) {
131+
publishableProject.copy(
132+
copy -> {
133+
copy.from(
134+
publishableProject.getBuildDir()
135+
+ "/docs/javadoc/reference");
136+
copy.include("**/*");
137+
copy.into(firebaseDevsiteJavadoc);
138+
});
139+
140+
publishableProject.copy(
141+
copy -> {
142+
copy.from(
143+
publishableProject.getBuildDir()
144+
+ "/docs/javadoc/reference");
145+
copy.include("**/*");
146+
copy.into(gmsDevsiteJavadoc);
147+
});
148+
149+
publishableProject.copy(
150+
copy -> {
151+
copy.from(
152+
publishableProject.getBuildDir()
153+
+ "/docs/javadoc/reference/_toc.yaml");
154+
copy.include("**/*");
155+
copy.into(
156+
firebaseClientBuildDest
157+
+ "/"
158+
+ publishableProject.getName());
159+
});
160+
161+
publishableProject.copy(
162+
copy -> {
163+
copy.from(
164+
publishableProject.getBuildDir()
165+
+ "/docs/javadoc/reference/_toc.yaml");
166+
copy.include("**/*");
167+
copy.into(
168+
gmsClientBuildDest
169+
+ "/"
170+
+ publishableProject.getName());
171+
});
172+
}
173+
});
174+
}
175+
});
176+
177+
Delete prepareJavadocs =
178+
project
179+
.getTasks()
180+
.create(
181+
"prepareJavadocs",
182+
Delete.class,
183+
del -> {
184+
del.dependsOn(generateAllJavadocs);
185+
del.doLast(
186+
d -> {
187+
// cleanup docs
188+
project.delete(
189+
delSpec -> {
190+
ImmutableList<String> relativeDeletablePaths =
191+
ImmutableList.of(
192+
"timestamp.js",
193+
"navtree_data.js",
194+
"assets/",
195+
"classes.html",
196+
"hierarchy.html",
197+
"lists.js",
198+
"package-list",
199+
"packages.html",
200+
"index.html",
201+
"current.xml",
202+
"_toc.yaml");
203+
delSpec.delete(
204+
relativeDeletablePaths.stream()
205+
.flatMap(
206+
path ->
207+
ImmutableList.of(
208+
firebaseDevsiteJavadoc.getPath()
209+
+ "/"
210+
+ path,
211+
gmsDevsiteJavadoc.getPath()
212+
+ "/"
213+
+ path)
214+
.stream())
215+
.collect(Collectors.toList()));
216+
});
217+
// Transform
218+
project.exec(
219+
execSpec -> {
220+
execSpec.setIgnoreExitValue(true);
221+
execSpec.setWorkingDir(firebaseDevsiteJavadoc);
222+
execSpec.setCommandLine(
223+
project.getRootProject().file("buildSrc").getPath()
224+
+ "/devsite_transform.sh");
225+
});
226+
227+
project.exec(
228+
execSpec -> {
229+
execSpec.setIgnoreExitValue(true);
230+
execSpec.setWorkingDir(gmsDevsiteJavadoc);
231+
execSpec.commandLine(
232+
project.getRootProject().file("buildSrc").getPath()
233+
+ "/gms_transform.sh");
234+
});
235+
236+
// Tidy
237+
String tidyBinary = System.getProperty("tidyBinaryPath", null);
238+
String tidyConfig = System.getProperty("tidyConfigPath", null);
239+
if (tidyBinary != null && tidyConfig != null) {
240+
for (File dir :
241+
ImmutableList.of(
242+
firebaseDevsiteJavadoc, gmsDevsiteJavadoc)) {
243+
try {
244+
Files.walk(dir.toPath())
245+
.filter(
246+
p ->
247+
p.toFile().isFile()
248+
&& p.toString().endsWith(".html"))
249+
.forEach(
250+
p -> {
251+
project.exec(
252+
execSpec -> {
253+
System.out.println("Tidying " + p);
254+
execSpec.setIgnoreExitValue(true);
255+
execSpec.commandLine(
256+
tidyBinary, "-config", tidyConfig, p);
257+
});
258+
});
259+
} catch (IOException e) {
260+
throw new GradleException("Directory walk failed.", e);
261+
}
262+
}
263+
}
264+
});
265+
});
266+
267+
Zip assembleFirebaseJavadocZip =
268+
project
269+
.getTasks()
270+
.create(
271+
"assembleFirebaseJavadocZip",
272+
Zip.class,
273+
zip -> {
274+
zip.dependsOn(prepareJavadocs);
275+
zip.getDestinationDirectory().set(project.getBuildDir());
276+
zip.getArchiveFileName().set("firebase-javadoc.zip");
277+
zip.from(firebaseDevsiteJavadoc);
278+
zip.include("**/*");
279+
});
280+
281+
Zip assembleGmsJavadocZip =
282+
project
283+
.getTasks()
284+
.create(
285+
"assembleGmsJavadocZip",
286+
Zip.class,
287+
zip -> {
288+
zip.dependsOn(prepareJavadocs);
289+
zip.getDestinationDirectory().set(project.getBuildDir());
290+
zip.getArchiveFileName().set("gms-javadoc.zip");
291+
zip.from(gmsDevsiteJavadoc);
292+
zip.include("**/*");
293+
});
294+
295+
if (releaseJavadocs) {
296+
firebasePublish.dependsOn(assembleFirebaseJavadocZip, assembleGmsJavadocZip);
297+
}
298+
});
299+
}
300+
}

0 commit comments

Comments
 (0)