CI/CD - Practical Benefits

Danilo Assis

Danilo Assis

daniloab_daniloab
Woovi Logo

Tech Lead

Overview

  • What is CI/CD and why is it important?
  • The benefits of CI/CD
  • Pipeline
  • CI/CD at Woovi
  • CircleCI
  • BOTina
  • CI/CD Minimal Example
  • Platforms and Clouds

What is CI/CD and why is it important?

  • Deliver high-quality software
  • Faster
  • Automated
  • Reliable
  • Safer
  • Previews of Backend and Frontend
  • No human interaction

The benefits of CI/CD

  • Development cycle
  • Catch and fix bugs early
  • Overall cost reduction of bug fix
  • Efficient workflows
  • Overall improvement in quality and delivery

Workflows and Pipelines

  • Automated steps/stages
  • Predefined rules and conditions
  • Ensure that every change pass by the same checks from steps/stages
  • Conditional build
  • Split tests

Woovi CI/CD

  • CircleCI
  • GitHub Actions
  • BOTina
  • Slack
  • AWS
  • k8s

CircleCI

  • Staging
  • Production
  • Configuring a Worflow

Woovi CI/CD - CircleCI

Pipelines

Workflow Fail

Workflow Fail Detail

Workflow Fail Slack Notification

Workflow Success

Workflow Prod Success

Workflow Production

Configuring a Workflow

  • Config
  • yml
  • ORBS
  • jobs
  • commands
  • filters

config.yml

version: 2.1
setup: true
orbs:
path-filtering: circleci/path-filtering@0.0.2
parameters:
run_workflow_deploy:
default: false
type: boolean
workflows:
setup:
jobs:
- path-filtering/filter:
base-revision: main
mapping: |
yarn.lock yarn-modified true
packages/client/.* client-modified true
packages/main/.* main-modified true
config-path: .circleci/workflows.yml

Workflows

workflows.yml

version: 2.1
orbs:
slack: circleci/slack@4.10.1
aws-ecr: circleci/aws-ecr@8.1.2
aws-cli: circleci/aws-cli@3.1.1
kubernetes: circleci/kubernetes@1.3.0
parameters:
yarn-modified:
type: boolean
default: false
client-modified:
type: boolean
default: false
main-modified:
type: boolean
default: false

Initial Config

aliases

aliases:
# commands
- &yarn
name: Install Dependencies
command: |
yarn install --ignore-engines --frozen-lockfile --production=false
--non-interactive --cache-folder ~/.cache/yarn
# we need to checkout main to make git diff work well
- &checkout_main
name: checkout main
command: |
if [[ $(git rev-parse --abbrev-ref HEAD) != "main" ]]; then
git branch -f main origin/main;
fi
- &test
name: Run Tests
command: |
...
- &test_changed
name: Run Tests only affected by changed files
command: |
...

aliases

jobs

jobs:
install_deps:
executor: node16
steps:
- checkout
- run: *checkout_main
- run: node --version
- run: echo "This is pipeline ID << pipeline.id >>"
- run: echo $CIRCLE_COMPARE_URL
- restore_cache:
keys:
- yarn-packages-{{ checksum "yarn.lock" }}
- run: *yarn
- save_cache:
key: yarn-packages-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/yarn
- ./node_modules
- ./packages/client/node_modules
- ./packages/main/node_modules
- persist_to_workspace:
root: .
paths: .

filters

# Job Filters
- &filter-only-main
branches:
only:
- main
- &filter-production
branches:
only:
- /feature-production\/.*/

filters

test-changed

test_changed:
executor: node18
parallelism: 3
steps:
- attach_workspace:
at: ~/app
- restore_cache:
keys:
- mongodbbinaries-{{ checksum "yarn.lock" }}
- run: echo $CIRCLE_COMPARE_URL
- run: *copy_env
- run: *checkout_main
- run: *test_changed
- save_cache:
key: mongodbbinaries-{{ checksum "yarn.lock" }}
paths:
- ~/.cache/mongodb-binaries
- ~/.mongodb-binaries
- store_test_results:
path: ./test-results
- store_artifacts:
path: ./test-results

deploy-staging-server

deploy_staging_server:
executor: node16
steps:
- attach_workspace:
at: ~/app
- run: *copy_env_staging
- run:
name: Build Nodejs
command: |
yarn build
- build_docker:
IMAGE_NAME: $IMAGE_NAME_SERVER
DOCKERFILE: ./packages/main/Dockerfile
- push_docker_image:
registry: $REGISTRY
imageName: $IMAGE_NAME_SERVER
production: false
- update_kubernetes:
NAMESPACE: 'woovi-stg'
TOKEN: $TOKEN
SERVER: $SERVER
CONTAINER: 'container-stg-server'
DEPLOYMENT: 'container-stg-server'
IMAGE: $IMAGE_NAME_SERVER

BOTina

BOTina - Help Commands

BOTina - Diff Command

BOTina - Release

BOTina - CircleCI Release Workflow

Examples of CI/CD to your Projects

  • Test
  • Deploy
  • Automatic Updates

test.yml

name: tests
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Setup Node.js
uses: actions/setup-node@v2
with:
node-version: '16.14.2'
- run: yarn
- run: yarn relay
- run: yarn jest

deploy.yml

name: Deploy
on:
push:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: akhileshns/heroku-deploy@v3.12.12 # This is the action
with:
heroku_api_key: ${{secrets.HEROKU_API_KEY}}
heroku_app_name: 'my-server' #Must be unique in Heroku
heroku_email: 'hi@daniloassis.dev'
healthcheck: 'https://my.backend.com.br/status'
checkstring: 'Server Working'
rollbackonhealthcheckfailed: true
env:
JWT_KEY: ${{secrets.JWT_KEY}}
MONGO_URI: ${{secrets.MONGO_URI}}

deploy

dependabot.yml

version: 2
updates:
- package-ecosystem: npm
directory: '/'
schedule:
interval: daily
time: '01:00'
open-pull-requests-limit: 10

automerge.yml

name: auto-merge
on:
pull_request_target:
branches:
- main
jobs:
auto-merge:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- uses: ahmadnassri/action-dependabot-auto-merge@v2.4
with:
github-token: ${{ secrets.AUTOMERGE_TOKEN }}
command: 'squash and merge'
target: minor

Dependabot Working

Dependabot Working

Platforms and Clouds

  • Heroku
  • Vercel
  • CircleCI
  • GitHub Actions
  • AWS
  • Digital Ocean
  • onrender
  • Back4App
  • Cloudflare

References

  • Woovi - Shipping to Production Series'
  • Improving Operational Work with a Slack Bot
  • BOTina Slack - Open Source
  • Woovi Tech

Website

https://daniloassis.dev

Thanks

We are hiring!

woovi.com/jobs