Skip to content

Commit 263a06c

Browse files
committed
Merge branch 'upstream/blueprint-configure-system-settings' into release52
# Conflicts: # DEVELOPER.md # meteor/server/__tests__/cronjobs.test.ts
2 parents 49730ed + 8ac7b39 commit 263a06c

File tree

117 files changed

+2484
-1447
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

117 files changed

+2484
-1447
lines changed

DEVELOPER.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,11 @@ Then submit this as a PR.
140140
The ConfigManifests for Blueprints and Gateways was replaced with JSONSchema in R50.
141141
However, one usage by AdlibActions for their userDataManifest remains as this is not something we are actively using.
142142

143+
## Blueprint Migrations
144+
145+
In R52, the replacement flow of `validateConfig` and `applyConfig` was extended to the system blueprint
146+
It is no longer recommended to use the old migrations flow for system blueprints.
147+
143148
### ExpectedMediaItems
144149

145150
These are used for Media-manager which is no longer being developed.

meteor/__mocks__/defaultCollectionObjects.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,15 +105,15 @@ export function defaultStudio(_id: StudioId): DBStudio {
105105
mappingsWithOverrides: wrapDefaultObject({}),
106106
supportedShowStyleBase: [],
107107
blueprintConfigWithOverrides: wrapDefaultObject({}),
108-
settings: {
108+
settingsWithOverrides: wrapDefaultObject({
109109
frameRate: 25,
110110
mediaPreviewsUrl: '',
111111
minimumTakeSpan: DEFAULT_MINIMUM_TAKE_SPAN,
112112
fallbackPartDuration: DEFAULT_FALLBACK_PART_DURATION,
113113
allowHold: false,
114114
allowPieceDirectPlay: false,
115115
enableBuckets: false,
116-
},
116+
}),
117117
_rundownVersionHash: '',
118118
routeSetsWithOverrides: wrapDefaultObject({}),
119119
routeSetExclusivityGroupsWithOverrides: wrapDefaultObject({}),

meteor/__mocks__/helpers/database.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,25 @@ export async function setupMockCore(doc?: Partial<ICoreSystem>): Promise<ICoreSy
171171
version: '0.0.0',
172172
previousVersion: '0.0.0',
173173
serviceMessages: {},
174+
settingsWithOverrides: wrapDefaultObject({
175+
cron: {
176+
casparCGRestart: {
177+
enabled: true,
178+
},
179+
storeRundownSnapshots: {
180+
enabled: false,
181+
},
182+
},
183+
support: {
184+
message: '',
185+
},
186+
evaluationsMessage: {
187+
enabled: false,
188+
heading: '',
189+
message: '',
190+
},
191+
}),
192+
lastBlueprintConfig: undefined,
174193
}
175194
const coreSystem = _.extend(defaultCore, doc)
176195
await CoreSystem.removeAsync(SYSTEM_ID)

meteor/server/__tests__/api/serviceMessages/serviceMessagesApi.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
} from '@sofie-automation/meteor-lib/dist/collections/CoreSystem'
1010
import { CoreSystem } from '../../../collections'
1111
import { SupressLogMessages } from '../../../../__mocks__/suppressLogging'
12+
import { wrapDefaultObject } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
1213

1314
function convertExternalToServiceMessage(message: ExternalServiceMessage): ServiceMessage {
1415
return {
@@ -42,6 +43,8 @@ const fakeCoreSystem: ICoreSystem = {
4243
version: '3',
4344
previousVersion: null,
4445
serviceMessages: {},
46+
settingsWithOverrides: wrapDefaultObject({} as any),
47+
lastBlueprintConfig: undefined,
4548
}
4649

4750
describe('Service messages internal API', () => {

meteor/server/__tests__/cronjobs.test.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import '../../__mocks__/_extendJest'
22
import { runAllTimers, waitUntil } from '../../__mocks__/helpers/jest'
33
import { MeteorMock } from '../../__mocks__/meteor'
44
import { logger } from '../logging'
5-
import { getRandomId, getRandomString, protectString } from '../lib/tempLib'
5+
import { getRandomId, getRandomString, literal, protectString } from '../lib/tempLib'
66
import { SnapshotType } from '@sofie-automation/meteor-lib/dist/collections/Snapshots'
77
import { IBlueprintPieceType, PieceLifespan, StatusCode, TSR } from '@sofie-automation/blueprints-integration'
88
import {
@@ -64,26 +64,36 @@ import {
6464
import { DBSegment } from '@sofie-automation/corelib/dist/dataModel/Segment'
6565
import { Settings } from '../Settings'
6666
import { SofieIngestCacheType } from '@sofie-automation/corelib/dist/dataModel/SofieIngestDataCache'
67+
import { ObjectOverrideSetOp } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
6768

6869
describe('cronjobs', () => {
6970
let env: DefaultEnvironment
7071
let rundownId: RundownId
7172

72-
beforeAll(async () => {
73-
env = await setupDefaultStudioEnvironment()
74-
75-
const o = await setupDefaultRundownPlaylist(env)
76-
rundownId = o.rundownId
77-
73+
async function setCasparCGCronEnabled(enabled: boolean) {
7874
await CoreSystem.updateAsync(
7975
{},
8076
{
81-
$set: {
82-
'cron.casparCGRestart.enabled': true,
77+
// This is a little bit of a hack, as it will result in duplicate ops, but it's fine for unit tests
78+
$push: {
79+
'settingsWithOverrides.overrides': literal<ObjectOverrideSetOp>({
80+
op: 'set',
81+
path: 'cron.casparCGRestart.enabled',
82+
value: enabled,
83+
}),
8384
},
8485
},
8586
{ multi: true }
8687
)
88+
}
89+
90+
beforeAll(async () => {
91+
env = await setupDefaultStudioEnvironment()
92+
93+
const o = await setupDefaultRundownPlaylist(env)
94+
rundownId = o.rundownId
95+
96+
await setCasparCGCronEnabled(true)
8797

8898
jest.useFakeTimers()
8999
// set time to 2020/07/19 00:00 Local Time
@@ -591,15 +601,7 @@ describe('cronjobs', () => {
591601
})
592602
test('Does not attempt to restart CasparCG when job is disabled', async () => {
593603
await createMockPlayoutGatewayAndDevices(Date.now()) // Some time after the threshold
594-
await CoreSystem.updateAsync(
595-
{},
596-
{
597-
$set: {
598-
'cron.casparCGRestart.enabled': false,
599-
},
600-
},
601-
{ multi: true }
602-
)
604+
await setCasparCGCronEnabled(false)
603605
;(logger.info as jest.Mock).mockClear()
604606
// set time to 2020/07/{date} 04:05 Local Time, should be more than 24 hours after 2020/07/19 00:00 UTC
605607
mockCurrentTime = new Date(2020, 6, date++, 4, 5, 0).getTime()

meteor/server/api/evaluations.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { sendSlackMessageToWebhook } from './integration/slack'
1010
import { OrganizationId, UserId } from '@sofie-automation/corelib/dist/dataModel/Ids'
1111
import { DBRundownPlaylist } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist'
1212
import { Evaluations, RundownPlaylists } from '../collections'
13+
import { applyAndValidateOverrides } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
1314

1415
export async function saveEvaluation(
1516
credentials: {
@@ -33,8 +34,9 @@ export async function saveEvaluation(
3334
deferAsync(async () => {
3435
const studio = await fetchStudioLight(evaluation.studioId)
3536
if (!studio) throw new Meteor.Error(500, `Studio ${evaluation.studioId} not found!`)
37+
const studioSettings = applyAndValidateOverrides(studio.settingsWithOverrides).obj
3638

37-
const webhookUrls = _.compact((studio.settings.slackEvaluationUrls || '').split(','))
39+
const webhookUrls = _.compact((studioSettings.slackEvaluationUrls || '').split(','))
3840

3941
if (webhookUrls.length) {
4042
// Only send notes if not everything is OK

meteor/server/api/rest/v1/typeConversion.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ import {
5353
DEFAULT_FALLBACK_PART_DURATION,
5454
} from '@sofie-automation/shared-lib/dist/core/constants'
5555
import { Bucket } from '@sofie-automation/meteor-lib/dist/collections/Buckets'
56-
import { ForceQuickLoopAutoNext } from '@sofie-automation/corelib/dist/dataModel/RundownPlaylist'
56+
import { ForceQuickLoopAutoNext } from '@sofie-automation/shared-lib/dist/core/model/StudioSettings'
5757

5858
/*
5959
This file contains functions that convert between the internal Sofie-Core types and types exposed to the external API.
@@ -307,13 +307,17 @@ export async function studioFrom(apiStudio: APIStudio, existingId?: StudioId): P
307307
: convertObjectIntoOverrides(await StudioBlueprintConfigFromAPI(apiStudio, blueprintManifest))
308308
}
309309

310+
const studioSettings = studioSettingsFrom(apiStudio.settings)
311+
310312
return {
311313
_id: existingId ?? getRandomId(),
312314
name: apiStudio.name,
313315
blueprintId: blueprint?._id,
314316
blueprintConfigPresetId: apiStudio.blueprintConfigPresetId,
315317
blueprintConfigWithOverrides: blueprintConfig,
316-
settings: studioSettingsFrom(apiStudio.settings),
318+
settingsWithOverrides: studio
319+
? updateOverrides(studio.settingsWithOverrides, studioSettings)
320+
: wrapDefaultObject(studioSettings),
317321
supportedShowStyleBase: apiStudio.supportedShowStyleBase?.map((id) => protectString<ShowStyleBaseId>(id)) ?? [],
318322
organizationId: null,
319323
mappingsWithOverrides: wrapDefaultObject({}),
@@ -334,7 +338,7 @@ export async function studioFrom(apiStudio: APIStudio, existingId?: StudioId): P
334338
}
335339

336340
export async function APIStudioFrom(studio: DBStudio): Promise<Complete<APIStudio>> {
337-
const studioSettings = APIStudioSettingsFrom(studio.settings)
341+
const studioSettings = APIStudioSettingsFrom(applyAndValidateOverrides(studio.settingsWithOverrides).obj)
338342

339343
return {
340344
name: studio.name,

meteor/server/api/studio/api.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ export async function insertStudioInner(organizationId: OrganizationId | null, n
4444
supportedShowStyleBase: [],
4545
blueprintConfigWithOverrides: wrapDefaultObject({}),
4646
// testToolsConfig?: ITestToolsConfig
47-
settings: {
47+
settingsWithOverrides: wrapDefaultObject({
4848
frameRate: 25,
4949
mediaPreviewsUrl: '',
5050
minimumTakeSpan: DEFAULT_MINIMUM_TAKE_SPAN,
5151
allowHold: false,
5252
allowPieceDirectPlay: false,
5353
enableBuckets: true,
54-
},
54+
}),
5555
_rundownVersionHash: '',
5656
routeSetsWithOverrides: wrapDefaultObject({}),
5757
routeSetExclusivityGroupsWithOverrides: wrapDefaultObject({}),

meteor/server/collections/index.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,13 @@ export const CoreSystem = createAsyncOnlyMongoCollection<ICoreSystem>(Collection
6666
if (!access.update) return logNotAllowed('CoreSystem', access.reason)
6767

6868
return allowOnlyFields(doc, fields, [
69-
'support',
7069
'systemInfo',
7170
'name',
7271
'logLevel',
7372
'apm',
74-
'cron',
7573
'logo',
76-
'evaluations',
74+
'blueprintId',
75+
'settingsWithOverrides',
7776
])
7877
},
7978
})

meteor/server/coreSystem/index.ts

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import { getEnvLogLevel, logger, LogLevel, setLogLevel } from '../logging'
1010
const PackageInfo = require('../../package.json')
1111
import { startAgent } from '../api/profiler/apm'
1212
import { profiler } from '../api/profiler'
13-
import { TMP_TSR_VERSION } from '@sofie-automation/blueprints-integration'
13+
import { ICoreSystemSettings, TMP_TSR_VERSION } from '@sofie-automation/blueprints-integration'
1414
import { getAbsolutePath } from '../lib'
1515
import * as fs from 'fs/promises'
1616
import path from 'path'
1717
import { checkDatabaseVersions } from './checkDatabaseVersions'
1818
import PLazy from 'p-lazy'
1919
import { getCoreSystemAsync } from './collection'
20+
import { wrapDefaultObject } from '@sofie-automation/corelib/dist/settings/objectWithOverrides'
2021

2122
export { PackageInfo }
2223

@@ -59,11 +60,25 @@ async function initializeCoreSystem() {
5960
enabled: false,
6061
transactionSampleRate: -1,
6162
},
62-
cron: {
63-
casparCGRestart: {
64-
enabled: true,
63+
settingsWithOverrides: wrapDefaultObject<ICoreSystemSettings>({
64+
cron: {
65+
casparCGRestart: {
66+
enabled: true,
67+
},
68+
storeRundownSnapshots: {
69+
enabled: false,
70+
},
6571
},
66-
},
72+
support: {
73+
message: '',
74+
},
75+
evaluationsMessage: {
76+
enabled: false,
77+
heading: '',
78+
message: '',
79+
},
80+
}),
81+
lastBlueprintConfig: undefined,
6782
})
6883

6984
if (!isRunningInJest()) {

0 commit comments

Comments
 (0)