|
22 | 22 | import java.security.KeyPairGenerator; |
23 | 23 | import java.security.PrivateKey; |
24 | 24 | import java.security.Security; |
| 25 | +import java.util.List; |
25 | 26 | import java.util.Properties; |
26 | 27 | import java.util.stream.Stream; |
27 | 28 | import org.apache.commons.io.FileUtils; |
@@ -645,6 +646,129 @@ public void testRecipeOnLocalPluginWithRunMode(WireMockRuntimeInfo wmRuntimeInfo |
645 | 646 | } |
646 | 647 | } |
647 | 648 |
|
| 649 | + @Test |
| 650 | + @Tag("Slow") |
| 651 | + public void testMultiModulePluginAddCodeOwner(WireMockRuntimeInfo wmRuntimeInfo) throws Exception { |
| 652 | + |
| 653 | + Path logFile = setupLogs("testMultiModulePluginAddCodeOwner"); |
| 654 | + |
| 655 | + // Copy multi-module plugin to cache and use as local plugin |
| 656 | + final String plugin = "test-plugin"; |
| 657 | + final Path multiModulePluginPath = Path.of("src/test/resources").resolve("multi-module-plugin"); |
| 658 | + Path targetPath = cachePath |
| 659 | + .resolve("jenkins-plugin-modernizer-cli") |
| 660 | + .resolve(plugin) |
| 661 | + .resolve("sources"); |
| 662 | + FileUtils.copyDirectory(multiModulePluginPath.toFile(), targetPath.toFile()); |
| 663 | + Git.init().setDirectory(targetPath.toFile()).call().close(); |
| 664 | + |
| 665 | + final String recipe = "AddCodeOwner"; |
| 666 | + |
| 667 | + try (GitHubServerContainer gitRemote = new GitHubServerContainer(wmRuntimeInfo, keysPath, plugin, "main")) { |
| 668 | + |
| 669 | + gitRemote.start(); |
| 670 | + |
| 671 | + // Junit attachment with logs file for the plugin build |
| 672 | + System.out.printf("[[ATTACHMENT|%s]]%n", getMavenInvokerLog(plugin)); |
| 673 | + System.out.printf("[[ATTACHMENT|%s]]%n", logFile.toAbsolutePath()); |
| 674 | + |
| 675 | + Invoker invoker = buildInvoker(); |
| 676 | + InvocationRequest request = buildRequest( |
| 677 | + "run --recipe %s %s".formatted(recipe, getRunArgs(wmRuntimeInfo, Plugin.build(plugin, targetPath))), |
| 678 | + logFile); |
| 679 | + InvocationResult result = invoker.execute(request); |
| 680 | + |
| 681 | + // Assert output |
| 682 | + assertAll( |
| 683 | + () -> assertEquals(0, result.getExitCode()), |
| 684 | + () -> assertTrue( |
| 685 | + Files.readAllLines(logFile).stream() |
| 686 | + .anyMatch(line -> line.matches("(.*)Modified file: .github/CODEOWNERS(.*)")), |
| 687 | + "Code owner file not modified on logs"), |
| 688 | + () -> assertTrue(Files.readAllLines(logFile).stream() |
| 689 | + .anyMatch(line -> line.matches("(.*)Dry run mode. Changes were made on (.*)")))); |
| 690 | + |
| 691 | + // Check that CODEOWNERS file was created in the plugin module subdirectory |
| 692 | + Path codeownersPath = targetPath.resolve("test-plugin").resolve(ArchetypeCommonFile.CODEOWNERS.getPath()); |
| 693 | + assertTrue(Files.exists(codeownersPath), "Code owner file was not created in plugin module subdirectory"); |
| 694 | + |
| 695 | + // Verify correct team name is used (plugin artifactId, not parent artifactId) |
| 696 | + List<String> codeownersLines = Files.readAllLines(codeownersPath); |
| 697 | + assertTrue( |
| 698 | + codeownersLines.stream().anyMatch(line -> line.contains("@jenkinsci/test-plugin-developers")), |
| 699 | + "CODEOWNERS file should contain correct team name based on plugin artifactId (test-plugin), not parent artifactId"); |
| 700 | + assertFalse( |
| 701 | + codeownersLines.stream() |
| 702 | + .anyMatch(line -> line.contains("@jenkinsci/multi-module-parent-developers")), |
| 703 | + "CODEOWNERS file should not contain parent artifactId in team name"); |
| 704 | + } |
| 705 | + } |
| 706 | + |
| 707 | + /** |
| 708 | + * Test multi-module plugin with FetchMetadata recipe (requires compilation) |
| 709 | + * This verifies that multi-module plugins can be properly compiled and modernized |
| 710 | + */ |
| 711 | + @Test |
| 712 | + @Tag("Slow") |
| 713 | + public void testMultiModulePluginFetchMetadata(WireMockRuntimeInfo wmRuntimeInfo) throws Exception { |
| 714 | + |
| 715 | + Path logFile = setupLogs("testMultiModulePluginFetchMetadata"); |
| 716 | + |
| 717 | + // Copy multi-module plugin to cache and use as local plugin |
| 718 | + final String plugin = "test-plugin"; |
| 719 | + final Path multiModulePluginPath = Path.of("src/test/resources").resolve("multi-module-plugin"); |
| 720 | + Path targetPath = cachePath |
| 721 | + .resolve("jenkins-plugin-modernizer-cli") |
| 722 | + .resolve(plugin) |
| 723 | + .resolve("sources"); |
| 724 | + FileUtils.copyDirectory(multiModulePluginPath.toFile(), targetPath.toFile()); |
| 725 | + Git.init().setDirectory(targetPath.toFile()).call().close(); |
| 726 | + |
| 727 | + final String recipe = "FetchMetadata"; |
| 728 | + |
| 729 | + try (GitHubServerContainer gitRemote = new GitHubServerContainer(wmRuntimeInfo, keysPath, plugin, "main")) { |
| 730 | + |
| 731 | + gitRemote.start(); |
| 732 | + |
| 733 | + // Junit attachment with logs file for the plugin build |
| 734 | + System.out.printf("[[ATTACHMENT|%s]]%n", getMavenInvokerLog(plugin)); |
| 735 | + System.out.printf("[[ATTACHMENT|%s]]%n", logFile.toAbsolutePath()); |
| 736 | + |
| 737 | + Invoker invoker = buildInvoker(); |
| 738 | + InvocationRequest request = buildRequest( |
| 739 | + "run --recipe %s %s".formatted(recipe, getRunArgs(wmRuntimeInfo, Plugin.build(plugin, targetPath))), |
| 740 | + logFile); |
| 741 | + InvocationResult result = invoker.execute(request); |
| 742 | + |
| 743 | + // Assert output - FetchMetadata requires compilation so it should complete successfully |
| 744 | + assertAll( |
| 745 | + () -> assertEquals(0, result.getExitCode(), "Build should succeed for multi-module plugin"), |
| 746 | + () -> assertTrue( |
| 747 | + Files.readAllLines(logFile).stream() |
| 748 | + .anyMatch( |
| 749 | + line -> line.matches("(.*)Multi-module project detected for plugin (.*)")), |
| 750 | + "Multi-module detection message not found in logs"), |
| 751 | + () -> assertTrue( |
| 752 | + Files.readAllLines(logFile).stream() |
| 753 | + .anyMatch(line -> line.matches("(.*)Found Jenkins plugin module at:(.*)")), |
| 754 | + "Plugin module detection message not found in logs")); |
| 755 | + |
| 756 | + // Verify metadata was collected from the plugin module (not parent) |
| 757 | + Path pluginMetadataPath = cachePath |
| 758 | + .resolve("jenkins-plugin-modernizer-cli") |
| 759 | + .resolve(plugin) |
| 760 | + .resolve("plugin-metadata.json"); |
| 761 | + assertTrue( |
| 762 | + Files.exists(pluginMetadataPath), "Plugin metadata file should exist after FetchMetadata recipe"); |
| 763 | + |
| 764 | + // Read and verify the metadata contains correct plugin name |
| 765 | + String metadataContent = Files.readString(pluginMetadataPath); |
| 766 | + assertTrue( |
| 767 | + metadataContent.contains("\"pluginName\":\"Test Plugin\""), |
| 768 | + "Metadata should contain correct plugin name from plugin module"); |
| 769 | + } |
| 770 | + } |
| 771 | + |
648 | 772 | /** |
649 | 773 | * Build the invoker |
650 | 774 | * @return the invoker |
|
0 commit comments