From 541514ba0e47d062c9bf12b5b4e71cb45b01006b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Gro=C3=9F?= Date: Sun, 18 Oct 2026 21:38:51 +0200 Subject: [PATCH] test: read the pull_request trigger's settings whatever their YAML spelling The convention test from #203 matched lines indented by four spaces right after `pull_request:`, so a flow mapping (`pull_request: { branches: [...] }`) and a block after a blank line both passed with a branch filter present. It now takes the text after the key's colon plus every deeper-indented line up to the next key, comments removed. Found-By: pre-tag analysis (#179) Defect-Class: weak-guard Closes #237 Co-Authored-By: Claude Opus 5.5 --- .../ReleaseWiringConventionTests.cs | 36 ++++++++++++++++--- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/test/CodoMetis.ValueRanges.Conventions.Tests/ReleaseWiringConventionTests.cs b/test/CodoMetis.ValueRanges.Conventions.Tests/ReleaseWiringConventionTests.cs index 03444f76..07f79caf 100644 --- a/test/CodoMetis.ValueRanges.Conventions.Tests/ReleaseWiringConventionTests.cs +++ b/test/CodoMetis.ValueRanges.Conventions.Tests/ReleaseWiringConventionTests.cs @@ -202,12 +202,9 @@ private static IEnumerable BuildOnlyReferencesOf(PackableProject project [TestMethod] public void PullRequests_AreBuiltWhateverTheirBase() { - var trigger = Regex.Match( - BuildWorkflowText(), @"^ pull_request:[^\n]*\n((?: [^\n]*\n)*)", RegexOptions.Multiline); + var settings = TriggerSettings(BuildWorkflowText(), "pull_request"); - Assert.IsTrue(trigger.Success, "The .NET workflow has no pull_request trigger."); - - var settings = trigger.Groups[1].Value; + Assert.IsNotNull(settings, "The .NET workflow has no pull_request trigger."); Assert.IsFalse( settings.Contains("branches", StringComparison.Ordinal), @@ -257,6 +254,35 @@ public void TheIntegrationGate_PassesOnlyWhenEveryLegPassed() StringAssert.Contains(gate, "needs.integration-legs.result }}\" = success"); } + /// + /// The settings of one trigger under on:, comments removed: whatever follows its colon on + /// the same line (a flow mapping such as { branches: [ main ] }), and every following line + /// that is blank or indented deeper than the key, up to the next key at the key's indentation or + /// shallower. A line-anchored regex missed both the flow form and a block after a blank line + /// (#237). when the trigger isn't there. + /// + private static string? TriggerSettings(string workflow, string trigger) + { + var lines = workflow.Replace("\r\n", "\n", StringComparison.Ordinal).Split('\n'); + var keyLine = Array.FindIndex(lines, line => Regex.IsMatch(line, $@"^\s+{trigger}\s*:")); + + if (keyLine < 0) return null; + + static string Uncommented(string line) => Regex.Replace(line, @"(^|\s)#.*$", ""); + + var indent = lines[keyLine].Length - lines[keyLine].TrimStart().Length; + var settings = new List { Uncommented(lines[keyLine][(lines[keyLine].IndexOf(':') + 1)..]) }; + + foreach (var line in lines.Skip(keyLine + 1)) + { + if (line.Trim().Length == 0 || line.TrimStart().StartsWith('#')) continue; + if (line.Length - line.TrimStart().Length <= indent) break; + settings.Add(Uncommented(line)); + } + + return string.Join('\n', settings); + } + private static string BuildWorkflowText() => File.ReadAllText(Path.Combine(RepoLayout.Root.FullName, ".github", "workflows", "dotnet.yml"));