CI/CD

CircleCI快速使用

2018-12-07  本文已影响381人  你家旭哥

前段时间一直使用drone来做敏捷开发,现在由于项目要求并不高,改为使用circleCI,记录一下使用的过程,也给需要了解的同学一些建议吧

前期

我是使用Bitbucket开发的,也不知道需要不需要过墙,反正我开电脑就开着梯子。如果有需要了解github的同学也可以瞧瞧,不妨碍。
添加项目的一些操作就不聊了,下面主要说说配置文件的事情。

概念

Orbs

orbs是项目之间共享配置包。

Jobs

Jobs是一系列的步骤,job里的所有步骤都是circleCI容器中的独立单元。

Steps

Steps是在job运行期间的可执行命令的集合。

安全策略

SSH和HTTPS技术来加密网络请求和服务。所有jobs都在一个沙箱内工作,外网无法访问。通过SSH来获取执行代码,特定的测试和配置文件会从外网获取到沙箱内供代码使用。job完成后会销毁相关的容器,下个任务会重新构建。环境变量通过Hashicorp Vault加密,采用AES256-GCM96加密变量,CircleCI无法获取。

提示:用户可以完全访问在构建容器中运行的任何文件或进程,因此仅向那些信任您的源代码的用户提供对CircleCI的访问权限。

采用的第三方技术

采用Pusher来完成服务跟游览器的交互任务。在安装Pusher时采用了slanger封装,所以Pusher服务无法访问CircleCI或者您的代码。
采用Replicated管理CircleCI的安装向导,许可密钥,系统审核日志,软件更新以及其他维护和系统任务

审核日志事件

这部分内容是部署到自己的服务或者私有云上的,这里就不谈了。

开始 (适用于2.0以上版本)

具体的等级结构:


1.项目根目录下需要如下格式的配置文件

mkdir .circleci && touch .circleci/config.yml

2.版本声明

version: 2.1  //版本号

3.orbs 配置包管理 这个包管理是2.1的特性 2.1以下无法使用

version: 2.1
orbs:
    hello: circleci/hello-build@0.0.5
workflows:
    "Hello Workflow":
        jobs:
          - hello/hello-build

4.commands sh指令 版本2.1以上

commands:
  sayhello:
    description: "A very simple command for demonstration purposes"
    parameters:
      to:
        type: string
        default: "Hello World"
    steps:
      - run: echo << parameters.to >>
  1. executors 执行单元 自定义的执行沙盒(容器) 2.1以上
version: 2.1
executors:
  my-executor:
    docker:
      - image: circleci/ruby:2.5.1-node-browsers

jobs:
  my-job:
    executor: my-executor
    steps:
      - run: echo outside the executor
  1. jobs 工作单元
jobs:
  build:
    docker:
      - image: buildpack-deps:trusty
    environment:
      FOO: bar
    parallelism: 3
    resource_class: large
    working_directory: ~/my-app
    branches:
      only:
        - master
        - /rc-.*/
    steps:
      - run: make test
      - run: make

Jobs 是用map指定的,job的名字就是map的key值,如果你使用Workflows,jobs的名字必须保持唯一。如果没有使用workflows,就必须包含build这个key。build是版本控制push时的默认入口,然后再开始其他的工作。

jobs的最大工作时间是5小时,超过这个时间你就得考虑使用并行模式。


job的参数说明:

docker: 指定容器的配置。
machine: 虚拟机。
macos: iOS运行机。

executor: docker, machine, macos 这三个只能设置一个,多个会报错。

shell: 所有steps都需要运行的shell指令,会被steps里的shell覆盖。
steps: 需要执行的步骤列表。
working_directory: 在哪个目录下运行你的steps
parallelism: 要运行的此job的并行实例数,一般情况下是1,更多就得花钱买。
environment: 环境变量。
branches: 分支管理,白名单和黑名单。
resource_class: 资源分配,分配多少CPU等。只有付费用户才有的特性。

docker

executor就是steps运行的地方。CircleCI可以一次性运行多个容器,或者使用整个虚拟机。
docker使用的key包括:
image: 容器的镜像。
name: 容器的名字 可以通过名字来访问其他容器 默认是localhost。
entrypoint: 容器启动时执行的指令。
command: 作为为entrypoint的参数或者没有entrypoint直接执行命令 参考docker设计理念。
user: 容器内执行程序的用户名称。
environment: 环境变量 这个优先级高于外面job声明的。
auth: docker login 的登录凭证。
aws_auth: AWS EC2容器仓库的登录凭证。
典型的栗子

jobs:
  build:
    docker:
      - image: buildpack-deps:trusty # primary container
        environment:
          ENV: CI

      - image: mongo:2.6.8
        command: [--smallfiles]

      - image: postgres:9.4.1
        environment:
          POSTGRES_USER: root

      - image: redis@sha256:54057dd7e125ca41afe526a877e8bd35ec2cdd33b9217e022ed37bdcf7d09673

如果你使用私人镜像,提供登录凭证就行了,这个参数的值可以在CircleCI的后台游览器里进行设置。

jobs:
  build:
    docker:
      - image: acme-private/private-image:321
        auth:
          username: mydockerhub-user  # can specify string literal values
          password: $DOCKERHUB_PASSWORD  # or project UI env-var reference

在容器内部可以重用外部的commands指令。

jobs:
  myjob:
    docker:
      - image: "circleci/node:9.6.1"
    steps:
      - sayhello:
          to: "Lev"
machine 不谈了,说白了就是主机模式,就是运行了一个ubuntu镜像的容器,容器里有docker、docker-compose。详细了解的可以到 machine executor
version: 2
jobs:
  build:
    machine:
      image: circleci/classic:201708-01
macos iOS macOS tvOS watchOS平台所用的
jobs:
  build:
    macos:
      xcode: "9.0"
branches

定义分支的黑白名单(没有使用Workflows并且是2.0)如果你使用Workflows,只会执行workflows中定义的branches,如果你使用2.1,你必须得用workflows。
栗子:

jobs:
  build:
    branches:
      only:
        - master
        - /rc-.*/
jobs:
  build:
    branches:
      ignore:
        - develop
        - /feature-.*/
resource_class (付费节目 不谈)。

steps

先把栗子甩出来:

jobs:
  build:
    working_directory: ~/canary-python
    environment:
      FOO: bar
    steps:
      - run:
          name: Running tests
          command: make test

steps应该是单一的键值对,key是代表step类型。这里的run只是一个step类型(step_type下面会讲更多的step类型),name是为了说明这个step是干嘛的,会在后台ui上输出,command就是sh指令。

jobs:
  build:
    steps:
      - run: make test

这个是缩写模式,name就是make test。还有一种缩写模式。

jobs:
  build:
    steps:
      - checkout
step_type: run

command 通过shell运行的指令。
name step的名称。
shell 执行指令的shell。
environment command的环境变量。
background 是否后台运行。
working_directory 目录 默认是job的。
no_output_timeout 没有输出情况下运行的时间 就是延时。
when 什么时候开启和关闭step 值有always, on_success, on_fail
每一个run都会生成一个shell,一个run的多个command都是在一个shell工作的

- run:
    command: |
      echo Running test
      mkdir -p /tmp/test-results
      make test

默认的shell是这个:/bin/bash -eo pipefail 如果命令返回非0值,会跳出报错,steps也走不下去。如果需要忽略指令的结果,可以主动修改shell,或者按照如下的set指令来修改,不过推荐使用默认的,因为这样你就能看到错误信息了。

- run:
    command: |
      echo Running test
      set +e
      mkdir -p /tmp/test-results
      make test

- run:
    shell: /bin/sh
    command: |
      echo Running test
      mkdir -p /tmp/test-results
      make test

一些简单的缩写格式

- run: make test

# shorthanded command can also have multiple lines
- run: |
    mkdir -p /tmp/test-results
    make test

when这个值很有意思,如果前面的step出现了错误,后面的step就不会执行(on_success)。如果你指明when为always的话,则这个step怎么都会执行的,on_fail只会前面有错误才执行,这对错误收集有作用。

steps:
  - run:
      name: Testing application
      command: make test
      shell: /bin/bash
      working_directory: ~/my-app
      no_output_timeout: 30m
      environment:
        FOO: bar

  - run: echo 127.0.0.1 devhost | sudo tee -a /etc/hosts

  - run: |
      sudo -u root createuser -h localhost --superuser ubuntu &&
      sudo createdb -h localhost test_db

  - run:
      name: Upload Failed Tests
      command: curl --data fail_tests.log http://example.com/error_logs
      when: on_fail
when注意这个when是跟run同级别的 上面那个when是run的子key(2.1的新特性,2.1干了很多控制方面的事情)

先睹栗子

version: 2.1

jobs: # conditional steps may also be defined in `commands:`
  job_with_optional_custom_checkout:
    parameters:
      custom_checkout:
        type: string
        default: \"\"
    machine: true
    steps:
      - when:
          condition: <<parameters.custom_checkout>>
          steps:
            - run: echo \"my custom checkout\"
      - unless:
          condition: <<parameters.custom_checkout>>
          steps:
            - checkout
workflows:
  build-test-deploy:
    jobs:
      - job_with_optional_custom_checkout:
          custom_checkout: \"any non-empty string is truthy\"
      - job_with_optional_custom_checkout            

这个不聊了 看栗子吧

checkout

直接拉取代码,通过SSH方式

- checkout
- run: git submodule sync
- run: git submodule update --init

由于checkout不支持子模块,如果需要拉子模块跑git指令

setup_remote_docker 创建配置为执行Docker命令的远程Docker环境(付费节目)
save_cache

在我们的对象存储中生成并存储文件或文件目录的缓存,例如依赖项或源代码

restore_cache

基于key恢复以前保存的缓存

deploy

deploy使用与run步骤相同的配置映射和语义

store_artifacts

store_artifacts可在Web应用程序中或通过API提供的工件(例如日志,二进制文件等)

- store_artifacts:
    path: /code/test-results
    destination: prefix
store_test_results

用于上传测试结果的特殊步骤,以便在构建中显示

persist_to_workspace

用于持久保存临时文件以供工作流中的另一个作业使用的特殊步骤。

attach_workspace

用于将工作流的工作空间附加到当前容器的特殊步骤

add_ssh_keys

将SSH密钥从项目设置添加到容器的特殊步骤。还配置SSH以使用这些密钥


workflows

工作流程 编排jobs
整个配置文件

version: 2
jobs:
  build:
    docker:
      - image: ubuntu:14.04

      - image: mongo:2.6.8
        command: [mongod, --smallfiles]

      - image: postgres:9.4.1
        # some containers require setting environment variables
        environment:
          POSTGRES_USER: root

      - image: redis@sha256:54057dd7e125ca41afe526a877e8bd35ec2cdd33b9217e022ed37bdcf7d09673

      - image: rabbitmq:3.5.4

    environment:
      TEST_REPORTS: /tmp/test-reports

    working_directory: ~/my-project

    branches:
      ignore:
        - develop
        - /feature-.*/

    steps:
      - checkout

      - run:
          command: echo 127.0.0.1 devhost | sudo tee -a /etc/hosts

      # Create Postgres users and database
      # Note the YAML heredoc '|' for nicer formatting
      - run: |
          sudo -u root createuser -h localhost --superuser ubuntu &&
          sudo createdb -h localhost test_db

      - restore_cache:
          keys:
            - v1-my-project-{{ checksum "project.clj" }}
            - v1-my-project-

      - run:
          environment:
            SSH_TARGET: "localhost"
            TEST_ENV: "linux"
          command: |
            set -xu
            mkdir -p ${TEST_REPORTS}
            run-tests.sh
            cp out/tests/*.xml ${TEST_REPORTS}

      - run: |
          set -xu
          mkdir -p /tmp/artifacts
          create_jars.sh ${CIRCLE_BUILD_NUM}
          cp *.jar /tmp/artifacts

      - save_cache:
          key: v1-my-project-{{ checksum "project.clj" }}
          paths:
            - ~/.m2

      # Save artifacts
      - store_artifacts:
          path: /tmp/artifacts
          destination: build

      # Upload test results
      - store_test_results:
          path: /tmp/test-reports
          
  deploy-stage:
    docker:
      - image: ubuntu:14.04
    working_directory: /tmp/my-project  
    steps:
      - run:
          name: Deploy if tests pass and branch is Staging
          command: ansible-playbook site.yml -i staging          
          
  deploy-prod:
    docker:
      - image: ubuntu:14.04
    working_directory: /tmp/my-project  
    steps:
      - run:
          name: Deploy if tests pass and branch is Master
          command: ansible-playbook site.yml -i production

workflows:
  version: 2
  build-deploy:
    jobs:
      - build
      - deploy-stage:
          requires:
            - build
          filters:
            branches:
              only: staging
      - deploy-prod:
          requires:
            - build
          filters:
            branches:
              only: master

写的比较粗糙,后期有时间再完善。

上一篇 下一篇

猜你喜欢

热点阅读