Circleci: How to deploy depending on git tag

9.6k views Asked by At

Is there a way to restrict circleci deployment on checkings that have a specific git tag?

Currently I am using this

...
deployment:
  dockerhub:
    branch: master
    commands:
      - docker login -e $DOCKER_EMAIL -u $DOCKER_USER -p $DOCKER_PASS
      - docker push abcdef

Instead of branch: master I would like to write something like tag: /release_.*/

Background: I would like to set docker tags depending on git tags. So for example, whenever something is committed to master, a new docker images with latest tag will be created and pushed. Whenever a special git tag is set (e.g. release_1.0_2015-06-13) a new docker image with a tag 1.0 will be created and pushed.

Alternative is to only use different branches according to the different tags. But I would like to use tags to mark a specific release.

4

There are 4 answers

6
Dean On BEST ANSWER

It looks like this was added since Kim answered.

Normally, pushing a tag will not run a build. If there is a deployment configuration with a tag property that matches the name of the tag you created, we will run the build and the deployment section that matches.

In the below example, pushing a tag named release-v1.05 would trigger a build & deployment. Pushing a tag qa-9502 would not trigger a build.

deployment:
  release:
    tag: /release-.*/
    owner: circleci
    commands:
      - ./deploy_master.sh
2
kimh On

This is Kim from CircleCI.

To archive what you want to do, I think you must be able to trigger a build when a new tag is pushed to Github. However, only a new commit will trigger a build, so it seems this is not doable as of now. Sorry!

UPDATE: This feature has now been implemented: https://circleci.com/docs/configuration/#tags

10
mediafreakch On

I'm putting this here for people that followed the documentation but didn't get this to work. CircleCI seems to ignore tags at all if you have a branch only configuration in your general settings. Tagged commits will appear as "Not run" that way.

To build only on specific branches and deploy on a specific tag, use the branch and ignore option along with a negative lookahead regex:

# circle.yml
general:
  branches:
    ignore:
      - /^(?!master).*$/
deployment:
  beta:
    tag: /v[0-9]+(\.[0-9]+)*(-.*)*/
    owner: mediafreakch
    commands:
      - deploy.sh

This will build every commit to master and deploy if it's a tagged commit. To tag a commit, I use npm version.

0
Leigh Mathieson On

Here is a full working example note version needs to be 2.1 or above. The staging_workflow will run only on push to main branch (not on a git tags push) and the prod_workflow will run only on a git tag push (not a push to main) which starts with 'R..' - intended use is for production deploys to git tag your commit with a release tag:

git tag -a R2.1.0 -m "Some new release feature"

Then push the tag:

git push origin --tags

Also included is as example of how to integrate with AWS using assume-role-with-web-identity (this is preferred over using permanent AWS credentials stored on CirceCI) It assumes you have set up an IDP in AWS (you just need the CircleCI organisation Id and add an admin role) then store the role ARN in CircleCI Organisations context. The example here is if you have 2 AWS accounts for staging and prod, contexts are aws-staging and aws-prod respectively, then the only env var you need in the context is: AWS_ROLE_ARN although you may wish to include AWS_DEFAULT_REGION.

Here's an excerpt from my package.json (nodeJs project) so you can see the scripts the pipeline is running including linting, testing and CICDPackage & CICDDeploy (AWS SAM/ serverless project - for staging and prod using ‘sam package’ and ‘sam deploy’, I use sam sync for dev stacks as it's faster):

package.json excerpt:

"scripts": {
    "test": "jest",
    "watchTestFiles": "jest --watch --verbose=false",
    "lint": "eslint \"src/**/*.js\"",
    "build": "node scripts/bundle",
    "CICDPackage": "sam package --s3-bucket serverless-packaged-artifacts --template template.yaml --output-template-file templateOut.yaml --region eu-west-1",
    "CICDDeploy": "sam deploy --template-file templateOut.yaml --stack-name some-stack-name --capabilities CAPABILITY_NAMED_IAM --region eu-west-1"
}

config.yml

version: 2.1
orbs:
  aws-cli: circleci/[email protected]

jobs:
  test_and_lint:
    docker:
      - image: cimg/node:lts
    steps:
      - checkout
      - run: npm i
      - run: npm run lint
      - run: npm run test

  deploy_staging:
    docker:
      - image: cimg/node:lts
    steps:
      - checkout
      - run: npm i
      - run: npm run build
      - aws-cli/setup
      # if using standard AWS user credentials stored as organisation context & not OIDC token
      # - run: aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID --profile default
      # - run: aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY --profile default
      # - run: aws configure set default.region $AWS_DEFAULT_REGION
      - run: curl -L https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip -o aws-sam-cli-linux-x86_64.zip
      - run: unzip aws-sam-cli-linux-x86_64.zip -d sam-installation
      - run: sudo ./sam-installation/install
      - run:
          name: AWS authentication
          command: |
            read -r AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN \<<< \
              $(aws sts assume-role-with-web-identity \
              --role-arn ${AWS_ROLE_ARN} \
              --role-session-name "CircleCI-${CIRCLE_WORKFLOW_ID}-${CIRCLE_JOB}" \
              --web-identity-token $CIRCLE_OIDC_TOKEN \
              --duration-seconds 3600 \
              --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
              --output text)
              echo export AWS_ACCESS_KEY_ID="$AWS_ACCESS_KEY_ID" >> $BASH_ENV
              echo export AWS_SECRET_ACCESS_KEY="$AWS_SECRET_ACCESS_KEY" >> $BASH_ENV
              echo export AWS_SESSION_TOKEN="$AWS_SESSION_TOKEN" >> $BASH_ENV
      - run: npm run CICDPackage
      - run: npm run CICDDeploy

  deploy_prod:
    docker:
      - image: cimg/node:lts
    steps:
      - checkout
      - run: npm i
      - run: npm run build
      - aws-cli/setup
      # if using standard AWS user credentials stored as organisation context & not OIDC token
      # - run: aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID --profile default
      # - run: aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY --profile default
      # - run: aws configure set default.region $AWS_DEFAULT_REGION
      - run: curl -L https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip -o aws-sam-cli-linux-x86_64.zip
      - run: unzip aws-sam-cli-linux-x86_64.zip -d sam-installation
      - run: sudo ./sam-installation/install
      - run:
          name: AWS authentication
          command: |
            read -r AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN \<<< \
              $(aws sts assume-role-with-web-identity \
              --role-arn ${AWS_ROLE_ARN} \
              --role-session-name "CircleCI-${CIRCLE_WORKFLOW_ID}-${CIRCLE_JOB}" \
              --web-identity-token $CIRCLE_OIDC_TOKEN \
              --duration-seconds 3600 \
              --query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \
              --output text)
              echo export AWS_ACCESS_KEY_ID="$AWS_ACCESS_KEY_ID" >> $BASH_ENV
              echo export AWS_SECRET_ACCESS_KEY="$AWS_SECRET_ACCESS_KEY" >> $BASH_ENV
              echo export AWS_SESSION_TOKEN="$AWS_SESSION_TOKEN" >> $BASH_ENV
      - run: npm run CICDPackage
      - run: npm run CICDDeploy

workflows:
  staging_workflow:
    when:
      and:
        - or:
            - matches:
                pattern: "^master$"
                value: << pipeline.git.branch >>
        - not:
            matches:
              pattern: "^R.+$"
              value: << pipeline.git.tag >>
    jobs:
      - test_and_lint
      - deploy_staging:
          context: aws-staging
          requires:
            - test_and_lint

  prod_workflow:
    when:
      and:
        - or:
            - matches:
                pattern: "^master$"
                value: << pipeline.git.branch >>
        - or:
            - matches:
                pattern: "^R.+$"
                value: << pipeline.git.tag >>
    jobs:
      - test_and_lint
      - deploy_prod:
          context: aws-prod
          requires:
            - test_and_lint

Note it also exports the temp AWS credentials to >> $BASH_ENV so they are available in other steps