GitHub Actions:YAML 编程荒原中的新希望
程序员最大的超能力在于 她 能够 自动化几乎所有事情。 这就是 GitHub Actions 的优势所在…… 前提是 你能自信地 用 YAML编写一个 GitHub 工作流 来解决 你的特定问题。 这还只是个 假设 。但即使你不能,也还有 希望 。
让我向你介绍一个由 Piotr Krzemiński 发起的开源项目,过去几个月我为该项目做出了很大贡献👨🏻💻
使用 Kotlin 编写 GitHub Actions 工作流。你再也不需要用 YAML 了!
github-workflows-kt是一个在 类型安全脚本中生成 GitHub Actions 工作流 YAML 文件 的 工具 ,可帮助您使用 Kotlin 愉快地为您的 GitHub 项目构建 稳健 的 工作流,而不会出现 错误 。
您不会再回到 YAML!
💡 想法
我们经常被 YAML 配置所包围。它是一种功能强大的格式,提供了用于定义分层数据的简单语法,但有时它会被(滥用?)用于配置复杂的场景,从而导致文件复杂,难以编写和维护。
我们当中谁没有不小心使用了错误的缩进,错过了提取可重用代码的机会,或者被模糊的类型弄糊涂过?在这些情况下,通用编程语言的强大功能就会派上用场。
我们正在开发 github-workflows-kt 来解决这些问题和其他问题,以便您可以放心地创建 GitHub 工作流。
✨ 好处
没有缩进混淆 ——Kotlin 的语法不依赖于它
立即 ……
什么意思 github-actions-kotlin-dsl
?
github-actions-kotlin-dsl
(*) 是一个库,允许您以类型安全的方式为 Kotlin Actions 生成 GitHub 工作流。
(*) 我知道这有点拗口。我个人称之为 github-actions.kts
1) 在免费且出色的 IntelliJ IDEA 社区版中编辑脚本 2) 将脚本放入文件夹中 .github/workflows
,使其可执行 3) 安装 Kotlin 4) github-actions-kotlin-dsl
是用于构建 GitHub Workflow 对象的库 5) 最后,调用 workflow.writeToFile()
6) 生成 .github/workflows/$NAME$.yaml
可在 GitHub Actions 上运行的脚本。
您可以看到蓝色下划线表示 YAML 工作流的主要组件具有直接的 Kotlin 等效项: workflow() Push() job() uses() run() GithubActionNameVxxx()
要实际运行您的第一个 Kotlin 工作流, 请阅读友好的文档
此时,您可能会问自己:
等等,但是为什么🤔?
GitHub Actions 是一项很棒的服务,但是......
程序员的主要超能力是 她 能够 自动化几乎所有事情。
因为这正是 GitHub Actions 的用途,所以一切都很好,对吧?
不幸的是, 大多数人都很难编写 GitHub 工作流程来解决他们的特定问题 :这是因为 YAML 是一种糟糕的编程语言 - 见下文。
因此,我们转而采用 复制/粘贴编程 ,试图找到已经花时间编写工作流程来解决与我们类似的问题的人。
别误会,复制/粘贴编程总比没有好,我已经为 Java/Kotlin 开发人员编写了一份指南,帮助他们快速启动并运行 CI
但如果我们不能自动化解决特定问题,我们就会错失良机。
那么问题是什么?
Github 的 YAML 是一种糟糕的编程语言
普通的 YAML 开发人员试图完成任务,但每次迭代之间都会浪费十分钟或更长时间。
一般来说,YAML 只是编写 JSON 的另一种方式。
有一系列不同的问题...
但 GitHub 按照Duck Typing 的原理,把 YAML 扩展成了我们应该认可的编程语言 。
* 🐥 GitHub YAML 作为编程语言:🐥 *
它允许编写任意脚本
它在 Azure 上的任意 VM 上运行
...具有任意数量的作业和命令
...用任意语言编写的大量插件,可以以各种方式进行配置
...带有变量和秘密
...使用 for 循环 - 又称策略矩阵
...使用布尔逻辑 - 仅当前一个作业成功时才运行此作业,仅在出现错误时运行此操作
...使用强大的 GitHib 表达式 - 又称为 eval
函数
...
如果它走路像鸭子、叫声也像鸭子,那它一定是只鸭子。
这里的问题是 YAML 从来没有为此设计过
因此,IDE 的支持相当差。他们确实会尽力提供帮助,但远不如真正的编程语言。YAML 看起来比 JSON 更花哨,是因为它的规则不那么简单,但这意味着你更容易出错。
最重要的是:
GitHub Action 的编辑-编译-运行反馈循环非常慢
您在上图中看不到的是,GitHub Actions YAML 开发人员可能在脚本的每次迭代中浪费 10 分钟或更长时间!
那么,有没有办法走出 YAML 荒地呢?
类型安全的工作流
在 YAML 中,不正确的语法看起来很像正确的语法。
on:
cron: '7 42 * * 7'
schedule: '7 42 * * 7'
cron:
schedule: '7 42 * * 7'
schedule:
cron: '7 42 * * 7'
schedule:
- cron: '7 42 * * 7'
Enter fullscreen mode
Exit fullscreen mode
哪种语法是正确的?
这次没有争论了。类型系统的存在本身就让各种小错误消失了!
该库还保证其生成的所有内容都是有效的 YAML。无需再等待 CI 生成 MalformedYamlError
...
此外,还有一些运行时检查,它会立即且快速地失败,而不是稍后缓慢地失败。
name: Hello : World!
on :
pr :
schedule :
- cron : ' 7 42 * * 7'
jobs :
" git checkout" :
runs-on : " ubuntu_latest"
steps :
- id : step-0
name: First : git checkout
uses : actions/checkout@v3
Enter fullscreen mode
Exit fullscreen mode
你能找到上述工作流程中的 7 个错误吗?
让我们看一下 Kotlin 的对应代码
val workflow = workflow (
name = "Hello: World" , // 1. runtime error: semicolon not allowed
on = listOf (
Schedule ( listOf (
// 2. named arguments 07:42 instead of 42:07 in the YAML
// 3. runtime error: Field 'dayWeek' outside of range 0..6
Cron ( minute = "42" , hour = "7" , dayWeek = "7" ))
),
PR (), // 4. compile error: should be PullRequest()
),
sourceFile = __FILE__ . toPath (),
) {
job (
id = "git checkout" , // 5. runtime error: space not allowed in a job id
runsOn = ubuntu_latest // 6. compile error: should be UbuntuLatest
) {
// 7. runtime error: semicolon not allowed here
uses ( name = "First: Check out" , action = CheckoutV3 ())
}
}
Enter fullscreen mode
Exit fullscreen mode
只需编译和运行脚本,我们就可以避免大量小错误 ,这些错误会浪费我们在 CI 上的每 10 分钟时间。
类型安全操作
看看这个动作是如何配置的:
steps :
- id : step-0
name : git check out
uses : actions/checkout@v4
with :
branch : main
fetch-depth : 0
Enter fullscreen mode
Exit fullscreen mode
这里有三个问题:
branch
看起来像一个有效参数,但实际上不是
我不知道魔法值是什么 fetch-depth
意思
v4 尚不存在
我们来看看 Kotlin 版本:
在这里我们清楚地看到这 branch
是错误的,自动完成功能告诉我们 ref
使用
F1: Documentation
允许我们查看文档,并且特殊值有一个名称。
CheckoutV4
甚至无法编译
在我写下这些文字的时候,我们已经 支持 89 个动作包装器
类型安全表达式
GitHub Actions 还具有强大的表达式语法。
我想你现在明白了:我们也为它们提供了一种类型安全的替代方案:
更多信息请阅读: https://krzema12.github.io/github-actions-kotlin-dsl/user-guide/type-safe-expressions/
自动迁移您现有的工作流程
现在我知道你在想什么了:
这太酷了,我刚开始的时候就希望有这个功能。 但现在我有一个可以运行的 YAML 工作流, 我不想从头开始。
我理解你的想法。 我也有同样的担忧。
然后一个邪恶的想法在我脑海里诞生了:
好的,所以我们可以编写一个 Kotlin 脚本来生成它的 YAML 版本。 但是,我们能否利用现有的 YAML 来生成一个可以自行生成的 Kotlin 脚本呢?这有点像孩子生下父母一样。
事实证明这是可行的,经过一番深入的思考, 脚本生成器诞生了 。它允许您自动迁移到 Kotlin。
你可以运行如下命令:
$ ./gradlew :script-generator:run --args /path/to/.github/workflows/build.yaml
Kotlin script written to build.main.kts
Run it with: ./build.main.kts
The resulting YAML file with be available at build.yaml
Enter fullscreen mode
Exit fullscreen mode
然后,您可以通过使用https://yamldiff.com/ 进行语义差异来确保新的 YAML 与旧的 YAML 等效
我不会详细介绍: 请阅读友好的文档
幕后:包装器生成器
当我发现这个项目时,图书馆支持的活动可能有十几个。
我主要关心的是:如何扩大规模?
GitHub Actions 有几十个,而且它们总是在发布新版本,添加或弃用参数。
答案:维护者 Piotr Krzemiński 和我引入了 动作包装器的自动生成 。
创建这个包装器生成器需要做很多工作,但它是值得的:
在我写下这些文字的时候,我们已经 支持 89 个动作包装器
幕后:GitHub Actions
另一件让我们能够在有限时间内应对挑战的事情是: GitHub Actions 本身 。
我们是我们库的首批用户,并利用了 GitHub Actions 的强大功能:
检查是否需要更新一些现有的包装器(例如新参数)。
检查现有包装器(V2 到 V3)是否有新的主要版本可用。
自动发布我们的库。
作为我们 PR 上的 CI
对于那些有动力的人来说,我们的行动可以在以下网址找到: https://github.com/krzema12/github-actions-kotlin-dsl/tree/main/.github/workflows
这确实让我深有体会:如果你有信心可以编写一个工作流程来解决你的特定问题,那么 GitHub Actions 将会是一笔多么宝贵的资产。
常问问题
如果我不知道 Kotlin 怎么办?
我认为编程语言的选择并不重要,只要它不是 Bash 就行。我的意思是,任何具有良好 IDE 支持的现代编程语言都可以胜任这项任务。
我们这里只做了一些基本的事情。我们 Workflow
通过调用 workflow()
then job
then run("my command")
或 uses(MyActionWithParameters(....))
唯一的问题是您需要安装 IntelliJ IDEA 社区版, 但它是免费且非常棒。
有什么缺点吗?
如果您在提交之前未运行 Kotlin 脚本,或者忘记提交 YAML 文件,或者直接编辑 YAML 文件,YAML 和 Kotlin 代码将不同步。我们提供了一致性检查,以便在出现这种情况时提前失败。只需使用 即可 workflow.writeToFile(addConsistencyCheck = true)
。代价是持续集成 (CI) 速度会慢 15 秒左右。
GitHub 的 YAML 功能众多,您可能会遇到一些库尚未支持的功能。我们提供了一个 类型不安全的替代方案 来弥补这些缺陷。您也可以查看 未解决的问题 或创建自己的问题。
IntelliJ 不支持 Kotlin 脚本,但它支持常规的 Kotlin 编程。希望这种情况能随着时间的推移得到改善。
编译和运行 Kotlin 脚本比你习惯的 Python 或 JavaScript 等解释型语言要慢。但它仍然比在 CI 上提交、推送并等待 10 分钟要快两个数量级。
如果你在团队中使用它,你必须确保你的同事明白这个 YAML 文件是由 Kotlin 脚本生成的。请注意,第一行 YAML 代码如下: # This file was generated using Kotlin DSL (.github/workflows/hello_world_workflow.main.kts).
欢迎您向他们发送我的文章链接:)
我是 GitHub Action 维护者,我可以帮忙吗?
是的!
规范中缺少的 action.yml
是每个输入参数的类型。我们目前正在 将这些信息添加到我们的代码库中, action-types.yml
但如果能像 一些优秀的早期采用者那样, 将其放在您自己的代码库文件中,那就更好了 。
请参阅 https://github.com/krzema12/github-actions-typing
链接
本文的标题取自 Michel Pardo 的演讲 《Kotlin:Java 6 Wasteland 中的新希望》, 该演讲当年曾让人想转向 Kotlin。
完结
朋友们,就这些了。非常感谢你们让我走到今天。
我特别高兴能够回来写文章,这是我近一年来一直没能做到的事情。
如果您尝试一下,我很乐意听到您的反馈。
鏂囩珷鏉ユ簮锛�https://dev.to/jmfayard/github-actions-a-new-hope-in-yaml-wasteland-1i9c