CI execution logic to avoid concurrency

Hi all,
I can’t get my head around the CI excution logic, this is what I would like to achieve:

  • testing: run every commit
  • staging: on all the commits that are tagged with (X.Y.Z) on develop branch. (this should before run testing stage)
  • deploy: on all commits that are tagged with X.Y.Z tag on master branch.(this should before run testing stage and staging test)

and I would want to have just 1 of this case at a time, not that if I push to master a tag 1.1.1 i’ll have 3 test, 2 staging 1 deployment…

how should I define the conditions? this is what I’ve done so far (with no result)

so i’ve

stages:
  - test
  - staging
  - production

where test has no except or only

the staging is

  only:
    -  /^(\d+\.)?(\d+\.)?(\*|\d+)$/

the deploy is

only:
    -  /^(\d+\.)?(\d+\.)?(\*|\d+)$/
except:
   - develop