Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"old-type-no-migrations": {
"name": "old-type-no-migrations",
"migrationVersions": [],
"hash": "4631898d09a686928fabbbe1ad0b7f2b22c44b565443408ab5d20b4dcae64e35",
"hash": "2491dd0321b2bb36278a0a7fab9adb9575d1f960cdbab5a4a8a2ed26d1f9370c",
"modelVersions": [],
"schemaVersions": [],
"mappings": {
Expand All @@ -24,7 +24,7 @@
"migrationVersions": [
"8.7.0"
],
"hash": "a7916755843d9ed712ccefb6888ebcbdd2f2f3628e058bfd174454aef644437a",
"hash": "7090f00c3ce9bf5bbce821b5b14c48ab538abe1d2f87ccc8d022cb96dde43ce1",
"modelVersions": [],
"schemaVersions": [
"8.7.0"
Expand All @@ -38,11 +38,11 @@
"person-so-type": {
"name": "person-so-type",
"migrationVersions": [],
"hash": "b8a80c7a77c2d5f4d7964af4ef584a490a83d92012099e0d943ce566f9d52cfc",
"hash": "65702f72482adb0d4ab4c64978ef9510dc51766b483cc8f8525ab5aa5c8003ad",
"modelVersions": [
{
"version": "1",
"modelVersionHash": "e851da8aa62ba712eaa3e27bd787a982393fdde9a5627a779f48168edb0f86b0",
"modelVersionHash": "b7ee7569250dc40b80214f4d346caf2a3be065bb3059d7d69a4619af4c593bca",
"changeTypes": [
"mappings_addition"
],
Expand All @@ -52,8 +52,8 @@
"lastName.type"
],
"schemas": {
"forwardCompatibility": "2fc7b480e391f573cce65c0da1991d8925fa9d1aa998c89b50181a47f10e71e4",
"create": "79a184ebeb6bdecdae9b2314c5ded4c9f3379da264b3512ab561a12d917de3f6"
"forwardCompatibility": "68d31f32c675678cb718a4792259243c033963a22d647960e8f7052d86476f44",
"create": "8de56583fdfc0dec65578fffec6bd929ae763d63f1aa56fd2d3b6828379ec2dc"
}
}
],
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { updateBaselineHashes } from './update_baseline_hashes';

/**
* Utility to refresh computed hashes in `baseline_snapshot.json`.
*
* Run when transitive dependency changes (e.g. `joi`) cause the
* `Check Saved Objects` CI step to fail with a false positive like:
*
* "Some modelVersions have been updated for SO type 'person-so-type'
* after they were defined: 10.1.0."
*
* Usage:
* yarn test:jest packages/kbn-check-saved-objects-cli/src/commands/test/update_baseline_hashes.test.ts
*/
it('updates baseline_snapshot.json hashes', async () => {
const { updated, path } = await updateBaselineHashes();

if (updated.length === 0) {
// eslint-disable-next-line no-console
console.log(`✅ baseline_snapshot.json is already up to date — no hashes changed.`);
} else {
// eslint-disable-next-line no-console
console.log(
`✅ Updated hashes for ${updated.length} type(s) in baseline_snapshot.json: ${updated.join(
', '
)}\n` + ` File: ${path}`
);
}
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { readFileSync, writeFileSync } from 'fs';
import { resolve } from 'path';
import { takeSnapshot } from '../../snapshots/take_snapshot';
import type { MigrationInfoRecord, MigrationSnapshot } from '../../types';
import { TEST_TYPES } from './types';

const BASELINE_SNAPSHOT_PATH = resolve(__dirname, './baseline_snapshot.json');

/**
* Refreshes computed hashes in `baseline_snapshot.json` while preserving
* the hand-designed "before" state structure.
*
* Hashes are derived from `@kbn/config-schema` objects whose serialization
* depends on transitive dependencies (e.g. `joi`). When those dependencies
* are updated, the hashes drift and the CI `Check Saved Objects` test-mode
* fallback fails with a "modelVersions have been updated" false positive.
*
* This function:
* 1. Loads the existing baseline (preserving its structure: which types,
* which model versions, mappings, etc.).
* 2. Takes a fresh snapshot of `TEST_TYPES` to compute current hashes.
* 3. Patches only the hash-dependent fields (`hash`, `modelVersionHash`,
* `schemas`) in the baseline from the fresh snapshot.
* 4. Writes the updated baseline back to disk.
*/
export const updateBaselineHashes = async (): Promise<{ updated: string[]; path: string }> => {
const baseline: MigrationSnapshot = JSON.parse(
readFileSync(BASELINE_SNAPSHOT_PATH, { encoding: 'utf-8' })
);
const freshSnapshot = await takeSnapshot(TEST_TYPES);
const updated: string[] = [];

for (const [typeName, baselineType] of Object.entries(baseline.typeDefinitions)) {
const freshType: MigrationInfoRecord | undefined = freshSnapshot.typeDefinitions[typeName];

if (!freshType) {
continue;
}

let typeUpdated = false;

// Refresh the top-level type `hash` (from `getMigrationHash`).
if (baselineType.hash !== freshType.hash) {
baselineType.hash = freshType.hash;
typeUpdated = true;
}

// Refresh hashes inside each model version present in the baseline.
for (const baselineMV of baselineType.modelVersions) {
const freshMV = freshType.modelVersions.find((mv) => mv.version === baselineMV.version);

if (!freshMV) {
continue;
}

if (baselineMV.modelVersionHash !== freshMV.modelVersionHash) {
baselineMV.modelVersionHash = freshMV.modelVersionHash;
typeUpdated = true;
}

if (
baselineMV.schemas.forwardCompatibility !== freshMV.schemas.forwardCompatibility ||
baselineMV.schemas.create !== freshMV.schemas.create
) {
baselineMV.schemas = { ...freshMV.schemas };
typeUpdated = true;
}
}

if (typeUpdated) {
updated.push(typeName);
}
}

writeFileSync(BASELINE_SNAPSHOT_PATH, JSON.stringify(baseline, null, 2) + '\n');

return { updated, path: BASELINE_SNAPSHOT_PATH };
};