diff --git a/README.adoc b/README.adoc index 306b2ab5..8703628e 100644 --- a/README.adoc +++ b/README.adoc @@ -37,6 +37,9 @@ The **<> can be defined globally or at the folder This plugin allows transitioning smoothly from the legacy https://plugins.jenkins.io/maven-plugin/[Maven Integration] job type by allowing to reuse **<>** and by proposing the **<>**. + +Please note **per default some features will not be available** and you will have to change/configure a database storage which suits your environment. + toc::[] [#installation] @@ -46,8 +49,8 @@ The plugin can be found under the name `Pipeline Maven Integration Plugin` in th **For tests purposes only**, pre-releases (beta) versions are available in the https://updates.jenkins.io/#experimental-plugin-site[Experimental Plugin Site] and development versions (incremental releases) are archived on every successful build on https://ci.jenkins.io/job/Plugins/job/pipeline-maven-plugin/[our CI environment]. -CAUTION: **If you use the feature <> it is critical to <>** instead of the default embedded H2 instance. -**If you don't do it, it might degrade your environment stability** (The H2 database is running in your instance JVM and could request too many resources). +CAUTION: **If you want to use the feature <> it is critical to <>** as H2 is not preconfigured by default any more. +**Using H2 might degrade your environment stability** (The H2 database is running in your instance JVM and could request too many resources). [#changelog] == Changelog @@ -460,8 +463,8 @@ Trigger downstream pipeline that depend on Maven artifact generated by upstream * The downstream pipeline must have selected the build trigger `Build whenever a SNAPSHOT dependency is built` ** The build trigger can be defined at the pipeline level (`Build Triggers`), at the multibranch pipeline level (`Scan Repository Triggers`) or at the GitHub Organization / Bitbucket Project level (`Scan Organizations Triggers`) * You have to manually trigger once the upstream pipeline, and the downstream pipeline so that the link between the pipelines based on the SNAPSHOT dependency is established -* The dependency graph is, for the moment, exclusively stored in an H2 embedded database (`$JENKINS_HOME/jenkins-jobs/jenkins-jobs.mv.db`). -Support for an external H2 database and then for alternate databases (PostgreSQL) is on the roadmap (see https://github.com/jenkinsci/pipeline-maven-plugin/blob/pipeline-maven-3.0.0-beta-1/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginH2Dao.java[PipelineMavenPluginH2Dao.java]) +* The dependency graph is, for the moment, optionally stored in an H2 embedded database (`$JENKINS_HOME/jenkins-jobs/jenkins-jobs.mv.db`). And there is support + for PostgreSQL and MySql as well (see details below) ==== image:docs/images/trigger-downstream-1.png[] @@ -501,6 +504,22 @@ We want to quickly add reporters for CheckStyle, Jacoco... [#db-setup] == Database Setup +NOTE: Available since version 1332.xxxxxxxx.xxx + +To use a database you must first install the `Pipeline Maven Plugin Database` + +image::docs/images/pipeline-maven-plugin-database.png[] + +Have a look at the Tools configuration: + +image::docs/images/dao-choice.png[] + +The make a choice in available DAOs options: + +image::docs/images/dao-list-database.png[] + +For Configuration as Code users, these are the field to add into their yaml file `daoClass` and `jdbcUrl` + [#db-setup-mysql] === Using a MySQL Database diff --git a/docs/images/dao-choice.png b/docs/images/dao-choice.png new file mode 100644 index 00000000..ff6eeedb Binary files /dev/null and b/docs/images/dao-choice.png differ diff --git a/docs/images/dao-list-database.png b/docs/images/dao-list-database.png new file mode 100644 index 00000000..d2a99986 Binary files /dev/null and b/docs/images/dao-list-database.png differ diff --git a/docs/images/pipeline-maven-plugin-database.png b/docs/images/pipeline-maven-plugin-database.png new file mode 100644 index 00000000..64ed4b5c Binary files /dev/null and b/docs/images/pipeline-maven-plugin-database.png differ diff --git a/jenkins-plugin/pom.xml b/jenkins-plugin/pom.xml index 55794d87..e3edbec2 100644 --- a/jenkins-plugin/pom.xml +++ b/jenkins-plugin/pom.xml @@ -41,59 +41,34 @@ https://github.com/jenkinsci/pipeline-maven-plugin/releases + 1333 - - - - io.jenkins.tools.bom - bom-2.361.x - ${jenkins-tools-bom.version} - pom - import - - - - - - com.google.code.gson - gson - ${gson.version} - - - org.codehaus.plexus - plexus-utils - ${plexus-utils.version} - - - org.fusesource.jansi - jansi - ${jansi.version} - - - - com.zaxxer - HikariCP - ${hikaricp.version} - - - org.slf4j - slf4j-api - - + org.jenkins-ci.plugins + pipeline-maven-api + + + + + org.jenkins-ci.plugins + pipeline-maven-database + ${project.version} + test io.jenkins.plugins h2-api ${jenkins-plugin-h2.version} + test io.jenkins.plugins mysql-api ${jenkins-plugin-mysql.version} - true + test com.google.protobuf @@ -105,7 +80,7 @@ io.jenkins.plugins postgresql-api ${jenkins-plugin-postgresql.version} - true + test org.jenkins-ci.main @@ -334,10 +309,8 @@ true - ch.qos.logback - logback-classic - ${logback.version} - test + org.slf4j + slf4j-simple @@ -455,25 +428,21 @@ org.testcontainers junit-jupiter - ${testcontainers.version} test org.testcontainers mysql - ${testcontainers.version} test org.testcontainers postgresql - ${testcontainers.version} test org.testcontainers testcontainers - ${testcontainers.version} test diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfig.java b/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfig.java index 62f8882b..a3ebed0c 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfig.java +++ b/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfig.java @@ -28,15 +28,13 @@ import com.cloudbees.plugins.credentials.CredentialsProvider; import com.cloudbees.plugins.credentials.common.StandardListBoxModel; import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials; -import com.zaxxer.hikari.HikariConfig; -import com.zaxxer.hikari.HikariDataSource; import hudson.Extension; +import hudson.ExtensionList; import hudson.init.Terminator; import hudson.model.Result; import hudson.security.ACL; import hudson.util.FormValidation; import hudson.util.ListBoxModel; -import hudson.util.Secret; import jenkins.model.GlobalConfiguration; import jenkins.model.GlobalConfigurationCategory; import jenkins.model.Jenkins; @@ -44,13 +42,8 @@ import net.sf.json.JSONObject; import org.apache.commons.lang.StringUtils; import org.jenkinsci.Symbol; -import org.jenkinsci.plugins.pipeline.maven.dao.CustomTypePipelineMavenPluginDaoDecorator; -import org.jenkinsci.plugins.pipeline.maven.dao.MonitoringPipelineMavenPluginDaoDecorator; import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginDao; -import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginH2Dao; -import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginMySqlDao; import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginNullDao; -import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginPostgreSqlDao; import org.jenkinsci.plugins.pipeline.maven.service.PipelineTriggerService; import org.kohsuke.stapler.DataBoundConstructor; import org.kohsuke.stapler.DataBoundSetter; @@ -61,21 +54,12 @@ import edu.umd.cs.findbugs.annotations.CheckForNull; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; -import javax.sql.DataSource; -import java.io.File; import java.io.IOException; -import java.io.StringReader; -import java.sql.Connection; -import java.sql.DatabaseMetaData; -import java.sql.DriverManager; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Objects; -import java.util.Properties; +import java.util.Optional; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; @@ -105,11 +89,33 @@ public class GlobalPipelineMavenConfig extends GlobalConfiguration { private String jdbcCredentialsId; private String properties; + private String daoClass; + @DataBoundConstructor public GlobalPipelineMavenConfig() { load(); } + public List getPipelineMavenPluginDaos() { + return ExtensionList.lookup(PipelineMavenPluginDao.class); + } + + public String getDaoClass() { + return daoClass; + } + + @DataBoundSetter + public void setDaoClass(String daoClass) { + this.daoClass = daoClass; + } + + private Optional findDaoFromExtension(String daoClass) { + return ExtensionList.lookup(PipelineMavenPluginDao.class) + .stream() + .filter(pipelineMavenPluginDao -> StringUtils.equals(pipelineMavenPluginDao.getClass().getName(), daoClass)) + .findFirst(); + } + @Override public ToolConfigurationCategory getCategory() { return GlobalConfigurationCategory.get(ToolConfigurationCategory.class); @@ -221,6 +227,10 @@ public synchronized void setJdbcCredentialsId(String jdbcCredentialsId) { @Override public boolean configure(StaplerRequest req, JSONObject json) throws FormException { + if(!StringUtils.equals(json.getString("daoClass"), daoClass)) { + closeDatasource(); + this.dao = null; + } req.bindJSON(this, json); // stapler oddity, empty lists coming from the HTTP request are not set on bean by "req.bindJSON(this, json)" this.publisherOptions = req.bindJSONToList(MavenPublisher.class, json.get("publisherOptions")); @@ -228,113 +238,33 @@ public boolean configure(StaplerRequest req, JSONObject json) throws FormExcepti return true; } - boolean isDaoInitialized() { - return dao != null; + public String getDaoPrettyString() { + return dao != null ? dao.toPrettyString() : "Dao Not Ready yet"; } @NonNull public synchronized PipelineMavenPluginDao getDao() { + if (dao != null) { + return dao; + } Jenkins j = Jenkins.getInstanceOrNull(); if (j == null) { throw new IllegalStateException("Request to get DAO whilst Jenkins is shutting down or starting up"); } else if (j.isTerminating()) { throw new IllegalStateException("Request to get DAO whilst Jenkins is terminating"); } - if (dao == null) { - try { - String jdbcUrl, jdbcUserName, jdbcPassword; - if (StringUtils.isBlank(this.jdbcUrl)) { - // default embedded H2 database - File databaseRootDir = new File(j.getRootDir(), "jenkins-jobs"); - if (!databaseRootDir.exists()) { - boolean created = databaseRootDir.mkdirs(); - if (!created) { - throw new IllegalStateException("Failure to create database root dir " + databaseRootDir); - } - } - jdbcUrl = "jdbc:h2:file:" + new File(databaseRootDir, "jenkins-jobs").getAbsolutePath() + ";" + - "AUTO_SERVER=TRUE;MULTI_THREADED=1;QUERY_CACHE_SIZE=25;JMX=TRUE"; - jdbcUserName = "sa"; - jdbcPassword = "sa"; - } else { - jdbcUrl = this.jdbcUrl; - if (this.jdbcCredentialsId == null) - throw new IllegalStateException("No credentials defined for JDBC URL '" + jdbcUrl + "'"); - - UsernamePasswordCredentials jdbcCredentials = (UsernamePasswordCredentials) CredentialsMatchers.firstOrNull( - CredentialsProvider.lookupCredentials(UsernamePasswordCredentials.class, j, - ACL.SYSTEM, Collections.EMPTY_LIST), - CredentialsMatchers.withId(this.jdbcCredentialsId)); - if (jdbcCredentials == null) { - throw new IllegalStateException("Credentials '" + jdbcCredentialsId + "' defined for JDBC URL '" + jdbcUrl + "' NOT found"); - } - jdbcUserName = jdbcCredentials.getUsername(); - jdbcPassword = Secret.toString(jdbcCredentials.getPassword()); - } - - HikariConfig dsConfig = createHikariConfig(properties, jdbcUrl, jdbcUserName, jdbcPassword); - dsConfig.setAutoCommit(false); - - // TODO cleanup this quick fix for JENKINS-54587, we should have a better solution with the JDBC driver loaded by the DAO itself - try { - DriverManager.getDriver(jdbcUrl); - } catch (SQLException e) { - if ("08001".equals(e.getSQLState()) && 0 == e.getErrorCode()) { - // if it's a "No suitable driver" exception, we try to load the jdbc driver and retry - if (jdbcUrl.startsWith("jdbc:h2:")) { - try { - Class.forName("org.h2.Driver"); - } catch (ClassNotFoundException cnfe) { - throw new IllegalStateException("H2 driver should be bundled with this plugin"); - } - } else if (jdbcUrl.startsWith("jdbc:mysql:")) { - try { - Class.forName("com.mysql.cj.jdbc.Driver"); - } catch (ClassNotFoundException cnfe) { - throw new RuntimeException("MySql driver 'com.mysql.cj.jdbc.Driver' not found. Please install the 'MySQL Database Plugin' to install the MySql driver"); - } - } else if (jdbcUrl.startsWith("jdbc:postgresql:")) { - try { - Class.forName("org.postgresql.Driver"); - } catch (ClassNotFoundException cnfe) { - throw new RuntimeException("PostgreSQL driver 'org.postgresql.Driver' not found. Please install the 'PostgreSQL Database Plugin' to install the PostgreSQL driver"); - } - } else { - throw new IllegalArgumentException("Unsupported database type in JDBC URL " + jdbcUrl); - } - DriverManager.getDriver(jdbcUrl); - } else { - throw e; - } - } - - LOGGER.log(Level.INFO, "Connect to database {0} with username {1}", new Object[]{jdbcUrl, jdbcUserName}); - DataSource ds = new HikariDataSource(dsConfig); - - Class daoClass; - if (jdbcUrl.startsWith("jdbc:h2:")) { - daoClass = PipelineMavenPluginH2Dao.class; - } else if (jdbcUrl.startsWith("jdbc:mysql:")) { - daoClass = PipelineMavenPluginMySqlDao.class; - } else if (jdbcUrl.startsWith("jdbc:postgresql:")) { - daoClass = PipelineMavenPluginPostgreSqlDao.class; - } else { - throw new IllegalArgumentException("Unsupported database type in JDBC URL " + jdbcUrl); - } - try { - dao = new MonitoringPipelineMavenPluginDaoDecorator(new CustomTypePipelineMavenPluginDaoDecorator(daoClass.getConstructor(DataSource.class).newInstance(ds))); - } catch (Exception e) { - throw new SQLException( - "Exception connecting to '" + this.jdbcUrl + "' with credentials '" + this.jdbcCredentialsId + "' (" + - jdbcUserName + "/***) and DAO " + daoClass.getSimpleName(), e); - } - - - } catch (RuntimeException | SQLException e) { - LOGGER.log(Level.WARNING, "Exception creating database dao, skip", e); - dao = new PipelineMavenPluginNullDao(); - } + Optional optionalPipelineMavenPluginDao = findDaoFromExtension(getDaoClass()); + if (optionalPipelineMavenPluginDao.isPresent()) { + PipelineMavenPluginDao.Builder.Config config = new PipelineMavenPluginDao.Builder.Config() + .credentialsId(jdbcCredentialsId) + .jdbcUrl(jdbcUrl) + .properties(properties); + this.dao = optionalPipelineMavenPluginDao.get().getBuilder().build(config); + } else { + LOGGER.info("cannot configure any dao so use the default null values one"); + this.dao = new PipelineMavenPluginNullDao(); } + return dao; } @@ -386,210 +316,27 @@ public ListBoxModel doFillJdbcCredentialsIdItems() { public FormValidation doValidateJdbcConnection( @QueryParameter String jdbcUrl, @QueryParameter String properties, - @QueryParameter String jdbcCredentialsId) { + @QueryParameter String jdbcCredentialsId, + @QueryParameter String daoClass) { Jenkins.get().checkPermission(Jenkins.ADMINISTER); - if (StringUtils.isBlank(jdbcUrl)) { + Optional optionalPipelineMavenPluginDao = findDaoFromExtension(daoClass); + if(optionalPipelineMavenPluginDao.isEmpty()) { return FormValidation.ok("OK"); } - String driverClass = null; - try { - if (StringUtils.isBlank(jdbcUrl)) { - driverClass = "org.h2.Driver"; - } else if (jdbcUrl.startsWith("jdbc:h2")) { - driverClass = "org.h2.Driver"; - } else if (jdbcUrl.startsWith("jdbc:mysql")) { - driverClass = "com.mysql.cj.jdbc.Driver"; - } else if (jdbcUrl.startsWith("jdbc:postgresql:")) { - driverClass = "org.postgresql.Driver"; - } else { - return FormValidation.error("Unsupported database specified in JDBC url '" + jdbcUrl + "'"); - } - try { - Class.forName(driverClass); - } catch (ClassNotFoundException e) { - if ("com.mysql.cj.jdbc.Driver".equals(driverClass)) { - return FormValidation.error(e, "MySQL JDBC driver '" + driverClass + "' not found, please install the Jenkins 'MySQL API Plugin'" + jdbcUrl); - } else if ("org.postgresql.Driver".equals(driverClass)) { - return FormValidation.error(e, "PostgreSQL JDBC driver '" + driverClass + "' not found, please install the Jenkins 'PostgreSQL API Plugin'" + jdbcUrl); - } else { - throw e; - } - } - - String jdbcUserName, jdbcPassword; - if (StringUtils.isEmpty(jdbcCredentialsId)) { - if (StringUtils.isBlank(jdbcUrl)) { - // embedded database, assume OK - return FormValidation.ok("OK"); - } else { - return FormValidation.error("No credentials specified for JDBC url '" + jdbcUrl + "'"); - } - } else { - UsernamePasswordCredentials jdbcCredentials = (UsernamePasswordCredentials) CredentialsMatchers.firstOrNull( - CredentialsProvider.lookupCredentials(UsernamePasswordCredentials.class, Jenkins.get(), - ACL.SYSTEM, Collections.EMPTY_LIST), - CredentialsMatchers.withId(jdbcCredentialsId)); - if (jdbcCredentials == null) { - return FormValidation.error("Credentials '" + jdbcCredentialsId + "' defined for JDBC URL '" + jdbcUrl + "' not found"); - } - jdbcUserName = jdbcCredentials.getUsername(); - jdbcPassword = Secret.toString(jdbcCredentials.getPassword()); - } - - HikariConfig dsConfig = createHikariConfig(properties, jdbcUrl, jdbcUserName, jdbcPassword); - - try (HikariDataSource ds = new HikariDataSource(dsConfig)) { - try (Connection cnn = ds.getConnection()) { - DatabaseMetaData metaData = cnn.getMetaData(); - // getDatabaseProductVersion(): - // * MySQL: "8.0.13" - // * Amazon Aurora: "5.6.10" - // * MariaDB: "5.5.5-10.2.20-MariaDB", "5.5.5-10.3.11-MariaDB-1:10.3.11+maria~bionic" - String databaseVersionDescription = metaData.getDatabaseProductName() + " " + metaData.getDatabaseProductVersion(); - String databaseRequirement = "MySQL Server version 5.7+ or Amazon Aurora MySQL 5.6+ or MariaDB 10.2+ or PostgreSQL 10+ is required"; - if ("MySQL".equals(metaData.getDatabaseProductName())) { - @Nullable - String amazonAuroraVersion; - try (Statement stmt = cnn.createStatement()) { - try (ResultSet rst = stmt.executeQuery("select AURORA_VERSION()")) { - rst.next(); - amazonAuroraVersion = rst.getString(1); - databaseVersionDescription += " / Aurora " + rst.getString(1); - } catch (SQLException e) { - if (e.getErrorCode() == 1305) { // com.mysql.cj.exceptions.MysqlErrorNumbers.ER_SP_DOES_NOT_EXIST - amazonAuroraVersion = null; - } else { - LOGGER.log(Level.WARNING,"Exception checking Amazon Aurora version", e); - amazonAuroraVersion = null; - } - } - } - @Nullable - String mariaDbVersion = PipelineMavenPluginMySqlDao.extractMariaDbVersion(metaData.getDatabaseProductVersion()); - - switch (metaData.getDatabaseMajorVersion()) { - case 8: - // OK - break; - case 5: - switch (metaData.getDatabaseMinorVersion()) { - case 7: - // ok - break; - case 6: - if (amazonAuroraVersion == null) { - // see JENKINS-54784 - return FormValidation.warning("Non validated MySQL version " + metaData.getDatabaseProductVersion() + ". " + databaseRequirement); - } else { - // we have successfully tested on Amazon Aurora MySQL 5.6.10a - break; - } - case 5: - if (mariaDbVersion == null) { - return FormValidation.warning("Non validated MySQL version " + metaData.getDatabaseProductVersion() + ". " + databaseRequirement); - } else { - // JENKINS-55378 have successfully tested with "5.5.5-10.2.20-MariaDB" - return FormValidation.ok("MariaDB version " + mariaDbVersion + " detected. Please ensure that your MariaDB version is at least version 10.2+"); - } - default: - return FormValidation.error("Non supported MySQL version " + metaData.getDatabaseProductVersion() + ". " + databaseRequirement); - } - break; - default: - return FormValidation.error("Non supported MySQL version " + metaData.getDatabaseProductVersion() + ". " + databaseRequirement); - } - } else if ("PostgreSQL".equals(metaData.getDatabaseProductName())) { - @Nullable - String amazonAuroraVersion; // https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Updates.html - try (Statement stmt = cnn.createStatement()) { - try (ResultSet rst = stmt.executeQuery("select AURORA_VERSION()")) { - rst.next(); - amazonAuroraVersion = rst.getString(1); - databaseVersionDescription += " / Aurora " + rst.getString(1); - } catch (SQLException e) { - if ("42883".equals(e.getSQLState())) { // org.postgresql.util.PSQLState.UNDEFINED_FUNCTION.getState() - amazonAuroraVersion = null; - } else { - LOGGER.log(Level.WARNING,"Exception checking Amazon Aurora version", e); - amazonAuroraVersion = null; - } - } - } - switch (metaData.getDatabaseMajorVersion()) { - case 14: - case 13: - case 12: - case 11: - case 10: - case 9: - case 8: - // OK - break; - default: - return FormValidation.warning("Non tested PostgreSQL version " + metaData.getDatabaseProductVersion() + ". " + databaseRequirement); - } - } else { - return FormValidation.warning("Non production grade database. For production workloads, " + databaseRequirement); - } - try (Statement stmt = cnn.createStatement()) { - try (ResultSet rst = stmt.executeQuery("select 1")) { - rst.next(); - // TODO more tests - } - } - return FormValidation.ok(databaseVersionDescription + " is a supported database"); - } catch (SQLException e ){ - return FormValidation.error(e, "Failure to connect to the database " + jdbcUrl); - } - } - } catch (RuntimeException e) { - return FormValidation.error(e, "Failed to test JDBC connection '" + jdbcUrl + "'"); - } catch (ClassNotFoundException e) { - return FormValidation.error(e, "Failed to load JDBC driver '" + driverClass + "' for JDBC connection '" + jdbcUrl + "'"); - } - - } - - private static HikariConfig createHikariConfig(String properties, String jdbcUrl, String jdbcUserName, String jdbcPassword) { - Properties p = new Properties(); - // todo refactor the DAO to inject config defaults in the DAO - if (jdbcUrl.startsWith("jdbc:mysql")) { - // https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby - // https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration - p.setProperty("dataSource.cachePrepStmts", "true"); - p.setProperty("dataSource.prepStmtCacheSize", "250"); - p.setProperty("dataSource.prepStmtCacheSqlLimit", "2048"); - p.setProperty("dataSource.useServerPrepStmts", "true"); - p.setProperty("dataSource.useLocalSessionState", "true"); - p.setProperty("dataSource.rewriteBatchedStatements", "true"); - p.setProperty("dataSource.cacheResultSetMetadata", "true"); - p.setProperty("dataSource.cacheServerConfiguration", "true"); - p.setProperty("dataSource.elideSetAutoCommits", "true"); - p.setProperty("dataSource.maintainTimeStats", "false"); - } else if (jdbcUrl.startsWith("jdbc:postgresql")) { - // no tuning recommendations found for postgresql - } else if (jdbcUrl.startsWith("jdbc:h2")) { - // dsConfig.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource"); don't specify the datasource due to a classloading issue - } else { - // unsupported config + if (StringUtils.isBlank(jdbcUrl)) { + jdbcUrl = optionalPipelineMavenPluginDao.get().getDefaultJdbcUrl(); } - if (StringUtils.isNotBlank(properties)) { - try { - p.load(new StringReader(properties)); - } catch (IOException e) { - throw new IllegalStateException("Failed to read properties.", e); - } + try { + PipelineMavenPluginDao.Builder.Config config = new PipelineMavenPluginDao.Builder.Config() + .credentialsId(jdbcCredentialsId) + .jdbcUrl(jdbcUrl) + .properties(properties); + return optionalPipelineMavenPluginDao.get().getBuilder().validateConfiguration(config); + } catch (Exception e) { + return FormValidation.error(e, e.getMessage()); } - LOGGER.log(Level.INFO, "Applied pool properties {0}", p); - HikariConfig dsConfig = new HikariConfig(p); - dsConfig.setJdbcUrl(jdbcUrl); - dsConfig.setUsername(jdbcUserName); - dsConfig.setPassword(jdbcPassword); - // to mimic the old behaviour pre JENKINS-69375 fix - dsConfig.setDataSourceProperties(p); - return dsConfig; } @Terminator diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/NeededPipelineMavenDatabasePluginAdminMonitor.java b/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/NeededPipelineMavenDatabasePluginAdminMonitor.java new file mode 100644 index 00000000..92486c68 --- /dev/null +++ b/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/NeededPipelineMavenDatabasePluginAdminMonitor.java @@ -0,0 +1,58 @@ +/* + * The MIT License + * + * Copyright (c) 2016, CloudBees, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.jenkinsci.plugins.pipeline.maven; + +import hudson.Extension; +import hudson.model.AdministrativeMonitor; +import jenkins.model.Jenkins; +import org.apache.commons.lang.StringUtils; +import org.kohsuke.stapler.StaplerRequest; +import org.kohsuke.stapler.StaplerResponse; +import org.kohsuke.stapler.interceptor.RequirePOST; + +import java.io.IOException; +import java.util.Objects; + +/** + * + */ +@Extension +public class NeededPipelineMavenDatabasePluginAdminMonitor extends AdministrativeMonitor { + + @Override + public boolean isActivated() { + String jdbcUrl = Objects.requireNonNull(GlobalPipelineMavenConfig.get()).getJdbcUrl(); + return (StringUtils.startsWith(jdbcUrl, "jdbc:h2") + || StringUtils.startsWith(jdbcUrl, "jdbc:mysql") + || StringUtils.startsWith(jdbcUrl, "jdbc:postgresql")) + && Jenkins.get().getPlugin("pipeline-maven-database") == null; + } + + @Override + public String getDisplayName() { + return "Pipeline Maven Integration - Need Pipeline Maven Database"; + } + +} \ No newline at end of file diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitor.java b/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitor.java deleted file mode 100644 index 31cdb2ad..00000000 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitor.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.jenkinsci.plugins.pipeline.maven; - -import hudson.Extension; -import hudson.model.AdministrativeMonitor; - -import org.kohsuke.stapler.StaplerRequest; -import org.kohsuke.stapler.StaplerResponse; -import org.kohsuke.stapler.interceptor.RequirePOST; - -import java.io.IOException; - -/** - * @author Cyrille Le Clerc - */ -@Extension -public class NonProductionGradeDatabaseWarningAdministrativeMonitor extends AdministrativeMonitor { - - @Override - public boolean isActivated() { - String jdbcUrl = GlobalPipelineMavenConfig.get().getJdbcUrl(); - if (jdbcUrl != null && !jdbcUrl.trim().isEmpty()) { - return jdbcUrl.startsWith("jdbc:h2:"); - } - - if (GlobalPipelineMavenConfig.get().isDaoInitialized()) { - return !GlobalPipelineMavenConfig.get().getDao().isEnoughProductionGradeForTheWorkload(); - } - - return false; - } - - @Override - public String getDisplayName() { - return "Pipeline Maven Integration - Non Production Database"; - } - - /** - * Depending on whether the user said "yes" or "no", send him to the right place. - */ - @RequirePOST - public void doAct(StaplerRequest req, StaplerResponse rsp) throws IOException { - if (req.hasParameter("no")) { - disable(true); - rsp.sendRedirect(req.getContextPath() + "/manage"); - } else { - rsp.sendRedirect(req.getContextPath() + "/configureTools"); - } - } -} \ No newline at end of file diff --git a/jenkins-plugin/src/main/resources/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfig/config.jelly b/jenkins-plugin/src/main/resources/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfig/config.jelly index b48d440f..30ef5be0 100644 --- a/jenkins-plugin/src/main/resources/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfig/config.jelly +++ b/jenkins-plugin/src/main/resources/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfig/config.jelly @@ -27,8 +27,17 @@ THE SOFTWARE. xmlns:f="/lib/form" xmlns:c="/lib/credentials"> + + + -
${instance.dao.toPrettyString()}
+
${instance.getDaoPrettyString()}
- + diff --git a/jenkins-plugin/src/main/resources/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitor/message.jelly b/jenkins-plugin/src/main/resources/org/jenkinsci/plugins/pipeline/maven/NeededPipelineMavenDatabasePluginAdminMonitor/message.jelly similarity index 73% rename from jenkins-plugin/src/main/resources/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitor/message.jelly rename to jenkins-plugin/src/main/resources/org/jenkinsci/plugins/pipeline/maven/NeededPipelineMavenDatabasePluginAdminMonitor/message.jelly index 9ea2d125..acb6102b 100644 --- a/jenkins-plugin/src/main/resources/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitor/message.jelly +++ b/jenkins-plugin/src/main/resources/org/jenkinsci/plugins/pipeline/maven/NeededPipelineMavenDatabasePluginAdminMonitor/message.jelly @@ -23,12 +23,8 @@ THE SOFTWARE. --> - +
-
- - - - The Pipeline Maven Plugin is currently using an embedded H2 database. A production grade database, MySQL or PostgreSQL, should be used. + The Pipeline Maven Plugin is currently using a jdbc url for a database but the plugin pipeline-maven-database plugin is not installed
diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/ConfigurationAsCodeNeedDockerTest.java b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/ConfigurationAsCodeNeedDockerTest.java new file mode 100644 index 00000000..24f92612 --- /dev/null +++ b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/ConfigurationAsCodeNeedDockerTest.java @@ -0,0 +1,117 @@ +package org.jenkinsci.plugins.pipeline.maven; + +import com.cloudbees.plugins.credentials.CredentialsProvider; +import hudson.ExtensionList; +import io.jenkins.plugins.casc.ConfigurationAsCode; +import io.jenkins.plugins.casc.ConfigurationContext; +import io.jenkins.plugins.casc.ConfiguratorRegistry; +import org.apache.commons.lang.StringUtils; +import org.jenkinsci.plugins.pipeline.maven.dao.MonitoringPipelineMavenPluginDaoDecorator; +import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginNullDao; +import org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginMySqlDao; +import org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginPostgreSqlDao; +import org.junit.jupiter.api.Test; +import org.jvnet.hudson.test.JenkinsRule; +import org.jvnet.hudson.test.junit.jupiter.WithJenkins; +import org.testcontainers.containers.MySQLContainer; +import org.testcontainers.containers.PostgreSQLContainer; +import org.testcontainers.junit.jupiter.Container; +import org.testcontainers.junit.jupiter.Testcontainers; + +import java.nio.file.Files; +import java.nio.file.Path; + +import static io.jenkins.plugins.casc.misc.Util.*; +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; + +@WithJenkins +@Testcontainers(disabledWithoutDocker = true) +public class ConfigurationAsCodeNeedDockerTest { + + @Container + public static MySQLContainer MYSQL_DB = new MySQLContainer<>(MySQLContainer.NAME).withUsername("aUser").withPassword("aPass"); + + @Container + public static PostgreSQLContainer POSTGRE_DB = new PostgreSQLContainer<>(PostgreSQLContainer.IMAGE).withUsername("aUser").withPassword("aPass"); + + @Test + public void should_support_mysql_configuration(JenkinsRule r) throws Exception { + + try { + MYSQL_DB.start(); + ExtensionList extensionList = r.jenkins.getExtensionList(CredentialsProvider.class); + extensionList.add(extensionList.size(), new GlobalPipelineMavenConfigTest.FakeCredentialsProvider()); + String jdbcUrl = MYSQL_DB.getJdbcUrl(); + + String yamlContent = toStringFromYamlFile(this, "configuration-as-code_mysql.yml"); + yamlContent = StringUtils.replace(yamlContent, "theJdbcUrl", jdbcUrl); + + Path tmpYml = Files.createTempFile("pipeline-maven-plugin-test", "yml"); + Files.write(tmpYml, yamlContent.getBytes()); + + ConfigurationAsCode.get().configure(singletonList(tmpYml.toFile().getAbsolutePath())); + + GlobalPipelineMavenConfig config = r.jenkins.getExtensionList(GlobalPipelineMavenConfig.class).get(0); + + assertThat(config.getJdbcUrl()).isEqualTo(jdbcUrl); + assertThat(config.getProperties()).isEqualTo("dataSource.cachePrepStmts=true\ndataSource.prepStmtCacheSize=250\n"); + assertThat(config.getDaoClass()).isEqualTo(PipelineMavenPluginMySqlDao.class.getName()); + + // we can't really test the PipelineMavenPluginMySqlDao is used as it is plenty of layers + // which doesn't expose the real implementation + assertThat(config.getDao().getClass()).isNotEqualTo(PipelineMavenPluginMySqlDao.class); + assertThat(config.getDao().getClass()).isNotEqualTo(PipelineMavenPluginNullDao.class); + assertThat(config.getDao().getClass()).isEqualTo(MonitoringPipelineMavenPluginDaoDecorator.class); + + ConfiguratorRegistry registry = ConfiguratorRegistry.get(); + ConfigurationContext context = new ConfigurationContext(registry); + String exported = toYamlString(getToolRoot(context).get("pipelineMaven")); + String expected = toStringFromYamlFile(this, "expected_output_mysql.yml"); + expected = StringUtils.replace(expected, "theJdbcUrl", jdbcUrl); + assertThat(exported).isEqualTo(expected); + } finally { + MYSQL_DB.stop(); + } + } + + @Test + public void should_support_postgres_configuration(JenkinsRule r) throws Exception { + + try { + POSTGRE_DB.start(); + ExtensionList extensionList = r.jenkins.getExtensionList(CredentialsProvider.class); + extensionList.add(extensionList.size(), new GlobalPipelineMavenConfigTest.FakeCredentialsProvider()); + String jdbcUrl = POSTGRE_DB.getJdbcUrl(); + + String yamlContent = toStringFromYamlFile(this, "configuration-as-code_postgresql.yml"); + yamlContent = StringUtils.replace(yamlContent, "theJdbcUrl", jdbcUrl); + + Path tmpYml = Files.createTempFile("pipeline-maven-plugin-test", "yml"); + Files.write(tmpYml, yamlContent.getBytes()); + + ConfigurationAsCode.get().configure(singletonList(tmpYml.toFile().getAbsolutePath())); + + GlobalPipelineMavenConfig config = r.jenkins.getExtensionList(GlobalPipelineMavenConfig.class).get(0); + + assertThat(config.getJdbcUrl()).isEqualTo(jdbcUrl); + assertThat(config.getDaoClass()).isEqualTo(PipelineMavenPluginPostgreSqlDao.class.getName()); + + // we can't really test the PipelineMavenPluginPostgreSqlDao is used as it is plenty of layers + // which doesn't expose the real implementation + assertThat(config.getDao().getClass()).isNotEqualTo(PipelineMavenPluginPostgreSqlDao.class); + assertThat(config.getDao().getClass()).isNotEqualTo(PipelineMavenPluginNullDao.class); + assertThat(config.getDao().getClass()).isEqualTo(MonitoringPipelineMavenPluginDaoDecorator.class); + + ConfiguratorRegistry registry = ConfiguratorRegistry.get(); + ConfigurationContext context = new ConfigurationContext(registry); + String exported = toYamlString(getToolRoot(context).get("pipelineMaven")); + String expected = toStringFromYamlFile(this, "expected_output_postgresql.yml"); + expected = StringUtils.replace(expected, "theJdbcUrl", jdbcUrl); + assertThat(exported).isEqualTo(expected); + } finally { + POSTGRE_DB.stop(); + } + } + +} diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/ConfigurationAsCodeTest.java b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/ConfigurationAsCodeTest.java index 3e7b4c5c..1bb9fe73 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/ConfigurationAsCodeTest.java +++ b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/ConfigurationAsCodeTest.java @@ -79,31 +79,14 @@ public void should_support_triggers_configuration(JenkinsRule r) throws Exceptio assertThat(exported).isEqualTo(expected); } - @Test - public void should_support_mysql_configuration(JenkinsRule r) throws Exception { - ConfigurationAsCode.get().configure(singletonList(getClass().getResource("configuration-as-code_mysql.yml").toExternalForm())); - - GlobalPipelineMavenConfig config = r.jenkins.getExtensionList(GlobalPipelineMavenConfig.class).get(0); - - assertThat(config.getJdbcUrl()).isEqualTo("jdbc:mysql://dbserver/jenkinsdb"); - assertThat(config.getProperties()).isEqualTo("dataSource.cachePrepStmts=true\ndataSource.prepStmtCacheSize=250\n"); - - ConfiguratorRegistry registry = ConfiguratorRegistry.get(); - ConfigurationContext context = new ConfigurationContext(registry); - String exported = toYamlString(getToolRoot(context).get("pipelineMaven")); - String expected = toStringFromYamlFile(this, "expected_output_mysql.yml"); - - assertThat(exported).isEqualTo(expected); - } - @Test public void should_support_postgresql_configuration(JenkinsRule r) throws Exception { ConfigurationAsCode.get().configure(singletonList(getClass().getResource("configuration-as-code_postgresql.yml").toExternalForm())); GlobalPipelineMavenConfig config = r.jenkins.getExtensionList(GlobalPipelineMavenConfig.class).get(0); - assertThat(config.getJdbcUrl()).isEqualTo("jdbc:postgresql://dbserver/jenkinsdb"); - assertThat(config.getJdbcCredentialsId()).isEqualTo("pg-creds"); + assertThat(config.getJdbcUrl()).isEqualTo("theJdbcUrl"); + assertThat(config.getJdbcCredentialsId()).isEqualTo("credsId"); ConfiguratorRegistry registry = ConfiguratorRegistry.get(); ConfigurationContext context = new ConfigurationContext(registry); diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/DependencyGraphTest.java b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/DependencyGraphTest.java index 9199be4e..4602f155 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/DependencyGraphTest.java +++ b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/DependencyGraphTest.java @@ -4,12 +4,15 @@ import static org.jenkinsci.plugins.pipeline.maven.TestUtils.runAfterMethod; import static org.jenkinsci.plugins.pipeline.maven.TestUtils.runBeforeMethod; +import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Future; import java.util.stream.Collectors; +import hudson.ExtensionList; import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginDao; +import org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginH2Dao; import org.jenkinsci.plugins.pipeline.maven.publishers.PipelineGraphPublisher; import org.jenkinsci.plugins.pipeline.maven.trigger.WorkflowJobDependencyTrigger; import org.jenkinsci.plugins.pipeline.maven.util.WorkflowMultibranchProjectTestsUtils; @@ -39,6 +42,10 @@ public class DependencyGraphTest extends AbstractIntegrationTest { @BeforeEach public void setup() throws Exception { + ExtensionList.lookupSingleton(GlobalPipelineMavenConfig.class).setDaoClass(PipelineMavenPluginH2Dao.class.getName()); + String jdbcUrl = "jdbc:h2:file:" + new File("target", getClass().getName() + "-h2").getAbsolutePath() + ";" + + "AUTO_SERVER=TRUE;MULTI_THREADED=1;QUERY_CACHE_SIZE=25;JMX=TRUE"; + ExtensionList.lookupSingleton(GlobalPipelineMavenConfig.class).setJdbcUrl(jdbcUrl); downstreamArtifactRepoRule = new GitSampleRepoRule(); runBeforeMethod(downstreamArtifactRepoRule); diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfigTest.java b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfigTest.java index 763049ca..7b1b2536 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfigTest.java +++ b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/GlobalPipelineMavenConfigTest.java @@ -13,9 +13,9 @@ import org.jenkinsci.plugins.pipeline.maven.dao.CustomTypePipelineMavenPluginDaoDecorator; import org.jenkinsci.plugins.pipeline.maven.dao.MonitoringPipelineMavenPluginDaoDecorator; import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginDao; -import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginH2Dao; -import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginMySqlDao; -import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginPostgreSqlDao; +import org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginH2Dao; +import org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginMySqlDao; +import org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginPostgreSqlDao; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; import org.jvnet.hudson.test.JenkinsRule; @@ -55,7 +55,7 @@ public static void setup(JenkinsRule r) { private static JenkinsRule j; - private static class FakeCredentialsProvider extends CredentialsProvider { + public static class FakeCredentialsProvider extends CredentialsProvider { public FakeCredentialsProvider() { } @@ -80,6 +80,7 @@ public List getCredentials(Class type, ItemGroup i @Test public void shouldBuildH2Dao() throws Exception { + config.setDaoClass(PipelineMavenPluginH2Dao.class.getName()); PipelineMavenPluginDao dao = config.getDao(); assertThat(dao).isInstanceOf(MonitoringPipelineMavenPluginDaoDecorator.class); @@ -91,6 +92,7 @@ public void shouldBuildH2Dao() throws Exception { @Test public void shouldBuildMysqlDao() throws Exception { + config.setDaoClass(PipelineMavenPluginMySqlDao.class.getName()); ExtensionList extensionList = Jenkins.getInstance().getExtensionList(CredentialsProvider.class); extensionList.add(extensionList.size(), new FakeCredentialsProvider()); config.setJdbcUrl(MYSQL_DB.getJdbcUrl()); @@ -125,6 +127,7 @@ public void shouldBuildMysqlDao() throws Exception { @Test public void shouldBuildPostgresqlDao() throws Exception { + config.setDaoClass(PipelineMavenPluginPostgreSqlDao.class.getName()); ExtensionList extensionList = Jenkins.getInstance().getExtensionList(CredentialsProvider.class); extensionList.add(extensionList.size(), new FakeCredentialsProvider()); config.setJdbcUrl(POSTGRE_DB.getJdbcUrl()); diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitorIntegrationTest.java b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitorIntegrationTest.java deleted file mode 100644 index 8d7f35d1..00000000 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitorIntegrationTest.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.jenkinsci.plugins.pipeline.maven; - -import static com.cloudbees.plugins.credentials.CredentialsScope.GLOBAL; -import static java.util.Arrays.asList; -import static org.assertj.core.api.Assertions.assertThat; - -import java.util.List; - -import org.acegisecurity.Authentication; -import org.junit.jupiter.api.Test; -import org.jvnet.hudson.test.JenkinsRule; -import org.jvnet.hudson.test.junit.jupiter.WithJenkins; -import org.testcontainers.containers.MySQLContainer; -import org.testcontainers.containers.PostgreSQLContainer; -import org.testcontainers.junit.jupiter.Container; -import org.testcontainers.junit.jupiter.Testcontainers; - -import com.cloudbees.plugins.credentials.Credentials; -import com.cloudbees.plugins.credentials.CredentialsProvider; -import com.cloudbees.plugins.credentials.domains.DomainRequirement; -import com.cloudbees.plugins.credentials.impl.UsernamePasswordCredentialsImpl; - -import hudson.ExtensionList; -import hudson.model.AdministrativeMonitor; -import hudson.model.ItemGroup; - -@Testcontainers(disabledWithoutDocker = true) -@WithJenkins -public class NonProductionGradeDatabaseWarningAdministrativeMonitorIntegrationTest { - - @Container - public static MySQLContainer MYSQL_DB = new MySQLContainer<>(MySQLContainer.NAME).withUsername("aUser").withPassword("aPass"); - - @Container - public static PostgreSQLContainer POSTGRE_DB = new PostgreSQLContainer<>(PostgreSQLContainer.IMAGE).withUsername("aUser").withPassword("aPass"); - - private static class FakeCredentialsProvider extends CredentialsProvider { - public FakeCredentialsProvider() { - } - - @Override - public boolean isEnabled(Object context) { - return true; - } - - @Override - public List getCredentials(Class type, ItemGroup itemGroup, Authentication authentication, - List domainRequirements) { - return (List) asList(new UsernamePasswordCredentialsImpl(GLOBAL, "credsId", "", "aUser", "aPass")); - } - - @Override - public List getCredentials(Class type, ItemGroup itemGroup, Authentication authentication) { - return getCredentials(type, itemGroup, authentication, null); - } - } - - @Test - public void shouldMitigateComputationWithH2Database(JenkinsRule j) throws Exception { - NonProductionGradeDatabaseWarningAdministrativeMonitor monitor = j.getInstance().getExtensionList(AdministrativeMonitor.class) - .get(NonProductionGradeDatabaseWarningAdministrativeMonitor.class); - assertThat(monitor).isNotNull(); - - assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized()).isFalse(); - assertThat(monitor.isActivated()).isFalse(); - - GlobalPipelineMavenConfig.get().setJdbcUrl("jdbc:h2:file:/tmp/some.file"); - - assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized()).isFalse(); - assertThat(monitor.isActivated()).isTrue(); - - GlobalPipelineMavenConfig.get().setJdbcUrl(null); - - assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized()).isFalse(); - assertThat(monitor.isActivated()).isFalse(); - - GlobalPipelineMavenConfig.get().getDao(); - - assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized()).isTrue(); - assertThat(monitor.isActivated()).isFalse(); - - for (int i = 1; i <= 101; i++) { - GlobalPipelineMavenConfig.get().getDao().recordGeneratedArtifact("a job", i, "a.group.id", "anArtifactId", "1.0.0-SNAPSHOT", "jar", - "1.0.0-SNAPSHOT", null, false, "jar", null); - } - - assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized()).isTrue(); - assertThat(monitor.isActivated()).isTrue(); - } - - @Test - public void shouldNotDisplayWarningWithMysqlDatabase(JenkinsRule j) throws Exception { - ExtensionList extensionList = j.getInstance().getExtensionList(CredentialsProvider.class); - extensionList.add(extensionList.size(), new FakeCredentialsProvider()); - GlobalPipelineMavenConfig.get().setJdbcUrl(MYSQL_DB.getJdbcUrl()); - GlobalPipelineMavenConfig.get().setJdbcCredentialsId("credsId"); - - NonProductionGradeDatabaseWarningAdministrativeMonitor monitor = j.jenkins.getExtensionList(AdministrativeMonitor.class) - .get(NonProductionGradeDatabaseWarningAdministrativeMonitor.class); - - assertThat(monitor).isNotNull(); - assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized()).isFalse(); - assertThat(monitor.isActivated()).isFalse(); - } - - @Test - public void shouldNotDisplayWarningWithPostgresDatabase(JenkinsRule j) throws Exception { - ExtensionList extensionList = j.getInstance().getExtensionList(CredentialsProvider.class); - extensionList.add(extensionList.size(), new FakeCredentialsProvider()); - GlobalPipelineMavenConfig.get().setJdbcUrl(POSTGRE_DB.getJdbcUrl()); - GlobalPipelineMavenConfig.get().setJdbcCredentialsId("credsId"); - - NonProductionGradeDatabaseWarningAdministrativeMonitor monitor = j.jenkins.getExtensionList(AdministrativeMonitor.class) - .get(NonProductionGradeDatabaseWarningAdministrativeMonitor.class); - - assertThat(monitor).isNotNull(); - assertThat(GlobalPipelineMavenConfig.get().isDaoInitialized()).isFalse(); - assertThat(monitor.isActivated()).isFalse(); - } -} diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitorTest.java b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitorTest.java deleted file mode 100644 index 2d3e741e..00000000 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/NonProductionGradeDatabaseWarningAdministrativeMonitorTest.java +++ /dev/null @@ -1,173 +0,0 @@ -package org.jenkinsci.plugins.pipeline.maven; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mockStatic; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -import org.jenkinsci.plugins.pipeline.maven.dao.PipelineMavenPluginDao; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.MockedStatic; -import org.mockito.junit.jupiter.MockitoExtension; - -@ExtendWith(MockitoExtension.class) -public class NonProductionGradeDatabaseWarningAdministrativeMonitorTest { - - @InjectMocks - private NonProductionGradeDatabaseWarningAdministrativeMonitor monitor; - - @Mock - private GlobalPipelineMavenConfig config; - - @Mock - private PipelineMavenPluginDao dao; - - @Test - public void test_is_activated_no_config_and_uninitialized() { - try (MockedStatic c = mockStatic(GlobalPipelineMavenConfig.class)) { - c.when(GlobalPipelineMavenConfig::get).thenReturn(config); - when(config.getJdbcUrl()).thenReturn(null); - when(config.isDaoInitialized()).thenReturn(false); - - assertThat(monitor.isActivated()).isFalse(); - - verify(config).getJdbcUrl(); - verify(config).isDaoInitialized(); - verifyNoMoreInteractions(config, dao); - } - } - - @Test - public void test_is_activated_empty_config_and_uninitialized() { - try (MockedStatic c = mockStatic(GlobalPipelineMavenConfig.class)) { - c.when(GlobalPipelineMavenConfig::get).thenReturn(config); - when(config.getJdbcUrl()).thenReturn(""); - when(config.isDaoInitialized()).thenReturn(false); - - assertThat(monitor.isActivated()).isFalse(); - - verify(config).getJdbcUrl(); - verify(config).isDaoInitialized(); - verifyNoMoreInteractions(config, dao); - } - } - - @Test - public void test_is_activated_no_config_and_initialized_non_production() { - try (MockedStatic c = mockStatic(GlobalPipelineMavenConfig.class)) { - c.when(GlobalPipelineMavenConfig::get).thenReturn(config); - when(config.getJdbcUrl()).thenReturn(null); - when(config.isDaoInitialized()).thenReturn(true); - when(config.getDao()).thenReturn(dao); - when(dao.isEnoughProductionGradeForTheWorkload()).thenReturn(false); - - assertThat(monitor.isActivated()).isTrue(); - - verify(config).getJdbcUrl(); - verify(config).getDao(); - verify(config).isDaoInitialized(); - verify(dao).isEnoughProductionGradeForTheWorkload(); - verifyNoMoreInteractions(config, dao); - } - } - - @Test - public void test_is_activated_empty_config_and_initialized_non_production() { - try (MockedStatic c = mockStatic(GlobalPipelineMavenConfig.class)) { - c.when(GlobalPipelineMavenConfig::get).thenReturn(config); - when(config.getJdbcUrl()).thenReturn(""); - when(config.isDaoInitialized()).thenReturn(true); - when(config.getDao()).thenReturn(dao); - when(dao.isEnoughProductionGradeForTheWorkload()).thenReturn(false); - - assertThat(monitor.isActivated()).isTrue(); - - verify(config).getJdbcUrl(); - verify(config).getDao(); - verify(config).isDaoInitialized(); - verify(dao).isEnoughProductionGradeForTheWorkload(); - verifyNoMoreInteractions(config, dao); - } - } - - @Test - public void test_is_activated_no_config_and_initialized_production() { - try (MockedStatic c = mockStatic(GlobalPipelineMavenConfig.class)) { - c.when(GlobalPipelineMavenConfig::get).thenReturn(config); - when(config.getJdbcUrl()).thenReturn(null); - when(config.isDaoInitialized()).thenReturn(true); - when(config.getDao()).thenReturn(dao); - when(dao.isEnoughProductionGradeForTheWorkload()).thenReturn(true); - - assertThat(monitor.isActivated()).isFalse(); - - verify(config).getJdbcUrl(); - verify(config).getDao(); - verify(config).isDaoInitialized(); - verify(dao).isEnoughProductionGradeForTheWorkload(); - verifyNoMoreInteractions(config, dao); - } - } - - @Test - public void test_is_activated_empty_config_and_initialized_production() { - try (MockedStatic c = mockStatic(GlobalPipelineMavenConfig.class)) { - c.when(GlobalPipelineMavenConfig::get).thenReturn(config); - when(config.getJdbcUrl()).thenReturn(""); - when(config.isDaoInitialized()).thenReturn(true); - when(config.getDao()).thenReturn(dao); - when(dao.isEnoughProductionGradeForTheWorkload()).thenReturn(true); - - assertThat(monitor.isActivated()).isFalse(); - - verify(config).getJdbcUrl(); - verify(config).getDao(); - verify(config).isDaoInitialized(); - verify(dao).isEnoughProductionGradeForTheWorkload(); - verifyNoMoreInteractions(config, dao); - } - } - - @Test - public void test_is_activated_with_h2_config() { - try (MockedStatic c = mockStatic(GlobalPipelineMavenConfig.class)) { - c.when(GlobalPipelineMavenConfig::get).thenReturn(config); - when(config.getJdbcUrl()).thenReturn("jdbc:h2:some url"); - - assertThat(monitor.isActivated()).isTrue(); - - verify(config).getJdbcUrl(); - verifyNoMoreInteractions(config, dao); - } - } - - @Test - public void test_is_activated_with_mysql_config() { - try (MockedStatic c = mockStatic(GlobalPipelineMavenConfig.class)) { - c.when(GlobalPipelineMavenConfig::get).thenReturn(config); - when(config.getJdbcUrl()).thenReturn("jdbc:mysql:some url"); - - assertThat(monitor.isActivated()).isFalse(); - - verify(config).getJdbcUrl(); - verifyNoMoreInteractions(config, dao); - } - } - - @Test - public void test_is_activated_with_postgresql_config() { - try (MockedStatic c = mockStatic(GlobalPipelineMavenConfig.class)) { - c.when(GlobalPipelineMavenConfig::get).thenReturn(config); - when(config.getJdbcUrl()).thenReturn("jdbc:postgresql:some url"); - - assertThat(monitor.isActivated()).isFalse(); - - verify(config).getJdbcUrl(); - verifyNoMoreInteractions(config, dao); - } - } -} diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/listeners/DownstreamPipelineTriggerRunListenerIntegrationTest.java b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/listeners/DownstreamPipelineTriggerRunListenerIntegrationTest.java index e2f43aff..30de9202 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/listeners/DownstreamPipelineTriggerRunListenerIntegrationTest.java +++ b/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/listeners/DownstreamPipelineTriggerRunListenerIntegrationTest.java @@ -3,14 +3,17 @@ import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; +import java.io.File; import java.util.ArrayList; import java.util.List; +import hudson.ExtensionList; import org.jenkinsci.plugins.pipeline.maven.AbstractIntegrationTest; import org.jenkinsci.plugins.pipeline.maven.GlobalPipelineMavenConfig; import org.jenkinsci.plugins.pipeline.maven.MavenArtifact; import org.jenkinsci.plugins.pipeline.maven.MavenDependency; import org.jenkinsci.plugins.pipeline.maven.MavenPublisher; +import org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginH2Dao; import org.jenkinsci.plugins.pipeline.maven.publishers.FindbugsAnalysisPublisher; import org.jenkinsci.plugins.pipeline.maven.publishers.PipelineGraphPublisher; import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition; @@ -34,6 +37,10 @@ public class DownstreamPipelineTriggerRunListenerIntegrationTest extends Abstrac @BeforeEach public void setup() throws Exception { + ExtensionList.lookupSingleton(GlobalPipelineMavenConfig.class).setDaoClass(PipelineMavenPluginH2Dao.class.getName()); + String jdbcUrl = "jdbc:h2:file:" + new File("target", getClass().getName() + "-h2").getAbsolutePath() + ";" + + "AUTO_SERVER=TRUE;MULTI_THREADED=1;QUERY_CACHE_SIZE=25;JMX=TRUE"; + ExtensionList.lookupSingleton(GlobalPipelineMavenConfig.class).setJdbcUrl(jdbcUrl); List publisherOptions = GlobalPipelineMavenConfig.get().getPublisherOptions(); if (publisherOptions == null) { publisherOptions = new ArrayList<>(); diff --git a/jenkins-plugin/src/test/resources/logback-test.xml b/jenkins-plugin/src/test/resources/logback-test.xml deleted file mode 100644 index 3ec10b26..00000000 --- a/jenkins-plugin/src/test/resources/logback-test.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - %d{HH:mm:ss.SSS} [%thread] %highlight(%-5level) %logger{36} - %msg%n - - - - - - - - - \ No newline at end of file diff --git a/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/configuration-as-code_mysql.yml b/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/configuration-as-code_mysql.yml index 8029be5a..ea176970 100644 --- a/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/configuration-as-code_mysql.yml +++ b/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/configuration-as-code_mysql.yml @@ -3,7 +3,9 @@ jenkins: tool: pipelineMaven: - jdbcUrl: jdbc:mysql://dbserver/jenkinsdb + jdbcUrl: theJdbcUrl + daoClass: org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginMySqlDao + jdbcCredentialsId: credsId properties: | dataSource.cachePrepStmts=true dataSource.prepStmtCacheSize=250 diff --git a/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/configuration-as-code_postgresql.yml b/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/configuration-as-code_postgresql.yml index a6f2a162..96ab35e5 100644 --- a/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/configuration-as-code_postgresql.yml +++ b/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/configuration-as-code_postgresql.yml @@ -3,5 +3,6 @@ jenkins: tool: pipelineMaven: - jdbcUrl: jdbc:postgresql://dbserver/jenkinsdb - JdbcCredentialsId: pg-creds + jdbcUrl: theJdbcUrl + daoClass: org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginPostgreSqlDao + JdbcCredentialsId: credsId diff --git a/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/expected_output_mysql.yml b/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/expected_output_mysql.yml index 0d82fece..6e398d5e 100644 --- a/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/expected_output_mysql.yml +++ b/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/expected_output_mysql.yml @@ -1,5 +1,7 @@ +daoClass: "org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginMySqlDao" globalTraceability: false -jdbcUrl: "jdbc:mysql://dbserver/jenkinsdb" +jdbcCredentialsId: "credsId" +jdbcUrl: "theJdbcUrl" properties: | dataSource.cachePrepStmts=true dataSource.prepStmtCacheSize=250 diff --git a/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/expected_output_postgresql.yml b/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/expected_output_postgresql.yml index 2bb67dbb..d221548e 100644 --- a/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/expected_output_postgresql.yml +++ b/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/expected_output_postgresql.yml @@ -1,6 +1,7 @@ +daoClass: "org.jenkinsci.plugins.pipeline.maven.db.PipelineMavenPluginPostgreSqlDao" globalTraceability: false -jdbcCredentialsId: "pg-creds" -jdbcUrl: "jdbc:postgresql://dbserver/jenkinsdb" +jdbcCredentialsId: "credsId" +jdbcUrl: "theJdbcUrl" triggerDownstreamUponResultAborted: false triggerDownstreamUponResultFailure: false triggerDownstreamUponResultNotBuilt: false diff --git a/maven-spy/pom.xml b/maven-spy/pom.xml index 2bce893c..0cb867de 100644 --- a/maven-spy/pom.xml +++ b/maven-spy/pom.xml @@ -46,7 +46,7 @@ org.apache.maven maven-core - 3.3.9 + provided org.sonatype.aether diff --git a/pipeline-maven-api/pom.xml b/pipeline-maven-api/pom.xml new file mode 100644 index 00000000..6dd37edd --- /dev/null +++ b/pipeline-maven-api/pom.xml @@ -0,0 +1,29 @@ + + + 4.0.0 + + org.jenkins-ci.plugins + pipeline-maven-parent + ${changelist} + + pipeline-maven-api + Pipeline Maven Plugin API + hpi + + + + org.apache.maven + maven-artifact + + + org.apache.maven.resolver + maven-resolver-api + 1.7.3 + + + org.slf4j + slf4j-simple + + + + diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/MavenArtifact.java b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/MavenArtifact.java similarity index 100% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/MavenArtifact.java rename to pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/MavenArtifact.java diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/MavenDependency.java b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/MavenDependency.java similarity index 100% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/MavenDependency.java rename to pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/MavenDependency.java diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/AbstractPipelineMavenPluginDaoDecorator.java b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/AbstractPipelineMavenPluginDaoDecorator.java similarity index 96% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/AbstractPipelineMavenPluginDaoDecorator.java rename to pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/AbstractPipelineMavenPluginDaoDecorator.java index 24bb814d..91b9fbe4 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/AbstractPipelineMavenPluginDaoDecorator.java +++ b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/AbstractPipelineMavenPluginDaoDecorator.java @@ -5,6 +5,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; + import java.io.IOException; import java.util.List; import java.util.Map; @@ -18,6 +19,16 @@ public AbstractPipelineMavenPluginDaoDecorator(@NonNull PipelineMavenPluginDao d this.delegate = delegate; } + @Override + public String getDescription() { + return delegate.getDescription(); + } + + @Override + public Builder getBuilder() { + return delegate.getBuilder(); + } + @Override public void recordDependency(@NonNull String jobFullName, int buildNumber, @NonNull String groupId, @NonNull String artifactId, @NonNull String version, @NonNull String type, @NonNull String scope, boolean ignoreUpstreamTriggers, String classifier) { delegate.recordDependency(jobFullName, buildNumber, groupId, artifactId, version, type, scope, ignoreUpstreamTriggers, classifier); diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/CacheStats.java b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/CacheStats.java similarity index 100% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/CacheStats.java rename to pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/CacheStats.java diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/CustomTypePipelineMavenPluginDaoDecorator.java b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/CustomTypePipelineMavenPluginDaoDecorator.java similarity index 100% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/CustomTypePipelineMavenPluginDaoDecorator.java rename to pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/CustomTypePipelineMavenPluginDaoDecorator.java diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/MonitoringPipelineMavenPluginDaoDecorator.java b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/MonitoringPipelineMavenPluginDaoDecorator.java similarity index 99% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/MonitoringPipelineMavenPluginDaoDecorator.java rename to pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/MonitoringPipelineMavenPluginDaoDecorator.java index e196a680..47ed96b4 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/MonitoringPipelineMavenPluginDaoDecorator.java +++ b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/MonitoringPipelineMavenPluginDaoDecorator.java @@ -2,7 +2,6 @@ import org.jenkinsci.plugins.pipeline.maven.MavenArtifact; import org.jenkinsci.plugins.pipeline.maven.MavenDependency; -import org.jenkinsci.plugins.pipeline.maven.listeners.DaoHelper; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginDao.java b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginDao.java similarity index 89% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginDao.java rename to pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginDao.java index 43289bea..ac962556 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginDao.java +++ b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginDao.java @@ -26,10 +26,10 @@ import hudson.model.Item; import hudson.model.Run; +import hudson.util.FormValidation; import org.apache.maven.artifact.Artifact; import org.jenkinsci.plugins.pipeline.maven.MavenArtifact; import org.jenkinsci.plugins.pipeline.maven.MavenDependency; -import org.jenkinsci.plugins.pipeline.maven.publishers.PipelineGraphPublisher; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; @@ -52,7 +52,7 @@ public interface PipelineMavenPluginDao extends Closeable { * @param version Maven dependency version * @param type Maven dependency type (e.g. "jar", "war", "pom", hpi"...) * @param scope Maven dependency scope ("compile", "test", "provided"...) - * @param ignoreUpstreamTriggers see {@link PipelineGraphPublisher#isIgnoreUpstreamTriggers()} ()} + * @param ignoreUpstreamTriggers see PipelineGraphPublisher#isIgnoreUpstreamTriggers() * @param classifier Maven dependency classifier */ void recordDependency(@NonNull String jobFullName, int buildNumber, @@ -67,7 +67,7 @@ void recordDependency(@NonNull String jobFullName, int buildNumber, * @param parentGroupId Maven dependency groupId * @param parentArtifactId Maven dependency artifactId * @param parentVersion Maven dependency version - * @param ignoreUpstreamTriggers see {@link PipelineGraphPublisher#isIgnoreUpstreamTriggers()} ()} + * @param ignoreUpstreamTriggers see PipelineGraphPublisher#isIgnoreUpstreamTriggers() */ void recordParentProject(@NonNull String jobFullName, int buildNumber, @NonNull String parentGroupId, @NonNull String parentArtifactId, @NonNull String parentVersion, @@ -85,7 +85,7 @@ void recordParentProject(@NonNull String jobFullName, int buildNumber, * (e.g. baseVersion is "1.1-SNAPSHOT" for a "1.1-SNAPSHOT" artifact that has been deployed to a repo and expanded * to "1.1-20170808.155524-66") * @param repositoryUrl URL of the Maven repository on which the artifact is deployed ("mvn deploy"). {@code null} if the artifact was not deployed - * @param skipDownstreamTriggers see {@link PipelineGraphPublisher#isSkipDownstreamTriggers()} + * @param skipDownstreamTriggers see PipelineGraphPublisher#isSkipDownstreamTriggers() * @param extension * @param classifier */ @@ -94,7 +94,7 @@ void recordGeneratedArtifact(@NonNull String jobFullName, int buildNumber, @Nullable String repositoryUrl, boolean skipDownstreamTriggers, String extension, String classifier); /** - * TODO add {@link MavenArtifact} as {@link org.jenkinsci.plugins.pipeline.maven.cause.MavenDependencyUpstreamCause} gives these details + * TODO add {@link MavenArtifact} as org.jenkinsci.plugins.pipeline.maven.cause.MavenDependencyUpstreamCause gives these details * @param upstreamJobName Job that triggered the build. See {@link Item#getFullName()}. * @param upstreamBuildNumber Job that triggered the build. See {@link Run#getNumber()}. * @param downstreamJobName Job that is triggered. See {@link Item#getFullName()}. @@ -262,6 +262,8 @@ default SortedSet listDownstreamJobs(@NonNull String groupId, @NonNull S */ String toPrettyString(); + String getDescription(); + /** * Update the database with build result details. @@ -282,4 +284,56 @@ default SortedSet listDownstreamJobs(@NonNull String groupId, @NonNull S * @return {@code false} if the underlying database is not production grade enough for the workload */ boolean isEnoughProductionGradeForTheWorkload(); + + interface Builder { + class Config { + private String jdbcUrl; + + private String credentialsId; + + private String properties; + + public String getJdbcUrl() { + return jdbcUrl; + } + + public Config jdbcUrl(String jdbcUrl) { + this.jdbcUrl = jdbcUrl; + return this; + } + + public String getCredentialsId() { + return this.credentialsId; + } + + public Config credentialsId(String credentialsId) { + this.credentialsId = credentialsId; + return this; + } + + public String getProperties() { + return this.properties; + } + + public Config properties(String properties) { + this.properties = properties; + return this; + } + + public Config() { + // + } + } + + PipelineMavenPluginDao build(Config config); + + FormValidation validateConfiguration(Config config); + + } + + Builder getBuilder(); + + default String getDefaultJdbcUrl() { + return null; + } } diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginNullDao.java b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginNullDao.java similarity index 78% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginNullDao.java rename to pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginNullDao.java index d69e11a3..31212042 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginNullDao.java +++ b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginNullDao.java @@ -24,10 +24,13 @@ package org.jenkinsci.plugins.pipeline.maven.dao; +import hudson.Extension; +import hudson.util.FormValidation; import org.jenkinsci.plugins.pipeline.maven.MavenArtifact; import org.jenkinsci.plugins.pipeline.maven.MavenDependency; import edu.umd.cs.findbugs.annotations.NonNull; + import java.io.IOException; import java.util.Collections; import java.util.List; @@ -40,12 +43,33 @@ /** * @author Cyrille Le Clerc */ +@Extension public class PipelineMavenPluginNullDao implements PipelineMavenPluginDao { private static Logger LOGGER = Logger.getLogger(PipelineMavenPluginNullDao.class.getName()); + @Override + public String getDescription() { + return Messages.dao_null_description(); + } + + @Override + public PipelineMavenPluginDao.Builder getBuilder() { + return new Builder() { + @Override + public PipelineMavenPluginDao build(Config config) { + return new PipelineMavenPluginNullDao(); + } + + @Override + public FormValidation validateConfiguration(Config config) { + return FormValidation.ok(); + } + }; + } + @Override public void recordDependency(String jobFullName, int buildNumber, String groupId, String artifactId, String version, String type, String scope, boolean ignoreUpstreamTriggers, String classifier) { - LOGGER.log(Level.INFO, "recordDependency({0}#{1}, {2}:{3}:{4}:{5}, {6}, ignoreUpstreamTriggers:{7}})", + LOGGER.log(Level.FINEST, "NOT recordDependency({0}#{1}, {2}:{3}:{4}:{5}, {6}, ignoreUpstreamTriggers:{7}})", new Object[]{jobFullName, buildNumber, groupId, artifactId, version, type, scope, ignoreUpstreamTriggers}); } @@ -57,39 +81,39 @@ public List listDependencies(@NonNull String jobFullName, int b @Override public void recordParentProject(@NonNull String jobFullName, int buildNumber, @NonNull String parentGroupId, @NonNull String parentArtifactId, @NonNull String parentVersion, boolean ignoreUpstreamTriggers) { - LOGGER.log(Level.INFO, "recordParentProject({0}#{1}, {2}:{3} ignoreUpstreamTriggers:{5}})", + LOGGER.log(Level.FINEST, "NOT recordParentProject({0}#{1}, {2}:{3} ignoreUpstreamTriggers:{5}})", new Object[]{jobFullName, buildNumber, parentGroupId, parentArtifactId, parentVersion, ignoreUpstreamTriggers}); } @Override public void recordGeneratedArtifact(String jobFullName, int buildNumber, String groupId, String artifactId, String version, String type, String baseVersion, String repositoryUrl, boolean skipDownstreamTriggers, String extension, String classifier) { - LOGGER.log(Level.INFO, "recordGeneratedArtifact({0}#{1}, {2}:{3}:{4}:{5}, version:{6}, repositoryUrl:{7}, skipDownstreamTriggers:{8})", + LOGGER.log(Level.FINEST, "NOT recordGeneratedArtifact({0}#{1}, {2}:{3}:{4}:{5}, version:{6}, repositoryUrl:{7}, skipDownstreamTriggers:{8})", new Object[]{jobFullName, buildNumber, groupId, artifactId, baseVersion, type, version, repositoryUrl, skipDownstreamTriggers}); } @Override public void recordBuildUpstreamCause(String upstreamJobName, int upstreamBuildNumber, String downstreamJobName, int downstreamBuildNumber) { - LOGGER.log(Level.INFO, "recordBuildUpstreamCause(upstreamBuild: {0}#{1}, downstreamBuild: {2}#{3})", + LOGGER.log(Level.FINEST, "NOT recordBuildUpstreamCause(upstreamBuild: {0}#{1}, downstreamBuild: {2}#{3})", new Object[]{upstreamJobName, upstreamBuildNumber, downstreamJobName, downstreamBuildNumber}); } @Override public void renameJob(String oldFullName, String newFullName) { - LOGGER.log(Level.INFO, "renameJob({0}, {1})", new Object[]{oldFullName, newFullName}); + LOGGER.log(Level.FINEST, "NOT renameJob({0}, {1})", new Object[]{oldFullName, newFullName}); } @Override public void deleteJob(String jobFullName) { - LOGGER.log(Level.INFO, "deleteJob({0})", new Object[]{jobFullName}); + LOGGER.log(Level.FINEST, "NOT deleteJob({0})", new Object[]{jobFullName}); } @Override public void deleteBuild(String jobFullName, int buildNumber) { - LOGGER.log(Level.INFO, "deleteBuild({0}#{1})", new Object[]{jobFullName, buildNumber}); + LOGGER.log(Level.FINEST, "NOT deleteBuild({0}#{1})", new Object[]{jobFullName, buildNumber}); } @@ -133,7 +157,7 @@ public Map listTransitiveUpstreamJobs(String jobFullName, int b @Override public void cleanup() { - LOGGER.log(Level.INFO, "cleanup()"); + LOGGER.log(Level.FINEST, "cleanup()"); } @NonNull @@ -144,7 +168,7 @@ public List getGeneratedArtifacts(@NonNull String jobFullName, in @Override public void updateBuildOnCompletion(@NonNull String jobFullName, int buildNumber, int buildResultOrdinal, long startTimeInMillis, long durationInMillis) { - LOGGER.log(Level.INFO, "updateBuildOnCompletion({0}, {1}, result: {2}, startTime): {3}, duration: {4}", + LOGGER.log(Level.FINEST, "NOOT updateBuildOnCompletion({0}, {1}, result: {2}, startTime): {3}, duration: {4}", new Object[]{jobFullName, buildNumber, buildResultOrdinal, startTimeInMillis, durationInMillis}); } diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/UpstreamMemory.java b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/UpstreamMemory.java similarity index 84% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/UpstreamMemory.java rename to pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/UpstreamMemory.java index f8b6c6b3..2d18f963 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/UpstreamMemory.java +++ b/pipeline-maven-api/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/UpstreamMemory.java @@ -1,7 +1,5 @@ package org.jenkinsci.plugins.pipeline.maven.dao; -import static org.jenkinsci.plugins.pipeline.maven.dao.MonitoringPipelineMavenPluginDaoDecorator.registerCacheStatsSupplier; - import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; @@ -22,7 +20,7 @@ public class UpstreamMemory { private static final AtomicInteger MISSES = new AtomicInteger(); static { - registerCacheStatsSupplier(() -> new CacheStats("listUpstreamJobs", HITS.get(), MISSES.get())); + MonitoringPipelineMavenPluginDaoDecorator.registerCacheStatsSupplier(() -> new CacheStats("listUpstreamJobs", HITS.get(), MISSES.get())); } // remember the already known upstreams diff --git a/pipeline-maven-api/src/main/resources/index.jelly b/pipeline-maven-api/src/main/resources/index.jelly new file mode 100644 index 00000000..498a4bf0 --- /dev/null +++ b/pipeline-maven-api/src/main/resources/index.jelly @@ -0,0 +1,4 @@ + +
+ Pipeline Maven Plugin API +
diff --git a/pipeline-maven-api/src/main/resources/org/jenkinsci/plugins/pipeline/maven/dao/Messages.properties b/pipeline-maven-api/src/main/resources/org/jenkinsci/plugins/pipeline/maven/dao/Messages.properties new file mode 100644 index 00000000..b673d168 --- /dev/null +++ b/pipeline-maven-api/src/main/resources/org/jenkinsci/plugins/pipeline/maven/dao/Messages.properties @@ -0,0 +1 @@ +dao.null.description=Pipeline Maven Plugin no storage mode \ No newline at end of file diff --git a/pipeline-maven-database/pom.xml b/pipeline-maven-database/pom.xml new file mode 100644 index 00000000..12763d5c --- /dev/null +++ b/pipeline-maven-database/pom.xml @@ -0,0 +1,84 @@ + + + 4.0.0 + + org.jenkins-ci.plugins + pipeline-maven-parent + ${changelist} + + pipeline-maven-database + Pipeline Maven Plugin Database + hpi + + + + org.jenkins-ci.plugins + pipeline-maven-api + + + org.jenkins-ci.plugins + credentials + + + com.zaxxer + HikariCP + ${hikaricp.version} + + + org.slf4j + slf4j-api + + + + + io.jenkins.plugins + h2-api + ${jenkins-plugin-h2.version} + true + + + io.jenkins.plugins + mysql-api + ${jenkins-plugin-mysql.version} + true + + + com.google.protobuf + protobuf-java + + + + + io.jenkins.plugins + postgresql-api + ${jenkins-plugin-postgresql.version} + true + + + org.slf4j + slf4j-simple + + + org.testcontainers + junit-jupiter + test + + + org.testcontainers + mysql + test + + + org.testcontainers + postgresql + test + + + org.testcontainers + testcontainers + test + + + + + diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/AbstractPipelineMavenPluginDao.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/AbstractPipelineMavenPluginDao.java similarity index 76% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/AbstractPipelineMavenPluginDao.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/AbstractPipelineMavenPluginDao.java index 390cdff6..d0c85ef7 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/AbstractPipelineMavenPluginDao.java +++ b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/AbstractPipelineMavenPluginDao.java @@ -22,20 +22,32 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; - +package org.jenkinsci.plugins.pipeline.maven.db; + +import com.cloudbees.plugins.credentials.CredentialsMatchers; +import com.cloudbees.plugins.credentials.CredentialsProvider; +import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials; +import com.zaxxer.hikari.HikariConfig; +import com.zaxxer.hikari.HikariDataSource; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import hudson.ExtensionList; import hudson.model.Item; import hudson.model.Result; import hudson.model.Run; +import hudson.security.ACL; +import hudson.util.FormValidation; +import hudson.util.Secret; +import jenkins.model.Jenkins; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.h2.api.ErrorCode; import org.jenkinsci.plugins.pipeline.maven.MavenArtifact; import org.jenkinsci.plugins.pipeline.maven.MavenDependency; +import org.jenkinsci.plugins.pipeline.maven.dao.*; import org.jenkinsci.plugins.pipeline.maven.db.migration.MigrationStep; -import org.jenkinsci.plugins.pipeline.maven.util.ClassUtils; -import org.jenkinsci.plugins.pipeline.maven.util.RuntimeIoException; -import org.jenkinsci.plugins.pipeline.maven.util.RuntimeSqlException; +import org.jenkinsci.plugins.pipeline.maven.db.util.ClassUtils; +import org.jenkinsci.plugins.pipeline.maven.db.util.RuntimeIoException; +import org.jenkinsci.plugins.pipeline.maven.db.util.RuntimeSqlException; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; @@ -43,9 +55,11 @@ import java.io.Closeable; import java.io.IOException; import java.io.InputStream; +import java.io.StringReader; import java.nio.charset.StandardCharsets; import java.sql.Connection; import java.sql.DatabaseMetaData; +import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; @@ -53,17 +67,8 @@ import java.sql.Timestamp; import java.text.DecimalFormat; import java.text.NumberFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.Map.Entry; -import java.util.Objects; -import java.util.SortedSet; -import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; @@ -81,16 +86,344 @@ public abstract class AbstractPipelineMavenPluginDao implements PipelineMavenPlu @Nullable private transient Long jenkinsMasterPrimaryKey; - public AbstractPipelineMavenPluginDao(@NonNull DataSource ds) { - ds.getClass(); // check non null + @SuppressFBWarnings("NP_NONNULL_FIELD_NOT_INITIALIZED_IN_CONSTRUCTOR") + protected AbstractPipelineMavenPluginDao() { + // this one is here only to help when using Extension.lookup + } + public AbstractPipelineMavenPluginDao(@NonNull DataSource ds) { + Objects.requireNonNull(ds, "Datasource cannot be null"); this.ds = ds; - registerJdbcDriver(); initializeDatabase(); testDatabase(); } + protected boolean acceptNoCredentials() { + return false; + } + + private class JDBCDaoBuilder implements Builder { + protected final Logger LOGGER = Logger.getLogger(JDBCDaoBuilder.class.getName()); + + private final Class pipelineMavenPluginDaoClass; + + public JDBCDaoBuilder(Class pipelineMavenPluginDaoClass) { + this.pipelineMavenPluginDaoClass = pipelineMavenPluginDaoClass; + } + + @Override + public PipelineMavenPluginDao build(Config config) { + Jenkins j = Jenkins.get(); + PipelineMavenPluginDao dao; + try { + String jdbcUrl = config.getJdbcUrl(); + if(StringUtils.isBlank(jdbcUrl)) { + // some dao such h2 can use default jdbc ur + Optional optionalPipelineMavenPluginDao = + ExtensionList.lookup(PipelineMavenPluginDao.class) + .stream() + .filter(pipelineMavenPluginDao -> pipelineMavenPluginDao.getClass().getName().equals(pipelineMavenPluginDaoClass.getName())) + .findFirst(); + if(optionalPipelineMavenPluginDao.isPresent()){ + jdbcUrl = optionalPipelineMavenPluginDao.get().getDefaultJdbcUrl(); + } + } + String jdbcUserName, jdbcPassword; + + if (StringUtils.isBlank(config.getCredentialsId()) && !AbstractPipelineMavenPluginDao.this.acceptNoCredentials()) + throw new IllegalStateException("No credentials defined for JDBC URL '" + jdbcUrl + "'"); + + UsernamePasswordCredentials jdbcCredentials = null; + if (!StringUtils.isBlank(config.getCredentialsId())) { + jdbcCredentials = (UsernamePasswordCredentials) CredentialsMatchers.firstOrNull( + CredentialsProvider.lookupCredentials(UsernamePasswordCredentials.class, j, + ACL.SYSTEM, Collections.EMPTY_LIST), + CredentialsMatchers.withId(config.getCredentialsId())); + } + + if (jdbcCredentials == null && pipelineMavenPluginDaoClass == PipelineMavenPluginH2Dao.class) { + jdbcUserName = "sa"; + jdbcPassword = "sa"; + } + else if (jdbcCredentials == null) { + throw new IllegalStateException("Credentials '" + config.getCredentialsId() + "' defined for JDBC URL '" + jdbcUrl + "' NOT found"); + } + else { + jdbcUserName = jdbcCredentials.getUsername(); + jdbcPassword = Secret.toString(jdbcCredentials.getPassword()); + } + + HikariConfig dsConfig = createHikariConfig(config.getProperties(), jdbcUrl, jdbcUserName, jdbcPassword); + dsConfig.setAutoCommit(false); + + // TODO cleanup this quick fix for JENKINS-54587, we should have a better solution with the JDBC driver loaded by the DAO itself + try { + DriverManager.getDriver(jdbcUrl); + } catch (SQLException e) { + if ("08001".equals(e.getSQLState()) && 0 == e.getErrorCode()) { + // if it's a "No suitable driver" exception, we try to load the jdbc driver and retry + if (jdbcUrl.startsWith("jdbc:h2:")) { + try { + Class.forName("org.h2.Driver"); + } catch (ClassNotFoundException cnfe) { + throw new IllegalStateException("H2 driver should be bundled with this plugin"); + } + } else if (jdbcUrl.startsWith("jdbc:mysql:")) { + try { + Class.forName("com.mysql.cj.jdbc.Driver"); + } catch (ClassNotFoundException cnfe) { + throw new RuntimeException("MySql driver 'com.mysql.cj.jdbc.Driver' not found. Please install the 'MySQL Database Plugin' to install the MySql driver"); + } + } else if (jdbcUrl.startsWith("jdbc:postgresql:")) { + try { + Class.forName("org.postgresql.Driver"); + } catch (ClassNotFoundException cnfe) { + throw new RuntimeException("PostgreSQL driver 'org.postgresql.Driver' not found. Please install the 'PostgreSQL Database Plugin' to install the PostgreSQL driver"); + } + } else { + throw new IllegalArgumentException("Unsupported database type in JDBC URL " + jdbcUrl); + } + DriverManager.getDriver(jdbcUrl); + } else { + throw e; + } + } + + LOGGER.log(Level.INFO, "Connect to database {0} with username {1}", new Object[]{jdbcUrl, jdbcUserName}); + DataSource ds = new HikariDataSource(dsConfig); + + try { + dao = new MonitoringPipelineMavenPluginDaoDecorator( + new CustomTypePipelineMavenPluginDaoDecorator((PipelineMavenPluginDao)pipelineMavenPluginDaoClass + .getConstructor(DataSource.class) + .newInstance(ds))); + } catch (Exception e) { + throw new SQLException( + "Exception connecting to '" + jdbcUrl + "' with credentials '" + config.getCredentialsId() + "' (" + + jdbcUserName + "/***) and DAO " + getClass().getSimpleName(), e); + } + } catch (RuntimeException | SQLException e) { + LOGGER.log(Level.WARNING, "Exception creating database dao, skip", e); + dao = new PipelineMavenPluginNullDao(); + } + return dao; + } + + @Override + public FormValidation validateConfiguration(Config config) { + String jdbcUrl = config.getJdbcUrl(); + if (StringUtils.isBlank(jdbcUrl)) { + return FormValidation.ok(); + } + + String driverClass = null; + try { + if (StringUtils.isBlank(jdbcUrl)) { + driverClass = "org.h2.Driver"; + } else if (jdbcUrl.startsWith("jdbc:h2")) { + driverClass = "org.h2.Driver"; + } else if (jdbcUrl.startsWith("jdbc:mysql")) { + driverClass = "com.mysql.cj.jdbc.Driver"; + } else if (jdbcUrl.startsWith("jdbc:postgresql:")) { + driverClass = "org.postgresql.Driver"; + } else { + return FormValidation.error("Unsupported database specified in JDBC url '" + jdbcUrl + "'"); + } + try { + Class.forName(driverClass); + } catch (ClassNotFoundException e) { + if ("com.mysql.cj.jdbc.Driver".equals(driverClass)) { + return FormValidation.error("MySQL JDBC driver '" + driverClass + "' not found, please install the Jenkins 'MySQL API Plugin'", e); + } else if ("org.postgresql.Driver".equals(driverClass)) { + return FormValidation.error("PostgreSQL JDBC driver '" + driverClass + "' not found, please install the Jenkins 'PostgreSQL API Plugin'" + jdbcUrl, e); + } else { + throw e; + } + } + + String jdbcCredentialsId = config.getCredentialsId(); + + String jdbcUserName, jdbcPassword; + if (StringUtils.isEmpty(jdbcCredentialsId)) { + if (AbstractPipelineMavenPluginDao.this.acceptNoCredentials()) { + // embedded database, assume OK + return FormValidation.ok(); + } else { + return FormValidation.error("No credentials specified for JDBC url '" + jdbcUrl + "'"); + } + } else { + UsernamePasswordCredentials jdbcCredentials = (UsernamePasswordCredentials) CredentialsMatchers.firstOrNull( + CredentialsProvider.lookupCredentials(UsernamePasswordCredentials.class, Jenkins.get(), + ACL.SYSTEM, Collections.EMPTY_LIST), + CredentialsMatchers.withId(jdbcCredentialsId)); + if (jdbcCredentials == null) { + return FormValidation.error("Credentials '" + jdbcCredentialsId + "' defined for JDBC URL '" + jdbcUrl + "' not found"); + } + jdbcUserName = jdbcCredentials.getUsername(); + jdbcPassword = Secret.toString(jdbcCredentials.getPassword()); + } + + HikariConfig dsConfig = createHikariConfig(config.getProperties(), jdbcUrl, jdbcUserName, jdbcPassword); + + try (HikariDataSource ds = new HikariDataSource(dsConfig)) { + try (Connection cnn = ds.getConnection()) { + DatabaseMetaData metaData = cnn.getMetaData(); + // getDatabaseProductVersion(): + // * MySQL: "8.0.13" + // * Amazon Aurora: "5.6.10" + // * MariaDB: "5.5.5-10.2.20-MariaDB", "5.5.5-10.3.11-MariaDB-1:10.3.11+maria~bionic" + String databaseVersionDescription = metaData.getDatabaseProductName() + " " + metaData.getDatabaseProductVersion(); + String databaseRequirement = "MySQL Server version 5.7+ or Amazon Aurora MySQL 5.6+ or MariaDB 10.2+ or PostgreSQL 10+ is required"; + if ("MySQL".equals(metaData.getDatabaseProductName())) { + @Nullable + String amazonAuroraVersion; + try (Statement stmt = cnn.createStatement()) { + try (ResultSet rst = stmt.executeQuery("select AURORA_VERSION()")) { + rst.next(); + amazonAuroraVersion = rst.getString(1); + databaseVersionDescription += " / Aurora " + rst.getString(1); + } catch (SQLException e) { + if (e.getErrorCode() == 1305) { // com.mysql.cj.exceptions.MysqlErrorNumbers.ER_SP_DOES_NOT_EXIST + amazonAuroraVersion = null; + } else { + LOGGER.log(Level.WARNING,"Exception checking Amazon Aurora version", e); + amazonAuroraVersion = null; + } + } + } + @Nullable + String mariaDbVersion = PipelineMavenPluginMySqlDao.extractMariaDbVersion(metaData.getDatabaseProductVersion()); + + switch (metaData.getDatabaseMajorVersion()) { + case 8: + // OK + break; + case 5: + switch (metaData.getDatabaseMinorVersion()) { + case 7: + // ok + break; + case 6: + if (amazonAuroraVersion == null) { + // see JENKINS-54784 + return FormValidation.warning("Non validated MySQL version " + metaData.getDatabaseProductVersion() + ". " + databaseRequirement); + } else { + // we have successfully tested on Amazon Aurora MySQL 5.6.10a + break; + } + case 5: + if (mariaDbVersion == null) { + return FormValidation.warning("Non validated MySQL version " + metaData.getDatabaseProductVersion() + ". " + databaseRequirement); + } else { + // JENKINS-55378 have successfully tested with "5.5.5-10.2.20-MariaDB" + return FormValidation.ok("MariaDB version " + mariaDbVersion + " detected. Please ensure that your MariaDB version is at least version 10.2+"); + } + default: + return FormValidation.error("Non supported MySQL version " + metaData.getDatabaseProductVersion() + ". " + databaseRequirement); + } + break; + default: + return FormValidation.error("Non supported MySQL version " + metaData.getDatabaseProductVersion() + ". " + databaseRequirement); + } + } else if ("PostgreSQL".equals(metaData.getDatabaseProductName())) { + @Nullable + String amazonAuroraVersion; // https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraPostgreSQL.Updates.html + try (Statement stmt = cnn.createStatement()) { + try (ResultSet rst = stmt.executeQuery("select AURORA_VERSION()")) { + rst.next(); + amazonAuroraVersion = rst.getString(1); + databaseVersionDescription += " / Aurora " + rst.getString(1); + } catch (SQLException e) { + if ("42883".equals(e.getSQLState())) { // org.postgresql.util.PSQLState.UNDEFINED_FUNCTION.getState() + amazonAuroraVersion = null; + } else { + LOGGER.log(Level.WARNING,"Exception checking Amazon Aurora version", e); + amazonAuroraVersion = null; + } + } + } + switch (metaData.getDatabaseMajorVersion()) { + case 14: + case 13: + case 12: + case 11: + case 10: + case 9: + case 8: + // OK + break; + default: + return FormValidation.warning("Non tested PostgreSQL version " + metaData.getDatabaseProductVersion() + ". " + databaseRequirement); + } + } else { + return FormValidation.warning("Non production grade database. For production workloads, " + databaseRequirement); + } + try (Statement stmt = cnn.createStatement()) { + try (ResultSet rst = stmt.executeQuery("select 1")) { + rst.next(); + // TODO more tests + } + } + return FormValidation.ok(databaseVersionDescription + " is a supported database"); + } catch (SQLException e ){ + return FormValidation.error(e, "Failure to connect to the database " + jdbcUrl); + } + } + } catch (RuntimeException e) { + return FormValidation.error(e, "Failed to test JDBC connection '" + jdbcUrl + "'"); + } catch (ClassNotFoundException e) { + return FormValidation.error(e, "Failed to load JDBC driver '" + driverClass + "' for JDBC connection '" + jdbcUrl + "'"); + } + } + } + + @Override + public Builder getBuilder() { + return new JDBCDaoBuilder(getClass()); + } + + private static HikariConfig createHikariConfig(String properties, String jdbcUrl, String jdbcUserName, String jdbcPassword) { + Properties p = new Properties(); + // todo refactor the DAO to inject config defaults in the DAO + if (jdbcUrl.startsWith("jdbc:mysql")) { + // https://github.com/brettwooldridge/HikariCP#configuration-knobs-baby + // https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration + p.setProperty("dataSource.cachePrepStmts", "true"); + p.setProperty("dataSource.prepStmtCacheSize", "250"); + p.setProperty("dataSource.prepStmtCacheSqlLimit", "2048"); + p.setProperty("dataSource.useServerPrepStmts", "true"); + p.setProperty("dataSource.useLocalSessionState", "true"); + p.setProperty("dataSource.rewriteBatchedStatements", "true"); + p.setProperty("dataSource.cacheResultSetMetadata", "true"); + p.setProperty("dataSource.cacheServerConfiguration", "true"); + p.setProperty("dataSource.elideSetAutoCommits", "true"); + p.setProperty("dataSource.maintainTimeStats", "false"); + } else if (jdbcUrl.startsWith("jdbc:postgresql")) { + // no tuning recommendations found for postgresql + } else if (jdbcUrl.startsWith("jdbc:h2")) { + // dsConfig.setDataSourceClassName("org.h2.jdbcx.JdbcDataSource"); don't specify the datasource due to a classloading issue + } else { + // unsupported config + } + + if (StringUtils.isNotBlank(properties)) { + try { + p.load(new StringReader(properties)); + } catch (IOException e) { + throw new IllegalStateException("Failed to read properties.", e); + } + } + Logger.getLogger(AbstractPipelineMavenPluginDao.class.getName()).log(Level.INFO, "Applied pool properties {0}", p); + HikariConfig dsConfig = new HikariConfig(p); + dsConfig.setJdbcUrl(jdbcUrl); + dsConfig.setUsername(jdbcUserName); + dsConfig.setPassword(jdbcPassword); + // to mimic the old behaviour pre JENKINS-69375 fix + dsConfig.setDataSourceProperties(p); + return dsConfig; + } + protected abstract void registerJdbcDriver(); @Override diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginH2Dao.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginH2Dao.java similarity index 84% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginH2Dao.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginH2Dao.java index 0d35deb5..5f63879f 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginH2Dao.java +++ b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginH2Dao.java @@ -22,11 +22,14 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; +import hudson.Extension; +import jenkins.model.Jenkins; import org.h2.jdbcx.JdbcConnectionPool; import edu.umd.cs.findbugs.annotations.NonNull; + import javax.sql.DataSource; import java.io.File; import java.io.IOException; @@ -39,17 +42,33 @@ /** * @author Cyrille Le Clerc */ +@Extension public class PipelineMavenPluginH2Dao extends AbstractPipelineMavenPluginDao { + public PipelineMavenPluginH2Dao() { + super(); + } + public PipelineMavenPluginH2Dao(@NonNull DataSource ds) { super(ds); } + protected boolean acceptNoCredentials() { + return true; + } + + @Override + public String getDescription() { + return Messages.dao_h2_description(); + } + public PipelineMavenPluginH2Dao(@NonNull File rootDir) { this(JdbcConnectionPool.create("jdbc:h2:file:" + new File(rootDir, "jenkins-jobs").getAbsolutePath() + ";" + "AUTO_SERVER=TRUE;MULTI_THREADED=1;QUERY_CACHE_SIZE=25;JMX=TRUE", "sa", "sa")); } + + @Override protected void registerJdbcDriver() { try { @@ -122,4 +141,17 @@ public void close() throws IOException { } super.close(); } + + public String getDefaultJdbcUrl() { + File databaseRootDir = new File(Jenkins.get().getRootDir(), "jenkins-jobs"); + if (!databaseRootDir.exists()) { + boolean created = databaseRootDir.mkdirs(); + if (!created) { + throw new IllegalStateException("Failure to create database root dir " + databaseRootDir); + } + } + return "jdbc:h2:file:" + new File(databaseRootDir, "jenkins-jobs").getAbsolutePath() + ";" + + "AUTO_SERVER=TRUE;MULTI_THREADED=1;QUERY_CACHE_SIZE=25;JMX=TRUE"; + } + } diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDao.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDao.java similarity index 93% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDao.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDao.java index d1a702fb..2f3e7db6 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDao.java +++ b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDao.java @@ -22,11 +22,12 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; import com.mysql.cj.exceptions.MysqlErrorNumbers; +import hudson.Extension; import org.apache.commons.lang.StringUtils; -import org.jenkinsci.plugins.pipeline.maven.util.RuntimeSqlException; +import org.jenkinsci.plugins.pipeline.maven.db.util.RuntimeSqlException; import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; @@ -41,8 +42,18 @@ /** * @author Cyrille Le Clerc */ +@Extension public class PipelineMavenPluginMySqlDao extends AbstractPipelineMavenPluginDao { + public PipelineMavenPluginMySqlDao() { + super(); + } + + @Override + public String getDescription() { + return Messages.dao_mysql_description(); + } + /** * Extract the MariaDB server version from {@link DatabaseMetaData#getDatabaseProductVersion()} * diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginPostgreSqlDao.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginPostgreSqlDao.java similarity index 93% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginPostgreSqlDao.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginPostgreSqlDao.java index be9e2079..130d1798 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginPostgreSqlDao.java +++ b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginPostgreSqlDao.java @@ -22,8 +22,9 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; +import hudson.Extension; import org.postgresql.util.PSQLState; import edu.umd.cs.findbugs.annotations.NonNull; @@ -39,12 +40,23 @@ /** * @author Cyrille Le Clerc */ +@Extension public class PipelineMavenPluginPostgreSqlDao extends AbstractPipelineMavenPluginDao { + public PipelineMavenPluginPostgreSqlDao() { + super(); + } + public PipelineMavenPluginPostgreSqlDao(@NonNull DataSource ds) { super(ds); } + + @Override + public String getDescription() { + return Messages.dao_postgesql_description(); + } + @Override public String getJdbcScheme() { return "postgresql"; diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/MigrationStep.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/MigrationStep.java similarity index 100% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/MigrationStep.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/MigrationStep.java diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep10.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep10.java similarity index 100% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep10.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep10.java diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep11.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep11.java similarity index 100% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep11.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep11.java diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep8.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep8.java similarity index 100% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep8.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/h2/MigrationStep8.java diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/mysql/MigrationStep12.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/mysql/MigrationStep12.java similarity index 100% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/mysql/MigrationStep12.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/migration/mysql/MigrationStep12.java diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/ClassUtils.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/ClassUtils.java similarity index 91% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/ClassUtils.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/ClassUtils.java index cb9a541a..deb95b51 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/ClassUtils.java +++ b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/ClassUtils.java @@ -1,4 +1,4 @@ -package org.jenkinsci.plugins.pipeline.maven.util; +package org.jenkinsci.plugins.pipeline.maven.db.util; import java.io.InputStream; diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/RuntimeIoException.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/RuntimeIoException.java similarity index 93% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/RuntimeIoException.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/RuntimeIoException.java index 52b8ae9d..5a2b0cfd 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/RuntimeIoException.java +++ b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/RuntimeIoException.java @@ -1,4 +1,4 @@ -package org.jenkinsci.plugins.pipeline.maven.util; +package org.jenkinsci.plugins.pipeline.maven.db.util; /** * We prefer {@link RuntimeException} to catched exceptions. diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/RuntimeSqlException.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/RuntimeSqlException.java similarity index 93% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/RuntimeSqlException.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/RuntimeSqlException.java index ace4550a..495440b6 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/RuntimeSqlException.java +++ b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/RuntimeSqlException.java @@ -1,4 +1,4 @@ -package org.jenkinsci.plugins.pipeline.maven.util; +package org.jenkinsci.plugins.pipeline.maven.db.util; /** * We prefer {@link RuntimeException} to catched exceptions. diff --git a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/SqlUtils.java b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/SqlUtils.java similarity index 92% rename from jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/SqlUtils.java rename to pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/SqlUtils.java index 575ad7ed..de4d1f9e 100644 --- a/jenkins-plugin/src/main/java/org/jenkinsci/plugins/pipeline/maven/util/SqlUtils.java +++ b/pipeline-maven-database/src/main/java/org/jenkinsci/plugins/pipeline/maven/db/util/SqlUtils.java @@ -1,4 +1,4 @@ -package org.jenkinsci.plugins.pipeline.maven.util; +package org.jenkinsci.plugins.pipeline.maven.db.util; import java.io.PrintStream; import java.sql.ResultSet; diff --git a/pipeline-maven-database/src/main/resources/index.jelly b/pipeline-maven-database/src/main/resources/index.jelly new file mode 100644 index 00000000..498a4bf0 --- /dev/null +++ b/pipeline-maven-database/src/main/resources/index.jelly @@ -0,0 +1,4 @@ + +
+ Pipeline Maven Plugin API +
diff --git a/pipeline-maven-database/src/main/resources/org/jenkinsci/plugins/pipeline/maven/db/Messages.properties b/pipeline-maven-database/src/main/resources/org/jenkinsci/plugins/pipeline/maven/db/Messages.properties new file mode 100644 index 00000000..84559b11 --- /dev/null +++ b/pipeline-maven-database/src/main/resources/org/jenkinsci/plugins/pipeline/maven/db/Messages.properties @@ -0,0 +1,3 @@ +dao.mysql.description=Pipeline Maven Plugin storage using MySql +dao.h2.description=Pipeline Maven Plugin storage using H2 +dao.postgesql.description=Pipeline Maven Plugin storage using Postgres \ No newline at end of file diff --git a/jenkins-plugin/src/main/resources/sql/h2/01_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/01_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/01_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/01_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/02_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/02_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/02_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/02_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/03_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/03_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/03_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/03_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/04_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/04_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/04_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/04_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/05_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/05_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/05_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/05_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/06_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/06_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/06_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/06_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/07_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/07_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/07_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/07_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/08_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/08_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/08_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/08_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/09_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/09_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/09_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/09_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/10_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/10_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/10_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/10_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/11_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/11_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/11_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/11_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/h2/12_migration.sql b/pipeline-maven-database/src/main/resources/sql/h2/12_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/h2/12_migration.sql rename to pipeline-maven-database/src/main/resources/sql/h2/12_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/01_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/01_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/01_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/01_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/02_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/02_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/02_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/02_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/03_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/03_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/03_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/03_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/04_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/04_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/04_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/04_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/05_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/05_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/05_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/05_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/06_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/06_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/06_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/06_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/07_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/07_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/07_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/07_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/08_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/08_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/08_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/08_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/09_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/09_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/09_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/09_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/10_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/10_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/10_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/10_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/11_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/11_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/11_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/11_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/12_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/12_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/12_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/12_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/mysql/13_migration.sql b/pipeline-maven-database/src/main/resources/sql/mysql/13_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/mysql/13_migration.sql rename to pipeline-maven-database/src/main/resources/sql/mysql/13_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/postgresql/01_migration.sql b/pipeline-maven-database/src/main/resources/sql/postgresql/01_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/postgresql/01_migration.sql rename to pipeline-maven-database/src/main/resources/sql/postgresql/01_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/postgresql/02_migration.sql b/pipeline-maven-database/src/main/resources/sql/postgresql/02_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/postgresql/02_migration.sql rename to pipeline-maven-database/src/main/resources/sql/postgresql/02_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/postgresql/03_migration.sql b/pipeline-maven-database/src/main/resources/sql/postgresql/03_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/postgresql/03_migration.sql rename to pipeline-maven-database/src/main/resources/sql/postgresql/03_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/postgresql/04_migration.sql b/pipeline-maven-database/src/main/resources/sql/postgresql/04_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/postgresql/04_migration.sql rename to pipeline-maven-database/src/main/resources/sql/postgresql/04_migration.sql diff --git a/jenkins-plugin/src/main/resources/sql/postgresql/05_migration.sql b/pipeline-maven-database/src/main/resources/sql/postgresql/05_migration.sql similarity index 100% rename from jenkins-plugin/src/main/resources/sql/postgresql/05_migration.sql rename to pipeline-maven-database/src/main/resources/sql/postgresql/05_migration.sql diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginDaoAbstractTest.java b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginDaoAbstractTest.java similarity index 99% rename from jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginDaoAbstractTest.java rename to pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginDaoAbstractTest.java index 56f3685c..ef658a1d 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginDaoAbstractTest.java +++ b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginDaoAbstractTest.java @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; import static org.assertj.core.api.Assertions.assertThat; @@ -37,7 +37,7 @@ import org.jenkinsci.plugins.pipeline.maven.MavenArtifact; import org.jenkinsci.plugins.pipeline.maven.MavenDependency; -import org.jenkinsci.plugins.pipeline.maven.util.SqlTestsUtils; +import org.jenkinsci.plugins.pipeline.maven.db.util.SqlTestsUtils; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginH2DaoInitializationTest.java b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginH2DaoInitializationTest.java similarity index 99% rename from jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginH2DaoInitializationTest.java rename to pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginH2DaoInitializationTest.java index 61918516..f39701e6 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginH2DaoInitializationTest.java +++ b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginH2DaoInitializationTest.java @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; import static org.assertj.core.api.Assertions.assertThat; diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginH2DaoTest.java b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginH2DaoTest.java similarity index 97% rename from jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginH2DaoTest.java rename to pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginH2DaoTest.java index 9283429e..1b02739e 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginH2DaoTest.java +++ b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginH2DaoTest.java @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; import org.h2.jdbcx.JdbcConnectionPool; import org.jenkinsci.plugins.pipeline.maven.db.migration.MigrationStep; diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDaoIT.java b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDaoIT.java similarity index 98% rename from jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDaoIT.java rename to pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDaoIT.java index 8f99397a..b552fece 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDaoIT.java +++ b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDaoIT.java @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; import javax.sql.DataSource; diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDaoInitializationTest.java b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDaoInitializationTest.java similarity index 99% rename from jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDaoInitializationTest.java rename to pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDaoInitializationTest.java index 70d2a80e..ea487def 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDaoInitializationTest.java +++ b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDaoInitializationTest.java @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; import static org.assertj.core.api.Assertions.assertThat; diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDaoTest.java b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDaoTest.java similarity index 98% rename from jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDaoTest.java rename to pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDaoTest.java index df2978cb..3c998c00 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginMySqlDaoTest.java +++ b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginMySqlDaoTest.java @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; import static org.assertj.core.api.Assertions.assertThat; diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginPostgreSqlDaoIT.java b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginPostgreSqlDaoIT.java similarity index 98% rename from jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginPostgreSqlDaoIT.java rename to pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginPostgreSqlDaoIT.java index f1b34bb0..68495341 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginPostgreSqlDaoIT.java +++ b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginPostgreSqlDaoIT.java @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; import javax.sql.DataSource; diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginPostgreSqlDaoTest.java b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginPostgreSqlDaoTest.java similarity index 97% rename from jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginPostgreSqlDaoTest.java rename to pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginPostgreSqlDaoTest.java index 4efa1ae6..8a3c6015 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/dao/PipelineMavenPluginPostgreSqlDaoTest.java +++ b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/PipelineMavenPluginPostgreSqlDaoTest.java @@ -22,7 +22,7 @@ * THE SOFTWARE. */ -package org.jenkinsci.plugins.pipeline.maven.dao; +package org.jenkinsci.plugins.pipeline.maven.db; import org.h2.jdbcx.JdbcConnectionPool; import org.jenkinsci.plugins.pipeline.maven.db.migration.MigrationStep; diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/util/ClassUtilsTest.java b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/util/ClassUtilsTest.java similarity index 72% rename from jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/util/ClassUtilsTest.java rename to pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/util/ClassUtilsTest.java index 2580b92a..481fcb6f 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/util/ClassUtilsTest.java +++ b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/util/ClassUtilsTest.java @@ -1,7 +1,7 @@ -package org.jenkinsci.plugins.pipeline.maven.util; +package org.jenkinsci.plugins.pipeline.maven.db.util; import static org.assertj.core.api.Assertions.assertThat; -import static org.jenkinsci.plugins.pipeline.maven.util.ClassUtils.getResourceAsStream; +import static org.jenkinsci.plugins.pipeline.maven.db.util.ClassUtils.getResourceAsStream; import org.junit.jupiter.api.Test; diff --git a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/util/SqlTestsUtils.java b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/util/SqlTestsUtils.java similarity index 96% rename from jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/util/SqlTestsUtils.java rename to pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/util/SqlTestsUtils.java index 8b23fdf6..2c5734bd 100644 --- a/jenkins-plugin/src/test/java/org/jenkinsci/plugins/pipeline/maven/util/SqlTestsUtils.java +++ b/pipeline-maven-database/src/test/java/org/jenkinsci/plugins/pipeline/maven/db/util/SqlTestsUtils.java @@ -1,8 +1,10 @@ -package org.jenkinsci.plugins.pipeline.maven.util; +package org.jenkinsci.plugins.pipeline.maven.db.util; import org.h2.api.ErrorCode; import edu.umd.cs.findbugs.annotations.NonNull; +import org.jenkinsci.plugins.pipeline.maven.db.util.RuntimeSqlException; + import javax.sql.DataSource; import static java.util.Optional.ofNullable; diff --git a/jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/util/classutils-test-1.txt b/pipeline-maven-database/src/test/resources/org/jenkinsci/plugins/pipeline/maven/util/classutils-test-1.txt similarity index 100% rename from jenkins-plugin/src/test/resources/org/jenkinsci/plugins/pipeline/maven/util/classutils-test-1.txt rename to pipeline-maven-database/src/test/resources/org/jenkinsci/plugins/pipeline/maven/util/classutils-test-1.txt diff --git a/pom.xml b/pom.xml index c97d6be3..febc6fa5 100644 --- a/pom.xml +++ b/pom.xml @@ -72,6 +72,8 @@ + pipeline-maven-api + pipeline-maven-database maven-spy jenkins-plugin @@ -102,9 +104,10 @@ 2102.v854b_fec19c92 2.361.4 5.10.0 - 1.4.11 + 3.3.9 0.3.5 3.3.0 + 3.4.2 3.8.8 3.5.1 2.0.7 @@ -114,6 +117,34 @@ + io.jenkins.tools.bom + bom-2.361.x + ${jenkins-tools-bom.version} + pom + import + + + + + + + org.apache.maven + maven-artifact + ${maven.version} + + + org.apache.maven + maven-core + ${maven-compat.version} + + + org.codehaus.plexus + plexus-utils + ${plexus-utils.version} + + org.junit junit-bom ${junit.version} @@ -126,13 +157,32 @@ slf4j-api ${slf4j.version} + + org.slf4j + slf4j-simple + ${slf4j.version} + + + org.jenkins-ci.plugins + pipeline-maven-api + ${project.version} + org.assertj assertj-core ${assertj.version} test + + + org.testcontainers + testcontainers-bom + ${testcontainers.version} + pom + import + +