changelog: Added crosland link
Added notice to changelog errors that indicate only Cusky builds are supported. HTML errors now display the Crosland link to retrieve the changelog for ChromiumOS builds.
BUG=b/160901711
TEST=unittests, run local
Change-Id: Ibecb75bd5ccbbdb848024b99355e33770a3959e2
diff --git a/src/cmd/changelog-cli/main.go b/src/cmd/changelog-cli/main.go
index f2e9f7c..7b6a622 100755
--- a/src/cmd/changelog-cli/main.go
+++ b/src/cmd/changelog-cli/main.go
@@ -78,7 +78,7 @@
if err != nil {
return fmt.Errorf("generateChangelog: failed to create http client: \n%v", err)
}
- sourceToTargetChanges, targetToSourceChanges, err := changelog.Changelog(httpClient, source, target, instance, manifestRepo, -1)
+ sourceToTargetChanges, targetToSourceChanges, err := changelog.Changelog(httpClient, source, target, instance, manifestRepo, "", -1)
if err != nil {
return fmt.Errorf("generateChangelog: error retrieving changelog between builds %s and %s on GoB instance: %s with manifest repository: %s\n%v",
source, target, instance, manifestRepo, err)
diff --git a/src/cmd/changelog-webapp/app.yaml b/src/cmd/changelog-webapp/app.yaml
index 38ba74c..c365fc5 100644
--- a/src/cmd/changelog-webapp/app.yaml
+++ b/src/cmd/changelog-webapp/app.yaml
@@ -23,3 +23,4 @@
COS_INTERNAL_FALLBACK_GERRIT_INSTANCE_NAME: "cos-internal-fallback-gerrit-instance"
COS_INTERNAL_GOB_INSTANCE_NAME: "cos-internal-gob-instance"
COS_INTERNAL_MANIFEST_REPO_NAME: "cos-internal-manifest-repo"
+ CROSLAND_NAME: "crosland-url"
diff --git a/src/cmd/changelog-webapp/controllers/pageHandlers.go b/src/cmd/changelog-webapp/controllers/pageHandlers.go
index 20bf4e5..31a558e 100644
--- a/src/cmd/changelog-webapp/controllers/pageHandlers.go
+++ b/src/cmd/changelog-webapp/controllers/pageHandlers.go
@@ -40,6 +40,7 @@
internalFallbackGerritInstance string
internalGoBInstance string
internalManifestRepo string
+ croslandURL string
externalGerritInstance string
externalFallbackGerritInstance string
externalGoBInstance string
@@ -78,6 +79,10 @@
if err != nil {
log.Fatalf("Failed to retrieve secret for COS_INTERNAL_MANIFEST_REPO_NAME with key name %s\n%v", os.Getenv("COS_INTERNAL_MANIFEST_REPO_NAME"), err)
}
+ croslandURL, err = getSecret(client, os.Getenv("CROSLAND_NAME"))
+ if err != nil {
+ log.Fatalf("Failed to retrieve secret for CROSLAND_NAME with key name %s\n%v", os.Getenv("CROSLAND_NAME"), err)
+ }
externalGerritInstance = os.Getenv("COS_EXTERNAL_GERRIT_INSTANCE")
externalFallbackGerritInstance = os.Getenv("COS_EXTERNAL_FALLBACK_GERRIT_INSTANCE")
externalGoBInstance = os.Getenv("COS_EXTERNAL_GOB_INSTANCE")
@@ -337,7 +342,7 @@
http.Redirect(w, r, loginURL, http.StatusTemporaryRedirect)
return
}
- added, removed, utilErr := changelog.Changelog(httpClient, source, target, instance, manifestRepo, querySize)
+ added, removed, utilErr := changelog.Changelog(httpClient, source, target, instance, manifestRepo, croslandURL, querySize)
if utilErr != nil {
log.Errorf("error retrieving changelog between builds %s and %s on GoB instance: %s with manifest repository: %s\n%v\n",
source, target, externalGoBInstance, externalManifestRepo, utilErr)
diff --git a/src/pkg/changelog/changelog.go b/src/pkg/changelog/changelog.go
index 866b929..265e399 100644
--- a/src/pkg/changelog/changelog.go
+++ b/src/pkg/changelog/changelog.go
@@ -105,7 +105,7 @@
}
buildNum := strings.Replace(build[2], "-", ".", 3)
log.Debugf("resolveImageName: image name %s was resolved to build number %s", imageName, buildNum)
- return strings.Replace(build[2], "-", ".", 3)
+ return buildNum
}
// Creates a unique identifier for a repo + branch pairing.
@@ -320,7 +320,7 @@
//
// The second changelog contains all commits that are present in the source build
// but not present in the target build
-func Changelog(httpClient *http.Client, source string, target string, host string, repo string, querySize int) (map[string]*RepoLog, map[string]*RepoLog, utils.ChangelogError) {
+func Changelog(httpClient *http.Client, source, target, host, repo, croslandURL string, querySize int) (map[string]*RepoLog, map[string]*RepoLog, utils.ChangelogError) {
if httpClient == nil {
log.Error("httpClient is nil")
return nil, nil, utils.InternalServerError
@@ -335,13 +335,14 @@
if err != nil {
return nil, nil, err
}
- sourceRepos, err := mappedManifest(manifestClient, repo, sourceBuildNum)
- if err != nil {
- return nil, nil, err
- }
- targetRepos, err := mappedManifest(manifestClient, repo, targetBuildNum)
- if err != nil {
- return nil, nil, err
+ sourceRepos, sourceErr := mappedManifest(manifestClient, repo, sourceBuildNum)
+ targetRepos, targetErr := mappedManifest(manifestClient, repo, targetBuildNum)
+ if sourceErr != nil && sourceErr.HTTPCode() == "404" && targetErr != nil && targetErr.HTTPCode() == "404" {
+ return nil, nil, utils.BothBuildsNotFound(croslandURL, source, target)
+ } else if sourceErr != nil {
+ return nil, nil, sourceErr
+ } else if targetErr != nil {
+ return nil, nil, targetErr
}
clients[host] = manifestClient
diff --git a/src/pkg/changelog/changelog_test.go b/src/pkg/changelog/changelog_test.go
index e309b8e..8a17a8a 100644
--- a/src/pkg/changelog/changelog_test.go
+++ b/src/pkg/changelog/changelog_test.go
@@ -64,7 +64,7 @@
httpClient, _ := getHTTPClient()
// Test invalid source
- additions, removals, err := Changelog(httpClient, "15", "15043.0.0", cosInstance, defaultManifestRepo, -1)
+ additions, removals, err := Changelog(httpClient, "15", "15043.0.0", cosInstance, defaultManifestRepo, "", -1)
if additions != nil {
t.Errorf("changelog failed, expected nil additions, got %v", additions)
} else if removals != nil {
@@ -76,7 +76,7 @@
}
// Test invalid target
- additions, removals, err = Changelog(httpClient, "15043.0.0", "abx", cosInstance, defaultManifestRepo, -1)
+ additions, removals, err = Changelog(httpClient, "15043.0.0", "abx", cosInstance, defaultManifestRepo, "", -1)
if additions != nil {
t.Errorf("changelog failed, expected nil additions, got %v", additions)
} else if removals != nil {
@@ -88,7 +88,7 @@
}
// Test invalid instance
- additions, removals, err = Changelog(httpClient, "15036.0.0", "15041.0.0", "com", defaultManifestRepo, -1)
+ additions, removals, err = Changelog(httpClient, "15036.0.0", "15041.0.0", "com", defaultManifestRepo, "", -1)
if additions != nil {
t.Errorf("changelog failed, expected nil additions, got %v", additions)
} else if removals != nil {
@@ -100,7 +100,7 @@
}
// Test invalid manifest repo
- additions, removals, err = Changelog(httpClient, "15036.0.0", "15041.0.0", cosInstance, "cos/not-a-repo", -1)
+ additions, removals, err = Changelog(httpClient, "15036.0.0", "15041.0.0", cosInstance, "cos/not-a-repo", "", -1)
if additions != nil {
t.Errorf("changelog failed, expected nil additions, got %v", additions)
} else if removals != nil {
@@ -112,7 +112,7 @@
}
// Test build number higher than latest release
- additions, removals, err = Changelog(httpClient, "15036.0.0", "99999.0.0", cosInstance, defaultManifestRepo, -1)
+ additions, removals, err = Changelog(httpClient, "15036.0.0", "99999.0.0", cosInstance, defaultManifestRepo, "", -1)
if additions != nil {
t.Errorf("changelog failed, expected nil additions, got %v", additions)
} else if removals != nil {
@@ -124,7 +124,7 @@
}
// Test manifest with remote urls specified and no default URL
- additions, removals, err = Changelog(httpClient, "1.0.0", "2.0.0", cosInstance, defaultManifestRepo, -1)
+ additions, removals, err = Changelog(httpClient, "1.0.0", "2.0.0", cosInstance, defaultManifestRepo, "", -1)
if additions == nil {
t.Errorf("changelog failed, expected additions, got nil")
} else if removals == nil {
@@ -248,7 +248,7 @@
"9bc12bb411f357188d008864f80dfba43210b9d8",
"bf0dd3757826b9bc9d7082f5f749ff7615d4bcb3",
}
- additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, -1)
+ additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, "", -1)
if err != nil {
t.Errorf("changelog failed, expected no error, got %v", err)
} else if len(removals) != 0 {
@@ -292,7 +292,7 @@
"src/platform2",
"src/third_party/chromiumos-overlay",
}
- additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, -1)
+ additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, "", -1)
if err != nil {
t.Errorf("changelog failed, expected no error, got %v", err)
}
@@ -306,7 +306,7 @@
source = "15030.0.0"
target = "15050.0.0"
querySize := 50
- additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, querySize)
+ additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, "", querySize)
if err != nil {
t.Errorf("changelog failed, expected no error, got %v", err)
} else if additions == nil {
@@ -332,7 +332,7 @@
// Test changelog handles manifest with non-matching repositories
source = "12871.1177.0"
target = "12871.1179.0"
- additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, querySize)
+ additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, "", querySize)
if err != nil {
t.Errorf("changelog failed, expected no error, got %v", err)
} else if len(removals) != 0 {
@@ -357,7 +357,7 @@
// Test with different release branches
source = "13310.1035.0"
target = "15000.0.0"
- additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, querySize)
+ additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, "", querySize)
if err != nil {
t.Errorf("Changelog failed, expected no error, got %v", err)
} else if len(additions) == 0 {
@@ -369,7 +369,7 @@
// Test empty repository
source = "0.0.0"
target = "2.0.0"
- additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, querySize)
+ additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, "", querySize)
if additions != nil {
t.Errorf("changelog failed, expected nil additions, got %v", additions)
} else if removals != nil {
@@ -383,7 +383,7 @@
// Test image name
source = "cos-rc-85-13310-1034-0"
target = "cos-rc-85-13310-1030-0"
- additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, querySize)
+ additions, removals, err = Changelog(httpClient, source, target, cosInstance, defaultManifestRepo, "", querySize)
if err != nil {
t.Errorf("Changelog failed, expected no error, got %v", err)
} else if len(additions) != 0 {
diff --git a/src/pkg/utils/changelogerror.go b/src/pkg/utils/changelogerror.go
index f5b415f..f59a206 100644
--- a/src/pkg/utils/changelogerror.go
+++ b/src/pkg/utils/changelogerror.go
@@ -23,6 +23,7 @@
"errors"
"fmt"
"regexp"
+ "strings"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -119,13 +120,63 @@
return innerErr
}
+func croslandLink(croslandURL, source, target string) string {
+ return fmt.Sprintf("%s/log/%s..%s", croslandURL, source, target)
+}
+
+// BothBuildsNotFound indicates that neither build was not found
+func BothBuildsNotFound(croslandURL, source, target string) *UtilChangelogError {
+ return &UtilChangelogError{
+ httpCode: "404",
+ header: "Build Not Found",
+ err: strings.Join([]string{
+ "The builds associated with input",
+ source,
+ "and",
+ target,
+ "cannot be found. It may be possible that the inputs are either invalid or both belong",
+ "to pre-Cusky builds. If both of the inputs belong to pre-Cusky builds, note that this tool only supports changelogs",
+ "between Cusky builds. Otherwise, please input valid build numbers (example: 13310.1035.0) or valid image names",
+ "(example: cos-rc-85-13310-1034-0).",
+ }, " "),
+ htmlErr: fmt.Sprintf("%s %s and %s %s<br><br>%s %s <a href=%s target=\"_blank\">%s</a>. %s %s",
+ "The builds associated with input",
+ source,
+ target,
+ "could not be found.",
+ "It may be possible that the inputs are either invalid or both belong to pre-Cusky builds.",
+ "If both of the inputs belong to pre-Cusky builds, please check",
+ croslandLink(croslandURL, source, target),
+ croslandLink(croslandURL, source, target),
+ "Otherwise, please input valid build numbers",
+ "(example: 13310.1035.0) or valid image names (example: cos-rc-85-13310-1034-0).",
+ ),
+ }
+}
+
// BuildNotFound returns a ChangelogError object for changelog indicating
// the desired build could not be found
func BuildNotFound(buildNumber string) *UtilChangelogError {
return &UtilChangelogError{
httpCode: "404",
header: "Build Not Found",
- err: fmt.Sprintf("The build associated with input %s cannot be found. Please input a valid build number (example: 13310.1035.0) or a valid image name (example: cos-rc-85-13310-1034-0).", buildNumber),
+ err: strings.Join([]string{
+ "The build associated with input",
+ buildNumber,
+ "cannot be found. It may be possible that the input is either invalid or belongs to a",
+ "pre-Cusky build. If you entered a pre-Cusky build number or image name, note that changelog between",
+ "pre-Cusky and Cusky builds are not supported. Otherwise, please input a valid build number",
+ "(example: 13310.1035.0) or a valid image name (example: cos-rc-85-13310-1034-0).",
+ }, " "),
+ htmlErr: fmt.Sprintf("%s %s %s<br><br>%s %s %s %s",
+ "The build associated with input",
+ buildNumber,
+ "cannot be found.",
+ "It may be possible that either the input is either invalid or belongs to a",
+ "pre-Cusky build. If you entered a pre-Cusky build number or image name, note that changelog between",
+ "pre-Cusky and Cusky builds are not supported. Otherwise, please input a valid build number",
+ "(example: 13310.1035.0) or a valid image name (example: cos-rc-85-13310-1034-0).",
+ ),
}
}
diff --git a/src/pkg/utils/changelogerror_test.go b/src/pkg/utils/changelogerror_test.go
index e636449..f24ea1a 100644
--- a/src/pkg/utils/changelogerror_test.go
+++ b/src/pkg/utils/changelogerror_test.go
@@ -17,6 +17,7 @@
import (
"errors"
"fmt"
+ "strings"
"testing"
"google.golang.org/grpc/codes"
@@ -28,7 +29,7 @@
)
func testCLLink(clID, instanceURL string) string {
- return fmt.Sprintf("<a href=\"%s/q/%s\" target=\"_blank\">CL %s</a>", instanceURL, clID, clID)
+ return fmt.Sprintf("<a href=\"%s/c/%s\" target=\"_blank\">CL %s</a>", instanceURL, clID, clID)
}
func TestGerritErrCode(t *testing.T) {
@@ -87,11 +88,69 @@
}
}
+func TestBothBuildsNotFound(t *testing.T) {
+ source := "1a"
+ target := "ddddddd"
+ croslandURL := "https://www.google.com"
+ expectedCode := "404"
+ expectedErrHeader := "Build Not Found"
+ expectedErrStr := strings.Join([]string{
+ "The builds associated with input",
+ source,
+ "and",
+ target,
+ "cannot be found. It may be possible that the inputs are either invalid or both belong",
+ "to pre-Cusky builds. If both of the inputs belong to pre-Cusky builds, note that this tool only supports changelogs",
+ "between Cusky builds. Otherwise, please input valid build numbers (example: 13310.1035.0) or valid image names",
+ "(example: cos-rc-85-13310-1034-0).",
+ }, " ")
+ expectedHTMLErrStr := fmt.Sprintf("%s %s and %s %s<br><br>%s %s <a href=%s target=\"_blank\">%s</a>. %s %s",
+ "The builds associated with input",
+ source,
+ target,
+ "could not be found.",
+ "It may be possible that the inputs are either invalid or both belong to pre-Cusky builds.",
+ "If both of the inputs belong to pre-Cusky builds, please check",
+ croslandLink(croslandURL, source, target),
+ croslandLink(croslandURL, source, target),
+ "Otherwise, please input valid build numbers",
+ "(example: 13310.1035.0) or valid image names (example: cos-rc-85-13310-1034-0).",
+ )
+ err := BothBuildsNotFound(croslandURL, source, target)
+ if err.HTTPCode() != expectedCode {
+ t.Errorf("expected HTTP code %s, got %s", expectedCode, err.HTTPCode())
+ } else if err.Header() != expectedErrHeader {
+ t.Errorf("expected error header \"%s\", got %s", expectedErrHeader, err.Header())
+ } else if err.Error() != expectedErrStr {
+ t.Errorf("expected error string %s, got %s", expectedErrStr, err.Error())
+ } else if err.HTMLError() != expectedHTMLErrStr {
+ t.Errorf("expected html error string %s, got %s", expectedErrStr, err.HTMLError())
+ } else if err.Retryable() {
+ t.Errorf("expected retryable = false, got true")
+ }
+}
+
func TestBuildNotFound(t *testing.T) {
buildNumber := "15000.0.0"
expectedCode := "404"
expectedErrHeader := "Build Not Found"
- expectedErrStr := fmt.Sprintf("The build associated with input %s cannot be found. Please input a valid build number (example: 13310.1035.0) or a valid image name (example: cos-rc-85-13310-1034-0).", buildNumber)
+ expectedErrStr := strings.Join([]string{
+ "The build associated with input",
+ buildNumber,
+ "cannot be found. It may be possible that the input is either invalid or belongs to a",
+ "pre-Cusky build. If you entered a pre-Cusky build number or image name, note that changelog between",
+ "pre-Cusky and Cusky builds are not supported. Otherwise, please input a valid build number",
+ "(example: 13310.1035.0) or a valid image name (example: cos-rc-85-13310-1034-0).",
+ }, " ")
+ expectedHTMLErrStr := fmt.Sprintf("%s %s %s<br><br>%s %s %s %s",
+ "The build associated with input",
+ buildNumber,
+ "cannot be found.",
+ "It may be possible that either the input is either invalid or belongs to a",
+ "pre-Cusky build. If you entered a pre-Cusky build number or image name, note that changelog between",
+ "pre-Cusky and Cusky builds are not supported. Otherwise, please input a valid build number",
+ "(example: 13310.1035.0) or a valid image name (example: cos-rc-85-13310-1034-0).",
+ )
err := BuildNotFound(buildNumber)
if err.HTTPCode() != expectedCode {
t.Errorf("expected HTTP code %s, got %s", expectedCode, err.HTTPCode())
@@ -99,7 +158,7 @@
t.Errorf("expected error header \"%s\", got %s", expectedErrHeader, err.Header())
} else if err.Error() != expectedErrStr {
t.Errorf("expected error string %s, got %s", expectedErrStr, err.Error())
- } else if err.HTMLError() != expectedErrStr {
+ } else if err.HTMLError() != expectedHTMLErrStr {
t.Errorf("expected html error string %s, got %s", expectedErrStr, err.HTMLError())
} else if err.Retryable() {
t.Errorf("expected retryable = false, got true")
@@ -127,7 +186,7 @@
func TestCLLandingNotFound(t *testing.T) {
clID := "1540"
- expectedCode := "404"
+ expectedCode := "406"
expectedErrHeader := "No Build Found"
expectedErrStr := fmt.Sprintf("No build was found containing CL %s.", clID)
link := testCLLink(clID, testInstanceURL)