@oneuptime/common 11.5.13 → 11.6.0
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/Models/DatabaseModels/EnterpriseLicense.ts +21 -0
- package/Models/DatabaseModels/EnterpriseLicenseInstance.ts +25 -0
- package/Models/DatabaseModels/GlobalConfig.ts +76 -0
- package/Server/API/EnterpriseLicenseAPI.ts +57 -0
- package/Server/API/GlobalConfigAPI.ts +62 -1
- package/Server/EnvironmentConfig.ts +22 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.ts +38 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.ts +25 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/AnalyticsDatabaseService.ts +48 -45
- package/Server/Services/DatabaseService.ts +66 -1
- package/Server/Services/WorkflowService.ts +100 -39
- package/Server/Types/Workflow/Components/Schedule.ts +57 -32
- package/Server/Utils/AnalyticsDatabase/InsertDedupContext.ts +59 -0
- package/Server/Utils/Express.ts +13 -0
- package/Server/Utils/Telemetry/TelemetryFanInWriter.ts +799 -0
- package/Server/Utils/Telemetry/TelemetryWriterClient.ts +263 -0
- package/Server/Utils/Telemetry/TelemetryWriterServer.ts +240 -0
- package/Server/Utils/Telemetry/TelemetryWriterShedMetrics.ts +93 -0
- package/Tests/Server/Services/DatabaseServiceSanitizeUpdateData.test.ts +232 -0
- package/Tests/Server/Services/UpdateOneByIdKeepsRowId.test.ts +107 -0
- package/Tests/Server/Services/WorkflowService.test.ts +308 -0
- package/Tests/Server/Utils/Attribution.test.ts +203 -0
- package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +183 -0
- package/Tests/Server/Utils/Marketing/GoogleAds.test.ts +340 -0
- package/Tests/Server/Utils/Monitor/Criteria/ExceptionMonitorCriteria.test.ts +87 -0
- package/Tests/Server/Utils/Monitor/Criteria/LogMonitorCriteria.test.ts +165 -0
- package/Tests/Server/Utils/Monitor/Criteria/TraceMonitorCriteria.test.ts +86 -0
- package/Tests/Server/Utils/Telemetry/TelemetryFanInWriter.test.ts +1565 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterClient.test.ts +313 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterServer.test.ts +270 -0
- package/Tests/Server/Utils/Telemetry/TelemetryWriterShedMetrics.test.ts +127 -0
- package/Tests/Types/AI/CodeFixTaskType.test.ts +3 -0
- package/Tests/Types/Monitor/MonitorCriteriaMetricVariables.test.ts +228 -0
- package/Tests/Types/Monitor/MonitorStepDefaultTelemetryConfig.test.ts +169 -0
- package/Tests/Types/Monitor/MonitorStepExceptionMonitor.test.ts +289 -0
- package/Tests/Types/Monitor/MonitorStepLogMonitor.test.ts +231 -0
- package/Tests/Types/Monitor/MonitorStepMetricViewConfigUtil.test.ts +245 -0
- package/Tests/Types/Monitor/MonitorStepNetworkDeviceMonitor.test.ts +155 -0
- package/Tests/Types/Monitor/MonitorStepTelemetrySerialization.test.ts +141 -0
- package/Tests/Types/Monitor/MonitorStepTraceMonitor.test.ts +137 -0
- package/Tests/Types/Workspace/NotificationRules/NotificationRuleCondition.test.ts +311 -0
- package/Tests/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.test.ts +461 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +2852 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +758 -0
- package/Tests/UI/Utils/NotificationMethodUtil.test.ts +564 -0
- package/Tests/Utils/Array.test.ts +156 -0
- package/Tests/Utils/CronTab.test.ts +199 -0
- package/Tests/Utils/ModelImportExport.test.ts +101 -0
- package/Tests/Utils/Number.test.ts +179 -0
- package/Tests/Utils/VersionUtil.test.ts +348 -0
- package/Tests/jest.setup.ts +1 -0
- package/Types/EnterpriseLicense/EnterpriseLicenseInstanceSummary.ts +6 -0
- package/Types/Monitor/MonitorStep.ts +24 -4
- package/Types/Monitor/MonitorStepMetricViewConfigUtil.ts +105 -0
- package/UI/Components/EditionLabel/EditionLabel.tsx +445 -12
- package/UI/Components/Workflow/ArgumentsForm.tsx +68 -30
- package/UI/Components/Workflow/CronScheduleField.tsx +411 -0
- package/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.ts +176 -0
- package/UI/Utils/NotificationMethodUtil.ts +310 -0
- package/Utils/CronTab.ts +823 -0
- package/Utils/ModelImportExport.ts +21 -6
- package/Utils/VersionUtil.ts +260 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +22 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
- package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js +26 -0
- package/build/dist/Models/DatabaseModels/EnterpriseLicenseInstance.js.map +1 -1
- package/build/dist/Models/DatabaseModels/GlobalConfig.js +81 -0
- package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
- package/build/dist/Server/API/EnterpriseLicenseAPI.js +47 -0
- package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +1 -1
- package/build/dist/Server/API/GlobalConfigAPI.js +52 -1
- package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +17 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784659816363-AddInstanceVersionAndLatestReleaseColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1784705487674-AddEnterpriseLicenseEvaluationColumns.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AnalyticsDatabaseService.js +44 -16
- package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +53 -1
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/WorkflowService.js +80 -30
- package/build/dist/Server/Services/WorkflowService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Schedule.js +44 -19
- package/build/dist/Server/Types/Workflow/Components/Schedule.js.map +1 -1
- package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js +24 -0
- package/build/dist/Server/Utils/AnalyticsDatabase/InsertDedupContext.js.map +1 -0
- package/build/dist/Server/Utils/Express.js +12 -0
- package/build/dist/Server/Utils/Express.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js +496 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryFanInWriter.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterClient.js +165 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterClient.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterServer.js +136 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterServer.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterShedMetrics.js +76 -0
- package/build/dist/Server/Utils/Telemetry/TelemetryWriterShedMetrics.js.map +1 -0
- package/build/dist/Types/Monitor/MonitorStep.js +20 -4
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js +73 -0
- package/build/dist/Types/Monitor/MonitorStepMetricViewConfigUtil.js.map +1 -0
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +261 -13
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +30 -6
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/CronScheduleField.js +209 -0
- package/build/dist/UI/Components/Workflow/CronScheduleField.js.map +1 -0
- package/build/dist/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.js +129 -0
- package/build/dist/UI/Utils/Breadcrumb/BreadcrumbTrailResolver.js.map +1 -0
- package/build/dist/UI/Utils/NotificationMethodUtil.js +189 -0
- package/build/dist/UI/Utils/NotificationMethodUtil.js.map +1 -0
- package/build/dist/Utils/CronTab.js +609 -0
- package/build/dist/Utils/CronTab.js.map +1 -0
- package/build/dist/Utils/ModelImportExport.js +20 -6
- package/build/dist/Utils/ModelImportExport.js.map +1 -1
- package/build/dist/Utils/VersionUtil.js +193 -0
- package/build/dist/Utils/VersionUtil.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
import VersionUtil, { ParsedVersion } from "../../Utils/VersionUtil";
|
|
2
|
+
|
|
3
|
+
describe("VersionUtil", () => {
|
|
4
|
+
describe("normalize", () => {
|
|
5
|
+
it("strips a leading v from a GitHub tag name", () => {
|
|
6
|
+
expect(VersionUtil.normalize("v11.5.13")).toBe("11.5.13");
|
|
7
|
+
expect(VersionUtil.normalize("V11.5.13")).toBe("11.5.13");
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
it("trims surrounding whitespace", () => {
|
|
11
|
+
expect(VersionUtil.normalize(" 11.5.13\n")).toBe("11.5.13");
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
it("returns an empty string for non-strings", () => {
|
|
15
|
+
expect(VersionUtil.normalize(null)).toBe("");
|
|
16
|
+
expect(VersionUtil.normalize(undefined)).toBe("");
|
|
17
|
+
expect(VersionUtil.normalize(11)).toBe("");
|
|
18
|
+
expect(VersionUtil.normalize({ version: "1.0.0" })).toBe("");
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("caps absurdly long input", () => {
|
|
22
|
+
expect(VersionUtil.normalize("1".repeat(5000)).length).toBe(100);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe("parse", () => {
|
|
27
|
+
it("parses a plain release", () => {
|
|
28
|
+
const parsed: ParsedVersion | null = VersionUtil.parse("11.5.13");
|
|
29
|
+
|
|
30
|
+
expect(parsed).toEqual({
|
|
31
|
+
major: 11,
|
|
32
|
+
minor: 5,
|
|
33
|
+
patch: 13,
|
|
34
|
+
prerelease: null,
|
|
35
|
+
});
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("parses a prerelease", () => {
|
|
39
|
+
const parsed: ParsedVersion | null = VersionUtil.parse("11.6.0-rc.1");
|
|
40
|
+
|
|
41
|
+
expect(parsed).toEqual({
|
|
42
|
+
major: 11,
|
|
43
|
+
minor: 6,
|
|
44
|
+
patch: 0,
|
|
45
|
+
prerelease: "rc.1",
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it("discards build metadata, which takes no part in precedence", () => {
|
|
50
|
+
expect(VersionUtil.parse("11.5.13+abc123")?.prerelease).toBeNull();
|
|
51
|
+
expect(VersionUtil.compare("11.5.13+abc123", "11.5.13")).toBe(0);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("returns null for partial, empty and garbage versions", () => {
|
|
55
|
+
const invalid: Array<unknown> = [
|
|
56
|
+
"11.5",
|
|
57
|
+
"11",
|
|
58
|
+
"",
|
|
59
|
+
" ",
|
|
60
|
+
"latest",
|
|
61
|
+
"unknown",
|
|
62
|
+
"v",
|
|
63
|
+
"1.0.0.0",
|
|
64
|
+
"-1.0.0",
|
|
65
|
+
"1.0.0-",
|
|
66
|
+
null,
|
|
67
|
+
undefined,
|
|
68
|
+
11.5,
|
|
69
|
+
{},
|
|
70
|
+
[],
|
|
71
|
+
];
|
|
72
|
+
|
|
73
|
+
for (const value of invalid) {
|
|
74
|
+
expect(VersionUtil.parse(value)).toBeNull();
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("rejects numbers too large to be a real version", () => {
|
|
79
|
+
expect(VersionUtil.parse("99999999999.0.0")).toBeNull();
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("reports validity", () => {
|
|
83
|
+
expect(VersionUtil.isValid("11.5.13")).toBe(true);
|
|
84
|
+
expect(VersionUtil.isValid("unknown")).toBe(false);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe("canonicalize", () => {
|
|
89
|
+
it("rebuilds the version from its parts", () => {
|
|
90
|
+
expect(VersionUtil.canonicalize("11.5.13")).toBe("11.5.13");
|
|
91
|
+
expect(VersionUtil.canonicalize("v11.5.13")).toBe("11.5.13");
|
|
92
|
+
expect(VersionUtil.canonicalize(" 11.6.0-rc.1 ")).toBe("11.6.0-rc.1");
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
/*
|
|
96
|
+
* A caller that validates with isValid() and then stores the string it
|
|
97
|
+
* passed in can end up storing "v11.5.13" for the input "vv11.5.13",
|
|
98
|
+
* because normalize() strips one "v" per call and isValid() normalizes a
|
|
99
|
+
* second time. canonicalize is the fix: it rebuilds from a single parse,
|
|
100
|
+
* so a doubled prefix is simply not a version and the result never carries
|
|
101
|
+
* a "v" for the UIs to double up on.
|
|
102
|
+
*/
|
|
103
|
+
it("never returns a value that still carries a v prefix", () => {
|
|
104
|
+
expect(VersionUtil.canonicalize("vv11.5.13")).toBeNull();
|
|
105
|
+
expect(VersionUtil.canonicalize("vV11.5.13")).toBeNull();
|
|
106
|
+
|
|
107
|
+
for (const value of ["11.5.13", "v11.5.13", " V11.5.13 "]) {
|
|
108
|
+
expect(VersionUtil.canonicalize(value)).toBe("11.5.13");
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("drops build metadata, which takes no part in precedence", () => {
|
|
113
|
+
expect(VersionUtil.canonicalize("11.5.13+abc123")).toBe("11.5.13");
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("is idempotent", () => {
|
|
117
|
+
const once: string | null = VersionUtil.canonicalize("v11.5.13");
|
|
118
|
+
|
|
119
|
+
expect(VersionUtil.canonicalize(once)).toBe(once);
|
|
120
|
+
});
|
|
121
|
+
|
|
122
|
+
it("returns null for anything that is not a version", () => {
|
|
123
|
+
expect(VersionUtil.canonicalize("unknown")).toBeNull();
|
|
124
|
+
expect(VersionUtil.canonicalize("")).toBeNull();
|
|
125
|
+
expect(VersionUtil.canonicalize(null)).toBeNull();
|
|
126
|
+
expect(VersionUtil.canonicalize("vvv1.2.3")).toBeNull();
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe("compare", () => {
|
|
131
|
+
it("orders by major, then minor, then patch", () => {
|
|
132
|
+
expect(VersionUtil.compare("10.0.0", "11.0.0")).toBe(-1);
|
|
133
|
+
expect(VersionUtil.compare("11.4.0", "11.5.0")).toBe(-1);
|
|
134
|
+
expect(VersionUtil.compare("11.5.12", "11.5.13")).toBe(-1);
|
|
135
|
+
expect(VersionUtil.compare("11.5.13", "11.5.12")).toBe(1);
|
|
136
|
+
expect(VersionUtil.compare("2.0.0", "10.0.0")).toBe(-1);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("treats equal versions as equal regardless of a v prefix", () => {
|
|
140
|
+
expect(VersionUtil.compare("11.5.13", "v11.5.13")).toBe(0);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("ranks a prerelease below the release of the same triple", () => {
|
|
144
|
+
expect(VersionUtil.compare("11.6.0-rc.1", "11.6.0")).toBe(-1);
|
|
145
|
+
expect(VersionUtil.compare("11.6.0", "11.6.0-rc.1")).toBe(1);
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
it("orders prerelease identifiers by semver precedence", () => {
|
|
149
|
+
expect(VersionUtil.compare("1.0.0-alpha", "1.0.0-alpha.1")).toBe(-1);
|
|
150
|
+
expect(VersionUtil.compare("1.0.0-alpha.1", "1.0.0-alpha.beta")).toBe(-1);
|
|
151
|
+
expect(VersionUtil.compare("1.0.0-alpha.beta", "1.0.0-beta")).toBe(-1);
|
|
152
|
+
expect(VersionUtil.compare("1.0.0-beta.2", "1.0.0-beta.11")).toBe(-1);
|
|
153
|
+
expect(VersionUtil.compare("1.0.0-rc.1", "1.0.0-rc.1")).toBe(0);
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("returns null when either side cannot be parsed", () => {
|
|
157
|
+
expect(VersionUtil.compare("unknown", "11.5.13")).toBeNull();
|
|
158
|
+
expect(VersionUtil.compare("11.5.13", "")).toBeNull();
|
|
159
|
+
expect(VersionUtil.compare(null, undefined)).toBeNull();
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
it("is antisymmetric across a range of pairs", () => {
|
|
163
|
+
const versions: Array<string> = [
|
|
164
|
+
"1.0.0",
|
|
165
|
+
"1.0.1",
|
|
166
|
+
"1.1.0",
|
|
167
|
+
"2.0.0",
|
|
168
|
+
"11.5.13",
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
for (const a of versions) {
|
|
172
|
+
for (const b of versions) {
|
|
173
|
+
const forward: number = VersionUtil.compare(a, b) as number;
|
|
174
|
+
const reverse: number = VersionUtil.compare(b, a) as number;
|
|
175
|
+
|
|
176
|
+
// `|| 0` keeps the negation of 0 from producing -0, which toBe rejects.
|
|
177
|
+
expect(forward).toBe(-reverse || 0);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe("isUpdateAvailable", () => {
|
|
184
|
+
it("is true only when the latest release is strictly newer", () => {
|
|
185
|
+
expect(
|
|
186
|
+
VersionUtil.isUpdateAvailable({
|
|
187
|
+
currentVersion: "11.5.13",
|
|
188
|
+
latestVersion: "11.6.0",
|
|
189
|
+
}),
|
|
190
|
+
).toBe(true);
|
|
191
|
+
|
|
192
|
+
expect(
|
|
193
|
+
VersionUtil.isUpdateAvailable({
|
|
194
|
+
currentVersion: "11.5.13",
|
|
195
|
+
latestVersion: "v11.5.14",
|
|
196
|
+
}),
|
|
197
|
+
).toBe(true);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
it("is false when the installation is up to date", () => {
|
|
201
|
+
expect(
|
|
202
|
+
VersionUtil.isUpdateAvailable({
|
|
203
|
+
currentVersion: "11.5.13",
|
|
204
|
+
latestVersion: "11.5.13",
|
|
205
|
+
}),
|
|
206
|
+
).toBe(false);
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it("never suggests a downgrade for a build ahead of the release", () => {
|
|
210
|
+
expect(
|
|
211
|
+
VersionUtil.isUpdateAvailable({
|
|
212
|
+
currentVersion: "11.6.0",
|
|
213
|
+
latestVersion: "11.5.13",
|
|
214
|
+
}),
|
|
215
|
+
).toBe(false);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("never nudges a stable installation onto a prerelease", () => {
|
|
219
|
+
expect(
|
|
220
|
+
VersionUtil.isUpdateAvailable({
|
|
221
|
+
currentVersion: "11.5.13",
|
|
222
|
+
latestVersion: "11.6.0-beta.1",
|
|
223
|
+
}),
|
|
224
|
+
).toBe(false);
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
it("does tell a release candidate about the matching stable release", () => {
|
|
228
|
+
expect(
|
|
229
|
+
VersionUtil.isUpdateAvailable({
|
|
230
|
+
currentVersion: "11.6.0-rc.1",
|
|
231
|
+
latestVersion: "11.6.0",
|
|
232
|
+
}),
|
|
233
|
+
).toBe(true);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
it("is false when the latest release is a prerelease of a new major", () => {
|
|
237
|
+
expect(
|
|
238
|
+
VersionUtil.isUpdateAvailable({
|
|
239
|
+
currentVersion: "11.5.13",
|
|
240
|
+
latestVersion: "12.0.0-rc.1",
|
|
241
|
+
}),
|
|
242
|
+
).toBe(false);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it("is false whenever either version is unknown or missing", () => {
|
|
246
|
+
const unknownValues: Array<unknown> = [
|
|
247
|
+
"unknown",
|
|
248
|
+
"",
|
|
249
|
+
null,
|
|
250
|
+
undefined,
|
|
251
|
+
"latest",
|
|
252
|
+
42,
|
|
253
|
+
];
|
|
254
|
+
|
|
255
|
+
for (const value of unknownValues) {
|
|
256
|
+
expect(
|
|
257
|
+
VersionUtil.isUpdateAvailable({
|
|
258
|
+
currentVersion: value,
|
|
259
|
+
latestVersion: "11.6.0",
|
|
260
|
+
}),
|
|
261
|
+
).toBe(false);
|
|
262
|
+
|
|
263
|
+
expect(
|
|
264
|
+
VersionUtil.isUpdateAvailable({
|
|
265
|
+
currentVersion: "11.5.13",
|
|
266
|
+
latestVersion: value,
|
|
267
|
+
}),
|
|
268
|
+
).toBe(false);
|
|
269
|
+
}
|
|
270
|
+
});
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
describe("isMajorUpgrade", () => {
|
|
274
|
+
it("is true only when the update crosses a major version", () => {
|
|
275
|
+
expect(
|
|
276
|
+
VersionUtil.isMajorUpgrade({
|
|
277
|
+
currentVersion: "11.5.13",
|
|
278
|
+
latestVersion: "12.0.0",
|
|
279
|
+
}),
|
|
280
|
+
).toBe(true);
|
|
281
|
+
|
|
282
|
+
expect(
|
|
283
|
+
VersionUtil.isMajorUpgrade({
|
|
284
|
+
currentVersion: "10.9.9",
|
|
285
|
+
latestVersion: "12.0.0",
|
|
286
|
+
}),
|
|
287
|
+
).toBe(true);
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
it("is false for a minor or patch update", () => {
|
|
291
|
+
expect(
|
|
292
|
+
VersionUtil.isMajorUpgrade({
|
|
293
|
+
currentVersion: "11.5.13",
|
|
294
|
+
latestVersion: "11.6.0",
|
|
295
|
+
}),
|
|
296
|
+
).toBe(false);
|
|
297
|
+
|
|
298
|
+
expect(
|
|
299
|
+
VersionUtil.isMajorUpgrade({
|
|
300
|
+
currentVersion: "11.5.13",
|
|
301
|
+
latestVersion: "11.5.14",
|
|
302
|
+
}),
|
|
303
|
+
).toBe(false);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
it("is false when there is no update to take at all", () => {
|
|
307
|
+
expect(
|
|
308
|
+
VersionUtil.isMajorUpgrade({
|
|
309
|
+
currentVersion: "12.0.0",
|
|
310
|
+
latestVersion: "12.0.0",
|
|
311
|
+
}),
|
|
312
|
+
).toBe(false);
|
|
313
|
+
|
|
314
|
+
// Ahead of the release — a new major behind us is still not an upgrade.
|
|
315
|
+
expect(
|
|
316
|
+
VersionUtil.isMajorUpgrade({
|
|
317
|
+
currentVersion: "12.1.0",
|
|
318
|
+
latestVersion: "11.9.9",
|
|
319
|
+
}),
|
|
320
|
+
).toBe(false);
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
it("is false when the new major is only a prerelease", () => {
|
|
324
|
+
expect(
|
|
325
|
+
VersionUtil.isMajorUpgrade({
|
|
326
|
+
currentVersion: "11.5.13",
|
|
327
|
+
latestVersion: "12.0.0-rc.1",
|
|
328
|
+
}),
|
|
329
|
+
).toBe(false);
|
|
330
|
+
});
|
|
331
|
+
|
|
332
|
+
it("is false whenever either version is unknown or missing", () => {
|
|
333
|
+
expect(
|
|
334
|
+
VersionUtil.isMajorUpgrade({
|
|
335
|
+
currentVersion: "unknown",
|
|
336
|
+
latestVersion: "12.0.0",
|
|
337
|
+
}),
|
|
338
|
+
).toBe(false);
|
|
339
|
+
|
|
340
|
+
expect(
|
|
341
|
+
VersionUtil.isMajorUpgrade({
|
|
342
|
+
currentVersion: "11.5.13",
|
|
343
|
+
latestVersion: null,
|
|
344
|
+
}),
|
|
345
|
+
).toBe(false);
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
});
|
package/Tests/jest.setup.ts
CHANGED
|
@@ -13,6 +13,12 @@ type EnterpriseLicenseInstanceSummary = {
|
|
|
13
13
|
userCount: number | null;
|
|
14
14
|
// ISO date string of the most recent usage report from this instance.
|
|
15
15
|
lastReportedAt: string | null;
|
|
16
|
+
/*
|
|
17
|
+
* OneUptime version this instance last reported, for example "11.5.13".
|
|
18
|
+
* Null for instances that have not reported since upgrading to a build
|
|
19
|
+
* that sends its version, and for dev builds with no APP_VERSION baked in.
|
|
20
|
+
*/
|
|
21
|
+
version: string | null;
|
|
16
22
|
};
|
|
17
23
|
|
|
18
24
|
export default EnterpriseLicenseInstanceSummary;
|
|
@@ -302,10 +302,30 @@ export default class MonitorStep extends DatabaseProperty {
|
|
|
302
302
|
retryCountOnError: undefined,
|
|
303
303
|
requestTimeoutInMs: undefined,
|
|
304
304
|
retryCount: undefined,
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
305
|
+
/*
|
|
306
|
+
* Seed the telemetry sub-config for the monitor's OWN type so a
|
|
307
|
+
* monitor saved on defaults (without the user touching the telemetry
|
|
308
|
+
* sub-form) still persists a usable query config. Without this the
|
|
309
|
+
* sub-config stayed undefined and the worker threw "<type> query/config
|
|
310
|
+
* is missing" on every evaluation, so the monitor never ran. Only the
|
|
311
|
+
* matching type is seeded; every other type stays undefined.
|
|
312
|
+
*/
|
|
313
|
+
logMonitor:
|
|
314
|
+
arg.monitorType === MonitorType.Logs
|
|
315
|
+
? MonitorStepLogMonitorUtil.getDefault()
|
|
316
|
+
: undefined,
|
|
317
|
+
traceMonitor:
|
|
318
|
+
arg.monitorType === MonitorType.Traces
|
|
319
|
+
? MonitorStepTraceMonitorUtil.getDefault()
|
|
320
|
+
: undefined,
|
|
321
|
+
metricMonitor:
|
|
322
|
+
arg.monitorType === MonitorType.Metrics
|
|
323
|
+
? MonitorStepMetricMonitorUtil.getDefault()
|
|
324
|
+
: undefined,
|
|
325
|
+
exceptionMonitor:
|
|
326
|
+
arg.monitorType === MonitorType.Exceptions
|
|
327
|
+
? MonitorStepExceptionMonitorUtil.getDefault()
|
|
328
|
+
: undefined,
|
|
309
329
|
profileMonitor: undefined,
|
|
310
330
|
snmpMonitor: undefined,
|
|
311
331
|
networkDeviceMonitor: undefined,
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import MetricFormulaConfigData from "../Metrics/MetricFormulaConfigData";
|
|
2
|
+
import MetricQueryConfigData from "../Metrics/MetricQueryConfigData";
|
|
3
|
+
import MetricsViewConfig from "../Metrics/MetricsViewConfig";
|
|
4
|
+
import { MonitorStepType } from "./MonitorStep";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Every monitor-step data key that carries a `metricViewConfig`. These are the
|
|
8
|
+
* "metric-shaped" monitor types — the ones whose alert criteria evaluate a
|
|
9
|
+
* metric query (CheckOn.MetricValue). The order here is not significant; a
|
|
10
|
+
* given monitor step only ever populates one of these keys.
|
|
11
|
+
*
|
|
12
|
+
* Keeping this list in one place is what prevents the class of bug where a new
|
|
13
|
+
* metric-shaped monitor type (e.g. Host, Podman, DockerSwarm, IoT) is wired
|
|
14
|
+
* into the step form but forgotten in the criteria UI, leaving the "Which
|
|
15
|
+
* metric query should this alert rule check?" dropdown blank ("No options").
|
|
16
|
+
*/
|
|
17
|
+
const METRIC_VIEW_CONFIG_KEYS: Array<keyof MonitorStepType> = [
|
|
18
|
+
"metricMonitor",
|
|
19
|
+
"hostMonitor",
|
|
20
|
+
"kubernetesMonitor",
|
|
21
|
+
"dockerMonitor",
|
|
22
|
+
"dockerSwarmMonitor",
|
|
23
|
+
"podmanMonitor",
|
|
24
|
+
"proxmoxMonitor",
|
|
25
|
+
"cephMonitor",
|
|
26
|
+
"iotMonitor",
|
|
27
|
+
];
|
|
28
|
+
|
|
29
|
+
export default class MonitorStepMetricViewConfigUtil {
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the `metricViewConfig` from whichever metric-shaped monitor sub-config
|
|
32
|
+
* is populated on this monitor step. Returns undefined when the step is not
|
|
33
|
+
* metric-shaped (or none of the metric configs is present).
|
|
34
|
+
*/
|
|
35
|
+
public static getMetricViewConfig(
|
|
36
|
+
monitorStepData: MonitorStepType | undefined,
|
|
37
|
+
): MetricsViewConfig | undefined {
|
|
38
|
+
if (!monitorStepData) {
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
* Each metric-shaped sub-config is an object with an optional
|
|
44
|
+
* `metricViewConfig`. Index through a record view so the lookup stays
|
|
45
|
+
* data-driven (see METRIC_VIEW_CONFIG_KEYS) without fighting the wide
|
|
46
|
+
* union of MonitorStepType's value types.
|
|
47
|
+
*/
|
|
48
|
+
const stepRecord: Record<
|
|
49
|
+
string,
|
|
50
|
+
{ metricViewConfig?: MetricsViewConfig } | undefined
|
|
51
|
+
> = monitorStepData as unknown as Record<
|
|
52
|
+
string,
|
|
53
|
+
{ metricViewConfig?: MetricsViewConfig } | undefined
|
|
54
|
+
>;
|
|
55
|
+
|
|
56
|
+
for (const key of METRIC_VIEW_CONFIG_KEYS) {
|
|
57
|
+
const subConfig: { metricViewConfig?: MetricsViewConfig } | undefined =
|
|
58
|
+
stepRecord[key];
|
|
59
|
+
|
|
60
|
+
if (subConfig?.metricViewConfig) {
|
|
61
|
+
return subConfig.metricViewConfig;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Collect the distinct, non-empty metric variables (aliases) from the step's
|
|
70
|
+
* query configs and formula configs. These become the options for the
|
|
71
|
+
* criteria "Metric" dropdown. Empty variables are dropped and duplicates are
|
|
72
|
+
* removed while preserving first-seen order.
|
|
73
|
+
*/
|
|
74
|
+
public static getMetricVariables(
|
|
75
|
+
monitorStepData: MonitorStepType | undefined,
|
|
76
|
+
): Array<string> {
|
|
77
|
+
const metricViewConfig: MetricsViewConfig | undefined =
|
|
78
|
+
this.getMetricViewConfig(monitorStepData);
|
|
79
|
+
|
|
80
|
+
if (!metricViewConfig) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const variables: Array<string> = [];
|
|
85
|
+
|
|
86
|
+
for (const queryConfig of metricViewConfig.queryConfigs || []) {
|
|
87
|
+
variables.push(
|
|
88
|
+
(queryConfig as MetricQueryConfigData).metricAliasData
|
|
89
|
+
?.metricVariable || "",
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
for (const formulaConfig of metricViewConfig.formulaConfigs || []) {
|
|
94
|
+
variables.push(
|
|
95
|
+
(formulaConfig as MetricFormulaConfigData).metricAliasData
|
|
96
|
+
?.metricVariable || "",
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Remove duplicates (first-seen order) and drop empty strings.
|
|
101
|
+
return variables.filter((item: string, index: number): boolean => {
|
|
102
|
+
return variables.indexOf(item) === index && item !== "";
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
}
|