From a873be2920bb8f2c7d470d1f2e37b94d135713af Mon Sep 17 00:00:00 2001 From: Cho-William Date: Mon, 17 Jun 2024 00:35:01 -0400 Subject: [PATCH] #146 copying transitive dependencies functionality for containerize-dependencies goal --- README.md | 46 ++- habushu-maven-plugin/pom.xml | 18 ++ .../habushu/CacheWheelsMojo.java | 4 + .../habushu/CleanHabushuMojo.java | 33 +-- .../habushu/ContainerizeDepsMojo.java | 269 ++++++++++++++++++ .../habushu/PyenvAndPoetrySetup.java | 2 +- .../habushu/RetrieveWheelsMojo.java | 4 + .../habushu/util/HabushuUtil.java | 37 +++ .../resources/META-INF/plexus/components.xml | 4 - .../ContainerizeDepsMojoTestWrapper.java | 147 ++++++++++ .../habushu/ContainerizeDepsSteps.java | 135 +++++++++ .../test-monorepo/java-dep-X/pom.xml | 13 + .../java-dep-X/src/main/javaDepX.java | 0 .../no-monorepo-dep-application/pom.xml | 31 ++ .../test-monorepo/pom.xml | 18 ++ .../pom.xml | 38 +++ .../extensions-python-dep-X/README.md | 0 .../extensions-python-dep-X/pom.xml | 38 +++ .../extensions-python-dep-X/pyproject.toml | 21 ++ .../src/python_dep_x/python_dep_x.py | 0 .../test-monorepo/extensions/pom.xml | 18 ++ .../foundation-python-dep-Y/README.md | 0 .../foundation-python-dep-Y/pom.xml | 34 +++ .../foundation-python-dep-Y/pyproject.toml | 23 ++ .../src/python_dep_y/python_dep_y.py | 1 + .../test-monorepo/foundation/pom.xml | 17 ++ .../test-monorepo/pom.xml | 18 ++ .../containerize-dependencies.feature | 12 + 28 files changed, 943 insertions(+), 38 deletions(-) create mode 100644 habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/ContainerizeDepsMojo.java create mode 100644 habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDepsMojoTestWrapper.java create mode 100644 habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDepsSteps.java create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/java-dep-X/pom.xml create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/java-dep-X/src/main/javaDepX.java create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/no-monorepo-dep-application/pom.xml create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-no-monorepo-dep/test-monorepo/pom.xml create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-monorepo-dep-consuming-application/pom.xml create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/README.md create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/pom.xml create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/extensions-python-dep-X/pyproject.toml create mode 100644 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 create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/extensions/pom.xml create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/README.md create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/pom.xml create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/foundation-python-dep-Y/pyproject.toml create mode 100644 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 create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/foundation/pom.xml create mode 100644 habushu-maven-plugin/src/test/resources/containerize-dependencies/default-single-monorepo-dep/test-monorepo/pom.xml create mode 100644 habushu-maven-plugin/src/test/resources/specifications/containerize-dependencies.feature diff --git a/README.md b/README.md index d370fec..3e47c68 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,43 @@ 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 a single `habushu` dependency specified the project's `pom.xml`, including all transitive habushu-packaged dependencies. After collecting the set of necessary dependencies, Habushu will copy the project files to the build directory under `venv-support`, while preserving the original structure of the dependency modules to ensure that any path-based dependencies can be leveraged as-is. This directory can then be copied onto a Docker container and used to create a virtual environment capable of running the target Habushu project. + +```xml + + org.technologybrewery.habushu + habushu-maven-plugin + + ... + + + + 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 dependencie 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 +719,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 +915,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..a69e7b3 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 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/CleanHabushuMojo.java b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/CleanHabushuMojo.java index 2997654..4d7e835 100644 --- a/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/CleanHabushuMojo.java +++ b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/CleanHabushuMojo.java @@ -14,7 +14,6 @@ import java.io.File; import java.lang.reflect.Field; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; /** @@ -122,8 +121,10 @@ private void clean() throws MojoExecutionException { List filesetsToDelete = new ArrayList<>(); boolean removeVenvManually = false; - String virtualEnvFullPath = findCurrentVirtualEnvironmentFullPath(); - virtualEnvFullPath = getCleanVirtualEnvironmentPath(virtualEnvFullPath); + String virtualEnvFullPath = HabushuUtil.findCurrentVirtualEnvironmentFullPath( + pythonVersion, usePyenv, patchInstallScript, + workingDirectory, rewriteLocalPathDepsInArchives, getLog()); + virtualEnvFullPath = HabushuUtil.getCleanVirtualEnvironmentPath(virtualEnvFullPath); String inVirtualEnvironmentPath = HabushuUtil.getInProjectVirtualEnvironmentPath(this.workingDirectory); File venv = new File(inVirtualEnvironmentPath); @@ -188,33 +189,7 @@ private void clean() throws MojoExecutionException { super.execute(); } - /** - * Removes (Activated) from path in 1.3.x and higher versions. - * - * @param virtualEnvFullPath path to clean - * @return cleaned path - */ - private static String getCleanVirtualEnvironmentPath(String virtualEnvFullPath) { - return StringUtils.replace(virtualEnvFullPath, " (Activated)", StringUtils.EMPTY); - - } - private String findCurrentVirtualEnvironmentFullPath() throws MojoExecutionException { - String virtualEnvFullPath = null; - PyenvAndPoetrySetup configureTools = new PyenvAndPoetrySetup(pythonVersion, usePyenv, - patchInstallScript, workingDirectory, rewriteLocalPathDepsInArchives, getLog()); - configureTools.execute(); - - try { - PoetryCommandHelper poetryHelper = new PoetryCommandHelper(this.workingDirectory); - virtualEnvFullPath = poetryHelper.execute(Arrays.asList("env", "list", "--full-path")); - } catch (RuntimeException e) { - getLog().debug("Could not retrieve Poetry-managed virtual environment path - it likely does not exist", - e); - } - - return virtualEnvFullPath; - } /** * Creates a new {@link Fileset} that may be used to identify a set of files diff --git a/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/ContainerizeDepsMojo.java b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/ContainerizeDepsMojo.java new file mode 100644 index 0000000..218c905 --- /dev/null +++ b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/ContainerizeDepsMojo.java @@ -0,0 +1,269 @@ +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.plugins.annotations.Parameter; +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 org.technologybrewery.habushu.util.HabushuUtil; + +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.*; +import java.util.stream.Collectors; + +/** + * Stages the source files of a monorepo dependency + * to the target directory along with the source files of + * any transitive path-based dependencies. + */ +@Mojo(name = "containerize-dependencies", defaultPhase = LifecyclePhase.PACKAGE) +public class ContainerizeDepsMojo extends AbstractHabushuMojo { + + private static final Logger logger = LoggerFactory.getLogger(ContainerizeDepsMojo.class); + + @Component + protected MavenSession session; + + /** + * The desired version of Python to use. + */ + @Parameter(defaultValue = PyenvAndPoetrySetup.PYTHON_DEFAULT_VERSION_REQUIREMENT, property = "habushu.pythonVersion") + protected String pythonVersion; + + /** + * Should Habushu use pyenv to manage the utilized version of Python? + */ + @Parameter(defaultValue = "true", property = "habushu.usePyenv") + protected boolean usePyenv; + + /** + * Indicates whether Habushu should leverage the + * {@code poetry-monorepo-dependency-plugin} to rewrite any local path + * dependencies (to other Poetry projects) as versioned packaged dependencies in + * generated wheel/sdist archives. If {@code true}, Habushu will replace + * invocations of Poetry's {@code build} and {@code publish} commands in the + * {@link BuildDeploymentArtifactsMojo} and {@link PublishToPyPiRepoMojo} with + * the extensions of those commands exposed by the + * {@code poetry monorepo-dependency-plugin}, which are + * {@code build-rewrite-path-deps} and {@code publish-rewrite-path-deps} + * respectively. + *

+ * Typically, this flag will only be {@code true} when deploying/releasing + * Habushu modules within a CI environment that are part of a monorepo project + * structure which multiple Poetry projects depend on one another. + */ + @Parameter(defaultValue = "false", property = "habushu.rewriteLocalPathDepsInArchives") + protected boolean rewriteLocalPathDepsInArchives; + + /** + * File specifying the location of a generated shell script that will attempt to + * install the specified version of Python using "pyenv install --patch" with a + * patch that attempts to resolve the expected compilation error. + */ + @Parameter(defaultValue = "pyenv-patch-install-python-version.sh", readonly = true) + private String patchInstallScriptRelativeToBuildDirectory; + + /** + * Working directory relative to the basedir - typically working direcotry and basedir are the same. + */ + @Parameter(readonly = true, required = true) + protected String workingDirectoryRelativeToBasedir; + + /** + * Expected subdirectory of the monorepo dependency's basedir + * in which Poetry places generated source and wheel archive distributions. + */ + @Parameter(defaultValue = "dist", readonly = true, required = true) + protected String distDirRelativeToBasedir; + + /** + * Expected subdirectory of the monorepo dependency's basedir + * in which Maven places build-time artifacts. Should NOT include dist items. + */ + @Parameter(defaultValue = "target", readonly = true, required = true) + protected String targetDirRelativeToBasedir; + + /** + * Location of where containerization files will be placed. + */ + @Parameter(defaultValue = "${project.build.directory}/containerize-support", readonly = true, required = true) + protected File containerizeSupportDirectory; + + /** + * Upstream directory that houses all necessary monorepo dependencies. + * Monorepo dependency source files will be copied from here. + */ + @Parameter(readonly = true, required = true) + protected File anchorSourceDirectory; + + private File anchorOutputDirectory; + + protected final String HABUSHU = "habushu"; + protected final String FORWARD_SLASH = "/"; + protected final String GLOB_RECURSIVE_ALL = "/**"; + + /** + * 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()); + } + + if (this.workingDirectoryRelativeToBasedir == null) { + this.workingDirectoryRelativeToBasedir = ""; + } + + Set habushuProjects = getHabushuProjects(); + try { + copySourceCode(habushuProjects); + } catch (IOException e) { + throw new HabushuException(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 + * @throws MojoExecutionException + */ + protected void copySourceCode(Set habushuProjects) throws IOException, MojoExecutionException { + this.anchorOutputDirectory = new File(containerizeSupportDirectory + + FORWARD_SLASH + this.anchorSourceDirectory.getName()); + Path srcRoot = this.anchorSourceDirectory.toPath(); + Path destRoot = this.anchorOutputDirectory.toPath(); + + Map dependencyFileSets = new HashMap<>(); + for (MavenProject project : habushuProjects) { + Path projectPath = getWorkingDirectoryPath(project); + Path relativeProjectPath = srcRoot.relativize(projectPath); + FileSet fileSet = getDefaultFileSet(project); + fileSet.setDirectory(projectPath.toString()); + dependencyFileSets.put(relativeProjectPath, fileSet); + } + + FileSetManager fileSetManager = new FileSetManager(); + for (Path project : dependencyFileSets.keySet()) { + FileSet fileSet = dependencyFileSets.get(project); + logger.info("Staging {} monorepo dependency 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 Path getWorkingDirectoryPath(MavenProject project) { + return project.getBasedir().toPath().resolve(workingDirectoryRelativeToBasedir); + } + + private FileSet getDefaultFileSet(MavenProject project) throws MojoExecutionException { + FileSet fileSet = new FileSet(); + fileSet.addExclude(distDirRelativeToBasedir + GLOB_RECURSIVE_ALL); + fileSet.addExclude(targetDirRelativeToBasedir + GLOB_RECURSIVE_ALL); + + // find the virtual environment path for the given Habushu-packaged project + String virtualEnvironmentPath = HabushuUtil.findCurrentVirtualEnvironmentFullPath( + pythonVersion, + usePyenv, + new File(project.getBuild().getDirectory() + + FORWARD_SLASH + patchInstallScriptRelativeToBuildDirectory), + new File(project.getBasedir() + + FORWARD_SLASH + workingDirectoryRelativeToBasedir), + rewriteLocalPathDepsInArchives, + getLog() + ); + virtualEnvironmentPath = HabushuUtil.getCleanVirtualEnvironmentPath(virtualEnvironmentPath); + + // if a valid virtual environment was found, relativize and add to the fileSet for exclusions + if (virtualEnvironmentPath != null && !virtualEnvironmentPath.isEmpty() + && new File(virtualEnvironmentPath).isDirectory()) { + Path venvDirRelativeToBasedir = getWorkingDirectoryPath(project) + .relativize(Paths.get(virtualEnvironmentPath)); + fileSet.addExclude(venvDirRelativeToBasedir + GLOB_RECURSIVE_ALL); + } + + 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() { + Set habushuProjects = new HashSet<>(); + Set directHabushuDeps = session.getCurrentProject().getDependencies().stream() + .filter(d -> HABUSHU.equals(d.getType())) + .collect(Collectors.toSet()); + // TODO: modify this exception throw, once support for + // more than one direct monorepo dep specification is implemented + if (directHabushuDeps.size() > 1) { + throw new HabushuException("More than one habushu-type dependency was found." + + "Only one habushu-type dependency should be specified."); + } + + collectHabushuDependenciesAsProjects(project, habushuProjects); + return habushuProjects; + } + + /** + * Collects the projects with 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 + */ + protected void collectHabushuDependenciesAsProjects(MavenProject currentProject, Set habushuProjects) { + Set habushuDeps = currentProject.getDependencies().stream() + .filter(d -> HABUSHU.equals(d.getType())) + .map(ContainerizeDepsMojo::toGav) + .collect(Collectors.toSet()); + for (MavenProject project : getSession().getProjects()) { + if (habushuDeps.contains(toGav(project))) { + logger.info("Found project {} as habushu-type dependency.", project); + habushuProjects.add(project); + collectHabushuDependenciesAsProjects(project, habushuProjects); + } + } + } + + protected static String toGav(Dependency dependency) { + return dependency.getGroupId() + ":" + dependency.getArtifactId() + ":" + dependency.getVersion(); + } + protected 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/PyenvAndPoetrySetup.java b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/PyenvAndPoetrySetup.java index 9c72a11..3a84f05 100644 --- a/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/PyenvAndPoetrySetup.java +++ b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/PyenvAndPoetrySetup.java @@ -26,7 +26,7 @@ *

  • Required Poetry plugins (currently only {@code poetry-monorepo-dependency-plugin})
  • * */ -class PyenvAndPoetrySetup { +public class PyenvAndPoetrySetup { /** * Specifies the semver compliant requirement for the default version of Python that 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/java/org/technologybrewery/habushu/util/HabushuUtil.java b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/util/HabushuUtil.java index be14d38..f71c553 100644 --- a/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/util/HabushuUtil.java +++ b/habushu-maven-plugin/src/main/java/org/technologybrewery/habushu/util/HabushuUtil.java @@ -1,9 +1,14 @@ package org.technologybrewery.habushu.util; import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.Log; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.technologybrewery.habushu.HabushuException; +import org.technologybrewery.habushu.PyenvAndPoetrySetup; +import org.technologybrewery.habushu.exec.PoetryCommandHelper; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -11,6 +16,7 @@ import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; +import java.util.Arrays; /** * Contains utility functionality for Habushu, including bash script execution @@ -167,4 +173,35 @@ public static void copyFile(String sourceFilePath, String destinationFilePath) { public static String getInProjectVirtualEnvironmentPath(File workingDirectory) { return workingDirectory.getAbsolutePath() + "/.venv"; } + + + public static String findCurrentVirtualEnvironmentFullPath(String pythonVersion, boolean usePyenv, + File patchInstallScript, File workingDirectory, boolean rewriteLocalPathDepsInArchives, Log log) + throws MojoExecutionException { + String virtualEnvFullPath = null; + PyenvAndPoetrySetup configureTools = new PyenvAndPoetrySetup(pythonVersion, usePyenv, + patchInstallScript, workingDirectory, rewriteLocalPathDepsInArchives, log); + configureTools.execute(); + + try { + PoetryCommandHelper poetryHelper = new PoetryCommandHelper(workingDirectory); + virtualEnvFullPath = poetryHelper.execute(Arrays.asList("env", "list", "--full-path")); + } catch (RuntimeException e) { + log.debug("Could not retrieve Poetry-managed virtual environment path - it likely does not exist", + e); + } + + return virtualEnvFullPath; + } + + /** + * Removes (Activated) from path in 1.3.x and higher versions. + * + * @param virtualEnvFullPath path to clean + * @return cleaned path + */ + public static String getCleanVirtualEnvironmentPath(String virtualEnvFullPath) { + return StringUtils.replace(virtualEnvFullPath, " (Activated)", StringUtils.EMPTY); + + } } \ No newline at end of file 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/ContainerizeDepsMojoTestWrapper.java b/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDepsMojoTestWrapper.java new file mode 100644 index 0000000..bb7c1e2 --- /dev/null +++ b/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDepsMojoTestWrapper.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 ContainerizeDepsMojoTestWrapper extends AbstractMojoTestCase { + + private static final Logger logger = LoggerFactory.getLogger(ContainerizeDepsMojoTestWrapper.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 ContainerizeDepsMojoTestWrapper}, + * 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(); + ContainerizeDepsMojo mojo = lookupConfiguredMojo(project, goal); + return mojo; + } + + + +} diff --git a/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDepsSteps.java b/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDepsSteps.java new file mode 100644 index 0000000..5a006ed --- /dev/null +++ b/habushu-maven-plugin/src/test/java/org/technologybrewery/habushu/ContainerizeDepsSteps.java @@ -0,0 +1,135 @@ +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 ContainerizeDepsSteps { + + 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 ContainerizeDepsMojoTestWrapper mojoTestCase = new ContainerizeDepsMojoTestWrapper(); + + private ContainerizeDepsMojo 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 dependency with packaging type habushu") + public void a_single_dependency_with_packaging_type_habushu() 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 = (ContainerizeDepsMojo) 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 source files of the dependency and transitive Habushu-type dependencies are staged for containerization") + public void + the_source_files_of_the_dependency_and_transitive_habushu_type_dependencies_are_staged_for_containerization() { + assertStaged(mojo.getAnchorOutputDirectory().toPath()); + } + + @Given("no Habushu-type dependencies") + public void no_habushu_type_dependencies() throws Exception { + mavenProjectPath = targetDefaultNoMonorepoDepPath + "/no-monorepo-dep-application"; + mojo = (ContainerizeDepsMojo) 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 containerizeSupportPath = mojo.getSession().getCurrentProject().getBuild().getDirectory() + + "/containerize-support"; + Assertions.assertTrue(isNonExistentOrEmptyDir(new File(containerizeSupportPath))); + } + + 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(Path 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(Path rootDir) throws IOException { + try (Stream paths = Files.walk(rootDir)) { + return paths + .filter(Files::isRegularFile) + .map(rootDir::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..5e0c8d3 --- /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,38 @@ + + + 4.0.0 + + Extensions::Monorepo Dependency-Consuming Application + org.test.monorepo + extensions-monorepo-dep-consuming-application + 1.0.0-SNAPSHOT + + pom + + + ${project.basedir}/target + + + 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..1046faa --- /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 dependency with packaging type habushu + When the containerize-dependencies goal is executed + Then the source files of the dependency and transitive Habushu-type dependencies are staged for containerization + + 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