Skip to content

Commit 4f6ac55

Browse files
authored
Add a unit test covering codeflow reverts (#6292)
#6293
1 parent c6b40d2 commit 4f6ac55

1 file changed

Lines changed: 75 additions & 0 deletions

File tree

test/Darc/Microsoft.DotNet.DarcLib.Codeflow.Tests/ForwardFlowTests.cs

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,4 +743,79 @@ public async Task ForwardflowDoesntFlowOlderBuilds()
743743
var exception = await act.Should().ThrowAsync<NonLinearCodeflowException>();
744744
exception.Which.FlowingOldBuild.Should().BeTrue();
745745
}
746+
747+
[Test]
748+
public async Task ReflowAfterRevertedForwardflowAppliesCleanlyTest()
749+
{
750+
await EnsureTestRepoIsInitialized();
751+
752+
const string branchName = nameof(ReflowAfterRevertedForwardflowAppliesCleanlyTest);
753+
const string vmrSideFileName = "vmr-side-file.txt";
754+
755+
// 1. Forward flow a first change and merge it
756+
var codeFlowResult = await ChangeRepoFileAndFlowIt("First change in the individual repo", branchName);
757+
codeFlowResult.ShouldHaveUpdates();
758+
await FinalizeForwardFlow(branchName);
759+
CheckFileContents(_productRepoVmrFilePath, "First change in the individual repo");
760+
761+
// 2. Forward flow a second change and merge it - keep a reference to the build so we can re-flow it later
762+
await GitOperations.Checkout(ProductRepoPath, "main");
763+
await File.WriteAllTextAsync(_productRepoFilePath, "Second change in the individual repo");
764+
await GitOperations.CommitAll(ProductRepoPath, "Second change in the individual repo");
765+
var secondBuild = await CreateNewRepoBuild([]);
766+
767+
codeFlowResult = await CallForwardflow(Constants.ProductRepoName, ProductRepoPath, branchName, buildToFlow: secondBuild);
768+
codeFlowResult.ShouldHaveUpdates();
769+
await FinalizeForwardFlow(branchName);
770+
CheckFileContents(_productRepoVmrFilePath, "Second change in the individual repo");
771+
772+
// Capture the squash-merge commit for the second forward flow so we can revert it later
773+
await GitOperations.Checkout(VmrPath, "main");
774+
var secondFlowMergeCommit = await GitOperations.GetRepoLastCommit(VmrPath);
775+
776+
// 3. Backflow a VMR change to the product repo and merge it
777+
await GitOperations.Checkout(VmrPath, "main");
778+
await File.WriteAllTextAsync(_productRepoVmrPath / "backflowed-file.txt", "File added in the VMR to be backflowed");
779+
await GitOperations.CommitAll(VmrPath, "Add a file in the VMR to be backflowed");
780+
781+
codeFlowResult = await CallBackflow(Constants.ProductRepoName, ProductRepoPath, branchName);
782+
codeFlowResult.ShouldHaveUpdates();
783+
await FinalizeBackFlow(branchName);
784+
CheckFileContents(ProductRepoPath / "backflowed-file.txt", "File added in the VMR to be backflowed");
785+
786+
// 4. Make an unrelated change in the VMR in the same product repo (must survive the revert + reflow)
787+
await GitOperations.Checkout(VmrPath, "main");
788+
await File.WriteAllTextAsync(_productRepoVmrPath / vmrSideFileName, "VMR-only change in the product repo");
789+
await GitOperations.CommitAll(VmrPath, "Direct VMR change in the product repo");
790+
791+
// 5. Revert the second codeflow's merge commit in the VMR
792+
var revertResult = await GitOperations.ExecuteGitCommand(VmrPath, "revert", "--no-edit", secondFlowMergeCommit);
793+
revertResult.ThrowIfFailed("Failed to revert the second forward flow merge commit");
794+
795+
// After the revert, the second forward flow's content should be gone, but the VMR-only change should remain
796+
CheckFileContents(_productRepoVmrFilePath, "First change in the individual repo");
797+
File.Exists(_productRepoVmrPath / vmrSideFileName).Should().BeTrue();
798+
CheckFileContents(_productRepoVmrPath / vmrSideFileName, "VMR-only change in the product repo");
799+
800+
// 6. Backflow without merging - the product repo's file shouldn't be reverted back to the first state
801+
codeFlowResult = await CallBackflow(Constants.ProductRepoName, ProductRepoPath, branchName);
802+
codeFlowResult.ShouldHaveUpdates();
803+
CheckFileContents(_productRepoFilePath, "Second change in the individual repo");
804+
805+
// Reset the product repo back to main so the re-flow uses the latest repo commit
806+
await GitOperations.Checkout(ProductRepoPath, "main");
807+
808+
// 7. Flow the same build again - it should cleanly apply just like the first time
809+
codeFlowResult = await CallForwardflow(Constants.ProductRepoName, ProductRepoPath, branchName, buildToFlow: secondBuild);
810+
codeFlowResult.ShouldHaveUpdates();
811+
codeFlowResult.ConflictedFiles.Should().BeEmpty(
812+
"Re-flowing a build whose previous forward flow was reverted should apply cleanly without conflicts");
813+
814+
await FinalizeForwardFlow(branchName);
815+
816+
// The second change should be re-applied and the VMR-only change should still be present
817+
CheckFileContents(_productRepoVmrFilePath, "Second change in the individual repo");
818+
File.Exists(_productRepoVmrPath / vmrSideFileName).Should().BeTrue();
819+
CheckFileContents(_productRepoVmrPath / vmrSideFileName, "VMR-only change in the product repo");
820+
}
746821
}

0 commit comments

Comments
 (0)