Initially, the plan for uis/devops/continuous-delivery/ci-templates#42 (closed) was to re-implement the migration functionality found in deploy.yml in the terraform-pipeline.yml. However, testing proved that this was going to end up very cumbersome and especially difficult to manage when we have multiple instances of this gcp-cloud-run-app module deployed by a single Terraform repo.
After some research, I found some recommendations for running database migrations using Cloud Run jobs. This sparked the idea of including the migration command as a "pre-deploy" Cloud Run job within this gcp-cloud-run-app Terraform module which is triggered whenever the container image is updated. This has the added benefit of natively managing connections to Cloud SQL and also, by default, ends up being a one to one relationship with our Cloud Run services, meaning projects which deploy multiple instances of the gcp-cloud-run-app module are no more difficult to manage.
I've explained how it hangs together in the README.md so I won't go over it again, here is a copypasta.
The `v8` release introduced an `enable_pre_deploy_job` variable. When set to `true` a [Cloud
Run job](https://cloud.google.com/run/docs/create-jobs) is created to execute a configurable command
_before_ the main Cloud Run service is deployed. The initial use case for this is to run database
migrations, however in the future we're sure there'll be more.
The pre-deploy job uses the image specified in `var.pre_deploy_job_image_name` if set, otherwise it
falls back to the same `var.image_name` that the main service uses. The command and arguments that
the job executes are configurable via the `pre_deploy_job_command` and `pre_deploy_job_args`
A `null_resource` is also configured to execute the pre-deploy job whenever it detects that the
value of `var.image_name` has changed (or at every `apply` if `var.force_pre_deploy_job` is set to
`true`). This uses the `gcloud run jobs execute` command and is run in the context of the
`terraform-deploy` service account via an access token. Using `null_resource` is never ideal.
However, in this situation it provides a very handy way to trigger this simple job so it has been
To ensure that the pre-deploy job always runs _before_ a new revision of the Cloud Run webapp
service is deployed, the resources in question are explicitly configured with `depends_on`
relationships, as follows.
1. The `google_cloud_run_v2_job.pre_deploy` Cloud Run job has no `depends_on` relationships defined
and is therefore deployed first.
2. The `null_resource.pre_deploy_job_trigger` resource depends on
`google_cloud_run_v2_job.pre_deploy` and therefore won't be deployed until the Cloud Run job is
3. Finally, the `google_cloud_run_service.webapp` Cloud Run service depends on
`null_resource.pre_deploy_job_trigger`, meaning it is only deployed once the
`null_resource.pre_deploy_job_trigger` has executed successfully.
Seeing as we've literally just bumped the major version of this module (but nobody is actually using v8 yet) I am proposing just adding these changes to v8.