Skip to content
Merged
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 @@ -4,6 +4,7 @@

using Elastic.Documentation.AppliesTo;
using Elastic.Documentation.Configuration.Products;
using Elastic.Documentation.Extensions;
using Elastic.Markdown.Diagnostics;
using Elastic.Markdown.Helpers;

Expand Down Expand Up @@ -67,23 +68,10 @@ public override void FinalizeAndValidate(ParserContext context)

public static string GenerateSyncKey(string appliesToDefinition, ProductsConfiguration productsConfiguration)
{
// Parse the YAML to get the ApplicableTo object, then use its hash
// This ensures both simple syntax and YAML objects produce consistent sync keys
try
{
var applicableTo = YamlSerialization.Deserialize<ApplicableTo>(appliesToDefinition, productsConfiguration);
if (applicableTo != null)
{
// Use the object's hash for a consistent, unique identifier
return $"applies-{System.Math.Abs(applicableTo.GetHashCode())}";
}
}
catch
{
// If parsing fails, fall back to the original definition
}

// Fallback to original definition if parsing fails
return appliesToDefinition.Slugify().Replace(".", "-");
var applicableTo = YamlSerialization.Deserialize<ApplicableTo>(appliesToDefinition, productsConfiguration);
// Use ShortId.Create for a stable, deterministic hash based on the normalized ToString()
// ToString() normalizes different YAML representations into a canonical form,
// ensuring semantically equivalent definitions get the same sync key
return $"applies-{ShortId.Create(applicableTo.ToString())}";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -170,10 +170,7 @@ public void ParsesSyncKey()

// Verify all sync keys have the expected hash-based format
foreach (var item in items)
{
item.SyncKey.Should().StartWith("applies-", "Sync key should start with 'applies-' prefix");
item.SyncKey.Should().MatchRegex(@"^applies-\d+$", "Sync key should be in format 'applies-{hash}'");
}

// Verify that different applies_to definitions produce different sync keys
items[0].SyncKey.Should().NotBe(items[1].SyncKey, "Different applies_to definitions should produce different sync keys");
Expand Down Expand Up @@ -220,7 +217,43 @@ public void GeneratesConsistentSyncKeysForYamlObjects()

// Also verify the key has the expected format
key1.Should().StartWith("applies-", "Sync key should start with 'applies-' prefix");
key1.Should().MatchRegex(@"^applies-\d+$", "Sync key should be in format 'applies-{hash}'");
key1.Should().MatchRegex(@"^applies-[0-9A-F]{8}$", "Sync key should be in format 'applies-{8 hex digits}'");
}
}

[Fact]
public void GeneratesDeterministicSyncKeysAcrossMultipleRuns()
{
var expectedKeys = new Dictionary<string, string>
{
// These are the actual SHA256-based hashes that should never change
{ "stack: ga 9.1", "applies-031B7112" },
{ "stack: preview 9.0", "applies-361F73DC" },
{ "ess: ga 8.11", "applies-32E204F7" },
{ "deployment: { ece: ga 9.0, ess: ga 9.1 }", "applies-D099CDEF" },
{ "serverless: all", "applies-A34B17C6" },
};

foreach (var (definition, expectedKey) in expectedKeys)
{
var actualKey = AppliesItemBlock.GenerateSyncKey(definition, Block!.Build.ProductsConfiguration);

actualKey.Should().Be(expectedKey,
$"The sync key for '{definition}' must match the expected value. " +
$"If this fails, the hash algorithm has changed and will break sync IDs across builds!");

// Also verify multiple invocations in this run produce the same key
var keys = Enumerable.Range(0, 5)
.Select(_ => AppliesItemBlock.GenerateSyncKey(definition, Block!.Build.ProductsConfiguration))
.ToList();

keys.Distinct().Should().HaveCount(1,
$"All invocations for '{definition}' should produce identical keys");
}

// Verify that different definitions produce different keys
var allKeys = expectedKeys.Values.ToList();
allKeys.Distinct().Should().HaveCount(expectedKeys.Count,
"Different applies_to definitions must produce different sync keys");
}
}
Loading