Three merges in ten minutes produced three deploys, running concurrently, and the one that finished last was the oldest commit.
concurrency:
group: deploy-production
cancel-in-progress: false
# for CI on a pull request, the opposite is right
concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true
Two settings, two opposite answers: a superseded CI run should be cancelled and a superseded deploy should not, because cancelling mid-deploy leaves an unknown state. Queuing means the last merge wins by running last, which is what you want, and it also means a slow deploy delays the next — visible as a pending job rather than as a mystery, which is the improvement.