GitLab CI 的多行 YAML 字符串 (.gitlab-ci.yml)
Posted
技术标签:
【中文标题】GitLab CI 的多行 YAML 字符串 (.gitlab-ci.yml)【英文标题】:Multiline YAML string for GitLab CI (.gitlab-ci.yml) 【发布时间】:2017-07-22 10:53:51 【问题描述】:我正在尝试编写一个gitlab-ci.yml
文件,该文件使用多行字符串作为命令。但是,它似乎没有被解析。我已经尝试了- |
和- >
,结果相同。
stages:
- mystage
Build:
stage: mystage
script:
- |
echo -e "
echo 'hi';
echo 'bye';
"
当它尝试运行时,它只显示echo -e '
作为要运行的脚本,而不是整个多行字符串。这给我带来了问题。
写这样的东西的正确语法是什么?
【问题讨论】:
有一个问题:gitlab.com/gitlab-org/gitlab-ci-multi-runner/issues/166 我不清楚问题是什么,因为您的代码应该与那里提出的解决方案等效(足够)YAML。您可以尝试将\
附加到您的行中,但我不能说这是否可行。
【参考方案1】:
我来这里是先发制人的,以为这会是个问题,但以下用于提高可读性的“多行”命令对我有用:
Gitlab Runner: Shell Runner 版本 1.11.0 / Gitlab 版本: 8.17.2
myjob:
stage: deploy
script:
# Single line command
- az component update --add sql
# Multi-line command
- az sql server create -n $variable -g $variable -l $variable
--administrator-login $variable --administrator-login-password $variable
【讨论】:
这里有什么诀窍?您是否将第二行缩进到与第一行相同的级别? @victor-grazi 据我了解:在纯 YAML(纯流标量)中,转义(例如换行符\n
)不执行任何操作,并且忽略前导空格 - 它似乎Gitlab YAML 以这种方式解析脚本块。关于缩进:YAML 规范说In YAML block styles, structure is determined by indentation
,因此第二行的缩进量与 YAML 规范所需的一样多(相对于父缩进一个空格),并且为了可读性而多缩进一个(这在技术上是多余的,但更漂亮)。
像魅力一样工作。也适用于新行中的所有参数【参考方案2】:
TL;DR;你想使用一个多行 YAML 标量(为了可读性),它作为单行字符串加载,可以由 Gitlab-CI 作为命令发出。为此,请在 YAML 中使用分布在多行中的普通(不带引号)标量:
script:
- echo -e
"echo 'hi';
echo 'bye';"
请注意,YAML 对此类标量施加了一些限制。您当然需要知道的是,接下来的每一行都比echo -e
缩进至少一个位置(相对于它的集合节点缩进两个位置,根本不缩进),并且每个新行都被替换加载时按空格(因此您需要注意在哪里放置换行符)。
您的帖子中存在多种误解,导致您提出错误的问题。
没有多行 YAML 字符串这种东西。 YAML 有标量,其中一些标量可以由程序加载为字符串,而其他一些将加载为整数、浮点数等。
您显然对作为字符串加载的标量节点感兴趣,因为该字符串可以被解释为命令行。但是您不想拥有多行命令行(即嵌入换行符),因为 Gitlab CI 不支持 multi-line scripts(如 @Jordan 所示)。
为了便于阅读,您希望使用 YAML 的标准功能将多行标量加载为单行字符串。
如果您不关心可读性,您可以使用:
- echo -e "\n echo 'hi';\n echo 'bye';\n"
并且由于您的标量没有被引用(即它以 echo
开头),您不需要在 YAML 中为反斜杠或引号做任何特殊的事情。
脚本的结果是一样的(打印一个空行,在缩进四个空格的行上打印echo 'hi';
,在缩进四个空格的行上打印echo 'bye';
。)
如果您想使用多行输入以提高可读性,将其作为单行加载,基本上有两种选择:使用多行平面标量或在 YAML 中使用折叠标量。
多行纯标量
Plain 表示标量未加引号,与 YAML 中的任何多行内容一样,多行表示后面的行需要适当缩进,在这种情况下比初始行更远
script:
- echo -e
"echo 'hi';
echo 'bye';"
换行符被空格替换,所以不要这样做:
script:
- echo -e
"echo 'hi';
echo '
bye';"
因为您将在bye
之前获得一个可见空间。
有一些限制,例如在这样的标量中不能有冒号后跟空格(这会使它看起来像键值对)。
没有必要在纯标量中转义反斜杠,因为您无法在纯标量中转义任何字符,但当然您可以包含反斜杠,它最终会出现在从 YAML 加载的字符串中,可以 对从该字符串执行的命令有意义。
折叠标量
折叠标量类似于普通标量,在加载期间所有(单个)换行符都被空格替换:
script:
- >
echo -e
"echo 'hi';
echo 'bye';"
您需要缩进实际命令信息至少与折叠标量指示符 (>
) 一样多。
与普通的标量相反,:
这样的东西没有特殊含义。因此,如果普通标量因抛出 YAML 错误而失败,则类似的折叠标量很可能不会。
【讨论】:
为了清晰和可维护性,我想多行编写它。虽然我的例子很简单,但真正的脚本绝对不是。 我能理解。在 GitLab CI 处理可读 YAML 文件之前对其进行预处理是否可以接受? 我已经考虑过了。这是一个额外的步骤并增加了一些复杂性,但可能是值得的。 我添加了一个可能的解决方案。 哦,男孩。虽然在技术上是正确的,但这个答案却荒谬地冗长到难以阅读的程度。每个不编写 YAML 解析器的人可能只想要 PotatoFarmer 的 highly upvoted and much terser answer,而不是。【参考方案3】:您可以通过 yaml literal_block 和锚点功能使用任何多行脚本/命令。示例:
.build: &build |
echo -e "\n$hl? Building $green$build_path/$build_assets_dir/*.js $nl\n"
echo -e "javascript-obfuscator $build_path/$build_assets_dir/*.js"
[...]
build:master:
stage: build
script:
- *rsync
- *build
[...]
【讨论】:
感谢您的分享 - 这个更高级的功能对于作业的可读性/能够在整个配方中重用代码块特别有用。 这是一个很好的例子,但如果你定义 .rsync 会更清楚【参考方案4】:wp config create 命令非常挑剔...来自 .gitlab-ci...
build:
stage: build
script:
- echo "Building the app"
- |
wp config create --dbname=$vardb --dbhost=$varhost --dbuser=$varusr --dbpass=$varpas --extra-php <<PHP
define( 'WP_DEBUG', false );
define( 'FS_METHOD', 'direct' );
define( 'WP_POST_REVISIONS', 5 );
define( 'AUTOSAVE_INTERVAL', 600 );
PHP
- scp ./wp-config.php continued...
allow_failure: true
【讨论】:
【参考方案5】:这在 Travis CI 中为我工作
before_install:
- set -e
- |
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
<settings xmlns=\"http://maven.apache.org/SETTINGS/1.0.0\"
xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
xsi:schemaLocation=\"http://maven.apache.org/SETTINGS/1.0.0
http://maven.apache.org/xsd/settings-1.0.0.xsd\">
<servers>
<server>
<id>github</id>
<username>$GITHUB_USERNAME</username>
<password>$GITHUB_PASSWORD</password>
</server>
</servers>
</settings>
" > $HOME/.m2/settings.xml
这里还将插入两个 env 变量($GITHUB_USERNAME
和 $GITHUB_PASSWORD
)
【讨论】:
【参考方案6】:这种格式可以工作。在 YAML 中使用普通(不带引号)标量。例如用于初始化 terraform 后端的脚本
before_script:
- cd $TF_ROOT
- terraform init -backend-config="address=$GITLAB_TF_ADDRESS"
-backend-config="lock_address=$GITLAB_TF_ADDRESS/lock"
-backend-config="unlock_address=$GITLAB_TF_ADDRESS/lock"
-backend-config="username=$GITLAB_USER_LOGIN" -backend-config="password=$GITLAB_ACCESS_TOKEN"
-backend-config="lock_method=POST" -backend-config="unlock_method=DELETE"
-backend-config="retry_wait_min=5"
【讨论】:
以上是关于GitLab CI 的多行 YAML 字符串 (.gitlab-ci.yml)的主要内容,如果未能解决你的问题,请参考以下文章
无法在 GitLab CI YAML 中打印包含双引号的字符串
如何使用 JAVA_OPTS 在 gitlab-ci.yaml 中设置 Gradle 代理变量
聊聊如何将gitlab ci的环境变量透传给k8s deployment.yaml