diff --git a/.licenses/npm/minimatch.dep.yml b/.licenses/npm/minimatch.dep.yml
new file mode 100644
index 0000000..5709755
Binary files /dev/null and b/.licenses/npm/minimatch.dep.yml differ
diff --git a/__tests__/merge.test.ts b/__tests__/merge.test.ts
new file mode 100644
index 0000000..e4deba2
--- /dev/null
+++ b/__tests__/merge.test.ts
@@ -0,0 +1,175 @@
+import * as core from '@actions/core'
+import artifact from '@actions/artifact'
+import {run} from '../src/merge/merge-artifacts'
+import {Inputs} from '../src/merge/constants'
+import * as search from '../src/shared/search'
+
+const fixtures = {
+  artifactName: 'my-merged-artifact',
+  tmpDirectory: '/tmp/merge-artifact',
+  filesToUpload: [
+    '/some/artifact/path/file-a.txt',
+    '/some/artifact/path/file-b.txt',
+    '/some/artifact/path/file-c.txt'
+  ],
+  artifacts: [
+    {
+      name: 'my-artifact-a',
+      id: 1,
+      size: 100,
+      createdAt: new Date('2024-01-01T00:00:00Z')
+    },
+    {
+      name: 'my-artifact-b',
+      id: 2,
+      size: 100,
+      createdAt: new Date('2024-01-01T00:00:00Z')
+    },
+    {
+      name: 'my-artifact-c',
+      id: 3,
+      size: 100,
+      createdAt: new Date('2024-01-01T00:00:00Z')
+    }
+  ]
+}
+
+jest.mock('@actions/github', () => ({
+  context: {
+    repo: {
+      owner: 'actions',
+      repo: 'toolkit'
+    },
+    runId: 123,
+    serverUrl: 'https://github.com'
+  }
+}))
+
+jest.mock('@actions/core')
+
+jest.mock('fs/promises', () => ({
+  mkdtemp: jest.fn().mockResolvedValue('/tmp/merge-artifact'),
+  rm: jest.fn().mockResolvedValue(undefined)
+}))
+
+/* eslint-disable no-unused-vars */
+const mockInputs = (overrides?: Partial<{[K in Inputs]?: any}>) => {
+  const inputs = {
+    [Inputs.Name]: 'my-merged-artifact',
+    [Inputs.Pattern]: '*',
+    [Inputs.SeparateDirectories]: false,
+    [Inputs.RetentionDays]: 0,
+    [Inputs.CompressionLevel]: 6,
+    [Inputs.DeleteMerged]: false,
+    ...overrides
+  }
+
+  ;(core.getInput as jest.Mock).mockImplementation((name: string) => {
+    return inputs[name]
+  })
+  ;(core.getBooleanInput as jest.Mock).mockImplementation((name: string) => {
+    return inputs[name]
+  })
+
+  return inputs
+}
+
+describe('merge', () => {
+  beforeEach(async () => {
+    mockInputs()
+
+    jest
+      .spyOn(artifact, 'listArtifacts')
+      .mockResolvedValue({artifacts: fixtures.artifacts})
+
+    jest.spyOn(artifact, 'downloadArtifact').mockResolvedValue({
+      downloadPath: fixtures.tmpDirectory
+    })
+
+    jest.spyOn(search, 'findFilesToUpload').mockResolvedValue({
+      filesToUpload: fixtures.filesToUpload,
+      rootDirectory: fixtures.tmpDirectory
+    })
+
+    jest.spyOn(artifact, 'uploadArtifact').mockResolvedValue({
+      size: 123,
+      id: 1337
+    })
+
+    jest
+      .spyOn(artifact, 'deleteArtifact')
+      .mockImplementation(async artifactName => {
+        const artifact = fixtures.artifacts.find(a => a.name === artifactName)
+        if (!artifact) throw new Error(`Artifact ${artifactName} not found`)
+        return {id: artifact.id}
+      })
+  })
+
+  it('merges artifacts', async () => {
+    await run()
+
+    for (const a of fixtures.artifacts) {
+      expect(artifact.downloadArtifact).toHaveBeenCalledWith(a.id, {
+        path: fixtures.tmpDirectory
+      })
+    }
+
+    expect(artifact.uploadArtifact).toHaveBeenCalledWith(
+      fixtures.artifactName,
+      fixtures.filesToUpload,
+      fixtures.tmpDirectory,
+      {compressionLevel: 6}
+    )
+  })
+
+  it('fails if no artifacts found', async () => {
+    mockInputs({[Inputs.Pattern]: 'this-does-not-match'})
+
+    expect(run()).rejects.toThrow()
+
+    expect(artifact.uploadArtifact).not.toBeCalled()
+    expect(artifact.downloadArtifact).not.toBeCalled()
+  })
+
+  it('supports custom compression level', async () => {
+    mockInputs({
+      [Inputs.CompressionLevel]: 2
+    })
+
+    await run()
+
+    expect(artifact.uploadArtifact).toHaveBeenCalledWith(
+      fixtures.artifactName,
+      fixtures.filesToUpload,
+      fixtures.tmpDirectory,
+      {compressionLevel: 2}
+    )
+  })
+
+  it('supports custom retention days', async () => {
+    mockInputs({
+      [Inputs.RetentionDays]: 7
+    })
+
+    await run()
+
+    expect(artifact.uploadArtifact).toHaveBeenCalledWith(
+      fixtures.artifactName,
+      fixtures.filesToUpload,
+      fixtures.tmpDirectory,
+      {retentionDays: 7, compressionLevel: 6}
+    )
+  })
+
+  it('supports deleting artifacts after merge', async () => {
+    mockInputs({
+      [Inputs.DeleteMerged]: true
+    })
+
+    await run()
+
+    for (const a of fixtures.artifacts) {
+      expect(artifact.deleteArtifact).toHaveBeenCalledWith(a.name)
+    }
+  })
+})
diff --git a/merge/README.md b/merge/README.md
new file mode 100644
index 0000000..ff75372
--- /dev/null
+++ b/merge/README.md
@@ -0,0 +1,63 @@
+# `@actions/upload-artifact/merge`
+
+Merge multiple [Actions Artifacts](https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts) in Workflow Runs. Internally powered by [@actions/artifact](https://github.com/actions/toolkit/tree/main/packages/artifact) package.
+
+- [`@actions/upload-artifact/merge`](#actionsupload-artifactmerge)
+  - [Usage](#usage)
+    - [Inputs](#inputs)
+    - [Outputs](#outputs)
+  - [Examples](#examples)
+
+## Usage
+
+> [!IMPORTANT]
+> upload-artifact/merge@v4+ is not currently supported on GHES.
+
+Note: this actions can only merge artifacts created with actions/upload-artifact@v4+
+
+### Inputs
+
+```yaml
+- uses: actions/upload-artifact/merge@v4
+  with:
+    # The name of the artifact that the artifacts will be merged into
+    # Optional. Default is 'merged-artifacts'
+    name:
+
+    # A glob pattern matching the artifacts that should be merged.
+    # Optional. Default is '*'
+    pattern:
+
+    # If true, the artifacts will be merged into separate directories.
+    # If false, the artifacts will be merged into the root of the destination.
+    # Optional. Default is 'false'
+    separate-directories:
+
+    # If true, the artifacts that were merged will be deleted.
+    # If false, the artifacts will still exist.
+    # Optional. Default is 'false'
+    delete-merged:
+
+    # Duration after which artifact will expire in days. 0 means using default retention.
+    # Minimum 1 day.
+    # Maximum 90 days unless changed from the repository settings page.
+    # Optional. Defaults to repository settings.
+    retention-days:
+
+    # The level of compression for Zlib to be applied to the artifact archive.
+    # The value can range from 0 to 9.
+    # For large files that are not easily compressed, a value of 0 is recommended for significantly faster uploads.
+    # Optional. Default is '6'
+    compression-level:
+```
+
+### Outputs
+
+| Name | Description | Example |
+| - | - | - |
+| `artifact-id` | GitHub ID of an Artifact, can be used by the REST API | `1234` |
+| `artifact-url` | URL to download an Artifact. Can be used in many scenarios such as linking to artifacts in issues or pull requests. Users must be logged-in in order for this URL to work. This URL is valid as long as the artifact has not expired or the artifact, run or repository have not been deleted | `https://github.com/example-org/example-repo/actions/runs/1/artifacts/1234` |
+
+## Examples
+
+TODO(robherley): add examples
diff --git a/merge/action.yml b/merge/action.yml
new file mode 100644
index 0000000..8d85864
--- /dev/null
+++ b/merge/action.yml
@@ -0,0 +1,57 @@
+name: 'Merge Build Artifacts'
+description: 'Merge one or more build Artifacts'
+author: 'GitHub'
+inputs:
+  name:
+    description: 'The name of the artifact that the artifacts will be merged into.'
+    required: true
+    default: 'merged-artifacts'
+  pattern:
+    description: 'A glob pattern matching the artifact names that should be merged.'
+    default: '*'
+  separate-directories:
+    description: 'When multiple artifacts are matched, this changes the behavior of how they are merged in the archive.
+      If true, the matched artifacts will be extracted into individual named directories within the specified path.
+      If false, the matched artifacts will combined in the same directory.'
+    default: 'false'
+  retention-days:
+    description: >
+      Duration after which artifact will expire in days. 0 means using default retention.
+
+      Minimum 1 day.
+      Maximum 90 days unless changed from the repository settings page.
+  compression-level:
+    description: >
+      The level of compression for Zlib to be applied to the artifact archive.
+      The value can range from 0 to 9:
+      - 0: No compression
+      - 1: Best speed
+      - 6: Default compression (same as GNU Gzip)
+      - 9: Best compression
+      Higher levels will result in better compression, but will take longer to complete.
+      For large files that are not easily compressed, a value of 0 is recommended for significantly faster uploads.
+    default: '6'
+  delete-merged:
+    description: >
+      If true, the artifacts that were merged will be deleted.
+      If false, the artifacts will still exist.
+    default: 'false'
+
+outputs:
+  artifact-id:
+    description: >
+      A unique identifier for the artifact that was just uploaded. Empty if the artifact upload failed.
+
+      This ID can be used as input to other APIs to download, delete or get more information about an artifact: https://docs.github.com/en/rest/actions/artifacts
+  artifact-url:
+    description: >
+      A download URL for the artifact that was just uploaded. Empty if the artifact upload failed.
+
+      This download URL only works for requests Authenticated with GitHub. Anonymous downloads will be prompted to first login. 
+      If an anonymous download URL is needed than a short time restricted URL can be generated using the download artifact API: https://docs.github.com/en/rest/actions/artifacts#download-an-artifact    
+
+      This URL will be valid for as long as the artifact exists and the workflow run and repository exists. Once an artifact has expired this URL will no longer work.
+      Common uses cases for such a download URL can be adding download links to artifacts in descriptions or comments on pull requests or issues.
+runs:
+  using: 'node20'
+  main: '../dist/merge/index.js'
diff --git a/package-lock.json b/package-lock.json
index 3efeb2c..1555e91 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,19 +1,20 @@
 {
   "name": "upload-artifact",
-  "version": "4.0.0",
+  "version": "4.3.0",
   "lockfileVersion": 2,
   "requires": true,
   "packages": {
     "": {
       "name": "upload-artifact",
-      "version": "4.0.0",
+      "version": "4.3.0",
       "license": "MIT",
       "dependencies": {
         "@actions/artifact": "^2.1.0",
         "@actions/core": "^1.10.0",
         "@actions/github": "^6.0.0",
         "@actions/glob": "^0.3.0",
-        "@actions/io": "^1.1.2"
+        "@actions/io": "^1.1.2",
+        "minimatch": "^9.0.3"
       },
       "devDependencies": {
         "@types/jest": "^29.2.5",
@@ -198,6 +199,26 @@
         "minimatch": "^3.0.4"
       }
     },
+    "node_modules/@actions/glob/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/@actions/glob/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/@actions/http-client": {
       "version": "2.2.0",
       "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.0.tgz",
@@ -1068,6 +1089,28 @@
         "url": "https://opencollective.com/eslint"
       }
     },
+    "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/@eslint/eslintrc/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/@fastify/busboy": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.0.tgz",
@@ -1096,6 +1139,28 @@
         "node": ">=10.10.0"
       }
     },
+    "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/@humanwhocodes/config-array/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/@humanwhocodes/module-importer": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
@@ -1402,6 +1467,16 @@
         }
       }
     },
+    "node_modules/@jest/reporters/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/@jest/reporters/node_modules/glob": {
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -1422,6 +1497,18 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/@jest/reporters/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/@jest/schemas": {
       "version": "29.0.0",
       "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.0.0.tgz",
@@ -2367,6 +2454,15 @@
         "node": ">= 6"
       }
     },
+    "node_modules/archiver-utils/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/archiver-utils/node_modules/glob": {
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -2386,6 +2482,17 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/archiver-utils/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/archiver-utils/node_modules/readable-stream": {
       "version": "2.3.8",
       "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
@@ -2669,12 +2776,11 @@
       "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
     },
     "node_modules/brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
       "dependencies": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
+        "balanced-match": "^1.0.0"
       }
     },
     "node_modules/braces": {
@@ -2971,7 +3077,7 @@
     "node_modules/concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
     },
     "node_modules/concurrently": {
       "version": "7.6.0",
@@ -3214,6 +3320,15 @@
         "dot-object": "bin/dot-object"
       }
     },
+    "node_modules/dot-object/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/dot-object/node_modules/glob": {
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -3233,6 +3348,17 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/dot-object/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/electron-to-chromium": {
       "version": "1.4.284",
       "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz",
@@ -3591,6 +3717,16 @@
         "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8"
       }
     },
+    "node_modules/eslint-plugin-import/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/eslint-plugin-import/node_modules/debug": {
       "version": "2.6.9",
       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -3612,6 +3748,18 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/eslint-plugin-import/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/eslint-plugin-import/node_modules/ms": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -3669,6 +3817,28 @@
         "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8"
       }
     },
+    "node_modules/eslint-plugin-jsx-a11y/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/eslint-plugin-jsx-a11y/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/eslint-plugin-jsx-a11y/node_modules/semver": {
       "version": "6.3.1",
       "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@@ -3763,6 +3933,16 @@
         "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
       }
     },
+    "node_modules/eslint/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/eslint/node_modules/escape-string-regexp": {
       "version": "4.0.0",
       "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -3785,6 +3965,18 @@
         "type-check": "~0.4.0"
       }
     },
+    "node_modules/eslint/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/eslint/node_modules/optionator": {
       "version": "0.9.1",
       "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@@ -4247,15 +4439,6 @@
         "node": ">=10.13.0"
       }
     },
-    "node_modules/glob/node_modules/brace-expansion": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
-      "dev": true,
-      "dependencies": {
-        "balanced-match": "^1.0.0"
-      }
-    },
     "node_modules/glob/node_modules/minimatch": {
       "version": "5.1.2",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz",
@@ -5035,6 +5218,16 @@
         }
       }
     },
+    "node_modules/jest-config/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/jest-config/node_modules/glob": {
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -5055,6 +5248,18 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/jest-config/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/jest-diff": {
       "version": "29.3.1",
       "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.3.1.tgz",
@@ -5335,6 +5540,16 @@
         "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
       }
     },
+    "node_modules/jest-runtime/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/jest-runtime/node_modules/glob": {
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -5355,6 +5570,18 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/jest-runtime/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/jest-snapshot": {
       "version": "29.3.1",
       "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.3.1.tgz",
@@ -5844,14 +6071,17 @@
       }
     },
     "node_modules/minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "version": "9.0.3",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+      "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
       "dependencies": {
-        "brace-expansion": "^1.1.7"
+        "brace-expansion": "^2.0.1"
       },
       "engines": {
-        "node": "*"
+        "node": ">=16 || 14 >=14.17"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
       }
     },
     "node_modules/minimist": {
@@ -6370,14 +6600,6 @@
         "minimatch": "^5.1.0"
       }
     },
-    "node_modules/readdir-glob/node_modules/brace-expansion": {
-      "version": "2.0.1",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
-      "dependencies": {
-        "balanced-match": "^1.0.0"
-      }
-    },
     "node_modules/readdir-glob/node_modules/minimatch": {
       "version": "5.1.6",
       "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
@@ -6511,6 +6733,16 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/rimraf/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/rimraf/node_modules/glob": {
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -6531,6 +6763,18 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/rimraf/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/run-parallel": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
@@ -6894,6 +7138,16 @@
         "node": ">=8"
       }
     },
+    "node_modules/test-exclude/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/test-exclude/node_modules/glob": {
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -6914,6 +7168,18 @@
         "url": "https://github.com/sponsors/isaacs"
       }
     },
+    "node_modules/test-exclude/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
     "node_modules/text-table": {
       "version": "0.2.0",
       "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
@@ -7496,6 +7762,15 @@
         "node": ">= 10"
       }
     },
+    "node_modules/zip-stream/node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
     "node_modules/zip-stream/node_modules/glob": {
       "version": "7.2.3",
       "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -7514,6 +7789,17 @@
       "funding": {
         "url": "https://github.com/sponsors/isaacs"
       }
+    },
+    "node_modules/zip-stream/node_modules/minimatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
     }
   },
   "dependencies": {
@@ -7658,6 +7944,25 @@
       "requires": {
         "@actions/core": "^1.2.6",
         "minimatch": "^3.0.4"
+      },
+      "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        }
       }
     },
     "@actions/http-client": {
@@ -8335,6 +8640,27 @@
         "js-yaml": "^4.1.0",
         "minimatch": "^3.1.2",
         "strip-json-comments": "^3.1.1"
+      },
+      "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        }
       }
     },
     "@fastify/busboy": {
@@ -8357,6 +8683,27 @@
         "@humanwhocodes/object-schema": "^1.2.1",
         "debug": "^4.1.1",
         "minimatch": "^3.0.5"
+      },
+      "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        }
       }
     },
     "@humanwhocodes/module-importer": {
@@ -8593,6 +8940,16 @@
         "v8-to-istanbul": "^9.0.1"
       },
       "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
         "glob": {
           "version": "7.2.3",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -8606,6 +8963,15 @@
             "once": "^1.3.0",
             "path-is-absolute": "^1.0.0"
           }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
         }
       }
     },
@@ -9363,6 +9729,15 @@
         "readable-stream": "^2.0.0"
       },
       "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
         "glob": {
           "version": "7.2.3",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -9376,6 +9751,14 @@
             "path-is-absolute": "^1.0.0"
           }
         },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
         "readable-stream": {
           "version": "2.3.8",
           "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
@@ -9596,12 +9979,11 @@
       "integrity": "sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw=="
     },
     "brace-expansion": {
-      "version": "1.1.11",
-      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
-      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+      "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
       "requires": {
-        "balanced-match": "^1.0.0",
-        "concat-map": "0.0.1"
+        "balanced-match": "^1.0.0"
       }
     },
     "braces": {
@@ -9806,7 +10188,7 @@
     "concat-map": {
       "version": "0.0.1",
       "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
-      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+      "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
     },
     "concurrently": {
       "version": "7.6.0",
@@ -9981,6 +10363,15 @@
         "glob": "^7.1.5"
       },
       "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
         "glob": {
           "version": "7.2.3",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -9993,6 +10384,14 @@
             "once": "^1.3.0",
             "path-is-absolute": "^1.0.0"
           }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
         }
       }
     },
@@ -10161,6 +10560,16 @@
         "text-table": "^0.2.0"
       },
       "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
         "escape-string-regexp": {
           "version": "4.0.0",
           "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
@@ -10177,6 +10586,15 @@
             "type-check": "~0.4.0"
           }
         },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
         "optionator": {
           "version": "0.9.1",
           "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.1.tgz",
@@ -10339,6 +10757,16 @@
         "tsconfig-paths": "^3.14.1"
       },
       "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
         "debug": {
           "version": "2.6.9",
           "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -10357,6 +10785,15 @@
             "esutils": "^2.0.2"
           }
         },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
         "ms": {
           "version": "2.0.0",
           "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@@ -10395,6 +10832,25 @@
         "semver": "^6.3.0"
       },
       "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
+        },
         "semver": {
           "version": "6.3.1",
           "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
@@ -10773,15 +11229,6 @@
         "once": "^1.3.0"
       },
       "dependencies": {
-        "brace-expansion": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-          "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
-          "dev": true,
-          "requires": {
-            "balanced-match": "^1.0.0"
-          }
-        },
         "minimatch": {
           "version": "5.1.2",
           "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.2.tgz",
@@ -11331,6 +11778,16 @@
         "strip-json-comments": "^3.1.1"
       },
       "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
         "glob": {
           "version": "7.2.3",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -11344,6 +11801,15 @@
             "once": "^1.3.0",
             "path-is-absolute": "^1.0.0"
           }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
         }
       }
     },
@@ -11570,6 +12036,16 @@
         "strip-bom": "^4.0.0"
       },
       "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
         "glob": {
           "version": "7.2.3",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -11583,6 +12059,15 @@
             "once": "^1.3.0",
             "path-is-absolute": "^1.0.0"
           }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
         }
       }
     },
@@ -11995,11 +12480,11 @@
       "dev": true
     },
     "minimatch": {
-      "version": "3.1.2",
-      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
-      "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+      "version": "9.0.3",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
+      "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
       "requires": {
-        "brace-expansion": "^1.1.7"
+        "brace-expansion": "^2.0.1"
       }
     },
     "minimist": {
@@ -12371,14 +12856,6 @@
         "minimatch": "^5.1.0"
       },
       "dependencies": {
-        "brace-expansion": {
-          "version": "2.0.1",
-          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
-          "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
-          "requires": {
-            "balanced-match": "^1.0.0"
-          }
-        },
         "minimatch": {
           "version": "5.1.6",
           "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
@@ -12473,6 +12950,16 @@
         "glob": "^7.1.3"
       },
       "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
         "glob": {
           "version": "7.2.3",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -12486,6 +12973,15 @@
             "once": "^1.3.0",
             "path-is-absolute": "^1.0.0"
           }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
         }
       }
     },
@@ -12762,6 +13258,16 @@
         "minimatch": "^3.0.4"
       },
       "dependencies": {
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "dev": true,
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
         "glob": {
           "version": "7.2.3",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -12775,6 +13281,15 @@
             "once": "^1.3.0",
             "path-is-absolute": "^1.0.0"
           }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "dev": true,
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
         }
       }
     },
@@ -13202,6 +13717,15 @@
             "readable-stream": "^3.6.0"
           }
         },
+        "brace-expansion": {
+          "version": "1.1.11",
+          "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+          "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+          "requires": {
+            "balanced-match": "^1.0.0",
+            "concat-map": "0.0.1"
+          }
+        },
         "glob": {
           "version": "7.2.3",
           "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
@@ -13214,6 +13738,14 @@
             "once": "^1.3.0",
             "path-is-absolute": "^1.0.0"
           }
+        },
+        "minimatch": {
+          "version": "3.1.2",
+          "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+          "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+          "requires": {
+            "brace-expansion": "^1.1.7"
+          }
         }
       }
     }
diff --git a/package.json b/package.json
index 40c9c39..e69ced7 100644
--- a/package.json
+++ b/package.json
@@ -1,11 +1,11 @@
 {
   "name": "upload-artifact",
-  "version": "4.2.0",
+  "version": "4.3.0",
   "description": "Upload an Actions Artifact in a workflow run",
   "main": "dist/upload/index.js",
   "scripts": {
     "build": "tsc",
-    "release": "ncc build src/upload/index.ts -o dist/upload",
+    "release": "ncc build src/upload/index.ts -o dist/upload && ncc build src/merge/index.ts -o dist/merge",
     "check-all": "concurrently \"npm:format-check\" \"npm:lint\" \"npm:test\" \"npm:build\"",
     "format": "prettier --write **/*.ts",
     "format-check": "prettier --check **/*.ts",
@@ -33,7 +33,8 @@
     "@actions/core": "^1.10.0",
     "@actions/github": "^6.0.0",
     "@actions/glob": "^0.3.0",
-    "@actions/io": "^1.1.2"
+    "@actions/io": "^1.1.2",
+    "minimatch": "^9.0.3"
   },
   "devDependencies": {
     "@types/jest": "^29.2.5",
diff --git a/src/merge/constants.ts b/src/merge/constants.ts
new file mode 100644
index 0000000..8bc9539
--- /dev/null
+++ b/src/merge/constants.ts
@@ -0,0 +1,9 @@
+/* eslint-disable no-unused-vars */
+export enum Inputs {
+  Name = 'name',
+  Pattern = 'pattern',
+  SeparateDirectories = 'separate-directories',
+  RetentionDays = 'retention-days',
+  CompressionLevel = 'compression-level',
+  DeleteMerged = 'delete-merged'
+}
diff --git a/src/merge/index.ts b/src/merge/index.ts
new file mode 100644
index 0000000..52150a1
--- /dev/null
+++ b/src/merge/index.ts
@@ -0,0 +1,6 @@
+import * as core from '@actions/core'
+import {run} from './merge-artifacts'
+
+run().catch(error => {
+  core.setFailed((error as Error).message)
+})
diff --git a/src/merge/input-helper.ts b/src/merge/input-helper.ts
new file mode 100644
index 0000000..de53a2f
--- /dev/null
+++ b/src/merge/input-helper.ts
@@ -0,0 +1,44 @@
+import * as core from '@actions/core'
+import {Inputs} from './constants'
+import {MergeInputs} from './merge-inputs'
+
+/**
+ * Helper to get all the inputs for the action
+ */
+export function getInputs(): MergeInputs {
+  const name = core.getInput(Inputs.Name, {required: true})
+  const pattern = core.getInput(Inputs.Pattern, {required: true})
+  const separateDirectories = core.getBooleanInput(Inputs.SeparateDirectories)
+  const deleteMerged = core.getBooleanInput(Inputs.DeleteMerged)
+
+  const inputs = {
+    name,
+    pattern,
+    separateDirectories,
+    deleteMerged,
+    retentionDays: 0,
+    compressionLevel: 6
+  } as MergeInputs
+
+  const retentionDaysStr = core.getInput(Inputs.RetentionDays)
+  if (retentionDaysStr) {
+    inputs.retentionDays = parseInt(retentionDaysStr)
+    if (isNaN(inputs.retentionDays)) {
+      core.setFailed('Invalid retention-days')
+    }
+  }
+
+  const compressionLevelStr = core.getInput(Inputs.CompressionLevel)
+  if (compressionLevelStr) {
+    inputs.compressionLevel = parseInt(compressionLevelStr)
+    if (isNaN(inputs.compressionLevel)) {
+      core.setFailed('Invalid compression-level')
+    }
+
+    if (inputs.compressionLevel < 0 || inputs.compressionLevel > 9) {
+      core.setFailed('Invalid compression-level. Valid values are 0-9')
+    }
+  }
+
+  return inputs
+}
diff --git a/src/merge/merge-artifacts.ts b/src/merge/merge-artifacts.ts
new file mode 100644
index 0000000..b45ef9c
--- /dev/null
+++ b/src/merge/merge-artifacts.ts
@@ -0,0 +1,93 @@
+import * as path from 'path'
+import {mkdtemp, rm} from 'fs/promises'
+import * as core from '@actions/core'
+import {Minimatch} from 'minimatch'
+import artifactClient, {UploadArtifactOptions} from '@actions/artifact'
+import {getInputs} from './input-helper'
+import {uploadArtifact} from '../shared/upload-artifact'
+import {findFilesToUpload} from '../shared/search'
+
+const PARALLEL_DOWNLOADS = 5
+
+export const chunk = <T>(arr: T[], n: number): T[][] =>
+  arr.reduce((acc, cur, i) => {
+    const index = Math.floor(i / n)
+    acc[index] = [...(acc[index] || []), cur]
+    return acc
+  }, [] as T[][])
+
+export async function run(): Promise<void> {
+  const inputs = getInputs()
+  const tmpDir = await mkdtemp('merge-artifact')
+
+  const listArtifactResponse = await artifactClient.listArtifacts({
+    latest: true
+  })
+  const matcher = new Minimatch(inputs.pattern)
+  const artifacts = listArtifactResponse.artifacts.filter(artifact =>
+    matcher.match(artifact.name)
+  )
+  core.debug(
+    `Filtered from ${listArtifactResponse.artifacts.length} to ${artifacts.length} artifacts`
+  )
+
+  if (artifacts.length === 0) {
+    throw new Error(`No artifacts found matching pattern '${inputs.pattern}'`)
+  }
+
+  core.info(`Preparing to download the following artifacts:`)
+  artifacts.forEach(artifact => {
+    core.info(`- ${artifact.name} (ID: ${artifact.id}, Size: ${artifact.size})`)
+  })
+
+  const downloadPromises = artifacts.map(artifact =>
+    artifactClient.downloadArtifact(artifact.id, {
+      path: inputs.separateDirectories
+        ? path.join(tmpDir, artifact.name)
+        : tmpDir
+    })
+  )
+
+  const chunkedPromises = chunk(downloadPromises, PARALLEL_DOWNLOADS)
+  for (const chunk of chunkedPromises) {
+    await Promise.all(chunk)
+  }
+
+  const options: UploadArtifactOptions = {}
+  if (inputs.retentionDays) {
+    options.retentionDays = inputs.retentionDays
+  }
+
+  if (typeof inputs.compressionLevel !== 'undefined') {
+    options.compressionLevel = inputs.compressionLevel
+  }
+
+  const searchResult = await findFilesToUpload(tmpDir)
+
+  await uploadArtifact(
+    inputs.name,
+    searchResult.filesToUpload,
+    searchResult.rootDirectory,
+    options
+  )
+
+  core.info(
+    `The ${artifacts.length} artifact(s) have been successfully merged!`
+  )
+
+  if (inputs.deleteMerged) {
+    const deletePromises = artifacts.map(artifact =>
+      artifactClient.deleteArtifact(artifact.name)
+    )
+    await Promise.all(deletePromises)
+    core.info(`The ${artifacts.length} artifact(s) have been deleted`)
+  }
+
+  try {
+    await rm(tmpDir, {recursive: true})
+  } catch (error) {
+    core.warning(
+      `Unable to remove temporary directory: ${(error as Error).message}`
+    )
+  }
+}
diff --git a/src/merge/merge-inputs.ts b/src/merge/merge-inputs.ts
new file mode 100644
index 0000000..def507a
--- /dev/null
+++ b/src/merge/merge-inputs.ts
@@ -0,0 +1,33 @@
+export interface MergeInputs {
+  /**
+   * The name of the artifact that the artifacts will be merged into
+   */
+  name: string
+
+  /**
+   * A glob pattern matching the artifacts that should be merged.
+   */
+  pattern: string
+
+  /**
+   * Duration after which artifact will expire in days
+   */
+  retentionDays: number
+
+  /**
+   * The level of compression for Zlib to be applied to the artifact archive.
+   */
+  compressionLevel?: number
+
+  /**
+   * If true, the artifacts that were merged will be deleted.
+   * If false, the artifacts will still exist.
+   */
+  deleteMerged: boolean
+
+  /**
+   * If true, the artifacts will be merged into separate directories.
+   * If false, the artifacts will be merged into the root of the destination.
+   */
+  separateDirectories: boolean
+}