mirror of
				https://github.com/gitbucket/gitbucket.git
				synced 2025-10-31 18:46:28 +01:00 
			
		
		
		
	Make CLI options configurable via environmental variables (#2408)
This commit is contained in:
		| @@ -16,12 +16,17 @@ public class JettyLauncher { | |||||||
|         System.setProperty("java.awt.headless", "true"); |         System.setProperty("java.awt.headless", "true"); | ||||||
|  |  | ||||||
|         String host = null; |         String host = null; | ||||||
|         int port = 8080; |         String port = null; | ||||||
|         InetSocketAddress address = null; |         InetSocketAddress address = null; | ||||||
|         String contextPath = "/"; |         String contextPath = "/"; | ||||||
|         String tmpDirPath=""; |         String tmpDirPath=""; | ||||||
|         boolean forceHttps = false; |         boolean forceHttps = false; | ||||||
|  |  | ||||||
|  |         host = getEnvironmentVariable("gitbucket.host"); | ||||||
|  |         port = getEnvironmentVariable("gitbucket.port"); | ||||||
|  |         contextPath = getEnvironmentVariable("gitbucket.prefix"); | ||||||
|  |         tmpDirPath = getEnvironmentVariable("gitbucket.tempDir"); | ||||||
|  |  | ||||||
|         for(String arg: args) { |         for(String arg: args) { | ||||||
|             if(arg.startsWith("--") && arg.contains("=")) { |             if(arg.startsWith("--") && arg.contains("=")) { | ||||||
|                 String[] dim = arg.split("="); |                 String[] dim = arg.split("="); | ||||||
| @@ -31,13 +36,10 @@ public class JettyLauncher { | |||||||
|                             host = dim[1]; |                             host = dim[1]; | ||||||
|                             break; |                             break; | ||||||
|                         case "--port": |                         case "--port": | ||||||
|                             port = Integer.parseInt(dim[1]); |                             port = dim[1]; | ||||||
|                             break; |                             break; | ||||||
|                         case "--prefix": |                         case "--prefix": | ||||||
|                             contextPath = dim[1]; |                             contextPath = dim[1]; | ||||||
|                             if (!contextPath.startsWith("/")) { |  | ||||||
|                                 contextPath = "/" + contextPath; |  | ||||||
|                             } |  | ||||||
|                             break; |                             break; | ||||||
|                         case "--max_file_size": |                         case "--max_file_size": | ||||||
|                             System.setProperty("gitbucket.maxFileSize", dim[1]); |                             System.setProperty("gitbucket.maxFileSize", dim[1]); | ||||||
| @@ -62,10 +64,14 @@ public class JettyLauncher { | |||||||
|             } |             } | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  |         if (contextPath != null && !contextPath.startsWith("/")) { | ||||||
|  |             contextPath = "/" + contextPath; | ||||||
|  |         } | ||||||
|  |  | ||||||
|         if(host != null) { |         if(host != null) { | ||||||
|             address = new InetSocketAddress(host, port); |             address = new InetSocketAddress(host, getPort(port)); | ||||||
|         } else { |         } else { | ||||||
|             address = new InetSocketAddress(port); |             address = new InetSocketAddress(getPort(port)); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|         Server server = new Server(address); |         Server server = new Server(address); | ||||||
| @@ -143,6 +149,23 @@ public class JettyLauncher { | |||||||
|         return new File(System.getProperty("user.home"), ".gitbucket"); |         return new File(System.getProperty("user.home"), ".gitbucket"); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     private static String getEnvironmentVariable(String key){ | ||||||
|  |         String value =  System.getenv(key.toUpperCase().replace('.', '_')); | ||||||
|  |         if (value != null && value.length() == 0){ | ||||||
|  |             return null; | ||||||
|  |         } else { | ||||||
|  |             return value; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     private static int getPort(String port){ | ||||||
|  |         if(port == null) { | ||||||
|  |             return 8080; | ||||||
|  |         } else { | ||||||
|  |             return Integer.parseInt(port); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|     private static Handler addStatisticsHandler(Handler handler) { |     private static Handler addStatisticsHandler(Handler handler) { | ||||||
|         // The graceful shutdown is implemented via the statistics handler. |         // The graceful shutdown is implemented via the statistics handler. | ||||||
|         // See the following: https://bugs.eclipse.org/bugs/show_bug.cgi?id=420142 |         // See the following: https://bugs.eclipse.org/bugs/show_bug.cgi?id=420142 | ||||||
|   | |||||||
| @@ -15,7 +15,7 @@ import gitbucket.core.service.ProtectedBranchService.ProtectedBranchReceiveHook | |||||||
| import gitbucket.core.service.RepositoryService.RepositoryInfo | import gitbucket.core.service.RepositoryService.RepositoryInfo | ||||||
| import gitbucket.core.service.SystemSettingsService | import gitbucket.core.service.SystemSettingsService | ||||||
| import gitbucket.core.service.SystemSettingsService.SystemSettings | import gitbucket.core.service.SystemSettingsService.SystemSettings | ||||||
| import gitbucket.core.util.DatabaseConfig | import gitbucket.core.util.{ConfigUtil, DatabaseConfig} | ||||||
| import gitbucket.core.util.Directory._ | import gitbucket.core.util.Directory._ | ||||||
| import io.github.gitbucket.solidbase.Solidbase | import io.github.gitbucket.solidbase.Solidbase | ||||||
| import io.github.gitbucket.solidbase.manager.JDBCVersionManager | import io.github.gitbucket.solidbase.manager.JDBCVersionManager | ||||||
| @@ -235,7 +235,7 @@ object PluginRegistry { | |||||||
|       .reverse |       .reverse | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   lazy val extraPluginDir: Option[String] = Option(System.getProperty("gitbucket.pluginDir")) |   lazy val extraPluginDir: Option[String] = ConfigUtil.getConfigValue[String]("gitbucket.pluginDir") | ||||||
|  |  | ||||||
|   def getGitBucketVersion(pluginJarFileName: String): Option[String] = { |   def getGitBucketVersion(pluginJarFileName: String): Option[String] = { | ||||||
|     val regex = ".+-gitbucket\\_(\\d+\\.\\d+\\.\\d+(-SNAPSHOT)?)-.+".r |     val regex = ".+-gitbucket\\_(\\d+\\.\\d+\\.\\d+(-SNAPSHOT)?)-.+".r | ||||||
|   | |||||||
| @@ -305,7 +305,7 @@ object SystemSettingsService { | |||||||
|   private val PluginProxyPassword = "plugin.proxy.password" |   private val PluginProxyPassword = "plugin.proxy.password" | ||||||
|  |  | ||||||
|   private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = { |   private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = { | ||||||
|     getSystemProperty(key).getOrElse(getEnvironmentVariable(key).getOrElse { |     getConfigValue(key).getOrElse { | ||||||
|       defining(props.getProperty(key)) { value => |       defining(props.getProperty(key)) { value => | ||||||
|         if (value == null || value.isEmpty) { |         if (value == null || value.isEmpty) { | ||||||
|           default |           default | ||||||
| @@ -313,11 +313,11 @@ object SystemSettingsService { | |||||||
|           convertType(value).asInstanceOf[A] |           convertType(value).asInstanceOf[A] | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }) |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private def getOptionValue[A: ClassTag](props: java.util.Properties, key: String, default: Option[A]): Option[A] = { |   private def getOptionValue[A: ClassTag](props: java.util.Properties, key: String, default: Option[A]): Option[A] = { | ||||||
|     getSystemProperty(key).orElse(getEnvironmentVariable(key).orElse { |     getConfigValue(key).orElse { | ||||||
|       defining(props.getProperty(key)) { value => |       defining(props.getProperty(key)) { value => | ||||||
|         if (value == null || value.isEmpty) { |         if (value == null || value.isEmpty) { | ||||||
|           default |           default | ||||||
| @@ -325,7 +325,7 @@ object SystemSettingsService { | |||||||
|           Some(convertType(value)).asInstanceOf[Option[A]] |           Some(convertType(value)).asInstanceOf[Option[A]] | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }) |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										41
									
								
								src/main/scala/gitbucket/core/util/ConfigUtil.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/main/scala/gitbucket/core/util/ConfigUtil.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | |||||||
|  | package gitbucket.core.util | ||||||
|  |  | ||||||
|  | import gitbucket.core.util.SyntaxSugars.defining | ||||||
|  |  | ||||||
|  | import scala.reflect.ClassTag | ||||||
|  |  | ||||||
|  | object ConfigUtil { | ||||||
|  |  | ||||||
|  |   def getConfigValue[A: ClassTag](key: String): Option[A] = { | ||||||
|  |     getSystemProperty(key).orElse(getEnvironmentVariable(key)) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def getEnvironmentVariable[A: ClassTag](key: String): Option[A] = { | ||||||
|  |     val name = (if (key.startsWith("gitbucket.")) "" else "GITBUCKET_") + key.toUpperCase.replace('.', '_') | ||||||
|  |     val value = System.getenv(name) | ||||||
|  |     if (value != null && value.nonEmpty) { | ||||||
|  |       Some(convertType(value)) | ||||||
|  |     } else { | ||||||
|  |       None | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def getSystemProperty[A: ClassTag](key: String): Option[A] = { | ||||||
|  |     val name = if (key.startsWith("gitbucket.")) key else "gitbucket." + key | ||||||
|  |     val value = System.getProperty(name) | ||||||
|  |     if (value != null && value.nonEmpty) { | ||||||
|  |       Some(convertType(value)) | ||||||
|  |     } else { | ||||||
|  |       None | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   def convertType[A: ClassTag](value: String): A = | ||||||
|  |     defining(implicitly[ClassTag[A]].runtimeClass) { c => | ||||||
|  |       if (c == classOf[Boolean]) value.toBoolean | ||||||
|  |       else if (c == classOf[Long]) value.toLong | ||||||
|  |       else if (c == classOf[Int]) value.toInt | ||||||
|  |       else value | ||||||
|  |     }.asInstanceOf[A] | ||||||
|  |  | ||||||
|  | } | ||||||
| @@ -6,7 +6,6 @@ import java.io.File | |||||||
| import Directory._ | import Directory._ | ||||||
| import ConfigUtil._ | import ConfigUtil._ | ||||||
| import com.github.takezoe.slick.blocking.{BlockingH2Driver, BlockingJdbcProfile, BlockingMySQLDriver} | import com.github.takezoe.slick.blocking.{BlockingH2Driver, BlockingJdbcProfile, BlockingMySQLDriver} | ||||||
| import gitbucket.core.util.SyntaxSugars.defining |  | ||||||
| import liquibase.database.AbstractJdbcDatabase | import liquibase.database.AbstractJdbcDatabase | ||||||
| import liquibase.database.core.{H2Database, MySQLDatabase, PostgresDatabase} | import liquibase.database.core.{H2Database, MySQLDatabase, PostgresDatabase} | ||||||
| import org.apache.commons.io.FileUtils | import org.apache.commons.io.FileUtils | ||||||
| @@ -54,16 +53,14 @@ object DatabaseConfig { | |||||||
|   lazy val minimumIdle: Option[Int] = getOptionValue("db.minimumIdle", config.getInt) |   lazy val minimumIdle: Option[Int] = getOptionValue("db.minimumIdle", config.getInt) | ||||||
|   lazy val maximumPoolSize: Option[Int] = getOptionValue("db.maximumPoolSize", config.getInt) |   lazy val maximumPoolSize: Option[Int] = getOptionValue("db.maximumPoolSize", config.getInt) | ||||||
|  |  | ||||||
|   private def getValue[T](path: String, f: String => T): T = { |   private def getValue[T: ClassTag](path: String, f: String => T): T = { | ||||||
|     getSystemProperty(path).getOrElse(getEnvironmentVariable(path).getOrElse { |     getConfigValue(path).getOrElse(f(path)) | ||||||
|       f(path) |  | ||||||
|     }) |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   private def getOptionValue[T](path: String, f: String => T): Option[T] = { |   private def getOptionValue[T: ClassTag](path: String, f: String => T): Option[T] = { | ||||||
|     getSystemProperty(path).orElse(getEnvironmentVariable(path).orElse { |     getConfigValue(path).orElse { | ||||||
|       if (config.hasPath(path)) Some(f(path)) else None |       if (config.hasPath(path)) Some(f(path)) else None | ||||||
|     }) |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| } | } | ||||||
| @@ -114,33 +111,3 @@ object DatabaseType { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| object ConfigUtil { |  | ||||||
|  |  | ||||||
|   def getEnvironmentVariable[A](key: String): Option[A] = { |  | ||||||
|     val value = System.getenv("GITBUCKET_" + key.toUpperCase.replace('.', '_')) |  | ||||||
|     if (value != null && value.nonEmpty) { |  | ||||||
|       Some(convertType(value)).asInstanceOf[Option[A]] |  | ||||||
|     } else { |  | ||||||
|       None |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   def getSystemProperty[A](key: String): Option[A] = { |  | ||||||
|     val value = System.getProperty("gitbucket." + key) |  | ||||||
|     if (value != null && value.nonEmpty) { |  | ||||||
|       Some(convertType(value)).asInstanceOf[Option[A]] |  | ||||||
|     } else { |  | ||||||
|       None |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   def convertType[A: ClassTag](value: String) = |  | ||||||
|     defining(implicitly[ClassTag[A]].runtimeClass) { c => |  | ||||||
|       if (c == classOf[Boolean]) value.toBoolean |  | ||||||
|       else if (c == classOf[Long]) value.toLong |  | ||||||
|       else if (c == classOf[Int]) value.toInt |  | ||||||
|       else value |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -92,16 +92,12 @@ object FileUtil { | |||||||
|     name |     name | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   lazy val MaxFileSize = |   lazy val MaxFileSize: Long = { | ||||||
|     if (System.getProperty("gitbucket.maxFileSize") != null) |     ConfigUtil.getConfigValue[Long]("gitbucket.maxFileSize").getOrElse(3 * 1024 * 1024) | ||||||
|       System.getProperty("gitbucket.maxFileSize").toLong |   } | ||||||
|     else |  | ||||||
|       3 * 1024 * 1024 |  | ||||||
|  |  | ||||||
|   lazy val UploadTimeout = |   lazy val UploadTimeout: Long = { | ||||||
|     if (System.getProperty("gitbucket.UploadTimeout") != null) |     ConfigUtil.getConfigValue[Long]("gitbucket.UploadTimeout").getOrElse(3 * 10000) | ||||||
|       System.getProperty("gitbucket.UploadTimeout").toLong |   } | ||||||
|     else |  | ||||||
|       3 * 10000 |  | ||||||
|  |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -8,7 +8,7 @@ trait Validations { | |||||||
|   /** |   /** | ||||||
|    * Constraint for the identifier such as user name or page name. |    * Constraint for the identifier such as user name or page name. | ||||||
|    */ |    */ | ||||||
|   def identifier: Constraint = new Constraint() { |   val identifier: Constraint = new Constraint() { | ||||||
|     override def validate(name: String, value: String, messages: Messages): Option[String] = |     override def validate(name: String, value: String, messages: Messages): Option[String] = | ||||||
|       if (!value.matches("[a-zA-Z0-9\\-_.]+")) { |       if (!value.matches("[a-zA-Z0-9\\-_.]+")) { | ||||||
|         Some(s"${name} contains invalid character.") |         Some(s"${name} contains invalid character.") | ||||||
| @@ -22,19 +22,22 @@ trait Validations { | |||||||
|   /** |   /** | ||||||
|    * Constraint for the password. |    * Constraint for the password. | ||||||
|    */ |    */ | ||||||
|   def password: Constraint = new Constraint() { |   val password: Constraint = new Constraint() { | ||||||
|     override def validate(name: String, value: String, messages: Messages): Option[String] = |     lazy val validatePassword = ConfigUtil.getConfigValue[Boolean]("gitbucket.validate.password").getOrElse(true) | ||||||
|       if (System.getProperty("gitbucket.validate.password") != "false" && !value.matches("[a-zA-Z0-9\\-_.]+")) { |  | ||||||
|  |     override def validate(name: String, value: String, messages: Messages): Option[String] = { | ||||||
|  |       if (validatePassword == true && !value.matches("[a-zA-Z0-9\\-_.]+")) { | ||||||
|         Some(s"${name} contains invalid character.") |         Some(s"${name} contains invalid character.") | ||||||
|       } else { |       } else { | ||||||
|         None |         None | ||||||
|       } |       } | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * Constraint for the repository identifier. |    * Constraint for the repository identifier. | ||||||
|    */ |    */ | ||||||
|   def repository: Constraint = new Constraint() { |   val repository: Constraint = new Constraint() { | ||||||
|     override def validate(name: String, value: String, messages: Messages): Option[String] = |     override def validate(name: String, value: String, messages: Messages): Option[String] = | ||||||
|       if (!value.matches("[a-zA-Z0-9\\-\\+_.]+")) { |       if (!value.matches("[a-zA-Z0-9\\-\\+_.]+")) { | ||||||
|         Some(s"${name} contains invalid character.") |         Some(s"${name} contains invalid character.") | ||||||
| @@ -48,7 +51,7 @@ trait Validations { | |||||||
|   /** |   /** | ||||||
|    * Constraint for the color pattern. |    * Constraint for the color pattern. | ||||||
|    */ |    */ | ||||||
|   def color = pattern("#[0-9a-fA-F]{6}") |   val color = pattern("#[0-9a-fA-F]{6}") | ||||||
|  |  | ||||||
|   /** |   /** | ||||||
|    * ValueType for the java.util.Date property. |    * ValueType for the java.util.Date property. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user