On that last one, there's a potential bug in the deployment pipeline here – deploys could run simultaneously or some bad luck on runner speed could even see an older version of the code go out after a newer version. Combined with the automated database migrations this could be quite a big problem!
Actions thankfully solved this recently with the `concurrency` key that lets you form a serial queue by a given key such as the branch name.
What happens if there are conflicting migrations on two "parallel" branches?
What happens in you bad luck situation when commits are pushed in rapid succession on the same branch?
Does that address your need?
Edit with more context: We use CI for deploying to GitLab.com and use resource_group to prevent multiple jobs from running concurrently. What we lack is the ability to prevent multiple pipelines from running concurrently (resource_group is at the job level). It looks like concurrency for actions https://docs.github.com/en/actions/reference/workflow-syntax... can work on groups which is a bit nicer. There is some discussion about making this better for GitLab in https://gitlab.com/gitlab-org/gitlab/-/issues/217522
It's super flexible and you can do literally anything.
As for running migrations on the same database from multiple branches, not a good idea. Probably best to decide on the branch that is the release branch (maybe main/master) and only deploy from that.
GitHub Action's, Semaphore's, or even Jenkin's, concurrency primitives are pretty capable so I'd probably go with one of those.
Apart from feeling like they were in that sort of transition, GitLab's docs were fine, better than Circle's, but I find GitHub Actions much clearer.