diff --git a/README.md b/README.md
index 78e22c7695568c52e43d317ff4522069b1e2d8e4..8b8e58ae8b96a91377bbc110b8f9003089495bfd 100644
--- a/README.md
+++ b/README.md
@@ -1,74 +1,100 @@
 # GCP Cloud Run manager terraform module
 
-This module manages a Cloud Run-hosted container. It takes care of making
-sure the container is connected to a Cloud SQL instance and sets
-environment variables on the application.
+This module manages a Cloud Run-hosted container. It takes care of making sure the container is
+connected to a Cloud SQL instance and sets environment variables on the application.
 
-Specify the project to deploy into on the command line. So, for
-example, to deploy to the project ``my-project``:
+Specify the project to deploy into on the command line. So, for example, to deploy to the project
+`my-project`:
 
 ```console
 $ terraform init
 $ terraform apply -var project=my-project
 ```
 
-In this example, terraform is configured to use default application credentials.
-For Google APIs and these credentials should correspond to a user with owner or
-editor access to the target project. You can use the ``gcloud`` command line
-tool to set your personal credentials as application default credentials. See
-the ``gcloud auth application-default`` command output for more information.
+In this example, terraform is configured to use default application credentials. For Google APIs and
+these credentials should correspond to a user with owner or editor access to the target project. You
+can use the `gcloud` command line tool to set your personal credentials as application default
+credentials. See the `gcloud auth application-default` command output for more information.
 
 ## Versioning
 
-The `master` branch contains the tip of development and corresponds to the `v4`
-branch. The `v1`, `v2` and `v3` branches will maintain source compatibility with
-the initial release.
+The `master` branch contains the tip of development and corresponds to the `v8` branch. The `v1`,
+`v2`, `v3` etc. branches will maintain source compatibility with the initial release.
 
 ## Ingress style
-There are two supported ingress styles depending on `var.ingress_style` variable.
-
-`var.ingress_style` can be: 
 
-- `domain-mapping` (default): passing DNS domains as `var.dns_names` or `var.dns_name`,
-which takes precedence over `var.dns_names`, will create domain mappings to the Cloud
-Run service. Before setting this, you *must* have verified ownership of the provided
-domains with Google. [Instructions on how to do
-this](https://guidebook.devops.uis.cam.ac.uk/en/latest/notes/google-domain-verification/)
-can be found in the DevOps division guidebook.
+There are two supported ingress styles depending on `var.ingress_style` variable.
 
-- `load-balancer`: a load balancer will be configured instead of a domain mapping. The
-DNS domains in `var.dns_names` or `var.dns_name`, which takes precedence over `var.dns_names`,
-will get Google-managed or custom TLS certificates depending on `var.use_ssl_certificates`
-and `var.ssl_certificates`. An IPv6 address can also be allocated to the load balancer if
-`var.enable_ipv6` is `true`.
+`var.ingress_style` can be:
+
+- `domain-mapping` (default): passing DNS domains as `var.dns_names` or `var.dns_name`, which takes
+  precedence over `var.dns_names`, will create domain mappings to the Cloud Run service. Before
+  setting this, you _must_ have verified ownership of the provided domains with Google. [Instructions
+  on how to do
+  this](https://guidebook.devops.uis.cam.ac.uk/en/latest/notes/google-domain-verification/) can be
+  found in the DevOps division guidebook.
+
+- `load-balancer`: a load balancer will be configured instead of a domain mapping. The DNS domains
+  in `var.dns_names` or `var.dns_name`, which takes precedence over `var.dns_names`, will get
+  Google-managed or custom TLS certificates depending on `var.use_ssl_certificates` and
+  `var.ssl_certificates`. An IPv6 address can also be allocated to the load balancer if
+  `var.enable_ipv6` is `true`.
+
+## Pre-deploy Cloud Run job
+
+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`
+variables.
+
+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
+accepted.
+
+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
+   deployed successfully.
+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.
 
 ## Monitoring and Alerting
 
-If the variable [alerting_email_address](variables.tf) is set, the module adds
-basic uptime *alerting* via email for failing http polling.
+If the variable [alerting_email_address](variables.tf) is set, the module adds basic uptime
+_alerting_ via email for failing http polling.
 
-If the variable [disable_monitoring](variables.tf) is true, the module will
-disable *monitoring*. This is different from disabling alerting; if no
-alerting email addresses are provided, the uptime checks will still be
-configured, there just won't be any alerts sent if they fail. Disabling
-monitoring will also disable alerting as without any monitoring there is nothing
-to alert(!)
+If the variable [disable_monitoring](variables.tf) is true, the module will disable _monitoring_.
+This is different from disabling alerting; if no alerting email addresses are provided, the uptime
+checks will still be configured, there just won't be any alerts sent if they fail. Disabling
+monitoring will also disable alerting as without any monitoring there is nothing to alert(!)
 
 See [variables.tf](variables.tf) for how to configure alerting and monitoring.
 
-Note that the project containing resources to be monitored must be in a
-Stackdriver monitoring workspace and this must be configured manually. At the
-time of writing there is no terraform support for this. This module will error
-when applying if this is not so.
+Note that the project containing resources to be monitored must be in a Stackdriver monitoring
+workspace and this must be configured manually. At the time of writing there is no terraform support
+for this. This module will error when applying if this is not so.
 
-Stackdriver distinguishes between workspaces and projects within those
-workspaces. Each workspace must have a host project and that project *must* be
-the default project of the `google.stackdriver` provider used by this module.
-The `google.stackdriver` must be configured with credentials allowing monitoring
-resources to be created in the *host* project.
+Stackdriver distinguishes between workspaces and projects within those workspaces. Each workspace
+must have a host project and that project _must_ be the default project of the `google.stackdriver`
+provider used by this module. The `google.stackdriver` must be configured with credentials allowing
+monitoring resources to be created in the _host_ project.
 
-If the workspace host project differs from the project which contains the
-resources to be monitored, you can use a provider alias:
+If the workspace host project differs from the project which contains the resources to be monitored,
+you can use a provider alias:
 
 ```tf
 provider "google" {
@@ -96,12 +122,11 @@ module "cloud_run_service" {
 ### Monitoring instances which require service account authentication
 
 If `allow_unauthenticated_invocations` is not true, a Cloud Function will be created which
-authenticates via a service account, allowing the StackDriver monitoring to call the Cloud
-Function, with the Cloud Function authentication and proxying the request to the Cloud Run
-instance.
+authenticates via a service account, allowing the StackDriver monitoring to call the Cloud Function,
+with the Cloud Function authentication and proxying the request to the Cloud Run instance.
 
-Because this requires a Cloud Function to be created, the `cloudfunctions.googleapis.com`
-service should be enabled on the project that houses the Cloud Run instance.
+Because this requires a Cloud Function to be created, the `cloudfunctions.googleapis.com` service
+should be enabled on the project that houses the Cloud Run instance.
 
 ## Static Egress IP
 
@@ -112,26 +137,25 @@ from the cloud run through a static ip.
 **Important!**
 
 The static ip is configured with `prevent_destroy = true`, meaning that it cannot be destroyed
-without removing it from terraform state using `terraform state rm` and then manually destroying
-the resource within the GCP console. This is to prevent accidental destruction of an IP which
-is likely to be whitelisted within firewall configuration that lives outside of our deployments.
+without removing it from terraform state using `terraform state rm` and then manually destroying the
+resource within the GCP console. This is to prevent accidental destruction of an IP which is likely
+to be whitelisted within firewall configuration that lives outside of our deployments.
 
 ## Secrets as Volumes and Env Vars
 
-Secret Manager secrets can be as environment variables or volume mounts (files) in the 
-running container.
+Secret Manager secrets can be as environment variables or volume mounts (files) in the running
+container.
 
 The service account that Cloud Run runs as needs access to the secrets for this feature to work.
 Thus, this module gives `secretAccessor` role to that service account for the secrets passed on
 `secrets_volume` and `secrets_envars`.
 
-Any number of items in the list is supported and not defining these variables
-when calling this module is acceptable. The path of the mounted file will be
-based on `path/name`.
+Any number of items in the list is supported and not defining these variables when calling this
+module is acceptable. The path of the mounted file will be based on `path/name`.
 
-For the example configuration below the files will be `/secrets-1/foobarfile1`
-and `/secrets-2/foobarfile2`. A common `path` for multiple secrets is not supported, they must
-be unique.
+For the example configuration below the files will be `/secrets-1/foobarfile1` and
+`/secrets-2/foobarfile2`. A common `path` for multiple secrets is not supported, they must be
+unique.
 
 > Note: `name` should only have alphanumeric characters, hyphens and underscores.