Skip to content

Conversation

@danwkennedy
Copy link
Contributor

@danwkennedy danwkennedy commented Jan 26, 2026

Description

Being able to download un-zipped artifacts would be really useful. To support this in the future and to avoid some bugs we've seen before, we can check the content-type header to make sure the artifact is a zip before we attempt to unzip it. Right now, if the file isn't a zip (which can happen if someone extends/writes their own actions/upload-artifact), actions/download-artifact will fail in the extraction.

Changes:

  • Check whether downloaded file is a zip. We first check the content-type but also the URL file extension for backwards compatibility reasons:
    • Extract if it is (unchanged behavior)
    • Skip extraction if it isn't (new behavior)
  • Allow callers to pass a skipDecompress flag in case they want to override our new behavior

Example output from a custom actions/download-artifact build:

Non-zipped:

Downloading raw file (non-zip) to: /workspaces/actions/runner/_layout/_work/direct-upload/direct-upload/GitHub_Invertocat_Black.pdf
SHA256 digest of downloaded artifact is 9d30aac7deaf046f3e6ca4a46a6d03bcc347c595c64521dc103f4bad313aaf65
Artifact download completed successfully.
Total of 1 artifact(s) downloaded
Download artifact has finished successfully

Zipped:

SHA256 digest of downloaded artifact is 76ef7d397dc0352904bab221f72893dcc65a6db9e37cf64eeec244a57f4dcfff
Artifact download completed successfully.
Total of 1 artifact(s) downloaded
Download artifact has finished successfully

@danwkennedy danwkennedy requested review from a team as code owners January 26, 2026 19:05
Copilot AI review requested due to automatic review settings January 26, 2026 19:05
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR modifies the artifact download functionality to support downloading non-zip artifacts without attempting to extract them. The implementation checks the content-type header to determine whether to extract a file as a zip or save it directly as-is.

Changes:

  • Added content-type detection to distinguish between zip and non-zip artifacts based on HTTP headers
  • Implemented raw file saving for non-zip artifacts using filename extracted from Content-Disposition header
  • Refactored stream error handling to use shared callback functions
  • Added comprehensive test coverage for both zip and non-zip download scenarios
  • Included VS Code debug launch configuration

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 8 comments.

File Description
packages/artifact/src/internal/download/download-artifact.ts Core implementation: adds content-type checking, Content-Disposition parsing, and conditional logic to either extract zip files or save raw files
packages/artifact/tests/download-artifact.test.ts Test coverage: updates existing mocks with content-type headers and adds new test cases for various content types and scenarios
.vscode/launch.json IDE configuration: adds Jest debugging configurations (should be excluded from repository)
Comments suppressed due to low confidence (2)

packages/artifact/src/internal/download/download-artifact.ts:92

  • Content-Disposition parsing issue: The regex pattern for extracting filename from Content-Disposition has several issues. For RFC 2231 encoded filenames (filename*=UTF-8''encoded-name), the pattern (?:UTF-\d['"]*)? only matches "UTF-" followed by a single digit, which won't properly match "UTF-8". Additionally, the pattern doesn't correctly handle the RFC 2231 format which uses charset'lang'value syntax. Consider using a more robust parsing approach or a dedicated library for parsing Content-Disposition headers.
  const filenameMatch = contentDisposition.match(
    /filename\*?=['"]?(?:UTF-\d['"]*)?([^;\r\n"']*)['"]?/i
  )

packages/artifact/tests/download-artifact.test.ts:817

  • Consider adding a test case for Content-Type with additional parameters (e.g., "application/zip; charset=utf-8") to verify the behavior matches expectations. This would help catch the issue noted in the implementation where exact string matching is used instead of parsing the MIME type.
    })

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link

@zaataylor zaataylor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spotted a few things we should address before we consider shipping this.

I'd also really value a review from a more experienced member of the team in this area since this is the most meaningful set of behavioral changes in this repo I've ever reviewed 🙇

ericsciple
ericsciple previously approved these changes Jan 27, 2026
@crazy-max
Copy link

So I guess maintainers changed their mind related to #1874 (review)?

@danwkennedy danwkennedy force-pushed the danwkennedy/download-no-extract-non-zip branch from 18774b3 to 0f4cf89 Compare January 29, 2026 20:43
@danwkennedy
Copy link
Contributor Author

So I guess maintainers changed their mind related to #1874 (review)?

@crazy-max that's correct. However, we're being more intentional with that feature. You've already seen the changes to upload. We're also changing the backend to handle this more gracefully (right now, the backend assumes everything will be a zip no matter what).

@danwkennedy danwkennedy merged commit 975fcbd into main Jan 30, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants