背景是为了整合在jira的Tempo中记录的工时,与在confluence上记录的周报,并自动合成pdf周报。
开始寻找导出工具,考虑输出excel,word等方式,最后选择了jira的插件Better PDF Exporter for Jira来输出pdf。这个插件能定制化格式,并引入jira中多种类型数据,比较好用。使用vm模板issue-fo就包含了多种数据类型,包括Tempo日志。
流程是:在JIra中检索需输出的issue生成issue列表-->获取issue的相关信息如获取相关的confluence页面-->将issue列表和<issue key, 对应内容信息>传给pdfApi.getPdf-->调用vm模板(Velocity语言)-->按照模板生成pdf-->发送email
1. 以scriptrunner中使用Midori(better pdf Exporter)的例子做为基础扩展。可参见第一个Email的例子 -- https://scriptrunner.adaptavist.com/latest/jira/plugins/working-with-midori.html
在scriptrunner的script console中,使用此例子,可以把要导出的问题列表换位搜索出的问题列表。Debug使用log.warn(***)
def jqlSearch = "project = RPM AND issuetype = 项目流程管理 AND status in (Open, Pending, 规划, 设计, 开发, 维护, 实施) " def user = ComponentAccessor.jiraAuthenticationContext.getLoggedInUser() def searchService = ComponentAccessor.getComponent(SearchService) def parseResult = searchService.parseQuery(user, jqlSearch) if (parseResult.isValid()) { SearchResults searchResult = searchService.search(user, parseResult.getQuery(), PagerFilter.getUnlimitedFilter()) List Results = searchResult.getResults()再把输出函数中,传入的issue列表换为检索出的Results。pdfResult = pdfApi.getPdf(templateName, pdftitle.toString(), Results, [:])
2 判断获取的issue列表中issue是否符合日期条件,使用java的LocalDate
LocalDate today = LocalDate.now() date = content.substring(strStartIndex, strEndIndex) date = date.replace("/","-") LocalDate reportDay = LocalDate.parse(date) if (today.toEpochDay()-reportDay.toEpochDay()>9){ continue }
3 从issue的comment中获取网址,使用pattern
def commentManager = ComponentAccessor.getCommentManager() def comments = commentManager.getComments(issue) for (comment in comments){ def content = comment.getBody() if (content.contains("http")){ Pattern pattern = Pattern.compile("https?://[-a-zA-Z0-9+&@#/%?=~_|!:,.;]*[-a-zA-Z0-9+&@#/%=~_|]") Matcher matcher = pattern.matcher(content); if (matcher.find()){ ContentMap.put(issue.key,matcher.group().substring(matcher.group().indexOf('/',10))) } }
4 https协议下登录confluence页面,验证并获取页面内容
SSLContextBuilder builder = new SSLContextBuilder() builder.loadTrustMaterial(null, new TrustSelfSignedStrategy()); SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(),NoopHostnameVerifier.INSTANCE) CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build() CredentialsProvider credsProvider = new BasicCredentialsProvider() credsProvider.setCredentials(AuthScope.ANY, new NTCredentials("user","PASSWD", "", "")) // Create AuthCache instance AuthCache authCache = new BasicAuthCache() // Generate BASIC scheme object and add it to the local auth cache BasicScheme basicAuth = new BasicScheme() HttpHost target = new HttpHost("IP", PORT, "https"); authCache.put(target, basicAuth) // Make sure the same context is used to execute logically related requests HttpClientContext context = HttpClientContext.create() context.setCredentialsProvider(credsProvider) context.setAuthCache(authCache) HttpGet httpget = new HttpGet(entry.getValue()) CloseableHttpResponse response = httpclient.execute(target, httpget, context) try { StringBuilder sb = new StringBuilder(2048) HttpEntity entityRes = response.getEntity() Reader reader = new InputStreamReader(entityRes.getContent(),"UTF-8") def data while ((data = reader.readLine()) !=null ) { sb.append(data) } } response.getEntity().getContent().close()
5 精简获取到的页面内容
String regex_title = "<title>.*?</title>" String regex_table = "<table.*>.*</table>" final Pattern pa_title = Pattern.compile(regex_title, Pattern.CANON_EQ); final Pattern pa_talbe = Pattern.compile(regex_table, Pattern.CANON_EQ); final Matcher ma_table = pa_talbe.matcher(sb) final Matcher ma_title = pa_title.matcher(sb); while (ma_title.find()) { list.add(ma_title.group()) }
6 使用Jsoup(https://jsoup.org/cookbook/)处理并解析获得的网页内容,clean清理不必要的标签,使用Document和Elements解析html标签。
Whitelist relax = Whitelist.relaxed(); relax.addTags("title"); String JResult = Jsoup.clean(html, relax) Document doc = Jsoup.parse(JResult) Elements Title = doc.select("title") contentResult.add(Title.text()) Elements titles = doc.getElementsByTag("th") List<String> titleResult = new ArrayList<String>() for (Element title : titles) { String sTitle = title.text() if (!sTitle.contains("报告")) { titleResult.add(sTitle) } }
7 输出pdf,issue列表为issueList,自定义参数Report传递map变量ResultMap<String,LIst>(issue key与对应信息)
def pdfApiClass = this.class.forName('com.midori.jira.plugin.pdfview.api.PdfApi', true, ComponentAccessor.pluginAccessor.classLoader) def pdfApi = ComponentAccessor.getOSGiComponentInstanceOfType(pdfApiClass) ComponentAccessor.jiraAuthenticationContext.setLoggedInUser(user) pdfResult = pdfApi.getPdf(templateName, pdftitle.toString(), issueList, [Report:ResultMap])
8 自定义vm模板。在JIRA的插件-->Better PDF Exporter-->PDF Templates中,可以依据现有vm自定义vm模板。语言使用Velocity,格式为XSL-FO格式(https://www.runoob.com/xslfo/xslfo-tutorial.html)。$velocityCount是自带变量,记录循环次数,可直接使用。Report变量是从pdfAPI.getPdf传入的Map变量。
#foreach($item in $Report.entrySet()) #if($item.key == $issue.key) <fo:table-row> <fo:table-cell padding="4px"> #foreach($content in $item.value) #if($velocityCount == 1) <fo:block padding="4px" start-indent="4px" end-indent="4px" background-color="#F5F5F5" font-weight="bold" text-align="center">$i18n.getText($content)</fo:block> #else <fo:block padding="4px" start-indent="4px" end-indent="4px">$i18n.getText($content)</fo:block> #end #end </fo:table-cell> </fo:table-row> #end #end
9 获取字符串中最后一个指定字符串后的所有字符
StringUtils.substringAfterLast(c_table, "<table")
10. 所需要的import
import com.atlassian.jira.bc.issue.search.SearchService import com.atlassian.jira.component.ComponentAccessor import com.atlassian.jira.issue.IssueManager import com.atlassian.jira.issue.Issue import com.atlassian.jira.issue.search.SearchResults import com.atlassian.jira.web.bean.PagerFilter import javax.activation.DataHandler import javax.mail.internet.MimeBodyPart import javax.mail.internet.MimeMultipart import com.atlassian.jira.mail.util.ByteArrayDataSource import com.atlassian.mail.Email import com.atlassian.mail.queue.SingleMailQueueItem import com.atlassian.jira.issue.search.SearchProvider import com.atlassian.jira.jql.parser.JqlQueryParser //时间处理 import java.time.LocalDate import java.time.Period //Pattern检索 import java.util.regex.Matcher import java.util.regex.Pattern //https授权登录相关 import org.apache.http.ssl.SSLContextBuilder import org.apache.http.conn.ssl.TrustSelfSignedStrategy import org.apache.http.conn.ssl.SSLConnectionSocketFactory import org.apache.http.impl.client.CloseableHttpClient import org.apache.http.impl.client.HttpClients import org.apache.http.client.CredentialsProvider import org.apache.http.impl.client.BasicCredentialsProvider import org.apache.http.auth.AuthScope import org.apache.http.auth.UsernamePasswordCredentials import org.apache.http.client.methods.HttpGet import org.apache.http.client.methods.CloseableHttpResponse import org.apache.http.HttpEntity import org.apache.http.conn.ssl.NoopHostnameVerifier import org.apache.http.auth.NTCredentials import org.apache.http.client.protocol.HttpClientContext import org.apache.http.HttpHost import org.apache.http.client.AuthCache import org.apache.http.impl.auth.BasicScheme import org.apache.http.impl.client.BasicAuthCache //Jsoup相关 import org.jsoup.Jsoup import org.jsoup.safety.Whitelist import org.jsoup.nodes.Element import org.jsoup.nodes.Document import org.jsoup.select.Elements //字符串处理 import org.apache.commons.lang3.StringUtils
相关推荐
手把手教你如何整合jira+confluence的用户管理,实现jira+confluence使用同一套用户。
Jira ScriptRunner脚本-根据子任务修改父任务自定义字段状态
Adaptavist的Jira的ScriptRunner的Groovy脚本和代码段 ListCustomFieldsUsage.groovy是一个脚本,它将在您的Jira Server(或数据中心)实例中查找所有自定义字段,如果该字段是全局的(即,该字段没有上下文),则...
解决 JIRA 与 Confluence 数据无法同步问题,
JIRA是Atlassian公司出品的项目与事务跟踪工具,被广泛应用于缺陷跟踪、客户服务、需求收集、流程审批、任务跟踪、项目跟踪和敏捷管理等工作领域。 Confluence是一个专业的企业知识管理与协同软件,也可以用于构建...
crowd2.7下载:http://downloads.atlassian.com/software/crowd/downloads/atlassian-crowd-2.7.0.zip crowd安装+破解+集成jira+集成confluence
Jira&Confluence安装配置说明
docker安装jira7.13 confluence6.8 mysql5.7 ,synapseRT插件安装及用户同步。包下载https://download.csdn.net/download/qq_37037618/12739326
本节课程将介绍JIRA及Confluence集成于敏捷项目中的应用实践。重点在Scrum计划会议、立会、反思及检讨会议如何透过JIRA及Confluence实现协同合作,进而帮助敏捷团队持续过程改进。
linux下mysql、jira、confluence整合.docxlinux下mysql、jira、confluence整合.docx
jira与testlink整合(jira用oracle数据库)
jira_6.0.* confluence 5.0.* 语言包+破解包 请低调使用。毕竟没有花钱的东西。里面如何使用都有详细的readme。
admins looking to extend JIRA should also consult the JIRA Space in Confluence. Here are some pointers to get you started: • Not yet downloaded JIRA? You can get it from the JIRA download page. • ...
JDK+Crowd+JIRA+Confluence安装教程 JDK+Crowd+JIRA+Confluence安装教程
1. jira8.22.0数据备份还原、附件备份还原 2. jira项目导出和导入 3. confluence7.16数据备份和还原 4. confluence7.16附件备份和还原 5. confluence7.16空间导出和导入
1. JIRA用户使用指南-简化版.pdf 2. 工作流介绍.pdf 3. 使用JIRA搭建企业问题跟踪系统.pdf 4. jira 4.0.1 汉化包 ------------------------------------------------------------ 以前下载要求资源分, 现在取消了. ...
JIRA 、Confluence Switch User 插件 就像 linux 里面的 su 命令一样,管理员可以切换到其它用户身份来使用系统,而无需要知道或改变该用户的密码,方便调试。 其中 Confluence Switch User 插件是有管理和配置界面...
Confluence JIRA 报表(JIRA Report)蓝图 - CWIKIOSSEZ
Jira配置指南[整理].pdf
CentOS系统安装JDK+Crowd+JIRA+Confluence教程1