FINERACT-1470: Fineract release plugin
This commit is contained in:
committed by
Aleksandar Vidakovic
parent
b185937962
commit
40eb547a5c
@@ -0,0 +1,51 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
plugins {
|
||||
id 'io.spring.dependency-management' version '1.0.11.RELEASE'
|
||||
id 'groovy'
|
||||
id 'java-gradle-plugin'
|
||||
id 'groovy-gradle-plugin'
|
||||
}
|
||||
|
||||
apply from: "${projectDir}/src/main/groovy/org.apache.fineract.dependencies.gradle"
|
||||
|
||||
description = 'Fineract Gradle Plugin'
|
||||
|
||||
repositories {
|
||||
gradlePluginPortal()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.sun.mail:jakarta.mail'
|
||||
implementation 'org.freemarker:freemarker'
|
||||
implementation 'org.tmatesoft.svnkit:svnkit'
|
||||
implementation 'org.bouncycastle:bcprov-jdk15on'
|
||||
implementation 'org.bouncycastle:bcpg-jdk15on'
|
||||
implementation 'org.eclipse.jgit:org.eclipse.jgit'
|
||||
implementation 'org.eclipse.jgit:org.eclipse.jgit.ssh.apache'
|
||||
implementation 'com.vdurmont:semver4j'
|
||||
implementation 'org.beryx:text-io'
|
||||
implementation 'commons-io:commons-io'
|
||||
implementation 'com.squareup.okhttp3:okhttp'
|
||||
implementation 'com.squareup.okhttp3:logging-interceptor'
|
||||
implementation 'com.squareup.retrofit2:retrofit'
|
||||
implementation 'com.squareup.retrofit2:converter-jackson'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind'
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
implementation-class=org.apache.fineract.gradle.FineractPlugin
|
||||
@@ -0,0 +1,34 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<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 = ${project['fineract.release.version']} 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>
|
||||
@@ -0,0 +1,39 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
Hello everyone,
|
||||
|
||||
... based on our "How to Release Apache Fineract" process documented at https://cwiki.apache.org/confluence/x/DRwIB:
|
||||
|
||||
I will create a ${project['fineract.release.version']} branch off develop in our git repository at https://github.com/apache/fineract on ${project['fineract.release.date']}.
|
||||
|
||||
The release tracking umbrella issue for tracking all activity in JIRA is FINERACT-${project['fineract.release.issue']!'0000'} (https://issues.apache.org/jira/browse/FINERACT-${project['fineract.release.issue']!'0000'}) for this Fineract ${project['fineract.release.version']}.
|
||||
|
||||
If you have any work in progress that you would like to see included in this release, please add "blocking" links to the release JIRA issue.
|
||||
|
||||
I am the release manager for this release.
|
||||
|
||||
Cheers,
|
||||
|
||||
${project['fineract.config.name']}
|
||||
|
||||
|
||||
|
||||
🎉 Powered by Fineract Release Plugin 🎊
|
||||
@@ -0,0 +1,21 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
[FINERACT] [PROPOSAL] 📦 New release ${project['fineract.release.version']}
|
||||
@@ -0,0 +1,35 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
Hello everyone,
|
||||
|
||||
... as previously announced, I've just created the release branch for our upcoming ${project['fineract.release.version']} release.
|
||||
|
||||
You can continue working and merging PRs to the develop branch for future releases, as always.
|
||||
|
||||
The DRAFT release notes are on https://cwiki.apache.org/confluence/display/FINERACT/${project['fineract.release.version']}+-+Apache+Fineract. Does anyone see anything missing?
|
||||
|
||||
Does anyone have any last minutes changes they would like to see cherry-picked to branch ${project['fineract.release.version']}, or are we good go and actually cut the release based on this branch as it is?
|
||||
|
||||
I'll initiate the final stage of actually creating the release on ${project['fineract.release.date']} if nobody objects.
|
||||
|
||||
Cheers,
|
||||
|
||||
${project['fineract.config.name']}
|
||||
@@ -0,0 +1,21 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
[FINERACT] [ANNOUNCE] 🔀 ${project['fineract.release.version']} release branch
|
||||
@@ -0,0 +1,43 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
Hello everyone,
|
||||
|
||||
... we have created Apache Fineract ${project['fineract.release.version']} release, with the artifacts below up for a vote.
|
||||
|
||||
It fixes the following issues: https://cwiki.apache.org/confluence/display/FINERACT/${project['fineract.release.version']}+-+Apache+Fineract
|
||||
|
||||
Source & Binary files : https://dist.apache.org/repos/dist/dev/fineract/${project['fineract.release.version']}/
|
||||
|
||||
Tag to be voted on (rc#): https://gitbox.apache.org/repos/asf?p=fineract.git;a=commit;h=refs/heads/${project['fineract.release.version']}
|
||||
|
||||
Fineract's KEYS containing the PGP key we used to sign the release: https://dist.apache.org/repos/dist/dev/fineract/KEYS
|
||||
|
||||
Note that this release contains source and binary artifacts.
|
||||
|
||||
This vote will be open for 72 hours:
|
||||
|
||||
[ ] +1 approve
|
||||
[ ] +0 no opinion
|
||||
[ ] -1 disapprove (and reason why)
|
||||
|
||||
Cheers,
|
||||
|
||||
${project['fineract.config.name']}
|
||||
@@ -0,0 +1,21 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
[FINERACT] [VOTE] 🗳️ ${project['fineract.release.version']} for release
|
||||
@@ -0,0 +1,89 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
<#if (project['fineract.vote'].approve.binding?size + project['fineract.vote'].approve.nonBinding?size > project['fineract.vote'].disapprove.binding?size + project['fineract.vote'].disapprove.nonBinding?size)>
|
||||
Voting is now closed and has passed with the following tally,
|
||||
|
||||
Binding +1s: ${project['fineract.vote'].approve.binding?size}
|
||||
Non binding +1s: ${project['fineract.vote'].approve.nonBinding?size}
|
||||
<#else>
|
||||
Voting is now closed and has not passed with the following tally,
|
||||
|
||||
Binding +1s: ${project['fineract.vote'].approve.binding?size}
|
||||
Non binding +1s: ${project['fineract.vote'].approve.nonBinding?size}
|
||||
|
||||
Binding -1s: ${project['fineract.vote'].disapprove.binding?size}
|
||||
Non binding -1s: ${project['fineract.vote'].disapprove.nonBinding?size}
|
||||
</#if>
|
||||
|
||||
Here are the detailed results:
|
||||
|
||||
<#list project['fineract.vote'].approve.binding>
|
||||
Binding +1s:
|
||||
<#items as item>
|
||||
- ${item.name} (${item.email})
|
||||
</#items>
|
||||
</#list>
|
||||
|
||||
|
||||
<#list project['fineract.vote'].approve.nonBinding>
|
||||
Non binding +1s:
|
||||
<#items as item>
|
||||
- ${item.name} (${item.email})
|
||||
</#items>
|
||||
</#list>
|
||||
|
||||
|
||||
<#list project['fineract.vote'].disapprove.binding>
|
||||
Binding -1s:
|
||||
<#items as item>
|
||||
- ${item.name} (${item.email})
|
||||
</#items>
|
||||
</#list>
|
||||
|
||||
<#list project['fineract.vote'].disapprove.nonBinding>
|
||||
Non binding -1s:
|
||||
<#items as item>
|
||||
- ${item.name} (${item.email})
|
||||
</#items>
|
||||
</#list>
|
||||
|
||||
|
||||
<#list project['fineract.vote'].noOpinion.binding>
|
||||
Binding +0s:
|
||||
<#items as item>
|
||||
- ${item.name} (${item.email})
|
||||
</#items>
|
||||
</#list>
|
||||
|
||||
<#list project['fineract.vote'].noOpinion.nonBinding>
|
||||
Non binding +0s:
|
||||
<#items as item>
|
||||
- ${item.name} (${item.email})
|
||||
</#items>
|
||||
</#list>
|
||||
|
||||
<#if (project['fineract.vote'].approve.binding?size + project['fineract.vote'].approve.nonBinding?size > project['fineract.vote'].disapprove.binding?size + project['fineract.vote'].disapprove.nonBinding?size)>
|
||||
Thanks to everyone who voted! I'll now continue with the rest of the release process.
|
||||
<#else>
|
||||
Thanks to everyone who voted! Looks like we have to repeat the vote.
|
||||
</#if>
|
||||
|
||||
${project['fineract.config.name']}
|
||||
@@ -0,0 +1,21 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
[FINERACT] [VOTE] [RESULT] 🧾️ ${project['fineract.release.version']} for release
|
||||
@@ -0,0 +1,43 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
The Apache Fineract project is pleased to announce
|
||||
the release of Apache Fineract ${project['fineract.release.version']}.
|
||||
The release is available for download from
|
||||
https://fineract.apache.org/#downloads
|
||||
|
||||
Fineract provides a reliable, robust, and affordable solution for entrepreneurs,
|
||||
financial institutions, and service providers to offer financial services to the
|
||||
world’s 2 billion underbanked and unbanked. Fineract is aimed at innovative mobile
|
||||
and cloud-based solutions, and enables digital transaction accounts for all.
|
||||
|
||||
This release addressed ${project['fineract.release.issues']?size} issues.
|
||||
|
||||
Readme: https://github.com/apache/fineract/blob/${project['fineract.release.version']}/README.md
|
||||
|
||||
Release page: https://cwiki.apache.org/confluence/display/FINERACT/${project['fineract.release.version']}+-+Apache+Fineract
|
||||
|
||||
List of fixed issues:
|
||||
https://issues.apache.org/jira/secure/ReleaseNote.jspa?version=${project['fineract.release.versionId']}&styleName=Html&projectId=${project['fineract.release.projectId']}
|
||||
|
||||
For more information on Apache Fineract please visit
|
||||
project home page: https://fineract.apache.org
|
||||
|
||||
The Apache Fineract Team
|
||||
@@ -0,0 +1,21 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
[ANNOUNCE] Apache Fineract ${project['fineract.release.version']} Release
|
||||
@@ -0,0 +1,21 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
Fineract ${project['fineract.release.version']} release
|
||||
@@ -0,0 +1,38 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
[INSTRUCTIONS:START]
|
||||
|
||||
As discussed in https://issues.apache.org/jira/browse/FINERACT-1154, now that everything is final, please do the following to remove the release branch (and just keep the tag),
|
||||
and make sure that everything on the release tag is merged to develop and that e.g. git describe works:
|
||||
|
||||
>> git checkout develop
|
||||
>> git branch -D ${project['fineract.release.version']}
|
||||
>> git push origin :${project['fineract.release.version']}
|
||||
>> git checkout develop
|
||||
>> git checkout -b merge-${project['fineract.release.version']}
|
||||
>> git merge -s recursive -Xignore-all-space ${project['fineract.release.version']}
|
||||
>> git commit
|
||||
>> git push <USER>
|
||||
>> hub pull-request
|
||||
|
||||
[INSTRUCTIONS:END]
|
||||
@@ -0,0 +1,28 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
[INSTRUCTIONS:START]
|
||||
|
||||
Finally update the https://fineract.apache.org website with the latest release details.
|
||||
The website's HTML source code is available at https://github.com/apache/fineract-site.
|
||||
|
||||
[INSTRUCTIONS:END]
|
||||
@@ -0,0 +1,39 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
[INSTRUCTIONS:START]
|
||||
|
||||
Before a release is done, make sure that any issues that are fixed have their fix version setup correctly.
|
||||
|
||||
"project = FINERACT and resolution = fixed and fixVersion is empty"
|
||||
|
||||
Move all unresolved JIRA issues which have this release as Fix Version to the next release
|
||||
|
||||
"project = FINERACT and fixVersion = ${project['fineract.release.version']} and status not in ( Resolved, Done, Accepted, Closed )"
|
||||
|
||||
You can also run the following query to make sure that the issues fixed for the to-be-released version look accurate:
|
||||
|
||||
"project = FINERACT and fixVersion = ${project['fineract.release.version']}"
|
||||
|
||||
Finally, check out the output of the JIRA release note tool to see which tickets are included in the release, in order to do a sanity check.
|
||||
|
||||
[INSTRUCTIONS:END]
|
||||
@@ -0,0 +1,29 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
[INSTRUCTIONS:START]
|
||||
|
||||
You first need to close the release in JIRA so that the about to be released version cannot be used as "fixVersion" for new bugs anymore.
|
||||
Go to JIRA "Administer project" page and follow "Versions" in left menu. Table with list of all releases should appear, click on additional menu on the right of your release and choose "Release" option.
|
||||
Submit release date and you're done.
|
||||
|
||||
[INSTRUCTIONS:END]
|
||||
@@ -0,0 +1,38 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
[INSTRUCTIONS:START]
|
||||
|
||||
Following are the typical things we need to verify before voting on a release candidate. And the release manager should verify them too before calling out a vote.
|
||||
|
||||
Make sure release artifacts are hosted at https://dist.apache.org/repos/dist/dev/fineract
|
||||
|
||||
* Release candidates should be in format apache-fineract-${project['fineract.release.version']}-binary.tar.gz
|
||||
* Verify signatures and hashes. You may have to import the public key of the release manager to verify the signatures. (`gpg --recv-key <key id>`)
|
||||
* Git tag matches the released bits (diff -rf)
|
||||
* Can compile successfully from source
|
||||
* Verify DISCLAIMER, NOTICE and LICENSE (year etc)
|
||||
* All files have correct headers (Rat check should be clean - gradlew rat)
|
||||
* No jar files in the source artifacts
|
||||
* Integration tests should work
|
||||
|
||||
[INSTRUCTIONS:END]
|
||||
@@ -0,0 +1,33 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
= Changelog
|
||||
|
||||
== Breaking Changes
|
||||
|
||||
<#list issues?filter(i -> i.fields.labels?seq_contains("BreakingChange")) as issue>
|
||||
* [[${issue.key}]]${issue.key} - ${issue.fields.summary}
|
||||
</#list>
|
||||
|
||||
== Issues
|
||||
|
||||
<#list issues as issue>
|
||||
* [[${issue.key}]]${issue.key} - ${issue.fields.summary}
|
||||
</#list>
|
||||
@@ -0,0 +1,26 @@
|
||||
<#--
|
||||
|
||||
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.
|
||||
|
||||
-->
|
||||
Changelog
|
||||
=========
|
||||
|
||||
<#list issues as issue>
|
||||
* ${issue.key} - ${issue.fields.summary}
|
||||
</#list>
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"approve": {
|
||||
"binding": [
|
||||
{
|
||||
"name": "Some Body",
|
||||
"email": "bob@apache.org"
|
||||
}
|
||||
]
|
||||
},
|
||||
"disapprove": {
|
||||
"binding": [
|
||||
],
|
||||
"nonBinding": [
|
||||
]
|
||||
},
|
||||
"noOpinion": {
|
||||
"binding": [
|
||||
],
|
||||
"nonBinding": [
|
||||
]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user