curlgithub-actionsgithub-actions-artifacts

Being able to download a Github Actions artifact by copy-past the link URL to curl?


We are doing a proof of concept of looking into Github Actions for producing an artifact for a given commit for a legacy system, which we then need to process further in-house so I am looking into how we can do that relatively simply for now to demonstrate that this can work. We are fine with the zip wrapping.

Sample URL for such an artifact as identified by right-clicking on the Artifact in the job page in Actions: https://github.com/tandeday/actions-artifacts/suites/1767549169/artifacts/33720037

I understand that there is a full API for this, and I have successfully used this by hand to localize and download the artifact using a line similar to:

curl -O -J -L -H 'Authorization: token ...'  -H "Accept: application/vnd.github.v3+json" https://api.github.com/repos/tandeday/actions-artifacts/actions/artifacts/33720037/zip

I would like to be able to avoid creating an API client for this proof-of-concept, but instead allow the user to just pass in the link from the web page, but I have been unable to locate a simple way to do so.

So question is, how do I with a minimum of coding come from https://github.com/tandeday/actions-artifacts/suites/1767549169/artifacts/33720037 to https://api.github.com/repos/tandeday/actions-artifacts/actions/artifacts/33720037/zip ?


Solution

  • If you're ok with open-sourcing your repo (scroll further down in this answer if not), you can do this without needing to authenticate if you make a workflow that creates a release upon each commit, then builds your artifact, then uploads that artifact to the release. The trick is to be clever with your release tag's name, which is used in the release URL. A sample workflow is described here. I've modified this slightly to match your sample repo's scenario, and I instead use the first 8 characters of the commit hash in the tag name to generate a predictable but unique URL:

    on:
      push:
        # Runs on every pushed commit
    
    name: Upload Release Asset
    
    jobs:
      build:
        name: Upload Release Asset
        runs-on: ubuntu-latest
        steps:
          - name: Checkout code
            uses: actions/checkout@v2
    
            # For the sake of simplicity, we'll name the tag and the release with
            # the first 8 chars of the commit SHA:
          - name: Get short SHA
            id: short_sha
            run: echo "::set-output name=sha8::$(echo ${GITHUB_SHA} | cut -c1-8)"
    
          - name: Build project # This would actually build your project, using zip for your example date artifact
            run:  |
              date > date.txt
              zip -rT app.zip date.txt
          - name: Create Release
            id: create_release
            uses: actions/create-release@v1
            env:
              GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
            with:
              # Using short SHA from 2nd step for tag and release name.
              tag_name: ${{steps.short_sha.outputs.sha8}}
              release_name: ${{steps.short_sha.outputs.sha8}}
              draft: false
              prerelease: false
            # Now we upload the artifact we generated in the first step to
            # the release we created in the 3nd step
          - name: Upload Release Asset
            id: upload-release-asset 
            uses: actions/upload-release-asset@v1
            env:
              GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
            with:
              upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing its ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps 
              asset_path: ./app.zip
              asset_name: app.zip
              asset_content_type: application/zip
    

    Then, finally, your asset will be available at a URL with the pattern: github.com/orgname/reponame/releases/download/${short_sha}/app.zip, where short_sha is the first 8 characters of your commit. Since it has this known format, it's easy to generate the URL on the in-house user's side if they have access to the repository (pull from repo, get SHA at head, do some string interpolation, print URL to console).

    Test repo workflow

    Test release asset

    In case your repo must stay private within your org:

    Someone wrote up a nice Gist with some shell scripts to grab a release from a private repo - you'll need an access token.

    If you don't want to pollute the releases of your repo:

    You could modify the above workflow's tag_name and release_name to include an intermediate prefix so it's clear that it's not an actual release. Your URL format will be different if you take this route, though - the bit after /download/ will be your new tag name.