deploy-cloudrun icon indicating copy to clipboard operation
deploy-cloudrun copied to clipboard

Expose created revision name as an output

Open preritdas opened this issue 10 months ago • 12 comments

Closes #555.

Adds an output attribute to the action, revision, which is the latestCreatedRevisionName.

This will allow subsequent action steps to allocate traffic/run any checks on the new revision specifically.

preritdas avatar Jan 14 '25 03:01 preritdas

Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

View this failed invocation of the CLA check for more information.

For the most up to date status, view the checks section at the bottom of the pull request.

google-cla[bot] avatar Jan 14 '25 03:01 google-cla[bot]

A question I have for you @sethvargo, to make sure of the intended behavior of this PR, is if the latestCreatedRevisionName is in fact the name of the currently created revision, or, if it is the latest revision of the service unrelated to the current deployment. Of course they'll almost always be the same, but, not by definition and not necessarily always...

preritdas avatar Jan 14 '25 03:01 preritdas

A question I have for you @sethvargo, to make sure of the intended behavior of this PR, is if the latestCreatedRevisionName is in fact the name of the currently created revision, or, if it is the latest revision of the service unrelated to the current deployment. Of course they'll almost always be the same, but, not by definition and not necessarily always...

Good point. Does the JSON output include both (deployed revision name and latest revision name)? If so, we may want to include both and use those names explicitly (deployedRevisionName, latestRevisionName).

sethvargo avatar Jan 14 '25 14:01 sethvargo

@sethvargo Unfortunately it doesn't seem like this attribute exists... Here's a slightly-obfuscated real JSON response from the gcloud run deploy command using --format json.

{
  "@type": "type.googleapis.com/google.cloud.run.v1.Service",
  "apiVersion": "serving.knative.dev/v1",
  "kind": "Service",
  "metadata": {
    "annotations": {
      "run.googleapis.com/client-name": "gcloud",
      "run.googleapis.com/client-version": "504.0.1",
      "run.googleapis.com/ingress": "all",
      "run.googleapis.com/ingress-status": "all",
      "run.googleapis.com/operation-id": "eb748c25-744e-481e-bce8-0ed4c530d02f",
      "run.googleapis.com/urls": "[\"https://servicename-api-qa-463128594741.us-central1.run.app\",\"https://servicename-api-qa-rri5nwu7ya-uc.a.run.app\"]",
      "serving.knative.dev/creator": "[email protected]",
      "serving.knative.dev/lastModifier": "[email protected]"
    },
    "creationTimestamp": "2024-11-23T07:41:36.186310Z",
    "generation": 233,
    "labels": {
      "cloud.googleapis.com/location": "us-central1",
      "commit-sha": "1c3a3aa06e4b5538684316c38d552da33e6525fc",
      "managed-by": "github-actions"
    },
    "name": "servicename-api-qa",
    "namespace": "463128594741",
    "resourceVersion": "AAYrsUpyFa4",
    "selfLink": "/apis/serving.knative.dev/v1/namespaces/463128594741/services/servicename-api-qa",
    "uid": "e8acfec6-27fe-4868-9482-a9fe445d70db"
  },
  "spec": {
    "template": {
      "metadata": {
        "annotations": {
          "autoscaling.knative.dev/maxScale": "100",
          "autoscaling.knative.dev/minScale": "4",
          "run.googleapis.com/client-name": "gcloud",
          "run.googleapis.com/client-version": "504.0.1",
          "run.googleapis.com/startup-cpu-boost": "true"
        },
        "labels": {
          "client.knative.dev/nonce": "mzmyjcniof",
          "commit-sha": "1c3a3aa06e4b5538684316c38d552da33e6525fc",
          "managed-by": "github-actions",
          "run.googleapis.com/startupProbeType": "Default"
        }
      },
      "spec": {
        "containerConcurrency": 80,
        "containers": [
          {
            "image": "gcr.io/real-intent/servicename-api-qa",
            "ports": [
              {
                "containerPort": 8080,
                "name": "http1"
              }
            ],
            "resources": {
              "limits": {
                "cpu": "4",
                "memory": "16Gi"
              }
            },
            "startupProbe": {
              "failureThreshold": 1,
              "periodSeconds": 240,
              "tcpSocket": {
                "port": 8080
              },
              "timeoutSeconds": 240
            }
          }
        ],
        "serviceAccountName": "[email protected]",
        "timeoutSeconds": 300
      }
    },
    "traffic": [
      {
        "latestRevision": true,
        "percent": 100
      },
      {
        "revisionName": "servicename-api-qa-00001-ned",
        "tag": "pr-preview-12"
      },
      {
        "revisionName": "servicename-api-qa-00225-pam",
        "tag": "pr-preview-123"
      },
      {
        "revisionName": "servicename-api-qa-00231-buf",
        "tag": "pr-preview-124"
      }
    ]
  },
  "status": {
    "address": {
      "url": "https://servicename-api-qa-rri5nwu7ya-uc.a.run.app"
    },
    "conditions": [
      {
        "lastTransitionTime": "2025-01-14T21:31:58.460334Z",
        "status": "True",
        "type": "Ready"
      },
      {
        "lastTransitionTime": "2025-01-14T21:31:57.358992Z",
        "status": "True",
        "type": "ConfigurationsReady"
      },
      {
        "lastTransitionTime": "2025-01-14T21:31:58.423853Z",
        "status": "True",
        "type": "RoutesReady"
      }
    ],
    "latestCreatedRevisionName": "servicename-api-qa-00233-rrh",
    "latestReadyRevisionName": "servicename-api-qa-00233-rrh",
    "observedGeneration": 233,
    "traffic": [
      {
        "revisionName": "servicename-api-qa-00001-ned",
        "tag": "pr-preview-12",
        "url": "https://pr-preview-12---servicename-api-qa-rri5nwu7ya-uc.a.run.app"
      },
      {
        "revisionName": "servicename-api-qa-00002-bug",
        "tag": "pr-preview-13",
        "url": "https://pr-preview-13---servicename-api-qa-rri5nwu7ya-uc.a.run.app"
      },
      {
        "revisionName": "servicename-api-qa-00003-koj",
        "tag": "pr-preview-14",
        "url": "https://pr-preview-14---servicename-api-qa-rri5nwu7ya-uc.a.run.app"
      },
      {
        "revisionName": "servicename-api-qa-00006-tov",
        "tag": "pr-preview-15",
        "url": "https://pr-preview-15---servicename-api-qa-rri5nwu7ya-uc.a.run.app"
      },
      {
        "latestRevision": true,
        "percent": 100,
        "revisionName": "servicename-api-qa-00233-rrh"
      }
    ],
    "url": "https://servicename-api-qa-rri5nwu7ya-uc.a.run.app"
  }
}

I'm wondering now if the intended purpose of this PR is even achievable...

preritdas avatar Jan 14 '25 23:01 preritdas

We could definitely expose latestCreatedRevisionName and latestReadyRevisionName, with the caveat that they have no correlation to whether that revision is serving traffic.

sethvargo avatar Jan 15 '25 00:01 sethvargo

We could definitely expose latestCreatedRevisionName and latestReadyRevisionName, with the caveat that they have no correlation to whether that revision is serving traffic.

@sethvargo I guess the question is less of whether they're serving traffic and more of whether it's deterministically equivalent to the revision that was created due to that specific triggered gcloud run deploy... My intended use case is piping that into a subsequent update-traffic command.

preritdas avatar Jan 15 '25 00:01 preritdas

Hey @preritdas - I'm genuinely not sure. Can you describe more about what you're trying to do. I can try and ask someone on the cloud run team

sethvargo avatar Jan 15 '25 14:01 sethvargo

Hey @preritdas - I'm genuinely not sure. Can you describe more about what you're trying to do. I can try and ask someone on the cloud run team

@sethvargo That would be great. Right now, I have a GitHub action that deploys to Cloud Run on pushes to a branch and to a pull request (with a tag and using --no-traffic). Sometimes, with frequent subsequent pushes, the deployment workflows run concurrently. This works 99% of the time but occasionally when they run concurrently, the regular deployment will finish, then the pull request deployment with no traffic will finish, and only then will the first deployment subsequent command update traffic to the latest, sending all my traffic to a tagged deployment preview that's not supposed to have any traffic.

The simple solution to my specific scenario is creating a new service specifically for deployment previews. So I don't bring this up to say that anything is broken. That said, such a setup outlines the need for the Cloud Run deployment action, more specifically, the gcloud run deploy command, to report back on what it did. If it created a revision because that's the whole point of the command, what is the name of the revision that was created? Not the name of the current latest revision, which is usually the same, but deterministically the name of the revision created by this specific trigger of the command.

preritdas avatar Jan 15 '25 19:01 preritdas

We're also exploring ways of updating the traffic tag for new revisions in a dynamic way.

What we're currently doing in our Cloud Build triggers for push to main and pull request to main events are:

  1. Split up the services into one for preview (PR) and one for main (although it should work within one service)
  2. Tag all newly created revisions with the short SHA commit
  3. Fetch the revision name using gcloud run services describe and filtering on the short SHA commit
  4. Update the tags and include the PR number

However, if I understood you correctly @preritdas, you're facing the exact same issue we experience from time to time where subsequent commits to a PR might fail leaving you with a not so up-to-date PR number tag (potentially). I believe this is solved using the concurrency attribute (which sadly Cloud Build does not support) in a GHA workflow which is why we want to migrate. But seeing as this action doesn't expose the revision name it won't be feasable unless you script the entire thing like we've done for Cloud Build

alenmeister avatar Mar 02 '25 12:03 alenmeister

But seeing as this action doesn't expose the revision name it won't be feasable unless you script the entire thing like we've done for Cloud Build

As shown in https://github.com/google-github-actions/deploy-cloudrun/pull/556#issuecomment-2591307469, the API response does not include the name of the revision that was created. It includes latestCreatedRevisionName, but if you have two concurrent deployments, there's no guarantee that the version returned from the API is the one that you deployed.

/cc @steren for thoughts.

sethvargo avatar Mar 02 '25 14:03 sethvargo

Instead of fetching the auto generate revision name, have you considered specifying a revision name at deployment time?

We have the --revision-suffix flag for that, or, if using YAML, set the name field in Service.spec.template.metadata

steren avatar Mar 02 '25 15:03 steren

--revision-suffix maps to the suffix input already, so that's definitely an option @alenmeister @preritdas

sethvargo avatar Mar 02 '25 20:03 sethvargo