mirror of
https://github.com/scm-manager/scm-manager.git
synced 2025-10-26 08:06:09 +01:00
Implemented serve task for development mode
This commit is contained in:
committed by
René Pfeuffer
parent
6430c811e2
commit
fa7edc55b2
@@ -29,8 +29,11 @@ plugins {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(gradleApi())
|
||||
implementation gradleApi()
|
||||
implementation 'com.google.guava:guava:30.0-jre'
|
||||
implementation 'com.github.node-gradle:gradle-node-plugin:2.2.4'
|
||||
implementation 'org.eclipse.jetty:jetty-server:9.4.35.v20201120'
|
||||
implementation 'org.eclipse.jetty:jetty-webapp:9.4.35.v20201120'
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
@@ -40,6 +43,10 @@ gradlePlugin {
|
||||
id = 'org.scm-manager.core-plugins'
|
||||
implementationClass = 'com.cloudogu.scm.CorePluginsGradlePlugin'
|
||||
}
|
||||
serve {
|
||||
id = 'org.scm-manager.serve'
|
||||
implementationClass = 'com.cloudogu.scm.ServePlugin'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,4 +54,7 @@ repositories {
|
||||
maven {
|
||||
url "https://packages.scm-manager.org/repository/public/"
|
||||
}
|
||||
maven {
|
||||
url 'https://plugins.gradle.org/m2/'
|
||||
}
|
||||
}
|
||||
140
build-plugins/src/main/groovy/com/cloudogu/scm/ScmServer.groovy
Normal file
140
build-plugins/src/main/groovy/com/cloudogu/scm/ScmServer.groovy
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 com.cloudogu.scm
|
||||
|
||||
import com.google.common.base.Strings
|
||||
import groovy.json.JsonSlurper
|
||||
import org.eclipse.jetty.server.HttpConfiguration
|
||||
import org.eclipse.jetty.server.HttpConnectionFactory
|
||||
import org.eclipse.jetty.server.Server
|
||||
import org.eclipse.jetty.server.ServerConnector
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle
|
||||
import org.eclipse.jetty.util.component.LifeCycle
|
||||
import org.eclipse.jetty.webapp.WebAppContext
|
||||
|
||||
import java.awt.Desktop
|
||||
|
||||
public class ScmServer {
|
||||
|
||||
def configuration
|
||||
private Server server
|
||||
|
||||
private ScmServer(def configuration) {
|
||||
this.configuration = configuration
|
||||
}
|
||||
|
||||
void start() throws Exception {
|
||||
info('start scm-server at port %s', configuration.port)
|
||||
|
||||
System.setProperty('scm.home', configuration.home)
|
||||
if (configuration.disableCorePlugins) {
|
||||
info('disable core plugin extraction')
|
||||
System.setProperty('sonia.scm.boot.disable-core-plugin-extraction', 'true')
|
||||
}
|
||||
|
||||
if (!Strings.isNullOrEmpty(configuration.loggingConfiguration)) {
|
||||
System.setProperty('logback.configurationFile', configuration.loggingConfiguration);
|
||||
}
|
||||
|
||||
info('set stage %s', configuration.stage)
|
||||
System.setProperty('scm.stage', configuration.stage)
|
||||
|
||||
server = new Server()
|
||||
server.addConnector(createServerConnector(server))
|
||||
server.setHandler(createScmContext())
|
||||
server.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() {
|
||||
@Override
|
||||
void lifeCycleStarted(LifeCycle event) {
|
||||
|
||||
String endpoint = String.format('http://localhost:%d%s', configuration.port, configuration.contextPath)
|
||||
|
||||
System.out.println()
|
||||
System.out.println('==> scm-server started successfully and is accessible at:')
|
||||
System.out.append('==> ').println(endpoint)
|
||||
System.out.println()
|
||||
|
||||
if (configuration.openBrowser) {
|
||||
openBrowser(endpoint)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
server.start()
|
||||
}
|
||||
|
||||
private static void openBrowser(String endpoint) {
|
||||
try {
|
||||
Desktop desktop = Desktop.getDesktop()
|
||||
desktop.browse(URI.create(endpoint))
|
||||
} catch (IOException | URISyntaxException ex) {
|
||||
warn('could not open browser', ex)
|
||||
}
|
||||
}
|
||||
|
||||
private static void info(String message, Object... args) {
|
||||
log('INFO', message, args)
|
||||
}
|
||||
|
||||
private static void warn(String message, Exception exception) {
|
||||
log('WARN', message)
|
||||
exception.printStackTrace(System.out)
|
||||
}
|
||||
|
||||
private static void log(String level, String template, Object... args) {
|
||||
System.out.println("[${level}] " + String.format(template, args))
|
||||
}
|
||||
|
||||
private WebAppContext createScmContext() {
|
||||
WebAppContext warContext = new WebAppContext()
|
||||
|
||||
warContext.setContextPath(configuration.contextPath)
|
||||
warContext.setExtractWAR(true)
|
||||
warContext.setWar(configuration.warFile)
|
||||
|
||||
return warContext
|
||||
}
|
||||
|
||||
private ServerConnector createServerConnector(Server server) throws MalformedURLException {
|
||||
ServerConnector connector = new ServerConnector(server)
|
||||
HttpConfiguration cfg = new HttpConfiguration()
|
||||
|
||||
cfg.setRequestHeaderSize(configuration.headerSize)
|
||||
cfg.setResponseHeaderSize(configuration.headerSize)
|
||||
|
||||
connector.setConnectionFactories([new HttpConnectionFactory(cfg)])
|
||||
connector.setPort(configuration.port)
|
||||
|
||||
return connector
|
||||
}
|
||||
|
||||
static void main(String[] args) {
|
||||
String configurationPath = args[0]
|
||||
JsonSlurper slurper = new JsonSlurper()
|
||||
def configuration = slurper.parse(new File(configurationPath))
|
||||
ScmServer server = new ScmServer(configuration)
|
||||
server.start()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 com.cloudogu.scm
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import com.moowork.gradle.node.NodeExtension
|
||||
|
||||
|
||||
class ServePlugin implements Plugin<Project> {
|
||||
|
||||
void apply(Project project) {
|
||||
project.plugins.apply("com.github.node-gradle.node")
|
||||
def nodeExt = NodeExtension.get(project)
|
||||
nodeExt.setDownload(true)
|
||||
nodeExt.setVersion('14.15.1')
|
||||
nodeExt.setYarnVersion('1.22.5')
|
||||
nodeExt.setNodeModulesDir( project.rootProject.projectDir )
|
||||
|
||||
project.tasks.register('write-server-config', WriteServerConfigTask)
|
||||
project.tasks.register("serve", ServeTask) {
|
||||
dependsOn 'write-server-config', 'yarnSetup'
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 com.cloudogu.scm
|
||||
|
||||
import com.moowork.gradle.node.yarn.YarnTask
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.api.tasks.Nested
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
|
||||
class ServeTask extends DefaultTask {
|
||||
|
||||
@TaskAction
|
||||
void exec() {
|
||||
List<Closure<Void>> actions = new ArrayList<>();
|
||||
actions.add(createBackend())
|
||||
actions.add(createFrontend())
|
||||
|
||||
def threads = start(actions)
|
||||
wait(threads)
|
||||
}
|
||||
|
||||
private static void wait(List<Thread> threads) {
|
||||
for (Thread thread : threads) {
|
||||
thread.join()
|
||||
}
|
||||
}
|
||||
|
||||
private static List<Thread> start(List<Closure<Void>> actions) {
|
||||
return actions.collect({ action ->
|
||||
Thread thread = new Thread(action)
|
||||
thread.start()
|
||||
return thread
|
||||
})
|
||||
}
|
||||
|
||||
private Closure<Void> createBackend() {
|
||||
def backend = project.tasks.create('boot-backend', JavaExec) {
|
||||
main ScmServer.class.name
|
||||
args(new File(project.buildDir, 'server/config.json').toString())
|
||||
environment 'NODE_ENV', 'development'
|
||||
classpath project.buildscript.configurations.classpath
|
||||
}
|
||||
return {
|
||||
backend.exec()
|
||||
}
|
||||
}
|
||||
|
||||
private Closure<Void> createFrontend() {
|
||||
def frontend = project.tasks.create('boot-frontend', YarnTask) {
|
||||
args = ['run', 'serve']
|
||||
environment = [
|
||||
'NODE_ENV': 'development'
|
||||
]
|
||||
}
|
||||
return {
|
||||
frontend.exec()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* MIT License
|
||||
*
|
||||
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
|
||||
*
|
||||
* 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 com.cloudogu.scm
|
||||
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.file.Directory
|
||||
import org.gradle.api.file.DirectoryProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.Classpath
|
||||
import org.gradle.api.tasks.InputFile
|
||||
import org.gradle.api.tasks.Internal
|
||||
|
||||
import org.gradle.api.tasks.OutputFile
|
||||
import org.gradle.api.tasks.TaskAction
|
||||
import groovy.xml.MarkupBuilder
|
||||
import java.io.BufferedWriter
|
||||
import org.gradle.api.tasks.Input
|
||||
|
||||
import com.google.common.hash.Hashing
|
||||
import com.google.common.io.Files
|
||||
import groovy.json.JsonOutput
|
||||
|
||||
class WriteServerConfigTask extends DefaultTask {
|
||||
|
||||
@Input
|
||||
public String getHome() {
|
||||
if (project.hasProperty('home')) {
|
||||
return project.getProperty('home')
|
||||
}
|
||||
return new File(project.buildDir, 'scm-home').toString()
|
||||
}
|
||||
|
||||
@Input
|
||||
public int getPort() {
|
||||
if (project.hasProperty('port')) {
|
||||
return Integer.parseInt(project.getProperty('port'))
|
||||
}
|
||||
return 8081
|
||||
}
|
||||
|
||||
@InputFile
|
||||
public File getWarFile() {
|
||||
return new File(project.buildDir, 'libs/scm-webapp-dev.war')
|
||||
}
|
||||
|
||||
@OutputFile
|
||||
public File getServerConfig() {
|
||||
return new File(project.buildDir, 'server/config.json')
|
||||
}
|
||||
|
||||
@TaskAction
|
||||
void execute() {
|
||||
File serverConfig = getServerConfig()
|
||||
serverConfig.getParentFile().mkdirs()
|
||||
serverConfig.text = JsonOutput.toJson([
|
||||
home: getHome(),
|
||||
port: getPort(),
|
||||
contextPath: '/scm',
|
||||
stage: 'DEVELOPMENT',
|
||||
headerSize: 16384,
|
||||
openBrowser: true,
|
||||
warFile: getWarFile().toString()
|
||||
])
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,6 +26,10 @@ plugins {
|
||||
id 'java-platform'
|
||||
}
|
||||
|
||||
task('serve') {
|
||||
dependsOn ':scm-ui:yarn_install', ':scm-webapp:serve'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
constraints {
|
||||
// lombok
|
||||
|
||||
@@ -23,14 +23,14 @@
|
||||
*/
|
||||
|
||||
plugins {
|
||||
id 'com.github.node-gradle.node' version '2.2.4'
|
||||
id 'com.github.node-gradle.node' version '2.2.4'
|
||||
}
|
||||
|
||||
node {
|
||||
download = true
|
||||
version = '14.15.1'
|
||||
yarnVersion = '1.22.5'
|
||||
nodeModulesDir = file('${project.rootProject.projectDir}')
|
||||
nodeModulesDir = file(project.rootProject.projectDir)
|
||||
}
|
||||
|
||||
// TODO define inputs and outputs
|
||||
@@ -50,7 +50,7 @@ task typecheck(type: YarnTask) {
|
||||
doLast {
|
||||
File directory = new File(project.buildDir, 'tmp/typecheck')
|
||||
directory.mkdirs()
|
||||
File marker = new File(directory, "marker")
|
||||
File marker = new File(directory, 'marker')
|
||||
marker.createNewFile()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
plugins {
|
||||
id 'war'
|
||||
id 'org.scm-manager.core-plugins'
|
||||
id 'org.scm-manager.serve'
|
||||
id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.1.6'
|
||||
}
|
||||
|
||||
@@ -144,6 +145,18 @@ war {
|
||||
from project.configurations.assets
|
||||
dependsOn 'copy-core-plugins'
|
||||
}
|
||||
|
||||
// war without assets for development and livereload
|
||||
task 'dev-war' (type: War) {
|
||||
archiveName 'scm-webapp-dev.war'
|
||||
from 'build/war'
|
||||
dependsOn 'copy-core-plugins'
|
||||
}
|
||||
|
||||
serve {
|
||||
dependsOn 'dev-war'
|
||||
}
|
||||
|
||||
/**
|
||||
WTF???
|
||||
|
||||
|
||||
@@ -24,22 +24,19 @@
|
||||
|
||||
rootProject.name = 'scm'
|
||||
|
||||
def includePlugin(String name) {
|
||||
include ":${name}"
|
||||
project(":${name}").projectDir = new File("scm-plugins/${name}")
|
||||
}
|
||||
includeBuild 'build-plugins'
|
||||
include 'scm-annotations'
|
||||
include 'scm-annotation-processor'
|
||||
include 'scm-core'
|
||||
include 'scm-test'
|
||||
include 'scm-ui'
|
||||
include 'scm-plugins:scm-git-plugin'
|
||||
include 'scm-plugins:scm-hg-plugin'
|
||||
include 'scm-plugins:scm-svn-plugin'
|
||||
include 'scm-plugins:scm-legacy-plugin'
|
||||
include 'scm-plugins:scm-integration-test-plugin'
|
||||
include 'scm-dao-xml'
|
||||
include 'scm-webapp'
|
||||
include 'scm-server'
|
||||
|
||||
include('scm-annotations')
|
||||
include('scm-annotation-processor')
|
||||
include('scm-core')
|
||||
include('scm-test')
|
||||
// include('scm-ui')
|
||||
includePlugin('scm-git-plugin')
|
||||
includePlugin('scm-hg-plugin')
|
||||
includePlugin('scm-svn-plugin')
|
||||
includePlugin('scm-legacy-plugin')
|
||||
includePlugin('scm-integration-test-plugin')
|
||||
include('scm-dao-xml')
|
||||
include('scm-webapp')
|
||||
include('scm-server')
|
||||
includeBuild '../gradle-smp-plugin'
|
||||
|
||||
Reference in New Issue
Block a user