Repository: firebase/firebase-tools (ts)

Issue:
Cloud Run v1alpha1 API deprecated, resulting in 404 
<!-- DO NOT DELETE
validate_template=true
template_path=.github/ISSUE_TEMPLATE/bug_report.md
-->

<!--
Thank you for contributing to the Firebase community!

Think you found a bug?
=======================
Yeah, we're definitely not perfect! Please use this template and include a minimal repro when opening the issue. If you know how to solve the issue, please create a Pull Request, and we'd be happy to review it!

Have a feature request?
========================
Great, we love hearing how we can improve our products! However, do not use this template to submit a feature request. Please submit your feature requests to: https://firebase.google.com/support/contact/bugs-features/

Have a usage question?
=======================
We get lots of those and we love helping you, but GitHub is not the best place for them and they will be closed. Please take a look at the guide first: https://firebase.google.com/docs/cli/

If the official documentation doesn't help, try asking through our official support channel: https://firebase.google.com/support/

Additional locations to check for solutions or assistance from the community:
- Stack Overflow: https://stackoverflow.com/
- Firebase Slack Community: https://firebase.community/

*Please avoid duplicate posting across multiple channels!*
-->

### [REQUIRED] Environment info

**firebase-tools:**
Version 8.12.1

**Platform:**
macOS, but platform independent

### [REQUIRED] Test case

1. Create a Cloud Run service
2. Create a firebase rewrite rule to that cloud run service
3. Trigger the rewrite rule by calling the URL
4. Receive the following response from the Cloud Run API call

```
[hosting] Cloud Run rewrite {"source":"/<URL>,"run":{"serviceId":"<SERVICEID>","region":"<LOCATION>"}} triggered
[hosting] Looking up Cloud Run service "/v1alpha1/projects/<PROJECT>/locations/<LOCATION>/services/<SERVICEID>" for its URL

Error: Request failed with status code 500
A problem occurred while trying to handle a proxied rewrite: error looking up URL for Cloud Run service: FirebaseError: HTTP Error: 404, Requested entity was not found.
```

### [REQUIRED] Steps to reproduce

The reproduction path is in the test case

### [REQUIRED] Expected behavior

It should be able to retrieve the Cloud Run service URL and trigger the service

### [REQUIRED] Actual behavior

It returns a 404


Pull request:
Switch to Cloud Run API v1 endpoint
<!--

Thank you for contributing to the Firebase community! Please fill out the form below.

Run the linter and test suite
==============================
Run `npm test` to make sure your changes compile properly and the tests all pass on your local machine. We've hooked up this repo with continuous integration to double check those things for you.

-->

### Description

Fixes #2695

### Scenarios Tested

I was able to trigger a Cloud Run service using the test case described in #2695 after using `npm link`

### Sample Commands

N/A

Patch:
diff --git a/src/hosting/cloudRunProxy.ts b/src/hosting/cloudRunProxy.ts
index 489312019..5f86119ec 100644
--- a/src/hosting/cloudRunProxy.ts
+++ b/src/hosting/cloudRunProxy.ts
@@ -25,12 +25,12 @@ function getCloudRunUrl(rewrite: CloudRunProxyRewrite, projectId: string): Promi
     return Promise.resolve(alreadyFetched);
   }
 
-  const path = `/v1alpha1/projects/${projectId}/locations/${rewrite.run.region ||
+  const path = `/v1/projects/${projectId}/locations/${rewrite.run.region ||
     "us-central1"}/services/${rewrite.run.serviceId}`;
   logger.info(`[hosting] Looking up Cloud Run service "${path}" for its URL`);
   return apiRequest("GET", path, { origin: cloudRunApiOrigin, auth: true })
     .then((res) => {
-      const url = get(res, "body.status.address.hostname");
+      const url = get(res, "body.status.url");
       if (!url) {
         return Promise.reject("Cloud Run URL doesn't exist in response.");
       }


Test patch:
diff --git a/src/test/hosting/cloudRunProxy.spec.ts b/src/test/hosting/cloudRunProxy.spec.ts
index acd6cb225..c373dfd45 100644
--- a/src/test/hosting/cloudRunProxy.spec.ts
+++ b/src/test/hosting/cloudRunProxy.spec.ts
@@ -36,7 +36,7 @@ describe("cloudRunProxy", () => {
 
   it("should error when the Cloud Run service doesn't exist", async () => {
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/empty")
+      .get("/v1/projects/project-foo/locations/us-central1/services/empty")
       .reply(404, { error: "service doesn't exist" });
 
     const mwGenerator = await cloudRunProxy(fakeOptions);
@@ -53,8 +53,8 @@ describe("cloudRunProxy", () => {
 
   it("should error when the Cloud Run service doesn't exist", async () => {
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/badService")
-      .reply(200, { status: { address: {} } });
+      .get("/v1/projects/project-foo/locations/us-central1/services/badService")
+      .reply(200, { status: {} });
 
     const mwGenerator = await cloudRunProxy(fakeOptions);
     const mw = await mwGenerator({ run: { serviceId: "badService" } });
@@ -70,8 +70,8 @@ describe("cloudRunProxy", () => {
 
   it("should resolve a function returns middleware that proxies to the live version", async () => {
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/helloworld")
-      .reply(200, { status: { address: { hostname: cloudRunServiceOrigin } } });
+      .get("/v1/projects/project-foo/locations/us-central1/services/helloworld")
+      .reply(200, { status: { url: cloudRunServiceOrigin } });
     nock(cloudRunServiceOrigin)
       .get("/")
       .reply(200, "live version");
@@ -91,8 +91,8 @@ describe("cloudRunProxy", () => {
   it("should resolve to a live version in another region", async () => {
     const cloudRunServiceOriginAsia = "https://helloworld-hash-as.a.run.app";
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/asia-southeast1/services/helloworld")
-      .reply(200, { status: { address: { hostname: cloudRunServiceOriginAsia } } });
+      .get("/v1/projects/project-foo/locations/asia-southeast1/services/helloworld")
+      .reply(200, { status: { url: cloudRunServiceOriginAsia } });
     nock(cloudRunServiceOriginAsia)
       .get("/")
       .reply(200, "live version");
@@ -112,8 +112,8 @@ describe("cloudRunProxy", () => {
   it("should cache calls to look up Cloud Run service URLs", async () => {
     const multiCallOrigin = "https://multiLookup-hash-uc.a.run.app";
     const multiNock = nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/multiLookup")
-      .reply(200, { status: { address: { hostname: multiCallOrigin } } });
+      .get("/v1/projects/project-foo/locations/us-central1/services/multiLookup")
+      .reply(200, { status: { url: multiCallOrigin } });
     nock(multiCallOrigin)
       .persist() // Gets called multiple times
       .get("/")
@@ -131,7 +131,7 @@ describe("cloudRunProxy", () => {
 
     // New rewrite for the same Cloud Run service
     const failMultiNock = nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/multiLookup")
+      .get("/v1/projects/project-foo/locations/us-central1/services/multiLookup")
       .reply(500, "should not happen");
 
     const mw2Generator = await cloudRunProxy(fakeOptions);
@@ -154,8 +154,8 @@ describe("cloudRunProxy", () => {
 
   it("should pass through normal 404 errors", async () => {
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/helloworld")
-      .reply(200, { status: { address: { hostname: cloudRunServiceOrigin } } });
+      .get("/v1/projects/project-foo/locations/us-central1/services/helloworld")
+      .reply(200, { status: { url: cloudRunServiceOrigin } });
     nock(cloudRunServiceOrigin)
       .get("/404.html")
       .reply(404, "normal 404");
@@ -174,8 +174,8 @@ describe("cloudRunProxy", () => {
 
   it("should do nothing on 404 errors with x-cascade", async () => {
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/helloworld")
-      .reply(200, { status: { address: { hostname: cloudRunServiceOrigin } } });
+      .get("/v1/projects/project-foo/locations/us-central1/services/helloworld")
+      .reply(200, { status: { url: cloudRunServiceOrigin } });
     nock(cloudRunServiceOrigin)
       .get("/404-cascade.html")
       .reply(404, "normal 404 with cascade", { "x-cascade": "pass" });
@@ -201,8 +201,8 @@ describe("cloudRunProxy", () => {
 
   it("should remove cookies on non-private cached responses", async () => {
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/helloworld")
-      .reply(200, { status: { address: { hostname: cloudRunServiceOrigin } } });
+      .get("/v1/projects/project-foo/locations/us-central1/services/helloworld")
+      .reply(200, { status: { url: cloudRunServiceOrigin } });
     nock(cloudRunServiceOrigin)
       .get("/cached")
       .reply(200, "cached page", { "cache-control": "custom", "set-cookie": "nom" });
@@ -222,8 +222,8 @@ describe("cloudRunProxy", () => {
 
   it("should add required Vary headers to the response", async () => {
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/helloworld")
-      .reply(200, { status: { address: { hostname: cloudRunServiceOrigin } } });
+      .get("/v1/projects/project-foo/locations/us-central1/services/helloworld")
+      .reply(200, { status: { url: cloudRunServiceOrigin } });
     nock(cloudRunServiceOrigin)
       .get("/vary")
       .reply(200, "live vary version", { vary: "Other, Authorization" });
@@ -243,8 +243,8 @@ describe("cloudRunProxy", () => {
 
   it("should respond with a 500 error if an error occurs calling the Cloud Run service", async () => {
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/helloworld")
-      .reply(200, { status: { address: { hostname: cloudRunServiceOrigin } } });
+      .get("/v1/projects/project-foo/locations/us-central1/services/helloworld")
+      .reply(200, { status: { url: cloudRunServiceOrigin } });
     nock(cloudRunServiceOrigin)
       .get("/500")
       .replyWithError({ message: "normal error" });
@@ -263,8 +263,8 @@ describe("cloudRunProxy", () => {
 
   it("should respond with a 504 error if a timeout error occurs calling the Cloud Run service", async () => {
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/helloworld")
-      .reply(200, { status: { address: { hostname: cloudRunServiceOrigin } } });
+      .get("/v1/projects/project-foo/locations/us-central1/services/helloworld")
+      .reply(200, { status: { url: cloudRunServiceOrigin } });
     nock(cloudRunServiceOrigin)
       .get("/timeout")
       .replyWithError({ message: "ahh", code: "ETIMEDOUT" });
@@ -283,8 +283,8 @@ describe("cloudRunProxy", () => {
 
   it("should respond with a 504 error if a sockettimeout error occurs calling the Cloud Run service", async () => {
     nock(cloudRunApiOrigin)
-      .get("/v1alpha1/projects/project-foo/locations/us-central1/services/helloworld")
-      .reply(200, { status: { address: { hostname: cloudRunServiceOrigin } } });
+      .get("/v1/projects/project-foo/locations/us-central1/services/helloworld")
+      .reply(200, { status: { url: cloudRunServiceOrigin } });
     nock(cloudRunServiceOrigin)
       .get("/sockettimeout")
       .replyWithError({ message: "ahh", code: "ESOCKETTIMEDOUT" });