@@ -170,10 +170,7 @@ public void ParsesSyncKey()
170170
171171 // Verify all sync keys have the expected hash-based format
172172 foreach ( var item in items )
173- {
174173 item . SyncKey . Should ( ) . StartWith ( "applies-" , "Sync key should start with 'applies-' prefix" ) ;
175- item . SyncKey . Should ( ) . MatchRegex ( @"^applies-\d+$" , "Sync key should be in format 'applies-{hash}'" ) ;
176- }
177174
178175 // Verify that different applies_to definitions produce different sync keys
179176 items [ 0 ] . SyncKey . Should ( ) . NotBe ( items [ 1 ] . SyncKey , "Different applies_to definitions should produce different sync keys" ) ;
@@ -220,7 +217,43 @@ public void GeneratesConsistentSyncKeysForYamlObjects()
220217
221218 // Also verify the key has the expected format
222219 key1 . Should ( ) . StartWith ( "applies-" , "Sync key should start with 'applies-' prefix" ) ;
223- key1 . Should ( ) . MatchRegex ( @"^applies-\d+ $" , "Sync key should be in format 'applies-{hash }'" ) ;
220+ key1 . Should ( ) . MatchRegex ( @"^applies-[0-9A-F]{8} $" , "Sync key should be in format 'applies-{8 hex digits }'" ) ;
224221 }
225222 }
223+
224+ [ Fact ]
225+ public void GeneratesDeterministicSyncKeysAcrossMultipleRuns ( )
226+ {
227+ var expectedKeys = new Dictionary < string , string >
228+ {
229+ // These are the actual SHA256-based hashes that should never change
230+ { "stack: ga 9.1" , "applies-031B7112" } ,
231+ { "stack: preview 9.0" , "applies-361F73DC" } ,
232+ { "ess: ga 8.11" , "applies-32E204F7" } ,
233+ { "deployment: { ece: ga 9.0, ess: ga 9.1 }" , "applies-D099CDEF" } ,
234+ { "serverless: all" , "applies-A34B17C6" } ,
235+ } ;
236+
237+ foreach ( var ( definition , expectedKey ) in expectedKeys )
238+ {
239+ var actualKey = AppliesItemBlock . GenerateSyncKey ( definition , Block ! . Build . ProductsConfiguration ) ;
240+
241+ actualKey . Should ( ) . Be ( expectedKey ,
242+ $ "The sync key for '{ definition } ' must match the expected value. " +
243+ $ "If this fails, the hash algorithm has changed and will break sync IDs across builds!") ;
244+
245+ // Also verify multiple invocations in this run produce the same key
246+ var keys = Enumerable . Range ( 0 , 5 )
247+ . Select ( _ => AppliesItemBlock . GenerateSyncKey ( definition , Block ! . Build . ProductsConfiguration ) )
248+ . ToList ( ) ;
249+
250+ keys . Distinct ( ) . Should ( ) . HaveCount ( 1 ,
251+ $ "All invocations for '{ definition } ' should produce identical keys") ;
252+ }
253+
254+ // Verify that different definitions produce different keys
255+ var allKeys = expectedKeys . Values . ToList ( ) ;
256+ allKeys . Distinct ( ) . Should ( ) . HaveCount ( expectedKeys . Count ,
257+ "Different applies_to definitions must produce different sync keys" ) ;
258+ }
226259}
0 commit comments