Earthly 内置参数(Builtin Args)完全指南:通用、目标、Git 与平台参数详解
【免费下载链接】earthlySuper simple build framework with fast, repeatable builds and an instantly familiar syntax – like Dockerfile and Makefile had a baby.项目地址: https://gitcode.com/gh_mirrors/ea/earthly
导读
本文以 docs/earthfile/builtin-args.md 为骨架,系统讲解 Earthly 内置参数(builtin args)的完整体系:它们由 Earthly 自动填充、无法被覆盖,但可以借助"默认值取自内置参数的普通ARG"实现可覆盖的二次包装。阅读完本文,你将掌握通用参数、目标相关参数、Git 相关参数与平台相关参数四类内置参数的全部名称、语义、示例值与底层实现原理,并能在 Earthfile 中正确预声明、安全引用它们,构建可复现、支持多平台与 CI 场景的构建配方。
一、什么是 Builtin args
Builtin args 是 Earthly 在构建过程中自动填充值的变量。与普通ARG不同,内置参数的值永远不能被覆盖——无论是通过命令行--build-arg、--pass-args,还是在 Earthfile 内的ARG默认值,都无法改变其实际取值。
但 Earthly 提供了一种灵活的变通模式:你可以声明一个额外的普通ARG,将其默认值设为内置参数的值,随后这个新参数就可以被正常覆盖。典型场景是镜像标签:
ARG EARTHLY_TARGET_TAG ARG TAG=$EARTHLY_TARGET_TAG SAVE IMAGE --push some/name:$TAG这里TAG的默认值取自内置参数EARTHLY_TARGET_TAG,当用户在命令行传入--build-arg TAG=...时即可覆盖默认值,实现"默认跟随构建上下文、必要时人工指定"的双重灵活性。
使用前提:必须先预声明
内置参数必须先声明后使用。例如直接引用EARTHLY_TARGET而不先声明会报错:
# 错误:EARTHLY_TARGET 未声明 RUN echo "The current target is $EARTHLY_TARGET"正确的写法是先通过ARG声明:
ARG EARTHLY_TARGET RUN echo "The current target is $EARTHLY_TARGET"这一约束在源码中可以得到印证:variables/reserved/names.go将所有内置参数名登记在一个 map 中,并通过IsBuiltIn函数判定名称是否属于内置参数(见 variables/reserved/names.go);内置参数的实际赋值则统一发生在variables/builtin.go的BuiltinArgs函数中(见 variables/builtin.go),该函数根据目标引用、平台解析器、Git 元数据与功能开关(feature flags)等输入,构造出一个包含全部内置参数的变量作用域。
从源码结构可以推断:内置参数并非运行时"魔法注入",而是由 Earthly 在构建启动阶段一次性计算并放入内置作用域,Earthfile 解析器随后要求使用前显式
ARG声明,从而保证构建配方的可读性与显式性。
二、通用参数(General args)
| 名称 | 描述 | 示例值 |
|---|---|---|
EARTHLY_CI | 构建是否运行在--ci模式下。 | true、false |
EARTHLY_BUILD_SHA | 构建当前运行的 Earthly 版本时所用的 Git 提交哈希。 | 1a9eda7a83af0e2ec122720e93ff6dbe9231fc0c |
EARTHLY_LOCALLY | 当前 target 是否以LOCALLY方式执行。 | true、false |
EARTHLY_PUSH | earthly命令是否带有--push标志。 | true、false |
EARTHLY_VERSION | 当前运行的 Earthly 版本号。 | v0.8.0 |
这些参数在 variables/builtin.go 中的注入逻辑如下:
EARTHLY_PUSH仅在启用WaitBlock(--wait-block)功能开关时注入,值为push布尔量的字符串形式;EARTHLY_VERSION与EARTHLY_BUILD_SHA仅在启用EarthlyVersionArg(--earthly-version-arg,VERSION 0.7 起默认启用)时注入,值来自外部传入的DefaultArgs结构体(见 variables/builtin.go);EARTHLY_CI仅在启用EarthlyCIArg(--ci-arg)时注入;EARTHLY_LOCALLY仅在启用EarthlyLocallyArg(--earthly-locally-arg)时注入,且初始值为false。
从 features/features.go 可以看到,这些功能开关大多在VERSION 0.7中随版本默认启用,因此现代 Earthfile(如VERSION 0.7+)中可以放心使用。
在LOCALLY模式下,EARTHLY_LOCALLY会被置为true:源码中 earthfile2llb/converter.go 在进入本地执行分支时调用SetLocally(true),而常规构建则调用SetLocally(false)(见 earthfile2llb/converter.go)。
三、目标相关参数(Target-related args)
这组参数描述"当前正在构建的 target"的规范引用(canonical reference)各组成部分。
| 名称 | 描述 | 示例值 |
|---|---|---|
EARTHLY_TARGET_NAME | 当前 target 规范引用的名字部分。 | 对于github.com/bar/buz/src:john/work+foo,名字为foo |
EARTHLY_TARGET_PROJECT_NO_TAG | 当前 target 规范引用的项目部分,不含 tag。 | 对于github.com/bar/buz/src:john/work+foo,为github.com/bar/buz/src |
EARTHLY_TARGET_PROJECT | 当前 target 规范引用的项目部分。 | 对于github.com/bar/buz/src:john/work+foo,为github.com/bar/buz/src:john |
EARTHLY_TARGET_TAG_DOCKER | 当前 target 规范引用的 tag 部分,经过净化处理,保证可作为合法的 Docker tag 使用;即使不存在规范形式,也会保证是合法的 Docker tag(此时用latest)。 | 对于github.com/bar/buz/src:john/work+foo,为john_work |
EARTHLY_TARGET_TAG | 当前 target 规范引用的 tag 部分;若 target 没有规范形式,则为空字符串。 | 对于github.com/bar/buz/src:john/work+foo,为john/work |
EARTHLY_TARGET | 当前 target 的完整规范引用。 | 见下 |
以footarget 为例:它存在于john/work分支、仓库位于github.com/bar/buz、子目录为src,则规范引用为github.com/bar/buz/src:john/work+foo。关于规范引用的完整定义,参见 导入指南(canonical form):规范引用本质上是 target 的远程形式,仓库位置取自origin远程,子目录即 target 所在目录,tag 则按"首个 Git tag → 当前分支 → 当前 Git hash"的优先级推断;如果 Earthly 未检测到任何 Git 上下文,则该 target 不具有规范形式。
源码实现细节
在 variables/builtin.go 中:
ret.Add(arg.EarthlyTarget, target.StringCanonical()) ret.Add(arg.EarthlyTargetProject, target.ProjectCanonical()) targetNoTag := target targetNoTag.Tag = "" ret.Add(arg.EarthlyTargetProjectNoTag, targetNoTag.ProjectCanonical()) ret.Add(arg.EarthlyTargetName, target.Target) setTargetTag(ret, target, gitMeta)其中setTargetTag(见 variables/builtin.go)的取值逻辑值得注意:如果检测到 Git 元数据且存在分支覆盖标志(BranchOverrideTagArg),则优先使用分支名作为EARTHLY_TARGET_TAG;否则使用 target 自身的 tag。EARTHLY_TARGET_TAG_DOCKER则通过llbutil.DockerTagSafe函数将 tag 净化成合法的 Docker tag 形式(如将john/work转换为john_work)。
实战示例:用内置 tag 给镜像打标签
build: FROM alpine:3.18 ARG EARTHLY_TARGET_TAG ARG TAG=$EARTHLY_TARGET_TAG SAVE IMAGE --push some/name:$TAG若在带规范引用的 Git 仓库中运行,TAG默认为当前分支/tag;在命令行传入--build-arg TAG=stable即可覆盖。
仓库中的集成测试 tests/builtin-args.earth 验证了这些行为:在无 Git 上下文的本地构建中,EARTHLY_TARGET等于+builtin-args-test、EARTHLY_TARGET_PROJECT为空、EARTHLY_TARGET_TAG为空字符串(test -z断言),这正对应"无规范形式时 tag 为空"的文档描述。
四、Git 相关参数(Git-related args)
这组参数从构建上下文目录中检测到的 Git 仓库提取信息;若未检测到 Git 目录,值为空字符串。
| 名称 | 描述 | 示例值 | 功能开关(Feature Flag) |
|---|---|---|---|
EARTHLY_GIT_AUTHOR | 构建上下文目录中检测到的 Git 作者。未检测到 Git 目录时为空字符串。当前默认只含作者邮箱,启用开关后包含姓名。 | john@example.com(开启开关后为John Doe <john@example.com>) | --earthly-git-author-individual-args |
EARTHLY_GIT_AUTHOR_EMAIL | 构建上下文目录中检测到的 Git 作者邮箱。未检测到 Git 目录时为空字符串。 | john@example.com | --earthly-git-author-individual-args |
EARTHLY_GIT_AUTHOR_NAME | 构建上下文目录中检测到的 Git 作者姓名。未检测到 Git 目录时为空字符串。 | John Doe | --earthly-git-author-individual-args |
EARTHLY_GIT_CO_AUTHORS | 构建上下文目录中检测到的 Git 共同作者,以空格分隔。未检测到 Git 目录时为空字符串。 | Jane Doe <jane@example.com Jack Smith <jack@example.com> | — |
EARTHLY_GIT_COMMIT_AUTHOR_TIMESTAMP | 检测到的 Git 提交的作者时间戳(Unix 秒)。未检测到 Git 目录时为空字符串。 | 1626881847 | — |
EARTHLY_GIT_BRANCH | 检测到的 Git 提交所在分支。未检测到 Git 目录时为空字符串。 | main | — |
EARTHLY_GIT_COMMIT_TIMESTAMP | 检测到的 Git 提交的提交者时间戳(Unix 秒)。未检测到 Git 目录时为空字符串。 | 1626881847 | — |
EARTHLY_GIT_HASH | 检测到的 Git 提交哈希。未检测到 Git 目录时为空字符串。注意:该值频繁变化,可能导致无法命中缓存,使用需谨慎。 | 41cb5666ade67b29e42bef121144456d3977a67a | — |
EARTHLY_GIT_ORIGIN_URL | 检测到的 Git 远程 URL。未检测到 Git 目录时为空字符串。注意该值可能不一致,取决于使用的是 HTTPS 还是 SSH URL。 | git@github.com:bar/buz.git或https://github.com/bar/buz.git | — |
EARTHLY_GIT_PROJECT_NAME | 从 Git URL 中提取的项目名。未检测到 Git 目录时为空字符串。 | bar/buz | — |
EARTHLY_GIT_REFS | 检测到的 Git 提交的引用(refs),以空格分隔。未检测到 Git 目录时为空字符串。 | issue-2735-git-ref main | — |
EARTHLY_GIT_SHORT_HASH | 检测到的 Git 提交哈希的前 8 个字符。未检测到 Git 目录时为空字符串。注意:同样频繁变化,可能影响缓存命中。 | 41cb5666 | — |
EARTHLY_SOURCE_DATE_EPOCH | 检测到的 Git 提交时间戳(Unix 秒)。未检测到 Git 目录时为0(Unix 纪元)。 | 1626881847、0 | — |
功能开关与版本演进
这些参数的注入严格受功能开关控制(见 features/features.go):
--earthly-git-author-args(VERSION 0.7 起启用):注入EARTHLY_GIT_AUTHOR与EARTHLY_GIT_CO_AUTHORS,此时EARTHLY_GIT_AUTHOR的值为作者邮箱;--git-author-email-name-args(未发布功能):注入EARTHLY_GIT_AUTHOR_EMAIL与EARTHLY_GIT_AUTHOR_NAME,同时将EARTHLY_GIT_AUTHOR升级为Name <email>格式(见 variables/builtin.go);--git-commit-author-timestamp(VERSION 0.7 起启用):注入EARTHLY_GIT_COMMIT_AUTHOR_TIMESTAMP;--git-refs(VERSION 0.8 起启用):注入EARTHLY_GIT_REFS。
对应源码注入逻辑位于 variables/builtin.go:当gitMeta非空时依次注入 hash、短 hash、分支、tag、origin URL、脱敏后的 origin URL(EARTHLY_GIT_ORIGIN_URL_SCRUBBED,用于安全地输出到日志)、项目名与各时间戳;当gitMeta为空(未检测到 Git 目录)时,仅保证EARTHLY_SOURCE_DATE_EPOCH恒为0。
EARTHLY_GIT_PROJECT_NAME的提取算法为getProjectName(见 variables/builtin.go):它剥离协议前缀(http://、https://、ssh://等)、剥离开头的user@、去掉.git后缀,并兼容git@github.com:bar/buz.git这类 scp 风格 URL;对应的单元测试见 variables/builtin_test.go,覆盖了 HTTP(S)、SSH、带凭据、带子目录等多种 URL 形态。
实战:如何安全使用 Git 参数
# 注意:EARTHLY_GIT_HASH 频繁变化会破坏缓存,仅用于需要唯一标识的产物 build: ARG EARTHLY_GIT_SHORT_HASH RUN echo "building commit $EARTHLY_GIT_SHORT_HASH"测试文件 tests/empty-git.earth 展示了无 Git 上下文时的行为:EARTHLY_GIT_HASH为空字符串(test "$EARTHLY_GIT_HASH" == ""),EARTHLY_TARGET_TAG同样为空。因此涉及 Git 参数的逻辑必须对空值有兜底处理。
五、平台相关参数(Platform-related args)
这组参数描述构建运行环境与目标平台,与 Dockerfile 中的平台参数同源(TARGETOS/TARGETARCH/TARGETPLATFORM/TARGETVARIANT),并扩展出 NATIVE 与 USER 两套维度。
| 名称 | 描述 | 示例值 |
|---|---|---|
NATIVEARCH | 构建运行器的原生处理器架构。 | arm、amd64、arm64 |
NATIVEOS | 构建运行器的原生操作系统。 | linux |
NATIVEPLATFORM | 构建运行器的原生平台。 | linux/arm/v7、linux/amd64、darwin/arm64 |
NATIVEVARIANT | 构建运行器的原生处理器架构变体。 | v7 |
TARGETARCH | 目标 target 构建所面向的处理器架构。 | arm、amd64、arm64 |
TARGETOS | 目标 target 构建所面向的操作系统。 | linux |
TARGETPLATFORM | 目标 target 构建所面向的平台,默认取原生平台。 | linux/arm/v7、linux/amd64、linux/arm64 |
TARGETVARIANT | 目标 target 构建所面向的处理器架构变体。 | v7 |
USERARCH | 用户(调用earthly二进制的环境)的处理器架构。 | arm、amd64、arm64 |
USEROS | 用户(调用earthly二进制的环境)的操作系统。 | darwin |
USERPLATFORM | 用户(调用earthly二进制的环境)的平台。 | darwin/amd64、linux/amd64、darwin/arm64 |
USERVARIANT | 用户(调用earthly二进制的环境)的处理器架构变体。 | v7 |
三个维度的含义
- TARGET(目标):target 实际构建运行所面向的平台,决定产物形态。非
LOCALLY时,TARGETPLATFORM默认等于运行器的原生平台。 - NATIVE(原生):BuildKit 构建运行器的实际平台。启用
--new-platform(NewPlatform开关,VERSION 0.7 起)后才会注入 NATIVE 系列参数。 - USER(用户):执行
earthly命令的本地环境平台,与构建运行器(可能是远程 BuildKit 或 Docker 容器)平台不一定相同。
对应的注入逻辑见 variables/builtin.go:SetPlatformArgs基于平台解析器当前平台填充 TARGET 系列;setUserPlatformArgs填充 USER 系列;setNativePlatformArgs仅在NewPlatform开关开启时填充 NATIVE 系列。所有参数名均登记在 variables/reserved/names.go。
覆盖 TARGETPLATFORM 的三种方式
TARGETPLATFORM的默认值(非 LOCALLY 时)为运行器原生平台,可通过以下方式覆盖:
1. CLI 全局--platform标志
earthly --platform linux/amd64 +my-target这会将TARGETPLATFORM设为linux/amd64。
2. Earthfile 内BUILD --platform
BUILD --platform linux/amd64 +my-target3.FROM --platform指定基础镜像平台
FROM --platform linux/amd64 alpine:3.13LOCALLY 下的特殊行为
在LOCALLY模式下,TARGETPLATFORM始终等于用户平台(即调用earthly二进制的环境),并且不会被--platform标志覆盖。
此时有一个重要的声明顺序约束:TARGETPLATFORM必须在LOCALLY命令之后声明,才能取到正确的用户平台值:
my-target: LOCALLY ARG TARGETPLATFORM RUN echo "The target platform under LOCALLY is $TARGETPLATFORM"如果颠倒顺序、在LOCALLY之前声明,TARGETPLATFORM可能取不到用户平台值。这一约束与内置参数"构建启动时一次性注入"的实现方式相关——从源码结构看,LOCALLY命令会触发本地执行分支的状态切换,平台参数的作用域随之更新。
多平台构建实战模板
build: FROM alpine:3.18 ARG TARGETARCH ARG TARGETOS RUN echo "Building for $TARGETOS/$TARGETARCH" # 按架构下载对应二进制等 RUN wget -O /bin/app https://example.com/bin/app-$TARGETOS-$TARGETARCH SAVE ARTIFACT /bin/app AS LOCAL app-$TARGETOS-$TARGETARCH # 多平台输出:对每个目标平台分别构建 all: BUILD --platform linux/amd64 +build BUILD --platform linux/arm64 +build结合TARGETARCH/TARGETOS,可以在单个 target 内根据目标平台差异化执行下载、编译与打包,配合BUILD --platform实现真正的多平台产物输出。
六、内置参数的完整使用要点总结
- 先声明后使用:所有内置参数在使用前必须用
ARG显式声明,否则会报错。 - 不可覆盖,但可包装:内置参数值永远不可被覆盖;若需要可覆盖的默认值,声明
ARG X=$BUILTIN形式的普通参数即可。 - 受功能开关(feature flags)控制:部分内置参数(如 Git 作者系列、
EARTHLY_GIT_REFS、NATIVE 平台系列)依赖 VERSION 中的功能开关,使用前需确认 Earthfile 的VERSION声明(参考 features/features.go 中各开关的enabled_in_version)。 - 注意缓存影响:
EARTHLY_GIT_HASH、EARTHLY_GIT_SHORT_HASH随提交频繁变化,会显著降低缓存命中率,仅在确实需要唯一标识时使用。 - 无 Git 上下文时的空值:未检测到 Git 目录时,所有 Git 相关参数为空字符串,
EARTHLY_SOURCE_DATE_EPOCH为0,代码中需对空值做兜底。 - LOCALLY 模式特例:
TARGETPLATFORM在 LOCALLY 下恒为用户平台且不可被--platform覆盖;平台参数声明须放在LOCALLY命令之后。
深入阅读
- 内置参数官方参考:docs/earthfile/builtin-args.md
- 内置参数注入实现:variables/builtin.go
- 内置参数名登记与判定:variables/reserved/names.go
- 功能开关定义:features/features.go
- 规范引用(canonical form)说明:docs/guides/importing.md
- 集成测试:tests/builtin-args.earth、tests/empty-git.earth
- 平台参数提取单元测试:variables/builtin_test.go
【免费下载链接】earthlySuper simple build framework with fast, repeatable builds and an instantly familiar syntax – like Dockerfile and Makefile had a baby.项目地址: https://gitcode.com/gh_mirrors/ea/earthly
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考