使用 jq 检查 GitLab-CI 中是否存在密钥

Checking for presence of keys in GitLab-CI with jq

提问人:rosaLux161 提问时间:11/15/2023 最后编辑:Léa GrisrosaLux161 更新时间:11/16/2023 访问量:57

问:

我正在尝试分析 GitLab-CI 中的一个变量,看看是否有两个键,以及一个值是否具有某个值。

我现在的看起来像这样:

if [[ $(echo $TRIGGER_PAYLOAD | jq -e '.changes.title.previous and .changes.title.current and .object_attributes.detailed_merge_status == "mergeable"') ]]; then
    echo 'Do something'
fi

我已经尝试了很多东西,包括 select(),但现在我不知道该怎么做。


我刚刚为此创建了一个最小的示例:

set -x
payload="{\"object_attributes\": {\"detailed_merge_status\": \"draft_status\"},\"changes\": {}}"
echo $(echo $payload | jq -r .)

if jq -e '.changes.title.previous and .changes.title.current and .object_attributes.detailed_merge_status == "mergeable"' <<<"$payload"; then
    echo "true"
else
    echo "false"
fi

这个有效,反之亦然:

set -x
payload="{\"changes\": {\"title\": {\"previous\": \"test\", \"current\": \"test\"}},\"object_attributes\": {\"detailed_merge_status\": \"mergeable\"}}"
echo $(echo $payload | jq -r .)

if jq -e '.changes.title.previous and .changes.title.current and .object_attributes.detailed_merge_status == "mergeable"' <<<"$payload"; then
    echo "true"
else
    echo "false"
fi

如果我现在使用实际有效负载而不是虚拟 JSON,它就不能再工作了。而 jq 在 .key.key 上的简单查询适用于所有值。

$ if jq -e '.changes.title.previous and .changes.title.current and .object_attributes.detailed_merge_status == "mergeable"' <<<"$TRIGGER_PAYLOAD"; then # collapsed multi-line command
++ echo '$ if jq -e '\''.changes.title.previous and .changes.title.current and .object_attributes.detailed_merge_status == "mergeable"'\'' <<<"$TRIGGER_PAYLOAD"; then # collapsed multi-line command'
++ jq -e '.changes.title.previous and .changes.title.current and .object_attributes.detailed_merge_status == "mergeable"'
parse error: Invalid numeric literal at line 2, column 0
++ echo false
false
json bash shell gitlab jq

评论

1赞 Charles Duffy 11/15/2023
但是,如果没有更多关于到底出了什么问题的细节,我们无法确定这些事情是否是您的直接问题。(用于获取实际值的日志,并注意 stderr 是否从 jq 传递错误消息;错误消息、示例输入 &c 需要包含在问题本身中,以构成适当的最小可重现示例set -x)
1赞 Charles Duffy 11/15/2023
(要解释 printf-vs-echo 的建议,请参阅 Unix 和 Linux 问题的答案 为什么 printf 比 echo 更好? -- 特别是如果你不知道你的 CI 进程使用哪个 shell 运行,它可能与你的不同 -- bash 默认与 POSIX 略有不兼容(严格合规的 POSIX 将在输出时进行打印);容器通常使用 sh 实现而没有这些问题)。echoechoecho -e-e
1赞 rickhg12hs 11/16/2023
@CharlesDuffy 也会在这里工作吗?jq -n '$ENV.TRIGGER_PAYLOAD | ...'
1赞 Charles Duffy 11/16/2023
@rickhg12hs,它需要导出,但通常最好使用 和 。(我仍然希望 jq 可以设置自己的退出状态,并且......为什么我们要从 jq 传输管道?-n$ENV-e
1赞 Charles Duffy 11/16/2023
(LéaGris 的回答对我来说看起来很棒——所以虽然我很欣赏你对这个问题的更新,但我现在要退出,除非你发表评论并指出还有更多要添加的东西)。

答:

2赞 Léa Gris 11/16/2023 #1

测试命令的返回状态时,不使用括号测试,而是直接使用命令 (*1)。

以下是执行测试的方法:

#!/usr/bin/env bash

# Testing data
triggerPayload='
{
  "changes": {
    "title": {
      "previous": "test",
      "current": "test"
    }
  },
  "object_attributes": {
    "detailed_merge_status": "mergeable"
  }
}
'

# shellcheck disable=SC2016 # Does not expand shell expressions
jqFilter='
$j | (
  .changes.title.previous and
  .changes.title.current and
  .object_attributes.detailed_merge_status == "mergeable"
)'

if jq --exit-status --null-input --argjson j "$triggerPayload" "$jqFilter" >/dev/null; then
    echo 'Do something'
fi

笔记:

  1. or 实际上是一个 shell 命令,它接受测试参数,其中最后一个参数必须分别是 or。[[[]]]