FINERACT-1470: Fineract release plugin
This commit is contained in:
committed by
Aleksandar Vidakovic
parent
b185937962
commit
40eb547a5c
@@ -0,0 +1,183 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
|
||||
// Configuration for the dependency management plugin
|
||||
// https://github.com/spring-gradle-plugins/dependency-management-plugin
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom 'org.springframework:spring-framework-bom:5.3.19'
|
||||
mavenBom 'org.springframework.boot:spring-boot-dependencies:2.6.7'
|
||||
mavenBom 'org.jetbrains.kotlin:kotlin-bom:1.6.21'
|
||||
mavenBom 'org.junit:junit-bom:5.8.2'
|
||||
mavenBom 'com.fasterxml.jackson:jackson-bom:2.13.2.1'
|
||||
mavenBom 'io.cucumber:cucumber-bom:7.3.3'
|
||||
mavenBom 'io.netty:netty-bom:4.1.76.Final'
|
||||
mavenBom 'org.mockito:mockito-bom:4.5.1'
|
||||
mavenBom 'io.github.swagger2markup:swagger2markup-bom:1.3.4'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// We use fixed versions, instead of inheriting them from the Spring BOM, to be able to be on more recent ones.
|
||||
// We do not use :+ to get the latest available version available on Maven Central, as that could suddenly break things.
|
||||
// We use the Renovate Bot to automatically propose Pull Requests (PRs) when upgrades for all of these versions are available.
|
||||
|
||||
dependency 'org.slf4j:slf4j-api:1.7.36'
|
||||
dependency 'org.slf4j:slf4j-simple:1.7.36'
|
||||
dependency 'org.slf4j:jcl-over-slf4j:1.7.36'
|
||||
dependency 'org.slf4j:jul-to-slf4j:1.7.36'
|
||||
dependency 'org.slf4j:log4j-over-slf4j:1.7.36'
|
||||
dependency 'ch.qos.logback:logback-core:1.2.11'
|
||||
dependency 'ch.qos.logback:logback-classic:1.2.11'
|
||||
|
||||
dependency 'org.eclipse.persistence:org.eclipse.persistence.jpa:2.7.10'
|
||||
dependency 'com.google.guava:guava:31.1-jre'
|
||||
dependency 'com.google.code.gson:gson:2.9.0'
|
||||
dependency 'com.google.truth:truth:1.1.3'
|
||||
dependency 'com.google.truth.extensions:truth-java8-extension:1.1.3'
|
||||
dependency 'com.google.googlejavaformat:google-java-format:1.15.0'
|
||||
dependency ('org.apache.commons:commons-email:1.5') {
|
||||
exclude 'com.sun.mail:javax.mail'
|
||||
exclude 'javax.activation:activation'
|
||||
}
|
||||
dependency 'commons-io:commons-io:2.11.0'
|
||||
dependency 'com.github.librepdf:openpdf:1.3.27'
|
||||
dependency ('org.mnode.ical4j:ical4j:3.2.2') {
|
||||
exclude 'com.sun.mail:javax.mail'
|
||||
}
|
||||
dependency 'org.quartz-scheduler:quartz:2.3.2'
|
||||
dependency 'com.amazonaws:aws-java-sdk-s3:1.12.210'
|
||||
dependency 'org.ehcache:ehcache:3.10.0'
|
||||
dependency 'com.github.spullara.mustache.java:compiler:0.9.10'
|
||||
dependency 'com.jayway.jsonpath:json-path:2.7.0'
|
||||
dependency 'org.apache.tika:tika-core:2.3.0'
|
||||
dependency 'org.apache.httpcomponents:httpclient:4.5.13'
|
||||
dependency 'jakarta.management.j2ee:jakarta.management.j2ee-api:1.1.4'
|
||||
dependency 'jakarta.jms:jakarta.jms-api:2.0.3'
|
||||
dependency 'org.glassfish.jaxb:jaxb-runtime:2.3.6' // Swagger needs exactly this version
|
||||
dependency 'org.apache.bval:org.apache.bval.bundle:2.0.5'
|
||||
dependency 'joda-time:joda-time:2.10.14'
|
||||
|
||||
dependency 'io.github.classgraph:classgraph:4.8.146'
|
||||
dependency 'org.awaitility:awaitility:4.2.0'
|
||||
dependency 'com.github.spotbugs:spotbugs-annotations:4.6.0'
|
||||
dependency 'javax.cache:cache-api:1.1.1'
|
||||
dependency 'org.mock-server:mockserver-junit-jupiter:5.13.2'
|
||||
dependency 'org.webjars:webjars-locator-core:0.50'
|
||||
dependency 'com.icegreen:greenmail-junit5:1.6.8'
|
||||
dependency 'com.intuit.karate:karate-junit5:1.2.0.RC6'
|
||||
|
||||
// fineract client dependencies
|
||||
dependency "com.squareup.retrofit2:retrofit:2.9.0"
|
||||
dependency "com.squareup.retrofit2:retrofit-mock:2.9.0"
|
||||
dependency "com.squareup.retrofit2:adapter-java8:2.9.0"
|
||||
dependency "com.squareup.retrofit2:adapter-rxjava2:2.9.0"
|
||||
dependency "com.squareup.retrofit2:adapter-rxjava3:2.9.0"
|
||||
dependency "com.squareup.retrofit2:adapter-guava:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-wire:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-jackson:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-simplexml:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-jaxb:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-java8:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-scalars:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-gson:2.9.0"
|
||||
dependency "com.squareup.retrofit2:converter-protobuf:2.9.0"
|
||||
dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.common:1.0.1"
|
||||
dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.client:1.0.1"
|
||||
dependency "org.apache.oltu.oauth2:org.apache.oltu.oauth2.httpclient4:1.0.1"
|
||||
dependency "com.squareup.okhttp3:okhttp:4.9.3"
|
||||
dependency "com.squareup.okhttp3:okcurl:4.9.3"
|
||||
dependency "com.squareup.okhttp3:logging-interceptor:4.9.3"
|
||||
dependency "com.squareup.okhttp3:okhttp-apache:4.9.3"
|
||||
dependency "com.squareup.okhttp3:okhttp-android-support:4.9.3"
|
||||
dependency "com.squareup.okhttp3:okhttp-urlconnection:4.9.3"
|
||||
dependency "com.squareup.okhttp3:okhttp-sse:4.9.3"
|
||||
dependency "io.gsonfire:gson-fire:1.8.5"
|
||||
dependency "com.google.code.findbugs:jsr305:3.0.2"
|
||||
dependency "commons-codec:commons-codec:1.15"
|
||||
dependency "org.projectlombok:lombok:1.18.24"
|
||||
|
||||
dependency 'org.bouncycastle:bcpkix-jdk15to18:1.70'
|
||||
dependency 'org.bouncycastle:bcprov-jdk15to18:1.70'
|
||||
dependency 'org.bouncycastle:bcprov-jdk15on:1.70'
|
||||
dependency 'org.bouncycastle:bcpg-jdk15on:1.70'
|
||||
|
||||
dependency 'org.eclipse.jgit:org.eclipse.jgit:6.1.0.202203080745-r'
|
||||
dependency 'org.eclipse.jgit:org.eclipse.jgit.ssh.apache:6.1.0.202203080745-r'
|
||||
|
||||
dependency 'org.tmatesoft.svnkit:svnkit:1.10.5'
|
||||
dependency 'com.vdurmont:semver4j:3.1.0'
|
||||
dependency 'org.beryx:text-io:3.4.1'
|
||||
|
||||
dependency 'org.springdoc:springdoc-openapi-ui:1.6.8'
|
||||
dependency 'org.springdoc:springdoc-openapi-webmvc-core:1.6.8'
|
||||
dependency 'org.springdoc:springdoc-openapi-common:1.6.8'
|
||||
dependency 'org.springdoc:springdoc-openapi-security:1.6.8'
|
||||
dependency 'org.springdoc:springdoc-openapi-javadoc:1.6.8'
|
||||
|
||||
dependency 'com.google.cloud.sql:mysql-socket-factory-connector-j-8:1.5.0'
|
||||
|
||||
dependency ('org.apache.activemq:activemq-broker:5.17.1') {
|
||||
exclude 'javax.annotation:javax.annotation-api'
|
||||
}
|
||||
|
||||
dependency 'io.swagger:swagger-annotations:1.6.6'
|
||||
dependency 'io.swagger.core.v3:swagger-annotations:2.2.0'
|
||||
dependency ('io.swagger.core.v3:swagger-jaxrs2:2.2.0') {
|
||||
exclude 'jakarta.activation:jakarta.activation-api'
|
||||
}
|
||||
dependency ('io.swagger.core.v3:swagger-core:2.2.0') {
|
||||
exclude 'jakarta.activation:jakarta.activation-api'
|
||||
}
|
||||
|
||||
dependency "jakarta.annotation:jakarta.annotation-api:1.3.5"
|
||||
dependency 'jakarta.activation:jakarta.activation-api:1.2.2'
|
||||
dependency ('com.sun.mail:jakarta.mail:1.6.7') {
|
||||
exclude 'com.sun.activation:jakarta.activation'
|
||||
}
|
||||
dependency ('jakarta.xml.bind:jakarta.xml.bind-api:2.3.3') {
|
||||
exclude 'jakarta.activation:jakarta.activation-api'
|
||||
}
|
||||
|
||||
dependency ('org.liquibase:liquibase-core:4.9.1') {
|
||||
exclude 'javax.xml.bind:jaxb-api'
|
||||
}
|
||||
|
||||
dependency ('org.dom4j:dom4j:2.1.3') {
|
||||
exclude 'relaxngDatatype:relaxngDatatype' // already in com.sun.xml.bind:jaxb-osgi:2.3.0.1
|
||||
// FINERACT-940 && FINERACT-966 https://github.com/spotbugs/spotbugs/issues/1128
|
||||
exclude 'xpp3:xpp3'
|
||||
exclude 'pull-parser:pull-parser'
|
||||
}
|
||||
|
||||
dependency 'org.owasp.esapi:esapi:2.4.0.0'
|
||||
|
||||
dependencySet(group: 'org.apache.poi', version: '5.2.2') {
|
||||
entry 'poi'
|
||||
entry 'poi-ooxml'
|
||||
entry 'poi-ooxml-schemas'
|
||||
}
|
||||
|
||||
dependencySet(group: 'io.rest-assured', version: '4.5.1') {
|
||||
entry 'rest-assured'
|
||||
entry 'json-path'
|
||||
entry 'xml-path'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
apply plugin: 'org.apache.fineract.gradle'
|
||||
apply from: "${rootDir}/buildSrc/src/main/groovy/org.apache.fineract.dependencies.gradle"
|
||||
|
||||
fineract {
|
||||
config {
|
||||
username = "${findProperty('fineract.config.username')}"
|
||||
password = "${findProperty('fineract.config.password')}"
|
||||
|
||||
doc {
|
||||
url = 'git@github.com:apache/fineract-site.git'
|
||||
directory = "${System.getProperty("java.io.tmpdir")}/fineract-site"
|
||||
branch = "asf-site"
|
||||
}
|
||||
git {
|
||||
dir = "${projectDir.absolutePath}/.git"
|
||||
sections = [
|
||||
[
|
||||
section: "user",
|
||||
name: "name",
|
||||
value: "${findProperty('fineract.config.name')}",
|
||||
],
|
||||
[
|
||||
section: "user",
|
||||
name: "email",
|
||||
value: "${findProperty('fineract.config.email')}",
|
||||
],
|
||||
[
|
||||
section: "user",
|
||||
name: "signingkey",
|
||||
value: "${findProperty('fineract.config.gnupg.keyName')}",
|
||||
],
|
||||
[
|
||||
section: "commit",
|
||||
name: "gpgsign",
|
||||
value: "true",
|
||||
],
|
||||
]
|
||||
}
|
||||
template {
|
||||
templateDir = "${projectDir}/buildSrc/src/main/resources"
|
||||
}
|
||||
gpg {
|
||||
keyName = "${findProperty('fineract.config.gnupg.keyName')}"
|
||||
publicKeyring = "${findProperty('fineract.config.gnupg.publicKeyring')}"
|
||||
secretKeyring = "${findProperty('fineract.config.gnupg.secretKeyring')}"
|
||||
password = "${findProperty('fineract.config.gnupg.password')}"
|
||||
}
|
||||
smtp {
|
||||
host = 'smtp.gmail.com'
|
||||
username = "${findProperty('fineract.config.smtp.username')}"
|
||||
password = "${findProperty('fineract.config.smtp.password')}"
|
||||
tls = true
|
||||
ssl = true
|
||||
}
|
||||
subversion {
|
||||
username = "${findProperty('fineract.config.username')}"
|
||||
password = "${findProperty('fineract.config.password')}"
|
||||
revision = 'HEAD'
|
||||
}
|
||||
jira {
|
||||
url = 'https://issues.apache.org/jira/rest/api/2/'
|
||||
username = "${findProperty('fineract.config.username')}"
|
||||
password = "${findProperty('fineract.config.password')}"
|
||||
}
|
||||
confluence {
|
||||
url = 'https://cwiki.apache.org/confluence/rest/api/'
|
||||
username = "${findProperty('fineract.config.username')}"
|
||||
password = "${findProperty('fineract.config.password')}"
|
||||
}
|
||||
}
|
||||
|
||||
steps = [
|
||||
test: [
|
||||
order: 0,
|
||||
description: 'Test',
|
||||
email: [
|
||||
from: "${findProperty('fineract.config.email')}",
|
||||
to: "${findProperty('fineract.config.email')}",
|
||||
mime: 'text/plain',
|
||||
subject: "[FINERACT] [TEST] 📣 🏁 🗳️ 🚀 📈 🔀 🌠 Propose new release ${version}",
|
||||
messageTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step01.headsup.message.ftl"
|
||||
]
|
||||
],
|
||||
subversion: [
|
||||
url: 'https://dist.apache.org/repos/dist/dev/fineract',
|
||||
directory: "${System.getProperty("java.io.tmpdir")}"
|
||||
],
|
||||
jira: [
|
||||
query: "project in (\'FINERACT\') and fixVersion = ${findProperty('fineract.release.version')} and status in (CLOSED, RESOLVED)"
|
||||
],
|
||||
template: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/jira/changelog.txt.ftl"
|
||||
],
|
||||
gpg: [
|
||||
file: "${projectDir}/buildSrc/build/libs/buildSrc.jar"
|
||||
]
|
||||
],
|
||||
step1: [
|
||||
order: 1,
|
||||
description: 'Send heads-up email to dev mailing list',
|
||||
email: [
|
||||
from: "${findProperty('fineract.config.email')}",
|
||||
name: "${findProperty('fineract.config.name')}",
|
||||
to: "${findProperty('fineract.config.email')}",
|
||||
// to: 'dev@fineract.apache.org',
|
||||
mime: 'text/plain',
|
||||
subjectTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step01.headsup.subject.ftl"
|
||||
],
|
||||
messageTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step01.headsup.message.ftl"
|
||||
]
|
||||
]
|
||||
],
|
||||
step2: [
|
||||
order: 2,
|
||||
description: 'Clean up JIRA',
|
||||
],
|
||||
step3: [
|
||||
order: 3,
|
||||
description: 'Create a release branch',
|
||||
email: [
|
||||
from: "${findProperty('fineract.config.email')}",
|
||||
name: "${findProperty('fineract.config.name')}",
|
||||
to: "${findProperty('fineract.config.email')}",
|
||||
// to: 'dev@fineract.apache.org',
|
||||
mime: 'text/plain',
|
||||
subjectTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step03.branch.subject.ftl"
|
||||
],
|
||||
messageTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step03.branch.message.ftl"
|
||||
]
|
||||
]
|
||||
],
|
||||
step4: [
|
||||
order: 4,
|
||||
description: 'Freeze JIRA version',
|
||||
],
|
||||
step5: [
|
||||
order: 5,
|
||||
description: 'Create release tag',
|
||||
git: [
|
||||
messageTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/git/release.step05.tag.message.ftl"
|
||||
]
|
||||
]
|
||||
],
|
||||
step6: [
|
||||
order: 6,
|
||||
description: 'Create a distribution',
|
||||
],
|
||||
step7: [
|
||||
order: 7,
|
||||
description: 'Sign the distribution artifacts',
|
||||
gpg: [
|
||||
file: "${rootDir}/fineract-war/build/distributions/apache-fineract-binary-${project.version}.tar.gz"
|
||||
]
|
||||
],
|
||||
step8: [
|
||||
order: 8,
|
||||
description: 'Upload distribution artifacts to staging environment',
|
||||
subversion: [
|
||||
url: 'https://dist.apache.org/repos/dist/dev/fineract',
|
||||
directory: "${System.getProperty("java.io.tmpdir")}/fineract-dist-dev"
|
||||
],
|
||||
],
|
||||
step9: [
|
||||
order: 9,
|
||||
description: 'Verify distribution in staging environment',
|
||||
],
|
||||
step10: [
|
||||
order: 10,
|
||||
description: 'Start voting on the dev mailing list',
|
||||
email: [
|
||||
from: "${findProperty('fineract.config.email')}",
|
||||
name: "${findProperty('fineract.config.name')}",
|
||||
to: "${findProperty('fineract.config.email')}",
|
||||
// to: 'dev@fineract.apache.org',
|
||||
mime: 'text/plain',
|
||||
subjectTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step10.vote.subject.ftl"
|
||||
],
|
||||
messageTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step10.vote.message.ftl"
|
||||
]
|
||||
]
|
||||
],
|
||||
step11: [
|
||||
order: 11,
|
||||
description: 'Conclude the vote and announce results',
|
||||
email: [
|
||||
from: "${findProperty('fineract.config.email')}",
|
||||
name: "${findProperty('fineract.config.name')}",
|
||||
to: "${findProperty('fineract.config.email')}",
|
||||
// to: 'dev@fineract.apache.org',
|
||||
mime: 'text/plain',
|
||||
subjectTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step11.vote.subject.ftl"
|
||||
],
|
||||
messageTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step11.vote.message.ftl"
|
||||
]
|
||||
]
|
||||
],
|
||||
step12: [
|
||||
order: 12,
|
||||
description: 'Upload distribution artifacts to release environment',
|
||||
subversion: [
|
||||
url: 'https://dist.apache.org/repos/dist/release/fineract',
|
||||
directory: "${System.getProperty("java.io.tmpdir")}/fineract-dist-release"
|
||||
],
|
||||
],
|
||||
step13: [
|
||||
order: 13,
|
||||
description: 'Close release branch and merge to \'develop\'',
|
||||
],
|
||||
step14: [
|
||||
order: 14,
|
||||
description: 'Update website (not yet automated)',
|
||||
],
|
||||
step15: [
|
||||
order: 15,
|
||||
description: 'Send email to announcement mailing list',
|
||||
jira: [
|
||||
projectId: "12319420",
|
||||
query: "project in (\'FINERACT\') and fixVersion = ${findProperty('fineract.release.version')} and status in (CLOSED, RESOLVED, WONTFIX)"
|
||||
],
|
||||
email: [
|
||||
from: "${findProperty('fineract.config.email')}",
|
||||
name: "${findProperty('fineract.config.name')}",
|
||||
to: "${findProperty('fineract.config.email')}",
|
||||
// to: 'dev@fineract.apache.org',
|
||||
mime: 'text/plain',
|
||||
subjectTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step15.announce.subject.ftl"
|
||||
],
|
||||
messageTemplate: [
|
||||
templateFile: "${projectDir}/buildSrc/src/main/resources/email/release.step15.announce.message.ftl"
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,581 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.gradle
|
||||
|
||||
import groovy.json.JsonSlurper
|
||||
import org.apache.commons.io.FileUtils
|
||||
import org.apache.commons.io.filefilter.NotFileFilter
|
||||
import org.apache.commons.io.filefilter.PrefixFileFilter
|
||||
import org.apache.fineract.gradle.service.*
|
||||
import org.beryx.textio.TextIO
|
||||
import org.beryx.textio.TextIoFactory
|
||||
import org.beryx.textio.TextTerminal
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class FineractPlugin implements Plugin<Project> {
|
||||
private static final Logger log = LoggerFactory.getLogger(FineractPlugin.class)
|
||||
|
||||
private JiraService jiraService
|
||||
private ConfluenceService confluenceService
|
||||
private SubversionService subversionService
|
||||
private EmailService emailService
|
||||
private GpgService gpgService
|
||||
private TemplateService templateService
|
||||
private GitService gitService
|
||||
private Map<String, ?> context;
|
||||
|
||||
static {
|
||||
System.setProperty("org.beryx.textio.TextTerminal", "org.beryx.textio.system.SystemTextTerminal")
|
||||
}
|
||||
|
||||
void apply(Project project) {
|
||||
def extension = project.extensions.create("fineract", FineractPluginExtension, project)
|
||||
|
||||
project.fineract.extensions.create("config", FineractPluginExtension.FineractPluginConfig)
|
||||
project.fineract.config.extensions.create("doc", FineractPluginExtension.FineractPluginConfigDoc)
|
||||
project.fineract.config.extensions.create("template", FineractPluginExtension.FineractPluginConfigTemplate)
|
||||
project.fineract.config.extensions.create("smtp", FineractPluginExtension.FineractPluginConfigSmtp)
|
||||
project.fineract.config.extensions.create("subversion", FineractPluginExtension.FineractPluginConfigSubversion)
|
||||
project.fineract.config.extensions.create("jira", FineractPluginExtension.FineractPluginConfigJira)
|
||||
project.fineract.config.extensions.create("confluence", FineractPluginExtension.FineractPluginConfigConfluence)
|
||||
project.fineract.config.extensions.create("gpg", FineractPluginExtension.FineractPluginConfigGpg)
|
||||
project.fineract.config.extensions.create("git", FineractPluginExtension.FineractPluginConfigGit)
|
||||
|
||||
project.afterEvaluate {
|
||||
this.templateService = new TemplateService(extension.config.template)
|
||||
this.jiraService = new JiraService(extension.config.jira)
|
||||
this.confluenceService = new ConfluenceService(extension.config.confluence)
|
||||
this.subversionService = new SubversionService(extension.config.subversion)
|
||||
this.emailService = new EmailService(extension.config.smtp)
|
||||
this.gpgService = new GpgService(extension.config.gpg)
|
||||
this.gitService = new GitService(extension.config.git, extension.config.gpg)
|
||||
this.context = context(project)
|
||||
}
|
||||
|
||||
project.tasks.register("fineractDocPublish") {
|
||||
dependsOn(":fineract-doc:doc")
|
||||
|
||||
doLast {
|
||||
log.warn("Fineract Publish Doc...")
|
||||
|
||||
def url = extension.config.doc.url?:"git@github.com:apache/fineract-site.git";
|
||||
def branch = extension.config.doc.branch?:"asf-site"
|
||||
def directory = extension.config.doc.directory?:System.getProperty("java.io.tmpdir")+"/fineract-site"
|
||||
|
||||
def d = new File(directory)
|
||||
|
||||
if(d.exists()) {
|
||||
gitService.pull(directory)
|
||||
} else {
|
||||
gitService.clone(url, branch, directory)
|
||||
|
||||
gitService.config(directory, extension.config.git.sections)
|
||||
}
|
||||
|
||||
def source = new File("fineract-doc/build/docs/html/en");
|
||||
def target = new File(directory + "/docs/current")
|
||||
|
||||
if(!target.name) {
|
||||
target.mkdirs()
|
||||
}
|
||||
|
||||
FileUtils.copyDirectory(source, target, new NotFileFilter(new PrefixFileFilter(".asciidoctor")), true)
|
||||
|
||||
gitService.commit(directory)
|
||||
}
|
||||
}
|
||||
|
||||
project.tasks.register("fineractReleaseTest") {
|
||||
doFirst {
|
||||
// emojis:
|
||||
// https://gist.github.com/parmentf/035de27d6ed1dce0b36a
|
||||
// https://emojipedia.org/
|
||||
// https://unicode.org/emoji/charts/full-emoji-list.html
|
||||
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "test")
|
||||
|
||||
// TODO:
|
||||
// - jira:
|
||||
// - move tickets to new version
|
||||
|
||||
// jira query
|
||||
FineractPluginExtension.FineractPluginJiraParams result = jiraService.search(step.jira)
|
||||
log.warn(">>>>>>>>>>>>>>>> ISSUE: ${result.result[0]?.id} - ${result.result[0]?.key} - ${result.result[0]?.fields?['summary']} - ${result.result[0]?.fields?['fixVersions']}")
|
||||
|
||||
/*
|
||||
|
||||
// confluence create
|
||||
def content = new ConfluenceService.ConfluenceContent(title: "1.7.0 - Apache Fineract",
|
||||
space: new ConfluenceService.ConfluenceSpace(key: "FINERACT"),
|
||||
ancestors: [new ConfluenceService.ConfluenceParent(id: "75974324")],
|
||||
body: new ConfluenceService.ConfluenceBody(storage: new ConfluenceService.ConfluenceStorage(value: "<h1>Release Artifacts</h1>")))
|
||||
confluenceService.createContent(content)
|
||||
|
||||
// confluence get
|
||||
ConfluenceService.ConfluenceContent content = confluenceService.getContent("211881930")
|
||||
log.warn(">>>>>>>>>>>>>>>>>>>>> CONFLUENCE: ${content.id} - ${content.title} - ${content.body?.storage?.value}")
|
||||
|
||||
// confluence update
|
||||
content.body?.storage?.value = "<h1>Release Artifacts</h1><p><ac:structured-macro ac:macro-id=\"ac1cb3cb-84d4-45aa-820b-05cc42d39dd9\" ac:name=\"jira\" ac:schema-version=\"1\"><ac:parameter ac:name=\"server\">ASF JIRA</ac:parameter><ac:parameter ac:name=\"columnIds\">issuekey,summary,issuetype,created,updated,duedate,assignee,reporter,customfield_12311032,customfield_12311037,customfield_12311022,customfield_12311027,priority,status,resolution</ac:parameter><ac:parameter ac:name=\"columns\">key,summary,type,created,updated,due,assignee,reporter,Priority,Priority,Priority,Priority,priority,status,resolution</ac:parameter><ac:parameter ac:name=\"maximumIssues\">50</ac:parameter><ac:parameter ac:name=\"jqlQuery\">project = FINERACT AND fixVersion = 1.7.0 AND status not in (Open)</ac:parameter><ac:parameter ac:name=\"serverId\">5aa69414-a9e9-3523-82ec-879b028fb15b</ac:parameter></ac:structured-macro></p><p><br/></p>"
|
||||
content.space = new ConfluenceService.ConfluenceSpace(key: "FINERACT")
|
||||
content.status = null
|
||||
content.version = new ConfluenceService.ConfluenceVersion(number: 3)
|
||||
|
||||
// confluence update
|
||||
content = confluenceService.updateContent(content.id, content)
|
||||
log.warn(">>>>>>>>>>>>>>>>>>>>> CONFLUENCE: ${content.id} - ${content.title} - ${content.body?.storage?.value}")
|
||||
|
||||
// confluence delete
|
||||
ConfluenceService.ConfluenceResponse response = confluenceService.deleteContent("211881930")
|
||||
log.warn(">>>>>>>>>>>>>>>>>>>>> CONFLUENCE: ${response?.statusCode} - ${response?.message}")
|
||||
|
||||
// jira versions
|
||||
def versions = jiraService.getProjectVersions("12319420")
|
||||
versions.findAll {
|
||||
log.warn(">>>> VERSION: ${it.id} - ${it.name} - ${it.description}")
|
||||
}
|
||||
|
||||
def version = jiraService.getVersion("12351431")
|
||||
log.warn(">>>> !!! VERSION: ${version.id} - ${version.name} - ${version.description} - ${version.archived}")
|
||||
|
||||
version.archived = !version.archived
|
||||
|
||||
jiraService.updateVersion(version)
|
||||
version = jiraService.getVersion("12351431")
|
||||
log.warn(">>>> === VERSION: ${version.id} - ${version.name} - ${version.description} - ${version.archived}")
|
||||
|
||||
// jira projects
|
||||
def projects = jiraService.getProjects()
|
||||
|
||||
projects.findAll {
|
||||
log.warn(">>>>>>>>>>>> PROJECT: ${it.id} - ${it.key} - ${it.name}")
|
||||
}
|
||||
|
||||
// jira info
|
||||
Map<String, Object> info = jiraService.serverInfo()
|
||||
log.warn(">>>>>>>>>>>>>>>> INFO: ${info}")
|
||||
|
||||
// jira query
|
||||
FineractPluginExtension.FineractPluginJiraParams result = jiraService.search(step.jira)
|
||||
log.warn(">>>>>>>>>>>>>>>> INFO: ${result.result.size()}")
|
||||
|
||||
// format with template
|
||||
def tmp = templateService.render(step.template, [issues: result.result])
|
||||
|
||||
log.warn(tmp.output)
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: step for creating release Jira ticket missing!
|
||||
|
||||
// step 1
|
||||
project.tasks.register("fineractReleaseStep1") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step1")
|
||||
|
||||
String version = project.properties?['fineract.release.version']
|
||||
String issue = project.properties?['fineract.release.issue']
|
||||
String date = project.properties?['fineract.release.date']
|
||||
|
||||
if(!version || !issue || !date) {
|
||||
TextIO textIO = TextIoFactory.getTextIO()
|
||||
|
||||
if(!version) {
|
||||
version = textIO.newStringInputReader()
|
||||
.withPattern("\\d+.\\d+.\\d+")
|
||||
.read("Release Version");
|
||||
}
|
||||
if(!issue) {
|
||||
issue = textIO.newStringInputReader()
|
||||
.withMaxLength(4)
|
||||
.withPattern("\\d+")
|
||||
.read("Jira Issue");
|
||||
}
|
||||
if(!date) {
|
||||
date = textIO.newStringInputReader()
|
||||
.withMaxLength(10)
|
||||
.withPattern("\\d\\d\\d\\d-\\d\\d-\\d\\d")
|
||||
.read("Date");
|
||||
}
|
||||
|
||||
TextTerminal terminal = textIO.getTextTerminal()
|
||||
terminal.printf("\nResult: %s - FINERACT-%s - %s", version, issue, date)
|
||||
}
|
||||
|
||||
// TODO: input validation, see FINERACT-1610
|
||||
|
||||
this.context?.project?['fineract.release.version'] = version
|
||||
this.context?.project?['fineract.release.issue'] = issue
|
||||
this.context?.project?['fineract.release.date'] = date
|
||||
|
||||
if(step.email) {
|
||||
emailService.send( processEmailParams(step.email, this.context) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// step 2
|
||||
project.tasks.register("fineractReleaseStep2") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step2")
|
||||
|
||||
// TODO: implement this, see FINERACT-1611
|
||||
|
||||
printInstructions(project, "step2")
|
||||
}
|
||||
}
|
||||
|
||||
// step 3
|
||||
project.tasks.register("fineractReleaseStep3") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step3")
|
||||
|
||||
String version = project.properties?['fineract.release.version']
|
||||
String date = project.properties?['fineract.release.date']
|
||||
|
||||
if(!version || !date) {
|
||||
TextIO textIO = TextIoFactory.getTextIO()
|
||||
|
||||
if(!version) {
|
||||
version = textIO.newStringInputReader()
|
||||
.withPattern("\\d+.\\d+.\\d+")
|
||||
.read("Release Version");
|
||||
}
|
||||
if(!date) {
|
||||
date = textIO.newStringInputReader()
|
||||
.withMaxLength(10)
|
||||
.withPattern("\\d\\d\\d\\d-\\d\\d-\\d\\d")
|
||||
.read("Date");
|
||||
}
|
||||
|
||||
TextTerminal terminal = textIO.getTextTerminal()
|
||||
terminal.printf("\nResult: %s - %s", version, date)
|
||||
}
|
||||
|
||||
// TODO: input validation, see FINERACT-1610
|
||||
|
||||
// TODO: create release branch, see FINERACT-1611
|
||||
|
||||
this.context?.project?['fineract.release.version'] = version
|
||||
this.context?.project?['fineract.release.date'] = date
|
||||
|
||||
if(step.email) {
|
||||
emailService.send( processEmailParams(step.email, this.context) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// step 4
|
||||
project.tasks.register("fineractReleaseStep4") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step4")
|
||||
// TODO: implement this, see FINERACT-1611
|
||||
|
||||
printInstructions(project, "step4")
|
||||
}
|
||||
}
|
||||
|
||||
// step 5
|
||||
project.tasks.register("fineractReleaseStep5") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step5")
|
||||
|
||||
String version = project.properties?['fineract.release.version']
|
||||
|
||||
if(!version) {
|
||||
TextIO textIO = TextIoFactory.getTextIO()
|
||||
|
||||
if (!version) {
|
||||
version = textIO.newStringInputReader()
|
||||
.withPattern("\\d+.\\d+.\\d+")
|
||||
.read("Release Version");
|
||||
}
|
||||
}
|
||||
|
||||
this.context?.project?['fineract.release.version'] = version
|
||||
|
||||
def params = processGitParams(step.git, this.context)
|
||||
|
||||
params.tag = params.tag?:version
|
||||
|
||||
gitService.createTag(params.tag, params.message)
|
||||
}
|
||||
}
|
||||
|
||||
// step 6
|
||||
project.tasks.register("fineractReleaseStep6") {
|
||||
dependsOn(":fineract-war:binaryDistTar")
|
||||
}
|
||||
|
||||
// step 7
|
||||
project.tasks.register("fineractReleaseStep7") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step7")
|
||||
|
||||
gpgService.sign(step.gpg)
|
||||
|
||||
def md5 = gpgService.md5(step.gpg)
|
||||
def md5File = new File("${step.gpg.file}.md5")
|
||||
md5File.write md5
|
||||
|
||||
def sha512 = gpgService.sha512(step.gpg)
|
||||
def sha512File = new File("${step.gpg.file}.sha512")
|
||||
sha512File.write sha512
|
||||
}
|
||||
}
|
||||
|
||||
// step 8
|
||||
project.tasks.register("fineractReleaseStep8") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step8")
|
||||
|
||||
String version = project.properties?['fineract.release.version']
|
||||
|
||||
if(!version) {
|
||||
TextIO textIO = TextIoFactory.getTextIO()
|
||||
|
||||
version = textIO.newStringInputReader()
|
||||
.withPattern("\\d+.\\d+.\\d+")
|
||||
.read("Release Version");
|
||||
}
|
||||
|
||||
// TODO: input validation, see FINERACT-1610
|
||||
|
||||
subversionService.checkout(step.subversion)
|
||||
|
||||
def directory = step.subversion.directory?:System.getProperty("java.io.tmpdir") + "/fineract-dist-dev"
|
||||
|
||||
def source = new File("fineract-war/build/distributions")
|
||||
def target = new File("${directory}/${version}")
|
||||
|
||||
FileUtils.copyDirectory(source, target, true)
|
||||
|
||||
subversionService.commit(step.subversion)
|
||||
}
|
||||
}
|
||||
|
||||
// step 9
|
||||
project.tasks.register("fineractReleaseStep9") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step9")
|
||||
// TODO: implement this, see FINERACT-1611
|
||||
|
||||
printInstructions(project, "step9")
|
||||
}
|
||||
}
|
||||
|
||||
// step 10
|
||||
project.tasks.register("fineractReleaseStep10") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step10")
|
||||
|
||||
String version = project.properties?['fineract.release.version']
|
||||
|
||||
if(!version) {
|
||||
TextIO textIO = TextIoFactory.getTextIO();
|
||||
|
||||
version = textIO.newStringInputReader()
|
||||
.withPattern("\\d+.\\d+.\\d+")
|
||||
.read("Release Version");
|
||||
}
|
||||
|
||||
// TODO: input validation, see FINERACT-1610
|
||||
|
||||
this.context?.project?['fineract.release.version'] = version
|
||||
|
||||
if(step.email) {
|
||||
emailService.send( processEmailParams(step.email, this.context) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// step 11
|
||||
project.tasks.register("fineractReleaseStep11") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step11")
|
||||
|
||||
String version = project.properties?['fineract.release.version']
|
||||
|
||||
if(!version) {
|
||||
TextIO textIO = TextIoFactory.getTextIO()
|
||||
|
||||
version = textIO.newStringInputReader()
|
||||
.withPattern("\\d+.\\d+.\\d+")
|
||||
.read("Release Version");
|
||||
}
|
||||
|
||||
// TODO: input validation, see FINERACT-1610
|
||||
|
||||
this.context?.project?['fineract.release.version'] = version
|
||||
|
||||
def jsonSlurper = new JsonSlurper()
|
||||
def data = jsonSlurper.parse(new File("buildSrc/src/main/resources/vote/result.${version}.json"))
|
||||
|
||||
this.context?.project?['fineract.vote'] = data
|
||||
|
||||
if(step.email) {
|
||||
emailService.send( processEmailParams(step.email, this.context) )
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// step 12
|
||||
project.tasks.register("fineractReleaseStep12") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step12")
|
||||
|
||||
String version = project.properties?['fineract.release.version']
|
||||
|
||||
if(!version) {
|
||||
TextIO textIO = TextIoFactory.getTextIO()
|
||||
|
||||
version = textIO.newStringInputReader()
|
||||
.withPattern("\\d+.\\d+.\\d+")
|
||||
.read("Release Version");
|
||||
}
|
||||
|
||||
// TODO: input validation, see FINERACT-1610
|
||||
|
||||
subversionService.checkout(step.subversion)
|
||||
|
||||
def directory = step.subversion.directory?:System.getProperty("java.io.tmpdir") + "/fineract-dist-release"
|
||||
|
||||
def source = new File("fineract-war/build/distributions")
|
||||
def target = new File("${directory}/${version}")
|
||||
|
||||
FileUtils.copyDirectory(source, target, true)
|
||||
|
||||
subversionService.commit(step.subversion)
|
||||
}
|
||||
}
|
||||
|
||||
// step 13
|
||||
project.tasks.register("fineractReleaseStep13") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step13")
|
||||
// TODO: implement this, see FINERACT-1611
|
||||
|
||||
printInstructions(project, "step13")
|
||||
}
|
||||
}
|
||||
|
||||
// step 14
|
||||
project.tasks.register("fineractReleaseStep14") {
|
||||
doFirst {
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step14")
|
||||
// TODO: implement this, see FINERACT-1611
|
||||
|
||||
printInstructions(project, "step14")
|
||||
}
|
||||
}
|
||||
|
||||
// step 15
|
||||
project.tasks.register("fineractReleaseStep15") {
|
||||
doFirst {
|
||||
log.warn("Release step 15: send email to announcement mailing list")
|
||||
|
||||
FineractPluginExtension.FineractPluginStep step = step(extension, "step15")
|
||||
|
||||
String version = project.properties?['fineract.release.version']
|
||||
|
||||
if(!version) {
|
||||
TextIO textIO = TextIoFactory.getTextIO()
|
||||
|
||||
version = textIO.newStringInputReader()
|
||||
.withPattern("\\d+.\\d+.\\d+")
|
||||
.read("Release Version");
|
||||
}
|
||||
|
||||
// TODO: input validation, see FINERACT-1610
|
||||
|
||||
FineractPluginExtension.FineractPluginJiraParams issues = jiraService.search(step.jira)
|
||||
|
||||
def versions = jiraService.getProjectVersions(step.jira.projectId)
|
||||
def filteredVersions = versions.findAll {
|
||||
log.warn(">>>> VERSION: ${it.id} - ${it.name} - ${it.description}")
|
||||
it.name == version
|
||||
}
|
||||
|
||||
this.context?.project?['fineract.release.version'] = version
|
||||
this.context?.project?['fineract.release.issues'] = issues.result
|
||||
this.context?.project?['fineract.release.projectId'] = step.jira.projectId
|
||||
this.context?.project?['fineract.release.versionId'] = filteredVersions[0]?.id
|
||||
|
||||
if(step.email) {
|
||||
emailService.send( processEmailParams(step.email, this.context) )
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private FineractPluginExtension.FineractPluginStep step(FineractPluginExtension extension, String id) {
|
||||
FineractPluginExtension.FineractPluginStep step = extension.steps[id]
|
||||
|
||||
if(step) {
|
||||
log.warn("Fineract release step ${step.order}: ${step.description}.")
|
||||
} else {
|
||||
throw new RuntimeException("Could not find any parameters for step with ID '${id}'")
|
||||
}
|
||||
|
||||
return step
|
||||
}
|
||||
|
||||
private FineractPluginExtension.FineractPluginEmailParams processEmailParams(FineractPluginExtension.FineractPluginEmailParams params, Object data) {
|
||||
if(params.subjectTemplate) {
|
||||
def result = templateService.render(params.subjectTemplate, data)
|
||||
|
||||
params.subject = result.output
|
||||
}
|
||||
if(params.messageTemplate) {
|
||||
def result = templateService.render(params.messageTemplate, data)
|
||||
|
||||
params.message = result.output
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
private FineractPluginExtension.FineractPluginGitParams processGitParams(FineractPluginExtension.FineractPluginGitParams params, Object data) {
|
||||
if(params.messageTemplate) {
|
||||
def result = templateService.render(params.messageTemplate, data)
|
||||
|
||||
params.message = result.output
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
private Map<String, ?> context(Project project) {
|
||||
return Map.of("project", project.getProperties().findAll { it.key != "password"})
|
||||
}
|
||||
|
||||
private void printInstructions(Project project, String step) {
|
||||
String version = project.properties?['fineract.release.version']?:"0.0.0"
|
||||
|
||||
this.context?.project?['fineract.release.version'] = version
|
||||
|
||||
FineractPluginExtension.FineractPluginTemplateParams result = templateService.render(new FineractPluginExtension.FineractPluginTemplateParams(templateFile: new File("buildSrc/src/main/resources/instructions/${step}.txt.ftl")), this.context)
|
||||
|
||||
log.warn(result.output)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.gradle
|
||||
|
||||
import org.apache.fineract.gradle.service.JiraService
|
||||
import org.gradle.api.Project
|
||||
|
||||
class FineractPluginExtension {
|
||||
Project project
|
||||
Map<String, FineractPluginStep> steps = [:]
|
||||
|
||||
FineractPluginExtension(Project project) {
|
||||
this.project = project
|
||||
}
|
||||
|
||||
static class FineractPluginConfig {
|
||||
String username
|
||||
String password
|
||||
}
|
||||
|
||||
static class FineractPluginConfigDoc {
|
||||
String url
|
||||
String directory
|
||||
String branch
|
||||
}
|
||||
|
||||
static class FineractPluginConfigJira {
|
||||
String url
|
||||
String username
|
||||
String password
|
||||
String project
|
||||
}
|
||||
|
||||
static class FineractPluginConfigConfluence {
|
||||
String url
|
||||
String username
|
||||
String password
|
||||
String project
|
||||
}
|
||||
|
||||
static class FineractPluginConfigGpg {
|
||||
String keyName
|
||||
String publicKeyring
|
||||
String secretKeyring
|
||||
String password
|
||||
}
|
||||
|
||||
static class FineractPluginConfigTemplate {
|
||||
String templateDir
|
||||
}
|
||||
|
||||
static class FineractPluginConfigSmtp {
|
||||
String host
|
||||
int port
|
||||
String username
|
||||
String password
|
||||
boolean tls
|
||||
boolean ssl
|
||||
}
|
||||
|
||||
static class FineractPluginConfigGit {
|
||||
String username
|
||||
String password
|
||||
String dir
|
||||
boolean dryRun
|
||||
List<FineractPluginConfigGitSection> sections
|
||||
}
|
||||
|
||||
static class FineractPluginConfigGitSection {
|
||||
String section
|
||||
String subsection
|
||||
String name
|
||||
String value
|
||||
}
|
||||
|
||||
static class FineractPluginConfigSubversion {
|
||||
String username
|
||||
String password
|
||||
String revision
|
||||
}
|
||||
|
||||
static class FineractPluginStep {
|
||||
int order
|
||||
String description
|
||||
FineractPluginEmailParams email
|
||||
FineractPluginJiraParams jira
|
||||
FineractPluginTemplateParams template
|
||||
FineractPluginConfluenceParams confluence
|
||||
FineractPluginGitParams git
|
||||
FineractPluginSubversionParams subversion
|
||||
FineractPluginGpgParams gpg
|
||||
}
|
||||
|
||||
static class FineractPluginEmailParams {
|
||||
String from
|
||||
String name
|
||||
String to
|
||||
String cc
|
||||
String bcc
|
||||
String mime
|
||||
String subject
|
||||
FineractPluginTemplateParams subjectTemplate
|
||||
String message
|
||||
FineractPluginTemplateParams messageTemplate
|
||||
}
|
||||
|
||||
static class FineractPluginJiraParams {
|
||||
String command
|
||||
String projectId
|
||||
String fields = "*all"
|
||||
String query
|
||||
List<JiraService.JiraIssue> result = new ArrayList<>()
|
||||
int pageOffset = 0
|
||||
int pageSize= 50
|
||||
int total = 1000
|
||||
List<String> includes = ["summary", "status", "assignee", "fixVersions"]
|
||||
}
|
||||
|
||||
static class FineractPluginConfluenceParams {
|
||||
String title
|
||||
String content
|
||||
Integer ancestor
|
||||
}
|
||||
|
||||
static class FineractPluginGitParams {
|
||||
String tag
|
||||
String message
|
||||
FineractPluginTemplateParams messageTemplate
|
||||
}
|
||||
|
||||
static class FineractPluginSubversionParams {
|
||||
String url
|
||||
String command
|
||||
String revision = "HEAD"
|
||||
String directory
|
||||
}
|
||||
|
||||
static class FineractPluginTemplateParams {
|
||||
String template
|
||||
String templateFile
|
||||
String output
|
||||
String outputFile
|
||||
}
|
||||
|
||||
static class FineractPluginGpgParams {
|
||||
String file
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.gradle.service
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import okhttp3.ConnectionPool
|
||||
import okhttp3.Credentials
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Response
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import org.apache.fineract.gradle.FineractPluginExtension.FineractPluginConfigConfluence
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import retrofit2.Call
|
||||
import retrofit2.Callback
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.jackson.JacksonConverterFactory
|
||||
import retrofit2.http.*
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class ConfluenceService {
|
||||
private static final Logger log = LoggerFactory.getLogger(ConfluenceService.class)
|
||||
|
||||
private ConfluenceApi api
|
||||
|
||||
ConfluenceService(FineractPluginConfigConfluence config) {
|
||||
def credentials = Credentials.basic(config.username, config.password)
|
||||
|
||||
final ConnectionPool connectionPool = new ConnectionPool(5, 60, TimeUnit.SECONDS);
|
||||
|
||||
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(log::debug)
|
||||
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
|
||||
|
||||
OkHttpClient.Builder okClient = new OkHttpClient.Builder()
|
||||
.connectionPool(connectionPool)
|
||||
.addInterceptor(loggingInterceptor)
|
||||
.addInterceptor(new Interceptor() {
|
||||
@Override
|
||||
Response intercept(@NotNull Interceptor.Chain chain) throws IOException {
|
||||
def request = chain.request()
|
||||
request = request.newBuilder().header("Authorization", credentials).build()
|
||||
return chain.proceed(request)
|
||||
}
|
||||
})
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
|
||||
Retrofit.Builder builder = new Retrofit.Builder()
|
||||
.baseUrl(config.url)
|
||||
.client(okClient.build())
|
||||
.addConverterFactory(JacksonConverterFactory.create(mapper))
|
||||
|
||||
Retrofit retrofit = builder.build()
|
||||
|
||||
this.api = retrofit.create(ConfluenceApi.class)
|
||||
}
|
||||
|
||||
ConfluenceContent getContent(String id) {
|
||||
this.api.getContentById(id).execute().body()
|
||||
}
|
||||
|
||||
ConfluenceContent createContent(ConfluenceContent content) {
|
||||
this.api.postContent(content).execute().body()
|
||||
}
|
||||
|
||||
ConfluenceContent updateContent(String id, ConfluenceContent content) {
|
||||
this.api.putContent(id, content).execute().body()
|
||||
}
|
||||
|
||||
ConfluenceResponse deleteContent(String id) {
|
||||
this.api.deleteContentById(id).execute().body()
|
||||
}
|
||||
|
||||
static class ConfluenceContent {
|
||||
String id
|
||||
String type
|
||||
String title
|
||||
String status
|
||||
String self
|
||||
List<ConfluenceParent> ancestors
|
||||
ConfluenceSpace space
|
||||
ConfluenceBody body
|
||||
ConfluenceVersion version
|
||||
ConfluenceHistory history
|
||||
}
|
||||
|
||||
static class ConfluenceContentResult {
|
||||
List<ConfluenceContent> results
|
||||
private int start
|
||||
private int limit
|
||||
private int size
|
||||
}
|
||||
|
||||
static class ConfluenceParent {
|
||||
String id
|
||||
String type
|
||||
}
|
||||
|
||||
static class ConfluenceVersion {
|
||||
ConfluenceCreatedBy by
|
||||
Date when
|
||||
String message
|
||||
Integer number
|
||||
}
|
||||
|
||||
static class ConfluenceCreatedBy {
|
||||
String username
|
||||
String displayName
|
||||
}
|
||||
|
||||
static class ConfluenceHistory {
|
||||
boolean latest
|
||||
ConfluenceCreatedBy createdBy
|
||||
ConfluenceVersion nextVersion
|
||||
ConfluenceVersion previousVersion
|
||||
ConfluenceVersion lastUpdated
|
||||
}
|
||||
|
||||
static class ConfluenceSpace {
|
||||
String key
|
||||
String name
|
||||
}
|
||||
|
||||
static class ConfluenceSpaceResult {
|
||||
List<ConfluenceSpace> results
|
||||
}
|
||||
|
||||
static class ConfluenceBody {
|
||||
ConfluenceStorage storage
|
||||
}
|
||||
|
||||
static class ConfluenceStorage {
|
||||
String value
|
||||
String representation
|
||||
}
|
||||
|
||||
static class ConfluenceResponse {
|
||||
int statusCode
|
||||
String message
|
||||
Map<String, ?> data
|
||||
}
|
||||
|
||||
static interface ConfluenceApi {
|
||||
@GET("content")
|
||||
Call<ConfluenceContentResult> getContentResults();
|
||||
|
||||
@GET("content")
|
||||
Call<ConfluenceContentResult> getContentBySpaceKeyAndTitle(final @Query("key") String key, final @Query("title") String title);
|
||||
|
||||
@GET("content/{id}/child/{type}")
|
||||
Call<ConfluenceContentResult> getChildren(final @Path("id") String parentId, final @Path("type") String type, final @QueryMap Map<String, String> params);
|
||||
|
||||
|
||||
@GET("content/{id}?expand=body.storage")
|
||||
Call<ConfluenceContent> getContentById(final @Path("id") String id);
|
||||
|
||||
@POST("contentbody/convert/{to}")
|
||||
Call<ConfluenceStorage> postContentConversion(final @Body ConfluenceStorage storage, final @Path("to") String convertToFormat);
|
||||
|
||||
@POST("content")
|
||||
Call<ConfluenceContent> postContent(final @Body ConfluenceContent content);
|
||||
|
||||
@PUT("content/{id}")
|
||||
Call<ConfluenceContent> putContent(final @Path("id") String id, final @Body ConfluenceContent content);
|
||||
|
||||
@POST("content")
|
||||
void postContentWithCallback(final @Body ConfluenceContent content, final Callback<ConfluenceContent> callback);
|
||||
|
||||
@DELETE("content/{id}")
|
||||
Call<ConfluenceResponse> deleteContentById(final @Path("id") String id);
|
||||
|
||||
@GET("space")
|
||||
Call<ConfluenceSpaceResult> getSpaces();
|
||||
|
||||
@POST("space")
|
||||
Call<ConfluenceSpace> createSpace(final @Body ConfluenceSpace space);
|
||||
|
||||
@POST("space/_private")
|
||||
Call<ConfluenceSpace> createPrivateSpace(final @Body ConfluenceSpace space);
|
||||
|
||||
@GET("space/{spaceKey}/content/page")
|
||||
Call<ConfluenceContentResult> getAllSpaceContent(final @Path("spaceKey") String spaceKey, final @QueryMap Map<String, String> params);
|
||||
|
||||
@GET("space/{spaceKey}/content/{type}")
|
||||
Call<ConfluenceContentResult> getRootContentBySpaceKey(final @Path("spaceKey") String spaceKey, final @Path("type") String contentType);
|
||||
}
|
||||
}
|
||||
// curl -u aleks:xxx -X POST -H 'Content-Type: application/json' -d '{"type":"page","title":"1.7.0 - Apache Fineract","space":{"key":"FINERACT"},"ancestors":[{"id":75974324}],"body":{"storage":{"value":"<p>This is <br/> a new page</p>","representation": "storage"}}}' https://cwiki.apache.org/confluence/content/ | python -mjson.tool
|
||||
@@ -0,0 +1,87 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.gradle.service
|
||||
|
||||
import org.apache.fineract.gradle.FineractPluginExtension
|
||||
import org.apache.fineract.gradle.FineractPluginExtension.FineractPluginEmailParams
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
import javax.mail.*
|
||||
import javax.mail.internet.InternetAddress
|
||||
import javax.mail.internet.MimeMessage
|
||||
|
||||
class EmailService {
|
||||
private static final Logger log = LoggerFactory.getLogger(EmailService.class)
|
||||
|
||||
String username
|
||||
String password
|
||||
Properties properties
|
||||
|
||||
EmailService(FineractPluginExtension.FineractPluginConfigSmtp config) {
|
||||
this.username = config.username
|
||||
this.password = config.password
|
||||
|
||||
this.properties = new Properties()
|
||||
this.properties.put("mail.smtp.host", config.host)
|
||||
this.properties.put("mail.smtp.auth", "true")
|
||||
this.properties.put("mail.smtp.starttls.enable", config.tls.toString())
|
||||
if(config.ssl) {
|
||||
this.properties.put("mail.smtp.port", "465")
|
||||
this.properties.put("mail.smtp.socketFactory.port", "465");
|
||||
this.properties.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
|
||||
|
||||
} else {
|
||||
this.properties.put("mail.smtp.port", "587")
|
||||
}
|
||||
}
|
||||
|
||||
void send(FineractPluginEmailParams params) {
|
||||
log.warn("Sending email: ${params.from} -> ${params.to} - ${params.subject}")
|
||||
|
||||
Session session = Session.getInstance(this.properties, new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(getUsername(), getPassword())
|
||||
}
|
||||
})
|
||||
|
||||
try {
|
||||
|
||||
Message msg = new MimeMessage(session)
|
||||
msg.setFrom(new InternetAddress(params.from, params.name))
|
||||
msg.setRecipients(Message.RecipientType.TO, InternetAddress.parse(params.to))
|
||||
if(params.cc) {
|
||||
msg.setRecipients(Message.RecipientType.CC, InternetAddress.parse(params.cc))
|
||||
}
|
||||
if(params.bcc) {
|
||||
msg.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(params.bcc))
|
||||
}
|
||||
msg.setSubject(params.subject)
|
||||
msg.setText(params.message);
|
||||
|
||||
Transport.send(msg);
|
||||
|
||||
log.info("Done")
|
||||
|
||||
} catch (MessagingException e) {
|
||||
log.error(e.toString(), e)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.gradle.service
|
||||
|
||||
import org.apache.fineract.gradle.FineractPluginExtension
|
||||
import org.eclipse.jgit.annotations.NonNull
|
||||
import org.eclipse.jgit.annotations.Nullable
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.api.errors.CanceledException
|
||||
import org.eclipse.jgit.lib.CommitBuilder
|
||||
import org.eclipse.jgit.lib.GpgSigner
|
||||
import org.eclipse.jgit.lib.PersonIdent
|
||||
import org.eclipse.jgit.lib.Repository
|
||||
import org.eclipse.jgit.lib.StoredConfig
|
||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder
|
||||
import org.eclipse.jgit.transport.CredentialsProvider
|
||||
import org.eclipse.jgit.transport.RefSpec
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class GitService {
|
||||
private static final Logger log = LoggerFactory.getLogger(GitService.class)
|
||||
|
||||
private Git git
|
||||
private boolean dryRun
|
||||
|
||||
GitService(FineractPluginExtension.FineractPluginConfigGit config, FineractPluginExtension.FineractPluginConfigGpg gpgConfig) {
|
||||
GpgSigner.setDefault(new GpgSigner() {
|
||||
@Override
|
||||
void sign(@NonNull CommitBuilder commit, @Nullable String gpgSigningKey, @NonNull PersonIdent committer, CredentialsProvider credentialsProvider) throws CanceledException {
|
||||
log.warn("------------------------ KEY: ${gpgSigningKey} IDENT: ${committer}")
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean canLocateSigningKey(@Nullable String gpgSigningKey, @NonNull PersonIdent committer, CredentialsProvider credentialsProvider) throws CanceledException {
|
||||
log.warn("------------------------ KEY: ${gpgSigningKey} IDENT: ${committer}")
|
||||
return false
|
||||
}
|
||||
});
|
||||
|
||||
Repository repository = new FileRepositoryBuilder()
|
||||
.readEnvironment()
|
||||
.setGitDir(new File(config.dir))
|
||||
.findGitDir()
|
||||
.build();
|
||||
|
||||
this.git = new Git(repository)
|
||||
this.dryRun = config.dryRun
|
||||
}
|
||||
|
||||
void clone(String url, String branch, String directory) {
|
||||
def ref = "refs/heads/" + branch
|
||||
|
||||
Git.cloneRepository()
|
||||
.setURI(url)
|
||||
.setDirectory(new File(directory))
|
||||
.setBranchesToClone(Arrays.asList(ref))
|
||||
.setBranch(ref)
|
||||
.call();
|
||||
}
|
||||
|
||||
void pull(String directory) {
|
||||
Git git = Git.open(new File(directory));
|
||||
|
||||
git.pull().call()
|
||||
}
|
||||
|
||||
void commit(String directory) {
|
||||
Git git = Git.open(new File(directory));
|
||||
|
||||
def status = git.status().call()
|
||||
|
||||
if(!status.isClean()) {
|
||||
git.add().addFilepattern(".").call()
|
||||
|
||||
git.commit().setSign(true).setMessage("chore: Publish current docs").call()
|
||||
}
|
||||
|
||||
def result = git.push().call()
|
||||
}
|
||||
|
||||
void config(String directory, List<FineractPluginExtension.FineractPluginConfigGitSection> sections) {
|
||||
Git git = Git.open(new File(directory));
|
||||
|
||||
StoredConfig gitConfig = git.getRepository().getConfig();
|
||||
|
||||
sections.forEach(section -> {
|
||||
gitConfig.setString(section.section, section.subsection, section.name, section.value);
|
||||
})
|
||||
// gitConfig.setString("branch", "master", "merge", "refs/heads/master");
|
||||
gitConfig.save();
|
||||
}
|
||||
|
||||
void createTag(String name, String message) {
|
||||
def ref = git.tag()
|
||||
.setName(name)
|
||||
.setMessage(message)
|
||||
.setAnnotated(true)
|
||||
.setForceUpdate(true)
|
||||
.call()
|
||||
|
||||
try {
|
||||
git.push().setPushTags().setForce(true).setDryRun(dryRun).call()
|
||||
|
||||
log.warn("Tag created: ${name} (${ref.name})")
|
||||
} catch(Exception e) {
|
||||
log.error(e.toString(), e)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: explicitly provide the directory
|
||||
void removeTag(String name) {
|
||||
git.tagDelete().setTags(name).call()
|
||||
|
||||
RefSpec refSpec = new RefSpec(":refs/tags/${name}");
|
||||
git.push().setRefSpecs(refSpec).setRemote("origin").call()
|
||||
|
||||
log.warn("Tag deleted: ${name}")
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.gradle.service
|
||||
|
||||
import org.apache.fineract.gradle.FineractPluginExtension
|
||||
import org.apache.fineract.gradle.FineractPluginExtension.FineractPluginConfigGpg
|
||||
import org.bouncycastle.bcpg.ArmoredOutputStream
|
||||
import org.bouncycastle.bcpg.BCPGOutputStream
|
||||
import org.bouncycastle.gpg.keybox.BlobType
|
||||
import org.bouncycastle.gpg.keybox.PublicKeyRingBlob
|
||||
import org.bouncycastle.gpg.keybox.bc.BcKeyBox
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||
import org.bouncycastle.openpgp.*
|
||||
import org.bouncycastle.openpgp.operator.bc.BcKeyFingerprintCalculator
|
||||
import org.bouncycastle.openpgp.operator.bc.BcPGPContentSignerBuilder
|
||||
import org.bouncycastle.openpgp.operator.jcajce.JcePBESecretKeyDecryptorBuilder
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
import java.security.GeneralSecurityException
|
||||
import java.security.MessageDigest
|
||||
import java.security.Security
|
||||
|
||||
class GpgService {
|
||||
private static final Logger log = LoggerFactory.getLogger(GpgService.class)
|
||||
|
||||
private PGPPrivateKey privateKey;
|
||||
private PGPPublicKey publicKey;
|
||||
|
||||
static {
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
}
|
||||
|
||||
GpgService(FineractPluginConfigGpg config) {
|
||||
// TODO: provide implementation for *.gpg key rings
|
||||
def keyBox = config.publicKeyring.endsWith(".kbx") ? new BcKeyBox(new FileInputStream(config.publicKeyring)) : null
|
||||
|
||||
if(keyBox) {
|
||||
for(def keyBlob : keyBox.getKeyBlobs()) {
|
||||
switch (keyBlob.type) {
|
||||
case BlobType.X509_BLOB:
|
||||
break
|
||||
case BlobType.OPEN_PGP_BLOB:
|
||||
def publicKeyRing = (keyBlob as PublicKeyRingBlob).getPGPPublicKeyRing();
|
||||
def iterator = publicKeyRing.getPublicKeys();
|
||||
|
||||
while (publicKey == null && iterator.hasNext()) {
|
||||
def k = iterator.next();
|
||||
|
||||
if (k.isEncryptionKey()) {
|
||||
def keyName = Long.toHexString(k.keyID).toUpperCase()
|
||||
|
||||
if(config.keyName.substring(config.keyName.length()-keyName.length()) == keyName) {
|
||||
publicKey = k;
|
||||
log.warn("Found: ${publicKey.getUserIDs().next()}")
|
||||
break
|
||||
} else {
|
||||
log.warn("Key mismatch: ${config.keyName} <-> ${keyName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
PGPSecretKeyRingCollection secretRingCollection = new PGPSecretKeyRingCollection(new FileInputStream(config.secretKeyring), new BcKeyFingerprintCalculator())
|
||||
|
||||
def secretKey = secretRingCollection.getSecretKey(publicKey.keyID)
|
||||
|
||||
if(secretKey!=null) {
|
||||
this.privateKey = secretKey.extractPrivateKey(new JcePBESecretKeyDecryptorBuilder().setProvider(BouncyCastleProvider.PROVIDER_NAME).build(config.password.toCharArray()))
|
||||
}
|
||||
} else {
|
||||
log.warn("Could not open the public key ring.")
|
||||
}
|
||||
}
|
||||
|
||||
void sign(FineractPluginExtension.FineractPluginGpgParams params) {
|
||||
InputStream is = new FileInputStream(params.file)
|
||||
|
||||
BCPGOutputStream os = new BCPGOutputStream(new ArmoredOutputStream(new FileOutputStream(params.file + ".asc")))
|
||||
sign(is).encode(os)
|
||||
os.close();
|
||||
}
|
||||
|
||||
PGPSignature sign(InputStream is) throws IOException, PGPException, GeneralSecurityException {
|
||||
|
||||
PGPSignatureGenerator generator = new PGPSignatureGenerator(new BcPGPContentSignerBuilder(publicKey.getAlgorithm(), PGPUtil.SHA1));
|
||||
generator.init(PGPSignature.BINARY_DOCUMENT, privateKey);
|
||||
|
||||
byte[] buf = new byte[4096];
|
||||
int len;
|
||||
|
||||
while ((len = is.read(buf)) >= 0) {
|
||||
generator.update(buf, 0, len);
|
||||
}
|
||||
|
||||
return generator.generate();
|
||||
}
|
||||
|
||||
|
||||
String md5(FineractPluginExtension.FineractPluginGpgParams params) {
|
||||
return calc(new FileInputStream(params.file), MessageDigest.getInstance("MD5", BouncyCastleProvider.PROVIDER_NAME))
|
||||
}
|
||||
|
||||
String sha512(FineractPluginExtension.FineractPluginGpgParams params) {
|
||||
return calc(new FileInputStream(params.file), MessageDigest.getInstance("SHA-512", BouncyCastleProvider.PROVIDER_NAME))
|
||||
}
|
||||
|
||||
private static String calc(InputStream is, MessageDigest digest) {
|
||||
String output
|
||||
int read
|
||||
byte[] buffer = new byte[8192]
|
||||
|
||||
try {
|
||||
while ((read = is.read(buffer)) > 0) {
|
||||
digest.update(buffer, 0, read)
|
||||
}
|
||||
byte[] hash = digest.digest()
|
||||
BigInteger bigInt = new BigInteger(1, hash)
|
||||
output = bigInt.toString(16)
|
||||
while ( output.length() < 32 ) {
|
||||
output = "0"+output
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error(e.toString(), e)
|
||||
return null
|
||||
}
|
||||
|
||||
return output
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,324 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.gradle.service
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import okhttp3.*
|
||||
import okhttp3.logging.HttpLoggingInterceptor
|
||||
import org.apache.fineract.gradle.FineractPluginExtension
|
||||
import org.jetbrains.annotations.NotNull
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import retrofit2.Call
|
||||
import retrofit2.Retrofit
|
||||
import retrofit2.converter.jackson.JacksonConverterFactory
|
||||
import retrofit2.http.*
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
class JiraService {
|
||||
private static final Logger log = LoggerFactory.getLogger(JiraService.class)
|
||||
|
||||
private JiraApi api
|
||||
|
||||
JiraService(FineractPluginExtension.FineractPluginConfigJira config) {
|
||||
def credentials = Credentials.basic(config.username, config.password)
|
||||
|
||||
final ConnectionPool connectionPool = new ConnectionPool(5, 60, TimeUnit.SECONDS);
|
||||
|
||||
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(log::debug)
|
||||
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY)
|
||||
|
||||
OkHttpClient.Builder okClient = new OkHttpClient.Builder()
|
||||
.connectionPool(connectionPool)
|
||||
.addInterceptor(loggingInterceptor)
|
||||
.addInterceptor(new Interceptor() {
|
||||
@Override
|
||||
Response intercept(@NotNull Interceptor.Chain chain) throws IOException {
|
||||
def request = chain.request()
|
||||
request = request.newBuilder().header("Authorization", credentials).build()
|
||||
return chain.proceed(request)
|
||||
}
|
||||
})
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper()
|
||||
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
||||
|
||||
Retrofit.Builder builder = new Retrofit.Builder()
|
||||
.baseUrl(config.url)
|
||||
.client(okClient.build())
|
||||
.addConverterFactory(JacksonConverterFactory.create(mapper))
|
||||
|
||||
Retrofit retrofit = builder.build()
|
||||
|
||||
this.api = retrofit.create(JiraApi.class)
|
||||
}
|
||||
|
||||
Map<String, Object> serverInfo() {
|
||||
return this.api.serverInfo.execute().body()
|
||||
}
|
||||
|
||||
FineractPluginExtension.FineractPluginJiraParams search(FineractPluginExtension.FineractPluginJiraParams params) {
|
||||
def query = [:]
|
||||
|
||||
query['jql'] = params.query
|
||||
query['startAt'] = params.pageOffset?:0
|
||||
query['maxResults'] = params.pageSize?:50
|
||||
// query['expand'] = [
|
||||
// "names",
|
||||
// "schema",
|
||||
// "operations"
|
||||
// ]
|
||||
// query['fields'] = params.fields?:"*all"
|
||||
query['fields'] = params.includes?:[
|
||||
"summary",
|
||||
"status",
|
||||
"assignee",
|
||||
"fixVersions"
|
||||
]
|
||||
|
||||
// params.total = params.total?:1000
|
||||
params.total = 1000
|
||||
|
||||
def result = this.api.searchIssues(query).execute().body()
|
||||
|
||||
params.result.addAll(result?.issues as List)
|
||||
|
||||
if(result?.issues.size()>=params.pageSize && params.result.size() < params.total) {
|
||||
params.pageOffset += params.pageSize
|
||||
search(params);
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
|
||||
List getProjects() {
|
||||
return this.api.getProjects()?.execute()?.body()
|
||||
}
|
||||
|
||||
List getProjectVersions(String projectId) {
|
||||
return this.api.getProjectVersions(projectId)?.execute()?.body()
|
||||
}
|
||||
|
||||
JiraVersion getVersion(String id) {
|
||||
return this.api.getVersion(id)?.execute()?.body()
|
||||
}
|
||||
|
||||
void updateVersion(JiraVersion version) {
|
||||
this.api.updateVersion(version.id, version).execute()
|
||||
}
|
||||
|
||||
static class JiraVersion {
|
||||
String self
|
||||
String id
|
||||
String description
|
||||
String name
|
||||
boolean archived
|
||||
boolean released
|
||||
String releaseDate
|
||||
String userReleaseDate
|
||||
String project
|
||||
Integer projectId
|
||||
}
|
||||
|
||||
static class JiraSearchResult {
|
||||
String expand
|
||||
Integer startAt
|
||||
Integer maxResults
|
||||
Integer total
|
||||
List<JiraIssue> issues
|
||||
List<String> warningMessages
|
||||
Map<String, Object> names
|
||||
Map<String, Object> schema
|
||||
}
|
||||
|
||||
static class JiraIssue {
|
||||
String expand
|
||||
String self
|
||||
String id
|
||||
String key
|
||||
Map<String, Object> renderedFields
|
||||
Map<String, Object> properties
|
||||
Map<String, Object> names
|
||||
Map<String, Object> schema
|
||||
Map<String, Object> fields
|
||||
}
|
||||
|
||||
static class JiraIssueUpdateRequest {
|
||||
Map<String, Map<String, Object>> historyMetadata
|
||||
Map<String, List<Map<String, Object>>> update
|
||||
Map<String, Object> fields
|
||||
Map<String, List<Map<String, Object>>> properties
|
||||
}
|
||||
|
||||
static interface JiraApi {
|
||||
// Server Info
|
||||
@GET("serverInfo")
|
||||
Call<Map<String, Object>> getServerInfo()
|
||||
|
||||
// Components
|
||||
@GET("component/{id}")
|
||||
Call<Object> getComponent(@Path("id") String id)
|
||||
|
||||
@POST("component")
|
||||
Call<Object> createComponent(@Body Object component)
|
||||
|
||||
@PUT("component/{id}")
|
||||
Call<Void> updateComponent(@Path("id") String id, @Body Object component)
|
||||
|
||||
@GET("component/{id}/relatedIssueCounts")
|
||||
Call<Object> getComponentIssueCount(@Path("id") String id)
|
||||
|
||||
// Issue
|
||||
@GET("issue/{issueIdOrKey}")
|
||||
Call<Object> getIssue(@Path("issueIdOrKey") String issueIdOrKey)
|
||||
|
||||
@POST("issue")
|
||||
Call<Object> createIssue(@Body Object issue)
|
||||
|
||||
@PUT("issue/{issueIdOrKey}")
|
||||
Call<Object> updateIssue(@Path("issueIdOrKey") String issueIdOrKey, @Body Object issue, @QueryMap Map<String, String> queryMap)
|
||||
|
||||
@POST("issue/bulk")
|
||||
Call<Object> createIssues(@Body Object issues)
|
||||
|
||||
@PUT("issue/{issueIdOrKey}/assignee")
|
||||
Call<Void> assignIssue(@Path("issueIdOrKey") String issueIdOrKey, @Body Object user)
|
||||
|
||||
@GET("issue/{issueIdOrKey}/comment")
|
||||
Call<Object> getComments(@Path("issueIdOrKey") String issueIdOrKey)
|
||||
|
||||
@POST("issue/{issueIdOrKey}/comment")
|
||||
Call<Object> addComment(@Path("issueIdOrKey") String issueIdOrKey, @Body Object comment)
|
||||
|
||||
@PUT("issue/{issueIdOrKey}/comment/{id}")
|
||||
Call<Object> updateComment(@Path("issueIdOrKey") String issueIdOrKey, @Path("id") String id, @Body Object comment)
|
||||
|
||||
@GET("issue/{issueIdOrKey}/comment/{id}")
|
||||
Call<Object> getComment(@Path("issueIdOrKey") String issueIdOrKey, @Path("id") String id)
|
||||
|
||||
@POST("issue/{issueIdOrKey}/notify")
|
||||
Call<Void> notifyIssue(@Path("issueIdOrKey") String issueIdOrKey, @Body Object notify)
|
||||
|
||||
@GET("issue/{issueIdOrKey}/transitions?expand=transitions.fields")
|
||||
Call<Object> getTransitions(@Path("issueIdOrKey") String issueIdOrKey)
|
||||
|
||||
@POST("issue/{issueIdOrKey}/transitions")
|
||||
Call<Void> transitionIssue(@Path("issueIdOrKey") String issueIdOrKey, @Body Object issue)
|
||||
|
||||
@GET("issue/{issueIdOrKey}/watchers")
|
||||
Call<Object> getIssueWatches(@Path("issueIdOrKey") String issueIdOrKey)
|
||||
|
||||
@POST("issue/{issueIdOrKey}/watchers")
|
||||
Call<Void> addIssueWatcher(@Path("issueIdOrKey") String issueIdOrKey, @Body String user)
|
||||
|
||||
// Remote Issue Links
|
||||
@GET("issue/{issueIdOrKey}/remotelink")
|
||||
Call<Object> getIssueRemoteLinks(@Path("issueIdOrKey") String issueIdOrKey, @Query("globalId") String globalId)
|
||||
|
||||
@GET("issue/{issueIdOrKey}/remotelink/{linkId}")
|
||||
Call<Object> getIssueRemoteLink(@Path("issueIdOrKey") String issueIdOrKey, @Path("linkId") String linkId)
|
||||
|
||||
@POST("issue/{issueIdOrKey}/remotelink")
|
||||
Call<Object> createIssueRemoteLink(@Path("issueIdOrKey") String issueIdOrKey, @Body Object issueLink)
|
||||
|
||||
@POST("issue/{issueIdOrKey}/remotelink/{linkId}")
|
||||
Call<Object> updateIssueRemoteLink(@Path("issueIdOrKey") String issueIdOrKey, @Path("linkId") String linkId, @Body Object issueLink)
|
||||
|
||||
@DELETE("issue/{issueIdOrKey}/remotelink")
|
||||
Call<Object> deleteIssueRemoteLinks(@Path("issueIdOrKey") String issueIdOrKey, @Query("globalId") String globalId)
|
||||
|
||||
@DELETE("issue/{issueIdOrKey}/remotelink/{linkId}")
|
||||
Call<Object> deleteIssueRemoteLink(@Path("issueIdOrKey") String issueIdOrKey, @Path("linkId") String linkId)
|
||||
|
||||
// Issue Links
|
||||
@POST("issueLink")
|
||||
Call<Void> createIssueLink(@Body Object issueLink)
|
||||
|
||||
@GET("issueLink/{linkId}")
|
||||
Call<Object> getIssueLink(@Path("linkId") String linkId)
|
||||
|
||||
@DELETE("issueLink/{linkId}")
|
||||
Call<Object> deleteIssueLink(@Path("linkId") String linkId)
|
||||
|
||||
// Issue Link Types
|
||||
@GET("issueLinkType")
|
||||
Call<Object> getIssueLinkTypes()
|
||||
|
||||
// Project
|
||||
@GET("project?expand=lead,description")
|
||||
Call<List> getProjects()
|
||||
|
||||
@GET("project/{projectIdOrKey}")
|
||||
Call<Object> getProject(@Path("projectIdOrKey") String projectId)
|
||||
|
||||
@GET("project/{projectIdOrKey}/statuses")
|
||||
Call<Object> getProjectStatuses(@Path("projectIdOrKey") String projectId)
|
||||
|
||||
@GET("project/{projectIdOrKey}/components")
|
||||
Call<Object> getProjectComponents(@Path("projectIdOrKey") String projectId)
|
||||
|
||||
@GET("project/{projectIdOrKey}/versions")
|
||||
Call<List<JiraVersion>> getProjectVersions(@Path("projectIdOrKey") String projectId)
|
||||
|
||||
// Search
|
||||
@POST("search")
|
||||
Call<JiraSearchResult> searchIssues(@Body Map<String, Object> search)
|
||||
|
||||
// Version
|
||||
@POST("version")
|
||||
Call<JiraVersion> createVersion(@Body JiraVersion version)
|
||||
|
||||
@GET("version/{id}")
|
||||
Call<JiraVersion> getVersion(@Path("id") String id)
|
||||
|
||||
@PUT("version/{id}")
|
||||
Call<Void> updateVersion(@Path("id") String id, @Body JiraVersion version)
|
||||
|
||||
// Fields
|
||||
@GET("field")
|
||||
Call<Object> getFields()
|
||||
|
||||
@POST("field")
|
||||
Call<Object> createField(@Body Object field)
|
||||
|
||||
// Users
|
||||
@GET("user/search")
|
||||
Call<Object> userSearch(@Query("username") String userName, @Query("startAt") int startAt, @Query("maxResults") int maxResults)
|
||||
|
||||
@GET("user/assignable/search")
|
||||
Call<Object> assignableUserSearch(@Query("username") String userName, @Query("project") String project, @Query("issueKey") String issueKey, @Query("startAt") int startAt, @Query("maxResults") int maxResults)
|
||||
|
||||
@Multipart
|
||||
@retrofit2.http.Headers("X-Atlassian-Token: no-check")
|
||||
@POST("issue/{issueIdOrKey}/attachments")
|
||||
Call<Object> uploadAttachment(@Path("issueIdOrKey") String issueIdOrKey, @Part MultipartBody.Part file)
|
||||
|
||||
@GET("attachment/{attachmentId}")
|
||||
Call<Object> getAttachment(@Path("attachmentId") String attachmentId)
|
||||
|
||||
@DELETE("attachment/{attachmentId}")
|
||||
Call<Object> deleteAttachment(@Path("attachmentId") String attachmentId)
|
||||
|
||||
@Streaming
|
||||
@GET
|
||||
Call<ResponseBody> downloadFileWithDynamicUrl(@Url String fileUrl)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.gradle.service
|
||||
|
||||
import org.apache.fineract.gradle.FineractPluginExtension
|
||||
import org.gradle.api.GradleException
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
import org.tmatesoft.svn.core.SVNCancelException
|
||||
import org.tmatesoft.svn.core.SVNDepth
|
||||
import org.tmatesoft.svn.core.SVNException
|
||||
import org.tmatesoft.svn.core.SVNURL
|
||||
import org.tmatesoft.svn.core.wc.*
|
||||
|
||||
class SubversionService {
|
||||
private static final Logger log = LoggerFactory.getLogger(SubversionService.class)
|
||||
|
||||
private SVNUpdateClient client;
|
||||
private String revision;
|
||||
|
||||
SubversionService(FineractPluginExtension.FineractPluginConfigSubversion config) {
|
||||
ISVNOptions options = SVNWCUtil.createDefaultOptions(true)
|
||||
SVNClientManager clientManager = SVNClientManager.newInstance(options, SVNWCUtil.createDefaultAuthenticationManager(config.username, config.password))
|
||||
|
||||
this.client = clientManager.updateClient;
|
||||
this.client.ignoreExternals = false
|
||||
this.client.eventHandler = new ISVNEventHandler() {
|
||||
@Override
|
||||
void handleEvent(SVNEvent event, double progress) throws SVNException {
|
||||
println ">>> PROGRESS: ${progress>0?:'-'}"
|
||||
}
|
||||
|
||||
@Override
|
||||
void checkCancelled() throws SVNCancelException {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
this.revision = config.revision
|
||||
}
|
||||
|
||||
void checkout(FineractPluginExtension.FineractPluginSubversionParams params) {
|
||||
SVNURL svnUrl = SVNURL.parseURIEncoded(params.url)
|
||||
|
||||
SVNRevision svnRevision = this.revision == null ? SVNRevision.HEAD : SVNRevision.parse(this.revision)
|
||||
|
||||
if (svnRevision == SVNRevision.UNDEFINED) {
|
||||
throw new GradleException("Invalid SVN revision: " + this.revision)
|
||||
}
|
||||
|
||||
this.client.doCheckout(svnUrl, new File(params.directory), SVNRevision.HEAD, svnRevision, SVNDepth.INFINITY, false)
|
||||
}
|
||||
|
||||
void commit(FineractPluginExtension.FineractPluginSubversionParams params) {
|
||||
// TODO: implement this
|
||||
SVNURL svnUrl = SVNURL.parseURIEncoded(params.url)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.gradle.service
|
||||
|
||||
import freemarker.core.Environment
|
||||
import freemarker.template.Configuration
|
||||
import freemarker.template.Template
|
||||
import freemarker.template.TemplateException
|
||||
import freemarker.template.TemplateExceptionHandler
|
||||
import org.apache.fineract.gradle.FineractPluginExtension
|
||||
import org.slf4j.Logger
|
||||
import org.slf4j.LoggerFactory
|
||||
|
||||
class TemplateService {
|
||||
private static final Logger log = LoggerFactory.getLogger(TemplateService.class)
|
||||
|
||||
private Configuration config
|
||||
|
||||
TemplateService(FineractPluginExtension.FineractPluginConfigTemplate config) {
|
||||
def dir = new File(config.templateDir);
|
||||
|
||||
this.config = new Configuration(Configuration.VERSION_2_3_31);
|
||||
this.config.setDirectoryForTemplateLoading(dir)
|
||||
this.config.setDefaultEncoding("UTF-8");
|
||||
this.config.setLogTemplateExceptions(false);
|
||||
this.config.setWrapUncheckedExceptions(true);
|
||||
this.config.setFallbackOnNullLoopVariable(false);
|
||||
this.config.setTemplateExceptionHandler(new TemplateExceptionHandler() {
|
||||
@Override
|
||||
void handleTemplateException(TemplateException te, Environment env, Writer out) throws TemplateException {
|
||||
if (!env.isInAttemptBlock()) {
|
||||
PrintWriter pw = (out instanceof PrintWriter) ? (PrintWriter) out : new PrintWriter(out);
|
||||
pw.print("FreeMarker template error\n");
|
||||
te.printStackTrace(pw, false, true, false);
|
||||
pw.flush(); // To commit the HTTP response
|
||||
}
|
||||
}}
|
||||
)
|
||||
}
|
||||
|
||||
FineractPluginExtension.FineractPluginTemplateParams render(FineractPluginExtension.FineractPluginTemplateParams params, Object data) {
|
||||
Template template = null;
|
||||
|
||||
if(params.templateFile) {
|
||||
template = new Template("template", new FileReader(new File(params.templateFile)), this.config)
|
||||
}
|
||||
if(params.template) {
|
||||
template = new Template("template", new StringReader(params.template), this.config)
|
||||
}
|
||||
|
||||
if(template) {
|
||||
if(params.outputFile) {
|
||||
def output = new File(params.outputFile)
|
||||
output.createNewFile()
|
||||
|
||||
template.process(data, new FileWriter(output, false))
|
||||
} else {
|
||||
def output = new StringWriter()
|
||||
|
||||
template.process(data, output)
|
||||
|
||||
params.output = output.toString()
|
||||
}
|
||||
}
|
||||
|
||||
return params
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user