google-github-actions / deploy-cloud-functions

A GitHub Action that deploys source code to Google Cloud Functions.
https://cloud.google.com/functions
Apache License 2.0
304 stars 66 forks source link

Update V3.x ReadMe to Bring Back "Declarative" Message #421

Closed seth-acuitymd closed 3 weeks ago

seth-acuitymd commented 1 month ago

TL;DR

The v2 README has a block of text near the top that states

This GitHub Action is declarative, meaning it will overwrite any values on an existing Cloud Function deployment. If you manually deployed a Cloud Function, you must specify all parameters in this action. Any unspecified values will be reverted to their default value (which is usually "null").

The V3 README does not have that text, as such - when using the v3 action, I accidentally defaulted a bunch of config I was specifying via Terraform (that's why we test in lower envs first 😄 )

Detailed design

No response

Additional information

If this GitHub Action is not meant to be declarative in the way that v2 was, then there's a bug, but I assume since v2 is declarative, that v3 will be as well

sethvargo commented 1 month ago

Hi @seth-acuitymd - it's not supposed to be anymore 😄 . Do you have examples of the specific field(s) that were overwritten?

P.S. Cool name.

seth-acuitymd commented 1 month ago

P.S. Cool name. Right back at ya!

Here's the block in my GH Action Workflow

- id: 'Deploy'
  uses: 'google-github-actions/deploy-cloud-functions@v3'
  timeout-minutes: 10
  with:
    name: '<FUNCTION_NAME>'
    runtime: 'python311'
    region: 'us-east1'
    entry_point: '<FUNCTION_NAME>'
    source_dir: './cloud_functions/<FUNCTION_NAME>'
    project_id: '<PROJECT_NAME>'

After running this in my dev environment, I later made an unrelated Terraform change, and saw that my state had drifted for that specific function (this function has existed for many months) - was able to confirm that these changes were made when I checked the UI

~ resource "google_cloudfunctions2_function" "territory_visualizer" {
        id               = "projects/<PROJECT_NAME>/locations/us-east1/functions/<FUNCTION_NAME>"
        name             = "<FUNCTION_NAME>"
        # (11 unchanged attributes hidden)

      ~ service_config {
          ~ available_cpu                    = "0.1666" -> "1"
          ~ available_memory                 = "256Mi" -> "2G"
          ~ environment_variables            = {
              + "ENVIRONMENT"      = "development"
                # (1 unchanged element hidden)
            }
          ~ ingress_settings                 = "ALLOW_ALL" -> "ALLOW_INTERNAL_ONLY"
          ~ max_instance_count               = 100 -> 60
          ~ service_account_email            = "<DEFAULT_COMPUTE_SERVICE_ACCOUNT" -> "<FUNCTION_SPECIFIC_SERVICE_ACCOUNT>"
          ~ timeout_seconds                  = 60 -> 1800
            # (8 unchanged attributes hidden)

          + secret_environment_variables {
              + key        = "<SECRET_KEY>"
              + project_id = "<PROJECT_NAME>"
              + secret     = "<SECRET>"
              + version    = "latest"
            }
        }
    }

So it looks like it modified:

Thanks for looking my friend! Let me know if I can provide more info!

sethvargo commented 1 month ago

Can you apply that Terraform, then re-run the GitHub Action with GitHub logging enabled and send the output? You didn't set any environment_variables in the action.yml, so they should not have been set upstream.

Or if you can give me a Terraform snippet and full action.yml, I can try to reproduce this myself.

seth-acuitymd commented 1 month ago

@sethvargo yessir! I'll have that over ASAP - didn't want you to think this was getting stale!

seth-acuitymd commented 3 weeks ago

function.tf.txt action.yml.txt sorry for the delay!

sethvargo commented 3 weeks ago

Hi @seth-acuitymd your terraform uses node22, but your github action specifies python - that would trigger a full rebuild since you cannot change the environment runtime like that.

sethvargo commented 3 weeks ago

Hi @seth-acuitymd - I modified the Terraform to make it work. The first thing I noticed is that, without running any GitHub Action, Terraform is detecting changes:

  # google_cloudfunctions2_function.function_name will be updated in-place
  ~ resource "google_cloudfunctions2_function" "function_name" {
        id               = "projects/sethvargo-dev-e4e82/locations/us-east1/functions/function"
        name             = "function"
        # (11 unchanged attributes hidden)

      ~ service_config {
          ~ environment_variables            = {
              - "LOG_EXECUTION_ID" = "true" -> null
                # (1 unchanged element hidden)
            }
            # (14 unchanged attributes hidden)

            # (1 unchanged block hidden)
        }

        # (1 unchanged block hidden)
    }

Plan: 0 to add, 1 to change, 0 to destroy.

This repeats no matter how many times I apply the changes. If I ignore that, I think there could be a bug/misunderstanding in the FieldMask documentation for Cloud Functions which states (emphasis mine):

The list of fields to be updated. If no field mask is provided, all provided fields in the request will be updated.

My interpretation of that was, if no field is provided, the value will not be touched. The payload being produced by the GitHub Action YAML does not include any secrets or environment variables, so I would expect those fields to be untouched:

##[debug]Compiled Cloud Function definition: {
##[debug]  "name": "function",
##[debug]  "environment": "GEN_2",
##[debug]  "buildConfig": {
##[debug]    "runtime": "nodejs22",
##[debug]    "entryPoint": "function"
##[debug]  },
##[debug]  "serviceConfig": {
##[debug]    "allTrafficOnLatestRevision": true,
##[debug]    "availableMemory": "256Mi",
##[debug]    "ingressSettings": "ALLOW_ALL",
##[debug]    "timeoutSeconds": 60
##[debug]  }
##[debug]}

However, it seems like those fields are being modified, even though they aren't sent with the payload. I think that means we need to construct a field mask (sigh) by iterating over the object. It'll take me a bit to figure out a good way to do that.

seth-acuitymd commented 3 weeks ago

Hi @seth-acuitymd your terraform uses node22, but your github action specifies python - that would trigger a full rebuild since you cannot change the environment runtime like that.

@sethvargo - We have two cloud functions we deploy, one in Node and one in Python, I think I grabbed the Action for one, and the Terraform for the other, my bad! 😭

sethvargo commented 3 weeks ago

It's all good - I got it working and was able to reproduce it.