You can add a bot user to a required approval rule (requires Premium subscription) and use a CICD job with the bot user token to approve MRs via the API only after full tests pass.
Might look something like a job in the final stage of your pipeline that has similar rules:
to your "full" pipeline:
stages:
# ...
- approve_mr
approval_job:
stage: approve_mr # or the builtin ".post" stage can also be used
rules:
- # ... same rules as "full" (not "fast") pipeline job(s)
script:
- # ... script MR approval via API here
You could also use needs:
or dependencies:
as another way to ensure the required jobs are successful before this job runs.
Webhooks could also be used as an alternative to the pipeline job -- the hook might receive MR/pipeline events and checks if the full pipeline is configured ran successfully before submitting the approval.
In GitLab ultimate, there is also external status checks which could also achieve something similar.
Without GitLab Premium, you can kind of approximate the behavior of a required approval by using comment threads (similarly, create/resolve with the API) and enable the setting to prevent merge unless all threads are resolved. However, it's worth noting any user with permissions can resolve a thread, so it's not an impassable barrier, but it should help prevent accidents.