【问题标题】:Using output from a previous job in a new one in a GitHub Action在 GitHub Action 的新作业中使用先前作业的输出
【发布时间】:2020-03-29 05:10:01
【问题描述】:

出于(主要)教学原因,我正在尝试在 GitHub 操作中运行此工作流程:

name: "We ???? Perl"
on:
  issues:
    types: [opened, edited, milestoned]

jobs:
  seasonal_greetings:
    runs-on: windows-latest
    steps:
      - name: Maybe greet
        id: maybe-greet
        env:
          HEY: "Hey you!"
          GREETING: "Merry Xmas to you too!"
          BODY: ${{ github.event.issue.body }}
        run: |
          $output=(perl -e 'print ($ENV{BODY} =~ /Merry/)?$ENV{GREETING}:$ENV{HEY};')
          Write-Output "::set-output name=GREET::$output"
  produce_comment:
    name: Respond to issue
    runs-on: ubuntu-latest
    steps:
      - name: Dump job context
        env:
          JOB_CONTEXT: ${{ jobs.maybe-greet.steps.id }}
        run: echo "$JOB_CONTEXT"

我需要两个不同的工作,因为它们使用不同的上下文(操作系统),但我需要将第一个工作中的一个步骤的输出传递给第二个工作。我正在尝试使用jobs 找到的here 上下文的几种组合,但似乎没有任何方法可以做到这一点。显然,jobs 只是一个没有真正上下文的 YAML 变量的名称,而上下文 job 只包含成功或失败。有什么想法吗?

【问题讨论】:

    标签: perl github-actions


    【解决方案1】:

    检查 2020 年 4 月的“GitHub Actions: New workflow features”,这可能对您的情况有所帮助(参考以前工作的步骤输出)

    工作产出

    您可以指定一组要传递给后续作业的输出,然后从您的需求上下文中访问这些值。

    documentation:

    jobs.<jobs_id>.outputs
    

    工作输出地图

    作业输出可用于依赖此作业的所有下游作业。
    有关定义作业依赖项的更多信息,请参阅jobs.&lt;job_id&gt;.needs

    作业输出是字符串,包含表达式的作业输出在每个作业结束时在运行器上进行评估。包含秘密的输出在运行器上被编辑,而不是发送到 GitHub Actions。

    要在依赖作业中使用作业输出,您可以使用 needs 上下文。
    更多信息见“Context and expression syntax for GitHub Actions.

    要在依赖作业中使用作业输出,您可以使用需求上下文。

    例子

    jobs:
      job1:
        runs-on: ubuntu-latest
        # Map a step output to a job output
        outputs:
          output1: ${{ steps.step1.outputs.test }}
          output2: ${{ steps.step2.outputs.test }}
        steps:
        - id: step1
          run: echo "::set-output name=test::hello"
        - id: step2
          run: echo "::set-output name=test::world"
      job2:
        runs-on: ubuntu-latest
        needs: job1
        steps:
        - run: echo ${{needs.job1.outputs.output1}} ${{needs.job1.outputs.output2}}
    

    Jesse Adelman 加入the comments

    这似乎不适用于静态字符串以外的任何内容。
    例如,我将如何获取 step 的多行文本输出(例如,我正在运行 pytest 或类似的)并将该输出用于另一个作业?

    【讨论】:

    • 谢谢。这似乎不适用于静态字符串以外的任何内容。例如,我将如何获取 step 的多行文本输出(例如,我正在运行 pytest 或类似的)并将该输出用于另一个作业?
    • @JesseAdelman 好问题:我不确定。您应该提出一个单独的问题,并附上指向该答案的链接,以获得更准确的答案。
    • @Jesse Adelman,在这种情况下,您可能希望将多行文本写入文件。
    • 或者,您可以对输出进行 base64 编码,然后在下一个作业中对其进行解码
    • 对于任何想知道为什么没有生成输出的人;检查您的步骤是否使用id 而不是name
    【解决方案2】:

    更新:现在可以设置可用于将字符串值传输到下游作业的作业输出。见this answer

    以下是原始答案。这些技术对于某些用例可能仍然有用。

    1. 将数据写入文件并使用actions/upload-artifactactions/download-artifact。有点尴尬,但确实有效。
    2. 创建存储库调度事件并将数据发送到第二个工作流。我个人更喜欢这种方法,但缺点是它需要repo 作用域PAT

    这是第二种方式如何工作的示例。它使用repository-dispatch 动作。

    name: "We ? Perl"
    on:
      issues:
        types: [opened, edited, milestoned]
    
    jobs:
      seasonal_greetings:
        runs-on: windows-latest
        steps:
          - name: Maybe greet
            id: maybe-greet
            env:
              HEY: "Hey you!"
              GREETING: "Merry Xmas to you too!"
              BODY: ${{ github.event.issue.body }}
            run: |
              $output=(perl -e 'print ($ENV{BODY} =~ /Merry/)?$ENV{GREETING}:$ENV{HEY};')
              Write-Output "::set-output name=GREET::$output"
          - name: Repository Dispatch
            uses: peter-evans/repository-dispatch@v1
            with:
              token: ${{ secrets.REPO_ACCESS_TOKEN }}
              event-type: my-event
              client-payload: '{"greet": "${{ steps.maybe-greet.outputs.GREET }}"}'
    

    这会触发同一存储库中的存储库调度工作流。

    name: Repository Dispatch
    on:
      repository_dispatch:
        types: [my-event]
    jobs:
      myEvent:
        runs-on: ubuntu-latest
        steps:
          - run: echo ${{ github.event.client_payload.greet }}
    

    【讨论】:

    • 此外,第二个工作流不会显示为链接到原始推送或拉取请求。
    • 我相信output 现在已更改为outputs 所以${{ steps.maybe-greet.outputs.GREET }}
    • @MoltenIce 这是一个错字。我已经纠正了。谢谢。
    【解决方案3】:

    可以在run 步骤中捕获命令的整个输出(和返回代码),我在此写下此步骤,希望能免去其他人的麻烦。 公平警告,它需要大量的 shell 技巧和多行 run 以确保所有事情都发生在单个 shell 实例中。

    在我的例子中,我需要调用一个脚本并捕获其标准输出的整个以供后续步骤使用,并保留其结果以供错误检查:

    # capture stdout from script 
    SCRIPT_OUTPUT=$(./do-something.sh)
    
    # capture exit code as well
    SCRIPT_RC=$?
    
    # FYI, this would get stdout AND stderr
    SCRIPT_ALL_OUTPUT=$(./do-something.sh 2>&1)
    

    由于 Github 的作业输出似乎只能捕获单行文本,我不得不为输出转义任何换行符:

    echo "::set-output name=stdout::${SCRIPT_OUTPUT//$'\n'/\\n}"
    

    此外,我最终需要返回脚本的退出代码,以正确指示它是否失败。整个shebang最终看起来像这样:

    - name: A run step with stdout as a captured output
      id: myscript
      run: |
        # run in subshell, capturiing stdout to var
        SCRIPT_OUTPUT=$(./do-something.sh)
        # capture exit code too
        SCRIPT_RC=$?
        # print a single line output for github
        echo "::set-output name=stdout::${SCRIPT_OUTPUT//$'\n'/\\n}"
        # exit with the script status
        exit $SCRIPT_RC
      continue-on-error: true
    - name: Add above outcome and output as an issue comment
      uses: actions/github-script@v5
      env:
        STEP_OUTPUT: ${{ steps.myscript.outputs.stdout }}
      with:
        github-token: ${{ secrets.GITHUB_TOKEN }}
        script: |
          // indicates whather script succeeded or not
          let comment = `Script finished with \`${{ steps.myscript.outcome }}\`\n`;
    
          // adds stdout, unescaping newlines again to make it readable
          comment += `<details><summary>Show Output</summary>
    
          \`\`\`
          ${process.env.STEP_OUTPUT.replace(/\\n/g, '\n')}
          \`\`\`
    
          </details>`;
    
          // add the whole damn thing as an issue comment
          github.rest.issues.createComment({
            issue_number: context.issue.number,
            owner: context.repo.owner,
            repo: context.repo.repo,
            body: comment
          })
    

    编辑:还有an action 可以用更少的引导来完成此任务,我只是发现了这一点。

    【讨论】:

    • 有趣的解决方法。赞成。
    【解决方案4】:

    就我而言,我想传递整个构建/工件,而不仅仅是一个字符串:

    name: Build something on Ubuntu then use it on MacOS
    
    on:
      workflow_dispatch:
        # Allows for manual build trigger
    
    jobs:
      buildUbuntuProject:
        name: Builds the project on Ubuntu (Put your stuff here)
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v2
          - uses: some/compile-action@v99
          - uses: actions/upload-artifact@v2
            # Upload the artifact so the MacOS runner do something with it
            with:
              name: CompiledProject
              path: pathToCompiledProject
      doSomethingOnMacOS:
        name: Runs the program on MacOS or something
        runs-on: macos-latest
        needs: buildUniyProject # Needed so the job waits for the Ubuntu job to finish
        steps:
          - uses: actions/download-artifact@master
            with:
              name: CompiledProject
              path: somewhereToPutItOnMacOSRunner
          - run: ls somewhereToPutItOnMacOSRunner # See the artifact on the MacOS runner
    

    【讨论】:

      猜你喜欢
      • 2021-05-10
      • 2022-08-11
      • 2023-02-10
      • 2021-07-23
      • 1970-01-01
      • 1970-01-01
      • 2021-12-28
      • 2017-07-29
      • 2021-10-21
      相关资源
      最近更新 更多