Skip to content

Bitbucket Pipelines

Arkadi Shishlov edited this page Mar 5, 2021 · 2 revisions

Hub CLI-based deployments could be integrated into CI/CD Bitbucket Pipelines.

For example, here we have infra repository with hub.yaml defining infrastructure components, backend repo for the Java-based backend application, and webapp repo for React-based Web UI. Pipeline in infra deploys the whole stack. Pipelines in backend and webapp configures coresponding Kubernetes deployments only. The pipelines are configured with environment-specific variables:

  • HUB_DOMAIN_NAME is stack DNS domain name app.domain.tld
  • HUB_STATE and HUB_ELABORATE pointing to s3://123456789012.superhub.io/app.domain.tld/hub/infra/hub.state/elaborate
  • HUB_CRYPTO_AWS_KMS_KEY_ARN set to state encryption key arn:aws:kms:us-east-2:123456789012:alias/infra
  • AWS_DEFAULT_REGION us-east-2
  • AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY credentials
  • EKS_CLUSTER_NAME set to applications EKS cluster name

Infra hub.yaml references in-tree components and separate app's repositories:

version: 1
kind: stack
meta:
  name: Infra
components:
  - name: external-dns
    source:
      dir: components/external-dns
      git:
        remote: 'https://github.com/agilestacks/components.git'
        ref: master
        subDir: edns
...
  - name: backend
    source:
      dir: ../backend
  - name: webapp
    source:
      dir: ../webapp

lifecycle:
  verbs:
    - deploy
    - undeploy
  order:
    - external-dns
...
    - backend
    - webapp

Infra bitbucket-pipelines.yml clones extra application's repositories, decrypts environment-specific secrets, prepares Kubeconfig, then deploys the stack:

image: atlassian/default-image:2

definitions:
  steps:
  - step: &hub-deploy
      name: 'Deploy'
      image: agilestacks/toolbox
      script:
      - aws eks update-kubeconfig --name $EKS_CLUSTER_NAME --alias $HUB_DOMAIN_NAME --kubeconfig .kubeconfig
      - sops --decrypt --input-type dotenv --output-type dotenv --output .env.secrets .env.secrets.$BITBUCKET_DEPLOYMENT_ENVIRONMENT
      - cat .env.ci .env.versions .env.secrets > .env
      - echo "HUB_KUBECONFIG=\"$(pwd)/.kubeconfig\"" >> .env
      - sed -i -e 's|\.\./|repos/|' hub.yaml
      - hub stack deploy
      - git tag -f "$BITBUCKET_DEPLOYMENT_ENVIRONMENT"
      - git push -f origin "refs/tags/$BITBUCKET_DEPLOYMENT_ENVIRONMENT"

pipelines:
  branches:
    master:
    - step:
        name: 'Clone apps repositories'
        script:
        - mkdir -p repos
        - git clone --depth 1 [email protected]:org/backend.git repos/backend
        - git clone --depth 1 [email protected]:org/webapp.git  repos/webapp
        - git -C repos/backend log -n 1 --format='IMAGE_BACKEND_TAG="%H"' >>.env.versions
        - git -C repos/webapp  log -n 1 --format='IMAGE_WEBAPP_TAG="%H"'  >>.env.versions
        - rm -rf repos/*/.git
        artifacts:
        - repos/**
        - .env.versions

    - step:
        <<: *hub-deploy
        name: 'Deployment to Dev'
        deployment: dev

    - step:
        <<: *hub-deploy
        name: 'Deployment to Staging'
        deployment: staging
        trigger: manual

    - parallel:
      - step:
          <<: *hub-deploy
          name: 'Deployment to US'
          deployment: production us
          trigger: manual

      - step:
          <<: *hub-deploy
          name: 'Deployment to UK'
          deployment: production uk
          trigger: manual

Backend bitbucket-pipelines.yml pushes image into multiple regions and updates the deployment. The key part here is hub render pulling deployed stack parameters from S3 state to render the template. sed is further used to substitute commit hash as image tag:

image: maven

definitions:
  services:
    docker:
      memory: 3072

  steps:
  - step: &test
      name: Tests
      size: 2x
      caches:
      - maven
      script:
      - mvn --no-transfer-progress verify

  - step: &render-and-apply
      name: 'Deploy'
      image: agilestacks/hub
      script:
      - hub render 'deployments/*.yaml.template' -c backend -m $HUB_ELABORATE -s $HUB_STATE
      - sed -i -E -e "s|^(\s+image:[^:]+)(:.+)?|\1:$BITBUCKET_COMMIT|" deployments/deployment.yaml
      - cat deployments/deployment.yaml
      # atlernativelly we could have this implemented with toolbox
      # image: agilestacks/toolbox
      # - aws eks update-kubeconfig --name $EKS_CLUSTER_NAME
      # - kubectl apply -f deployments/deployment.yaml
      - pipe: atlassian/aws-eks-kubectl-run:1.4.1
        variables:
          AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
          AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
          AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
          CLUSTER_NAME: $EKS_CLUSTER_NAME
          KUBECTL_COMMAND: apply
          RESOURCE_PATH: deployments/deployment.yaml
      - git tag -f "$BITBUCKET_DEPLOYMENT_ENVIRONMENT"
      - git push -f origin "refs/tags/$BITBUCKET_DEPLOYMENT_ENVIRONMENT"

pipelines:
  pull-requests:
    feature/*:
    - step:
        <<: *test

  branches:
    master:
    - step:
        <<: *test

    - step:
        name: Build JARs
        caches:
        - maven
        script:
        - mvn --no-transfer-progress install -Dmaven.test.skip=true
        artifacts:
        - target/**

    - step:
        name: Build and Push Image
        deployment: images
        services:
        - docker
        script:
        - docker build -t backend:latest .
        - pipe: atlassian/aws-ecr-push-image:1.2.2
          variables:
            AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
            AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
            AWS_DEFAULT_REGION: us-east-2
            IMAGE_NAME: backend
            TAGS: $BITBUCKET_COMMIT latest
        - pipe: atlassian/aws-ecr-push-image:1.2.2
          variables:
            AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
            AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
            AWS_DEFAULT_REGION: eu-west-2
            IMAGE_NAME: backend
            TAGS: $BITBUCKET_COMMIT latest

    - step:
        <<: *render-and-apply
        name: 'Deployment to Dev'
        deployment: dev

    - step:
        <<: *render-and-apply
        name: 'Deployment to Staging'
        deployment: staging
        trigger: manual

    - parallel:
      - step:
          <<: *render-and-apply
          name: 'Deployment to US'
          deployment: production us
          trigger: manual

      - step:
          <<: *render-and-apply
          name: 'Deployment to UK'
          deployment: production uk
          trigger: manual

Webapp bitbucket-pipelines.yml is similar to backend's pipeline:

options:
  size: 2x

definitions:
  services:
    docker:
      memory: 4096

  steps:
  - step: &render-and-apply
      name: 'Deploy'
      image: agilestacks/hub
      script:
      - hub render 'deployments/*.yaml.template' -c webapp -m $HUB_ELABORATE -s $HUB_STATE
      - sed -i -E -e "s|^(\s+image:[^:]+)(:.+)?|\1:$BITBUCKET_COMMIT|" deployments/deployment.yaml
      - cat deployments/deployment.yaml
      - pipe: atlassian/aws-eks-kubectl-run:1.4.1
        variables:
          AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
          AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
          AWS_DEFAULT_REGION: $AWS_DEFAULT_REGION
          CLUSTER_NAME: $EKS_CLUSTER_NAME
          KUBECTL_COMMAND: apply
          RESOURCE_PATH: deployments/deployment.yaml
      - git tag -f "$BITBUCKET_DEPLOYMENT_ENVIRONMENT"
      - git push -f origin "refs/tags/$BITBUCKET_DEPLOYMENT_ENVIRONMENT"

pipelines:
  branches:
    master:
    - step:
        name: 'Build and Push Image'
        deployment: images
        services:
        - docker
        caches:
        - docker
        script:
        - docker build -t webapp:latest .
        - pipe: atlassian/aws-ecr-push-image:1.2.2
          variables:
            AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
            AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
            AWS_DEFAULT_REGION: us-east-2
            IMAGE_NAME: webapp
            TAGS: $BITBUCKET_COMMIT latest
        - pipe: atlassian/aws-ecr-push-image:1.2.2
          variables:
            AWS_ACCESS_KEY_ID: $AWS_ACCESS_KEY_ID
            AWS_SECRET_ACCESS_KEY: $AWS_SECRET_ACCESS_KEY
            AWS_DEFAULT_REGION: eu-west-2
            IMAGE_NAME: webapp
            TAGS: $BITBUCKET_COMMIT latest

    - step:
        <<: *render-and-apply
        name: 'Deployment to Dev'
        deployment: dev

    - step:
        <<: *render-and-apply
        name: 'Deployment to Staging'
        deployment: staging
        trigger: manual

    - parallel:
      - step:
          <<: *render-and-apply
          name: 'Deployment to US'
          deployment: production us
          trigger: manual

      - step:
          <<: *render-and-apply
          name: 'Deployment to UK'
          deployment: production uk
          trigger: manual
Clone this wiki locally