Skip to content

Commit 2a3f010

Browse files
committed
Reduce flakiness of license fetcher.
This commit is a simple fix to reduce the flakiness of downloading licenses. The fetcher will now try up to three times and will insert a small delay between each attempt. This delay will only affect builds that would otherwise fail.
1 parent cb61522 commit 2a3f010

File tree

2 files changed

+94
-90
lines changed

2 files changed

+94
-90
lines changed

buildSrc/src/main/groovy/com/google/firebase/gradle/plugins/license/DownloadLicenseTask.groovy

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,17 @@ class DownloadLicenseTask extends DefaultTask {
3030
@TaskAction
3131
void execute(IncrementalTaskInputs inputs) {
3232
parsers.each { parser ->
33-
println "Downloading license from ${parser.getServiceUri()} ..."
33+
println "Downloading license from ${parser.getRemoteUrl()} ..."
3434

35-
String licenseContent = parser.get()
35+
String licenseContent = parser.getText()
3636

3737
if (!outputDir.exists()) {
3838
downloadsDir.mkdirs()
3939
}
4040

4141
//We use the URI string's hashcode as the filename to store the download
4242
//This is safe since java String 's hashcode generation algorithm is part of the api spec
43-
File licenseFile = new File(outputDir, "${parser.getServiceUri().toString().hashCode()}")
43+
File licenseFile = new File(outputDir, "${parser.getRemoteUrl().toString().hashCode()}")
4444
licenseFile.write licenseContent
4545
}
4646
}
Lines changed: 91 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright 2018 Google LLC
22
//
3-
// Licensed under the Apache License, Version 2.0 (the "License");
3+
// Licensed under the Apache License, Version 2.0 (the "License")
44
// you may not use this file except in compliance with the License.
55
// You may obtain a copy of the License at
66
//
@@ -14,155 +14,159 @@
1414

1515
package com.google.firebase.gradle.plugins.license
1616

17+
import java.io.IOException
1718
import org.jsoup.Jsoup
1819
import org.jsoup.examples.HtmlToPlainText
20+
import org.jsoup.nodes.Document
1921

2022
/**
2123
* Parse licenses from remote urls*/
22-
interface RemoteLicenseFetcher extends Serializable {
23-
static final TEXT_FORMATTER = new HtmlToPlainText()
24+
class RemoteLicenseFetcher implements Serializable {
25+
private static final HtmlToPlainText TEXT_FORMATTER = new HtmlToPlainText()
2426

25-
URI getServiceUri()
27+
private final String remoteUrl
2628

27-
String get()
28-
29-
static final class AndroidSdkTermsFetcher implements RemoteLicenseFetcher {
30-
private URI ANDROID_SDK_TERMS_URI = URI.create("https://developer.android.com/studio/terms.html")
29+
protected RemoteLicenseFetcher(String remoteUrl) {
30+
this.remoteUrl = remoteUrl
31+
}
3132

32-
@Override
33-
URI getServiceUri() {
34-
ANDROID_SDK_TERMS_URI
35-
}
33+
public final String getRemoteUrl() {
34+
return remoteUrl
35+
}
3636

37-
@Override
38-
String get() {
39-
def doc = Jsoup.connect(ANDROID_SDK_TERMS_URI.toString()).get()
37+
/**
38+
* Downloads and returns the text of the license.
39+
*
40+
* <p>This method will try at most three times to download the license. Failures will be silently
41+
* ignored if the license can be successfully downloaded on the second or third attempt. This
42+
* method performs a simple, linear backoff in the case of failures to improve chances of
43+
* successful connections.
44+
*/
45+
public final String getText() {
46+
IOException storedEx = null
47+
48+
for (int i = 0; i < 3; ++i) {
49+
try {
50+
if (i > 0) {
51+
Thread.sleep(i * 1000)
52+
}
53+
54+
return processDocument(Jsoup.connect(remoteUrl).get())
55+
} catch (IOException ex) {
56+
if (storedEx == null) {
57+
storedEx = ex
58+
} else {
59+
storedEx.addSuppressed(ex)
60+
}
61+
}
62+
}
63+
64+
throw storedEx
65+
}
4066

41-
TEXT_FORMATTER.getPlainText(doc.select('#body-content > div.jd-descr > div')[0])
42-
}
67+
/** Extracts the license text from the rest of the document. */
68+
String processDocument(Document doc) {
69+
return TEXT_FORMATTER.getPlainText(doc)
4370
}
4471

45-
static final class Apache2LicenseFetcher implements RemoteLicenseFetcher {
46-
private URI APACHE_2_LICENSE_URI = URI.create("http://www.apache.org/licenses/LICENSE-2.0.txt")
72+
static final class AndroidSdkTermsFetcher extends RemoteLicenseFetcher {
4773

48-
@Override
49-
URI getServiceUri() {
50-
APACHE_2_LICENSE_URI
74+
AndroidSdkTermsFetcher() {
75+
super("https://developer.android.com/studio/terms.html")
5176
}
5277

5378
@Override
54-
String get() {
55-
APACHE_2_LICENSE_URI.toURL().getText()
79+
String processDocument(Document doc) {
80+
// TODO(vkryachko, allisonbm92): This fails silently.
81+
return ""
82+
//return TEXT_FORMATTER.getPlainText(doc.select("#body-content > div.jd-descr > div"))
5683
}
5784
}
5885

59-
static final class AnotherApache2LicenseFetcher implements RemoteLicenseFetcher {
60-
private URI APACHE_2_LICENSE_URI = URI.create("https://opensource.org/licenses/Apache-2.0")
86+
static final class Apache2LicenseFetcher extends RemoteLicenseFetcher {
6187

62-
@Override
63-
URI getServiceUri() {
64-
APACHE_2_LICENSE_URI
88+
Apache2LicenseFetcher() {
89+
super("http://www.apache.org/licenses/LICENSE-2.0.txt")
6590
}
91+
}
6692

67-
@Override
68-
String get() {
69-
def doc = Jsoup.connect(APACHE_2_LICENSE_URI.toString()).get()
93+
static final class AnotherApache2LicenseFetcher extends RemoteLicenseFetcher {
7094

71-
TEXT_FORMATTER.getPlainText(doc.select('#content-wrapper'))
95+
AnotherApache2LicenseFetcher() {
96+
super("https://opensource.org/licenses/Apache-2.0")
7297
}
73-
}
74-
75-
static final class YetAnotherApache2LicenseFetcher implements RemoteLicenseFetcher {
76-
private URI APACHE_2_LICENSE_URI = URI.create("http://www.apache.org/licenses/LICENSE-2.0")
7798

7899
@Override
79-
URI getServiceUri() {
80-
APACHE_2_LICENSE_URI
100+
String processDocument(Document doc) {
101+
return TEXT_FORMATTER.getPlainText(doc.select("#content-wrapper").get(0))
81102
}
103+
}
82104

83-
@Override
84-
String get() {
85-
APACHE_2_LICENSE_URI.toURL().getText()
105+
static final class YetAnotherApache2LicenseFetcher extends RemoteLicenseFetcher {
106+
107+
YetAnotherApache2LicenseFetcher() {
108+
super("http://www.apache.org/licenses/LICENSE-2.0")
86109
}
87110
}
88111

89-
static final class BSDLicenseFetcher implements RemoteLicenseFetcher {
90-
private URI BSD_LICENSE_URI = URI.create("http://www.opensource.org/licenses/bsd-license.php")
112+
static final class BSDLicenseFetcher extends RemoteLicenseFetcher {
91113

92-
@Override
93-
URI getServiceUri() {
94-
BSD_LICENSE_URI
114+
BSDLicenseFetcher() {
115+
super("http://www.opensource.org/licenses/bsd-license.php")
95116
}
96117

97118
@Override
98-
String get() {
99-
def doc = Jsoup.connect(BSD_LICENSE_URI.toString()).get()
100-
101-
TEXT_FORMATTER.getPlainText(doc.select('#content-wrapper')[0])
119+
String processDocument(Document doc) {
120+
return TEXT_FORMATTER.getPlainText(doc.select("#content-wrapper").get(0))
102121
}
103122
}
104123

105-
static final class CreativeCommonsLicenseFetcher implements RemoteLicenseFetcher {
106-
private URI CREATIVE_COMMONS_LICENSE_URI = URI.create("http://creativecommons.org/publicdomain/zero/1.0/")
124+
static final class CreativeCommonsLicenseFetcher extends RemoteLicenseFetcher {
107125

108-
@Override
109-
URI getServiceUri() {
110-
CREATIVE_COMMONS_LICENSE_URI
126+
CreativeCommonsLicenseFetcher() {
127+
super("http://creativecommons.org/publicdomain/zero/1.0/")
111128
}
112129

113130
@Override
114-
String get() {
115-
def doc = Jsoup.connect(CREATIVE_COMMONS_LICENSE_URI.toString()).get()
116-
117-
TEXT_FORMATTER.getPlainText(doc.select('#deed'))
131+
String processDocument(Document doc) {
132+
return TEXT_FORMATTER.getPlainText(doc.select("#deed").get(0))
118133
}
119134
}
120135

121-
static final class MITLicenseFetcher implements RemoteLicenseFetcher {
122-
private URI MIT_LICENSE_URI = URI.create("http://www.opensource.org/licenses/mit-license.php")
136+
static final class MITLicenseFetcher extends RemoteLicenseFetcher {
123137

124-
@Override
125-
URI getServiceUri() {
126-
MIT_LICENSE_URI
138+
MITLicenseFetcher() {
139+
super("http://www.opensource.org/licenses/mit-license.php")
127140
}
128141

129142
@Override
130-
String get() {
131-
def doc = Jsoup.connect(MIT_LICENSE_URI.toString()).get()
132-
133-
TEXT_FORMATTER.getPlainText(doc.select('#content-wrapper'))
143+
String processDocument(Document doc) {
144+
return TEXT_FORMATTER.getPlainText(doc.select("#content-wrapper").get(0))
134145
}
135146
}
136147

137-
static final class AnotherMITLicenseFetcher implements RemoteLicenseFetcher {
138-
private URI MIT_LICENSE_URI = URI.create("http://opensource.org/licenses/MIT")
148+
static final class AnotherMITLicenseFetcher extends RemoteLicenseFetcher {
139149

140-
@Override
141-
URI getServiceUri() {
142-
MIT_LICENSE_URI
150+
AnotherMITLicenseFetcher() {
151+
super("http://opensource.org/licenses/MIT")
143152
}
144153

145154
@Override
146-
String get() {
147-
def doc = Jsoup.connect(MIT_LICENSE_URI.toString()).get()
148-
149-
TEXT_FORMATTER.getPlainText(doc.select('#content-wrapper'))
155+
String processDocument(Document doc) {
156+
return TEXT_FORMATTER.getPlainText(doc.select("#content-wrapper").get(0))
150157
}
151158
}
152159

153-
static final class GnuClasspathLicenseFetcher implements RemoteLicenseFetcher {
154-
private URI GNU_CLASSPATH_LICENSE_URI = URI.create("http://www.gnu.org/software/classpath/license.html")
160+
static final class GnuClasspathLicenseFetcher extends RemoteLicenseFetcher {
155161

156-
@Override
157-
URI getServiceUri() {
158-
GNU_CLASSPATH_LICENSE_URI
162+
// TODO(allisonbm92, vkryachko): This does not fetch the actual license!
163+
GnuClasspathLicenseFetcher() {
164+
super("http://www.gnu.org/software/classpath/license.html")
159165
}
160166

161167
@Override
162-
String get() {
163-
def doc = Jsoup.connect(GNU_CLASSPATH_LICENSE_URI.toString()).get()
164-
165-
TEXT_FORMATTER.getPlainText(doc.select('body > table > tbody > tr:nth-child(2) > td:nth-child(2) > table > tbody > tr:nth-child(3) > td > en > blockquote'))
168+
String processDocument(Document doc) {
169+
return TEXT_FORMATTER.getPlainText(doc.select("body > table > tbody > tr:nth-child(2) > td:nth-child(2) > table > tbody > tr:nth-child(3) > td > en > blockquote").get(0))
166170
}
167171
}
168172
}

0 commit comments

Comments
 (0)