Repository: actions/toolkit
Pull request #1602 (2023-12-11 17:22:05)

[artifact] replace unzipper with unzip-stream
Unfortunately the `unzipper` library we first chose has some issues with node > 18:
- https://github.com/ZJONSSON/node-unzipper/issues/271
- https://github.com/ZJONSSON/node-unzipper/issues/286

So we're replacing with `unzip-stream`. In the future we may want to invest more changes into this, and keep track of a more maintained unzip library. Unfortunately there aren't a lot of great options that also stream the contents without writing the entire archive to disk:

- https://github.com/go-task/go-npm/issues/7#issuecomment-1568567117

Closes:
- https://github.com/github/actions-results-team/issues/2096

Example run:
- https://github.com/robherley/tmp-artifacts/actions/runs/7169128021


Patch:
diff --git a/packages/artifact/package-lock.json b/packages/artifact/package-lock.json
index 2696740..abe007b 100644
--- a/packages/artifact/package-lock.json
+++ b/packages/artifact/package-lock.json
@@ -18,15 +18,15 @@
         "@octokit/plugin-retry": "^3.0.9",
         "@octokit/request-error": "^5.0.0",
         "@protobuf-ts/plugin": "^2.2.3-alpha.1",
-        "@types/unzipper": "^0.10.6",
         "archiver": "^5.3.1",
         "crypto": "^1.0.1",
         "jwt-decode": "^3.1.2",
         "twirp-ts": "^2.5.0",
-        "unzipper": "^0.10.14"
+        "unzip-stream": "^0.3.1"
       },
       "devDependencies": {
         "@types/archiver": "^5.3.2",
+        "@types/unzip-stream": "^0.3.4",
         "typedoc": "^0.25.4",
         "typedoc-plugin-markdown": "^3.17.1",
         "typescript": "^5.2.2"
@@ -471,10 +471,11 @@
         "@types/node": "*"
       }
     },
-    "node_modules/@types/unzipper": {
-      "version": "0.10.6",
-      "resolved": "https://registry.npmjs.org/@types/unzipper/-/unzipper-0.10.6.tgz",
-      "integrity": "sha512-zcBj329AHgKLQyz209N/S9R0GZqXSkUQO4tJSYE3x02qg4JuDFpgKMj50r82Erk1natCWQDIvSccDddt7jPzjA==",
+    "node_modules/@types/unzip-stream": {
+      "version": "0.3.4",
+      "resolved": "https://registry.npmjs.org/@types/unzip-stream/-/unzip-stream-0.3.4.tgz",
+      "integrity": "sha512-ud0vtsNRF+joUCyvNMyo0j5DKX2Lh/im+xVgRzBEsfHhQYZ+i4fKTveova9XxLzt6Jl6G0e/0mM4aC0gqZYSnA==",
+      "dev": true,
       "dependencies": {
         "@types/node": "*"
       }
@@ -588,14 +589,6 @@
       "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
       "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ=="
     },
-    "node_modules/big-integer": {
-      "version": "1.6.51",
-      "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
-      "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==",
-      "engines": {
-        "node": ">=0.6"
-      }
-    },
     "node_modules/binary": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz",
@@ -618,11 +611,6 @@
         "readable-stream": "^3.4.0"
       }
     },
-    "node_modules/bluebird": {
-      "version": "3.4.7",
-      "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz",
-      "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA=="
-    },
     "node_modules/bottleneck": {
       "version": "2.19.5",
       "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz",
@@ -668,14 +656,6 @@
         "node": "*"
       }
     },
-    "node_modules/buffer-indexof-polyfill": {
-      "version": "1.0.2",
-      "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz",
-      "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==",
-      "engines": {
-        "node": ">=0.10"
-      }
-    },
     "node_modules/buffers": {
       "version": "0.1.1",
       "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz",
@@ -801,41 +781,6 @@
         "dot-object": "bin/dot-object"
       }
     },
-    "node_modules/duplexer2": {
-      "version": "0.1.4",
-      "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
-      "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
-      "dependencies": {
-        "readable-stream": "^2.0.2"
-      }
-    },
-    "node_modules/duplexer2/node_modules/readable-stream": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
-      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
-      "dependencies": {
-        "core-util-is": "~1.0.0",
-        "inherits": "~2.0.3",
-        "isarray": "~1.0.0",
-        "process-nextick-args": "~2.0.0",
-        "safe-buffer": "~5.1.1",
-        "string_decoder": "~1.1.1",
-        "util-deprecate": "~1.0.1"
-      }
-    },
-    "node_modules/duplexer2/node_modules/safe-buffer": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
-    },
-    "node_modules/duplexer2/node_modules/string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
-      "dependencies": {
-        "safe-buffer": "~5.1.0"
-      }
-    },
     "node_modules/end-of-stream": {
       "version": "1.4.4",
       "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
@@ -875,20 +820,6 @@
       "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
       "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
     },
-    "node_modules/fstream": {
-      "version": "1.0.12",
-      "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz",
-      "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==",
-      "dependencies": {
-        "graceful-fs": "^4.1.2",
-        "inherits": "~2.0.0",
-        "mkdirp": ">=0.5 0",
-        "rimraf": "2"
-      },
-      "engines": {
-        "node": ">=0.6"
-      }
-    },
     "node_modules/glob": {
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -1029,11 +960,6 @@
         "safe-buffer": "~5.1.0"
       }
     },
-    "node_modules/listenercount": {
-      "version": "1.0.1",
-      "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz",
-      "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ=="
-    },
     "node_modules/lodash": {
       "version": "4.17.21",
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
@@ -1278,17 +1204,6 @@
         "node": ">=10"
       }
     },
-    "node_modules/rimraf": {
-      "version": "2.7.1",
-      "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
-      "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
-      "dependencies": {
-        "glob": "^7.1.3"
-      },
-      "bin": {
-        "rimraf": "bin.js"
-      }
-    },
     "node_modules/safe-buffer": {
       "version": "5.2.1",
       "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
@@ -1313,11 +1228,6 @@
       "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
       "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
     },
-    "node_modules/setimmediate": {
-      "version": "1.0.5",
-      "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
-      "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA=="
-    },
     "node_modules/shiki": {
       "version": "0.14.5",
       "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz",
@@ -1513,48 +1423,13 @@
       "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz",
       "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w=="
     },
-    "node_modules/unzipper": {
-      "version": "0.10.14",
-      "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.14.tgz",
-      "integrity": "sha512-ti4wZj+0bQTiX2KmKWuwj7lhV+2n//uXEotUmGuQqrbVZSEGFMbI68+c6JCQ8aAmUWYvtHEz2A8K6wXvueR/6g==",
-      "dependencies": {
-        "big-integer": "^1.6.17",
-        "binary": "~0.3.0",
-        "bluebird": "~3.4.1",
-        "buffer-indexof-polyfill": "~1.0.0",
-        "duplexer2": "~0.1.4",
-        "fstream": "^1.0.12",
-        "graceful-fs": "^4.2.2",
-        "listenercount": "~1.0.1",
-        "readable-stream": "~2.3.6",
-        "setimmediate": "~1.0.4"
-      }
-    },
-    "node_modules/unzipper/node_modules/readable-stream": {
-      "version": "2.3.8",
-      "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
-      "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
-      "dependencies": {
-        "core-util-is": "~1.0.0",
-        "inherits": "~2.0.3",
-        "isarray": "~1.0.0",
-        "process-nextick-args": "~2.0.0",
-        "safe-buffer": "~5.1.1",
-        "string_decoder": "~1.1.1",
-        "util-deprecate": "~1.0.1"
-      }
-    },
-    "node_modules/unzipper/node_modules/safe-buffer": {
-      "version": "5.1.2",
-      "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
-      "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
-    },
-    "node_modules/unzipper/node_modules/string_decoder": {
-      "version": "1.1.1",
-      "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
-      "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+    "node_modules/unzip-stream": {
+      "version": "0.3.1",
+      "resolved": "https://registry.npmjs.org/unzip-stream/-/unzip-stream-0.3.1.tgz",
+      "integrity": "sha512-RzaGXLNt+CW+T41h1zl6pGz3EaeVhYlK+rdAap+7DxW5kqsqePO8kRtWPaCiVqdhZc86EctSPVYNix30YOMzmw==",
       "dependencies": {
-        "safe-buffer": "~5.1.0"
+        "binary": "^0.3.0",
+        "mkdirp": "^0.5.1"
       }
     },
     "node_modules/util-deprecate": {
diff --git a/packages/artifact/package.json b/packages/artifact/package.json
index 894e160..c4f826c 100644
--- a/packages/artifact/package.json
+++ b/packages/artifact/package.json
@@ -49,15 +49,15 @@
     "@octokit/plugin-retry": "^3.0.9",
     "@octokit/request-error": "^5.0.0",
     "@protobuf-ts/plugin": "^2.2.3-alpha.1",
-    "@types/unzipper": "^0.10.6",
     "archiver": "^5.3.1",
     "crypto": "^1.0.1",
     "jwt-decode": "^3.1.2",
     "twirp-ts": "^2.5.0",
-    "unzipper": "^0.10.14"
+    "unzip-stream": "^0.3.1"
   },
   "devDependencies": {
     "@types/archiver": "^5.3.2",
+    "@types/unzip-stream": "^0.3.4",
     "typedoc": "^0.25.4",
     "typedoc-plugin-markdown": "^3.17.1",
     "typescript": "^5.2.2"
diff --git a/packages/artifact/src/internal/download/download-artifact.ts b/packages/artifact/src/internal/download/download-artifact.ts
index 3bb3de6..a61e293 100644
--- a/packages/artifact/src/internal/download/download-artifact.ts
+++ b/packages/artifact/src/internal/download/download-artifact.ts
@@ -2,7 +2,7 @@ import fs from 'fs/promises'
 import * as github from '@actions/github'
 import * as core from '@actions/core'
 import * as httpClient from '@actions/http-client'
-import unzipper from 'unzipper'
+import unzip from 'unzip-stream'
 import {
   DownloadArtifactOptions,
   DownloadArtifactResponse
@@ -47,7 +47,12 @@ async function streamExtract(url: string, directory: string): Promise<void> {
     )
   }
 
-  return response.message.pipe(unzipper.Extract({path: directory})).promise()
+  return new Promise((resolve, reject) => {
+    response.message
+      .pipe(unzip.Extract({path: directory}))
+      .on('close', resolve)
+      .on('error', reject)
+  })
 }
 
 export async function downloadArtifactPublic(


Test patch:
diff --git a/packages/artifact/__tests__/download-artifact.test.ts b/packages/artifact/__tests__/download-artifact.test.ts
index 247a5e4..815a760 100644
--- a/packages/artifact/__tests__/download-artifact.test.ts
+++ b/packages/artifact/__tests__/download-artifact.test.ts
@@ -104,6 +104,7 @@ const mockGetArtifactSuccess = jest.fn(() => {
   const message = new http.IncomingMessage(new net.Socket())
   message.statusCode = 200
   message.push(fs.readFileSync(fixtures.exampleArtifact.path))
+  message.push(null)
   return {
     message
   }
@@ -113,6 +114,7 @@ const mockGetArtifactFailure = jest.fn(() => {
   const message = new http.IncomingMessage(new net.Socket())
   message.statusCode = 500
   message.push('Internal Server Error')
+  message.push(null)
   return {
     message
   }