actions / download-artifact

MIT License
1.43k stars 486 forks source link

[feat req] Keep artifact in ZIP format instead of extracting #143

Open lifehackerhansol opened 2 years ago

lifehackerhansol commented 2 years ago

What would you like to be added?

An option to keep the artifact in ZIP format would be nice to have. Having it automatically extract is useful in cases, but having it in a ZIP file can be useful as well.

Why is this needed?

For my case, my release and build archive are identical. So when a new release is created, I upload to build archive, and then directly upload the same archive to release.

Thus, a way to copy-paste the Actions workflow artifact directly to release would be to download the artifacts generated in the first half of the workflow, and then just release it directly. However, in the current state of things I have to manually re-zip everything because it is extracted. It would be nice to be able to cut the middleman.

austinsasko commented 2 years ago

+1

Tokenyet commented 2 years ago

This is useful when you have an auto-release feature in the job, so I think It's a reasonable feature.

esso23 commented 2 years ago

Until this gets fixed, here's a workaround for those searching for a quick solution (inspiration from an example here https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run at the bottom).

This downloads all artifacts of the workflow currently being executed (there's an example with matching in the link above).

  - name: Download artifacts
      uses: actions/github-script@v6
      with:
        script: |
          let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
             owner: context.repo.owner,
             repo: context.repo.repo,
             run_id: context.payload.workflow_run.id,
          });
          for (const artifact of allArtifacts.data.artifacts)
          {
            let download = await github.rest.actions.downloadArtifact({
               owner: context.repo.owner,
               repo: context.repo.repo,
               artifact_id: artifact.id,
               archive_format: 'zip',
            });

             let fs = require('fs');
             fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
          }
mandar1jn commented 2 years ago

Until this gets fixed, here's a workaround for those searching for a quick solution (inspiration from an example here https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run at the bottom).

This downloads all artifacts of the workflow currently being executed (there's an example with matching in the link above).

  - name: Download artifacts
      uses: actions/github-script@v6
      with:
        script: |
          let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
             owner: context.repo.owner,
             repo: context.repo.repo,
             run_id: context.payload.workflow_run.id,
          });
          for (const artifact of allArtifacts.data.artifacts)
          {
            let download = await github.rest.actions.downloadArtifact({
               owner: context.repo.owner,
               repo: context.repo.repo,
               artifact_id: artifact.id,
               archive_format: 'zip',
            });

             let fs = require('fs');
             fs.writeFileSync(`${process.env.GITHUB_WORKSPACE}/${artifact.name}.zip`, Buffer.from(download.data));
          }

This does not seem to work. I have a job that requires the first job to be finished. The second job needs To download the artifact if the first job to publish. Sadly, the artifact only become available after the whole workflow finished. So, my second job never downloads any artifacts

pattwell commented 2 years ago

This would be an extremely useful feature. I am using upload-artifact and download-artifact to do some magic with compiled source code for Lambdas and want to upload the zips to s3. It is quite inefficient to have to re-zip them.

austinsasko commented 2 years ago

@pattwell what version of these actions are you using? In my testing this issue seems to have been implemented. By default a zipped artifact on upload stays zipped on download.

pattwell commented 2 years ago

@austinsasko Ah you're right, I was deep in some debugging and the issue ended up coming from elsewhere in the workflow. I forgot to circle back to this issue. My apologies!

mitchcapper commented 1 year ago

For downloading artifacts from the current run I do not think this is possible. Each artifact is stored in uncompressed form until the end of the entire run when it is zipped up. If you look at download-artifact it downloads and each file/folder in the artifact individually. This is also why @esso23's solution doesn't work. The PR mentioning this by @austinsasko only stops the in-transit optional gzip compression (but again per file).

Here is the official docs that also talk about it: https://github.com/actions/upload-artifact

esso23 commented 1 year ago

Sorry, forgot to mention you need to use 2 separate workflows to do this. The first workflow (Publish) creates the artifacts using actions/upload-artifact@v3, the second workflow (Release) is triggered on completion of Publish workflow:

on:
  workflow_run:
    workflows: [Publish]
    types:
      - completed

jobs: 
  create_release:
    uses: IPECON/workflows-common/.github/workflows/create_release.yml@main
    with:
      trigger_conclusion: ${{ github.event.workflow_run.conclusion }}
    secrets: inherit

You pass the triggering workflow as a parameter, and then you use that parameter to get the artifacts. Since the triggering workflow had already finished running at that point, the artifacts are already zipped and ready to be downloaded by the triggered workflow.

Here's the Release workflow we're using: https://github.com/IPECON/workflows-common/blob/main/.github/workflows/create_release.yml

derrod commented 10 months ago

As v4 now operates on zipped files in blob storage rather than individual files this seems like it would be a nice addition. In our case we aggregate the results of several workflow jobs (windows, linux, mac) to then upload a draft release.

rmunn commented 6 months ago

If https://github.com/actions/upload-artifact/issues/38 ever gets fixed, so that the .zip file finally contains Unix file permissions (such as executable bits), then that would give another reason to want this. Because as https://github.com/actions/download-artifact/issues/14#issuecomment-2084480465 mentions, it's hard to extract Unix file permissions from a .zip file that you're streaming, because they are in the data block at the very end of the zip file, the last thing the stream will receive. So even if https://github.com/actions/upload-artifact/issues/38 gets fixed, Because as https://github.com/actions/download-artifact/issues/14 may take much longer to fix. In the meantime, a workaround would be to download just the single .zip file and unzip it with the standard Linux unzip tool, and then the file permissions from earlier steps would be effectively carried through to later job steps.

So if #14 is too hard to fix, this request would go a long way towards enabling a workflow that many builds need. (Build part 1 in parallel, use upload-artifact and download-artifact to consolidate the output from the parallel builds, then part 2 packages those files into an installer).

FibreFoX commented 2 months ago

Ended up using https://github.com/dawidd6/action-download-artifact for this.