actions / upload-release-asset

An Action to upload a release asset via the GitHub Release API
MIT License
688 stars 189 forks source link

support environment variables #17

Closed dh1tw closed 4 years ago

dh1tw commented 4 years ago

Hi, It would be nice if you could support variables in the required parameters like asset_path or asset_name. In this particular example I want to include the semVer tag in the asset name.


[non relevated details obmitted...]
    - name: Upload Release Artifact ${{ matrix.version }}
      uses: actions/upload-release-asset@v1.0.1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        VERSION: ${{ steps.get_version.outputs.VERSION }}
      with:
        upload_url: ${{ steps.get_release_url.outputs.URL }}
        asset_path: ./remoteAudio-$VERSION-${{ matrix.OS }}-${{ matrix.ARCH }}.zip
        asset_name: remoteAudio-$VERSION-${{ matrix.OS }}-${{ matrix.ARCH }}.zip
        asset_content_type: application/gzip

Unfortunately, executing this step results in the following error:

Run actions/upload-release-asset@v1.0.1
  with:
    upload_url: https://uploads.github.com/repos/dh1tw/remoteAudio/releases/21709660/assets{?name,label}
    asset_path: ./remoteAudio-$VERSION-linux-arm.zip
    asset_name: remoteAudio-$VERSION-linux-arm.zip
    asset_content_type: application/gzip
  env:
    GITHUB_TOKEN: ***
    VERSION: v0.4.2
##[error]ENOENT: no such file or directory, stat './remoteAudio-$VERSION-linux-arm.zip'
##[error]Node run failed with exit code 1

After having a look at the code, I presume that $VERSION is just read as a string and not interpreted as a shell environment variable.

Maybe a feasible solution would be to parse the parameters like asset_path for strings starting with a $ sign and then try to look them up in the environment variables.

Any thoughts?

dh1tw commented 4 years ago

This is my current workaround, but it feels dirty and filthy...


[non relevated details obmitted...]
    - name: Prepare artifact metadata
      id: prepare_artifact_metadata
      env:
        VERSION: ${{ steps.get_version.outputs.VERSION }}
      run: |
        echo ::set-output name=ARTIFACT_PATH::./remoteAudio-$VERSION-${{ matrix.OS }}-${{ matrix.ARCH }}.zip
        echo ::set-output name=ARTIFACT_NAME::remoteAudio-$VERSION-${{ matrix.OS }}-${{ matrix.ARCH }}.zip
    - name: Upload Release Artifact ${{ matrix.version }}
      uses: actions/upload-release-asset@v1.0.1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        upload_url: ${{ steps.get_release_url.outputs.URL }}
        asset_path: ${{ steps.prepare_artifact_metadata.outputs.ARTIFACT_PATH }}
        asset_name: ${{ steps.prepare_artifact_metadata.outputs.ARTIFACT_NAME }}
        asset_content_type: application/gzip

Basically I added a step that writes the asset's name and path into output variables of that step.

IAmHughes commented 4 years ago

Hey @dh1tw, there are some internal discussions around requests for supporting parameters in workflow files like this. It would be something that would need to be into the core of GitHub Actions, however, so its a bit out of the scope of an individual Action.

I believe we've recommended that workaround you're talking about, though we agree it isn't necessarily ideal.

dh1tw commented 4 years ago

Hey @IAmHughes, thanks for the swift reply! Working with variables and parameters is really a pain currently within and across jobs. It would be cool if the Github Actions team would relieve us from this pain in the future.

I still believe that parsing & looking up the environment variables could be done from within this action, but I would understand if you prefer to not add it until (hopefully) Github Actions comes up with a more universal approach.

Feel free to close the action.

IAmHughes commented 4 years ago

@dh1tw Totally understand that, I'll add the feedback to our internal issues! Thanks!

ethomson commented 4 years ago

This is my current workaround, but it feels dirty and filthy...

You could also just use the VERSION output from the prior step directly. This will save you having to run a shell just to set variables. eg:

[non relevated details obmitted...]
    - name: Upload Release Artifact ${{ matrix.version }}
      uses: actions/upload-release-asset@v1.0.1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        upload_url: ${{ steps.get_release_url.outputs.URL }}
        asset_path: ./remoteAudio-${{ steps.get_version.outputs.VERSION }}-${{ matrix.OS }}-${{ matrix.ARCH }}.zip
        asset_name: remoteAudio-${{ steps.get_version.outputs.VERSION }}-${{ matrix.OS }}-${{ matrix.ARCH }}.zip
        asset_content_type: application/gzip
kdefives commented 4 years ago

@dh1tw I am very interested to know how you defined this: ${{ steps.get_release_url.outputs.URL }}

As my release tag already exists when the github actions workflow is executed, i am stuck because i don't know how to get this url dynamically.

Could be very useful for me to know. Can you give me your code detail about that part?

Thanks in advance!

dh1tw commented 4 years ago

HI @kdefives,

I create a Github release in a job within my workflow. Since there is currently no way to share variables amongst jobs, I copy the release URL in a file and upload it as a workflow artifact.

Here is how I create the release and stash the release URL:

  create_release:
    runs-on: ubuntu-18.04
    needs: [build_linux, build_macos]
    if: startsWith(github.ref, 'refs/tags/v')
    steps:
    - name: Create Release
      id: create_release
      uses: actions/create-release@v1.0.0
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        tag_name: ${{ github.ref }}
        release_name: Release ${{ github.ref }}
        draft: true
        prerelease: false
    # since jobs can not share any variables we have to copy the URL of the created Github release
    # into a file and stash it as an artifact
    - name: Copy release URL into file
      run: |
        mkdir release
        printf "%s" "${{ steps.create_release.outputs.upload_url }}" > release/url.txt
    - name: Stash file containing the release URL as an artifact
      uses: actions/upload-artifact@v1
      with:
        name: release-url
        path: ./release

And then I upload all the build artifacts to the release URL with:

  # In this job we upload the release artifacts to the corresponding release
  upload:
    runs-on: ubuntu-18.04
    needs: create_release # release must be created before this job can start
    strategy:
      matrix:
        version: ['linux-armhf', 'linux-arm64', 'linux-i386', 'linux-amd64', 'darwin-amd64']
        # add the GO naming convention for OS ($GOOS) and architecture ($GOARCH)
        # instead of using Linux' naming convention (version items).
        include:
          - version: linux-armhf
            OS: linux
            ARCH: arm
          - version: linux-arm64
            OS: linux
            ARCH: arm64
          - version: linux-i386
            OS: linux
            ARCH: '386'
          - version: linux-amd64
            OS: linux
            ARCH: amd64
          - version: darwin-amd64
            OS: darwin
            ARCH: amd64
    steps:
    # Since Github actions (currently) doesn't provide a slugged version of the git tag we have to
    # create it by ourselves. It is then made available to other steps in this job as a step.outputs
    # variable
    - name: Get the version (git tag)
      id: get_version
      run: |
        echo ${GITHUB_REF/refs\/tags\//}
        echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
    - name: Retrieve stashed intermediary build artifact
      uses: actions/download-artifact@v1
      with:
        name: remoteAudio-${{ matrix.OS }}-${{ matrix.ARCH }}-${{ github.sha }}
    # rename the retrieved intermediary artifact and prepare zip file
    - name: Prepare release artifact
      env:
        VERSION: ${{ steps.get_version.outputs.VERSION }}
      run: |
        mv ./remoteAudio-${{ matrix.OS }}-${{ matrix.ARCH }}-${{ github.sha }}/remoteAudio .
        chmod +x ./remoteAudio
        zip -j remoteAudio-$VERSION-${{ matrix.OS }}-${{ matrix.ARCH }}.zip ./remoteAudio
    # Download the previously uploaded artifact which contains the release URL
    - name: Retrieve stashed release URL
      uses: actions/download-artifact@v1
      with:
        name: release-url
    # Write content of downloaded file (a string which contains the release URL) into a step.outputs variable
    - name: Read release URL
      id: get_release_url
      run: echo ::set-output name=URL::$(cat release-url/url.txt)
    # This step is only needed because the upload-release-asset currently doesn't support
    # environment variables. Therefore they must be written and referenced through step.outputs
    - name: Prepare artifact metadata
      id: prepare_artifact_metadata
      env:
        VERSION: ${{ steps.get_version.outputs.VERSION }}
      run: |
        echo ::set-output name=ARTIFACT_PATH::./remoteAudio-$VERSION-${{ matrix.OS }}-${{ matrix.ARCH }}.zip
        echo ::set-output name=ARTIFACT_NAME::remoteAudio-$VERSION-${{ matrix.OS }}-${{ matrix.ARCH }}.zip
    # Finally upload the artifact to the corresponding release
    - name: Upload Release Artifact ${{ matrix.version }}
      uses: actions/upload-release-asset@v1.0.1
      env:
        GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
      with:
        upload_url: ${{ steps.get_release_url.outputs.URL }}
        asset_path: ${{ steps.prepare_artifact_metadata.outputs.ARTIFACT_PATH }}
        asset_name: ${{ steps.prepare_artifact_metadata.outputs.ARTIFACT_NAME }}
        asset_content_type: application/gzip

You can find the complete workflow at github.com/dh1tw/remoteAudio.

I hope this helps!