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_atset - 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
- Create two branches, for example
main-1andmain-2. - In each branch, add a
gitlab-ci.ymlthat deploys to theproductionenvironment with a manual job. For example:deploy: script: echo deploy environment: production when: manual - Create and merge a merge request to
main-1. - Create and merge a merge request to
main-2. - Go to the latest pipeline for
main-1and trigger the manual deployment job - Go to the latest pipeline for
main-2and trigger the manual deployment job - Using the merge requests API, retrieve the details for both merge requests.
- The
first_deployed_to_production_attimestamp 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_deploymentwith the samerefas the current deployment when determining which MRs to update. - Option 2: Remove the
previous_deploymentcheck altogether, on the basis that iffirst_deployed_to_production_atis not set then the current deployment must be deploying it.