Repository: googleapis/api-linter
Pull request #1286 (2023-11-09 17:08:57)

fix(AIP-133): lint http collection ID for lookalikes
If there is a Custom Method that looks like a Standard Create e.g. `CreateAndCheckoutBook`, it will have a HTTP suffix like `.../books:createAndCheckout`. For a resource path like `books/{book}` this would be valid, sans custom method suffix, because the collection IDs match at the end of the HTTP path, but the rule naively included the custom method suffix and expects the resource pattern to look like `books:createAndCheckout`. While using Standard Method verbs for Custom Methods is not allowed, it happens occasionally, and ApiLinter shouldn't emit garbage as a result. 

Address [internal issue](http://b/309923830).

gcf-merge-on-green[bot]: Merge-on-green attempted to merge your PR for 6 hours, but it was not mergeable because either one of your required status checks failed, one of your required reviews was not approved, or there is a do not merge label. Learn more about your required status checks here: https://help.github.com/en/github/administering-a-repository/enabling-required-status-checks. You can remove and reapply the label to re-run the bot.

Patch:
diff --git a/rules/aip0133/http_uri_resource.go b/rules/aip0133/http_uri_resource.go
index 433cf53..25ac5b8 100644
--- a/rules/aip0133/http_uri_resource.go
+++ b/rules/aip0133/http_uri_resource.go
@@ -36,6 +36,12 @@ var httpURIResource = &lint.MethodRule{
 		// Extract the suffix of the URI path as the collection identifier.
 		uriParts := strings.Split(utils.GetHTTPRules(m)[0].URI, "/")
 		collectionName := uriParts[len(uriParts)-1]
+		// Custom Method Standard Create lookalikes can still be linted, but
+		// don't include the custom method http suffix
+		// e.g. .../books:createAndCheckout --> books.
+		if strings.Contains(collectionName, ":") {
+			collectionName = strings.Split(collectionName, ":")[0]
+		}
 
 		// Ensure that a collection identifier is provided.
 		if collectionName == "" {


Test patch:
diff --git a/rules/aip0133/http_uri_resource_test.go b/rules/aip0133/http_uri_resource_test.go
index e879a63..eaf0f79 100644
--- a/rules/aip0133/http_uri_resource_test.go
+++ b/rules/aip0133/http_uri_resource_test.go
@@ -30,9 +30,11 @@ func TestHTTPURIResource(t *testing.T) {
 		problems testutils.Problems
 	}{
 		{"Valid", "/v1/{parent=publishers/*}/books", "publishers/{publisher}/books/{book}", nil},
+		{"ValidCustomLookalike", "/v1/{parent=publishers/*}/books:createAndCheckout", "publishers/{publisher}/books/{book}", nil},
 		{"MethodMissingURIPath", "", "publishers/{publisher}/books/{book}", nil},
 		{"MethodMissingCollectionURISuffix", "/v1/", "publishers/{publisher}/books/{book}", testutils.Problems{{Message: "The URI path does not end in a collection identifier."}}},
 		{"ResourceMissingCollectionInPattern", "/v1/{parent=publishers/*}/books", "publishers/{publisher}", testutils.Problems{{Message: "Resource pattern should contain the collection identifier \"books/\"."}}},
+		{"ResourceMissingCollectionCustomLookalike", "/v1/{parent=publishers/*}/books:createAndCheckout", "publishers/{publisher}", testutils.Problems{{Message: "Resource pattern should contain the collection identifier \"books/\"."}}},
 	}
 
 	for _, test := range tests {