Compare commits

...

53 Commits

Author SHA1 Message Date
Rob Herley d3f86a106a Merge pull request #404 from actions/robherley/v4.3.0
Prep for v4.3.0 release
2025-04-24 12:25:03 -04:00
Rob Herley fc02353415 prep for v4.3.0 release 2025-04-24 11:21:41 -04:00
Josh Gross 77454371a4 Merge pull request #402 from actions/joshmgross/download-by-id-example
Fix workflow example for downloading by artifact ID
2025-04-24 11:04:38 -04:00
Josh Gross 84fc7a0a35 Remove path filters from Check dist workflow 2025-04-23 10:32:04 -04:00
Josh Gross 67f2bc382f Fix workflow example for downloading by artifact ID 2025-04-23 10:27:20 -04:00
Grant Birkinbine 8ea3c2c174 Merge pull request #401 from actions/download-by-id
feat: implement new `artifact-ids` input
2025-04-22 08:16:56 -07:00
GrantBirki d219c630f6 add supporting unit tests for artifact downloads with ids 2025-04-17 13:14:21 -07:00
GrantBirki 54124fbd88 revert getArtifact() changes - for now we have to list and filter by artifact-ids until a getArtifactById() public method exists 2025-04-17 12:30:12 -07:00
GrantBirki b83057b90d bundle 2025-04-17 12:20:46 -07:00
GrantBirki 171183c7dc use the same artifactClient.getArtifact structure as seen above in isSingleArtifactDownload logic 2025-04-17 12:18:37 -07:00
GrantBirki e463631f66 bundle 2025-04-17 11:49:32 -07:00
GrantBirki ec378bcca1 when only one artifact-id is given, use getArtifact and check the resulting id returned 2025-04-17 11:48:44 -07:00
GrantBirki 42aef06f22 apply https://github.com/actions/download-artifact/pull/401#discussion_r2048225048 suggestion 2025-04-17 09:55:13 -07:00
Grant Birkinbine ac35f995fe implement new artifact-ids input 2025-04-17 04:47:03 +00:00
Josh Gross 95815c38cf Merge pull request #391 from GhadimiR/main
Fix bug introduced in 4.2.0
2025-03-19 11:14:44 -04:00
Ryan Ghadimi 278fca438a Move log statements 2025-03-19 15:06:13 +00:00
Ryan Ghadimi 68909842a1 Merge branch 'main' into main 2025-03-19 15:04:09 +00:00
Josh Gross f9415c0ec3 Run unit tests in CI 2025-03-19 15:01:26 +00:00
Josh Gross 76a6eb5cbc Merge pull request #392 from GhadimiR/add_unit_tests
Add unit tests
2025-03-19 10:52:21 -04:00
Josh Gross a2426d7c45 Merge branch 'main' into add_unit_tests 2025-03-19 10:48:52 -04:00
Ryan Ghadimi 3ffa694f6f lint 2025-03-19 12:26:46 +00:00
Ryan Ghadimi 53f6aa5f93 Add extra assertion to download single artifact test 2025-03-19 12:25:37 +00:00
Ryan Ghadimi b456700053 lint 2025-03-19 11:31:11 +00:00
Ryan Ghadimi 9eab798a98 Configure tsconfig 2025-03-19 11:25:29 +00:00
Ryan Ghadimi a39a661f39 Unfix error 2025-03-19 11:22:27 +00:00
Ryan Ghadimi 9a869e9c49 Lint 2025-03-19 11:21:30 +00:00
Ryan Ghadimi 96a6f165f4 Add tests & test dependencies 2025-03-19 11:17:03 +00:00
Ryan Ghadimi df4ad15cb8 Merge branch 'main' into main 2025-03-18 22:02:13 +00:00
Ryan Ghadimi c7cfc3a2a3 dist & package.json 2025-03-18 21:28:08 +00:00
Ryan Ghadimi 2439186eed Fix bug introduced in 4.2.0 2025-03-18 21:25:22 +00:00
JoannaaKL b14cf4c926 Merge pull request #383 from GhadimiR/main
Bump artifact version, do digest check
2025-03-18 16:31:00 +01:00
Ryan Ghadimi c5804ef743 Update dist 2025-03-18 15:23:08 +00:00
Ryan Ghadimi 956811a503 Update artifact to 2.3.2 2025-03-18 15:21:17 +00:00
Ryan Ghadimi af3c6d3e5b Update artifact license 2025-03-18 13:23:53 +00:00
Ryan Ghadimi 4dd97f8f21 Bump artifact package 2025-03-18 11:57:35 +00:00
Ryan Ghadimi da9985dde6 Merge branch 'main' into main 2025-03-17 10:26:24 +00:00
Larissa Fortuna 81ba80daa4 Merge pull request #384 from actions/lkfortuna-patch-1
Update README.md
2025-03-13 08:12:46 -07:00
Larissa Fortuna 727afbf2b0 Update README.md
removing deprecation warning
2025-03-12 15:02:16 -07:00
Ryan Ghadimi 56c2d7ea8c Make work as intended 2025-03-12 16:21:59 +00:00
Ryan Ghadimi 7797bfcd59 run release 2025-03-12 16:20:09 +00:00
Ryan Ghadimi 9ff67cb2d2 Break the thing, also log the expected digest 2025-03-12 16:17:52 +00:00
Ryan Ghadimi 049eba1e9a unbreak testing code 2025-03-12 16:04:02 +00:00
Ryan Ghadimi 503e7a18ae Refactor loop, break for testing 2025-03-12 15:40:05 +00:00
Ryan Ghadimi a8a786b097 update dist 2025-03-12 14:13:07 +00:00
Ryan Ghadimi 24aef17bbf Refactor loop 2025-03-12 14:02:51 +00:00
Ryan Ghadimi b81a615862 Bump artifact version, do digest check 2025-03-12 13:47:20 +00:00
Yang Cao cc20338598 Merge pull request #380 from actions/yacaovsnc/release_4_1_9
Update artifact package to 2.2.2
2025-02-25 16:23:11 -05:00
Yang Cao 1fc0fee191 Update artifact package to 2.2.2 2025-02-25 16:10:45 -05:00
Rob Herley 7fba95161a Merge pull request #372 from andyfeller/patch-1
Update MIGRATION.md
2025-01-10 12:01:23 -05:00
Andy Feller f9ceb7763b Update MIGRATION.md
Fixing the broken link pointing to `actions/upload-artifact` content outside of the repository.

cc: @pedrolacerda
2025-01-10 11:56:44 -05:00
Josh Gross 533298bc57 Merge pull request #370 from froblesmartin/patch-1
docs: small migration fix
2024-12-23 13:12:54 -05:00
Francisco Robles Martín d06289e120 docs: small migration fix 2024-12-23 14:32:00 +01:00
Joel Ambass d0ce8fd116 Merge pull request #354 from actions/Jcambass-patch-1
Add workflow file for publishing releases to immutable action package
2024-09-26 08:20:04 +02:00
14 changed files with 9359 additions and 2662 deletions
-4
View File
@@ -10,11 +10,7 @@ on:
push:
branches:
- main
paths-ignore:
- '**.md'
pull_request:
paths-ignore:
- '**.md'
workflow_dispatch:
jobs:
+3
View File
@@ -40,6 +40,9 @@ jobs:
- name: Format
run: npm run format-check
- name: Run Unit Tests
run: npm test
- name: Create artifacts
run: |
mkdir -p path/to/artifact-A
+1 -1
View File
@@ -1,6 +1,6 @@
---
name: "@actions/artifact"
version: 2.1.8
version: 2.3.2
type: npm
summary: Actions artifact lib
homepage: https://github.com/actions/toolkit/tree/main/packages/artifact
+32 -6
View File
@@ -1,11 +1,5 @@
# `@actions/download-artifact`
> [!WARNING]
> actions/download-artifact@v3 is scheduled for deprecation on **November 30, 2024**. [Learn more.](https://github.blog/changelog/2024-04-16-deprecation-notice-v3-of-the-artifact-actions/)
> Similarly, v1/v2 are scheduled for deprecation on **June 30, 2024**.
> Please update your workflow to use v4 of the artifact actions.
> This deprecation will not impact any existing versions of GitHub Enterprise Server being used by customers.
Download [Actions Artifacts](https://docs.github.com/en/actions/using-workflows/storing-workflow-data-as-artifacts) from your Workflow Runs. Internally powered by the [@actions/artifact](https://github.com/actions/toolkit/tree/main/packages/artifact) package.
See also [upload-artifact](https://github.com/actions/upload-artifact).
@@ -19,6 +13,7 @@ See also [upload-artifact](https://github.com/actions/upload-artifact).
- [Outputs](#outputs)
- [Examples](#examples)
- [Download Single Artifact](#download-single-artifact)
- [Download Artifacts by ID](#download-artifacts-by-id)
- [Download All Artifacts](#download-all-artifacts)
- [Download multiple (filtered) Artifacts to the same directory](#download-multiple-filtered-artifacts-to-the-same-directory)
- [Download Artifacts from other Workflow Runs or Repositories](#download-artifacts-from-other-workflow-runs-or-repositories)
@@ -59,6 +54,11 @@ For assistance with breaking changes, see [MIGRATION.md](docs/MIGRATION.md).
# Optional.
name:
# IDs of the artifacts to download, comma-separated.
# Either inputs `artifact-ids` or `name` can be used, but not both.
# Optional.
artifact-ids:
# Destination path. Supports basic tilde expansion.
# Optional. Default is $GITHUB_WORKSPACE
path:
@@ -123,6 +123,32 @@ steps:
run: ls -R your/destination/dir
```
### Download Artifacts by ID
The `artifact-ids` input allows downloading artifacts using their unique ID rather than name. This is particularly useful when working with immutable artifacts from `actions/upload-artifact@v4` which assigns a unique ID to each artifact.
```yaml
steps:
- uses: actions/download-artifact@v4
with:
artifact-ids: 12345
- name: Display structure of downloaded files
run: ls -R
```
Multiple artifacts can be downloaded by providing a comma-separated list of IDs:
```yaml
steps:
- uses: actions/download-artifact@v4
with:
artifact-ids: 12345,67890
path: path/to/artifacts
- name: Display structure of downloaded files
run: ls -R path/to/artifacts
```
This will download multiple artifacts to separate directories (similar to downloading multiple artifacts by name).
### Download All Artifacts
+374
View File
@@ -0,0 +1,374 @@
import * as core from '@actions/core'
import artifact, {ArtifactNotFoundError} from '@actions/artifact'
import {run} from '../src/download-artifact'
import {Inputs} from '../src/constants'
jest.mock('@actions/github', () => ({
context: {
repo: {
owner: 'actions',
repo: 'toolkit'
},
runId: 123,
serverUrl: 'https://github.com'
}
}))
jest.mock('@actions/core')
/* eslint-disable no-unused-vars */ /* eslint-disable @typescript-eslint/no-explicit-any */
const mockInputs = (overrides?: Partial<{[K in Inputs]?: any}>) => {
const inputs = {
[Inputs.Name]: 'artifact-name',
[Inputs.Path]: '/some/artifact/path',
[Inputs.GitHubToken]: 'warn',
[Inputs.Repository]: 'owner/some-repository',
[Inputs.RunID]: 'some-run-id',
[Inputs.Pattern]: 'some-pattern',
...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('download', () => {
beforeEach(async () => {
mockInputs()
jest.clearAllMocks()
// Mock artifact client methods
jest
.spyOn(artifact, 'listArtifacts')
.mockImplementation(() => Promise.resolve({artifacts: []}))
jest.spyOn(artifact, 'getArtifact').mockImplementation(name => {
throw new ArtifactNotFoundError(`Artifact '${name}' not found`)
})
jest
.spyOn(artifact, 'downloadArtifact')
.mockImplementation(() => Promise.resolve({digestMismatch: false}))
})
test('downloads a single artifact by name', async () => {
const mockArtifact = {
id: 123,
name: 'artifact-name',
size: 1024,
digest: 'abc123'
}
jest
.spyOn(artifact, 'getArtifact')
.mockImplementation(() => Promise.resolve({artifact: mockArtifact}))
await run()
expect(artifact.downloadArtifact).toHaveBeenCalledWith(
mockArtifact.id,
expect.objectContaining({
expectedHash: mockArtifact.digest
})
)
expect(core.info).toHaveBeenCalledWith('Total of 1 artifact(s) downloaded')
expect(core.setOutput).toHaveBeenCalledWith(
'download-path',
expect.any(String)
)
expect(core.info).toHaveBeenCalledWith(
'Download artifact has finished successfully'
)
})
test('downloads multiple artifacts when no name or pattern provided', async () => {
jest.clearAllMocks()
mockInputs({
[Inputs.Name]: '',
[Inputs.Pattern]: ''
})
const mockArtifacts = [
{id: 123, name: 'artifact1', size: 1024, digest: 'abc123'},
{id: 456, name: 'artifact2', size: 2048, digest: 'def456'}
]
// Set up artifact mock after clearing mocks
jest
.spyOn(artifact, 'listArtifacts')
.mockImplementation(() => Promise.resolve({artifacts: mockArtifacts}))
// Reset downloadArtifact mock as well
jest
.spyOn(artifact, 'downloadArtifact')
.mockImplementation(() => Promise.resolve({digestMismatch: false}))
await run()
expect(core.info).toHaveBeenCalledWith(
'No input name, artifact-ids or pattern filtered specified, downloading all artifacts'
)
expect(core.info).toHaveBeenCalledWith('Total of 2 artifact(s) downloaded')
expect(artifact.downloadArtifact).toHaveBeenCalledTimes(2)
})
test('sets download path output even when no artifacts are found', async () => {
mockInputs({[Inputs.Name]: ''})
await run()
expect(core.setOutput).toHaveBeenCalledWith(
'download-path',
expect.any(String)
)
expect(core.info).toHaveBeenCalledWith(
'Download artifact has finished successfully'
)
expect(core.info).toHaveBeenCalledWith('Total of 0 artifact(s) downloaded')
})
test('filters artifacts by pattern', async () => {
const mockArtifacts = [
{id: 123, name: 'test-artifact', size: 1024, digest: 'abc123'},
{id: 456, name: 'prod-artifact', size: 2048, digest: 'def456'}
]
jest
.spyOn(artifact, 'listArtifacts')
.mockImplementation(() => Promise.resolve({artifacts: mockArtifacts}))
mockInputs({
[Inputs.Name]: '',
[Inputs.Pattern]: 'test-*'
})
await run()
expect(artifact.downloadArtifact).toHaveBeenCalledTimes(1)
expect(artifact.downloadArtifact).toHaveBeenCalledWith(
123,
expect.anything()
)
})
test('uses token and repository information when provided', async () => {
const token = 'ghp_testtoken123'
mockInputs({
[Inputs.Name]: '',
[Inputs.GitHubToken]: token,
[Inputs.Repository]: 'myorg/myrepo',
[Inputs.RunID]: '789'
})
jest
.spyOn(artifact, 'listArtifacts')
.mockImplementation(() => Promise.resolve({artifacts: []}))
await run()
expect(artifact.listArtifacts).toHaveBeenCalledWith(
expect.objectContaining({
findBy: {
token,
workflowRunId: 789,
repositoryName: 'myrepo',
repositoryOwner: 'myorg'
}
})
)
})
test('throws error when repository format is invalid', async () => {
mockInputs({
[Inputs.GitHubToken]: 'some-token',
[Inputs.Repository]: 'invalid-format' // Missing the owner/repo format
})
await expect(run()).rejects.toThrow(
"Invalid repository: 'invalid-format'. Must be in format owner/repo"
)
})
test('warns when digest validation fails', async () => {
const mockArtifact = {
id: 123,
name: 'corrupted-artifact',
size: 1024,
digest: 'abc123'
}
jest
.spyOn(artifact, 'getArtifact')
.mockImplementation(() => Promise.resolve({artifact: mockArtifact}))
jest
.spyOn(artifact, 'downloadArtifact')
.mockImplementation(() => Promise.resolve({digestMismatch: true}))
await run()
expect(core.warning).toHaveBeenCalledWith(
expect.stringContaining('digest validation failed')
)
})
test('downloads a single artifact by ID', async () => {
const mockArtifact = {
id: 456,
name: 'artifact-by-id',
size: 1024,
digest: 'def456'
}
mockInputs({
[Inputs.Name]: '',
[Inputs.Pattern]: '',
[Inputs.ArtifactIds]: '456'
})
jest.spyOn(artifact, 'listArtifacts').mockImplementation(() =>
Promise.resolve({
artifacts: [mockArtifact]
})
)
await run()
expect(core.info).toHaveBeenCalledWith('Downloading artifacts by ID')
expect(core.debug).toHaveBeenCalledWith('Parsed artifact IDs: ["456"]')
expect(artifact.downloadArtifact).toHaveBeenCalledTimes(1)
expect(artifact.downloadArtifact).toHaveBeenCalledWith(
456,
expect.objectContaining({
expectedHash: mockArtifact.digest
})
)
expect(core.info).toHaveBeenCalledWith('Total of 1 artifact(s) downloaded')
})
test('downloads multiple artifacts by ID', async () => {
const mockArtifacts = [
{id: 123, name: 'first-artifact', size: 1024, digest: 'abc123'},
{id: 456, name: 'second-artifact', size: 2048, digest: 'def456'},
{id: 789, name: 'third-artifact', size: 3072, digest: 'ghi789'}
]
mockInputs({
[Inputs.Name]: '',
[Inputs.Pattern]: '',
[Inputs.ArtifactIds]: '123, 456, 789'
})
jest.spyOn(artifact, 'listArtifacts').mockImplementation(() =>
Promise.resolve({
artifacts: mockArtifacts
})
)
await run()
expect(core.info).toHaveBeenCalledWith('Downloading artifacts by ID')
expect(core.debug).toHaveBeenCalledWith(
'Parsed artifact IDs: ["123","456","789"]'
)
expect(artifact.downloadArtifact).toHaveBeenCalledTimes(3)
mockArtifacts.forEach(mockArtifact => {
expect(artifact.downloadArtifact).toHaveBeenCalledWith(
mockArtifact.id,
expect.objectContaining({
expectedHash: mockArtifact.digest
})
)
})
expect(core.info).toHaveBeenCalledWith('Total of 3 artifact(s) downloaded')
})
test('warns when some artifact IDs are not found', async () => {
const mockArtifacts = [
{id: 123, name: 'found-artifact', size: 1024, digest: 'abc123'}
]
mockInputs({
[Inputs.Name]: '',
[Inputs.Pattern]: '',
[Inputs.ArtifactIds]: '123, 456, 789'
})
jest.spyOn(artifact, 'listArtifacts').mockImplementation(() =>
Promise.resolve({
artifacts: mockArtifacts
})
)
await run()
expect(core.warning).toHaveBeenCalledWith(
'Could not find the following artifact IDs: 456, 789'
)
expect(core.debug).toHaveBeenCalledWith('Found 1 artifacts by ID')
expect(artifact.downloadArtifact).toHaveBeenCalledTimes(1)
})
test('throws error when no artifacts with requested IDs are found', async () => {
mockInputs({
[Inputs.Name]: '',
[Inputs.Pattern]: '',
[Inputs.ArtifactIds]: '123, 456'
})
jest.spyOn(artifact, 'listArtifacts').mockImplementation(() =>
Promise.resolve({
artifacts: []
})
)
await expect(run()).rejects.toThrow(
'None of the provided artifact IDs were found'
)
})
test('throws error when artifact-ids input is empty', async () => {
mockInputs({
[Inputs.Name]: '',
[Inputs.Pattern]: '',
[Inputs.ArtifactIds]: ' '
})
await expect(run()).rejects.toThrow(
"No valid artifact IDs provided in 'artifact-ids' input"
)
})
test('throws error when some artifact IDs are not valid numbers', async () => {
mockInputs({
[Inputs.Name]: '',
[Inputs.Pattern]: '',
[Inputs.ArtifactIds]: '123, abc, 456'
})
await expect(run()).rejects.toThrow(
"Invalid artifact ID: 'abc'. Must be a number."
)
})
test('throws error when both name and artifact-ids are provided', async () => {
mockInputs({
[Inputs.Name]: 'some-artifact',
[Inputs.ArtifactIds]: '123'
})
await expect(run()).rejects.toThrow(
"Inputs 'name' and 'artifact-ids' cannot be used together. Please specify only one."
)
})
})
+3
View File
@@ -5,6 +5,9 @@ inputs:
name:
description: 'Name of the artifact to download. If unspecified, all artifacts for the run are downloaded.'
required: false
artifact-ids:
description: 'IDs of the artifacts to download, comma-separated. Either inputs `artifact-ids` or `name` can be used, but not both.'
required: false
path:
description: 'Destination path. Supports basic tilde expansion. Defaults to $GITHUB_WORKSPACE'
required: false
+522 -2232
View File
@@ -813,7 +813,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
__exportStar(__nccwpck_require__(54622), exports);
__exportStar(__nccwpck_require__(8626), exports);
__exportStar(__nccwpck_require__(58178), exports);
__exportStar(__nccwpck_require__(63077), exports);
__exportStar(__nccwpck_require__(49773), exports);
//# sourceMappingURL=index.js.map
/***/ }),
@@ -824,7 +824,7 @@ __exportStar(__nccwpck_require__(63077), exports);
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.ArtifactService = exports.DeleteArtifactResponse = exports.DeleteArtifactRequest = exports.GetSignedArtifactURLResponse = exports.GetSignedArtifactURLRequest = exports.ListArtifactsResponse_MonolithArtifact = exports.ListArtifactsResponse = exports.ListArtifactsRequest = exports.FinalizeArtifactResponse = exports.FinalizeArtifactRequest = exports.CreateArtifactResponse = exports.CreateArtifactRequest = void 0;
exports.ArtifactService = exports.DeleteArtifactResponse = exports.DeleteArtifactRequest = exports.GetSignedArtifactURLResponse = exports.GetSignedArtifactURLRequest = exports.ListArtifactsResponse_MonolithArtifact = exports.ListArtifactsResponse = exports.ListArtifactsRequest = exports.FinalizeArtifactResponse = exports.FinalizeArtifactRequest = exports.CreateArtifactResponse = exports.CreateArtifactRequest = exports.FinalizeMigratedArtifactResponse = exports.FinalizeMigratedArtifactRequest = exports.MigrateArtifactResponse = exports.MigrateArtifactRequest = void 0;
// @generated by protobuf-ts 2.9.1 with parameter long_type_string,client_none,generate_dependencies
// @generated from protobuf file "results/api/v1/artifact.proto" (package "github.actions.results.api.v1", syntax proto3)
// tslint:disable
@@ -838,6 +838,236 @@ const wrappers_1 = __nccwpck_require__(8626);
const wrappers_2 = __nccwpck_require__(8626);
const timestamp_1 = __nccwpck_require__(54622);
// @generated message type with reflection information, may provide speed optimized methods
class MigrateArtifactRequest$Type extends runtime_5.MessageType {
constructor() {
super("github.actions.results.api.v1.MigrateArtifactRequest", [
{ no: 1, name: "workflow_run_backend_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 3, name: "expires_at", kind: "message", T: () => timestamp_1.Timestamp }
]);
}
create(value) {
const message = { workflowRunBackendId: "", name: "" };
globalThis.Object.defineProperty(message, runtime_4.MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
(0, runtime_3.reflectionMergePartial)(this, message, value);
return message;
}
internalBinaryRead(reader, length, options, target) {
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string workflow_run_backend_id */ 1:
message.workflowRunBackendId = reader.string();
break;
case /* string name */ 2:
message.name = reader.string();
break;
case /* google.protobuf.Timestamp expires_at */ 3:
message.expiresAt = timestamp_1.Timestamp.internalBinaryRead(reader, reader.uint32(), options, message.expiresAt);
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? runtime_2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message, writer, options) {
/* string workflow_run_backend_id = 1; */
if (message.workflowRunBackendId !== "")
writer.tag(1, runtime_1.WireType.LengthDelimited).string(message.workflowRunBackendId);
/* string name = 2; */
if (message.name !== "")
writer.tag(2, runtime_1.WireType.LengthDelimited).string(message.name);
/* google.protobuf.Timestamp expires_at = 3; */
if (message.expiresAt)
timestamp_1.Timestamp.internalBinaryWrite(message.expiresAt, writer.tag(3, runtime_1.WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message github.actions.results.api.v1.MigrateArtifactRequest
*/
exports.MigrateArtifactRequest = new MigrateArtifactRequest$Type();
// @generated message type with reflection information, may provide speed optimized methods
class MigrateArtifactResponse$Type extends runtime_5.MessageType {
constructor() {
super("github.actions.results.api.v1.MigrateArtifactResponse", [
{ no: 1, name: "ok", kind: "scalar", T: 8 /*ScalarType.BOOL*/ },
{ no: 2, name: "signed_upload_url", kind: "scalar", T: 9 /*ScalarType.STRING*/ }
]);
}
create(value) {
const message = { ok: false, signedUploadUrl: "" };
globalThis.Object.defineProperty(message, runtime_4.MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
(0, runtime_3.reflectionMergePartial)(this, message, value);
return message;
}
internalBinaryRead(reader, length, options, target) {
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* bool ok */ 1:
message.ok = reader.bool();
break;
case /* string signed_upload_url */ 2:
message.signedUploadUrl = reader.string();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? runtime_2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message, writer, options) {
/* bool ok = 1; */
if (message.ok !== false)
writer.tag(1, runtime_1.WireType.Varint).bool(message.ok);
/* string signed_upload_url = 2; */
if (message.signedUploadUrl !== "")
writer.tag(2, runtime_1.WireType.LengthDelimited).string(message.signedUploadUrl);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message github.actions.results.api.v1.MigrateArtifactResponse
*/
exports.MigrateArtifactResponse = new MigrateArtifactResponse$Type();
// @generated message type with reflection information, may provide speed optimized methods
class FinalizeMigratedArtifactRequest$Type extends runtime_5.MessageType {
constructor() {
super("github.actions.results.api.v1.FinalizeMigratedArtifactRequest", [
{ no: 1, name: "workflow_run_backend_id", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 2, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 3, name: "size", kind: "scalar", T: 3 /*ScalarType.INT64*/ }
]);
}
create(value) {
const message = { workflowRunBackendId: "", name: "", size: "0" };
globalThis.Object.defineProperty(message, runtime_4.MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
(0, runtime_3.reflectionMergePartial)(this, message, value);
return message;
}
internalBinaryRead(reader, length, options, target) {
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* string workflow_run_backend_id */ 1:
message.workflowRunBackendId = reader.string();
break;
case /* string name */ 2:
message.name = reader.string();
break;
case /* int64 size */ 3:
message.size = reader.int64().toString();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? runtime_2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message, writer, options) {
/* string workflow_run_backend_id = 1; */
if (message.workflowRunBackendId !== "")
writer.tag(1, runtime_1.WireType.LengthDelimited).string(message.workflowRunBackendId);
/* string name = 2; */
if (message.name !== "")
writer.tag(2, runtime_1.WireType.LengthDelimited).string(message.name);
/* int64 size = 3; */
if (message.size !== "0")
writer.tag(3, runtime_1.WireType.Varint).int64(message.size);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message github.actions.results.api.v1.FinalizeMigratedArtifactRequest
*/
exports.FinalizeMigratedArtifactRequest = new FinalizeMigratedArtifactRequest$Type();
// @generated message type with reflection information, may provide speed optimized methods
class FinalizeMigratedArtifactResponse$Type extends runtime_5.MessageType {
constructor() {
super("github.actions.results.api.v1.FinalizeMigratedArtifactResponse", [
{ no: 1, name: "ok", kind: "scalar", T: 8 /*ScalarType.BOOL*/ },
{ no: 2, name: "artifact_id", kind: "scalar", T: 3 /*ScalarType.INT64*/ }
]);
}
create(value) {
const message = { ok: false, artifactId: "0" };
globalThis.Object.defineProperty(message, runtime_4.MESSAGE_TYPE, { enumerable: false, value: this });
if (value !== undefined)
(0, runtime_3.reflectionMergePartial)(this, message, value);
return message;
}
internalBinaryRead(reader, length, options, target) {
let message = target !== null && target !== void 0 ? target : this.create(), end = reader.pos + length;
while (reader.pos < end) {
let [fieldNo, wireType] = reader.tag();
switch (fieldNo) {
case /* bool ok */ 1:
message.ok = reader.bool();
break;
case /* int64 artifact_id */ 2:
message.artifactId = reader.int64().toString();
break;
default:
let u = options.readUnknownField;
if (u === "throw")
throw new globalThis.Error(`Unknown field ${fieldNo} (wire type ${wireType}) for ${this.typeName}`);
let d = reader.skip(wireType);
if (u !== false)
(u === true ? runtime_2.UnknownFieldHandler.onRead : u)(this.typeName, message, fieldNo, wireType, d);
}
}
return message;
}
internalBinaryWrite(message, writer, options) {
/* bool ok = 1; */
if (message.ok !== false)
writer.tag(1, runtime_1.WireType.Varint).bool(message.ok);
/* int64 artifact_id = 2; */
if (message.artifactId !== "0")
writer.tag(2, runtime_1.WireType.Varint).int64(message.artifactId);
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
return writer;
}
}
/**
* @generated MessageType for protobuf message github.actions.results.api.v1.FinalizeMigratedArtifactResponse
*/
exports.FinalizeMigratedArtifactResponse = new FinalizeMigratedArtifactResponse$Type();
// @generated message type with reflection information, may provide speed optimized methods
class CreateArtifactRequest$Type extends runtime_5.MessageType {
constructor() {
super("github.actions.results.api.v1.CreateArtifactRequest", [
@@ -1219,7 +1449,8 @@ class ListArtifactsResponse_MonolithArtifact$Type extends runtime_5.MessageType
{ no: 3, name: "database_id", kind: "scalar", T: 3 /*ScalarType.INT64*/ },
{ no: 4, name: "name", kind: "scalar", T: 9 /*ScalarType.STRING*/ },
{ no: 5, name: "size", kind: "scalar", T: 3 /*ScalarType.INT64*/ },
{ no: 6, name: "created_at", kind: "message", T: () => timestamp_1.Timestamp }
{ no: 6, name: "created_at", kind: "message", T: () => timestamp_1.Timestamp },
{ no: 7, name: "digest", kind: "message", T: () => wrappers_2.StringValue }
]);
}
create(value) {
@@ -1252,6 +1483,9 @@ class ListArtifactsResponse_MonolithArtifact$Type extends runtime_5.MessageType
case /* google.protobuf.Timestamp created_at */ 6:
message.createdAt = timestamp_1.Timestamp.internalBinaryRead(reader, reader.uint32(), options, message.createdAt);
break;
case /* google.protobuf.StringValue digest */ 7:
message.digest = wrappers_2.StringValue.internalBinaryRead(reader, reader.uint32(), options, message.digest);
break;
default:
let u = options.readUnknownField;
if (u === "throw")
@@ -1282,6 +1516,9 @@ class ListArtifactsResponse_MonolithArtifact$Type extends runtime_5.MessageType
/* google.protobuf.Timestamp created_at = 6; */
if (message.createdAt)
timestamp_1.Timestamp.internalBinaryWrite(message.createdAt, writer.tag(6, runtime_1.WireType.LengthDelimited).fork(), options).join();
/* google.protobuf.StringValue digest = 7; */
if (message.digest)
wrappers_2.StringValue.internalBinaryWrite(message.digest, writer.tag(7, runtime_1.WireType.LengthDelimited).fork(), options).join();
let u = options.writeUnknownFields;
if (u !== false)
(u == true ? runtime_2.UnknownFieldHandler.onWrite : u)(this.typeName, message, writer);
@@ -1523,29 +1760,21 @@ exports.ArtifactService = new runtime_rpc_1.ServiceType("github.actions.results.
{ name: "FinalizeArtifact", options: {}, I: exports.FinalizeArtifactRequest, O: exports.FinalizeArtifactResponse },
{ name: "ListArtifacts", options: {}, I: exports.ListArtifactsRequest, O: exports.ListArtifactsResponse },
{ name: "GetSignedArtifactURL", options: {}, I: exports.GetSignedArtifactURLRequest, O: exports.GetSignedArtifactURLResponse },
{ name: "DeleteArtifact", options: {}, I: exports.DeleteArtifactRequest, O: exports.DeleteArtifactResponse }
{ name: "DeleteArtifact", options: {}, I: exports.DeleteArtifactRequest, O: exports.DeleteArtifactResponse },
{ name: "MigrateArtifact", options: {}, I: exports.MigrateArtifactRequest, O: exports.MigrateArtifactResponse },
{ name: "FinalizeMigratedArtifact", options: {}, I: exports.FinalizeMigratedArtifactRequest, O: exports.FinalizeMigratedArtifactResponse }
]);
//# sourceMappingURL=artifact.js.map
/***/ }),
/***/ 63077:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
/***/ 49773:
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.createArtifactServiceServer = exports.ArtifactServiceMethodList = exports.ArtifactServiceMethod = exports.ArtifactServiceClientProtobuf = exports.ArtifactServiceClientJSON = void 0;
const twirp_ts_1 = __nccwpck_require__(66465);
exports.ArtifactServiceClientProtobuf = exports.ArtifactServiceClientJSON = void 0;
const artifact_1 = __nccwpck_require__(58178);
class ArtifactServiceClientJSON {
constructor(rpc) {
@@ -1642,405 +1871,7 @@ class ArtifactServiceClientProtobuf {
}
}
exports.ArtifactServiceClientProtobuf = ArtifactServiceClientProtobuf;
var ArtifactServiceMethod;
(function (ArtifactServiceMethod) {
ArtifactServiceMethod["CreateArtifact"] = "CreateArtifact";
ArtifactServiceMethod["FinalizeArtifact"] = "FinalizeArtifact";
ArtifactServiceMethod["ListArtifacts"] = "ListArtifacts";
ArtifactServiceMethod["GetSignedArtifactURL"] = "GetSignedArtifactURL";
ArtifactServiceMethod["DeleteArtifact"] = "DeleteArtifact";
})(ArtifactServiceMethod || (exports.ArtifactServiceMethod = ArtifactServiceMethod = {}));
exports.ArtifactServiceMethodList = [
ArtifactServiceMethod.CreateArtifact,
ArtifactServiceMethod.FinalizeArtifact,
ArtifactServiceMethod.ListArtifacts,
ArtifactServiceMethod.GetSignedArtifactURL,
ArtifactServiceMethod.DeleteArtifact,
];
function createArtifactServiceServer(service) {
return new twirp_ts_1.TwirpServer({
service,
packageName: "github.actions.results.api.v1",
serviceName: "ArtifactService",
methodList: exports.ArtifactServiceMethodList,
matchRoute: matchArtifactServiceRoute,
});
}
exports.createArtifactServiceServer = createArtifactServiceServer;
function matchArtifactServiceRoute(method, events) {
switch (method) {
case "CreateArtifact":
return (ctx, service, data, interceptors) => __awaiter(this, void 0, void 0, function* () {
ctx = Object.assign(Object.assign({}, ctx), { methodName: "CreateArtifact" });
yield events.onMatch(ctx);
return handleArtifactServiceCreateArtifactRequest(ctx, service, data, interceptors);
});
case "FinalizeArtifact":
return (ctx, service, data, interceptors) => __awaiter(this, void 0, void 0, function* () {
ctx = Object.assign(Object.assign({}, ctx), { methodName: "FinalizeArtifact" });
yield events.onMatch(ctx);
return handleArtifactServiceFinalizeArtifactRequest(ctx, service, data, interceptors);
});
case "ListArtifacts":
return (ctx, service, data, interceptors) => __awaiter(this, void 0, void 0, function* () {
ctx = Object.assign(Object.assign({}, ctx), { methodName: "ListArtifacts" });
yield events.onMatch(ctx);
return handleArtifactServiceListArtifactsRequest(ctx, service, data, interceptors);
});
case "GetSignedArtifactURL":
return (ctx, service, data, interceptors) => __awaiter(this, void 0, void 0, function* () {
ctx = Object.assign(Object.assign({}, ctx), { methodName: "GetSignedArtifactURL" });
yield events.onMatch(ctx);
return handleArtifactServiceGetSignedArtifactURLRequest(ctx, service, data, interceptors);
});
case "DeleteArtifact":
return (ctx, service, data, interceptors) => __awaiter(this, void 0, void 0, function* () {
ctx = Object.assign(Object.assign({}, ctx), { methodName: "DeleteArtifact" });
yield events.onMatch(ctx);
return handleArtifactServiceDeleteArtifactRequest(ctx, service, data, interceptors);
});
default:
events.onNotFound();
const msg = `no handler found`;
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.BadRoute, msg);
}
}
function handleArtifactServiceCreateArtifactRequest(ctx, service, data, interceptors) {
switch (ctx.contentType) {
case twirp_ts_1.TwirpContentType.JSON:
return handleArtifactServiceCreateArtifactJSON(ctx, service, data, interceptors);
case twirp_ts_1.TwirpContentType.Protobuf:
return handleArtifactServiceCreateArtifactProtobuf(ctx, service, data, interceptors);
default:
const msg = "unexpected Content-Type";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.BadRoute, msg);
}
}
function handleArtifactServiceFinalizeArtifactRequest(ctx, service, data, interceptors) {
switch (ctx.contentType) {
case twirp_ts_1.TwirpContentType.JSON:
return handleArtifactServiceFinalizeArtifactJSON(ctx, service, data, interceptors);
case twirp_ts_1.TwirpContentType.Protobuf:
return handleArtifactServiceFinalizeArtifactProtobuf(ctx, service, data, interceptors);
default:
const msg = "unexpected Content-Type";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.BadRoute, msg);
}
}
function handleArtifactServiceListArtifactsRequest(ctx, service, data, interceptors) {
switch (ctx.contentType) {
case twirp_ts_1.TwirpContentType.JSON:
return handleArtifactServiceListArtifactsJSON(ctx, service, data, interceptors);
case twirp_ts_1.TwirpContentType.Protobuf:
return handleArtifactServiceListArtifactsProtobuf(ctx, service, data, interceptors);
default:
const msg = "unexpected Content-Type";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.BadRoute, msg);
}
}
function handleArtifactServiceGetSignedArtifactURLRequest(ctx, service, data, interceptors) {
switch (ctx.contentType) {
case twirp_ts_1.TwirpContentType.JSON:
return handleArtifactServiceGetSignedArtifactURLJSON(ctx, service, data, interceptors);
case twirp_ts_1.TwirpContentType.Protobuf:
return handleArtifactServiceGetSignedArtifactURLProtobuf(ctx, service, data, interceptors);
default:
const msg = "unexpected Content-Type";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.BadRoute, msg);
}
}
function handleArtifactServiceDeleteArtifactRequest(ctx, service, data, interceptors) {
switch (ctx.contentType) {
case twirp_ts_1.TwirpContentType.JSON:
return handleArtifactServiceDeleteArtifactJSON(ctx, service, data, interceptors);
case twirp_ts_1.TwirpContentType.Protobuf:
return handleArtifactServiceDeleteArtifactProtobuf(ctx, service, data, interceptors);
default:
const msg = "unexpected Content-Type";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.BadRoute, msg);
}
}
function handleArtifactServiceCreateArtifactJSON(ctx, service, data, interceptors) {
return __awaiter(this, void 0, void 0, function* () {
let request;
let response;
try {
const body = JSON.parse(data.toString() || "{}");
request = artifact_1.CreateArtifactRequest.fromJson(body, {
ignoreUnknownFields: true,
});
}
catch (e) {
if (e instanceof Error) {
const msg = "the json request could not be decoded";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = (0, twirp_ts_1.chainInterceptors)(...interceptors);
response = yield interceptor(ctx, request, (ctx, inputReq) => {
return service.CreateArtifact(ctx, inputReq);
});
}
else {
response = yield service.CreateArtifact(ctx, request);
}
return JSON.stringify(artifact_1.CreateArtifactResponse.toJson(response, {
useProtoFieldName: true,
emitDefaultValues: false,
}));
});
}
function handleArtifactServiceFinalizeArtifactJSON(ctx, service, data, interceptors) {
return __awaiter(this, void 0, void 0, function* () {
let request;
let response;
try {
const body = JSON.parse(data.toString() || "{}");
request = artifact_1.FinalizeArtifactRequest.fromJson(body, {
ignoreUnknownFields: true,
});
}
catch (e) {
if (e instanceof Error) {
const msg = "the json request could not be decoded";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = (0, twirp_ts_1.chainInterceptors)(...interceptors);
response = yield interceptor(ctx, request, (ctx, inputReq) => {
return service.FinalizeArtifact(ctx, inputReq);
});
}
else {
response = yield service.FinalizeArtifact(ctx, request);
}
return JSON.stringify(artifact_1.FinalizeArtifactResponse.toJson(response, {
useProtoFieldName: true,
emitDefaultValues: false,
}));
});
}
function handleArtifactServiceListArtifactsJSON(ctx, service, data, interceptors) {
return __awaiter(this, void 0, void 0, function* () {
let request;
let response;
try {
const body = JSON.parse(data.toString() || "{}");
request = artifact_1.ListArtifactsRequest.fromJson(body, {
ignoreUnknownFields: true,
});
}
catch (e) {
if (e instanceof Error) {
const msg = "the json request could not be decoded";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = (0, twirp_ts_1.chainInterceptors)(...interceptors);
response = yield interceptor(ctx, request, (ctx, inputReq) => {
return service.ListArtifacts(ctx, inputReq);
});
}
else {
response = yield service.ListArtifacts(ctx, request);
}
return JSON.stringify(artifact_1.ListArtifactsResponse.toJson(response, {
useProtoFieldName: true,
emitDefaultValues: false,
}));
});
}
function handleArtifactServiceGetSignedArtifactURLJSON(ctx, service, data, interceptors) {
return __awaiter(this, void 0, void 0, function* () {
let request;
let response;
try {
const body = JSON.parse(data.toString() || "{}");
request = artifact_1.GetSignedArtifactURLRequest.fromJson(body, {
ignoreUnknownFields: true,
});
}
catch (e) {
if (e instanceof Error) {
const msg = "the json request could not be decoded";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = (0, twirp_ts_1.chainInterceptors)(...interceptors);
response = yield interceptor(ctx, request, (ctx, inputReq) => {
return service.GetSignedArtifactURL(ctx, inputReq);
});
}
else {
response = yield service.GetSignedArtifactURL(ctx, request);
}
return JSON.stringify(artifact_1.GetSignedArtifactURLResponse.toJson(response, {
useProtoFieldName: true,
emitDefaultValues: false,
}));
});
}
function handleArtifactServiceDeleteArtifactJSON(ctx, service, data, interceptors) {
return __awaiter(this, void 0, void 0, function* () {
let request;
let response;
try {
const body = JSON.parse(data.toString() || "{}");
request = artifact_1.DeleteArtifactRequest.fromJson(body, {
ignoreUnknownFields: true,
});
}
catch (e) {
if (e instanceof Error) {
const msg = "the json request could not be decoded";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = (0, twirp_ts_1.chainInterceptors)(...interceptors);
response = yield interceptor(ctx, request, (ctx, inputReq) => {
return service.DeleteArtifact(ctx, inputReq);
});
}
else {
response = yield service.DeleteArtifact(ctx, request);
}
return JSON.stringify(artifact_1.DeleteArtifactResponse.toJson(response, {
useProtoFieldName: true,
emitDefaultValues: false,
}));
});
}
function handleArtifactServiceCreateArtifactProtobuf(ctx, service, data, interceptors) {
return __awaiter(this, void 0, void 0, function* () {
let request;
let response;
try {
request = artifact_1.CreateArtifactRequest.fromBinary(data);
}
catch (e) {
if (e instanceof Error) {
const msg = "the protobuf request could not be decoded";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = (0, twirp_ts_1.chainInterceptors)(...interceptors);
response = yield interceptor(ctx, request, (ctx, inputReq) => {
return service.CreateArtifact(ctx, inputReq);
});
}
else {
response = yield service.CreateArtifact(ctx, request);
}
return Buffer.from(artifact_1.CreateArtifactResponse.toBinary(response));
});
}
function handleArtifactServiceFinalizeArtifactProtobuf(ctx, service, data, interceptors) {
return __awaiter(this, void 0, void 0, function* () {
let request;
let response;
try {
request = artifact_1.FinalizeArtifactRequest.fromBinary(data);
}
catch (e) {
if (e instanceof Error) {
const msg = "the protobuf request could not be decoded";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = (0, twirp_ts_1.chainInterceptors)(...interceptors);
response = yield interceptor(ctx, request, (ctx, inputReq) => {
return service.FinalizeArtifact(ctx, inputReq);
});
}
else {
response = yield service.FinalizeArtifact(ctx, request);
}
return Buffer.from(artifact_1.FinalizeArtifactResponse.toBinary(response));
});
}
function handleArtifactServiceListArtifactsProtobuf(ctx, service, data, interceptors) {
return __awaiter(this, void 0, void 0, function* () {
let request;
let response;
try {
request = artifact_1.ListArtifactsRequest.fromBinary(data);
}
catch (e) {
if (e instanceof Error) {
const msg = "the protobuf request could not be decoded";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = (0, twirp_ts_1.chainInterceptors)(...interceptors);
response = yield interceptor(ctx, request, (ctx, inputReq) => {
return service.ListArtifacts(ctx, inputReq);
});
}
else {
response = yield service.ListArtifacts(ctx, request);
}
return Buffer.from(artifact_1.ListArtifactsResponse.toBinary(response));
});
}
function handleArtifactServiceGetSignedArtifactURLProtobuf(ctx, service, data, interceptors) {
return __awaiter(this, void 0, void 0, function* () {
let request;
let response;
try {
request = artifact_1.GetSignedArtifactURLRequest.fromBinary(data);
}
catch (e) {
if (e instanceof Error) {
const msg = "the protobuf request could not be decoded";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = (0, twirp_ts_1.chainInterceptors)(...interceptors);
response = yield interceptor(ctx, request, (ctx, inputReq) => {
return service.GetSignedArtifactURL(ctx, inputReq);
});
}
else {
response = yield service.GetSignedArtifactURL(ctx, request);
}
return Buffer.from(artifact_1.GetSignedArtifactURLResponse.toBinary(response));
});
}
function handleArtifactServiceDeleteArtifactProtobuf(ctx, service, data, interceptors) {
return __awaiter(this, void 0, void 0, function* () {
let request;
let response;
try {
request = artifact_1.DeleteArtifactRequest.fromBinary(data);
}
catch (e) {
if (e instanceof Error) {
const msg = "the protobuf request could not be decoded";
throw new twirp_ts_1.TwirpError(twirp_ts_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
if (interceptors && interceptors.length > 0) {
const interceptor = (0, twirp_ts_1.chainInterceptors)(...interceptors);
response = yield interceptor(ctx, request, (ctx, inputReq) => {
return service.DeleteArtifact(ctx, inputReq);
});
}
else {
response = yield service.DeleteArtifact(ctx, request);
}
return Buffer.from(artifact_1.DeleteArtifactResponse.toBinary(response));
});
}
//# sourceMappingURL=artifact.twirp.js.map
//# sourceMappingURL=artifact.twirp-client.js.map
/***/ }),
@@ -2328,6 +2159,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.downloadArtifactInternal = exports.downloadArtifactPublic = exports.streamExtractExternal = void 0;
const promises_1 = __importDefault(__nccwpck_require__(73292));
const crypto = __importStar(__nccwpck_require__(6113));
const stream = __importStar(__nccwpck_require__(12781));
const github = __importStar(__nccwpck_require__(95438));
const core = __importStar(__nccwpck_require__(42186));
const httpClient = __importStar(__nccwpck_require__(96255));
@@ -2364,8 +2197,7 @@ function streamExtract(url, directory) {
let retryCount = 0;
while (retryCount < 5) {
try {
yield streamExtractExternal(url, directory);
return;
return yield streamExtractExternal(url, directory);
}
catch (error) {
retryCount++;
@@ -2385,12 +2217,18 @@ function streamExtractExternal(url, directory) {
throw new Error(`Unexpected HTTP response from blob storage: ${response.message.statusCode} ${response.message.statusMessage}`);
}
const timeout = 30 * 1000; // 30 seconds
let sha256Digest = undefined;
return new Promise((resolve, reject) => {
const timerFn = () => {
response.message.destroy(new Error(`Blob storage chunk did not respond in ${timeout}ms`));
};
const timer = setTimeout(timerFn, timeout);
response.message
const hashStream = crypto.createHash('sha256').setEncoding('hex');
const passThrough = new stream.PassThrough();
response.message.pipe(passThrough);
passThrough.pipe(hashStream);
const extractStream = passThrough;
extractStream
.on('data', () => {
timer.refresh();
})
@@ -2402,7 +2240,12 @@ function streamExtractExternal(url, directory) {
.pipe(unzip_stream_1.default.Extract({ path: directory }))
.on('close', () => {
clearTimeout(timer);
resolve();
if (hashStream) {
hashStream.end();
sha256Digest = hashStream.read();
core.info(`SHA256 digest of downloaded artifact is ${sha256Digest}`);
}
resolve({ sha256Digest: `sha256:${sha256Digest}` });
})
.on('error', (error) => {
reject(error);
@@ -2415,6 +2258,7 @@ function downloadArtifactPublic(artifactId, repositoryOwner, repositoryName, tok
return __awaiter(this, void 0, void 0, function* () {
const downloadPath = yield resolveOrCreateDirectory(options === null || options === void 0 ? void 0 : options.path);
const api = github.getOctokit(token);
let digestMismatch = false;
core.info(`Downloading artifact '${artifactId}' from '${repositoryOwner}/${repositoryName}'`);
const { headers, status } = yield api.rest.actions.downloadArtifact({
owner: repositoryOwner,
@@ -2435,13 +2279,20 @@ function downloadArtifactPublic(artifactId, repositoryOwner, repositoryName, tok
core.info(`Redirecting to blob download url: ${scrubQueryParameters(location)}`);
try {
core.info(`Starting download of artifact to: ${downloadPath}`);
yield streamExtract(location, downloadPath);
const extractResponse = yield streamExtract(location, downloadPath);
core.info(`Artifact download completed successfully.`);
if (options === null || options === void 0 ? void 0 : options.expectedHash) {
if ((options === null || options === void 0 ? void 0 : options.expectedHash) !== extractResponse.sha256Digest) {
digestMismatch = true;
core.debug(`Computed digest: ${extractResponse.sha256Digest}`);
core.debug(`Expected digest: ${options.expectedHash}`);
}
}
}
catch (error) {
throw new Error(`Unable to download and extract artifact: ${error.message}`);
}
return { downloadPath };
return { downloadPath, digestMismatch };
});
}
exports.downloadArtifactPublic = downloadArtifactPublic;
@@ -2449,6 +2300,7 @@ function downloadArtifactInternal(artifactId, options) {
return __awaiter(this, void 0, void 0, function* () {
const downloadPath = yield resolveOrCreateDirectory(options === null || options === void 0 ? void 0 : options.path);
const artifactClient = (0, artifact_twirp_client_1.internalArtifactTwirpClient)();
let digestMismatch = false;
const { workflowRunBackendId, workflowJobRunBackendId } = (0, util_1.getBackendIdsFromToken)();
const listReq = {
workflowRunBackendId,
@@ -2471,13 +2323,20 @@ function downloadArtifactInternal(artifactId, options) {
core.info(`Redirecting to blob download url: ${scrubQueryParameters(signedUrl)}`);
try {
core.info(`Starting download of artifact to: ${downloadPath}`);
yield streamExtract(signedUrl, downloadPath);
const extractResponse = yield streamExtract(signedUrl, downloadPath);
core.info(`Artifact download completed successfully.`);
if (options === null || options === void 0 ? void 0 : options.expectedHash) {
if ((options === null || options === void 0 ? void 0 : options.expectedHash) !== extractResponse.sha256Digest) {
digestMismatch = true;
core.debug(`Computed digest: ${extractResponse.sha256Digest}`);
core.debug(`Expected digest: ${options.expectedHash}`);
}
}
}
catch (error) {
throw new Error(`Unable to download and extract artifact: ${error.message}`);
}
return { downloadPath };
return { downloadPath, digestMismatch };
});
}
exports.downloadArtifactInternal = downloadArtifactInternal;
@@ -2583,13 +2442,17 @@ function getArtifactPublic(artifactName, workflowRunId, repositoryOwner, reposit
name: artifact.name,
id: artifact.id,
size: artifact.size_in_bytes,
createdAt: artifact.created_at ? new Date(artifact.created_at) : undefined
createdAt: artifact.created_at
? new Date(artifact.created_at)
: undefined,
digest: artifact.digest
}
};
});
}
exports.getArtifactPublic = getArtifactPublic;
function getArtifactInternal(artifactName) {
var _a;
return __awaiter(this, void 0, void 0, function* () {
const artifactClient = (0, artifact_twirp_client_1.internalArtifactTwirpClient)();
const { workflowRunBackendId, workflowJobRunBackendId } = (0, util_1.getBackendIdsFromToken)();
@@ -2616,7 +2479,8 @@ function getArtifactInternal(artifactName) {
size: Number(artifact.size),
createdAt: artifact.createdAt
? generated_1.Timestamp.toDate(artifact.createdAt)
: undefined
: undefined,
digest: (_a = artifact.digest) === null || _a === void 0 ? void 0 : _a.value
}
};
});
@@ -2670,7 +2534,7 @@ function listArtifactsPublic(workflowRunId, repositoryOwner, repositoryName, tok
};
const github = (0, github_1.getOctokit)(token, opts, plugin_retry_1.retry, plugin_request_log_1.requestLog);
let currentPageNumber = 1;
const { data: listArtifactResponse } = yield github.rest.actions.listWorkflowRunArtifacts({
const { data: listArtifactResponse } = yield github.request('GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts', {
owner: repositoryOwner,
repo: repositoryName,
run_id: workflowRunId,
@@ -2689,14 +2553,18 @@ function listArtifactsPublic(workflowRunId, repositoryOwner, repositoryName, tok
name: artifact.name,
id: artifact.id,
size: artifact.size_in_bytes,
createdAt: artifact.created_at ? new Date(artifact.created_at) : undefined
createdAt: artifact.created_at
? new Date(artifact.created_at)
: undefined,
digest: artifact.digest
});
}
// Move to the next page
currentPageNumber++;
// Iterate over any remaining pages
for (currentPageNumber; currentPageNumber < numberOfPages; currentPageNumber++) {
currentPageNumber++;
(0, core_1.debug)(`Fetching page ${currentPageNumber} of artifact list`);
const { data: listArtifactResponse } = yield github.rest.actions.listWorkflowRunArtifacts({
const { data: listArtifactResponse } = yield github.request('GET /repos/{owner}/{repo}/actions/runs/{run_id}/artifacts', {
owner: repositoryOwner,
repo: repositoryName,
run_id: workflowRunId,
@@ -2710,7 +2578,8 @@ function listArtifactsPublic(workflowRunId, repositoryOwner, repositoryName, tok
size: artifact.size_in_bytes,
createdAt: artifact.created_at
? new Date(artifact.created_at)
: undefined
: undefined,
digest: artifact.digest
});
}
}
@@ -2733,14 +2602,18 @@ function listArtifactsInternal(latest = false) {
workflowJobRunBackendId
};
const res = yield artifactClient.ListArtifacts(req);
let artifacts = res.artifacts.map(artifact => ({
name: artifact.name,
id: Number(artifact.databaseId),
size: Number(artifact.size),
createdAt: artifact.createdAt
? generated_1.Timestamp.toDate(artifact.createdAt)
: undefined
}));
let artifacts = res.artifacts.map(artifact => {
var _a;
return ({
name: artifact.name,
id: Number(artifact.databaseId),
size: Number(artifact.size),
createdAt: artifact.createdAt
? generated_1.Timestamp.toDate(artifact.createdAt)
: undefined,
digest: (_a = artifact.digest) === null || _a === void 0 ? void 0 : _a.value
});
});
if (latest) {
artifacts = filterLatest(artifacts);
}
@@ -2852,6 +2725,7 @@ const generated_1 = __nccwpck_require__(49960);
const config_1 = __nccwpck_require__(74610);
const user_agent_1 = __nccwpck_require__(85164);
const errors_1 = __nccwpck_require__(38182);
const util_1 = __nccwpck_require__(63062);
class ArtifactHttpClient {
constructor(userAgent, maxAttempts, baseRetryIntervalMilliseconds, retryMultiplier) {
this.maxAttempts = 5;
@@ -2904,6 +2778,7 @@ class ArtifactHttpClient {
(0, core_1.debug)(`[Response] - ${response.message.statusCode}`);
(0, core_1.debug)(`Headers: ${JSON.stringify(response.message.headers, null, 2)}`);
const body = JSON.parse(rawBody);
(0, util_1.maskSecretUrls)(body);
(0, core_1.debug)(`Body: ${JSON.stringify(body, null, 2)}`);
if (this.isSuccessStatusCode(statusCode)) {
return { response, body };
@@ -2997,8 +2872,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getConcurrency = exports.getGitHubWorkspaceDir = exports.isGhes = exports.getResultsServiceUrl = exports.getRuntimeToken = exports.getUploadChunkSize = void 0;
exports.getUploadChunkTimeout = exports.getConcurrency = exports.getGitHubWorkspaceDir = exports.isGhes = exports.getResultsServiceUrl = exports.getRuntimeToken = exports.getUploadChunkSize = void 0;
const os_1 = __importDefault(__nccwpck_require__(22037));
const core_1 = __nccwpck_require__(42186);
// Used for controlling the highWaterMark value of the zip that is being streamed
// The same value is used as the chunk size that is use during upload to blob storage
function getUploadChunkSize() {
@@ -3038,18 +2914,44 @@ function getGitHubWorkspaceDir() {
return ghWorkspaceDir;
}
exports.getGitHubWorkspaceDir = getGitHubWorkspaceDir;
// Mimics behavior of azcopy: https://learn.microsoft.com/en-us/azure/storage/common/storage-use-azcopy-optimize
// If your machine has fewer than 5 CPUs, then the value of this variable is set to 32.
// Otherwise, the default value is equal to 16 multiplied by the number of CPUs. The maximum value of this variable is 300.
// The maximum value of concurrency is 300.
// This value can be changed with ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY variable.
function getConcurrency() {
const numCPUs = os_1.default.cpus().length;
if (numCPUs <= 4) {
return 32;
let concurrencyCap = 32;
if (numCPUs > 4) {
const concurrency = 16 * numCPUs;
concurrencyCap = concurrency > 300 ? 300 : concurrency;
}
const concurrency = 16 * numCPUs;
return concurrency > 300 ? 300 : concurrency;
const concurrencyOverride = process.env['ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY'];
if (concurrencyOverride) {
const concurrency = parseInt(concurrencyOverride);
if (isNaN(concurrency) || concurrency < 1) {
throw new Error('Invalid value set for ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY env variable');
}
if (concurrency < concurrencyCap) {
(0, core_1.info)(`Set concurrency based on the value set in ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY.`);
return concurrency;
}
(0, core_1.info)(`ACTIONS_ARTIFACT_UPLOAD_CONCURRENCY is higher than the cap of ${concurrencyCap} based on the number of cpus. Set it to the maximum value allowed.`);
return concurrencyCap;
}
// default concurrency to 5
return 5;
}
exports.getConcurrency = getConcurrency;
function getUploadChunkTimeout() {
const timeoutVar = process.env['ACTIONS_ARTIFACT_UPLOAD_TIMEOUT_MS'];
if (!timeoutVar) {
return 300000; // 5 minutes
}
const timeout = parseInt(timeoutVar);
if (isNaN(timeout)) {
throw new Error('Invalid value set for ACTIONS_ARTIFACT_UPLOAD_TIMEOUT_MS env variable');
}
return timeout;
}
exports.getUploadChunkTimeout = getUploadChunkTimeout;
//# sourceMappingURL=config.js.map
/***/ }),
@@ -3193,10 +3095,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.getBackendIdsFromToken = void 0;
exports.maskSecretUrls = exports.maskSigUrl = exports.getBackendIdsFromToken = void 0;
const core = __importStar(__nccwpck_require__(42186));
const config_1 = __nccwpck_require__(74610);
const jwt_decode_1 = __importDefault(__nccwpck_require__(84329));
const core_1 = __nccwpck_require__(42186);
const InvalidJwtError = new Error('Failed to get backend IDs: The provided JWT token is invalid and/or missing claims');
// uses the JWT token claims to get the
// workflow run and workflow job run backend ids
@@ -3245,6 +3148,74 @@ function getBackendIdsFromToken() {
throw InvalidJwtError;
}
exports.getBackendIdsFromToken = getBackendIdsFromToken;
/**
* Masks the `sig` parameter in a URL and sets it as a secret.
*
* @param url - The URL containing the signature parameter to mask
* @remarks
* This function attempts to parse the provided URL and identify the 'sig' query parameter.
* If found, it registers both the raw and URL-encoded signature values as secrets using
* the Actions `setSecret` API, which prevents them from being displayed in logs.
*
* The function handles errors gracefully if URL parsing fails, logging them as debug messages.
*
* @example
* ```typescript
* // Mask a signature in an Azure SAS token URL
* maskSigUrl('https://example.blob.core.windows.net/container/file.txt?sig=abc123&se=2023-01-01');
* ```
*/
function maskSigUrl(url) {
if (!url)
return;
try {
const parsedUrl = new URL(url);
const signature = parsedUrl.searchParams.get('sig');
if (signature) {
(0, core_1.setSecret)(signature);
(0, core_1.setSecret)(encodeURIComponent(signature));
}
}
catch (error) {
(0, core_1.debug)(`Failed to parse URL: ${url} ${error instanceof Error ? error.message : String(error)}`);
}
}
exports.maskSigUrl = maskSigUrl;
/**
* Masks sensitive information in URLs containing signature parameters.
* Currently supports masking 'sig' parameters in the 'signed_upload_url'
* and 'signed_download_url' properties of the provided object.
*
* @param body - The object should contain a signature
* @remarks
* This function extracts URLs from the object properties and calls maskSigUrl
* on each one to redact sensitive signature information. The function doesn't
* modify the original object; it only marks the signatures as secrets for
* logging purposes.
*
* @example
* ```typescript
* const responseBody = {
* signed_upload_url: 'https://example.com?sig=abc123',
* signed_download_url: 'https://example.com?sig=def456'
* };
* maskSecretUrls(responseBody);
* ```
*/
function maskSecretUrls(body) {
if (typeof body !== 'object' || body === null) {
(0, core_1.debug)('body is not an object or is null');
return;
}
if ('signed_upload_url' in body &&
typeof body.signed_upload_url === 'string') {
maskSigUrl(body.signed_upload_url);
}
if ('signed_url' in body && typeof body.signed_url === 'string') {
maskSigUrl(body.signed_url);
}
}
exports.maskSecretUrls = maskSecretUrls;
//# sourceMappingURL=util.js.map
/***/ }),
@@ -3298,37 +3269,34 @@ function uploadZipToBlobStorage(authenticatedUploadURL, zipUploadStream) {
return __awaiter(this, void 0, void 0, function* () {
let uploadByteCount = 0;
let lastProgressTime = Date.now();
let timeoutId;
const chunkTimer = (timeout) => {
// clear the previous timeout
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
const now = Date.now();
// if there's been more than 30 seconds since the
// last progress event, then we'll consider the upload stalled
if (now - lastProgressTime > timeout) {
throw new Error('Upload progress stalled.');
}
}, timeout);
return timeoutId;
};
const abortController = new AbortController();
const chunkTimer = (interval) => __awaiter(this, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
const timer = setInterval(() => {
if (Date.now() - lastProgressTime > interval) {
reject(new Error('Upload progress stalled.'));
}
}, interval);
abortController.signal.addEventListener('abort', () => {
clearInterval(timer);
resolve();
});
});
});
const maxConcurrency = (0, config_1.getConcurrency)();
const bufferSize = (0, config_1.getUploadChunkSize)();
const blobClient = new storage_blob_1.BlobClient(authenticatedUploadURL);
const blockBlobClient = blobClient.getBlockBlobClient();
const timeoutDuration = 300000; // 30 seconds
core.debug(`Uploading artifact zip to blob storage with maxConcurrency: ${maxConcurrency}, bufferSize: ${bufferSize}`);
const uploadCallback = (progress) => {
core.info(`Uploaded bytes ${progress.loadedBytes}`);
uploadByteCount = progress.loadedBytes;
chunkTimer(timeoutDuration);
lastProgressTime = Date.now();
};
const options = {
blobHTTPHeaders: { blobContentType: 'zip' },
onProgress: uploadCallback
onProgress: uploadCallback,
abortSignal: abortController.signal
};
let sha256Hash = undefined;
const uploadStream = new stream.PassThrough();
@@ -3337,9 +3305,10 @@ function uploadZipToBlobStorage(authenticatedUploadURL, zipUploadStream) {
zipUploadStream.pipe(hashStream).setEncoding('hex'); // This stream is used to compute a hash of the zip content that gets used. Integrity check
core.info('Beginning upload of artifact content to blob storage');
try {
// Start the chunk timer
timeoutId = chunkTimer(timeoutDuration);
yield blockBlobClient.uploadStream(uploadStream, bufferSize, maxConcurrency, options);
yield Promise.race([
blockBlobClient.uploadStream(uploadStream, bufferSize, maxConcurrency, options),
chunkTimer((0, config_1.getUploadChunkTimeout)())
]);
}
catch (error) {
if (errors_1.NetworkError.isNetworkErrorCode(error === null || error === void 0 ? void 0 : error.code)) {
@@ -3348,15 +3317,12 @@ function uploadZipToBlobStorage(authenticatedUploadURL, zipUploadStream) {
throw error;
}
finally {
// clear the timeout whether or not the upload completes
if (timeoutId) {
clearTimeout(timeoutId);
}
abortController.abort();
}
core.info('Finished uploading artifact content to blob storage!');
hashStream.end();
sha256Hash = hashStream.read();
core.info(`SHA256 hash of uploaded artifact zip is ${sha256Hash}`);
core.info(`SHA256 digest of uploaded artifact zip is ${sha256Hash}`);
if (uploadByteCount === 0) {
core.warning(`No data was uploaded to blob storage. Reported upload byte count is 0.`);
}
@@ -3607,6 +3573,7 @@ function uploadArtifact(name, files, rootDirectory, options) {
core.info(`Artifact ${name}.zip successfully finalized. Artifact ID ${artifactId}`);
return {
size: uploadResult.uploadSize,
digest: uploadResult.sha256Hash,
id: Number(artifactId)
};
});
@@ -3701,10 +3668,11 @@ function getUploadZipSpecification(filesToZip, rootDirectory) {
- file3.txt
*/
for (let file of filesToZip) {
if (!fs.existsSync(file)) {
const stats = fs.lstatSync(file, { throwIfNoEntry: false });
if (!stats) {
throw new Error(`File ${file} does not exist`);
}
if (!fs.statSync(file).isDirectory()) {
if (!stats.isDirectory()) {
// Normalize and resolve, this allows for either absolute or relative paths to be used
file = (0, path_1.normalize)(file);
file = (0, path_1.resolve)(file);
@@ -3716,7 +3684,8 @@ function getUploadZipSpecification(filesToZip, rootDirectory) {
(0, path_and_artifact_name_validation_1.validateFilePath)(uploadPath);
specification.push({
sourcePath: file,
destinationPath: uploadPath
destinationPath: uploadPath,
stats
});
}
else {
@@ -3725,7 +3694,8 @@ function getUploadZipSpecification(filesToZip, rootDirectory) {
(0, path_and_artifact_name_validation_1.validateFilePath)(directoryPath);
specification.push({
sourcePath: null,
destinationPath: directoryPath
destinationPath: directoryPath,
stats
});
}
}
@@ -3776,9 +3746,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.createZipUploadStream = exports.ZipUploadStream = exports.DEFAULT_COMPRESSION_LEVEL = void 0;
const stream = __importStar(__nccwpck_require__(12781));
const promises_1 = __nccwpck_require__(73292);
const archiver = __importStar(__nccwpck_require__(43084));
const core = __importStar(__nccwpck_require__(42186));
const fs_1 = __nccwpck_require__(57147);
const config_1 = __nccwpck_require__(74610);
exports.DEFAULT_COMPRESSION_LEVEL = 6;
// Custom stream transformer so we can set the highWaterMark property
@@ -3809,8 +3779,13 @@ function createZipUploadStream(uploadSpecification, compressionLevel = exports.D
zip.on('end', zipEndCallback);
for (const file of uploadSpecification) {
if (file.sourcePath !== null) {
// Add a normal file to the zip
zip.append((0, fs_1.createReadStream)(file.sourcePath), {
// Check if symlink and resolve the source path
let sourcePath = file.sourcePath;
if (file.stats.isSymbolicLink()) {
sourcePath = yield (0, promises_1.realpath)(file.sourcePath);
}
// Add the file to the zip
zip.file(sourcePath, {
name: file.destinationPath
});
}
@@ -48110,6 +48085,7 @@ const json_format_contract_1 = __nccwpck_require__(48139);
const reflection_equals_1 = __nccwpck_require__(39473);
const binary_writer_1 = __nccwpck_require__(44354);
const binary_reader_1 = __nccwpck_require__(65210);
const baseDescriptors = Object.getOwnPropertyDescriptors(Object.getPrototypeOf({}));
/**
* This standard message type provides reflection-based
* operations to work with a message.
@@ -48120,7 +48096,7 @@ class MessageType {
this.typeName = name;
this.fields = fields.map(reflection_info_1.normalizeFieldInfo);
this.options = options !== null && options !== void 0 ? options : {};
this.messagePrototype = Object.defineProperty({}, message_type_contract_1.MESSAGE_TYPE, { value: this });
this.messagePrototype = Object.create(null, Object.assign(Object.assign({}, baseDescriptors), { [message_type_contract_1.MESSAGE_TYPE]: { value: this } }));
this.refTypeCheck = new reflection_type_check_1.ReflectionTypeCheck(this);
this.refJsonReader = new reflection_json_reader_1.ReflectionJsonReader(this);
this.refJsonWriter = new reflection_json_writer_1.ReflectionJsonWriter(this);
@@ -64211,599 +64187,6 @@ class Deprecation extends Error {
exports.Deprecation = Deprecation;
/***/ }),
/***/ 13598:
/***/ ((module) => {
"use strict";
function _process (v, mod) {
var i
var r
if (typeof mod === 'function') {
r = mod(v)
if (r !== undefined) {
v = r
}
} else if (Array.isArray(mod)) {
for (i = 0; i < mod.length; i++) {
r = mod[i](v)
if (r !== undefined) {
v = r
}
}
}
return v
}
function parseKey (key, val) {
// detect negative index notation
if (key[0] === '-' && Array.isArray(val) && /^-\d+$/.test(key)) {
return val.length + parseInt(key, 10)
}
return key
}
function isIndex (k) {
return /^\d+$/.test(k)
}
function isObject (val) {
return Object.prototype.toString.call(val) === '[object Object]'
}
function isArrayOrObject (val) {
return Object(val) === val
}
function isEmptyObject (val) {
return Object.keys(val).length === 0
}
var blacklist = ['__proto__', 'prototype', 'constructor']
var blacklistFilter = function (part) { return blacklist.indexOf(part) === -1 }
function parsePath (path, sep) {
if (path.indexOf('[') >= 0) {
path = path.replace(/\[/g, sep).replace(/]/g, '')
}
var parts = path.split(sep)
var check = parts.filter(blacklistFilter)
if (check.length !== parts.length) {
throw Error('Refusing to update blacklisted property ' + path)
}
return parts
}
var hasOwnProperty = Object.prototype.hasOwnProperty
function DotObject (separator, override, useArray, useBrackets) {
if (!(this instanceof DotObject)) {
return new DotObject(separator, override, useArray, useBrackets)
}
if (typeof override === 'undefined') override = false
if (typeof useArray === 'undefined') useArray = true
if (typeof useBrackets === 'undefined') useBrackets = true
this.separator = separator || '.'
this.override = override
this.useArray = useArray
this.useBrackets = useBrackets
this.keepArray = false
// contains touched arrays
this.cleanup = []
}
var dotDefault = new DotObject('.', false, true, true)
function wrap (method) {
return function () {
return dotDefault[method].apply(dotDefault, arguments)
}
}
DotObject.prototype._fill = function (a, obj, v, mod) {
var k = a.shift()
if (a.length > 0) {
obj[k] = obj[k] || (this.useArray && isIndex(a[0]) ? [] : {})
if (!isArrayOrObject(obj[k])) {
if (this.override) {
obj[k] = {}
} else {
if (!(isArrayOrObject(v) && isEmptyObject(v))) {
throw new Error(
'Trying to redefine `' + k + '` which is a ' + typeof obj[k]
)
}
return
}
}
this._fill(a, obj[k], v, mod)
} else {
if (!this.override && isArrayOrObject(obj[k]) && !isEmptyObject(obj[k])) {
if (!(isArrayOrObject(v) && isEmptyObject(v))) {
throw new Error("Trying to redefine non-empty obj['" + k + "']")
}
return
}
obj[k] = _process(v, mod)
}
}
/**
*
* Converts an object with dotted-key/value pairs to it's expanded version
*
* Optionally transformed by a set of modifiers.
*
* Usage:
*
* var row = {
* 'nr': 200,
* 'doc.name': ' My Document '
* }
*
* var mods = {
* 'doc.name': [_s.trim, _s.underscored]
* }
*
* dot.object(row, mods)
*
* @param {Object} obj
* @param {Object} mods
*/
DotObject.prototype.object = function (obj, mods) {
var self = this
Object.keys(obj).forEach(function (k) {
var mod = mods === undefined ? null : mods[k]
// normalize array notation.
var ok = parsePath(k, self.separator).join(self.separator)
if (ok.indexOf(self.separator) !== -1) {
self._fill(ok.split(self.separator), obj, obj[k], mod)
delete obj[k]
} else {
obj[k] = _process(obj[k], mod)
}
})
return obj
}
/**
* @param {String} path dotted path
* @param {String} v value to be set
* @param {Object} obj object to be modified
* @param {Function|Array} mod optional modifier
*/
DotObject.prototype.str = function (path, v, obj, mod) {
var ok = parsePath(path, this.separator).join(this.separator)
if (path.indexOf(this.separator) !== -1) {
this._fill(ok.split(this.separator), obj, v, mod)
} else {
obj[path] = _process(v, mod)
}
return obj
}
/**
*
* Pick a value from an object using dot notation.
*
* Optionally remove the value
*
* @param {String} path
* @param {Object} obj
* @param {Boolean} remove
*/
DotObject.prototype.pick = function (path, obj, remove, reindexArray) {
var i
var keys
var val
var key
var cp
keys = parsePath(path, this.separator)
for (i = 0; i < keys.length; i++) {
key = parseKey(keys[i], obj)
if (obj && typeof obj === 'object' && key in obj) {
if (i === keys.length - 1) {
if (remove) {
val = obj[key]
if (reindexArray && Array.isArray(obj)) {
obj.splice(key, 1)
} else {
delete obj[key]
}
if (Array.isArray(obj)) {
cp = keys.slice(0, -1).join('.')
if (this.cleanup.indexOf(cp) === -1) {
this.cleanup.push(cp)
}
}
return val
} else {
return obj[key]
}
} else {
obj = obj[key]
}
} else {
return undefined
}
}
if (remove && Array.isArray(obj)) {
obj = obj.filter(function (n) {
return n !== undefined
})
}
return obj
}
/**
*
* Delete value from an object using dot notation.
*
* @param {String} path
* @param {Object} obj
* @return {any} The removed value
*/
DotObject.prototype.delete = function (path, obj) {
return this.remove(path, obj, true)
}
/**
*
* Remove value from an object using dot notation.
*
* Will remove multiple items if path is an array.
* In this case array indexes will be retained until all
* removals have been processed.
*
* Use dot.delete() to automatically re-index arrays.
*
* @param {String|Array<String>} path
* @param {Object} obj
* @param {Boolean} reindexArray
* @return {any} The removed value
*/
DotObject.prototype.remove = function (path, obj, reindexArray) {
var i
this.cleanup = []
if (Array.isArray(path)) {
for (i = 0; i < path.length; i++) {
this.pick(path[i], obj, true, reindexArray)
}
if (!reindexArray) {
this._cleanup(obj)
}
return obj
} else {
return this.pick(path, obj, true, reindexArray)
}
}
DotObject.prototype._cleanup = function (obj) {
var ret
var i
var keys
var root
if (this.cleanup.length) {
for (i = 0; i < this.cleanup.length; i++) {
keys = this.cleanup[i].split('.')
root = keys.splice(0, -1).join('.')
ret = root ? this.pick(root, obj) : obj
ret = ret[keys[0]].filter(function (v) {
return v !== undefined
})
this.set(this.cleanup[i], ret, obj)
}
this.cleanup = []
}
}
/**
* Alias method for `dot.remove`
*
* Note: this is not an alias for dot.delete()
*
* @param {String|Array<String>} path
* @param {Object} obj
* @param {Boolean} reindexArray
* @return {any} The removed value
*/
DotObject.prototype.del = DotObject.prototype.remove
/**
*
* Move a property from one place to the other.
*
* If the source path does not exist (undefined)
* the target property will not be set.
*
* @param {String} source
* @param {String} target
* @param {Object} obj
* @param {Function|Array} mods
* @param {Boolean} merge
*/
DotObject.prototype.move = function (source, target, obj, mods, merge) {
if (typeof mods === 'function' || Array.isArray(mods)) {
this.set(target, _process(this.pick(source, obj, true), mods), obj, merge)
} else {
merge = mods
this.set(target, this.pick(source, obj, true), obj, merge)
}
return obj
}
/**
*
* Transfer a property from one object to another object.
*
* If the source path does not exist (undefined)
* the property on the other object will not be set.
*
* @param {String} source
* @param {String} target
* @param {Object} obj1
* @param {Object} obj2
* @param {Function|Array} mods
* @param {Boolean} merge
*/
DotObject.prototype.transfer = function (
source,
target,
obj1,
obj2,
mods,
merge
) {
if (typeof mods === 'function' || Array.isArray(mods)) {
this.set(
target,
_process(this.pick(source, obj1, true), mods),
obj2,
merge
)
} else {
merge = mods
this.set(target, this.pick(source, obj1, true), obj2, merge)
}
return obj2
}
/**
*
* Copy a property from one object to another object.
*
* If the source path does not exist (undefined)
* the property on the other object will not be set.
*
* @param {String} source
* @param {String} target
* @param {Object} obj1
* @param {Object} obj2
* @param {Function|Array} mods
* @param {Boolean} merge
*/
DotObject.prototype.copy = function (source, target, obj1, obj2, mods, merge) {
if (typeof mods === 'function' || Array.isArray(mods)) {
this.set(
target,
_process(
// clone what is picked
JSON.parse(JSON.stringify(this.pick(source, obj1, false))),
mods
),
obj2,
merge
)
} else {
merge = mods
this.set(target, this.pick(source, obj1, false), obj2, merge)
}
return obj2
}
/**
*
* Set a property on an object using dot notation.
*
* @param {String} path
* @param {any} val
* @param {Object} obj
* @param {Boolean} merge
*/
DotObject.prototype.set = function (path, val, obj, merge) {
var i
var k
var keys
var key
// Do not operate if the value is undefined.
if (typeof val === 'undefined') {
return obj
}
keys = parsePath(path, this.separator)
for (i = 0; i < keys.length; i++) {
key = keys[i]
if (i === keys.length - 1) {
if (merge && isObject(val) && isObject(obj[key])) {
for (k in val) {
if (hasOwnProperty.call(val, k)) {
obj[key][k] = val[k]
}
}
} else if (merge && Array.isArray(obj[key]) && Array.isArray(val)) {
for (var j = 0; j < val.length; j++) {
obj[keys[i]].push(val[j])
}
} else {
obj[key] = val
}
} else if (
// force the value to be an object
!hasOwnProperty.call(obj, key) ||
(!isObject(obj[key]) && !Array.isArray(obj[key]))
) {
// initialize as array if next key is numeric
if (/^\d+$/.test(keys[i + 1])) {
obj[key] = []
} else {
obj[key] = {}
}
}
obj = obj[key]
}
return obj
}
/**
*
* Transform an object
*
* Usage:
*
* var obj = {
* "id": 1,
* "some": {
* "thing": "else"
* }
* }
*
* var transform = {
* "id": "nr",
* "some.thing": "name"
* }
*
* var tgt = dot.transform(transform, obj)
*
* @param {Object} recipe Transform recipe
* @param {Object} obj Object to be transformed
* @param {Array} mods modifiers for the target
*/
DotObject.prototype.transform = function (recipe, obj, tgt) {
obj = obj || {}
tgt = tgt || {}
Object.keys(recipe).forEach(
function (key) {
this.set(recipe[key], this.pick(key, obj), tgt)
}.bind(this)
)
return tgt
}
/**
*
* Convert object to dotted-key/value pair
*
* Usage:
*
* var tgt = dot.dot(obj)
*
* or
*
* var tgt = {}
* dot.dot(obj, tgt)
*
* @param {Object} obj source object
* @param {Object} tgt target object
* @param {Array} path path array (internal)
*/
DotObject.prototype.dot = function (obj, tgt, path) {
tgt = tgt || {}
path = path || []
var isArray = Array.isArray(obj)
Object.keys(obj).forEach(
function (key) {
var index = isArray && this.useBrackets ? '[' + key + ']' : key
if (
isArrayOrObject(obj[key]) &&
((isObject(obj[key]) && !isEmptyObject(obj[key])) ||
(Array.isArray(obj[key]) && !this.keepArray && obj[key].length !== 0))
) {
if (isArray && this.useBrackets) {
var previousKey = path[path.length - 1] || ''
return this.dot(
obj[key],
tgt,
path.slice(0, -1).concat(previousKey + index)
)
} else {
return this.dot(obj[key], tgt, path.concat(index))
}
} else {
if (isArray && this.useBrackets) {
tgt[path.join(this.separator).concat('[' + key + ']')] = obj[key]
} else {
tgt[path.concat(index).join(this.separator)] = obj[key]
}
}
}.bind(this)
)
return tgt
}
DotObject.pick = wrap('pick')
DotObject.move = wrap('move')
DotObject.transfer = wrap('transfer')
DotObject.transform = wrap('transform')
DotObject.copy = wrap('copy')
DotObject.object = wrap('object')
DotObject.str = wrap('str')
DotObject.set = wrap('set')
DotObject.delete = wrap('delete')
DotObject.del = DotObject.remove = wrap('remove')
DotObject.dot = wrap('dot');
['override', 'overwrite'].forEach(function (prop) {
Object.defineProperty(DotObject, prop, {
get: function () {
return dotDefault.override
},
set: function (val) {
dotDefault.override = !!val
}
})
});
['useArray', 'keepArray', 'useBrackets'].forEach(function (prop) {
Object.defineProperty(DotObject, prop, {
get: function () {
return dotDefault[prop]
},
set: function (val) {
dotDefault[prop] = val
}
})
})
DotObject._process = _process
module.exports = DotObject
/***/ }),
/***/ 84697:
@@ -88211,1152 +87594,6 @@ if (process.env.NODE_DEBUG && /\btunnel\b/.test(process.env.NODE_DEBUG)) {
exports.debug = debug; // for test
/***/ }),
/***/ 31524:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
/***/ }),
/***/ 66647:
/***/ ((__unused_webpack_module, exports) => {
"use strict";
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.isValidErrorCode = exports.httpStatusFromErrorCode = exports.TwirpErrorCode = exports.BadRouteError = exports.InternalServerErrorWith = exports.InternalServerError = exports.RequiredArgumentError = exports.InvalidArgumentError = exports.NotFoundError = exports.TwirpError = void 0;
/**
* Represents a twirp error
*/
class TwirpError extends Error {
constructor(code, msg) {
super(msg);
this.code = TwirpErrorCode.Internal;
this.meta = {};
this.code = code;
this.msg = msg;
Object.setPrototypeOf(this, TwirpError.prototype);
}
/**
* Adds a metadata kv to the error
* @param key
* @param value
*/
withMeta(key, value) {
this.meta[key] = value;
return this;
}
/**
* Returns a single metadata value
* return "" if not found
* @param key
*/
getMeta(key) {
return this.meta[key] || "";
}
/**
* Add the original error cause
* @param err
* @param addMeta
*/
withCause(err, addMeta = false) {
this._originalCause = err;
if (addMeta) {
this.withMeta("cause", err.message);
}
return this;
}
cause() {
return this._originalCause;
}
/**
* Returns the error representation to JSON
*/
toJSON() {
try {
return JSON.stringify({
code: this.code,
msg: this.msg,
meta: this.meta,
});
}
catch (e) {
return `{"code": "internal", "msg": "There was an error but it could not be serialized into JSON"}`;
}
}
/**
* Create a twirp error from an object
* @param obj
*/
static fromObject(obj) {
const code = obj["code"] || TwirpErrorCode.Unknown;
const msg = obj["msg"] || "unknown";
const error = new TwirpError(code, msg);
if (obj["meta"]) {
Object.keys(obj["meta"]).forEach((key) => {
error.withMeta(key, obj["meta"][key]);
});
}
return error;
}
}
exports.TwirpError = TwirpError;
/**
* NotFoundError constructor for the common NotFound error.
*/
class NotFoundError extends TwirpError {
constructor(msg) {
super(TwirpErrorCode.NotFound, msg);
}
}
exports.NotFoundError = NotFoundError;
/**
* InvalidArgumentError constructor for the common InvalidArgument error. Can be
* used when an argument has invalid format, is a number out of range, is a bad
* option, etc).
*/
class InvalidArgumentError extends TwirpError {
constructor(argument, validationMsg) {
super(TwirpErrorCode.InvalidArgument, argument + " " + validationMsg);
this.withMeta("argument", argument);
}
}
exports.InvalidArgumentError = InvalidArgumentError;
/**
* RequiredArgumentError is a more specific constructor for InvalidArgument
* error. Should be used when the argument is required (expected to have a
* non-zero value).
*/
class RequiredArgumentError extends InvalidArgumentError {
constructor(argument) {
super(argument, "is required");
}
}
exports.RequiredArgumentError = RequiredArgumentError;
/**
* InternalError constructor for the common Internal error. Should be used to
* specify that something bad or unexpected happened.
*/
class InternalServerError extends TwirpError {
constructor(msg) {
super(TwirpErrorCode.Internal, msg);
}
}
exports.InternalServerError = InternalServerError;
/**
* InternalErrorWith makes an internal error, wrapping the original error and using it
* for the error message, and with metadata "cause" with the original error type.
* This function is used by Twirp services to wrap non-Twirp errors as internal errors.
* The wrapped error can be extracted later with err.cause()
*/
class InternalServerErrorWith extends InternalServerError {
constructor(err) {
super(err.message);
this.withMeta("cause", err.name);
this.withCause(err);
}
}
exports.InternalServerErrorWith = InternalServerErrorWith;
/**
* A standard BadRoute Error
*/
class BadRouteError extends TwirpError {
constructor(msg, method, url) {
super(TwirpErrorCode.BadRoute, msg);
this.withMeta("twirp_invalid_route", method + " " + url);
}
}
exports.BadRouteError = BadRouteError;
var TwirpErrorCode;
(function (TwirpErrorCode) {
// Canceled indicates the operation was cancelled (typically by the caller).
TwirpErrorCode["Canceled"] = "canceled";
// Unknown error. For example when handling errors raised by APIs that do not
// return enough error information.
TwirpErrorCode["Unknown"] = "unknown";
// InvalidArgument indicates client specified an invalid argument. It
// indicates arguments that are problematic regardless of the state of the
// system (i.e. a malformed file name, required argument, number out of range,
// etc.).
TwirpErrorCode["InvalidArgument"] = "invalid_argument";
// Malformed indicates an error occurred while decoding the client's request.
// This may mean that the message was encoded improperly, or that there is a
// disagreement in message format between the client and server.
TwirpErrorCode["Malformed"] = "malformed";
// DeadlineExceeded means operation expired before completion. For operations
// that change the state of the system, this error may be returned even if the
// operation has completed successfully (timeout).
TwirpErrorCode["DeadlineExceeded"] = "deadline_exceeded";
// NotFound means some requested entity was not found.
TwirpErrorCode["NotFound"] = "not_found";
// BadRoute means that the requested URL path wasn't routable to a Twirp
// service and method. This is returned by the generated server, and usually
// shouldn't be returned by applications. Instead, applications should use
// NotFound or Unimplemented.
TwirpErrorCode["BadRoute"] = "bad_route";
// AlreadyExists means an attempt to create an entity failed because one
// already exists.
TwirpErrorCode["AlreadyExists"] = "already_exists";
// PermissionDenied indicates the caller does not have permission to execute
// the specified operation. It must not be used if the caller cannot be
// identified (Unauthenticated).
TwirpErrorCode["PermissionDenied"] = "permission_denied";
// Unauthenticated indicates the request does not have valid authentication
// credentials for the operation.
TwirpErrorCode["Unauthenticated"] = "unauthenticated";
// ResourceExhausted indicates some resource has been exhausted, perhaps a
// per-user quota, or perhaps the entire file system is out of space.
TwirpErrorCode["ResourceExhausted"] = "resource_exhausted";
// FailedPrecondition indicates operation was rejected because the system is
// not in a state required for the operation's execution. For example, doing
// an rmdir operation on a directory that is non-empty, or on a non-directory
// object, or when having conflicting read-modify-write on the same resource.
TwirpErrorCode["FailedPrecondition"] = "failed_precondition";
// Aborted indicates the operation was aborted, typically due to a concurrency
// issue like sequencer check failures, transaction aborts, etc.
TwirpErrorCode["Aborted"] = "aborted";
// OutOfRange means operation was attempted past the valid range. For example,
// seeking or reading past end of a paginated collection.
//
// Unlike InvalidArgument, this error indicates a problem that may be fixed if
// the system state changes (i.e. adding more items to the collection).
//
// There is a fair bit of overlap between FailedPrecondition and OutOfRange.
// We recommend using OutOfRange (the more specific error) when it applies so
// that callers who are iterating through a space can easily look for an
// OutOfRange error to detect when they are done.
TwirpErrorCode["OutOfRange"] = "out_of_range";
// Unimplemented indicates operation is not implemented or not
// supported/enabled in this service.
TwirpErrorCode["Unimplemented"] = "unimplemented";
// Internal errors. When some invariants expected by the underlying system
// have been broken. In other words, something bad happened in the library or
// backend service. Do not confuse with HTTP Internal Server Error; an
// Internal error could also happen on the client code, i.e. when parsing a
// server response.
TwirpErrorCode["Internal"] = "internal";
// Unavailable indicates the service is currently unavailable. This is a most
// likely a transient condition and may be corrected by retrying with a
// backoff.
TwirpErrorCode["Unavailable"] = "unavailable";
// DataLoss indicates unrecoverable data loss or corruption.
TwirpErrorCode["DataLoss"] = "data_loss";
})(TwirpErrorCode = exports.TwirpErrorCode || (exports.TwirpErrorCode = {}));
// ServerHTTPStatusFromErrorCode maps a Twirp error type into a similar HTTP
// response status. It is used by the Twirp server handler to set the HTTP
// response status code. Returns 0 if the ErrorCode is invalid.
function httpStatusFromErrorCode(code) {
switch (code) {
case TwirpErrorCode.Canceled:
return 408; // RequestTimeout
case TwirpErrorCode.Unknown:
return 500; // Internal Server Error
case TwirpErrorCode.InvalidArgument:
return 400; // BadRequest
case TwirpErrorCode.Malformed:
return 400; // BadRequest
case TwirpErrorCode.DeadlineExceeded:
return 408; // RequestTimeout
case TwirpErrorCode.NotFound:
return 404; // Not Found
case TwirpErrorCode.BadRoute:
return 404; // Not Found
case TwirpErrorCode.AlreadyExists:
return 409; // Conflict
case TwirpErrorCode.PermissionDenied:
return 403; // Forbidden
case TwirpErrorCode.Unauthenticated:
return 401; // Unauthorized
case TwirpErrorCode.ResourceExhausted:
return 429; // Too Many Requests
case TwirpErrorCode.FailedPrecondition:
return 412; // Precondition Failed
case TwirpErrorCode.Aborted:
return 409; // Conflict
case TwirpErrorCode.OutOfRange:
return 400; // Bad Request
case TwirpErrorCode.Unimplemented:
return 501; // Not Implemented
case TwirpErrorCode.Internal:
return 500; // Internal Server Error
case TwirpErrorCode.Unavailable:
return 503; // Service Unavailable
case TwirpErrorCode.DataLoss:
return 500; // Internal Server Error
default:
return 0; // Invalid!
}
}
exports.httpStatusFromErrorCode = httpStatusFromErrorCode;
// IsValidErrorCode returns true if is one of the valid predefined constants.
function isValidErrorCode(code) {
return httpStatusFromErrorCode(code) != 0;
}
exports.isValidErrorCode = isValidErrorCode;
/***/ }),
/***/ 56748:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.Gateway = exports.Pattern = void 0;
const querystring_1 = __nccwpck_require__(63477);
const dotObject = __importStar(__nccwpck_require__(13598));
const request_1 = __nccwpck_require__(8347);
const errors_1 = __nccwpck_require__(66647);
const http_client_1 = __nccwpck_require__(94091);
const server_1 = __nccwpck_require__(26604);
var Pattern;
(function (Pattern) {
Pattern["POST"] = "post";
Pattern["GET"] = "get";
Pattern["PATCH"] = "patch";
Pattern["PUT"] = "put";
Pattern["DELETE"] = "delete";
})(Pattern = exports.Pattern || (exports.Pattern = {}));
/**
* The Gateway proxies http requests to Twirp Compliant
* handlers
*/
class Gateway {
constructor(routes) {
this.routes = routes;
}
/**
* Middleware that rewrite the current request
* to a Twirp compliant request
*/
twirpRewrite(prefix = "/twirp") {
return (req, resp, next) => {
this.rewrite(req, resp, prefix)
.then(() => next())
.catch((e) => {
if (e instanceof errors_1.TwirpError) {
if (e.code !== errors_1.TwirpErrorCode.NotFound) {
server_1.writeError(resp, e);
}
else {
next();
}
}
});
};
}
/**
* Rewrite an incoming request to a Twirp compliant request
* @param req
* @param resp
* @param prefix
*/
rewrite(req, resp, prefix = "/twirp") {
return __awaiter(this, void 0, void 0, function* () {
const [match, route] = this.matchRoute(req);
const body = yield this.prepareTwirpBody(req, match, route);
const twirpUrl = `${prefix}/${route.packageName}.${route.serviceName}/${route.methodName}`;
req.url = twirpUrl;
req.originalUrl = twirpUrl;
req.method = "POST";
req.headers["content-type"] = "application/json";
req.rawBody = Buffer.from(JSON.stringify(body));
if (route.responseBodyKey) {
const endFn = resp.end.bind(resp);
resp.end = function (chunk) {
if (resp.statusCode === 200) {
endFn(`{ "${route.responseBodyKey}": ${chunk} }`);
}
else {
endFn(chunk);
}
};
}
});
}
/**
* Create a reverse proxy handler to
* proxy http requests to Twirp Compliant handlers
* @param httpClientOption
*/
reverseProxy(httpClientOption) {
const client = http_client_1.NodeHttpRPC(httpClientOption);
return (req, res) => __awaiter(this, void 0, void 0, function* () {
try {
const [match, route] = this.matchRoute(req);
const body = yield this.prepareTwirpBody(req, match, route);
const response = yield client.request(`${route.packageName}.${route.serviceName}`, route.methodName, "application/json", body);
res.statusCode = 200;
res.setHeader("content-type", "application/json");
let jsonResponse;
if (route.responseBodyKey) {
jsonResponse = JSON.stringify({ [route.responseBodyKey]: response });
}
else {
jsonResponse = JSON.stringify(response);
}
res.end(jsonResponse);
}
catch (e) {
server_1.writeError(res, e);
}
});
}
/**
* Prepares twirp body requests using http.google.annotions
* compliant spec
*
* @param req
* @param match
* @param route
* @protected
*/
prepareTwirpBody(req, match, route) {
return __awaiter(this, void 0, void 0, function* () {
const _a = match.params, { query_string } = _a, params = __rest(_a, ["query_string"]);
let requestBody = Object.assign({}, params);
if (query_string && route.bodyKey !== "*") {
const queryParams = this.parseQueryString(query_string);
requestBody = Object.assign(Object.assign({}, queryParams), requestBody);
}
let body = {};
if (route.bodyKey) {
const data = yield request_1.getRequestData(req);
try {
const jsonBody = JSON.parse(data.toString() || "{}");
if (route.bodyKey === "*") {
body = jsonBody;
}
else {
body[route.bodyKey] = jsonBody;
}
}
catch (e) {
const msg = "the json request could not be decoded";
throw new errors_1.TwirpError(errors_1.TwirpErrorCode.Malformed, msg).withCause(e, true);
}
}
return Object.assign(Object.assign({}, body), requestBody);
});
}
/**
* Matches a route
* @param req
*/
matchRoute(req) {
var _a;
const httpMethod = (_a = req.method) === null || _a === void 0 ? void 0 : _a.toLowerCase();
if (!httpMethod) {
throw new errors_1.BadRouteError(`method not allowed`, req.method || "", req.url || "");
}
const routes = this.routes[httpMethod];
for (const route of routes) {
const match = route.matcher(req.url || "/");
if (match) {
return [match, route];
}
}
throw new errors_1.NotFoundError(`url ${req.url} not found`);
}
/**
* Parse query string
* @param queryString
*/
parseQueryString(queryString) {
const queryParams = querystring_1.parse(queryString.replace("?", ""));
return dotObject.object(queryParams);
}
}
exports.Gateway = Gateway;
/***/ }),
/***/ 4263:
/***/ (function(__unused_webpack_module, exports) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.isHook = exports.chainHooks = void 0;
// ChainHooks creates a new ServerHook which chains the callbacks in
// each of the constituent hooks passed in. Each hook function will be
// called in the order of the ServerHooks values passed in.
//
// For the erroring hooks, RequestReceived and RequestRouted, any returned
// errors prevent processing by later hooks.
function chainHooks(...hooks) {
if (hooks.length === 0) {
return null;
}
if (hooks.length === 1) {
return hooks[0];
}
const serverHook = {
requestReceived(ctx) {
return __awaiter(this, void 0, void 0, function* () {
for (const hook of hooks) {
if (!hook.requestReceived) {
continue;
}
yield hook.requestReceived(ctx);
}
});
},
requestPrepared(ctx) {
return __awaiter(this, void 0, void 0, function* () {
for (const hook of hooks) {
if (!hook.requestPrepared) {
continue;
}
console.warn("hook requestPrepared is deprecated and will be removed in the next release. " +
"Please use responsePrepared instead.");
yield hook.requestPrepared(ctx);
}
});
},
responsePrepared(ctx) {
return __awaiter(this, void 0, void 0, function* () {
for (const hook of hooks) {
if (!hook.responsePrepared) {
continue;
}
yield hook.responsePrepared(ctx);
}
});
},
requestSent(ctx) {
return __awaiter(this, void 0, void 0, function* () {
for (const hook of hooks) {
if (!hook.requestSent) {
continue;
}
console.warn("hook requestSent is deprecated and will be removed in the next release. " +
"Please use responseSent instead.");
yield hook.requestSent(ctx);
}
});
},
responseSent(ctx) {
return __awaiter(this, void 0, void 0, function* () {
for (const hook of hooks) {
if (!hook.responseSent) {
continue;
}
yield hook.responseSent(ctx);
}
});
},
requestRouted(ctx) {
return __awaiter(this, void 0, void 0, function* () {
for (const hook of hooks) {
if (!hook.requestRouted) {
continue;
}
yield hook.requestRouted(ctx);
}
});
},
error(ctx, err) {
return __awaiter(this, void 0, void 0, function* () {
for (const hook of hooks) {
if (!hook.error) {
continue;
}
yield hook.error(ctx, err);
}
});
},
};
return serverHook;
}
exports.chainHooks = chainHooks;
function isHook(object) {
return ("requestReceived" in object ||
"requestPrepared" in object ||
"requestSent" in object ||
"requestRouted" in object ||
"responsePrepared" in object ||
"responseSent" in object ||
"error" in object);
}
exports.isHook = isHook;
/***/ }),
/***/ 94091:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.FetchRPC = exports.wrapErrorResponseToTwirpError = exports.NodeHttpRPC = void 0;
const http = __importStar(__nccwpck_require__(13685));
const https = __importStar(__nccwpck_require__(95687));
const url_1 = __nccwpck_require__(57310);
const errors_1 = __nccwpck_require__(66647);
/**
* a node HTTP RPC implementation
* @param options
* @constructor
*/
const NodeHttpRPC = (options) => ({
request(service, method, contentType, data) {
let client;
return new Promise((resolve, rejected) => {
const responseChunks = [];
const requestData = contentType === "application/protobuf"
? Buffer.from(data)
: JSON.stringify(data);
const url = new url_1.URL(options.baseUrl);
const isHttps = url.protocol === "https:";
if (isHttps) {
client = https;
}
else {
client = http;
}
const prefix = url.pathname !== "/" ? url.pathname : "";
const req = client
.request(Object.assign(Object.assign({}, (options ? options : {})), { method: "POST", protocol: url.protocol, host: url.hostname, port: url.port ? url.port : isHttps ? 443 : 80, path: `${prefix}/${service}/${method}`, headers: Object.assign(Object.assign({}, (options.headers ? options.headers : {})), { "Content-Type": contentType, "Content-Length": contentType === "application/protobuf"
? Buffer.byteLength(requestData)
: Buffer.from(requestData).byteLength }) }), (res) => {
res.on("data", (chunk) => responseChunks.push(chunk));
res.on("end", () => {
const data = Buffer.concat(responseChunks);
if (res.statusCode != 200) {
rejected(wrapErrorResponseToTwirpError(data.toString()));
}
else {
if (contentType === "application/json") {
resolve(JSON.parse(data.toString()));
}
else {
resolve(data);
}
}
});
res.on("error", (err) => {
rejected(err);
});
})
.on("error", (err) => {
rejected(err);
});
req.end(requestData);
});
},
});
exports.NodeHttpRPC = NodeHttpRPC;
function wrapErrorResponseToTwirpError(errorResponse) {
return errors_1.TwirpError.fromObject(JSON.parse(errorResponse));
}
exports.wrapErrorResponseToTwirpError = wrapErrorResponseToTwirpError;
/**
* a browser fetch RPC implementation
*/
const FetchRPC = (options) => ({
request(service, method, contentType, data) {
return __awaiter(this, void 0, void 0, function* () {
const headers = new Headers(options.headers);
headers.set("content-type", contentType);
const response = yield fetch(`${options.baseUrl}/${service}/${method}`, Object.assign(Object.assign({}, options), { method: "POST", headers, body: data instanceof Uint8Array ? data : JSON.stringify(data) }));
if (response.status === 200) {
if (contentType === "application/json") {
return yield response.json();
}
return new Uint8Array(yield response.arrayBuffer());
}
throw errors_1.TwirpError.fromObject(yield response.json());
});
},
});
exports.FetchRPC = FetchRPC;
/***/ }),
/***/ 66465:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __exportStar = (this && this.__exportStar) || function(m, exports) {
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.TwirpContentType = void 0;
__exportStar(__nccwpck_require__(31524), exports);
__exportStar(__nccwpck_require__(26604), exports);
__exportStar(__nccwpck_require__(48913), exports);
__exportStar(__nccwpck_require__(4263), exports);
__exportStar(__nccwpck_require__(66647), exports);
__exportStar(__nccwpck_require__(56748), exports);
__exportStar(__nccwpck_require__(94091), exports);
var request_1 = __nccwpck_require__(8347);
Object.defineProperty(exports, "TwirpContentType", ({ enumerable: true, get: function () { return request_1.TwirpContentType; } }));
/***/ }),
/***/ 48913:
/***/ (function(__unused_webpack_module, exports) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.chainInterceptors = void 0;
// chains multiple Interceptors into a single Interceptor.
// The first interceptor wraps the second one, and so on.
// Returns null if interceptors is empty.
function chainInterceptors(...interceptors) {
if (interceptors.length === 0) {
return;
}
if (interceptors.length === 1) {
return interceptors[0];
}
const first = interceptors[0];
return (ctx, request, handler) => __awaiter(this, void 0, void 0, function* () {
let next = handler;
for (let i = interceptors.length - 1; i > 0; i--) {
next = ((next) => (ctx, typedRequest) => {
return interceptors[i](ctx, typedRequest, next);
})(next);
}
return first(ctx, request, next);
});
}
exports.chainInterceptors = chainInterceptors;
/***/ }),
/***/ 8347:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.parseTwirpPath = exports.getRequestData = exports.validateRequest = exports.getContentType = exports.TwirpContentType = void 0;
const errors_1 = __nccwpck_require__(66647);
/**
* Supported Twirp Content-Type
*/
var TwirpContentType;
(function (TwirpContentType) {
TwirpContentType[TwirpContentType["Protobuf"] = 0] = "Protobuf";
TwirpContentType[TwirpContentType["JSON"] = 1] = "JSON";
TwirpContentType[TwirpContentType["Unknown"] = 2] = "Unknown";
})(TwirpContentType = exports.TwirpContentType || (exports.TwirpContentType = {}));
/**
* Get supported content-type
* @param mimeType
*/
function getContentType(mimeType) {
switch (mimeType) {
case "application/protobuf":
return TwirpContentType.Protobuf;
case "application/json":
return TwirpContentType.JSON;
default:
return TwirpContentType.Unknown;
}
}
exports.getContentType = getContentType;
/**
* Validate a twirp request
* @param ctx
* @param request
* @param pathPrefix
*/
function validateRequest(ctx, request, pathPrefix) {
if (request.method !== "POST") {
const msg = `unsupported method ${request.method} (only POST is allowed)`;
throw new errors_1.BadRouteError(msg, request.method || "", request.url || "");
}
const path = parseTwirpPath(request.url || "");
if (path.pkgService !==
(ctx.packageName ? ctx.packageName + "." : "") + ctx.serviceName) {
const msg = `no handler for path ${request.url}`;
throw new errors_1.BadRouteError(msg, request.method || "", request.url || "");
}
if (path.prefix !== pathPrefix) {
const msg = `invalid path prefix ${path.prefix}, expected ${pathPrefix}, on path ${request.url}`;
throw new errors_1.BadRouteError(msg, request.method || "", request.url || "");
}
const mimeContentType = request.headers["content-type"] || "";
if (ctx.contentType === TwirpContentType.Unknown) {
const msg = `unexpected Content-Type: ${request.headers["content-type"]}`;
throw new errors_1.BadRouteError(msg, request.method || "", request.url || "");
}
return Object.assign(Object.assign({}, path), { mimeContentType, contentType: ctx.contentType });
}
exports.validateRequest = validateRequest;
/**
* Get request data from the body
* @param req
*/
function getRequestData(req) {
return new Promise((resolve, reject) => {
const reqWithRawBody = req;
if (reqWithRawBody.rawBody instanceof Buffer) {
resolve(reqWithRawBody.rawBody);
return;
}
const chunks = [];
req.on("data", (chunk) => chunks.push(chunk));
req.on("end", () => __awaiter(this, void 0, void 0, function* () {
const data = Buffer.concat(chunks);
resolve(data);
}));
req.on("error", (err) => {
if (req.aborted) {
reject(new errors_1.TwirpError(errors_1.TwirpErrorCode.DeadlineExceeded, "failed to read request: deadline exceeded"));
}
else {
reject(new errors_1.TwirpError(errors_1.TwirpErrorCode.Malformed, err.message).withCause(err));
}
});
req.on("close", () => {
reject(new errors_1.TwirpError(errors_1.TwirpErrorCode.Canceled, "failed to read request: context canceled"));
});
});
}
exports.getRequestData = getRequestData;
/**
* Parses twirp url path
* @param path
*/
function parseTwirpPath(path) {
const parts = path.split("/");
if (parts.length < 2) {
return {
pkgService: "",
method: "",
prefix: "",
};
}
return {
method: parts[parts.length - 1],
pkgService: parts[parts.length - 2],
prefix: parts.slice(0, parts.length - 2).join("/"),
};
}
exports.parseTwirpPath = parseTwirpPath;
/***/ }),
/***/ 26604:
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.writeError = exports.TwirpServer = void 0;
const hooks_1 = __nccwpck_require__(4263);
const request_1 = __nccwpck_require__(8347);
const errors_1 = __nccwpck_require__(66647);
/**
* Runtime server implementation of a TwirpServer
*/
class TwirpServer {
constructor(options) {
this.pathPrefix = "/twirp";
this.hooks = [];
this.interceptors = [];
this.packageName = options.packageName;
this.serviceName = options.serviceName;
this.methodList = options.methodList;
this.matchRoute = options.matchRoute;
this.service = options.service;
}
/**
* Returns the prefix for this server
*/
get prefix() {
return this.pathPrefix;
}
/**
* The http handler for twirp complaint endpoints
* @param options
*/
httpHandler(options) {
return (req, resp) => {
// setup prefix
if ((options === null || options === void 0 ? void 0 : options.prefix) !== undefined) {
this.withPrefix(options.prefix);
}
return this._httpHandler(req, resp);
};
}
/**
* Adds interceptors or hooks to the request stack
* @param middlewares
*/
use(...middlewares) {
middlewares.forEach((middleware) => {
if (hooks_1.isHook(middleware)) {
this.hooks.push(middleware);
return this;
}
this.interceptors.push(middleware);
});
return this;
}
/**
* Adds a prefix to the service url path
* @param prefix
*/
withPrefix(prefix) {
if (prefix === false) {
this.pathPrefix = "";
}
else {
this.pathPrefix = prefix;
}
return this;
}
/**
* Returns the regex matching path for this twirp server
*/
matchingPath() {
const baseRegex = this.baseURI().replace(/\./g, "\\.");
return new RegExp(`${baseRegex}\/(${this.methodList.join("|")})`);
}
/**
* Returns the base URI for this twirp server
*/
baseURI() {
return `${this.pathPrefix}/${this.packageName ? this.packageName + "." : ""}${this.serviceName}`;
}
/**
* Create a twirp context
* @param req
* @param res
* @private
*/
createContext(req, res) {
return {
packageName: this.packageName,
serviceName: this.serviceName,
methodName: "",
contentType: request_1.getContentType(req.headers["content-type"]),
req: req,
res: res,
};
}
/**
* Twrip server http handler implementation
* @param req
* @param resp
* @private
*/
_httpHandler(req, resp) {
return __awaiter(this, void 0, void 0, function* () {
const ctx = this.createContext(req, resp);
try {
yield this.invokeHook("requestReceived", ctx);
const { method, mimeContentType } = request_1.validateRequest(ctx, req, this.pathPrefix || "");
const handler = this.matchRoute(method, {
onMatch: (ctx) => {
return this.invokeHook("requestRouted", ctx);
},
onNotFound: () => {
const msg = `no handler for path ${req.url}`;
throw new errors_1.BadRouteError(msg, req.method || "", req.url || "");
},
});
const body = yield request_1.getRequestData(req);
const response = yield handler(ctx, this.service, body, this.interceptors);
yield Promise.all([
this.invokeHook("responsePrepared", ctx),
// keep backwards compatibility till next release
this.invokeHook("requestPrepared", ctx),
]);
resp.statusCode = 200;
resp.setHeader("Content-Type", mimeContentType);
resp.end(response);
}
catch (e) {
yield this.invokeHook("error", ctx, mustBeTwirpError(e));
if (!resp.headersSent) {
writeError(resp, e);
}
}
finally {
yield Promise.all([
this.invokeHook("responseSent", ctx),
// keep backwards compatibility till next release
this.invokeHook("requestSent", ctx),
]);
}
});
}
/**
* Invoke a hook
* @param hookName
* @param ctx
* @param err
* @protected
*/
invokeHook(hookName, ctx, err) {
return __awaiter(this, void 0, void 0, function* () {
if (this.hooks.length === 0) {
return;
}
const chainedHooks = hooks_1.chainHooks(...this.hooks);
const hook = chainedHooks === null || chainedHooks === void 0 ? void 0 : chainedHooks[hookName];
if (hook) {
yield hook(ctx, err || new errors_1.InternalServerError("internal server error"));
}
});
}
}
exports.TwirpServer = TwirpServer;
/**
* Write http error response
* @param res
* @param error
*/
function writeError(res, error) {
const twirpError = mustBeTwirpError(error);
res.setHeader("Content-Type", "application/json");
res.statusCode = errors_1.httpStatusFromErrorCode(twirpError.code);
res.end(twirpError.toJSON());
}
exports.writeError = writeError;
/**
* Make sure that the error passed is a TwirpError
* otherwise it will wrap it into an InternalError
* @param err
*/
function mustBeTwirpError(err) {
if (err instanceof errors_1.TwirpError) {
return err;
}
return new errors_1.InternalServerErrorWith(err);
}
/***/ }),
/***/ 41773:
@@ -120473,6 +118710,7 @@ var Inputs;
Inputs["RunID"] = "run-id";
Inputs["Pattern"] = "pattern";
Inputs["MergeMultiple"] = "merge-multiple";
Inputs["ArtifactIds"] = "artifact-ids";
})(Inputs || (exports.Inputs = Inputs = {}));
var Outputs;
(function (Outputs) {
@@ -120523,7 +118761,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", ({ value: true }));
exports.chunk = void 0;
exports.run = exports.chunk = void 0;
const os = __importStar(__nccwpck_require__(22037));
const path = __importStar(__nccwpck_require__(71017));
const core = __importStar(__nccwpck_require__(42186));
@@ -120546,7 +118784,10 @@ function run() {
repository: core.getInput(constants_1.Inputs.Repository, { required: false }),
runID: parseInt(core.getInput(constants_1.Inputs.RunID, { required: false })),
pattern: core.getInput(constants_1.Inputs.Pattern, { required: false }),
mergeMultiple: core.getBooleanInput(constants_1.Inputs.MergeMultiple, { required: false })
mergeMultiple: core.getBooleanInput(constants_1.Inputs.MergeMultiple, {
required: false
}),
artifactIds: core.getInput(constants_1.Inputs.ArtifactIds, { required: false })
};
if (!inputs.path) {
inputs.path = process.env['GITHUB_WORKSPACE'] || process.cwd();
@@ -120554,7 +118795,12 @@ function run() {
if (inputs.path.startsWith(`~`)) {
inputs.path = inputs.path.replace('~', os.homedir());
}
// Check for mutually exclusive inputs
if (inputs.name && inputs.artifactIds) {
throw new Error(`Inputs 'name' and 'artifact-ids' cannot be used together. Please specify only one.`);
}
const isSingleArtifactDownload = !!inputs.name;
const isDownloadByIds = !!inputs.artifactIds;
const resolvedPath = path.resolve(inputs.path);
core.debug(`Resolved path is ${resolvedPath}`);
const options = {};
@@ -120571,6 +118817,7 @@ function run() {
};
}
let artifacts = [];
let artifactIds = [];
if (isSingleArtifactDownload) {
core.info(`Downloading single artifact`);
const { artifact: targetArtifact } = yield artifact_1.default.getArtifact(inputs.name, options);
@@ -120580,6 +118827,37 @@ function run() {
core.debug(`Found named artifact '${inputs.name}' (ID: ${targetArtifact.id}, Size: ${targetArtifact.size})`);
artifacts = [targetArtifact];
}
else if (isDownloadByIds) {
core.info(`Downloading artifacts by ID`);
const artifactIdList = inputs.artifactIds
.split(',')
.map(id => id.trim())
.filter(id => id !== '');
if (artifactIdList.length === 0) {
throw new Error(`No valid artifact IDs provided in 'artifact-ids' input`);
}
core.debug(`Parsed artifact IDs: ${JSON.stringify(artifactIdList)}`);
// Parse the artifact IDs
artifactIds = artifactIdList.map(id => {
const numericId = parseInt(id, 10);
if (isNaN(numericId)) {
throw new Error(`Invalid artifact ID: '${id}'. Must be a number.`);
}
return numericId;
});
// We need to fetch all artifacts to get metadata for the specified IDs
const listArtifactResponse = yield artifact_1.default.listArtifacts(Object.assign({ latest: true }, options));
artifacts = listArtifactResponse.artifacts.filter(artifact => artifactIds.includes(artifact.id));
if (artifacts.length === 0) {
throw new Error(`None of the provided artifact IDs were found`);
}
if (artifacts.length < artifactIds.length) {
const foundIds = artifacts.map(a => a.id);
const missingIds = artifactIds.filter(id => !foundIds.includes(id));
core.warning(`Could not find the following artifact IDs: ${missingIds.join(', ')}`);
}
core.debug(`Found ${artifacts.length} artifacts by ID`);
}
else {
const listArtifactResponse = yield artifact_1.default.listArtifacts(Object.assign({ latest: true }, options));
artifacts = listArtifactResponse.artifacts;
@@ -120591,7 +118869,7 @@ function run() {
core.debug(`Filtered from ${listArtifactResponse.artifacts.length} to ${artifacts.length} artifacts`);
}
else {
core.info('No input name or pattern filtered specified, downloading all artifacts');
core.info('No input name, artifact-ids or pattern filtered specified, downloading all artifacts');
if (!inputs.mergeMultiple) {
core.info('An extra directory with the artifact name will be created for each download');
}
@@ -120600,21 +118878,33 @@ function run() {
if (artifacts.length) {
core.info(`Preparing to download the following artifacts:`);
artifacts.forEach(artifact => {
core.info(`- ${artifact.name} (ID: ${artifact.id}, Size: ${artifact.size})`);
core.info(`- ${artifact.name} (ID: ${artifact.id}, Size: ${artifact.size}, Expected Digest: ${artifact.digest})`);
});
}
const downloadPromises = artifacts.map(artifact => artifact_1.default.downloadArtifact(artifact.id, Object.assign(Object.assign({}, options), { path: isSingleArtifactDownload || inputs.mergeMultiple
? resolvedPath
: path.join(resolvedPath, artifact.name) })));
const downloadPromises = artifacts.map(artifact => ({
name: artifact.name,
promise: artifact_1.default.downloadArtifact(artifact.id, Object.assign(Object.assign({}, options), { path: isSingleArtifactDownload || inputs.mergeMultiple
? resolvedPath
: path.join(resolvedPath, artifact.name), expectedHash: artifact.digest }))
}));
const chunkedPromises = (0, exports.chunk)(downloadPromises, PARALLEL_DOWNLOADS);
for (const chunk of chunkedPromises) {
yield Promise.all(chunk);
const chunkPromises = chunk.map(item => item.promise);
const results = yield Promise.all(chunkPromises);
for (let i = 0; i < results.length; i++) {
const outcome = results[i];
const artifactName = chunk[i].name;
if (outcome.digestMismatch) {
core.warning(`Artifact '${artifactName}' digest validation failed. Please verify the integrity of the artifact.`);
}
}
}
core.info(`Total of ${artifacts.length} artifact(s) downloaded`);
core.setOutput(constants_1.Outputs.DownloadPath, resolvedPath);
core.info('Download artifact has finished successfully');
});
}
exports.run = run;
run().catch(err => core.setFailed(`Unable to download artifact(s): ${err.message}`));
@@ -130590,7 +128880,7 @@ module.exports = index;
/***/ ((module) => {
"use strict";
module.exports = JSON.parse('{"name":"@actions/artifact","version":"2.1.8","preview":true,"description":"Actions artifact lib","keywords":["github","actions","artifact"],"homepage":"https://github.com/actions/toolkit/tree/main/packages/artifact","license":"MIT","main":"lib/artifact.js","types":"lib/artifact.d.ts","directories":{"lib":"lib","test":"__tests__"},"files":["lib","!.DS_Store"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/actions/toolkit.git","directory":"packages/artifact"},"scripts":{"audit-moderate":"npm install && npm audit --json --audit-level=moderate > audit.json","test":"cd ../../ && npm run test ./packages/artifact","bootstrap":"cd ../../ && npm run bootstrap","tsc-run":"tsc","tsc":"npm run bootstrap && npm run tsc-run","gen:docs":"typedoc --plugin typedoc-plugin-markdown --out docs/generated src/artifact.ts --githubPages false --readme none"},"bugs":{"url":"https://github.com/actions/toolkit/issues"},"dependencies":{"@actions/core":"^1.10.0","@actions/github":"^5.1.1","@actions/http-client":"^2.1.0","@azure/storage-blob":"^12.15.0","@octokit/core":"^3.5.1","@octokit/plugin-request-log":"^1.0.4","@octokit/plugin-retry":"^3.0.9","@octokit/request-error":"^5.0.0","@protobuf-ts/plugin":"^2.2.3-alpha.1","archiver":"^7.0.1","crypto":"^1.0.1","jwt-decode":"^3.1.2","twirp-ts":"^2.5.0","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"}}');
module.exports = JSON.parse('{"name":"@actions/artifact","version":"2.3.2","preview":true,"description":"Actions artifact lib","keywords":["github","actions","artifact"],"homepage":"https://github.com/actions/toolkit/tree/main/packages/artifact","license":"MIT","main":"lib/artifact.js","types":"lib/artifact.d.ts","directories":{"lib":"lib","test":"__tests__"},"files":["lib","!.DS_Store"],"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/actions/toolkit.git","directory":"packages/artifact"},"scripts":{"audit-moderate":"npm install && npm audit --json --audit-level=moderate > audit.json","test":"cd ../../ && npm run test ./packages/artifact","bootstrap":"cd ../../ && npm run bootstrap","tsc-run":"tsc","tsc":"npm run bootstrap && npm run tsc-run","gen:docs":"typedoc --plugin typedoc-plugin-markdown --out docs/generated src/artifact.ts --githubPages false --readme none"},"bugs":{"url":"https://github.com/actions/toolkit/issues"},"dependencies":{"@actions/core":"^1.10.0","@actions/github":"^5.1.1","@actions/http-client":"^2.1.0","@azure/storage-blob":"^12.15.0","@octokit/core":"^3.5.1","@octokit/plugin-request-log":"^1.0.4","@octokit/plugin-retry":"^3.0.9","@octokit/request-error":"^5.0.0","@protobuf-ts/plugin":"^2.2.3-alpha.1","archiver":"^7.0.1","jwt-decode":"^3.1.2","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"}}');
/***/ }),
@@ -130668,4 +128958,4 @@ module.exports = JSON.parse('[[[0,44],"disallowed_STD3_valid"],[[45,46],"valid"]
/******/ module.exports = __webpack_exports__;
/******/
/******/ })()
;
;
+47 -2
View File
@@ -4,6 +4,7 @@
- [Multiple uploads to the same named Artifact](#multiple-uploads-to-the-same-named-artifact)
- [Overwriting an Artifact](#overwriting-an-artifact)
- [Merging multiple artifacts](#merging-multiple-artifacts)
- [Working with Immutable Artifacts](#working-with-immutable-artifacts)
Several behavioral differences exist between Artifact actions `v3` and below vs `v4`. This document outlines common scenarios in `v3`, and how they would be handled in `v4`.
@@ -189,7 +190,8 @@ jobs:
- name: Create a File
run: echo "hello from ${{ matrix.runs-on }}" > file-${{ matrix.runs-on }}.txt
- name: Upload Artifact
uses: actions/upload-artifact@v3
- uses: actions/upload-artifact@v3
+ uses: actions/upload-artifact@v4
with:
- name: all-my-files
+ name: my-artifact-${{ matrix.runs-on }}
@@ -205,4 +207,47 @@ jobs:
+ pattern: my-artifact-*
```
Note that this will download all artifacts to a temporary directory and reupload them as a single artifact. For more information on inputs and other use cases for `actions/upload-artifact/merge@v4`, see [the action documentation](../merge/README.md).
Note that this will download all artifacts to a temporary directory and reupload them as a single artifact. For more information on inputs and other use cases for `actions/upload-artifact/merge@v4`, see [the action documentation](https://github.com/actions/upload-artifact/blob/main/merge/README.md).
## Working with Immutable Artifacts
In `v4`, artifacts are immutable by default and each artifact gets a unique ID when uploaded. When an artifact with the same name is uploaded again (with or without `overwrite: true`), it gets a new artifact ID.
To take advantage of this immutability for security purposes (to avoid potential TOCTOU issues where an artifact might be replaced between upload and download), the new `artifact-ids` input allows you to download artifacts by their specific ID rather than by name:
```yaml
jobs:
upload:
runs-on: ubuntu-latest
# Make the artifact ID available to the download job
outputs:
artifact-id: ${{ steps.upload-step.outputs.artifact-id }}
steps:
- name: Create a file
run: echo "hello world" > my-file.txt
- name: Upload Artifact
id: upload-step
uses: actions/upload-artifact@v4
with:
name: my-artifact
path: my-file.txt
# The upload step outputs the artifact ID
- name: Print Artifact ID
run: echo "Artifact ID is ${{ steps.upload-step.outputs.artifact-id }}"
download:
needs: upload
runs-on: ubuntu-latest
steps:
- name: Download Artifact by ID
uses: actions/download-artifact@v4
with:
# Use the artifact ID directly, not the name, to ensure you get exactly the artifact you expect
artifact-ids: ${{ needs.upload.outputs.artifact-id }}
```
This approach provides stronger guarantees about which artifact version you're downloading compared to using just the artifact name.
+12
View File
@@ -0,0 +1,12 @@
module.exports = {
clearMocks: true,
moduleFileExtensions: ['js', 'ts'],
roots: ['<rootDir>'],
testEnvironment: 'node',
testMatch: ['**/*.test.ts'],
testRunner: 'jest-circus/runner',
transform: {
'^.+\\.ts$': 'ts-jest'
},
verbose: true
}
+8273 -402
View File
File diff suppressed because it is too large Load Diff
+8 -3
View File
@@ -1,6 +1,6 @@
{
"name": "download-artifact",
"version": "4.1.7",
"version": "4.3.0",
"description": "Download an Actions Artifact from a workflow run",
"main": "dist/index.js",
"scripts": {
@@ -9,7 +9,8 @@
"check-all": "concurrently \"npm:format-check\" \"npm:lint\" \"npm:build\"",
"format": "prettier --write **/*.ts",
"format-check": "prettier --check **/*.ts",
"lint": "eslint **/*.ts"
"lint": "eslint **/*.ts",
"test": "jest"
},
"repository": {
"type": "git",
@@ -28,12 +29,13 @@
},
"homepage": "https://github.com/actions/download-artifact#readme",
"dependencies": {
"@actions/artifact": "^2.1.8",
"@actions/artifact": "^2.3.2",
"@actions/core": "^1.10.1",
"@actions/github": "^5.1.1",
"minimatch": "^9.0.3"
},
"devDependencies": {
"@types/jest": "^29.5.14",
"@types/node": "^12.12.6",
"@typescript-eslint/eslint-plugin": "^6.14.0",
"@vercel/ncc": "^0.33.4",
@@ -41,7 +43,10 @@
"eslint": "^8.55.0",
"eslint-plugin-github": "^4.10.1",
"eslint-plugin-prettier": "^5.0.1",
"jest": "^29.7.0",
"prettier": "^3.1.1",
"ts-jest": "^29.2.6",
"ts-node": "^10.9.2",
"typescript": "^5.3.3"
}
}
+2 -1
View File
@@ -5,7 +5,8 @@ export enum Inputs {
Repository = 'repository',
RunID = 'run-id',
Pattern = 'pattern',
MergeMultiple = 'merge-multiple'
MergeMultiple = 'merge-multiple',
ArtifactIds = 'artifact-ids'
}
export enum Outputs {
+81 -10
View File
@@ -15,7 +15,7 @@ export const chunk = <T>(arr: T[], n: number): T[][] =>
return acc
}, [] as T[][])
async function run(): Promise<void> {
export async function run(): Promise<void> {
const inputs = {
name: core.getInput(Inputs.Name, {required: false}),
path: core.getInput(Inputs.Path, {required: false}),
@@ -23,7 +23,10 @@ async function run(): Promise<void> {
repository: core.getInput(Inputs.Repository, {required: false}),
runID: parseInt(core.getInput(Inputs.RunID, {required: false})),
pattern: core.getInput(Inputs.Pattern, {required: false}),
mergeMultiple: core.getBooleanInput(Inputs.MergeMultiple, {required: false})
mergeMultiple: core.getBooleanInput(Inputs.MergeMultiple, {
required: false
}),
artifactIds: core.getInput(Inputs.ArtifactIds, {required: false})
}
if (!inputs.path) {
@@ -34,7 +37,15 @@ async function run(): Promise<void> {
inputs.path = inputs.path.replace('~', os.homedir())
}
// Check for mutually exclusive inputs
if (inputs.name && inputs.artifactIds) {
throw new Error(
`Inputs 'name' and 'artifact-ids' cannot be used together. Please specify only one.`
)
}
const isSingleArtifactDownload = !!inputs.name
const isDownloadByIds = !!inputs.artifactIds
const resolvedPath = path.resolve(inputs.path)
core.debug(`Resolved path is ${resolvedPath}`)
@@ -56,6 +67,7 @@ async function run(): Promise<void> {
}
let artifacts: Artifact[] = []
let artifactIds: number[] = []
if (isSingleArtifactDownload) {
core.info(`Downloading single artifact`)
@@ -74,6 +86,52 @@ async function run(): Promise<void> {
)
artifacts = [targetArtifact]
} else if (isDownloadByIds) {
core.info(`Downloading artifacts by ID`)
const artifactIdList = inputs.artifactIds
.split(',')
.map(id => id.trim())
.filter(id => id !== '')
if (artifactIdList.length === 0) {
throw new Error(`No valid artifact IDs provided in 'artifact-ids' input`)
}
core.debug(`Parsed artifact IDs: ${JSON.stringify(artifactIdList)}`)
// Parse the artifact IDs
artifactIds = artifactIdList.map(id => {
const numericId = parseInt(id, 10)
if (isNaN(numericId)) {
throw new Error(`Invalid artifact ID: '${id}'. Must be a number.`)
}
return numericId
})
// We need to fetch all artifacts to get metadata for the specified IDs
const listArtifactResponse = await artifactClient.listArtifacts({
latest: true,
...options
})
artifacts = listArtifactResponse.artifacts.filter(artifact =>
artifactIds.includes(artifact.id)
)
if (artifacts.length === 0) {
throw new Error(`None of the provided artifact IDs were found`)
}
if (artifacts.length < artifactIds.length) {
const foundIds = artifacts.map(a => a.id)
const missingIds = artifactIds.filter(id => !foundIds.includes(id))
core.warning(
`Could not find the following artifact IDs: ${missingIds.join(', ')}`
)
}
core.debug(`Found ${artifacts.length} artifacts by ID`)
} else {
const listArtifactResponse = await artifactClient.listArtifacts({
latest: true,
@@ -92,7 +150,7 @@ async function run(): Promise<void> {
)
} else {
core.info(
'No input name or pattern filtered specified, downloading all artifacts'
'No input name, artifact-ids or pattern filtered specified, downloading all artifacts'
)
if (!inputs.mergeMultiple) {
core.info(
@@ -106,26 +164,39 @@ async function run(): Promise<void> {
core.info(`Preparing to download the following artifacts:`)
artifacts.forEach(artifact => {
core.info(
`- ${artifact.name} (ID: ${artifact.id}, Size: ${artifact.size})`
`- ${artifact.name} (ID: ${artifact.id}, Size: ${artifact.size}, Expected Digest: ${artifact.digest})`
)
})
}
const downloadPromises = artifacts.map(artifact =>
artifactClient.downloadArtifact(artifact.id, {
const downloadPromises = artifacts.map(artifact => ({
name: artifact.name,
promise: artifactClient.downloadArtifact(artifact.id, {
...options,
path:
isSingleArtifactDownload || inputs.mergeMultiple
? resolvedPath
: path.join(resolvedPath, artifact.name)
: path.join(resolvedPath, artifact.name),
expectedHash: artifact.digest
})
)
}))
const chunkedPromises = chunk(downloadPromises, PARALLEL_DOWNLOADS)
for (const chunk of chunkedPromises) {
await Promise.all(chunk)
}
const chunkPromises = chunk.map(item => item.promise)
const results = await Promise.all(chunkPromises)
for (let i = 0; i < results.length; i++) {
const outcome = results[i]
const artifactName = chunk[i].name
if (outcome.digestMismatch) {
core.warning(
`Artifact '${artifactName}' digest validation failed. Please verify the integrity of the artifact.`
)
}
}
}
core.info(`Total of ${artifacts.length} artifact(s) downloaded`)
core.setOutput(Outputs.DownloadPath, resolvedPath)
core.info('Download artifact has finished successfully')
+1 -1
View File
@@ -9,5 +9,5 @@
"moduleResolution": "node",
"esModuleInterop": true
},
"exclude": ["node_modules", "**/*.test.ts"]
"exclude": ["node_modules", "**/*.test.ts", "jest.config.ts", "__tests__"]
}