用Typescript写自动化工作流

项目地址:acao

挺早之前写过一个工具帮我构建项目并发布到指定平台,主要流程就是获取项目根目录下的配置文件,然后根据配置文件在本地通过 docker 构建一个镜像然后 push 到镜像仓库,最后通过 ssh 连接指定的服务区执行发布任务

但是随着需求的增长项目就愈发臃肿,可能会存在多个镜像仓库,发布到多个平台,有可能是通过 docker-compose 管理 也有可能是 kubectl

要怎么办?

于是我在考虑有没有可能有个工具来帮助我自动化在本地或者远程执行一些任务,而我并不关心任务的内容

同时为了方便使用,需要支持继承本地或者远程的预设配置,让我可以很方便的从之前的工具过渡到新的方案上

他们都是怎么做的?

对于团队来说,可能会有现成的 jenkins 或者 git 平台的 runner,这种方案可以说并没有什么不能实现的,但是对于个人项目或者希望依赖本地环境做一些构建的情况下可能有点 太 重 了

或许也会考虑类似 GitHub Actions 的方式执行一些工作流,但是感觉对命令执行的结果不太好处理并提供给之后的流程

用 ts 写工作流

用编程的方式可能会提高一点使用门槛,但是对于程序员来说真的很方便,在这里向大家介绍一下最近开发的一个工具 acao 已经用在一些个人项目和部分公司业务代码中,基础功能应该没啥问题(欢迎 issue 讨论哦

接下来让我们看看要怎么用叭!

依赖处理 / 初始化

首先还是先安装一下,虽然也可以直接通过 npx 执行,但是对于 js 项目,使用暴露出来的一些辅助函数和预设都会比较方便

pnpm add acao -D

在项目根目录新建一个 acao.config.ts 文件,并先写一个简单的命令

import { defineConfig } from 'acao'export default defineConfig({jobs: {ci: {steps: ['echo ci']}}
})

这个工作流定义了一个 名为 ci 的 job 而且只有一个步骤,执行命令 echo ci 通过 npx acao 执行预期结果将会在控制台输出 ci 字符串,相信如果有 GitHub Actions 使用经验的小伙伴看起来应该还是有点眼熟的,数据结构的部分会有参考

如果对此完全陌生的小伙伴先可以简要介绍一下,这个配置的作用是定义一个工作流,一个工作流中可能会包含多个 job 数据类型是 Record<string, AcaoJob> key 是当前这个 job 的名称,多个 job 如果没有 needs 定义的依赖关系则默认同步执行,在 job 中需要定义 steps 数组作为具体执行步骤 steps 会按顺序执行

举个栗子

纯文字看起来还是有点抽象,接下来我们来实际完成一个工作流来熟悉一下

通常对于容器化前端 csr 项目的发布流程是,先生成静态文件,然后 build 一个 docker 镜像,最后推送到镜像仓库,这些会作为构建流程

而发布流程如果是 docker compose 的话则是登陆到指定服务器,然后替换掉 docker compose 中指定 service 的 image 最后 up 一下服务(简化一下

那么我们先通过 acao 来实现一下构建流程

import { defineConfig, run } from 'acao'const HARBOR_HOST = 'HARBOR_HOST'
const HARBOR_USERNAME = 'HARBOR_USERNAME'
const HARBOR_PASSWORD = 'HARBOR_PASSWORD'
const IMAGE = `${HARBOR_HOST}/frontend`export default defineConfig({jobs: {ci: {steps: ['npm run build',run('git log --format="%ad-%h" --date=format:%Y%m%d -1', { transform: stdout => `${IMAGE}:${JSON.parse(stdout)}` }),run((tag) => `docker build -t ${tag} . --platform linux/amd64`)`docker login ${HARBOR_HOST} --username ${HARBOR_USERNAME} --password ${HARBOR_PASSWORD}`,run((_, ctx) => `docker push ${ctx.outputs.ci[1]}`),],}},
})

在上面这个例子中,我们新引入了一个 run 函数,他同样可以和字符串一样被使用在 job steps 中来执行某个命令,在 acao 中字符串的方式是 run 函数没有特殊需求的一种简写 ‘echo ci’ 与 run(’echo ci’) 是等价的,而 run 函数提供了一些其他方法来帮助我们更好的处理命令之间的 pipeline

对于 run 的类型申明如下

type RunCmd<T = string> = T | ((prev: any, ctx: AcaoContext) => T | Promise<T>);interface RunOptions extends ExecaOptions {ssh: boolean;transform: (stdout: string) => any | Promise<any>;beforeExec: (ctx: AcaoContext) => any | Promise<any>;afterExec: (ctx: AcaoContext) => any | Promise<any>;
}declare function run(cmd: RunCmd, options?: Partial<RunOptions>): AcaoJobStep;

这样看起来可能有点抽象,我们结合例子来说明一下

run('git log --format="%ad-%h" --date=format:%Y%m%d -1', { transform: stdout => `${IMAGE}:${JSON.parse(stdout)}` }),

这个命令是通过 git 命令获取最近一条 commit 的 short_hash 和 日期并拼接成指定格式作为 image 的 tag 而 run 的第二个参数提供了一个 transform 参数来处理输出,拼上完整的 image 名称作为当前这个 step 的输出提供给其他 step 使用

接下来我们需要用到这条命令的输出并通过 docker 构建一个镜像

run((tag) => `docker build -t ${tag} . --platform linux/amd64`)

run 的命令支持使用一个一个返回值为字符串的函数,回调的第一个参数是上一条命令的输出,我们已经处理成完成的镜像名所以可以直接使用

接下来登陆并推送本地镜像到镜像仓库,我们主要看推送的命令

run((_, ctx) => `docker push ${ctx.outputs.ci[1]}`),

这一步我们同样需要用到处理好的镜像名称,但是对于当前这一步来说上一步的输出结果已经不是我们所期望的了,当然我们也可以通过 git 命令再获取一次,或者通过回调的第二个参数获取上下文中某个 step 的输出

ctx.outputs 中有当前不同 job 执行过所有命令的输出结果,可以通过 job 名称和 step index 获取到具体某条的结果

用一些预设

对于一些常用的命令 acao 也提供了一些预设来方便 steps 的创建,比如 volta / docker 让我们简化一下之前的 ci 流程

import { defineConfig, run } from 'acao'
import { voltaRun } from 'acao/volta'
import { dockerBuild, dockerLogin, dockerPush } from 'acao/docker'const HARBOR_HOST = 'HARBOR_HOST'
const HARBOR_USERNAME = 'HARBOR_USERNAME'
const HARBOR_PASSWORD = 'HARBOR_PASSWORD'
const IMAGE = `${HARBOR_HOST}/frontend`export default defineConfig({jobs: {ci: {steps: [voltaRun('npm run build', { node: '10.24.1' }),run('git log --format="%ad-%h" --date=format:%Y%m%d -1', { transform: stdout => `${IMAGE}:${JSON.parse(stdout)}` }),dockerBuild(tag => ({ tag, platform: 'linux/amd64' })),dockerLogin(HARBOR_HOST, { username: HARBOR_USERNAME, password: HARBOR_PASSWORD }),dockerPush((_, ctx) => ctx.outputs.ci[1]),],},
})

具体预设的使用方式可以看看 文档 这里就不过多展开了,函数的方式由于提供了比较好的类型提示,所以比字符串命令的形式还是友好很多

一些远程命令

那么对于发布流程,我们不可避免的需要通过 ssh 链接一些远程服务执行一些操作,对于这种需求 acao 也提供了一种简单的方式

import { defineConfig, run } from 'acao'export default defineConfig({jobs: {ci: {steps: [],},cd: {needs: ['ci'],ssh: {host: 'HOST',username: 'USERNAME',password: 'PASSWORD',},steps: [run('cd /data/docker_compose && docker-compose up -d'),]},},
}

在 job 中定义了 ssh 默认 steps 中执行的都是远程命令,也可以在 run 的第二个参数中指定 ssh: false 来混合执行和远程过命令,而且同样支持所有本地的方法比如 transform 和 ctx

在例子中可以看到 needs 参数,对于没有定义依赖的 job 默认会同步执行,而 needs 参数用来定义 job 的依赖 acao 会以此进行拓扑排序,存在循环依赖的话则所有任务都不会执行

最后

acao 的命令还有一些其他用法,比如指定执行某个 job 或者忽略依赖 通过命令行参数的方式注入等等,详细使用方式可以查看 文档

这个项目最近也在持续更新中,后续也会支持更多的预设,web ui 的操作方式也在计划中

小伙伴想参与预设的开发也欢迎 pr 呀

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/830382.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Github Action Bot 开发教程

Github Action Bot 开发教程 在使用 Github 时&#xff0c;你可能在一些著名的开源项目&#xff0c;例如 Kubernetes&#xff0c;Istio 中看到如下的一些评论&#xff1a; /lgtm /retest /area bug /assign xxxx ...等等&#xff0c;诸如此类的一些功能性评论。在这些评论出现…

Django-基础篇

Django是一个开放源代码的Web应用框架&#xff0c;由Python语言编写。它遵循MVC&#xff08;Model-View-Controller&#xff09;的软件设计模式&#xff0c;使开发者能够以高效、可扩展和安全的方式构建Web应用程序。 Django具有以下特点和优势&#xff1a; 强大的功能&#x…

MR混合现实情景实训教学系统在军事课堂上的应用

在现代军事教育中&#xff0c;实践教学的重要性日益凸显。传统的军事课堂教育方式往往侧重于理论知识的传授&#xff0c;而忽视了实践操作的重要性。而MR混合现实情景实训教学系统的引入&#xff0c;为军事课堂教育带来了全新的可能性。 MR混合现实情景实训教学系统是一种结合了…

面试笔记——线程池

线程池的核心参数&#xff08;原理&#xff09; public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize,long keepAliveTime,TimeUnit unit,BlockingQueue<Runnable> workQueue,ThreadFactory threadFactory,RejectedExecutionHandler handler)corePoolSize …

利用word2vec包将中文转变为词向量

代码展示&#xff1a; import jieba import re import json import logging import sys import gensim.models as word2vec from gensim.models.word2vec import LineSentence, loggerpattern u[\\s\\d,.<>/?:;\\"[\\]{}()\\|~!\t"#$%^&*\\-_a-zA-Z&…

C#创建obj三维模型文件

介绍 使用开源库创建obj三维模型文件。 开源库地址&#xff1a;https://github.com/JeremyAnsel/JeremyAnsel.Media.WavefrontObj 相关API地址&#xff1a;https://jeremyansel.github.io/JeremyAnsel.Media.WavefrontObj/api/JeremyAnsel.Media.WavefrontObj.ObjFile.html …

【docker】开放Docker端口

【docker 】 安装docker&#xff08;centOS7&#xff09;-CSDN博客 【docker】常用命令-CSDN博客 【docker】centos7配置docker镜像加速_docker仓库加速地址-CSDN博客 【docker】Hello World-CSDN博客 【docker 】Compose 使用介绍_docker compose 使用-CSDN博客 【docker…

linux(ubuntu18.04.2) Qt编译 MySQL(8.0以上版本)链接库 Qt版本 5.12.12及以上 包含Mysql动态库缺失问题

整理这篇文档的意义在于&#xff1a;自己走了很多弯路&#xff0c;淋过雨所以想为别人撑伞&#xff0c;也方便回顾&#xff0c;仅供参考 一、搭建开发环境&#xff1a; 虚拟机&#xff08;ubuntu-20.04.6-desktop-amd64&#xff09;&#xff1a;Mysql数据库 8.0.36Workbench …

tidb离线本地安装及mysql迁移到tidb

一、背景&#xff08;tidb8.0社区版&#xff09; 信创背景下不多说好吧&#xff0c;从资料上查tidb和OceanBase“兼容”&#xff08;这个词有意思&#xff09;的比较好。 其实对比了很多数据库&#xff0c;有些是提供云服务的&#xff0c;有些“不像”mysql&#xff0c;综合考虑…

智能合约语言(eDSL)—— wasmtime实现合约引擎补充

1、链上下文 由于我们是应用到区块链中&#xff0c;所以我们需要把链的环境传递给wasmtime&#xff0c;这样wasmtime在运行合约的时候&#xff0c;就可以获取到链上数据&#xff1b;我们运行合约当时的环境&#xff0c;打包成一个变量context&#xff0c;传递给wasmtime。conte…

【如何使用SSH密钥验证提升服务器安全性及操作效率】(优雅的连接到自己的linux服务器)

文章目录 一、理论基础&#xff08;不喜欢这部分的可直接看具体操作&#xff09;1.为什么要看本文&#xff08;为了zhuangbility&#xff09;2.为什么要用密钥验证&#xff08;更安全不易被攻破&#xff09;3.密码验证与密钥验证的区别 二、具体操作1.生成密钥对1.1抉择&#x…

计算机复试项目:SpringCloud实战高并发微服务架构设计

秒杀购物商城--环境搭建 秒杀购物商城基础服务组件--详细介绍 秒杀购物商城基础服务--权限中心 秒杀购物商城业务服务--收货地址 秒杀购物商城业务服务--秒杀活动服务 秒杀购物商城--购物车的功能设计及分析 秒杀购物商城基础服务-用户中心 秒杀购物商城业务服务--商品中…

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之九 简单进行嘴巴检测并添加特效的功能实现

Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之九 简单进行嘴巴检测并添加特效的功能实现 目录 Python 基于 OpenCV 视觉图像处理实战 之 OpenCV 简单人脸检测/识别实战案例 之九 简单进行嘴巴检测并添加特效的功能实现 一、简单介绍 二、简单…

Visual Studio Installer 运行python 汉字

问题描述&#xff1a; Visual Studio Installer 在正常情况下运行python文件时时候&#xff0c; 不能编译中文注释&#xff0c;更不能输出中文。 解决方法&#xff1a; 在程序开头下面这一行即可。 #coding:GBK 原因及解释&#xff1a; #coding:GBK 是 Python 源文件中的一个…

ceph 1 pool(s) do not have an application enabled

查看 ceph 状态 cluster:id: 58f90b9a-155c-43cf-98af-54cb611fc8e0health: HEALTH_OKservices:mon: 3 daemons, quorum a,b,d (age 79m)ne>mgr: b(active, since 59m), standbys: ane>mds: 1/1 daemons up, 1 hot standbyne>osd: 6 osds: 6 up (since 79m), 6 in…

ArcGIS小技巧—模型构建器快速提取河网

上篇文章介绍的基于DEM的河网提取&#xff0c;需要使用多个工具&#xff0c;整体操作比较繁琐&#xff0c;在日常工作中&#xff0c;使用Arcgis提供的模型构建器可以帮助我们将多个工具整合在一起&#xff0c;在面对大量数据批量处理时&#xff0c;可以大大提高工作效率 利用模…

Python基本数据类型

描述 Python是一种高级编程语言&#xff0c;拥有丰富的数据类型用于表示不同类型的数据。基本数据类型可以分为数值型&#xff08;Numbers&#xff09;、字符串型&#xff08;Strings&#xff09;、布尔型&#xff08;Booleans&#xff09;、空值&#xff08;NoneType&#xff…

8、Flink 在 source 处生成水位线 和 在 source 之后生成水位线案例

1、AtSourceGenerateWatermark 注意&#xff1a;从 Flink 1.17开始&#xff0c;FLIP-27 源框架支持拆分级别的水印对齐。 import java.time.Duration;public class _02_AtSourceGenerateWatermark {public static void main(String[] args) throws Exception {StreamExecution…

摇杆控制电机

参考&#xff1a; 摇杆电位器控制步进电机正反转调速-Arduino中文社区 - Powered by Discuz! 一个基于树莓派和Python的无人机视觉跟踪系统_ 北漠苍狼的专栏(QQ:1746430162)-CSDN博客

数字化wms仓库管理软件,实现企业仓储信息共享与智慧运行-亿发

在经济飞速发展的今天&#xff0c;企业面临着客户需求多样化、质量和交期要求提高以及激烈的市场竞争等挑战。在这样的背景下&#xff0c;许多企业开始考虑采用数字化仓储WMS系统来解决这些问题。 数字化仓储WMS系统通过打造高效、规范的仓库管理体系&#xff0c;实现了对产品…