Skip to content

Merge request metrics incorrect when manual jobs from multiple branches deploy to the same environment

Everyone can contribute. Help move this issue forward while earning points, leveling up and collecting rewards.

Summary

After a successful deployment to a production tier environment we set the first_deployed_to_production_at field for any associated merge requests that are being deployed (to production) for the first time.

To determine which merge requests should be updated, we find merge requests for the project that:

  • Were were merged into the branch being deployed
  • Have no first_deployed_to_production_at set
  • Were merged before the deployment completed
  • Were merged after the previous deployment completed, if one exists (as these are related to the previous deployment, not the current deployment).

The problem lies in excluding MRs that belong to the previous deployment: We assume that all deployments to an environment will be from the same branch, and therefore do not check this when fetching the previous deployment. This means a previous deployment from a different, unrelated branch (but still for the same environment) can be incorrectly considered as having deployed a merge request. Following the rules above, these MRs are then skipped and first_deployed_to_production_at is not set.

Usually this isn't an issue because in most cases merge requests are merged and deployed sequentially, with a flow such as MR1 merged -> Branch1 deployed -> MR2 merged -> Branch2 deployed. Here the previous deployment calculation is correct regardless of branch, because everything happened in the expected order. However, this is not the case when using manual jobs as a deployment job can be triggered at an arbitrary time. This can produce a flow such as MR1 merged -> MR2 merged -> Branch1 deployed -> Branch2 deployed, which is problematic because at the time of Branch2 deployed we incorrectly assume that Branch1 deployed already included MR2's changes.

Steps to reproduce

  1. Create two branches, for example main-1 and main-2.
  2. In each branch, add a gitlab-ci.yml that deploys to the production environment with a manual job. For example:
     deploy:
       script: echo deploy
       environment: production
       when: manual
  3. Create and merge a merge request to main-1.
  4. Create and merge a merge request to main-2.
  5. Go to the latest pipeline for main-1 and trigger the manual deployment job
  6. Go to the latest pipeline for main-2 and trigger the manual deployment job
  7. Using the merge requests API, retrieve the details for both merge requests.
  8. The first_deployed_to_production_at timestamp will be present and correct for the first merge request. For the second merge request, this field is empty.

Possible fixes

See Deployment#update_merge_request_metrics!.

  • Option 1: Only consider a previous_deployment with the same ref as the current deployment when determining which MRs to update.
  • Option 2: Remove the previous_deployment check altogether, on the basis that if first_deployed_to_production_at is not set then the current deployment must be deploying it.
Edited by 🤖 GitLab Bot 🤖