Migrate scm-it module to gradle

This commit is contained in:
Sebastian Sdorra
2020-12-23 16:33:35 +01:00
committed by René Pfeuffer
parent 36118c2e2a
commit 3a4a5a9d10
15 changed files with 466 additions and 32 deletions

View File

@@ -51,6 +51,10 @@ gradlePlugin {
id = 'org.scm-manager.serve'
implementationClass = 'com.cloudogu.scm.ServePlugin'
}
integrationTest {
id = 'org.scm-manager.integration-tests'
implementationClass = 'com.cloudogu.scm.IntegrationTestPlugin'
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* 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
class IntegrationTestPlugin implements Plugin<Project> {
void apply(Project project) {
def extension = project.extensions.create("scmServer", ScmServerExtension, project)
project.tasks.register('write-server-config', WriteServerConfigTask) {
it.extension = extension
}
project.tasks.register("startScmServer", ServeTask) {
it.extension = extension
it.waitForCompletion = false
it.frontend = false
dependsOn 'write-server-config'
}
project.tasks.register("stopScmServer", StopScmServer) {
it.extension = extension
}
}
}

View File

@@ -33,6 +33,9 @@ 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 org.eclipse.jetty.server.Handler
import org.eclipse.jetty.server.handler.HandlerList
import org.eclipse.jetty.server.handler.ShutdownHandler
import java.awt.Desktop
@@ -61,12 +64,20 @@ public class ScmServer {
info('set stage %s', configuration.stage)
System.setProperty('scm.stage', configuration.stage)
if (!Strings.isNullOrEmpty(configuration.livereloadUrl)) {
info('set livereload url', configuration.livereloadUrl)
System.setProperty('sonia.scm.ui.proxy', configuration.livereloadUrl)
}
server = new Server()
server.addConnector(createServerConnector(server))
server.setHandler(createScmContext())
HandlerList handlerList = new HandlerList()
handlerList.setHandlers([
createScmContext(),
createShutdownHandler()
] as Handler[])
server.setHandler(handlerList)
server.addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() {
@Override
void lifeCycleStarted(LifeCycle event) {
@@ -119,6 +130,10 @@ public class ScmServer {
return warContext
}
private ShutdownHandler createShutdownHandler() {
return new ShutdownHandler("_shutdown_", true, false)
}
private ServerConnector createServerConnector(Server server) throws MalformedURLException {
ServerConnector connector = new ServerConnector(server)
HttpConfiguration cfg = new HttpConfiguration()

View File

@@ -0,0 +1,105 @@
/*
* 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.artifacts.Configuration
import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.Classpath
import org.gradle.api.tasks.InputFile
import org.gradle.api.tasks.Input
import org.gradle.api.Project
class ScmServerExtension implements Serializable {
private Project project
private Configuration configuration
private boolean openBrowser = true
private boolean liveReload = true
private File warFile
ScmServerExtension(Project project) {
this.project = project
}
@Input
public boolean isOpenBrowser() {
return openBrowser
}
public void setOpenBrowser(boolean openBrowser) {
this.openBrowser = openBrowser
}
@Input
public boolean isLiveReload() {
return liveReload
}
public void setLiveReload(boolean liveReload) {
this.liveReload = liveReload
}
@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
}
@Optional
@InputFile
public File getWarFile() {
return warFile
}
public void setWarFile(File warFile) {
this.warFile = warFile
}
@Optional
@Classpath
Configuration getConfiguration() {
return configuration
}
void setConfiguration(Configuration configuration) {
this.configuration = configuration
}
void configuration(String configuration) {
setConfiguration(project.configurations.getByName(configuration))
}
}

View File

@@ -33,6 +33,8 @@ import com.moowork.gradle.node.NodeExtension
class ServePlugin implements Plugin<Project> {
void apply(Project project) {
def extension = project.extensions.create("scmServer", ScmServerExtension, project)
project.plugins.apply("com.github.node-gradle.node")
def nodeExt = NodeExtension.get(project)
nodeExt.setDownload(true)
@@ -40,8 +42,11 @@ class ServePlugin implements Plugin<Project> {
nodeExt.setYarnVersion('1.22.5')
nodeExt.setNodeModulesDir( project.rootProject.projectDir )
project.tasks.register('write-server-config', WriteServerConfigTask)
project.tasks.register('write-server-config', WriteServerConfigTask) {
it.extension = extension
}
project.tasks.register("serve", ServeTask) {
it.extension = extension
dependsOn 'write-server-config', 'yarnSetup'
}
}

View File

@@ -29,18 +29,72 @@ 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.Input
import org.gradle.api.tasks.TaskAction
import org.gradle.api.GradleException
class ServeTask extends DefaultTask {
private boolean frontend = true
private boolean waitForCompletion = true
private ScmServerExtension extension
@Nested
ScmServerExtension getExtension() {
return extension
}
void setExtension(ScmServerExtension extension) {
this.extension = extension
}
@Input
boolean isFrontend() {
return frontend
}
void setFrontend(boolean frontend) {
this.frontend = frontend
}
@Input
boolean isWaitForCompletion() {
return waitForCompletion
}
void setWaitForCompletion(boolean waitForCompletion) {
this.waitForCompletion = waitForCompletion
}
@TaskAction
void exec() {
List<Closure<Void>> actions = new ArrayList<>();
actions.add(createBackend())
if (frontend) {
actions.add(createFrontend())
}
def threads = start(actions)
if (waitForCompletion) {
wait(threads)
} else {
waitForPortToBeOpen()
}
}
private void waitForPortToBeOpen() {
int retries = 180
for (int i=0; i<retries; i++) {
try {
URL urlConnect = new URL("http://localhost:${extension.port}/scm/api/v2");
URLConnection conn = (HttpURLConnection) urlConnect.openConnection();
if (conn.getResponseCode() == 200) {
return
}
} catch (IOException ex) {
Thread.sleep(500)
}
}
throw new GradleException("scm-server not reachable")
}
private static void wait(List<Thread> threads) {

View File

@@ -0,0 +1,58 @@
/*
* 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.tasks.Nested
import org.gradle.api.tasks.TaskAction
class StopScmServer extends DefaultTask {
private ScmServerExtension extension
@Nested
ScmServerExtension getExtension() {
return extension
}
void setExtension(ScmServerExtension extension) {
this.extension = extension
}
@TaskAction
void exec() {
URL url = new URL("http://localhost:${extension.port}/shutdown?token=_shutdown_")
try {
HttpURLConnection connection = (HttpURLConnection )url.openConnection()
connection.setRequestMethod("POST")
// ???
connection.getResponseCode()
} catch (IOException ex) {
// already closed ?
}
}
}

View File

@@ -33,8 +33,9 @@ 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.Nested
import org.gradle.api.tasks.Internal
import org.gradle.api.GradleException
import org.gradle.api.tasks.OutputFile
import org.gradle.api.tasks.TaskAction
@@ -48,25 +49,15 @@ 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()
private ScmServerExtension extension
@Nested
ScmServerExtension getExtension() {
return extension
}
@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')
void setExtension(ScmServerExtension extension) {
this.extension = extension
}
@OutputFile
@@ -76,17 +67,37 @@ class WriteServerConfigTask extends DefaultTask {
@TaskAction
void execute() {
File warFile = extension.getWarFile()
if (warFile == null) {
Configuration configuration = extension.getConfiguration()
if (configuration == null) {
throw new GradleException("warFile or configuration must be used")
}
def artificat = configuration.resolvedConfiguration
.resolvedArtifacts
.find {
it.extension == 'war'
}
if (artificat == null) {
throw new GradleException("could not find war file in configuration")
}
warFile = artificat.getFile()
}
File serverConfig = getServerConfig()
serverConfig.getParentFile().mkdirs()
serverConfig.text = JsonOutput.toJson([
home: getHome(),
port: getPort(),
home: extension.getHome(),
port: extension.getPort(),
contextPath: '/scm',
stage: 'DEVELOPMENT',
headerSize: 16384,
openBrowser: true,
warFile: getWarFile().toString(),
livereloadUrl: 'http://localhost:3000'
openBrowser: extension.openBrowser,
warFile: warFile.toString(),
livereloadUrl: extension.liveReload ? 'http://localhost:3000' : null
])
}

View File

@@ -22,4 +22,4 @@
# SOFTWARE.
#
version=2.3.0-SNAPSHOT
version=2.13.0-SNAPSHOT

74
scm-it/build.gradle Normal file
View File

@@ -0,0 +1,74 @@
/*
* 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.
*/
plugins {
id 'java-library'
id 'org.scm-manager.integration-tests'
}
configurations {
itWebApp
}
dependencies {
testImplementation platform(project(':'))
testImplementation project(':scm-core')
testImplementation project(':scm-test')
// TODO add tests
testImplementation project(':scm-plugins:scm-git-plugin')
testImplementation project(path: ':scm-plugins:scm-git-plugin', configuration: 'tests')
testImplementation project(':scm-plugins:scm-hg-plugin')
testImplementation project(path: ':scm-plugins:scm-hg-plugin', configuration: 'tests')
testImplementation project(':scm-plugins:scm-svn-plugin')
testImplementation project(path: ':scm-plugins:scm-svn-plugin', configuration: 'tests')
testImplementation 'io.rest-assured:rest-assured:4.3.0'
testImplementation 'org.glassfish:javax.json:1.1.4'
itWebApp project(path: ':scm-webapp', configuration: 'webapp')
}
scmServer {
configuration 'itWebApp'
openBrowser = false
liveReload = false
}
test {
include '**/*Test.class'
exclude '**/*ITCase.class'
}
task integrationTest(type: Test) {
include '**/*ITCase.class'
exclude '**/*Test.class'
dependsOn 'test'
doFirst {
tasks.getByName('startScmServer').exec()
}
finalizedBy 'stopScmServer'
}

View File

@@ -28,7 +28,8 @@ plugins {
}
dependencies {
implementation 'sonia.jgit:org.eclipse.jgit:5.6.1.202002131546-r-scm1'
// required by scm-it
api 'sonia.jgit:org.eclipse.jgit:5.6.1.202002131546-r-scm1'
implementation 'sonia.jgit:org.eclipse.jgit.http.server:5.6.1.202002131546-r-scm1'
implementation 'sonia.jgit:org.eclipse.jgit.lfs.server:5.6.1.202002131546-r-scm1'
@@ -51,3 +52,19 @@ scmPlugin {
}
}
task testJar(type: Jar) {
classifier = 'tests'
from sourceSets.test.output
}
configurations {
tests {
canBeConsumed = true
canBeResolved = false
}
}
artifacts {
tests(testJar)
}

View File

@@ -52,3 +52,19 @@ scmPlugin {
}
}
task testJar(type: Jar) {
classifier = 'tests'
from sourceSets.test.output
}
configurations {
tests {
canBeConsumed = true
canBeResolved = false
}
}
artifacts {
tests(testJar)
}

View File

@@ -52,6 +52,22 @@ scmPlugin {
}
task testJar(type: Jar) {
classifier = 'tests'
from sourceSets.test.output
}
configurations {
tests {
canBeConsumed = true
canBeResolved = false
}
}
artifacts {
tests(testJar)
}
/*
<!--
SCMSvnDiffGenerator is a copy of an internal SVNKit class, with small changes for SCM-Manger.

View File

@@ -161,6 +161,12 @@ task 'dev-war' (type: War) {
dependsOn 'copy-core-plugins'
}
scmServer {
liveReload = true
openBrowser = true
warFile = file('build/libs/scm-webapp-dev.war')
}
serve {
dependsOn 'dev-war'
}

View File

@@ -44,5 +44,6 @@ include 'scm-packaging:deb'
include 'scm-packaging:rpm'
include 'scm-packaging:docker'
include 'scm-packaging:helm'
include 'scm-it'
includeBuild '../gradle-smp-plugin'