@frictionless-ts/dataset 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -0
- package/build/file/copy.d.ts +4 -0
- package/build/file/copy.js +7 -0
- package/build/file/copy.spec.d.ts +1 -0
- package/build/file/copy.spec.js +104 -0
- package/build/file/describe.d.ts +7 -0
- package/build/file/describe.js +9 -0
- package/build/file/fetch.d.ts +2 -0
- package/build/file/fetch.js +21 -0
- package/build/file/index.d.ts +9 -0
- package/build/file/index.js +10 -0
- package/build/file/infer.d.ts +10 -0
- package/build/file/infer.js +48 -0
- package/build/file/infer.spec.d.ts +1 -0
- package/build/file/infer.spec.js +141 -0
- package/build/file/load.d.ts +3 -0
- package/build/file/load.js +7 -0
- package/build/file/path.d.ts +2 -0
- package/build/file/path.js +17 -0
- package/build/file/save.d.ts +3 -0
- package/build/file/save.js +7 -0
- package/build/file/temp.d.ts +11 -0
- package/build/file/temp.js +23 -0
- package/build/file/validate.d.ts +6 -0
- package/build/file/validate.js +47 -0
- package/build/file/validate.spec.d.ts +1 -0
- package/build/file/validate.spec.js +180 -0
- package/build/folder/create.d.ts +1 -0
- package/build/folder/create.js +5 -0
- package/build/folder/index.d.ts +2 -0
- package/build/folder/index.js +3 -0
- package/build/folder/temp.d.ts +3 -0
- package/build/folder/temp.js +16 -0
- package/build/index.d.ts +36 -0
- package/build/index.js +35 -0
- package/build/package/index.d.ts +2 -0
- package/build/package/index.js +3 -0
- package/build/package/merge.d.ts +23 -0
- package/build/package/merge.js +12 -0
- package/build/package/path.d.ts +3 -0
- package/build/package/path.js +43 -0
- package/build/package/path.spec.d.ts +1 -0
- package/build/package/path.spec.js +56 -0
- package/build/plugin.d.ts +11 -0
- package/build/plugin.js +2 -0
- package/build/plugins/ckan/ckan/index.d.ts +1 -0
- package/build/plugins/ckan/ckan/index.js +2 -0
- package/build/plugins/ckan/ckan/request.d.ts +11 -0
- package/build/plugins/ckan/ckan/request.js +35 -0
- package/build/plugins/ckan/index.d.ts +4 -0
- package/build/plugins/ckan/index.js +5 -0
- package/build/plugins/ckan/package/Organization.d.ts +21 -0
- package/build/plugins/ckan/package/Organization.js +2 -0
- package/build/plugins/ckan/package/Package.d.ts +76 -0
- package/build/plugins/ckan/package/Package.js +2 -0
- package/build/plugins/ckan/package/Tag.d.ts +17 -0
- package/build/plugins/ckan/package/Tag.js +2 -0
- package/build/plugins/ckan/package/convert/fromCkan.d.ts +3 -0
- package/build/plugins/ckan/package/convert/fromCkan.js +63 -0
- package/build/plugins/ckan/package/convert/fromCkan.spec.d.ts +1 -0
- package/build/plugins/ckan/package/convert/fromCkan.spec.js +80 -0
- package/build/plugins/ckan/package/convert/toCkan.d.ts +22 -0
- package/build/plugins/ckan/package/convert/toCkan.js +51 -0
- package/build/plugins/ckan/package/convert/toCkan.spec.d.ts +1 -0
- package/build/plugins/ckan/package/convert/toCkan.spec.js +153 -0
- package/build/plugins/ckan/package/fixtures/ckan-package.json +308 -0
- package/build/plugins/ckan/package/index.d.ts +7 -0
- package/build/plugins/ckan/package/index.js +5 -0
- package/build/plugins/ckan/package/load.d.ts +21 -0
- package/build/plugins/ckan/package/load.js +74 -0
- package/build/plugins/ckan/package/load.spec.d.ts +1 -0
- package/build/plugins/ckan/package/load.spec.js +11 -0
- package/build/plugins/ckan/package/save.d.ts +10 -0
- package/build/plugins/ckan/package/save.js +83 -0
- package/build/plugins/ckan/package/save.spec.d.ts +1 -0
- package/build/plugins/ckan/package/save.spec.js +319 -0
- package/build/plugins/ckan/plugin.d.ts +19 -0
- package/build/plugins/ckan/plugin.js +18 -0
- package/build/plugins/ckan/plugin.spec.d.ts +1 -0
- package/build/plugins/ckan/plugin.spec.js +83 -0
- package/build/plugins/ckan/resource/Resource.d.ts +56 -0
- package/build/plugins/ckan/resource/Resource.js +2 -0
- package/build/plugins/ckan/resource/convert/fromCkan.d.ts +3 -0
- package/build/plugins/ckan/resource/convert/fromCkan.js +39 -0
- package/build/plugins/ckan/resource/convert/toCkan.d.ts +3 -0
- package/build/plugins/ckan/resource/convert/toCkan.js +20 -0
- package/build/plugins/ckan/resource/index.d.ts +3 -0
- package/build/plugins/ckan/resource/index.js +3 -0
- package/build/plugins/ckan/schema/Field.d.ts +34 -0
- package/build/plugins/ckan/schema/Field.js +2 -0
- package/build/plugins/ckan/schema/Schema.d.ts +10 -0
- package/build/plugins/ckan/schema/Schema.js +2 -0
- package/build/plugins/ckan/schema/convert/fixtures/ckan-schema.json +115 -0
- package/build/plugins/ckan/schema/convert/fromCkan.d.ts +3 -0
- package/build/plugins/ckan/schema/convert/fromCkan.js +47 -0
- package/build/plugins/ckan/schema/convert/fromCkan.spec.d.ts +1 -0
- package/build/plugins/ckan/schema/convert/fromCkan.spec.js +157 -0
- package/build/plugins/ckan/schema/convert/toCkan.d.ts +3 -0
- package/build/plugins/ckan/schema/convert/toCkan.js +50 -0
- package/build/plugins/ckan/schema/convert/toCkan.spec.d.ts +1 -0
- package/build/plugins/ckan/schema/convert/toCkan.spec.js +278 -0
- package/build/plugins/ckan/schema/index.d.ts +4 -0
- package/build/plugins/ckan/schema/index.js +3 -0
- package/build/plugins/datahub/index.d.ts +2 -0
- package/build/plugins/datahub/index.js +3 -0
- package/build/plugins/datahub/package/index.d.ts +1 -0
- package/build/plugins/datahub/package/index.js +2 -0
- package/build/plugins/datahub/package/load.d.ts +1 -0
- package/build/plugins/datahub/package/load.js +9 -0
- package/build/plugins/datahub/package/load.spec.d.ts +1 -0
- package/build/plugins/datahub/package/load.spec.js +11 -0
- package/build/plugins/datahub/plugin.d.ts +4 -0
- package/build/plugins/datahub/plugin.js +18 -0
- package/build/plugins/datahub/plugin.spec.d.ts +1 -0
- package/build/plugins/datahub/plugin.spec.js +78 -0
- package/build/plugins/descriptor/index.d.ts +1 -0
- package/build/plugins/descriptor/index.js +2 -0
- package/build/plugins/descriptor/plugin.d.ts +11 -0
- package/build/plugins/descriptor/plugin.js +29 -0
- package/build/plugins/descriptor/plugin.spec.d.ts +1 -0
- package/build/plugins/descriptor/plugin.spec.js +169 -0
- package/build/plugins/folder/index.d.ts +2 -0
- package/build/plugins/folder/index.js +3 -0
- package/build/plugins/folder/package/index.d.ts +2 -0
- package/build/plugins/folder/package/index.js +3 -0
- package/build/plugins/folder/package/load.d.ts +1 -0
- package/build/plugins/folder/package/load.js +6 -0
- package/build/plugins/folder/package/load.spec.d.ts +1 -0
- package/build/plugins/folder/package/load.spec.js +175 -0
- package/build/plugins/folder/package/save.d.ts +7 -0
- package/build/plugins/folder/package/save.js +35 -0
- package/build/plugins/folder/package/save.spec.d.ts +1 -0
- package/build/plugins/folder/package/save.spec.js +328 -0
- package/build/plugins/folder/plugin.d.ts +4 -0
- package/build/plugins/folder/plugin.js +19 -0
- package/build/plugins/folder/plugin.spec.d.ts +1 -0
- package/build/plugins/folder/plugin.spec.js +53 -0
- package/build/plugins/github/github/index.d.ts +1 -0
- package/build/plugins/github/github/index.js +2 -0
- package/build/plugins/github/github/path.d.ts +1 -0
- package/build/plugins/github/github/path.js +4 -0
- package/build/plugins/github/github/request.d.ts +15 -0
- package/build/plugins/github/github/request.js +43 -0
- package/build/plugins/github/index.d.ts +3 -0
- package/build/plugins/github/index.js +4 -0
- package/build/plugins/github/package/License.d.ts +21 -0
- package/build/plugins/github/package/License.js +2 -0
- package/build/plugins/github/package/Owner.d.ts +25 -0
- package/build/plugins/github/package/Owner.js +2 -0
- package/build/plugins/github/package/Package.d.ts +87 -0
- package/build/plugins/github/package/Package.js +2 -0
- package/build/plugins/github/package/convert/fromGithub.d.ts +3 -0
- package/build/plugins/github/package/convert/fromGithub.js +50 -0
- package/build/plugins/github/package/index.d.ts +6 -0
- package/build/plugins/github/package/index.js +4 -0
- package/build/plugins/github/package/load.d.ts +23 -0
- package/build/plugins/github/package/load.js +48 -0
- package/build/plugins/github/package/load.spec.d.ts +1 -0
- package/build/plugins/github/package/load.spec.js +15 -0
- package/build/plugins/github/package/save.d.ts +14 -0
- package/build/plugins/github/package/save.js +69 -0
- package/build/plugins/github/package/save.spec.d.ts +1 -0
- package/build/plugins/github/package/save.spec.js +566 -0
- package/build/plugins/github/plugin.d.ts +19 -0
- package/build/plugins/github/plugin.js +18 -0
- package/build/plugins/github/plugin.spec.d.ts +1 -0
- package/build/plugins/github/plugin.spec.js +73 -0
- package/build/plugins/github/resource/Resource.d.ts +29 -0
- package/build/plugins/github/resource/Resource.js +2 -0
- package/build/plugins/github/resource/convert/fromGithub.d.ts +5 -0
- package/build/plugins/github/resource/convert/fromGithub.js +24 -0
- package/build/plugins/github/resource/convert/toGithub.d.ts +3 -0
- package/build/plugins/github/resource/convert/toGithub.js +10 -0
- package/build/plugins/github/resource/index.d.ts +3 -0
- package/build/plugins/github/resource/index.js +3 -0
- package/build/plugins/zenodo/index.d.ts +3 -0
- package/build/plugins/zenodo/index.js +4 -0
- package/build/plugins/zenodo/package/Creator.d.ts +20 -0
- package/build/plugins/zenodo/package/Creator.js +2 -0
- package/build/plugins/zenodo/package/Package.d.ts +94 -0
- package/build/plugins/zenodo/package/Package.js +2 -0
- package/build/plugins/zenodo/package/convert/fromZenodo.d.ts +3 -0
- package/build/plugins/zenodo/package/convert/fromZenodo.js +43 -0
- package/build/plugins/zenodo/package/convert/toZenodo.d.ts +3 -0
- package/build/plugins/zenodo/package/convert/toZenodo.js +79 -0
- package/build/plugins/zenodo/package/index.d.ts +6 -0
- package/build/plugins/zenodo/package/index.js +5 -0
- package/build/plugins/zenodo/package/load.d.ts +23 -0
- package/build/plugins/zenodo/package/load.js +45 -0
- package/build/plugins/zenodo/package/load.spec.d.ts +1 -0
- package/build/plugins/zenodo/package/load.spec.js +15 -0
- package/build/plugins/zenodo/package/save.d.ts +13 -0
- package/build/plugins/zenodo/package/save.js +74 -0
- package/build/plugins/zenodo/package/save.spec.d.ts +1 -0
- package/build/plugins/zenodo/package/save.spec.js +524 -0
- package/build/plugins/zenodo/plugin.d.ts +19 -0
- package/build/plugins/zenodo/plugin.js +18 -0
- package/build/plugins/zenodo/plugin.spec.d.ts +1 -0
- package/build/plugins/zenodo/plugin.spec.js +78 -0
- package/build/plugins/zenodo/resource/Resource.d.ts +27 -0
- package/build/plugins/zenodo/resource/Resource.js +2 -0
- package/build/plugins/zenodo/resource/convert/fromZenodo.d.ts +10 -0
- package/build/plugins/zenodo/resource/convert/fromZenodo.js +18 -0
- package/build/plugins/zenodo/resource/convert/toZenodo.d.ts +3 -0
- package/build/plugins/zenodo/resource/convert/toZenodo.js +13 -0
- package/build/plugins/zenodo/resource/index.d.ts +3 -0
- package/build/plugins/zenodo/resource/index.js +3 -0
- package/build/plugins/zenodo/zenodo/index.d.ts +1 -0
- package/build/plugins/zenodo/zenodo/index.js +2 -0
- package/build/plugins/zenodo/zenodo/request.d.ts +12 -0
- package/build/plugins/zenodo/zenodo/request.js +36 -0
- package/build/plugins/zip/index.d.ts +2 -0
- package/build/plugins/zip/index.js +3 -0
- package/build/plugins/zip/package/index.d.ts +2 -0
- package/build/plugins/zip/package/index.js +3 -0
- package/build/plugins/zip/package/load.d.ts +1 -0
- package/build/plugins/zip/package/load.js +30 -0
- package/build/plugins/zip/package/load.spec.d.ts +1 -0
- package/build/plugins/zip/package/load.spec.js +173 -0
- package/build/plugins/zip/package/save.d.ts +5 -0
- package/build/plugins/zip/package/save.js +50 -0
- package/build/plugins/zip/package/save.spec.d.ts +1 -0
- package/build/plugins/zip/package/save.spec.js +287 -0
- package/build/plugins/zip/plugin.d.ts +11 -0
- package/build/plugins/zip/plugin.js +24 -0
- package/build/plugins/zip/plugin.spec.d.ts +1 -0
- package/build/plugins/zip/plugin.spec.js +158 -0
- package/build/resource/index.d.ts +1 -0
- package/build/resource/index.js +2 -0
- package/build/resource/save.d.ts +13 -0
- package/build/resource/save.js +53 -0
- package/build/resource/save.spec.d.ts +1 -0
- package/build/resource/save.spec.js +107 -0
- package/build/stream/concat.d.ts +3 -0
- package/build/stream/concat.js +5 -0
- package/build/stream/index.d.ts +3 -0
- package/build/stream/index.js +4 -0
- package/build/stream/load.d.ts +5 -0
- package/build/stream/load.js +46 -0
- package/build/stream/save.d.ts +5 -0
- package/build/stream/save.js +13 -0
- package/package.json +48 -0
|
@@ -0,0 +1,566 @@
|
|
|
1
|
+
import { relative } from "node:path";
|
|
2
|
+
import { loadPackageDescriptor } from "@frictionless-ts/metadata";
|
|
3
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
4
|
+
import { savePackageToGithub } from "./save.js";
|
|
5
|
+
describe("savePackageToGithub", () => {
|
|
6
|
+
const getFixturePath = (name) => relative(process.cwd(), `${import.meta.dirname}/fixtures/${name}`);
|
|
7
|
+
const mockPackage = {
|
|
8
|
+
name: "test-package",
|
|
9
|
+
title: "Test Package",
|
|
10
|
+
description: "A test package",
|
|
11
|
+
version: "1.0.0",
|
|
12
|
+
resources: [
|
|
13
|
+
{
|
|
14
|
+
name: "test-resource",
|
|
15
|
+
path: getFixturePath("data.csv"),
|
|
16
|
+
format: "csv",
|
|
17
|
+
bytes: 100,
|
|
18
|
+
},
|
|
19
|
+
],
|
|
20
|
+
};
|
|
21
|
+
const mockOptions = {
|
|
22
|
+
apiKey: "test-api-key",
|
|
23
|
+
repo: "test-repo",
|
|
24
|
+
};
|
|
25
|
+
const originalFetch = globalThis.fetch;
|
|
26
|
+
let fetchMock;
|
|
27
|
+
beforeEach(() => {
|
|
28
|
+
fetchMock = vi.fn();
|
|
29
|
+
// @ts-ignore
|
|
30
|
+
globalThis.fetch = fetchMock;
|
|
31
|
+
});
|
|
32
|
+
afterEach(() => {
|
|
33
|
+
globalThis.fetch = originalFetch;
|
|
34
|
+
vi.resetAllMocks();
|
|
35
|
+
});
|
|
36
|
+
it.skip("should save a package", async () => {
|
|
37
|
+
const dataPackage = await loadPackageDescriptor("core/package/fixtures/package.json");
|
|
38
|
+
const result = await savePackageToGithub(dataPackage, {
|
|
39
|
+
apiKey: "<key>",
|
|
40
|
+
repo: "test",
|
|
41
|
+
});
|
|
42
|
+
console.log(result);
|
|
43
|
+
expect(true).toBeDefined();
|
|
44
|
+
});
|
|
45
|
+
it("creates a repository in GitHub with correct API calls", async () => {
|
|
46
|
+
fetchMock.mockResolvedValueOnce({
|
|
47
|
+
ok: true,
|
|
48
|
+
json: () => Promise.resolve({
|
|
49
|
+
id: 12345,
|
|
50
|
+
name: "test-repo",
|
|
51
|
+
full_name: "test-user/test-repo",
|
|
52
|
+
owner: {
|
|
53
|
+
login: "test-user",
|
|
54
|
+
id: 1,
|
|
55
|
+
avatar_url: "https://avatars.githubusercontent.com/u/1",
|
|
56
|
+
html_url: "https://github.com/test-user",
|
|
57
|
+
type: "User",
|
|
58
|
+
},
|
|
59
|
+
html_url: "https://github.com/test-user/test-repo",
|
|
60
|
+
description: null,
|
|
61
|
+
created_at: "2024-01-01T00:00:00Z",
|
|
62
|
+
updated_at: "2024-01-01T00:00:00Z",
|
|
63
|
+
homepage: null,
|
|
64
|
+
size: 0,
|
|
65
|
+
stargazers_count: 0,
|
|
66
|
+
watchers_count: 0,
|
|
67
|
+
language: null,
|
|
68
|
+
license: null,
|
|
69
|
+
default_branch: "main",
|
|
70
|
+
topics: [],
|
|
71
|
+
private: false,
|
|
72
|
+
archived: false,
|
|
73
|
+
git_url: "git://github.com/test-user/test-repo.git",
|
|
74
|
+
ssh_url: "git@github.com:test-user/test-repo.git",
|
|
75
|
+
clone_url: "https://github.com/test-user/test-repo.git",
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
fetchMock.mockResolvedValueOnce({
|
|
79
|
+
ok: true,
|
|
80
|
+
json: () => Promise.resolve({
|
|
81
|
+
content: {
|
|
82
|
+
name: "data.csv",
|
|
83
|
+
path: "data.csv",
|
|
84
|
+
sha: "abc123",
|
|
85
|
+
},
|
|
86
|
+
}),
|
|
87
|
+
});
|
|
88
|
+
fetchMock.mockResolvedValueOnce({
|
|
89
|
+
ok: true,
|
|
90
|
+
json: () => Promise.resolve({
|
|
91
|
+
content: {
|
|
92
|
+
name: "datapackage.json",
|
|
93
|
+
path: "datapackage.json",
|
|
94
|
+
sha: "def456",
|
|
95
|
+
},
|
|
96
|
+
}),
|
|
97
|
+
});
|
|
98
|
+
const result = await savePackageToGithub(mockPackage, mockOptions);
|
|
99
|
+
expect(fetchMock).toHaveBeenCalledTimes(3);
|
|
100
|
+
const repoCreateCall = fetchMock.mock.calls[0];
|
|
101
|
+
expect(repoCreateCall).toBeDefined();
|
|
102
|
+
if (!repoCreateCall)
|
|
103
|
+
return;
|
|
104
|
+
expect(repoCreateCall[0]).toEqual("https://api.github.com/user/repos");
|
|
105
|
+
expect(repoCreateCall[1]).toMatchObject({
|
|
106
|
+
method: "POST",
|
|
107
|
+
headers: {
|
|
108
|
+
Authorization: "Bearer test-api-key",
|
|
109
|
+
"Content-Type": "application/json",
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
const repoPayload = JSON.parse(repoCreateCall[1].body);
|
|
113
|
+
expect(repoPayload.name).toEqual("test-repo");
|
|
114
|
+
expect(repoPayload.auto_init).toEqual(true);
|
|
115
|
+
expect(result).toEqual({
|
|
116
|
+
path: "https://raw.githubusercontent.com/test-user/test-repo/refs/heads/main/dataPackage.json",
|
|
117
|
+
repoUrl: "https://github.com/test-user/test-repo",
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
it("creates a repository in an organization when org is specified", async () => {
|
|
121
|
+
fetchMock.mockResolvedValueOnce({
|
|
122
|
+
ok: true,
|
|
123
|
+
json: () => Promise.resolve({
|
|
124
|
+
id: 12345,
|
|
125
|
+
name: "test-repo",
|
|
126
|
+
full_name: "test-org/test-repo",
|
|
127
|
+
owner: {
|
|
128
|
+
login: "test-org",
|
|
129
|
+
id: 2,
|
|
130
|
+
avatar_url: "https://avatars.githubusercontent.com/u/2",
|
|
131
|
+
html_url: "https://github.com/test-org",
|
|
132
|
+
type: "Organization",
|
|
133
|
+
},
|
|
134
|
+
html_url: "https://github.com/test-org/test-repo",
|
|
135
|
+
description: null,
|
|
136
|
+
created_at: "2024-01-01T00:00:00Z",
|
|
137
|
+
updated_at: "2024-01-01T00:00:00Z",
|
|
138
|
+
homepage: null,
|
|
139
|
+
size: 0,
|
|
140
|
+
stargazers_count: 0,
|
|
141
|
+
watchers_count: 0,
|
|
142
|
+
language: null,
|
|
143
|
+
license: null,
|
|
144
|
+
default_branch: "main",
|
|
145
|
+
topics: [],
|
|
146
|
+
private: false,
|
|
147
|
+
archived: false,
|
|
148
|
+
git_url: "git://github.com/test-org/test-repo.git",
|
|
149
|
+
ssh_url: "git@github.com:test-org/test-repo.git",
|
|
150
|
+
clone_url: "https://github.com/test-org/test-repo.git",
|
|
151
|
+
}),
|
|
152
|
+
});
|
|
153
|
+
fetchMock.mockResolvedValue({
|
|
154
|
+
ok: true,
|
|
155
|
+
json: () => Promise.resolve({
|
|
156
|
+
content: {
|
|
157
|
+
name: "file",
|
|
158
|
+
path: "file",
|
|
159
|
+
sha: "abc123",
|
|
160
|
+
},
|
|
161
|
+
}),
|
|
162
|
+
});
|
|
163
|
+
await savePackageToGithub(mockPackage, {
|
|
164
|
+
...mockOptions,
|
|
165
|
+
org: "test-org",
|
|
166
|
+
});
|
|
167
|
+
const repoCreateCall = fetchMock.mock.calls[0];
|
|
168
|
+
expect(repoCreateCall).toBeDefined();
|
|
169
|
+
if (!repoCreateCall)
|
|
170
|
+
return;
|
|
171
|
+
expect(repoCreateCall[0]).toEqual("https://api.github.com/orgs/test-org/repos");
|
|
172
|
+
});
|
|
173
|
+
it("uploads resource files with base64 encoding", async () => {
|
|
174
|
+
fetchMock.mockResolvedValueOnce({
|
|
175
|
+
ok: true,
|
|
176
|
+
json: () => Promise.resolve({
|
|
177
|
+
id: 12345,
|
|
178
|
+
name: "test-repo",
|
|
179
|
+
full_name: "test-user/test-repo",
|
|
180
|
+
owner: {
|
|
181
|
+
login: "test-user",
|
|
182
|
+
id: 1,
|
|
183
|
+
avatar_url: "https://avatars.githubusercontent.com/u/1",
|
|
184
|
+
html_url: "https://github.com/test-user",
|
|
185
|
+
type: "User",
|
|
186
|
+
},
|
|
187
|
+
html_url: "https://github.com/test-user/test-repo",
|
|
188
|
+
description: null,
|
|
189
|
+
created_at: "2024-01-01T00:00:00Z",
|
|
190
|
+
updated_at: "2024-01-01T00:00:00Z",
|
|
191
|
+
homepage: null,
|
|
192
|
+
size: 0,
|
|
193
|
+
stargazers_count: 0,
|
|
194
|
+
watchers_count: 0,
|
|
195
|
+
language: null,
|
|
196
|
+
license: null,
|
|
197
|
+
default_branch: "main",
|
|
198
|
+
topics: [],
|
|
199
|
+
private: false,
|
|
200
|
+
archived: false,
|
|
201
|
+
git_url: "git://github.com/test-user/test-repo.git",
|
|
202
|
+
ssh_url: "git@github.com:test-user/test-repo.git",
|
|
203
|
+
clone_url: "https://github.com/test-user/test-repo.git",
|
|
204
|
+
}),
|
|
205
|
+
});
|
|
206
|
+
fetchMock.mockResolvedValueOnce({
|
|
207
|
+
ok: true,
|
|
208
|
+
json: () => Promise.resolve({
|
|
209
|
+
content: {
|
|
210
|
+
name: "data.csv",
|
|
211
|
+
path: "data.csv",
|
|
212
|
+
sha: "abc123",
|
|
213
|
+
},
|
|
214
|
+
}),
|
|
215
|
+
});
|
|
216
|
+
fetchMock.mockResolvedValueOnce({
|
|
217
|
+
ok: true,
|
|
218
|
+
json: () => Promise.resolve({
|
|
219
|
+
content: {
|
|
220
|
+
name: "datapackage.json",
|
|
221
|
+
path: "datapackage.json",
|
|
222
|
+
sha: "def456",
|
|
223
|
+
},
|
|
224
|
+
}),
|
|
225
|
+
});
|
|
226
|
+
await savePackageToGithub(mockPackage, mockOptions);
|
|
227
|
+
const fileUploadCall = fetchMock.mock.calls[1];
|
|
228
|
+
expect(fileUploadCall).toBeDefined();
|
|
229
|
+
if (!fileUploadCall)
|
|
230
|
+
return;
|
|
231
|
+
expect(fileUploadCall[0]).toEqual("https://api.github.com/repos/test-user/test-repo/contents/data.csv");
|
|
232
|
+
expect(fileUploadCall[1]).toMatchObject({
|
|
233
|
+
method: "PUT",
|
|
234
|
+
headers: {
|
|
235
|
+
Authorization: "Bearer test-api-key",
|
|
236
|
+
"Content-Type": "application/json",
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
const filePayload = JSON.parse(fileUploadCall[1].body);
|
|
240
|
+
expect(filePayload.path).toEqual("data.csv");
|
|
241
|
+
expect(filePayload.message).toEqual('Added file "data.csv"');
|
|
242
|
+
expect(filePayload.content).toBeDefined();
|
|
243
|
+
expect(typeof filePayload.content).toEqual("string");
|
|
244
|
+
});
|
|
245
|
+
it("uploads datapackage.json metadata file", async () => {
|
|
246
|
+
fetchMock.mockResolvedValueOnce({
|
|
247
|
+
ok: true,
|
|
248
|
+
json: () => Promise.resolve({
|
|
249
|
+
id: 12345,
|
|
250
|
+
name: "test-repo",
|
|
251
|
+
full_name: "test-user/test-repo",
|
|
252
|
+
owner: {
|
|
253
|
+
login: "test-user",
|
|
254
|
+
id: 1,
|
|
255
|
+
avatar_url: "https://avatars.githubusercontent.com/u/1",
|
|
256
|
+
html_url: "https://github.com/test-user",
|
|
257
|
+
type: "User",
|
|
258
|
+
},
|
|
259
|
+
html_url: "https://github.com/test-user/test-repo",
|
|
260
|
+
description: null,
|
|
261
|
+
created_at: "2024-01-01T00:00:00Z",
|
|
262
|
+
updated_at: "2024-01-01T00:00:00Z",
|
|
263
|
+
homepage: null,
|
|
264
|
+
size: 0,
|
|
265
|
+
stargazers_count: 0,
|
|
266
|
+
watchers_count: 0,
|
|
267
|
+
language: null,
|
|
268
|
+
license: null,
|
|
269
|
+
default_branch: "main",
|
|
270
|
+
topics: [],
|
|
271
|
+
private: false,
|
|
272
|
+
archived: false,
|
|
273
|
+
git_url: "git://github.com/test-user/test-repo.git",
|
|
274
|
+
ssh_url: "git@github.com:test-user/test-repo.git",
|
|
275
|
+
clone_url: "https://github.com/test-user/test-repo.git",
|
|
276
|
+
}),
|
|
277
|
+
});
|
|
278
|
+
fetchMock.mockResolvedValueOnce({
|
|
279
|
+
ok: true,
|
|
280
|
+
json: () => Promise.resolve({
|
|
281
|
+
content: {
|
|
282
|
+
name: "data.csv",
|
|
283
|
+
path: "data.csv",
|
|
284
|
+
sha: "abc123",
|
|
285
|
+
},
|
|
286
|
+
}),
|
|
287
|
+
});
|
|
288
|
+
fetchMock.mockResolvedValueOnce({
|
|
289
|
+
ok: true,
|
|
290
|
+
json: () => Promise.resolve({
|
|
291
|
+
content: {
|
|
292
|
+
name: "datapackage.json",
|
|
293
|
+
path: "datapackage.json",
|
|
294
|
+
sha: "def456",
|
|
295
|
+
},
|
|
296
|
+
}),
|
|
297
|
+
});
|
|
298
|
+
await savePackageToGithub(mockPackage, mockOptions);
|
|
299
|
+
const datapackageUploadCall = fetchMock.mock.calls[2];
|
|
300
|
+
expect(datapackageUploadCall).toBeDefined();
|
|
301
|
+
if (!datapackageUploadCall)
|
|
302
|
+
return;
|
|
303
|
+
expect(datapackageUploadCall[0]).toEqual("https://api.github.com/repos/test-user/test-repo/contents/datapackage.json");
|
|
304
|
+
const datapackagePayload = JSON.parse(datapackageUploadCall[1].body);
|
|
305
|
+
expect(datapackagePayload.path).toEqual("datapackage.json");
|
|
306
|
+
expect(datapackagePayload.message).toEqual('Added file "datapackage.json"');
|
|
307
|
+
expect(datapackagePayload.content).toBeDefined();
|
|
308
|
+
expect(typeof datapackagePayload.content).toEqual("string");
|
|
309
|
+
});
|
|
310
|
+
it("passes API key as Bearer token in Authorization header", async () => {
|
|
311
|
+
fetchMock.mockResolvedValue({
|
|
312
|
+
ok: true,
|
|
313
|
+
json: () => Promise.resolve({
|
|
314
|
+
id: 12345,
|
|
315
|
+
name: "test-repo",
|
|
316
|
+
owner: {
|
|
317
|
+
login: "test-user",
|
|
318
|
+
id: 1,
|
|
319
|
+
avatar_url: "https://avatars.githubusercontent.com/u/1",
|
|
320
|
+
html_url: "https://github.com/test-user",
|
|
321
|
+
type: "User",
|
|
322
|
+
},
|
|
323
|
+
html_url: "https://github.com/test-user/test-repo",
|
|
324
|
+
description: null,
|
|
325
|
+
created_at: "2024-01-01T00:00:00Z",
|
|
326
|
+
updated_at: "2024-01-01T00:00:00Z",
|
|
327
|
+
homepage: null,
|
|
328
|
+
size: 0,
|
|
329
|
+
stargazers_count: 0,
|
|
330
|
+
watchers_count: 0,
|
|
331
|
+
language: null,
|
|
332
|
+
license: null,
|
|
333
|
+
default_branch: "main",
|
|
334
|
+
topics: [],
|
|
335
|
+
private: false,
|
|
336
|
+
archived: false,
|
|
337
|
+
git_url: "git://github.com/test-user/test-repo.git",
|
|
338
|
+
ssh_url: "git@github.com:test-user/test-repo.git",
|
|
339
|
+
clone_url: "https://github.com/test-user/test-repo.git",
|
|
340
|
+
}),
|
|
341
|
+
});
|
|
342
|
+
await savePackageToGithub(mockPackage, {
|
|
343
|
+
...mockOptions,
|
|
344
|
+
apiKey: "custom-api-key",
|
|
345
|
+
});
|
|
346
|
+
const firstCall = fetchMock.mock.calls[0];
|
|
347
|
+
expect(firstCall).toBeDefined();
|
|
348
|
+
if (!firstCall)
|
|
349
|
+
return;
|
|
350
|
+
const headers = firstCall[1].headers;
|
|
351
|
+
expect(headers.Authorization).toEqual("Bearer custom-api-key");
|
|
352
|
+
});
|
|
353
|
+
it("handles API errors from repository creation", async () => {
|
|
354
|
+
fetchMock.mockResolvedValueOnce({
|
|
355
|
+
ok: false,
|
|
356
|
+
status: 400,
|
|
357
|
+
statusText: "Bad Request",
|
|
358
|
+
text: () => Promise.resolve("Repository name already exists"),
|
|
359
|
+
});
|
|
360
|
+
await expect(savePackageToGithub(mockPackage, mockOptions)).rejects.toThrow("Github API error: 400 Bad Request");
|
|
361
|
+
});
|
|
362
|
+
it("handles API errors from file upload", async () => {
|
|
363
|
+
fetchMock.mockResolvedValueOnce({
|
|
364
|
+
ok: true,
|
|
365
|
+
json: () => Promise.resolve({
|
|
366
|
+
id: 12345,
|
|
367
|
+
name: "test-repo",
|
|
368
|
+
full_name: "test-user/test-repo",
|
|
369
|
+
owner: {
|
|
370
|
+
login: "test-user",
|
|
371
|
+
id: 1,
|
|
372
|
+
avatar_url: "https://avatars.githubusercontent.com/u/1",
|
|
373
|
+
html_url: "https://github.com/test-user",
|
|
374
|
+
type: "User",
|
|
375
|
+
},
|
|
376
|
+
html_url: "https://github.com/test-user/test-repo",
|
|
377
|
+
description: null,
|
|
378
|
+
created_at: "2024-01-01T00:00:00Z",
|
|
379
|
+
updated_at: "2024-01-01T00:00:00Z",
|
|
380
|
+
homepage: null,
|
|
381
|
+
size: 0,
|
|
382
|
+
stargazers_count: 0,
|
|
383
|
+
watchers_count: 0,
|
|
384
|
+
language: null,
|
|
385
|
+
license: null,
|
|
386
|
+
default_branch: "main",
|
|
387
|
+
topics: [],
|
|
388
|
+
private: false,
|
|
389
|
+
archived: false,
|
|
390
|
+
git_url: "git://github.com/test-user/test-repo.git",
|
|
391
|
+
ssh_url: "git@github.com:test-user/test-repo.git",
|
|
392
|
+
clone_url: "https://github.com/test-user/test-repo.git",
|
|
393
|
+
}),
|
|
394
|
+
});
|
|
395
|
+
fetchMock.mockResolvedValueOnce({
|
|
396
|
+
ok: false,
|
|
397
|
+
status: 500,
|
|
398
|
+
statusText: "Internal Server Error",
|
|
399
|
+
text: () => Promise.resolve("Failed to upload file"),
|
|
400
|
+
});
|
|
401
|
+
await expect(savePackageToGithub(mockPackage, mockOptions)).rejects.toThrow("Github API error: 500 Internal Server Error");
|
|
402
|
+
});
|
|
403
|
+
it("handles packages with multiple resources", async () => {
|
|
404
|
+
const multiResourcePackage = {
|
|
405
|
+
...mockPackage,
|
|
406
|
+
resources: [
|
|
407
|
+
{
|
|
408
|
+
name: "resource-1",
|
|
409
|
+
path: getFixturePath("data.csv"),
|
|
410
|
+
format: "csv",
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
name: "resource-2",
|
|
414
|
+
path: getFixturePath("data.csv"),
|
|
415
|
+
format: "json",
|
|
416
|
+
},
|
|
417
|
+
],
|
|
418
|
+
};
|
|
419
|
+
fetchMock.mockResolvedValue({
|
|
420
|
+
ok: true,
|
|
421
|
+
json: () => Promise.resolve({
|
|
422
|
+
id: 12345,
|
|
423
|
+
name: "test-repo",
|
|
424
|
+
full_name: "test-user/test-repo",
|
|
425
|
+
owner: {
|
|
426
|
+
login: "test-user",
|
|
427
|
+
id: 1,
|
|
428
|
+
avatar_url: "https://avatars.githubusercontent.com/u/1",
|
|
429
|
+
html_url: "https://github.com/test-user",
|
|
430
|
+
type: "User",
|
|
431
|
+
},
|
|
432
|
+
html_url: "https://github.com/test-user/test-repo",
|
|
433
|
+
description: null,
|
|
434
|
+
created_at: "2024-01-01T00:00:00Z",
|
|
435
|
+
updated_at: "2024-01-01T00:00:00Z",
|
|
436
|
+
homepage: null,
|
|
437
|
+
size: 0,
|
|
438
|
+
stargazers_count: 0,
|
|
439
|
+
watchers_count: 0,
|
|
440
|
+
language: null,
|
|
441
|
+
license: null,
|
|
442
|
+
default_branch: "main",
|
|
443
|
+
topics: [],
|
|
444
|
+
private: false,
|
|
445
|
+
archived: false,
|
|
446
|
+
git_url: "git://github.com/test-user/test-repo.git",
|
|
447
|
+
ssh_url: "git@github.com:test-user/test-repo.git",
|
|
448
|
+
clone_url: "https://github.com/test-user/test-repo.git",
|
|
449
|
+
}),
|
|
450
|
+
});
|
|
451
|
+
await savePackageToGithub(multiResourcePackage, mockOptions);
|
|
452
|
+
expect(fetchMock).toHaveBeenCalledTimes(4);
|
|
453
|
+
const secondFileUploadCall = fetchMock.mock.calls[2];
|
|
454
|
+
expect(secondFileUploadCall).toBeDefined();
|
|
455
|
+
if (!secondFileUploadCall)
|
|
456
|
+
return;
|
|
457
|
+
expect(secondFileUploadCall[0]).toContain("/contents/");
|
|
458
|
+
});
|
|
459
|
+
it("handles packages with no resources", async () => {
|
|
460
|
+
const emptyPackage = {
|
|
461
|
+
...mockPackage,
|
|
462
|
+
resources: [],
|
|
463
|
+
};
|
|
464
|
+
fetchMock.mockResolvedValueOnce({
|
|
465
|
+
ok: true,
|
|
466
|
+
json: () => Promise.resolve({
|
|
467
|
+
id: 12345,
|
|
468
|
+
name: "test-repo",
|
|
469
|
+
full_name: "test-user/test-repo",
|
|
470
|
+
owner: {
|
|
471
|
+
login: "test-user",
|
|
472
|
+
id: 1,
|
|
473
|
+
avatar_url: "https://avatars.githubusercontent.com/u/1",
|
|
474
|
+
html_url: "https://github.com/test-user",
|
|
475
|
+
type: "User",
|
|
476
|
+
},
|
|
477
|
+
html_url: "https://github.com/test-user/test-repo",
|
|
478
|
+
description: null,
|
|
479
|
+
created_at: "2024-01-01T00:00:00Z",
|
|
480
|
+
updated_at: "2024-01-01T00:00:00Z",
|
|
481
|
+
homepage: null,
|
|
482
|
+
size: 0,
|
|
483
|
+
stargazers_count: 0,
|
|
484
|
+
watchers_count: 0,
|
|
485
|
+
language: null,
|
|
486
|
+
license: null,
|
|
487
|
+
default_branch: "main",
|
|
488
|
+
topics: [],
|
|
489
|
+
private: false,
|
|
490
|
+
archived: false,
|
|
491
|
+
git_url: "git://github.com/test-user/test-repo.git",
|
|
492
|
+
ssh_url: "git@github.com:test-user/test-repo.git",
|
|
493
|
+
clone_url: "https://github.com/test-user/test-repo.git",
|
|
494
|
+
}),
|
|
495
|
+
});
|
|
496
|
+
fetchMock.mockResolvedValueOnce({
|
|
497
|
+
ok: true,
|
|
498
|
+
json: () => Promise.resolve({
|
|
499
|
+
content: {
|
|
500
|
+
name: "datapackage.json",
|
|
501
|
+
path: "datapackage.json",
|
|
502
|
+
sha: "def456",
|
|
503
|
+
},
|
|
504
|
+
}),
|
|
505
|
+
});
|
|
506
|
+
const result = await savePackageToGithub(emptyPackage, mockOptions);
|
|
507
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
508
|
+
expect(result.repoUrl).toEqual("https://github.com/test-user/test-repo");
|
|
509
|
+
});
|
|
510
|
+
it("skips resources without path", async () => {
|
|
511
|
+
const packageWithoutPath = {
|
|
512
|
+
...mockPackage,
|
|
513
|
+
resources: [
|
|
514
|
+
{
|
|
515
|
+
name: "resource-without-path",
|
|
516
|
+
format: "csv",
|
|
517
|
+
},
|
|
518
|
+
],
|
|
519
|
+
};
|
|
520
|
+
fetchMock.mockResolvedValueOnce({
|
|
521
|
+
ok: true,
|
|
522
|
+
json: () => Promise.resolve({
|
|
523
|
+
id: 12345,
|
|
524
|
+
name: "test-repo",
|
|
525
|
+
full_name: "test-user/test-repo",
|
|
526
|
+
owner: {
|
|
527
|
+
login: "test-user",
|
|
528
|
+
id: 1,
|
|
529
|
+
avatar_url: "https://avatars.githubusercontent.com/u/1",
|
|
530
|
+
html_url: "https://github.com/test-user",
|
|
531
|
+
type: "User",
|
|
532
|
+
},
|
|
533
|
+
html_url: "https://github.com/test-user/test-repo",
|
|
534
|
+
description: null,
|
|
535
|
+
created_at: "2024-01-01T00:00:00Z",
|
|
536
|
+
updated_at: "2024-01-01T00:00:00Z",
|
|
537
|
+
homepage: null,
|
|
538
|
+
size: 0,
|
|
539
|
+
stargazers_count: 0,
|
|
540
|
+
watchers_count: 0,
|
|
541
|
+
language: null,
|
|
542
|
+
license: null,
|
|
543
|
+
default_branch: "main",
|
|
544
|
+
topics: [],
|
|
545
|
+
private: false,
|
|
546
|
+
archived: false,
|
|
547
|
+
git_url: "git://github.com/test-user/test-repo.git",
|
|
548
|
+
ssh_url: "git@github.com:test-user/test-repo.git",
|
|
549
|
+
clone_url: "https://github.com/test-user/test-repo.git",
|
|
550
|
+
}),
|
|
551
|
+
});
|
|
552
|
+
fetchMock.mockResolvedValueOnce({
|
|
553
|
+
ok: true,
|
|
554
|
+
json: () => Promise.resolve({
|
|
555
|
+
content: {
|
|
556
|
+
name: "datapackage.json",
|
|
557
|
+
path: "datapackage.json",
|
|
558
|
+
sha: "def456",
|
|
559
|
+
},
|
|
560
|
+
}),
|
|
561
|
+
});
|
|
562
|
+
await savePackageToGithub(packageWithoutPath, mockOptions);
|
|
563
|
+
expect(fetchMock).toHaveBeenCalledTimes(2);
|
|
564
|
+
});
|
|
565
|
+
});
|
|
566
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2F2ZS5zcGVjLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vcGx1Z2lucy9naXRodWIvcGFja2FnZS9zYXZlLnNwZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxNQUFNLFdBQVcsQ0FBQTtBQUVwQyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQTtBQUNqRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsTUFBTSxRQUFRLENBQUE7QUFDeEUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sV0FBVyxDQUFBO0FBRS9DLFFBQVEsQ0FBQyxxQkFBcUIsRUFBRSxHQUFHLEVBQUU7SUFDbkMsTUFBTSxjQUFjLEdBQUcsQ0FBQyxJQUFZLEVBQUUsRUFBRSxDQUN0QyxRQUFRLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxPQUFPLGFBQWEsSUFBSSxFQUFFLENBQUMsQ0FBQTtJQUVwRSxNQUFNLFdBQVcsR0FBWTtRQUMzQixJQUFJLEVBQUUsY0FBYztRQUNwQixLQUFLLEVBQUUsY0FBYztRQUNyQixXQUFXLEVBQUUsZ0JBQWdCO1FBQzdCLE9BQU8sRUFBRSxPQUFPO1FBQ2hCLFNBQVMsRUFBRTtZQUNUO2dCQUNFLElBQUksRUFBRSxlQUFlO2dCQUNyQixJQUFJLEVBQUUsY0FBYyxDQUFDLFVBQVUsQ0FBQztnQkFDaEMsTUFBTSxFQUFFLEtBQUs7Z0JBQ2IsS0FBSyxFQUFFLEdBQUc7YUFDWDtTQUNGO0tBQ0YsQ0FBQTtJQUVELE1BQU0sV0FBVyxHQUFHO1FBQ2xCLE1BQU0sRUFBRSxjQUFjO1FBQ3RCLElBQUksRUFBRSxXQUFXO0tBQ2xCLENBQUE7SUFFRCxNQUFNLGFBQWEsR0FBRyxVQUFVLENBQUMsS0FBSyxDQUFBO0lBQ3RDLElB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TyxFQUFFLHdDQUF3QztnQkFDakQsU0FBUyxFQUFFLDRDQUE0QzthQUN4RCxDQUFDO1NBQ0wsQ0FBQyxDQUFBO1FBRUYsU0FBUyxDQUFDLHFCQUFxQixDQUFDO1lBQzlCLEVBQUUsRUFBRSxJQUFJO1lBQ1IsSUFBSSxFQUFFLEdBQUcsRUFBRSxDQUNULE9BQU8sQ0FBQyxPQUFPLENBQUM7Z0JBQ2QsT0FBTyxFQUFFO29CQUNQLElBQUksRUFBRSxrQkFBa0I7b0JBQ3hCLElBQUksRUFBRSxrQkFBa0I7b0JBQ3hCLEdBQUcsRUFBRSxRQUFRO2lCQUNkO2FBQ0YsQ0FBQztTQUNMLENBQUMsQ0FBQTtRQUVGLE1BQU0sbUJBQW1CLENBQUMsa0JBQWtCLEVBQUUsV0FBVyxDQUFDLENBQUE7UUFFMUQsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFBO0lBQzVDLENBQUMsQ0FBQyxDQUFBO0FBQ0osQ0FBQyxDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyByZWxhdGl2ZSB9IGZyb20gXCJub2RlOnBhdGhcIlxuaW1wb3J0IHR5cGUgeyBQYWNrYWdlIH0gZnJvbSBcIkBmcmljdGlvbmxlc3MtdHMvbWV0YWRhdGFcIlxuaW1wb3J0IHsgbG9hZFBhY2thZ2VEZXNjcmlwdG9yIH0gZnJvbSBcIkBmcmljdGlvbmxlc3MtdHMvbWV0YWRhdGFcIlxuaW1wb3J0IHsgYWZ0ZXJFYWNoLCBiZWZvcmVFYWNoLCBkZXNjcmliZSwgZXhwZWN0LCBpdCwgdmkgfSBmcm9tIFwidml0ZXN0XCJcbmltcG9ydCB7IHNhdmVQYWNrYWdlVG9HaXRodWIgfSBmcm9tIFwiLi9zYXZlLnRzXCJcblxuZGVzY3JpYmUoXCJzYXZlUGFja2FnZVRvR2l0aHViXCIsICgpID0+IHtcbiAgY29uc3QgZ2V0Rml4dHVyZVBhdGggPSAobmFtZTogc3RyaW5nKSA9PlxuICAgIHJlbGF0aXZlKHByb2Nlc3MuY3dkKCksIGAke2ltcG9ydC5tZXRhLmRpcm5hbWV9L2ZpeHR1cmVzLyR7bmFtZX1gKVxuXG4gIGNvbnN0IG1vY2tQYWNrYWdlOiBQYWNrYWdlID0ge1xuICAgIG5hbWU6IFwidGVzdC1wYWNrYWdlXCIsXG4gICAgdGl0bGU6IFwiVGVzdCBQYWNrYWdlXCIsXG4gICAgZGVzY3JpcHRpb246IFwiQSB0ZXN0IHBhY2thZ2VcIixcbiAgICB2ZXJzaW9uOiBcIjEuMC4wXCIsXG4gICAgcmVzb3VyY2VzOiBbXG4gICAgICB7XG4gICAgICAgIG5hbWU6IFwidGVzdC1yZXNvdXJjZVwiLFxuICAgICAgICBwYXRoOiBnZXRGaXh0dXJlUGF0aChcImRhdGEuY3N2XCIpLFxuICAgICAgICBmb3JtYXQ6IFwiY3N2XCIsXG4gICAgICAgIGJ5dGVzOiAxMDAsXG4gICAgICB9LFxuICAgIF0sXG4gIH1cblxuICBjb25zdCBtb2NrT3B0aW9ucyA9IHtcbiAgICBhcGlLZXk6IFwidGVzdC1hcGkta2V5XCIsXG4gICAgcmVwbzogXCJ0ZXN0LXJlcG9cIixcbiAgfVxuXG4gIGNvbnN0IG9yaWdpbmFsRmV0Y2ggPSBnbG9iYWxUaGlzLmZldGNoXG4gIGxldCBmZXRjaE1vY2s6IFJldHVyblR5cGU8dHlwZW9mIHZpLmZuPlxuXG4gIGJlZm9yZUVhY2goKCkgPT4ge1xuICAgIGZldGNoTW9jayA9IHZpLmZuKClcbiAgICAvLyBAdHMtaWdub3JlXG4gICAgZ2xvYmFsVGhpcy5mZXRjaCA9IGZldGNoTW9ja1xuICB9KVxuXG4gIGFmdGVyRWFjaCgoKSA9PiB7XG4gICAgZ2xvYmFsVGhpcy5mZXRjaCA9IG9yaWdpbmFsRmV0Y2hcbiAgICB2aS5yZXNldEFsbE1vY2tzKClcbiAgfSlcblxuICBpdC5za2lwKFwic2hvdWxkIHNhdmUgYSBwYWNrYWdlXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBkYXRhUGFja2FnZSA9IGF3YWl0IGxvYWRQYWNrYWdlRGVzY3JpcHRvcihcbiAgICAgIFwiY29yZS9wYWNrYWdlL2ZpeHR1cmVzL3BhY2thZ2UuanNvblwiLFxuICAgIClcblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHNhdmVQYWNrYWdlVG9HaXRodWIoZGF0YVBhY2thZ2UsIHtcbiAgICAgIGFwaUtleTogXCI8a2V5PlwiLFxuICAgICAgcmVwbzogXCJ0ZXN0XCIsXG4gICAgfSlcblxuICAgIGNvbnNvbGUubG9nKHJlc3VsdClcblxuICAgIGV4cGVjdCh0cnVlKS50b0JlRGVmaW5lZCgpXG4gIH0pXG5cbiAgaXQoXCJjcmVhdGVzIGEgcmVwb3NpdG9yeSBpbiBHaXRIdWIgd2l0aCBjb3JyZWN0IEFQSSBjYWxsc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgaWQ6IDEyMzQ1LFxuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXBvXCIsXG4gICAgICAgICAgZnVsbF9uYW1lOiBcInRlc3QtdXNlci90ZXN0LXJlcG9cIixcbiAgICAgICAgICBvd25lcjoge1xuICAgICAgICAgICAgbG9naW46IFwidGVzdC11c2VyXCIsXG4gICAgICAgICAgICBpZDogMSxcbiAgICAgICAgICAgIGF2YXRhcl91cmw6IFwiaHR0cHM6Ly9hdmF0YXJzLmdpdGh1YnVzZXJjb250ZW50LmNvbS91LzFcIixcbiAgICAgICAgICAgIGh0bWxfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXJcIixcbiAgICAgICAgICAgIHR5cGU6IFwiVXNlclwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgaHRtbF91cmw6IFwiaHR0cHM6Ly9naXRodWIuY29tL3Rlc3QtdXNlci90ZXN0LXJlcG9cIixcbiAgICAgICAgICBkZXNjcmlwdGlvbjogbnVsbCxcbiAgICAgICAgICBjcmVhdGVkX2F0OiBcIjIwMjQtMDEtMDFUMDA6MDA6MDBaXCIsXG4gICAgICAgICAgdXBkYXRlZF9hdDogXCIyMDI0LTAxLTAxVDAwOjAwOjAwWlwiLFxuICAgICAgICAgIGhvbWVwYWdlOiBudWxsLFxuICAgICAgICAgIHNpemU6IDAsXG4gICAgICAgICAgc3RhcmdhemVyc19jb3VudDogMCxcbiAgICAgICAgICB3YXRjaGVyc19jb3VudDogMCxcbiAgICAgICAgICBsYW5ndWFnZTogbnVsbCxcbiAgICAgICAgICBsaWNlbnNlOiBudWxsLFxuICAgICAgICAgIGRlZmF1bHRfYnJhbmNoOiBcIm1haW5cIixcbiAgICAgICAgICB0b3BpY3M6IFtdLFxuICAgICAgICAgIHByaXZhdGU6IGZhbHNlLFxuICAgICAgICAgIGFyY2hpdmVkOiBmYWxzZSxcbiAgICAgICAgICBnaXRfdXJsOiBcImdpdDovL2dpdGh1Yi5jb20vdGVzdC11c2VyL3Rlc3QtcmVwby5naXRcIixcbiAgICAgICAgICBzc2hfdXJsOiBcImdpdEBnaXRodWIuY29tOnRlc3QtdXNlci90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgICAgY2xvbmVfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXIvdGVzdC1yZXBvLmdpdFwiLFxuICAgICAgICB9KSxcbiAgICB9KVxuXG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgY29udGVudDoge1xuICAgICAgICAgICAgbmFtZTogXCJkYXRhLmNzdlwiLFxuICAgICAgICAgICAgcGF0aDogXCJkYXRhLmNzdlwiLFxuICAgICAgICAgICAgc2hhOiBcImFiYzEyM1wiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgIH0pXG5cbiAgICBmZXRjaE1vY2subW9ja1Jlc29sdmVkVmFsdWVPbmNlKHtcbiAgICAgIG9rOiB0cnVlLFxuICAgICAganNvbjogKCkgPT5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICBjb250ZW50OiB7XG4gICAgICAgICAgICBuYW1lOiBcImRhdGFwYWNrYWdlLmpzb25cIixcbiAgICAgICAgICAgIHBhdGg6IFwiZGF0YXBhY2thZ2UuanNvblwiLFxuICAgICAgICAgICAgc2hhOiBcImRlZjQ1NlwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgIH0pXG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBzYXZlUGFja2FnZVRvR2l0aHViKG1vY2tQYWNrYWdlLCBtb2NrT3B0aW9ucylcblxuICAgIGV4cGVjdChmZXRjaE1vY2spLnRvSGF2ZUJlZW5DYWxsZWRUaW1lcygzKVxuXG4gICAgY29uc3QgcmVwb0NyZWF0ZUNhbGwgPSBmZXRjaE1vY2subW9jay5jYWxsc1swXVxuICAgIGV4cGVjdChyZXBvQ3JlYXRlQ2FsbCkudG9CZURlZmluZWQoKVxuICAgIGlmICghcmVwb0NyZWF0ZUNhbGwpIHJldHVyblxuXG4gICAgZXhwZWN0KHJlcG9DcmVhdGVDYWxsWzBdKS50b0VxdWFsKFwiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS91c2VyL3JlcG9zXCIpXG4gICAgZXhwZWN0KHJlcG9DcmVhdGVDYWxsWzFdKS50b01hdGNoT2JqZWN0KHtcbiAgICAgIG1ldGhvZDogXCJQT1NUXCIsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIEF1dGhvcml6YXRpb246IFwiQmVhcmVyIHRlc3QtYXBpLWtleVwiLFxuICAgICAgICBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgIH0sXG4gICAgfSlcblxuICAgIGNvbnN0IHJlcG9QYXlsb2FkID0gSlNPTi5wYXJzZShyZXBvQ3JlYXRlQ2FsbFsxXS5ib2R5KVxuICAgIGV4cGVjdChyZXBvUGF5bG9hZC5uYW1lKS50b0VxdWFsKFwidGVzdC1yZXBvXCIpXG4gICAgZXhwZWN0KHJlcG9QYXlsb2FkLmF1dG9faW5pdCkudG9FcXVhbCh0cnVlKVxuXG4gICAgZXhwZWN0KHJlc3VsdCkudG9FcXVhbCh7XG4gICAgICBwYXRoOiBcImh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS90ZXN0LXVzZXIvdGVzdC1yZXBvL3JlZnMvaGVhZHMvbWFpbi9kYXRhUGFja2FnZS5qc29uXCIsXG4gICAgICByZXBvVXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXIvdGVzdC1yZXBvXCIsXG4gICAgfSlcbiAgfSlcblxuICBpdChcImNyZWF0ZXMgYSByZXBvc2l0b3J5IGluIGFuIG9yZ2FuaXphdGlvbiB3aGVuIG9yZyBpcyBzcGVjaWZpZWRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGZldGNoTW9jay5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2Uoe1xuICAgICAgb2s6IHRydWUsXG4gICAgICBqc29uOiAoKSA9PlxuICAgICAgICBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgIGlkOiAxMjM0NSxcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcmVwb1wiLFxuICAgICAgICAgIGZ1bGxfbmFtZTogXCJ0ZXN0LW9yZy90ZXN0LXJlcG9cIixcbiAgICAgICAgICBvd25lcjoge1xuICAgICAgICAgICAgbG9naW46IFwidGVzdC1vcmdcIixcbiAgICAgICAgICAgIGlkOiAyLFxuICAgICAgICAgICAgYXZhdGFyX3VybDogXCJodHRwczovL2F2YXRhcnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3UvMlwiLFxuICAgICAgICAgICAgaHRtbF91cmw6IFwiaHR0cHM6Ly9naXRodWIuY29tL3Rlc3Qtb3JnXCIsXG4gICAgICAgICAgICB0eXBlOiBcIk9yZ2FuaXphdGlvblwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgaHRtbF91cmw6IFwiaHR0cHM6Ly9naXRodWIuY29tL3Rlc3Qtb3JnL3Rlc3QtcmVwb1wiLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiBudWxsLFxuICAgICAgICAgIGNyZWF0ZWRfYXQ6IFwiMjAyNC0wMS0wMVQwMDowMDowMFpcIixcbiAgICAgICAgICB1cGRhdGVkX2F0OiBcIjIwMjQtMDEtMDFUMDA6MDA6MDBaXCIsXG4gICAgICAgICAgaG9tZXBhZ2U6IG51bGwsXG4gICAgICAgICAgc2l6ZTogMCxcbiAgICAgICAgICBzdGFyZ2F6ZXJzX2NvdW50OiAwLFxuICAgICAgICAgIHdhdGNoZXJzX2NvdW50OiAwLFxuICAgICAgICAgIGxhbmd1YWdlOiBudWxsLFxuICAgICAgICAgIGxpY2Vuc2U6IG51bGwsXG4gICAgICAgICAgZGVmYXVsdF9icmFuY2g6IFwibWFpblwiLFxuICAgICAgICAgIHRvcGljczogW10sXG4gICAgICAgICAgcHJpdmF0ZTogZmFsc2UsXG4gICAgICAgICAgYXJjaGl2ZWQ6IGZhbHNlLFxuICAgICAgICAgIGdpdF91cmw6IFwiZ2l0Oi8vZ2l0aHViLmNvbS90ZXN0LW9yZy90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgICAgc3NoX3VybDogXCJnaXRAZ2l0aHViLmNvbTp0ZXN0LW9yZy90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgICAgY2xvbmVfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LW9yZy90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgIH0pLFxuICAgIH0pXG5cbiAgICBmZXRjaE1vY2subW9ja1Jlc29sdmVkVmFsdWUoe1xuICAgICAgb2s6IHRydWUsXG4gICAgICBqc29uOiAoKSA9PlxuICAgICAgICBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgIGNvbnRlbnQ6IHtcbiAgICAgICAgICAgIG5hbWU6IFwiZmlsZVwiLFxuICAgICAgICAgICAgcGF0aDogXCJmaWxlXCIsXG4gICAgICAgICAgICBzaGE6IFwiYWJjMTIzXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSksXG4gICAgfSlcblxuICAgIGF3YWl0IHNhdmVQYWNrYWdlVG9HaXRodWIobW9ja1BhY2thZ2UsIHtcbiAgICAgIC4uLm1vY2tPcHRpb25zLFxuICAgICAgb3JnOiBcInRlc3Qtb3JnXCIsXG4gICAgfSlcblxuICAgIGNvbnN0IHJlcG9DcmVhdGVDYWxsID0gZmV0Y2hNb2NrLm1vY2suY2FsbHNbMF1cbiAgICBleHBlY3QocmVwb0NyZWF0ZUNhbGwpLnRvQmVEZWZpbmVkKClcbiAgICBpZiAoIXJlcG9DcmVhdGVDYWxsKSByZXR1cm5cblxuICAgIGV4cGVjdChyZXBvQ3JlYXRlQ2FsbFswXSkudG9FcXVhbChcbiAgICAgIFwiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9vcmdzL3Rlc3Qtb3JnL3JlcG9zXCIsXG4gICAgKVxuICB9KVxuXG4gIGl0KFwidXBsb2FkcyByZXNvdXJjZSBmaWxlcyB3aXRoIGJhc2U2NCBlbmNvZGluZ1wiLCBhc3luYyAoKSA9PiB7XG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgaWQ6IDEyMzQ1LFxuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXBvXCIsXG4gICAgICAgICAgZnVsbF9uYW1lOiBcInRlc3QtdXNlci90ZXN0LXJlcG9cIixcbiAgICAgICAgICBvd25lcjoge1xuICAgICAgICAgICAgbG9naW46IFwidGVzdC11c2VyXCIsXG4gICAgICAgICAgICBpZDogMSxcbiAgICAgICAgICAgIGF2YXRhcl91cmw6IFwiaHR0cHM6Ly9hdmF0YXJzLmdpdGh1YnVzZXJjb250ZW50LmNvbS91LzFcIixcbiAgICAgICAgICAgIGh0bWxfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXJcIixcbiAgICAgICAgICAgIHR5cGU6IFwiVXNlclwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgaHRtbF91cmw6IFwiaHR0cHM6Ly9naXRodWIuY29tL3Rlc3QtdXNlci90ZXN0LXJlcG9cIixcbiAgICAgICAgICBkZXNjcmlwdGlvbjogbnVsbCxcbiAgICAgICAgICBjcmVhdGVkX2F0OiBcIjIwMjQtMDEtMDFUMDA6MDA6MDBaXCIsXG4gICAgICAgICAgdXBkYXRlZF9hdDogXCIyMDI0LTAxLTAxVDAwOjAwOjAwWlwiLFxuICAgICAgICAgIGhvbWVwYWdlOiBudWxsLFxuICAgICAgICAgIHNpemU6IDAsXG4gICAgICAgICAgc3RhcmdhemVyc19jb3VudDogMCxcbiAgICAgICAgICB3YXRjaGVyc19jb3VudDogMCxcbiAgICAgICAgICBsYW5ndWFnZTogbnVsbCxcbiAgICAgICAgICBsaWNlbnNlOiBudWxsLFxuICAgICAgICAgIGRlZmF1bHRfYnJhbmNoOiBcIm1haW5cIixcbiAgICAgICAgICB0b3BpY3M6IFtdLFxuICAgICAgICAgIHByaXZhdGU6IGZhbHNlLFxuICAgICAgICAgIGFyY2hpdmVkOiBmYWxzZSxcbiAgICAgICAgICBnaXRfdXJsOiBcImdpdDovL2dpdGh1Yi5jb20vdGVzdC11c2VyL3Rlc3QtcmVwby5naXRcIixcbiAgICAgICAgICBzc2hfdXJsOiBcImdpdEBnaXRodWIuY29tOnRlc3QtdXNlci90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgICAgY2xvbmVfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXIvdGVzdC1yZXBvLmdpdFwiLFxuICAgICAgICB9KSxcbiAgICB9KVxuXG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgY29udGVudDoge1xuICAgICAgICAgICAgbmFtZTogXCJkYXRhLmNzdlwiLFxuICAgICAgICAgICAgcGF0aDogXCJkYXRhLmNzdlwiLFxuICAgICAgICAgICAgc2hhOiBcImFiYzEyM1wiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgIH0pXG5cbiAgICBmZXRjaE1vY2subW9ja1Jlc29sdmVkVmFsdWVPbmNlKHtcbiAgICAgIG9rOiB0cnVlLFxuICAgICAganNvbjogKCkgPT5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICBjb250ZW50OiB7XG4gICAgICAgICAgICBuYW1lOiBcImRhdGFwYWNrYWdlLmpzb25cIixcbiAgICAgICAgICAgIHBhdGg6IFwiZGF0YXBhY2thZ2UuanNvblwiLFxuICAgICAgICAgICAgc2hhOiBcImRlZjQ1NlwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgIH0pXG5cbiAgICBhd2FpdCBzYXZlUGFja2FnZVRvR2l0aHViKG1vY2tQYWNrYWdlLCBtb2NrT3B0aW9ucylcblxuICAgIGNvbnN0IGZpbGVVcGxvYWRDYWxsID0gZmV0Y2hNb2NrLm1vY2suY2FsbHNbMV1cbiAgICBleHBlY3QoZmlsZVVwbG9hZENhbGwpLnRvQmVEZWZpbmVkKClcbiAgICBpZiAoIWZpbGVVcGxvYWRDYWxsKSByZXR1cm5cblxuICAgIGV4cGVjdChmaWxlVXBsb2FkQ2FsbFswXSkudG9FcXVhbChcbiAgICAgIFwiaHR0cHM6Ly9hcGkuZ2l0aHViLmNvbS9yZXBvcy90ZXN0LXVzZXIvdGVzdC1yZXBvL2NvbnRlbnRzL2RhdGEuY3N2XCIsXG4gICAgKVxuICAgIGV4cGVjdChmaWxlVXBsb2FkQ2FsbFsxXSkudG9NYXRjaE9iamVjdCh7XG4gICAgICBtZXRob2Q6IFwiUFVUXCIsXG4gICAgICBoZWFkZXJzOiB7XG4gICAgICAgIEF1dGhvcml6YXRpb246IFwiQmVhcmVyIHRlc3QtYXBpLWtleVwiLFxuICAgICAgICBcIkNvbnRlbnQtVHlwZVwiOiBcImFwcGxpY2F0aW9uL2pzb25cIixcbiAgICAgIH0sXG4gICAgfSlcblxuICAgIGNvbnN0IGZpbGVQYXlsb2FkID0gSlNPTi5wYXJzZShmaWxlVXBsb2FkQ2FsbFsxXS5ib2R5KVxuICAgIGV4cGVjdChmaWxlUGF5bG9hZC5wYXRoKS50b0VxdWFsKFwiZGF0YS5jc3ZcIilcbiAgICBleHBlY3QoZmlsZVBheWxvYWQubWVzc2FnZSkudG9FcXVhbCgnQWRkZWQgZmlsZSBcImRhdGEuY3N2XCInKVxuICAgIGV4cGVjdChmaWxlUGF5bG9hZC5jb250ZW50KS50b0JlRGVmaW5lZCgpXG4gICAgZXhwZWN0KHR5cGVvZiBmaWxlUGF5bG9hZC5jb250ZW50KS50b0VxdWFsKFwic3RyaW5nXCIpXG4gIH0pXG5cbiAgaXQoXCJ1cGxvYWRzIGRhdGFwYWNrYWdlLmpzb24gbWV0YWRhdGEgZmlsZVwiLCBhc3luYyAoKSA9PiB7XG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgaWQ6IDEyMzQ1LFxuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXBvXCIsXG4gICAgICAgICAgZnVsbF9uYW1lOiBcInRlc3QtdXNlci90ZXN0LXJlcG9cIixcbiAgICAgICAgICBvd25lcjoge1xuICAgICAgICAgICAgbG9naW46IFwidGVzdC11c2VyXCIsXG4gICAgICAgICAgICBpZDogMSxcbiAgICAgICAgICAgIGF2YXRhcl91cmw6IFwiaHR0cHM6Ly9hdmF0YXJzLmdpdGh1YnVzZXJjb250ZW50LmNvbS91LzFcIixcbiAgICAgICAgICAgIGh0bWxfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXJcIixcbiAgICAgICAgICAgIHR5cGU6IFwiVXNlclwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgaHRtbF91cmw6IFwiaHR0cHM6Ly9naXRodWIuY29tL3Rlc3QtdXNlci90ZXN0LXJlcG9cIixcbiAgICAgICAgICBkZXNjcmlwdGlvbjogbnVsbCxcbiAgICAgICAgICBjcmVhdGVkX2F0OiBcIjIwMjQtMDEtMDFUMDA6MDA6MDBaXCIsXG4gICAgICAgICAgdXBkYXRlZF9hdDogXCIyMDI0LTAxLTAxVDAwOjAwOjAwWlwiLFxuICAgICAgICAgIGhvbWVwYWdlOiBudWxsLFxuICAgICAgICAgIHNpemU6IDAsXG4gICAgICAgICAgc3RhcmdhemVyc19jb3VudDogMCxcbiAgICAgICAgICB3YXRjaGVyc19jb3VudDogMCxcbiAgICAgICAgICBsYW5ndWFnZTogbnVsbCxcbiAgICAgICAgICBsaWNlbnNlOiBudWxsLFxuICAgICAgICAgIGRlZmF1bHRfYnJhbmNoOiBcIm1haW5cIixcbiAgICAgICAgICB0b3BpY3M6IFtdLFxuICAgICAgICAgIHByaXZhdGU6IGZhbHNlLFxuICAgICAgICAgIGFyY2hpdmVkOiBmYWxzZSxcbiAgICAgICAgICBnaXRfdXJsOiBcImdpdDovL2dpdGh1Yi5jb20vdGVzdC11c2VyL3Rlc3QtcmVwby5naXRcIixcbiAgICAgICAgICBzc2hfdXJsOiBcImdpdEBnaXRodWIuY29tOnRlc3QtdXNlci90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgICAgY2xvbmVfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXIvdGVzdC1yZXBvLmdpdFwiLFxuICAgICAgICB9KSxcbiAgICB9KVxuXG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgY29udGVudDoge1xuICAgICAgICAgICAgbmFtZTogXCJkYXRhLmNzdlwiLFxuICAgICAgICAgICAgcGF0aDogXCJkYXRhLmNzdlwiLFxuICAgICAgICAgICAgc2hhOiBcImFiYzEyM1wiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgIH0pXG5cbiAgICBmZXRjaE1vY2subW9ja1Jlc29sdmVkVmFsdWVPbmNlKHtcbiAgICAgIG9rOiB0cnVlLFxuICAgICAganNvbjogKCkgPT5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICBjb250ZW50OiB7XG4gICAgICAgICAgICBuYW1lOiBcImRhdGFwYWNrYWdlLmpzb25cIixcbiAgICAgICAgICAgIHBhdGg6IFwiZGF0YXBhY2thZ2UuanNvblwiLFxuICAgICAgICAgICAgc2hhOiBcImRlZjQ1NlwiLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pLFxuICAgIH0pXG5cbiAgICBhd2FpdCBzYXZlUGFja2FnZVRvR2l0aHViKG1vY2tQYWNrYWdlLCBtb2NrT3B0aW9ucylcblxuICAgIGNvbnN0IGRhdGFwYWNrYWdlVXBsb2FkQ2FsbCA9IGZldGNoTW9jay5tb2NrLmNhbGxzWzJdXG4gICAgZXhwZWN0KGRhdGFwYWNrYWdlVXBsb2FkQ2FsbCkudG9CZURlZmluZWQoKVxuICAgIGlmICghZGF0YXBhY2thZ2VVcGxvYWRDYWxsKSByZXR1cm5cblxuICAgIGV4cGVjdChkYXRhcGFja2FnZVVwbG9hZENhbGxbMF0pLnRvRXF1YWwoXG4gICAgICBcImh0dHBzOi8vYXBpLmdpdGh1Yi5jb20vcmVwb3MvdGVzdC11c2VyL3Rlc3QtcmVwby9jb250ZW50cy9kYXRhcGFja2FnZS5qc29uXCIsXG4gICAgKVxuXG4gICAgY29uc3QgZGF0YXBhY2thZ2VQYXlsb2FkID0gSlNPTi5wYXJzZShkYXRhcGFja2FnZVVwbG9hZENhbGxbMV0uYm9keSlcbiAgICBleHBlY3QoZGF0YXBhY2thZ2VQYXlsb2FkLnBhdGgpLnRvRXF1YWwoXCJkYXRhcGFja2FnZS5qc29uXCIpXG4gICAgZXhwZWN0KGRhdGFwYWNrYWdlUGF5bG9hZC5tZXNzYWdlKS50b0VxdWFsKCdBZGRlZCBmaWxlIFwiZGF0YXBhY2thZ2UuanNvblwiJylcbiAgICBleHBlY3QoZGF0YXBhY2thZ2VQYXlsb2FkLmNvbnRlbnQpLnRvQmVEZWZpbmVkKClcbiAgICBleHBlY3QodHlwZW9mIGRhdGFwYWNrYWdlUGF5bG9hZC5jb250ZW50KS50b0VxdWFsKFwic3RyaW5nXCIpXG4gIH0pXG5cbiAgaXQoXCJwYXNzZXMgQVBJIGtleSBhcyBCZWFyZXIgdG9rZW4gaW4gQXV0aG9yaXphdGlvbiBoZWFkZXJcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGZldGNoTW9jay5tb2NrUmVzb2x2ZWRWYWx1ZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgaWQ6IDEyMzQ1LFxuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXBvXCIsXG4gICAgICAgICAgb3duZXI6IHtcbiAgICAgICAgICAgIGxvZ2luOiBcInRlc3QtdXNlclwiLFxuICAgICAgICAgICAgaWQ6IDEsXG4gICAgICAgICAgICBhdmF0YXJfdXJsOiBcImh0dHBzOi8vYXZhdGFycy5naXRodWJ1c2VyY29udGVudC5jb20vdS8xXCIsXG4gICAgICAgICAgICBodG1sX3VybDogXCJodHRwczovL2dpdGh1Yi5jb20vdGVzdC11c2VyXCIsXG4gICAgICAgICAgICB0eXBlOiBcIlVzZXJcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIGh0bWxfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXIvdGVzdC1yZXBvXCIsXG4gICAgICAgICAgZGVzY3JpcHRpb246IG51bGwsXG4gICAgICAgICAgY3JlYXRlZF9hdDogXCIyMDI0LTAxLTAxVDAwOjAwOjAwWlwiLFxuICAgICAgICAgIHVwZGF0ZWRfYXQ6IFwiMjAyNC0wMS0wMVQwMDowMDowMFpcIixcbiAgICAgICAgICBob21lcGFnZTogbnVsbCxcbiAgICAgICAgICBzaXplOiAwLFxuICAgICAgICAgIHN0YXJnYXplcnNfY291bnQ6IDAsXG4gICAgICAgICAgd2F0Y2hlcnNfY291bnQ6IDAsXG4gICAgICAgICAgbGFuZ3VhZ2U6IG51bGwsXG4gICAgICAgICAgbGljZW5zZTogbnVsbCxcbiAgICAgICAgICBkZWZhdWx0X2JyYW5jaDogXCJtYWluXCIsXG4gICAgICAgICAgdG9waWNzOiBbXSxcbiAgICAgICAgICBwcml2YXRlOiBmYWxzZSxcbiAgICAgICAgICBhcmNoaXZlZDogZmFsc2UsXG4gICAgICAgICAgZ2l0X3VybDogXCJnaXQ6Ly9naXRodWIuY29tL3Rlc3QtdXNlci90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgICAgc3NoX3VybDogXCJnaXRAZ2l0aHViLmNvbTp0ZXN0LXVzZXIvdGVzdC1yZXBvLmdpdFwiLFxuICAgICAgICAgIGNsb25lX3VybDogXCJodHRwczovL2dpdGh1Yi5jb20vdGVzdC11c2VyL3Rlc3QtcmVwby5naXRcIixcbiAgICAgICAgfSksXG4gICAgfSlcblxuICAgIGF3YWl0IHNhdmVQYWNrYWdlVG9HaXRodWIobW9ja1BhY2thZ2UsIHtcbiAgICAgIC4uLm1vY2tPcHRpb25zLFxuICAgICAgYXBpS2V5OiBcImN1c3RvbS1hcGkta2V5XCIsXG4gICAgfSlcblxuICAgIGNvbnN0IGZpcnN0Q2FsbCA9IGZldGNoTW9jay5tb2NrLmNhbGxzWzBdXG4gICAgZXhwZWN0KGZpcnN0Q2FsbCkudG9CZURlZmluZWQoKVxuICAgIGlmICghZmlyc3RDYWxsKSByZXR1cm5cblxuICAgIGNvbnN0IGhlYWRlcnMgPSBmaXJzdENhbGxbMV0uaGVhZGVyc1xuICAgIGV4cGVjdChoZWFkZXJzLkF1dGhvcml6YXRpb24pLnRvRXF1YWwoXCJCZWFyZXIgY3VzdG9tLWFwaS1rZXlcIilcbiAgfSlcblxuICBpdChcImhhbmRsZXMgQVBJIGVycm9ycyBmcm9tIHJlcG9zaXRvcnkgY3JlYXRpb25cIiwgYXN5bmMgKCkgPT4ge1xuICAgIGZldGNoTW9jay5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2Uoe1xuICAgICAgb2s6IGZhbHNlLFxuICAgICAgc3RhdHVzOiA0MDAsXG4gICAgICBzdGF0dXNUZXh0OiBcIkJhZCBSZXF1ZXN0XCIsXG4gICAgICB0ZXh0OiAoKSA9PiBQcm9taXNlLnJlc29sdmUoXCJSZXBvc2l0b3J5IG5hbWUgYWxyZWFkeSBleGlzdHNcIiksXG4gICAgfSlcblxuICAgIGF3YWl0IGV4cGVjdChzYXZlUGFja2FnZVRvR2l0aHViKG1vY2tQYWNrYWdlLCBtb2NrT3B0aW9ucykpLnJlamVjdHMudG9UaHJvdyhcbiAgICAgIFwiR2l0aHViIEFQSSBlcnJvcjogNDAwIEJhZCBSZXF1ZXN0XCIsXG4gICAgKVxuICB9KVxuXG4gIGl0KFwiaGFuZGxlcyBBUEkgZXJyb3JzIGZyb20gZmlsZSB1cGxvYWRcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGZldGNoTW9jay5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2Uoe1xuICAgICAgb2s6IHRydWUsXG4gICAgICBqc29uOiAoKSA9PlxuICAgICAgICBQcm9taXNlLnJlc29sdmUoe1xuICAgICAgICAgIGlkOiAxMjM0NSxcbiAgICAgICAgICBuYW1lOiBcInRlc3QtcmVwb1wiLFxuICAgICAgICAgIGZ1bGxfbmFtZTogXCJ0ZXN0LXVzZXIvdGVzdC1yZXBvXCIsXG4gICAgICAgICAgb3duZXI6IHtcbiAgICAgICAgICAgIGxvZ2luOiBcInRlc3QtdXNlclwiLFxuICAgICAgICAgICAgaWQ6IDEsXG4gICAgICAgICAgICBhdmF0YXJfdXJsOiBcImh0dHBzOi8vYXZhdGFycy5naXRodWJ1c2VyY29udGVudC5jb20vdS8xXCIsXG4gICAgICAgICAgICBodG1sX3VybDogXCJodHRwczovL2dpdGh1Yi5jb20vdGVzdC11c2VyXCIsXG4gICAgICAgICAgICB0eXBlOiBcIlVzZXJcIixcbiAgICAgICAgICB9LFxuICAgICAgICAgIGh0bWxfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXIvdGVzdC1yZXBvXCIsXG4gICAgICAgICAgZGVzY3JpcHRpb246IG51bGwsXG4gICAgICAgICAgY3JlYXRlZF9hdDogXCIyMDI0LTAxLTAxVDAwOjAwOjAwWlwiLFxuICAgICAgICAgIHVwZGF0ZWRfYXQ6IFwiMjAyNC0wMS0wMVQwMDowMDowMFpcIixcbiAgICAgICAgICBob21lcGFnZTogbnVsbCxcbiAgICAgICAgICBzaXplOiAwLFxuICAgICAgICAgIHN0YXJnYXplcnNfY291bnQ6IDAsXG4gICAgICAgICAgd2F0Y2hlcnNfY291bnQ6IDAsXG4gICAgICAgICAgbGFuZ3VhZ2U6IG51bGwsXG4gICAgICAgICAgbGljZW5zZTogbnVsbCxcbiAgICAgICAgICBkZWZhdWx0X2JyYW5jaDogXCJtYWluXCIsXG4gICAgICAgICAgdG9waWNzOiBbXSxcbiAgICAgICAgICBwcml2YXRlOiBmYWxzZSxcbiAgICAgICAgICBhcmNoaXZlZDogZmFsc2UsXG4gICAgICAgICAgZ2l0X3VybDogXCJnaXQ6Ly9naXRodWIuY29tL3Rlc3QtdXNlci90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgICAgc3NoX3VybDogXCJnaXRAZ2l0aHViLmNvbTp0ZXN0LXVzZXIvdGVzdC1yZXBvLmdpdFwiLFxuICAgICAgICAgIGNsb25lX3VybDogXCJodHRwczovL2dpdGh1Yi5jb20vdGVzdC11c2VyL3Rlc3QtcmVwby5naXRcIixcbiAgICAgICAgfSksXG4gICAgfSlcblxuICAgIGZldGNoTW9jay5tb2NrUmVzb2x2ZWRWYWx1ZU9uY2Uoe1xuICAgICAgb2s6IGZhbHNlLFxuICAgICAgc3RhdHVzOiA1MDAsXG4gICAgICBzdGF0dXNUZXh0OiBcIkludGVybmFsIFNlcnZlciBFcnJvclwiLFxuICAgICAgdGV4dDogKCkgPT4gUHJvbWlzZS5yZXNvbHZlKFwiRmFpbGVkIHRvIHVwbG9hZCBmaWxlXCIpLFxuICAgIH0pXG5cbiAgICBhd2FpdCBleHBlY3Qoc2F2ZVBhY2thZ2VUb0dpdGh1Yihtb2NrUGFja2FnZSwgbW9ja09wdGlvbnMpKS5yZWplY3RzLnRvVGhyb3coXG4gICAgICBcIkdpdGh1YiBBUEkgZXJyb3I6IDUwMCBJbnRlcm5hbCBTZXJ2ZXIgRXJyb3JcIixcbiAgICApXG4gIH0pXG5cbiAgaXQoXCJoYW5kbGVzIHBhY2thZ2VzIHdpdGggbXVsdGlwbGUgcmVzb3VyY2VzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBtdWx0aVJlc291cmNlUGFja2FnZTogUGFja2FnZSA9IHtcbiAgICAgIC4uLm1vY2tQYWNrYWdlLFxuICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInJlc291cmNlLTFcIixcbiAgICAgICAgICBwYXRoOiBnZXRGaXh0dXJlUGF0aChcImRhdGEuY3N2XCIpLFxuICAgICAgICAgIGZvcm1hdDogXCJjc3ZcIixcbiAgICAgICAgfSxcbiAgICAgICAge1xuICAgICAgICAgIG5hbWU6IFwicmVzb3VyY2UtMlwiLFxuICAgICAgICAgIHBhdGg6IGdldEZpeHR1cmVQYXRoKFwiZGF0YS5jc3ZcIiksXG4gICAgICAgICAgZm9ybWF0OiBcImpzb25cIixcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfVxuXG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlKHtcbiAgICAgIG9rOiB0cnVlLFxuICAgICAganNvbjogKCkgPT5cbiAgICAgICAgUHJvbWlzZS5yZXNvbHZlKHtcbiAgICAgICAgICBpZDogMTIzNDUsXG4gICAgICAgICAgbmFtZTogXCJ0ZXN0LXJlcG9cIixcbiAgICAgICAgICBmdWxsX25hbWU6IFwidGVzdC11c2VyL3Rlc3QtcmVwb1wiLFxuICAgICAgICAgIG93bmVyOiB7XG4gICAgICAgICAgICBsb2dpbjogXCJ0ZXN0LXVzZXJcIixcbiAgICAgICAgICAgIGlkOiAxLFxuICAgICAgICAgICAgYXZhdGFyX3VybDogXCJodHRwczovL2F2YXRhcnMuZ2l0aHVidXNlcmNvbnRlbnQuY29tL3UvMVwiLFxuICAgICAgICAgICAgaHRtbF91cmw6IFwiaHR0cHM6Ly9naXRodWIuY29tL3Rlc3QtdXNlclwiLFxuICAgICAgICAgICAgdHlwZTogXCJVc2VyXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBodG1sX3VybDogXCJodHRwczovL2dpdGh1Yi5jb20vdGVzdC11c2VyL3Rlc3QtcmVwb1wiLFxuICAgICAgICAgIGRlc2NyaXB0aW9uOiBudWxsLFxuICAgICAgICAgIGNyZWF0ZWRfYXQ6IFwiMjAyNC0wMS0wMVQwMDowMDowMFpcIixcbiAgICAgICAgICB1cGRhdGVkX2F0OiBcIjIwMjQtMDEtMDFUMDA6MDA6MDBaXCIsXG4gICAgICAgICAgaG9tZXBhZ2U6IG51bGwsXG4gICAgICAgICAgc2l6ZTogMCxcbiAgICAgICAgICBzdGFyZ2F6ZXJzX2NvdW50OiAwLFxuICAgICAgICAgIHdhdGNoZXJzX2NvdW50OiAwLFxuICAgICAgICAgIGxhbmd1YWdlOiBudWxsLFxuICAgICAgICAgIGxpY2Vuc2U6IG51bGwsXG4gICAgICAgICAgZGVmYXVsdF9icmFuY2g6IFwibWFpblwiLFxuICAgICAgICAgIHRvcGljczogW10sXG4gICAgICAgICAgcHJpdmF0ZTogZmFsc2UsXG4gICAgICAgICAgYXJjaGl2ZWQ6IGZhbHNlLFxuICAgICAgICAgIGdpdF91cmw6IFwiZ2l0Oi8vZ2l0aHViLmNvbS90ZXN0LXVzZXIvdGVzdC1yZXBvLmdpdFwiLFxuICAgICAgICAgIHNzaF91cmw6IFwiZ2l0QGdpdGh1Yi5jb206dGVzdC11c2VyL3Rlc3QtcmVwby5naXRcIixcbiAgICAgICAgICBjbG9uZV91cmw6IFwiaHR0cHM6Ly9naXRodWIuY29tL3Rlc3QtdXNlci90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgIH0pLFxuICAgIH0pXG5cbiAgICBhd2FpdCBzYXZlUGFja2FnZVRvR2l0aHViKG11bHRpUmVzb3VyY2VQYWNrYWdlLCBtb2NrT3B0aW9ucylcblxuICAgIGV4cGVjdChmZXRjaE1vY2spLnRvSGF2ZUJlZW5DYWxsZWRUaW1lcyg0KVxuXG4gICAgY29uc3Qgc2Vjb25kRmlsZVVwbG9hZENhbGwgPSBmZXRjaE1vY2subW9jay5jYWxsc1syXVxuICAgIGV4cGVjdChzZWNvbmRGaWxlVXBsb2FkQ2FsbCkudG9CZURlZmluZWQoKVxuICAgIGlmICghc2Vjb25kRmlsZVVwbG9hZENhbGwpIHJldHVyblxuXG4gICAgZXhwZWN0KHNlY29uZEZpbGVVcGxvYWRDYWxsWzBdKS50b0NvbnRhaW4oXCIvY29udGVudHMvXCIpXG4gIH0pXG5cbiAgaXQoXCJoYW5kbGVzIHBhY2thZ2VzIHdpdGggbm8gcmVzb3VyY2VzXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBlbXB0eVBhY2thZ2U6IFBhY2thZ2UgPSB7XG4gICAgICAuLi5tb2NrUGFja2FnZSxcbiAgICAgIHJlc291cmNlczogW10sXG4gICAgfVxuXG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgaWQ6IDEyMzQ1LFxuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXBvXCIsXG4gICAgICAgICAgZnVsbF9uYW1lOiBcInRlc3QtdXNlci90ZXN0LXJlcG9cIixcbiAgICAgICAgICBvd25lcjoge1xuICAgICAgICAgICAgbG9naW46IFwidGVzdC11c2VyXCIsXG4gICAgICAgICAgICBpZDogMSxcbiAgICAgICAgICAgIGF2YXRhcl91cmw6IFwiaHR0cHM6Ly9hdmF0YXJzLmdpdGh1YnVzZXJjb250ZW50LmNvbS91LzFcIixcbiAgICAgICAgICAgIGh0bWxfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXJcIixcbiAgICAgICAgICAgIHR5cGU6IFwiVXNlclwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgaHRtbF91cmw6IFwiaHR0cHM6Ly9naXRodWIuY29tL3Rlc3QtdXNlci90ZXN0LXJlcG9cIixcbiAgICAgICAgICBkZXNjcmlwdGlvbjogbnVsbCxcbiAgICAgICAgICBjcmVhdGVkX2F0OiBcIjIwMjQtMDEtMDFUMDA6MDA6MDBaXCIsXG4gICAgICAgICAgdXBkYXRlZF9hdDogXCIyMDI0LTAxLTAxVDAwOjAwOjAwWlwiLFxuICAgICAgICAgIGhvbWVwYWdlOiBudWxsLFxuICAgICAgICAgIHNpemU6IDAsXG4gICAgICAgICAgc3RhcmdhemVyc19jb3VudDogMCxcbiAgICAgICAgICB3YXRjaGVyc19jb3VudDogMCxcbiAgICAgICAgICBsYW5ndWFnZTogbnVsbCxcbiAgICAgICAgICBsaWNlbnNlOiBudWxsLFxuICAgICAgICAgIGRlZmF1bHRfYnJhbmNoOiBcIm1haW5cIixcbiAgICAgICAgICB0b3BpY3M6IFtdLFxuICAgICAgICAgIHByaXZhdGU6IGZhbHNlLFxuICAgICAgICAgIGFyY2hpdmVkOiBmYWxzZSxcbiAgICAgICAgICBnaXRfdXJsOiBcImdpdDovL2dpdGh1Yi5jb20vdGVzdC11c2VyL3Rlc3QtcmVwby5naXRcIixcbiAgICAgICAgICBzc2hfdXJsOiBcImdpdEBnaXRodWIuY29tOnRlc3QtdXNlci90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgICAgY2xvbmVfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXIvdGVzdC1yZXBvLmdpdFwiLFxuICAgICAgICB9KSxcbiAgICB9KVxuXG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgY29udGVudDoge1xuICAgICAgICAgICAgbmFtZTogXCJkYXRhcGFja2FnZS5qc29uXCIsXG4gICAgICAgICAgICBwYXRoOiBcImRhdGFwYWNrYWdlLmpzb25cIixcbiAgICAgICAgICAgIHNoYTogXCJkZWY0NTZcIixcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICB9KVxuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgc2F2ZVBhY2thZ2VUb0dpdGh1YihlbXB0eVBhY2thZ2UsIG1vY2tPcHRpb25zKVxuXG4gICAgZXhwZWN0KGZldGNoTW9jaykudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDIpXG4gICAgZXhwZWN0KHJlc3VsdC5yZXBvVXJsKS50b0VxdWFsKFwiaHR0cHM6Ly9naXRodWIuY29tL3Rlc3QtdXNlci90ZXN0LXJlcG9cIilcbiAgfSlcblxuICBpdChcInNraXBzIHJlc291cmNlcyB3aXRob3V0IHBhdGhcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHBhY2thZ2VXaXRob3V0UGF0aDogUGFja2FnZSA9IHtcbiAgICAgIC4uLm1vY2tQYWNrYWdlLFxuICAgICAgcmVzb3VyY2VzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcInJlc291cmNlLXdpdGhvdXQtcGF0aFwiLFxuICAgICAgICAgIGZvcm1hdDogXCJjc3ZcIixcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgfVxuXG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgaWQ6IDEyMzQ1LFxuICAgICAgICAgIG5hbWU6IFwidGVzdC1yZXBvXCIsXG4gICAgICAgICAgZnVsbF9uYW1lOiBcInRlc3QtdXNlci90ZXN0LXJlcG9cIixcbiAgICAgICAgICBvd25lcjoge1xuICAgICAgICAgICAgbG9naW46IFwidGVzdC11c2VyXCIsXG4gICAgICAgICAgICBpZDogMSxcbiAgICAgICAgICAgIGF2YXRhcl91cmw6IFwiaHR0cHM6Ly9hdmF0YXJzLmdpdGh1YnVzZXJjb250ZW50LmNvbS91LzFcIixcbiAgICAgICAgICAgIGh0bWxfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXJcIixcbiAgICAgICAgICAgIHR5cGU6IFwiVXNlclwiLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgaHRtbF91cmw6IFwiaHR0cHM6Ly9naXRodWIuY29tL3Rlc3QtdXNlci90ZXN0LXJlcG9cIixcbiAgICAgICAgICBkZXNjcmlwdGlvbjogbnVsbCxcbiAgICAgICAgICBjcmVhdGVkX2F0OiBcIjIwMjQtMDEtMDFUMDA6MDA6MDBaXCIsXG4gICAgICAgICAgdXBkYXRlZF9hdDogXCIyMDI0LTAxLTAxVDAwOjAwOjAwWlwiLFxuICAgICAgICAgIGhvbWVwYWdlOiBudWxsLFxuICAgICAgICAgIHNpemU6IDAsXG4gICAgICAgICAgc3RhcmdhemVyc19jb3VudDogMCxcbiAgICAgICAgICB3YXRjaGVyc19jb3VudDogMCxcbiAgICAgICAgICBsYW5ndWFnZTogbnVsbCxcbiAgICAgICAgICBsaWNlbnNlOiBudWxsLFxuICAgICAgICAgIGRlZmF1bHRfYnJhbmNoOiBcIm1haW5cIixcbiAgICAgICAgICB0b3BpY3M6IFtdLFxuICAgICAgICAgIHByaXZhdGU6IGZhbHNlLFxuICAgICAgICAgIGFyY2hpdmVkOiBmYWxzZSxcbiAgICAgICAgICBnaXRfdXJsOiBcImdpdDovL2dpdGh1Yi5jb20vdGVzdC11c2VyL3Rlc3QtcmVwby5naXRcIixcbiAgICAgICAgICBzc2hfdXJsOiBcImdpdEBnaXRodWIuY29tOnRlc3QtdXNlci90ZXN0LXJlcG8uZ2l0XCIsXG4gICAgICAgICAgY2xvbmVfdXJsOiBcImh0dHBzOi8vZ2l0aHViLmNvbS90ZXN0LXVzZXIvdGVzdC1yZXBvLmdpdFwiLFxuICAgICAgICB9KSxcbiAgICB9KVxuXG4gICAgZmV0Y2hNb2NrLm1vY2tSZXNvbHZlZFZhbHVlT25jZSh7XG4gICAgICBvazogdHJ1ZSxcbiAgICAgIGpzb246ICgpID0+XG4gICAgICAgIFByb21pc2UucmVzb2x2ZSh7XG4gICAgICAgICAgY29udGVudDoge1xuICAgICAgICAgICAgbmFtZTogXCJkYXRhcGFja2FnZS5qc29uXCIsXG4gICAgICAgICAgICBwYXRoOiBcImRhdGFwYWNrYWdlLmpzb25cIixcbiAgICAgICAgICAgIHNoYTogXCJkZWY0NTZcIixcbiAgICAgICAgICB9LFxuICAgICAgICB9KSxcbiAgICB9KVxuXG4gICAgYXdhaXQgc2F2ZVBhY2thZ2VUb0dpdGh1YihwYWNrYWdlV2l0aG91dFBhdGgsIG1vY2tPcHRpb25zKVxuXG4gICAgZXhwZWN0KGZldGNoTW9jaykudG9IYXZlQmVlbkNhbGxlZFRpbWVzKDIpXG4gIH0pXG59KVxuIl19
|