Upload multi assets from different os to a release

I have a golang based project, I want to build binary on linux and MacOS, and create release on tags pushed, upload assets to this release.

But create_release will be called multi times in matrix, then failed. I also tried to use a seperate job for create_release, but don’t know how to access its output in another job.

   

on:
  push:
    tags:
      - 'v*'
jobs:
  release:
    name: create release
    stragety:
      matrix:
        os: ["ubuntu-latest", "macos-latest"]
     steps:
      - name: create_release
        id: create_release
        uses: actions/create-release@v1.0.0
....build on os ....
      - name: Upload Release Asset
        id: upload-release-asset
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.create_release.outputs.upload_url }}
          asset_path: ./bin/snet
          asset_name: snet
          asset_content_type: application/octet-stream
3 Likes

If you would like to share the data between different jobs, please use ‘actions/upload-artifact’ and ‘download-artifact’ actions. It’s mentioned here: Passing data between jobs in a workflow

Code sample as below:

createrelease:
    name: createrelease
    runs-on: [macOS-latest]
    steps:
      - name: Check out code
        uses: actions/checkout@v1
      - name: create release
        id: create_release
        uses: actions/create-release@v1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          tag_name: ${{ github.ref }}
          release_name: Release ${{ github.ref }}
          draft: false
          prerelease: false
      - name: Output Release URL File
        run: echo "${{ steps.create_release.outputs.upload_url }}" > release_url.txt
      - name: Save Release URL File for publish
        uses: actions/upload-artifact@v1
        with:
          name: release_url
          path: release_url.txt


  build_and_upload:
    needs: [createrelease]
    name: build and upload
    strategy:
      matrix:
        os: [ubuntu-latest, macOS-latest]
    runs-on : ${{ matrix.os }}
    env:
      KERNEL: $(uname | tr '[:upper:]' '[:lower:]')
    steps:
      - name: Check out code
        uses: actions/checkout@v1

      - name: Setup Go
        uses: actions/setup-go@v1
        with:
          go-version: "1.13"

      - name: Build
        run: make
      - name: Load Release URL File from release job
        uses: actions/download-artifact@v1
        with:
          name: release_url
      - name: Get Release File Name & Upload URL
        id: get_release_info
        run: |
          value=`cat release_url/release_url.txt`
          echo ::set-output name=upload_url::$value

      - name: Upload Release Asset
        id: upload-release-asset
        uses: actions/upload-release-asset@v1.0.1
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          upload_url: ${{ steps.get_release_info.outputs.upload_url }}
          asset_path: ./bin/snet
          asset_name: snet_${KERNEL}_amd64
          asset_content_type: application/octet-stream

You can refer to this link for more details, thanks.

This solution doesn’t work when there are multiple workflows, I believe, because I don’t think you can share artifacts between them.

I was facing the same issue and I ended up using a third party action than can handle this: https://github.com/softprops/action-gh-release.

How about this:

Workflow1

  • triggers on tags

  • main job

  - runs on OS1 only (doesn’t really matter which)

  - calls actions/create-release

  - saves upload_url

  - sends dispatch X to repo with upload_url as payload

Workflow2

  • triggers on dispatch X

  • main job

  - runs on OS1, OS2, …

  - builds and prepares everything

  - calls actions/upload-release-asset with upload_url taken from dispatch payload

How to send upload_url?

There are ready-to-use actions around which helps with that, let’s take this one as example

- uses: actions/create-release@v1
id: create_release
# ... #
- uses: peter-evans/repository-dispatch@v1
with:
token: ${{ secrets.REPO_ACCESS_TOKEN }}
repository: your-usename/your-repo
event-type: update-release
client-payload: '{"upload_url": "${{ steps.create_release.outputs.upload_url }}" }'

If you need to send more data (tag name or w/e), add more entries to client-payload, just remember about client-payload limitation which is not mentioned in API docs (read: neither me or action author could find anything about it).

Also note that all what’s action is doing under the hood is sending POST request - it could be replaced with curl one-liner, what might be important for repos with strict Actions policy or those which don’t really like external dependencies.

How to use repository_dispatch?

Event itself is documented here, so after RTFM Workflow2 starts like this

on:
 repository_dispatch:
  types: [update-release]

This will trigger Workflow2 only on event-type sent by Workflow1; any other random dispatches will be ignored.

How to read upload_url?

Workflow2, as it’s triggered by dispatch, have access to payload via github context. Knowing this, time to finally do something productive.

- uses: action/upload-release-asset@v1
with:
upload_url: ${{ github.event.client_payload.upload_url }}
# ... #

TADA.WAV


All above could be done in single workflow file, but i don’t want to pollute answer with crazy ifs which i’m overusing in own workflows :stuck_out_tongue: And to make it work without them, we’d need to be able to define multiple workflows in one yaml file first; gods knows when/if it gonna happen.

Using dispatch, other than making your dreams come true, have one smaller or bigger advantage - you can create (pre)release by hand, manually send dispatch with upload url, and then just sip tea until Workflow2 finish doing all boring uploading stuff for you (and if you’d add dispatch trigger to Workflow1 as well (with different name/type), you can test whole thing anytime without tagging).

Whole thing needs some tweaking obviously (which commit should be checked out, making sure upload_url is present in payload, and so on), but you get a picture.