简单实现一个任务模版

任务模版

介绍

任务模版 在开发中还是非常刚需的,因为任务是高度复用化的,不论是github的workflow还是自研的任务流水线,或多或少都要定义一堆的任务,但是其实会发现一点需要大量定义一些重复的任务配置,这样就会导致维护困难。任务模版+include指令可以很好的解决这些问题,具体可以看下文的例子~~

其中任务模版会有几个概念:

  1. 模版变量:可以根据模版变化渲染任务配置
  • HOME: 用户根路径
  1. 模版函数:一些复杂的逻辑可以通过模版函数来实现, 暂时仅支持了个三元表达式
  • IF: 三元表达式,例如:{{ IF .DEBUG "1" "--debug" "-" }} 表示:如果DEBUG=1则输出--debug否则是-, 注意代码中会将- 认为是空值""
  1. Include 指令:可以引用别的模版配置,实现组合的效果,因此诞生了任务模块的概念

Todo:

  1. 支持并行逻辑,例如下图,即我们需要一个 组任务的概念,目前还没有此类需要,所以暂时没有支持
  1. 解决循环引用的问题,既然我们支持了 include 指令,必不可少的就是循环引用检测

使用说明

devtool工具在这里:github.com/anthony-don...

shell 复制代码
➜  ~ devtool run --help
Name: Run task templates

Usage: devtool run [flags]

Options:
  -c, --config string     The task config file
  -d, --debug             Enable Debug
  -h, --help              help for run
  -I, --include strings   Add an config search path for includes
  -l, --list              List task config files
      --var strings       Define template variables

Global Options:
      --config-file string   Set the config file
      --log-level string     Set the log level in [fatal|error|warn|info|debug]
  -v, --verbose              Turn on verbose mode      

核心介绍一下 -I 参数,你可以指定多个include路径,类似于 gcc -I 这个参数一样搜索头文件,因为我们可能会定义一些公共模块在一个通用目录下。其次 include指令的搜索逻辑是优先当前引用文件的路径,其次是指定-I 的路径下搜索!

例子

相关配置文件在 test 文件夹下

  1. 背景:我们这边有多个API服务,他的框架都一样,因此大概它的启动脚本都一样,字节这边go-api服务基本使用的是hertz/ginex,这里以ginex框架为例子

  2. 第一步: 定义 sd.yaml , 它是一个服务发现service discovery的任务模版,主要是用于注册服务

yaml 复制代码
- name: "注册 {{ .SERVICE }} 服务" # 任务名称,其中 {{ .XXX }} 模版表达式,使用的是Go语言的自带的模版
  cmd: "sd" # 命令名称
  daemon: true # 表示后台运行这个程序,当整个程序组结束时会kill掉此进程的
  args:
    - "consul"
    - "--service"
    - "{{ .SERVICE }}"
    - "--env"
    - "{{ .ENV }}"
    - "--cluster"
    - "{{ .CLUSTER }}"
    - "--port"
    - "{{ .PORT }}"
  vars: # 模版变量
    ENV: "dev_xiaoming"
    CLUSTER: "default"
    PORT: 10086
  1. 定义 ginex.yaml 为 ginex 框架的运行模版
yaml 复制代码
- include: "sd.yaml" # include sd.yaml 配置
  vars:
    PORT: 9999 #ginex 服务的端口是9999
- name: "启动 {{ .SERVICE }} 服务"
  cmd: "devtool"
  dir: "{{ .HOME }}/go/src/{{ .REPO }}" # HOME 为全局变量默认是用户根路径
  env:
    - "SSO_DEBUG_USER={{ .USERNAME }}"
    - "LOAD_SERVICE={{ .SERVICE }}"
  args:
    - "go"
    - "run"
    - '{{ IF .DEBUG "1" "--debug" "-" }}' # 通过IF表达式来动态注入--debug参数
    - "--run"
    - "."
    - "--"
    - "-service={{ .SERVICE }}"
    - "-conf-dir=conf"
    - "-log-dir=log"
  vars:
    DEBUG: 0 # 默认是0表示禁止DEBUG
    USERNAME: "xiaoming" # 默认是xiaoming
  1. 定义Api服务 github.search.api.yaml 的配置文件
yaml 复制代码
- include: "ginex.yaml"
  vars:
    SERVICE: "github.search.api"
    REPO: "github.com/github/search_api"
    DEBUG: 1
  1. 测试,可以执行 devtool run -c command/run/test/github.search.api.yaml -d -v 来输出配置信息,检查是否正确
shell 复制代码
➜  golang git:(master) ✗ devtool run -c command/run/test/github.search.api.yaml -d -v
[DEBUG] 13:25:44.496 start cmd: devtool, cmd.args: [], os.args: ["devtool","run","-c","command/run/test/github.search.api.yaml","-d","-v"]
[DEBUG] 13:25:44.496 includes: ["/Users/bytedance/go/src/github.com/anthony-dong/golang"]. debug file: true.
[INFO] 13:25:44.496 init template vars: {
    "HOME": "/Users/bytedance",
    "PWD": "/Users/bytedance/go/src/github.com/anthony-dong/golang"
}
[INFO] 13:25:44.497 file: /Users/bytedance/go/src/github.com/anthony-dong/golang/command/run/test/github.search.api.yaml
- name: 注册 github.search.api 服务
  cmd: sd
  args:
    - consul
    - --service
    - github.search.api
    - --env
    - dev_xiaoming
    - --cluster
    - default
    - --port
    - "9999"
  vars:
    CLUSTER: default
    ENV: dev_xiaoming
    PORT: "9999"
  daemon: true
- name: 启动 github.search.api 服务
  cmd: devtool
  dir: /Users/bytedance/go/src/github.com/github/search_api
  env:
    - SSO_DEBUG_USER=xiaoming
    - LOAD_SERVICE=github.search.api
  args:
    - go
    - run
    - --debug
    - --run
    - .
    - --
    - -service=github.search.api
    - -conf-dir=conf
    - -log-dir=log
  vars:
    DEBUG: "1"
    USERNAME: xiaoming
  1. 执行,只需要把 -d 参数移除掉就会开始执行任务
相关推荐
我不是外星人6 小时前
有了 Harness Engineering ,真的还需要研发工程师吗?
前端·后端·ai编程
candyTong7 小时前
RTK 技术原理:一次典型会话里,80% 上下文是怎么省下来的
javascript·后端·架构
Rust研习社9 小时前
组合真的优于继承吗?为什么 Rust 和 Go 都拥抱组合舍弃继承?
后端·rust·编程语言
IT_陈寒9 小时前
JavaScript的闭包把我坑惨了,说好的内存会自动回收呢?
前端·人工智能·后端
CaffeinePro10 小时前
Pydantic深度使用:数据校验、枚举、ORM映射
后端·fastapi
Chenyiax10 小时前
从 Chat 到 Responses:OpenAI API 抽象为什么变了?
后端
MariaH10 小时前
Koa和Express的区别
后端
MariaH10 小时前
Koa框架的使用
后端
luckdewei12 小时前
那个用 passlib 做认证的新同事,上线第一天就把用户密码写进了日志
后端
ping某13 小时前
为什么 Nginx 明明监听了 80,转发后端时却用了 4xxxx 端口?
后端·nginx