diff --git a/README.md b/README.md index d370fec..133a863 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,44 @@ For example, developers may use this feature to bind a Habushu module's `compile ``` +### Leveraging the containerize-dependencies Goal to Prepare a Containerized Virtual Environment ### +If the execution is specified (does not run by default), the `containerize-dependencies` goal will collect the monorepo python dependency specified in the dependencies block of the project's `pom.xml`, including all transitive dependencies. After collecting the set of necessary dependencies, Habushu will copy the source files to the build directory, while preserving the original structure of the dependency modules to ensure that any path-based dependencies can be leveraged as-is. + +```xml + + org.technologybrewery.habushu + habushu-maven-plugin + true + + ... + + + + containerize-deps + validate + + containerize-dependencies + + + + +``` + +The plugin will only examine dependencies that are of the type `habushu` in the dependencies block of the `pom.xml` file. + +```xml + + + your-group-id + your-artifact-id + your-version + habushu + + +``` + +Any transitive monorepo dependency `pom.xml` files shoud also use this convention to ensure they are captured by the plugin. + ### Leveraging Maven Build Cache for Faster Builds ### Habushu enables support for faster builds via @@ -682,13 +720,15 @@ Folder in which Python test files are located - should align with Poetry's proje Default: `${project.basedir}/tests` -#### cacheWheels #### +#### cacheWheels (deprecated) #### +The `cache-wheels` goal has been `deprecated`, please see the `containerize-dependencies` goal instead. Enables or Disables the copying of wheels into Poetry cache. Default: `false` -#### wheelDependencies #### +#### wheelDependencies (deprecated) #### +The `retrieve-wheels` goal has been `deprecated`, please see the `containerize-dependencies` goal instead. Optional set of wheel dependencies to retrieve from poetry cache. This allows previously cached external wheel dependencies to be copied into a given target directory if it exists in poetry cache. This logic @@ -876,8 +916,7 @@ Uses [behave](https://github.com/behave/behave) to execute BDD scenarios that ar Builds the `sdist` and `wheel` archives of this project using `poetry build`. It also generates a `requirements.txt` file which is useful when installing the package in a Docker container where you may want to install the dependencies in a specific Docker layer to optimize caching. ##### install ##### -Publishes the `pom.xml` for the module into your local Maven Repository (`~/.m2/repository`). If the **cacheWheels** configuration is set to True, the `wheel` archive will be copied to the poetry cache directory (`~/{poetry-cache-dir}/cache/repositories/wheels/{artifact-id}/`). The **cacheWheels** configuration default behavior is not to cache the `wheel` archive. If the **wheelDependencies** list is set, each specified wheel dependency will be -retrieve and placed into the given target directory. +Publishes the `pom.xml` for the module into your local Maven Repository (`~/.m2/repository`). ##### deploy ##### diff --git a/habushu-maven-plugin/pom.xml b/habushu-maven-plugin/pom.xml index 9d8313a..1c64bae 100644 --- a/habushu-maven-plugin/pom.xml +++ b/habushu-maven-plugin/pom.xml @@ -152,6 +152,24 @@ cucumber-junit-platform-engine test + + junit + junit + 4.13.2 + test + + + org.apache.maven + maven-compat + ${version.maven} + test + + + org.apache.maven.plugin-testing + maven-plugin-testing-harness + 4.0.0-alpha-2 + test + org.junit.platform junit-platform-suite @@ -191,6 +209,9 @@ cucumber.junit-platform.naming-strategy=long + + **/ContainerizeDependenciesMojoTestCase.java + diff --git a/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/CacheWheelsMojo.java b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/CacheWheelsMojo.java index ea54afe..f9c7386 100644 --- a/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/CacheWheelsMojo.java +++ b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/CacheWheelsMojo.java @@ -20,7 +20,9 @@ * wheel files in poetry. * * @throws HabushuException + * @deprecated This mojo is deprecated, use the containerize-dependencies goal instead */ +@Deprecated @Mojo(name = "cache-wheels", defaultPhase = LifecyclePhase.INSTALL) public class CacheWheelsMojo extends AbstractHabushuMojo { /** @@ -31,6 +33,8 @@ public class CacheWheelsMojo extends AbstractHabushuMojo { @Override public void doExecute() throws MojoExecutionException, MojoFailureException { + getLog().warn("The cache-wheels goal has been deperecated," + + "please see the containerize-dependencies goal instead." ); if (cacheWheels) { cacheWheels(); } diff --git a/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/ContainerizeDependenciesMojo.java b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/ContainerizeDependenciesMojo.java new file mode 100644 index 0000000..815f619 --- /dev/null +++ b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/ContainerizeDependenciesMojo.java @@ -0,0 +1,156 @@ +package org.technologybrewery.habushu; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.model.Dependency; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.project.MavenProject; +import org.apache.maven.shared.model.fileset.FileSet; +import org.apache.maven.shared.model.fileset.util.FileSetManager; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * Stages the source files of a monorepo dependency + * to the target directory along with the source file of + * any transitive path-based dependencies. + */ + +@Mojo(name = "containerize-dependencies", defaultPhase = LifecyclePhase.VALIDATE) +public class ContainerizeDependenciesMojo extends AbstractHabushuMojo { + + private static final Logger logger = LoggerFactory.getLogger(ContainerizeDependenciesMojo.class); + + @Component + protected MavenSession session; + + protected File anchorSourceDirectory; + protected File anchorOutputDirectory; + protected final String HABUSHU = "habushu"; + + /** + * Overriding to allow execution in non-habushu projects. + */ + @Override + public void execute() throws MojoExecutionException, MojoFailureException { + doExecute(); + } + + @Override + protected void doExecute() throws MojoExecutionException, MojoFailureException { + if (this.anchorSourceDirectory == null) { + this.anchorSourceDirectory = new File(session.getExecutionRootDirectory()); + } + + Set habushuProjects = getHabushuProjects(); + try { + copyRelevant(habushuProjects); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + /** + * Copies the relevant source files by leveraging {@link FileSet}s to filter appropriately. + * @param habushuProjects corresponding projects of the pom's habushu-type dependencies + * @throws IOException + */ + private void copyRelevant(Set habushuProjects) throws IOException { + this.anchorOutputDirectory = new File(project.getBuild().getDirectory() + + "/venv-support/" + this.anchorSourceDirectory.getName()); + Path srcRoot = this.anchorSourceDirectory.toPath(); + Path destRoot = this.anchorOutputDirectory.toPath(); + + Map dependencyFileSets = new HashMap<>(); + for (MavenProject project : habushuProjects) { + Path projectPath = project.getFile().getParentFile().toPath(); + Path relativeProjectPath = srcRoot.relativize(projectPath); + FileSet fileSet = getDefaultFileSet(); + fileSet.setDirectory(projectPath.toString()); + dependencyFileSets.put(relativeProjectPath, fileSet); + } + + FileSetManager fileSetManager = new FileSetManager(); + for (Path project : dependencyFileSets.keySet()) { + FileSet fileSet = dependencyFileSets.get(project); + logger.info("Copying {} files from {}", + fileSetManager.getIncludedFiles(fileSet).length, + project.getFileName() + ); + for (String includedFile : fileSetManager.getIncludedFiles(fileSet)) { + Path relativePath = project.resolve(includedFile); + Files.createDirectories(destRoot.resolve(relativePath).getParent()); + Files.copy(srcRoot.resolve(relativePath), destRoot.resolve(relativePath)); + } + } + } + + private FileSet getDefaultFileSet() { + FileSet fileSet = new FileSet(); + fileSet.addExclude("target/**"); + fileSet.addExclude(".venv/**"); + fileSet.addExclude("dist/**"); + return fileSet; + } + + /** + * Checks listed habushu-type dependencies against the set of projects included in the Maven build's session + * @return the corresponding Maven projects that match the habushu-type dependencies + */ + protected Set getHabushuProjects() { + HashSet habushuProjects = new HashSet<>(); + collectHabushuDependenciesAsProjects(project, habushuProjects); + return habushuProjects; + } + + /** + * Collects the projects of the habushu-type dependencies and adds them to the given project set + * @param currentProject the project to interrogate the habushu-type dependencies against + * @param habushuProjects the set to append to with matching projects + */ + private void collectHabushuDependenciesAsProjects(MavenProject currentProject, Set habushuProjects) { + Set habushuDeps = currentProject.getDependencies().stream() + .filter(d -> HABUSHU.equals(d.getType())) + .map(ContainerizeDependenciesMojo::toGav) + .collect(Collectors.toSet()); + for (MavenProject project : getSession().getProjects()) { + if (habushuDeps.contains(toGav(project))) { + logger.info("Found habushu-type dependency's project {}.", project); + habushuProjects.add(project); + collectHabushuDependenciesAsProjects(project, habushuProjects); + } + } + } + + private static String toGav(Dependency dependency) { + return dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getVersion(); + } + private static String toGav(MavenProject project) { + return project.getGroupId() + ":" + project.getArtifactId() + ":" + project.getVersion(); + } + + protected MavenSession getSession() { + return this.session; + } + + protected void setAnchorSourceDirectory(File anchorSourceDirectory) { + this.anchorSourceDirectory = anchorSourceDirectory; + } + + public File getAnchorOutputDirectory() { + return anchorOutputDirectory; + } +} diff --git a/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/RetrieveWheelsMojo.java b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/RetrieveWheelsMojo.java index a1d8979..c263b7e 100644 --- a/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/RetrieveWheelsMojo.java +++ b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/RetrieveWheelsMojo.java @@ -23,7 +23,9 @@ * wheel artifacts cached by the {@param cacheWheels} parameter and REQUIRES * the requested wheel to have first been cached prior to setting this config * @throws HabushuException + * @deprecated This mojo is deprecated, use the containerize-dependencies goal instead */ +@Deprecated @Mojo(name = "retrieve-wheels", defaultPhase = LifecyclePhase.VALIDATE) public class RetrieveWheelsMojo extends AbstractHabushuMojo { /** @@ -42,6 +44,8 @@ public void execute() throws MojoExecutionException, MojoFailureException { @Override public void doExecute() throws MojoExecutionException, MojoFailureException { + getLog().warn("The cache-wheels goal has been deperecated," + + "please see the containerize-dependencies goal instead." ); if (!wheelDependencies.isEmpty()) { processWheelDependencies(); } diff --git a/habushu-maven-plugin/src/main/resources/META-INF/plexus/components.xml b/habushu-maven-plugin/src/main/resources/META-INF/plexus/components.xml index d4f9630..7bc3341 100644 --- a/habushu-maven-plugin/src/main/resources/META-INF/plexus/components.xml +++ b/habushu-maven-plugin/src/main/resources/META-INF/plexus/components.xml @@ -18,9 +18,6 @@ org.technologybrewery.habushu:habushu-maven-plugin:${project.version}:initialize-habushu, org.technologybrewery.habushu:habushu-maven-plugin:${project.version}:baton-migrate - - org.technologybrewery.habushu:habushu-maven-plugin:${project.version}:retrieve-wheels - org.technologybrewery.habushu:habushu-maven-plugin:${project.version}:install-dependencies org.technologybrewery.habushu:habushu-maven-plugin:${project.version}:format-python, @@ -30,7 +27,6 @@ org.technologybrewery.habushu:habushu-maven-plugin:${project.version}:behave-bdd-test org.technologybrewery.habushu:habushu-maven-plugin:${project.version}:build-deployment-artifacts - org.technologybrewery.habushu:habushu-maven-plugin:${project.version}:cache-wheels, org.apache.maven.plugins:maven-install-plugin:install diff --git a/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDependenciesMojoTestCase.java b/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDependenciesMojoTestCase.java new file mode 100644 index 0000000..2e01a71 --- /dev/null +++ b/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDependenciesMojoTestCase.java @@ -0,0 +1,147 @@ +package org.technologybrewery.habushu; + +import org.apache.maven.DefaultMaven; +import org.apache.maven.Maven; +import org.apache.maven.execution.*; +import org.apache.maven.plugin.Mojo; +import org.apache.maven.plugin.testing.AbstractMojoTestCase; +import org.apache.maven.project.MavenProject; +import org.apache.maven.project.ProjectBuilder; +import org.apache.maven.project.ProjectBuildingRequest; +import org.apache.maven.session.scope.internal.SessionScope; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory; +import org.eclipse.aether.repository.LocalRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * Wraps the default behavior provided by the Maven plugin testing harness through {@link AbstractMojoTestCase} to + * set standard Maven defaults on any {@link Mojo}s that are created and reduce the amount of mock stubs required. + *

+ * This class is largely adapted from the testing approach developed by the license-audit-maven-plugin's + * {@code BetterAbstractMojoTestCase} (https://github.com/ahgittin/license-audit-maven-plugin) + */ +public class ContainerizeDependenciesMojoTestCase extends AbstractMojoTestCase { + + private static final Logger logger = LoggerFactory.getLogger(ContainerizeDependenciesMojoTestCase.class); + + private List mavenProjectFiles = new ArrayList<>(); + + public void configurePluginTestHarness() throws Exception { + super.setUp(); + } + + public void tearDownPluginTestHarness() throws Exception { + super.tearDown(); + } + + /** + * Creates a new {@link MavenSession} with default configurations relevant for testing the plugin. + * + * @return MavenSession + */ + public MavenSession newDefaultMavenSession() { + try { + MavenExecutionRequest request = new DefaultMavenExecutionRequest(); + MavenExecutionResult result = new DefaultMavenExecutionResult(); + + // Populates sensible defaults, including repository basedir and remote repos + MavenExecutionRequestPopulator populator = getContainer().lookup(MavenExecutionRequestPopulator.class); + populator.populateDefaults(request); + + // Enables the usage of Java system properties for interpolation and profile activation + request.setSystemProperties(System.getProperties()); + + request.setMakeBehavior(MavenExecutionRequest.REACTOR_MAKE_UPSTREAM); + + // Ensures that the repo session in the maven session has a repo manager and points to the local repo + DefaultMaven maven = (DefaultMaven) getContainer().lookup(Maven.class); + DefaultRepositorySystemSession repoSession = + (DefaultRepositorySystemSession) maven.newRepositorySession(request); + repoSession.setLocalRepositoryManager( + new SimpleLocalRepositoryManagerFactory().newInstance( + repoSession, + new LocalRepository(request.getLocalRepository().getBasedir()) + ) + ); + + // instantiate and seed the session, so it can be injected during initialization + @SuppressWarnings("deprecation") + MavenSession session = new MavenSession(getContainer(), repoSession, request, result); + SessionScope sessionScope = getContainer().lookup(SessionScope.class); + sessionScope.enter(); + sessionScope.seed(MavenSession.class, session); + + return session; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * Overrides super's {@link #newMavenSession(MavenProject)} to delegate to + * the new {@link #newDefaultMavenSession()} introduced in {@link ContainerizeDependenciesMojoTestCase}, + * which sets the defaults that are normally expected by Maven. + */ + @Override + protected MavenSession newMavenSession(MavenProject project) { + MavenSession session = newDefaultMavenSession(); + ArrayList mavenProjects = new ArrayList<>(); + + try { + ProjectBuilder projectBuilder = lookup(ProjectBuilder.class); + + for(File mavenProjectFile: this.mavenProjectFiles) { + mavenProjects.add(projectBuilder.build(mavenProjectFile, session.getProjectBuildingRequest()).getProject()); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + + session.setProjects(mavenProjects); + session.setCurrentProject(project); + + return session; + } + + public void addMavenProjectFile(File mavenProjectFile) { + this.mavenProjectFiles.add(mavenProjectFile); + } + + public void clearMavenProjectFiles() { + this.mavenProjectFiles = new ArrayList<>(); + } + + /** + * Overloads super's {@link #lookupConfiguredMojo(MavenProject, String)} + * to ingest the given {@code pom.xml} {@link File} instead of a {@link MavenProject}. + * Creates and appropriately configures the {@link Mojo} responsible for executing + * the plugin goal as defined within the given {@code pom.xml} {@link File}. + * + * @param pom {@code pom.xml} file defining desired plugin and configuration to test. + * @param goal target plugin goal for which to create the associated {@link Mojo} + * @return + * @throws Exception + */ + public Mojo lookupConfiguredMojo(File pom, String goal) throws Exception { + assertNotNull(pom); + assertTrue(pom.exists()); + + MavenSession session = newDefaultMavenSession(); + ProjectBuildingRequest buildingRequest = session.getProjectBuildingRequest(); + buildingRequest.setResolveDependencies(true); + ProjectBuilder projectBuilder = lookup(ProjectBuilder.class); + + MavenProject project = projectBuilder.build(pom, buildingRequest).getProject(); + ContainerizeDependenciesMojo mojo = lookupConfiguredMojo(project, goal); + return mojo; + } + + + +} diff --git a/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDependenciesSteps.java b/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDependenciesSteps.java new file mode 100644 index 0000000..149c64a --- /dev/null +++ b/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDependenciesSteps.java @@ -0,0 +1,133 @@ +package org.technologybrewery.habushu; + +import io.cucumber.java.After; +import io.cucumber.java.Before; +import io.cucumber.java.en.Given; +import io.cucumber.java.en.Then; +import io.cucumber.java.en.When; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.junit.jupiter.api.Assertions; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ContainerizeDependenciesSteps { + + protected String targetDefaultNoMonorepoDepPath = "target/test-classes/containerize-dependencies/" + + "default-no-monorepo-dep/test-monorepo"; + protected String targetDefaultSingleMonorepoDepPath = "target/test-classes/containerize-dependencies/" + + "default-single-monorepo-dep/test-monorepo"; + protected String mavenProjectPath; + private final String POM_FILE = "pom.xml"; + + private final ContainerizeDependenciesMojoTestCase mojoTestCase = new ContainerizeDependenciesMojoTestCase(); + + private ContainerizeDependenciesMojo mojo; + + @Before("@containerizeDependencies") + public void configureMavenTestSession() throws Exception { + // important for registering Habushu's mojos to AbstractTestCase.mojoDescriptors, + // which ensures that lookupConfiguredMojo will return the configured mojo + mojoTestCase.configurePluginTestHarness(); + } + + @After("@containerizeDependencies") + public void tearDownMavenPluginTestHarness() throws Exception { + mojoTestCase.clearMavenProjectFiles(); + mojoTestCase.tearDownPluginTestHarness(); + } + + @Given("a single Habushu-type dependency") + public void a_single_habushu_type_dependency() throws Exception { + mavenProjectPath = targetDefaultSingleMonorepoDepPath + "/extensions/extensions-monorepo-dep-consuming-application"; + + // enables us to mock a maven build with the --also-make flag + mojoTestCase.addMavenProjectFile(new File(targetDefaultSingleMonorepoDepPath + "/extensions/extensions-python-dep-X/pom.xml")); + mojoTestCase.addMavenProjectFile(new File(targetDefaultSingleMonorepoDepPath + "/foundation/foundation-python-dep-Y/pom.xml")); + + mojo = (ContainerizeDependenciesMojo) mojoTestCase.lookupConfiguredMojo( + new File(mavenProjectPath, POM_FILE), "containerize-dependencies" + ); + mojo.setAnchorSourceDirectory(new File("target/test-classes/containerize-dependencies/default-single-monorepo-dep/test-monorepo").getAbsoluteFile()); + mojo.session.getRequest().setBaseDirectory(new File(targetDefaultSingleMonorepoDepPath)); + + } + + @When("the containerize-dependencies goal is executed") + public void the_containerize_dependencies_goal_is_executed() throws MojoExecutionException, MojoFailureException { + mojo.execute(); + } + + @Then("the sources files of the dependency and transitive Habushu-type dependencies are staged and structured") + public void the_source_files_of_the_dependency_and_transitive_habushu_type_dependencies_are_staged_and_structured() { + assertStaged(mojo.getAnchorOutputDirectory()); + } + + @Given("no Habushu-type dependencies") + public void no_habushu_type_dependencies() throws Exception { + mavenProjectPath = targetDefaultNoMonorepoDepPath + "/no-monorepo-dep-application"; + mojo = (ContainerizeDependenciesMojo) mojoTestCase.lookupConfiguredMojo( + new File(mavenProjectPath, POM_FILE), "containerize-dependencies" + ); + mojo.session.getRequest().setBaseDirectory(new File(targetDefaultNoMonorepoDepPath)); + } + + @Then("no source files are staged in the build directory") + public void no_source_files_are_staged_in_the_build_directory() { + String venvSupportPath = mojo.getSession().getCurrentProject().getBuild().getDirectory() + "/venv-support"; + Assertions.assertTrue(isNonExistentOrEmptyDir(new File(venvSupportPath))); + } + + private boolean isNonExistentOrEmptyDir(File dir) { + // Directory does not exist + if (!dir.exists()) { + return true; + } + + // The path exists but is not a directory + if (!dir.isDirectory()) { + return false; + } + + // Check if the directory is empty + String[] contents = dir.list(); + return contents == null || contents.length == 0; + } + + private void assertStaged(File actual) { + Set actualFiles; + try { + actualFiles = getRelativizedPaths(actual); + } catch (Exception e) { + throw new RuntimeException(); + } + + assertFile(actualFiles, "extensions/extensions-python-dep-X/src/python_dep_x/python_dep_x.py"); + assertFile(actualFiles, "extensions/extensions-python-dep-X/pyproject.toml"); + assertFile(actualFiles, "extensions/extensions-python-dep-X/README.md"); + assertFile(actualFiles, "foundation/foundation-python-dep-Y/src/python_dep_y/python_dep_y.py"); + assertFile(actualFiles, "foundation/foundation-python-dep-Y/pyproject.toml"); + assertFile(actualFiles, "foundation/foundation-python-dep-Y/README.md"); + } + + private static void assertFile(Set actualFiles, String path) { + Assertions.assertTrue(actualFiles.contains(Paths.get(path)), "Could not find: " + path); + } + + private Set getRelativizedPaths(File rootDir) throws IOException { + try (Stream paths = Files.walk(rootDir.toPath())) { + return paths + .filter(Files::isRegularFile) + .map(rootDir.toPath()::relativize) + .collect(Collectors.toSet()); + } + } + +} diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/java-dep-X/pom.xml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/java-dep-X/pom.xml new file mode 100644 index 0000000..52e542f --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/java-dep-X/pom.xml @@ -0,0 +1,13 @@ + + + 4.0.0 + + Java Dependency X + org.test.monorepo + java-dep-X + 1.0.0 + + jar + + \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/java-dep-X/src/main/javaDepX.java b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/java-dep-X/src/main/javaDepX.java new file mode 100644 index 0000000..e69de29 diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/no-monorepo-dep-application/pom.xml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/no-monorepo-dep-application/pom.xml new file mode 100644 index 0000000..4b1256a --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/no-monorepo-dep-application/pom.xml @@ -0,0 +1,31 @@ + + + 4.0.0 + + No Monorepo Dependency Application + org.test.monorepo + no-monorepo-dep-application + 1.0.0 + + pom + + + + + org.technologybrewery.habushu + habushu-maven-plugin + ${project.version} + + + + + + + org.test.monorepo + java-dep-X + ${project.version} + + + + \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/pom.xml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/pom.xml new file mode 100644 index 0000000..2643853 --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + Test Monorepo + org.test.monorepo + test-monorepo + 1.0.0 + + pom + + + java-dep-X + no-monorepo-dep-application + + + \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-monorepo-dep-consuming-application/pom.xml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-monorepo-dep-consuming-application/pom.xml new file mode 100644 index 0000000..c0b8451 --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-monorepo-dep-consuming-application/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + Extensions::Monorepo Dependency-Consuming Application + org.test.monorepo + extensions-monorepo-dep-consuming-application + 1.0.0-SNAPSHOT + + pom + + + + + org.technologybrewery.habushu + habushu-maven-plugin + 2.15.0 + + + + + + + org.technologybrewery.habushu + habushu-maven-plugin + 2.15.0 + + + org.test.monorepo + extensions-python-dep-X + ${project.version} + habushu + + + + \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/README.md b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/README.md new file mode 100644 index 0000000..e69de29 diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/pom.xml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/pom.xml new file mode 100644 index 0000000..6fa6673 --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/pom.xml @@ -0,0 +1,38 @@ + + + 4.0.0 + + Extensions::Python Dependency X + org.test.monorepo + extensions-python-dep-X + 1.0.0-SNAPSHOT + + habushu + + + + + org.technologybrewery.habushu + habushu-maven-plugin + 2.15.0 + true + + + + + + + org.technologybrewery.habushu + habushu-maven-plugin + 2.15.0 + + + org.test.monorepo + foundation-python-dep-Y + ${project.version} + habushu + + + + \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/pyproject.toml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/pyproject.toml new file mode 100644 index 0000000..086c205 --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/pyproject.toml @@ -0,0 +1,21 @@ +[tool.poetry] +name = "extensions-python-dep-X" +version = "1.0.0.dev" +description = "description" +authors = ["author"] +packages = [ + {include = "python_dep_x", from = "src"}, +] + +[tool.poetry.dependencies] +python = ">=3.11.4, <4" + +[tool.poetry.group.dev.dependencies] +black = ">=22.1.0" +behave = ">=1.2.6" +nose = ">=1.3.7" +pylint = "^3.2.3" + +[build-system] +requires = ["poetry-core>=1.7.0"] +build-backend = "poetry.core.masonry.api" \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/src/python_dep_x/python_dep_x.py b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/src/python_dep_x/python_dep_x.py new file mode 100644 index 0000000..e69de29 diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/pom.xml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/pom.xml new file mode 100644 index 0000000..4a4e24b --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + Extensions + org.test.monorepo + extensions + 1.0.0-SNAPSHOT + + pom + + + extensions-monorepo-dep-consuming-application + extensions-python-dep-X + + + \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/README.md b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/README.md new file mode 100644 index 0000000..e69de29 diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/pom.xml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/pom.xml new file mode 100644 index 0000000..a428d4a --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + Foundation::Python Dependency Y + org.test.monorepo + foundation-python-dep-Y + 1.0.0-SNAPSHOT + + habushu + + + + + org.technologybrewery.habushu + habushu-maven-plugin + 2.15.0 + true + + + + + + + org.technologybrewery.habushu + habushu-maven-plugin + 2.15.0 + + + + + + \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/pyproject.toml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/pyproject.toml new file mode 100644 index 0000000..093ba37 --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/pyproject.toml @@ -0,0 +1,23 @@ +[tool.poetry] +name = "extensions-python-dep-Y" +version = "1.0.0.dev" +description = "description" +authors = ["author"] +packages = [ + {include = "python_dep_y", from = "src"}, +] + +[tool.poetry.dependencies] +python = ">=3.11.4, <4" + +[tool.poetry.group.dev.dependencies] +black = ">=22.1.0" +behave = ">=1.2.6" +nose = ">=1.3.7" +pylint = "^3.2.3" + + + +[build-system] +requires = ["poetry-core>=1.7.0"] +build-backend = "poetry.core.masonry.api" \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/src/python_dep_y/python_dep_y.py b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/src/python_dep_y/python_dep_y.py new file mode 100644 index 0000000..fdffa2a --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/src/python_dep_y/python_dep_y.py @@ -0,0 +1 @@ +# placeholder diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/pom.xml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/pom.xml new file mode 100644 index 0000000..c6e39f3 --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/pom.xml @@ -0,0 +1,17 @@ + + + 4.0.0 + + Foundation + org.test.monorepo + foundation + 1.0.0-SNAPSHOT + + pom + + + foundation-python-dep-Y + + + \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/pom.xml b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/pom.xml new file mode 100644 index 0000000..0fb7c36 --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/pom.xml @@ -0,0 +1,18 @@ + + + 4.0.0 + + Test Monorepo + org.test.monorepo + test-monorepo + 1.0.0-SNAPSHOT + + pom + + + extensions + foundation + + + \ No newline at end of file diff --git a/habushu-maven-plugin/src/test/resources/specifications/containerize-dependencies.feature b/habushu-maven-plugin/src/test/resources/specifications/containerize-dependencies.feature new file mode 100644 index 0000000..bc200e7 --- /dev/null +++ b/habushu-maven-plugin/src/test/resources/specifications/containerize-dependencies.feature @@ -0,0 +1,12 @@ +@containerizeDependencies +Feature: Test staging source files of specified dependencies and transitive path-based dependencies + + Scenario: One Habushu-type dependency is specified with the default configuration + Given a single Habushu-type dependency + When the containerize-dependencies goal is executed + Then the sources files of the dependency and transitive Habushu-type dependencies are staged and structured + + Scenario: No Habushu-type dependencies are specified with the default configuration + Given no Habushu-type dependencies + When the containerize-dependencies goal is executed + Then no source files are staged in the build directory \ No newline at end of file