流水线配置中,支持指定YAML文件,用于描述如何在Serverless应用中心上运行流水线,来构建或发布Serverless应用。本文介绍如何配置YAML文件以及文件中预定义的字段含义。

背景信息

YAML配置文件描述了流水线运行所需要的流水线对象以及流水线模板对象的数据结构,当您的代码仓库发生变更时,会通过Webhook触发应用中心,并按照配置文件的描述执行流水线动作。

采用配置文件描述流水线运行的方式,是应用中心比较推荐的DevOps实践。您可以在创建应用阶段指定或新建该YAML配置文件,也可以在环境中指定或新建该YAML配置文件。关于如何指定YAML文件,请参见配置流水线

前提条件

  • 您已了解流水线及流水线模板相关概念。更多信息,请参见流水线流水线模板
  • 创建一个应用中心支持的Git仓库,并拥有管理权限。您也可以使用应用中心在创建新应用过程中,创建并初始化的Git仓库。
  • 在Git仓库根目录创建一个YAML配置文件,本文以创建的cicd.yaml文件为例进行介绍。

配置YAML文件

YAML文件支持添加对流水线、流水线模板和任务模板的描述,其中流水线描述为必选,流水线模板和任务模板的描述为可选。

  1. 添加流水线描述。
    示例如下。
    ---# 提交流水线执行
    kind: Pipeline
    # 流水线执行名称,需要全局唯一。如果流水线模板存在,则不能成功提交流水线执行
    # 推荐使用commitID与时间戳构造唯一的名称
    name: "p-<% .git.shortCommitId %>-<% .currentTimestampMs %>"
    # 一些任意的描述信息
    description: 'demo pipeline'
    # 添加任意的labels,用于查询过滤
    # 应用中心会在提交时也会添加其他labels
    labels:
      myLabel: my-cicd-example
    spec:
      context:
        data:
          ## 全局钉钉通知配置,覆盖模板中的配置
          #dingdingNotification:
          #  # 设置全局关闭钉钉通知,下面可以按需打开
          #  enable: false
          #  # 设置在任务执行成功时跳过通知
          #  skipOnSuccess: false
          #  # 钉钉通知webhook配置
          #  webhook: https://oapi.dingtalk.com/robot/send?access_token=xxx
          #  # 钉钉通知的签名密钥
          #  secret: xxx
          #  # 钉钉通知的内容。不要统一配置text,除非目的是统一通知的内容
          #  message:
          #    at:
          #      isAtAll: false
          #      atUserIds: ["admin"]
          #      atMobiles: ["188xxxx8888"]
          #    msgtype: text
          #    # text支持模板语法,模板可以获取到当前执行的状态以及异常信息
          #    text: |
          #      task finished.
          #      TaskName: {{ .currentTask.name }}
          #      Success: {{ .success }}
          #      Status: {{ .currentTask.status.phase }}
          # 通过s工具部署,指定s.yaml文件位置,触发时会自动填入
          # deployFile: s.yaml
          # 应用中心所在的应用名称,触发时会自动填入
          appName: <% .appName %>
      # 本次执行使用的流水线模板
      # 可以选择已有的模板,也可以在配置文件中自定义
      # 这里的例子为引用下文
      templateName: mytemplate-<% .git.branch %>
    ---

    上述示例中,当满足条件的Git事件产生时,会产生一条名称为p-<% .git.shortCommitId %>-<% .currentTimestampMs %>的流水线,并全局声明流水线执行过程中,每个任务执行结束时的通知配置。

  2. 可选:添加流水线模板的描述。
    步骤1中,流水线引用了一个名称为mytemplate-<% .git.branch %>的流水线模板,通过在模板名称构造中引入分支名称,可以做到不同的分支使用不同的流水线模板。

    以下示例描述一个对比、审批然后构建部署的流水线模板。

    ---
    # 修改流水线模板,应用中心会按照该配置,创建或更新对应的模板
    kind: PipelineTemplate
    # 流水线模板名称,需要全局唯一,如果流水线模板存在,则会更新已有模板
    # 推荐使用Branch或MR关联的ID构造唯一的名称
    name: mytemplate-<% .git.branch %>
    # 一些任意的描述信息
    description: 用于测试环境的流水线模板
    # 添加任意的labels,用于查询过滤
    # 应用中心会在提交时也会添加其他labels
    labels:
      myLabel: my-cicd-example
    spec:
      context:
        data:
          # 环境名称,推荐不同的环境使用不同的流水线模板
          envName: test
          deployFile: s.yaml
          ## serverless cd runner部署配置,如果不指定,将在应用中心的某个沙箱环境中执行。
          # runnerConfig:
          #   # 构建任务运行的地域,推荐在中国内地以外的地域构建GitHub
          #   regionId: ap-southeast-1
          #   # 日志搜集配置,运行日志将会投递到指定SLS日志库中
          #   logConfig:
          #     logstore: function-log
          #     project: my-project
          #   # 运行的网络vpc信息
          #   vpcConfig:
          #     securityGroupId: xxx
          #     vSwitchIds: ["xxx"]
          #     vpcId: xxx
          #   # 运行规格,采用1核2GB的计算实例
          #   cpu: 1
          #   memory: 2048
          #   # 服务端超时时间,这里是15分钟
          #   timeout: 900
          #   # 运行在debug模式,runner对应的函数在短时间内不会被回收
          #   # 一般不建议打开
          #   debugMode: true
          #   # runner的环境变量配置
          #   environmentVariables:
          #     GOMODCACHE: /mnt/data/cache/.gomod-cache/
          #     DEBUG: "*"
      # 要执行的任务,默认所有任务会一同尝试执行
      # 执行会满足runAfters引入的先后约束,任务必须在runAfters声明的任务执行完毕后才可以被执行
      # 用户可以使用此特性,达到DAG描述的效果
      tasks:
      # 构建前检查
      - name: pre-check
        context:
          data:
            displayName: "前置检查"
            # 打开任务执行,默认是关闭的
            enable: true
            # 同样可以在此处声明钉钉告警配置,修改告警模板
            # dingdingNotification:
            # 同样可以在此处声明或修改RunnerConfig
            # runnerConfig:
            # 执行步骤。下述步骤将会采用开源项目serverless-cd提供的engine进行执行
            steps:
              # 第一步,checkout代码
              # 这里采用了plugin机制,运行serverless-cd社区的插件
              # @serverless-cd/checkout是一个社区提供的插件,它会将代码checkout到默认路径
              # 我们会陆续为社区提供更多的插件
              - plugin: "@serverless-cd/checkout"
              # 第二步,初始化s工具
              # 这里采用了bash执行机制,运行一段自定义的bash脚本。
              # 通常,我们建议将脚本充分测试后check-in到代码仓库中,并通过makefile运行它们
              # 例如:- run: make prepare
              # 这里为了演示方便,将脚本内容显式写入流水线
              - run: |
                  echo "Setup Serverless Devs ing..."
                  # 打开调试模式,将命令输出
                  set -x
                  ls -al
                  # aliyun cloud authentication infos.
                  access_key_id=${{ sts.accessKeyId || "dummy-ak" }}
                  access_key_secret=${{ sts.accessKeySecret || "dummy-sk" }}
                  security_token=${{ sts.securityToken || "dummy-token" }}
                  uid=${{ uid || "dummy-uid" }}
                  # account info alias
                  alias=my-account
                  s --version
                  if [[ $? -ne 0 ]]; then
                    echo "Serverless Devs is not installed."
                    exit 1
                  fi
                  s config add --AccessKeyID "${access_key_id}" --AccessKeySecret "${access_key_secret}" \
                  --AccountID "${uid}" --SecurityToken "${security_token}" --access "${alias}" -f
                  if [[ $? -ne 0 ]]; then
                    echo "Failed to setup Serverless Devs."
                    exit 1
                  fi
                  echo "Setup Serverless Devs success."
                # 执行s-plan,并打印输出内容
                # 这里为了说明engine能力,将它拆分成了多个step执行
              - run: s plan --local --access my-account -o json >> plan.out
              - run: echo "s plan finished."
              - run: cat plan.out
        # 任务模板。这里使用了内置的模板serverless-runner-task
        taskTemplate: serverless-runner-task
        # 执行顺序,当前任务执行依赖runAfters任务都执行成功
        runAfters: []
      - name: pre-check-approval
        context:
          data:
            dingdingNotification:
              # 关闭通知
              enable: false
            # 打开任务执行
            enable: true
        # 采用内置的need-approval模板
        taskTemplate: need-approval
        runAfters:
        # 需要在pre-check执行后才执行
        - name: pre-check
      # 构建并部署
      - name: build-and-deploy
        context:
          data:
            # 打开任务执行,默认是关闭的
            enable: true
            # 同样可以在此处声明钉钉告警配置,修改告警模板
            # dingdingNotification:
            # 同样可以在此处声明或修改RunnerConfig
            # runnerConfig:
            # 执行步骤。下述步骤将会采用开源项目serverless-cd提供的engine进行执行
            steps:
              # 每个Task都是独立运行的Serverless实例,需要重新checkout
              # 如果使用了缓存,它会执行得很快
              - plugin: "@serverless-cd/checkout"
              # 同理,需要再次初始化s工具
              - run: |
                  echo "Setup Serverless Devs ing..."
                  # 打开调试模式,将命令输出
                  set -x
                  ls -al
                  # aliyun cloud authentication infos.
                  access_key_id=${{ sts.accessKeyId || "dummy-ak" }}
                  access_key_secret=${{ sts.accessKeySecret || "dummy-sk" }}
                  security_token=${{ sts.securityToken || "dummy-token" }}
                  uid=${{ uid || "dummy-uid" }}
                  # account info alias
                  alias=my-account
                  s --version
                  if [[ $? -ne 0 ]]; then
                    echo "Serverless Devs is not installed."
                    exit 1
                  fi
                  s config add --AccessKeyID "${access_key_id}" --AccessKeySecret "${access_key_secret}" \
                  --AccountID "${uid}" --SecurityToken "${security_token}" --access "${alias}" -f
                  if [[ $? -ne 0 ]]; then
                    echo "Failed to setup Serverless Devs."
                    exit 1
                  fi
                  echo "Setup Serverless Devs success."
              # 执行s-deploy
              - run: |
                  echo "Deploy by Serverless Devs ing..."
                  set -x
                  alias=my-account
                  deploy_file=${{ ctx.data.deployFile || "" }}
                  if [[ -z "${deploy_file}" ]]; then
                    if [[ -f "s.yaml" ]]; then
                      deploy_file="s.yaml"
                    elif [[ -f "s.yml" ]]; then
                      deploy_file="s.yml"
                    fi
                  fi
                  if [[ ! -f "${deploy_file}" ]]; then
                    echo "Failed to find s.yaml file."
                    exit 1
                  fi
                  echo "s.yaml file location: ${deploy_file}"
                  s deploy --access "${alias}" -t "${deploy_file}" --use-local --assume-yes --skip-push
                  echo "Deploy by Serverless Devs success."
        taskTemplate: serverless-runner-task
        # 执行顺序,当前任务执行依赖runAfters任务都执行成功
        runAfters:
        # 在approval后执行
        - name: pre-check-approval
    ---

YAML文件预定义变量

应用中心提供以下预置的变量,在触发时会将YAML文件中的占位符替换为变量对应的值,再提交文件描述的流水线以及任务对象。

名称解释示例
<% .appName %>应用名称。headless-ffmpeg-wcha
<% .accountId %>阿里云账号(主账号)ID。143199913651****
<% .releaseVersion %>当前执行流水线的部署版本。1676913428****
<% .envName %>当前流水线所在的环境。staging
<% .git.branch %>当前流水线所在分支。test
<% .git.commitId %>本次Git操作中HEAD Commit的CommitId。3b6b823cea88c356b10442580da5a02cde4****
<% .git.shortCommitId %>本次Git操作中HEAD Commit的CommitId前7位。3b6b823
<% .git.commitMessage %>本次Git操作中HEAD Commit的Message内容。update .s file
<% .git.tag %>本次Git操作中的tag名称(如果存在tag)。dev
<% .git.author %>本次Git操作的作者。developer
<% .git.action %>本次Git操作的行为名称。push
<% .currentTimestampMs %>执行部署时的时间戳,单位为毫秒。1676971965781
<% .currentTimestampS %>执行部署时的时间戳,单位为秒。1676971891
<% .randomString6 %>随机6位字符串。abcdef