如何在GitHub Actions中获取特定步骤的输出?

100

我有一个GitHub Actions工作流程,用于运行测试,但现在我正在集成Slack通知。我想要获取运行测试步骤的输出,并将其作为消息发送到Slack步骤中。

  - name: Run tests
    run: |
      mix compile --warnings-as-errors
      mix format --check-formatted
      mix ecto.create
      mix ecto.migrate
      mix test
    env:
      MIX_ENV: test
      PGHOST: localhost
      PGUSER: postgres

  - name: Slack Notification
    uses: rtCamp/action-slack-notify@master
    env:
      SLACK_MESSAGE: Run tests output
      SLACK_TITLE: CI Test Suite
      SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}
4个回答

155
你需要做3件事情:
1. 在你想要输出的步骤中添加一个id。 2. 使用GITHUB_OUTPUT环境变量创建输出。 3. 在另一个步骤中使用id和输出名称来获取输出,然后将它们合并成一个消息发送到slack。
- name: Run tests
  run: |
    echo "mix-compile--warnings-as-errors=$(mix compile --warnings-as-errors)\n" >> $GITHUB_OUTPUT
    echo "mix-format--check-formatted=$(mix format --check-formatted)\n" >> $GITHUB_OUTPUT
    echo "mix-ecto_create=$(mix ecto.create)\n" >> $GITHUB_OUTPUT
    echo "mix-ecto_migrate=$(mix ecto.migrate)\n" >> $GITHUB_OUTPUT
    echo "mix-test=$(mix test)\n" >> $GITHUB_OUTPUT
  id: run_tests
  env:
    MIX_ENV: test
    PGHOST: localhost
    PGUSER: postgres

- name: Slack Notification
  uses: rtCamp/action-slack-notify@v2
  env:
    SLACK_MESSAGE: ${{join(steps.run_tests.outputs.*, '\n')}}
    SLACK_TITLE: CI Test Suite
    SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

请参阅元数据语法以获取输出名称描述。

1
这对我有点用。我的输出结果每行的前导空格都被截断了,而且每行不知何故都被单引号包围。这是否也发生在其他人身上?这是非常奇怪的行为,而且文档不够完善。我正在做同样的事情;尝试捕获命令的输出并将其发送到 Slack,尽管我使用的是 pullreminders/slack-action - Kevin Gwynn
7
GitHub正逐渐弃用set-output命令:https://github.blog/changelog/2022-10-11-github-actions-deprecating-save-state-and-set-output-commands/。 - Rafael Membrives
2
@RafaelMembrives 谢谢你的提示。答案已经更新,使用了新的环境变量。 - smac89
1
在VALUE中的空格是否需要进行特殊处理? - Max Murphy
3
请注意,在PowerShell中,您应该像这样引用环境变量“GITHUB_OUTPUT”:$env:GITHUB_OUTPUT,否则评估输出变量的下一步将会失败。 - Antebios
显示剩余2条评论

22

当前已接受的回答存在问题,因为测试执行结果被echo命令掩盖,导致步骤结果始终为success

对最后一行进行修改应该能保留原始退出状态:

mix test 2>&1 | tee test.log
result_code=${PIPESTATUS[0]}
echo "::set-output name=mix-test::$(cat test.log)"
exit $result_code

2
你测试过这个吗?文档中说,对于bash和非Windows机器上的默认shell,shell会使用set -eo pipefail运行。-e有区别吗?我没有测试过,但我也没有看到过在命令失败时使用-e将允许shell继续执行脚本的情况。我可以稍后测试以确认。 - smac89
我已经成功运行了,没有任何问题。 - juan
当被接受的答案无法解决问题时,这个方法对我也起作用了。 - Gustav Wengel
1
请注意这个解决方案:如果 test.log 包含多行,输出 mix-test 将只接收文件的第一行。参见:Set-output Truncates Multiline Strings #26288 - Ludal
1
::set-output已被弃用 - Kat Lim Ruiz

17

我创建了一个与run接口相同的操作,它将stdoutstderr存储在输出变量中,以简化一些类似于此类的情况:

- name: Run tests
  uses: mathiasvr/command-output@v1
  id: tests
  with:
    run: |
      mix compile --warnings-as-errors
      mix format --check-formatted
      mix ecto.create
      mix ecto.migrate
      mix test

- name: Slack Notification
  uses: rtCamp/action-slack-notify@master
  env:
    SLACK_MESSAGE: ${{ steps.tests.outputs.stdout }}         
    SLACK_TITLE: CI Test Suite
    SLACK_WEBHOOK: ${{ secrets.SLACK_WEBHOOK }}

3

我想补充一下@smac89的解决方案虽然有些帮助,但对我来说不太适用。我使用了不同的Slack操作(pullreminders/slack-action)来构建更具体的内容。我发现每个换行符处都会得到单引号,并且每行开头的空格也被截断了。在阅读了https://github.com/actions/toolkit/issues/403并进行了一些尝试之后,我发现在我的情况下,我需要对输出中的换行符进行转义(一个字面意义上的\n),因此我用\\n字符替换了\n字符。接着,我用Unicode的“En Space”字符替换了普通空格字符。

这是有效的代码:

Bash运行步骤:

        Tools/get-changed-fields.sh src/objects origin/${{ env.DIFF_BRANCH }} > changed-fields.out
        output="$(cat changed-fields.out)"
        output="${output//$'\n'/\\n}"
        output="${output// /}"     # replace regular space with 'En Space'
        echo "::set-output name=changed-fields-output::$output"

Slack通知步骤:

    - name: Changed Fields Slack Notification
      if: ${{ success() && steps.summarize-changed-fields.outputs.changed-fields-output != '' && steps.changed-fields-cache.outputs.cache-hit != 'true' }}
      env:
        SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
      uses: pullreminders/slack-action@master
      with:
        args: '{\"channel\":\"${{ env.SUCCESS_SLACK_CHANNEL }}\",\"attachments\":[{\"color\":\"#36a64f\",\"title\":\"Changed Fields Report:\",\"author_name\":\"${{ github.workflow }} #${{ github.run_number }}: ${{ env.BRANCH }} -> ${{ env.TARGET_ORG }} (by: ${{ github.actor }})\",\"author_link\":\"${{ github.server_url }}/${{ github.repository }}/runs/${{ github.run_id }}\",\"text\":\"```\n${{ steps.summarize-changed-fields.outputs.changed-fields-output }}\n```\"}]}'

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接