import com.atlassian.jira.JiraDataType;
import com.atlassian.jira.JiraDataTypes
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.search.SearchProvider
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.query.Query;
import com.atlassian.jira.jql.parser.JqlParseException;
// import com.atlassian.jira.issue.search.SearchQuery
import com.atlassian.jira.jql.operand.QueryLiteral
import com.atlassian.jira.jql.parser.JqlQueryParser
import ru.mail.jira.plugins.groovy.util.lucene.IssueIdCollector;
import com.atlassian.jira.jql.query.QueryCreationContext
import com.atlassian.jira.jql.validator.NumberOfArgumentsValidator
import com.atlassian.jira.user.ApplicationUser
import com.atlassian.jira.util.MessageSet
import com.atlassian.jira.util.MessageSetImpl
import com.atlassian.query.clause.TerminalClause
import com.atlassian.query.operand.FunctionOperand
import ru.mail.jira.plugins.groovy.api.jql.ScriptedJqlValuesFunction
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
class DemoFunction implements ScriptedJqlValuesFunction {
  private final Logger logger = LoggerFactory.getLogger(DemoFunction.class);
  @Override
  public JiraDataType getDataType() {
    return JiraDataTypes.ISSUE;
  @Override
  public MessageSet validate(ApplicationUser searcher, FunctionOperand operand, TerminalClause terminalClause) {
    def i18n = ComponentAccessor.getI18nHelperFactory().getInstance(searcher)
    def numberValidMessage = new NumberOfArgumentsValidator(1i, i18n).validate(operand);
    if (numberValidMessage.hasAnyErrors()) {
      return numberValidMessage
    def messageSet = new MessageSetImpl();
    JqlQueryParser jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser)
    try {
      def query = jqlQueryParser.parseQuery(operand.getArgs().get(0))
      // messageSet.addMessage(MessageSet.Level.WARNING, "jqlQueryParser :${query}");
    } catch (any) {
      messageSet.addErrorMessage("not valid jql:${operand.getArgs().get(0)}");
      messageSet.addErrorMessage("${any}");
    return messageSet
  public List<QueryLiteral> getValues(QueryCreationContext queryCreationContext, FunctionOperand functionOperand, TerminalClause terminalClause) {
    final List<QueryLiteral> literals = new LinkedList<>();
    String jql = functionOperand.getArgs().get(0);
    for (MutableIssue issue: getIssuesByJQL(jql, queryCreationContext.getApplicationUser()) ){
      literals.add(new QueryLiteral(functionOperand, issue.getKey()));
      for (Issue subIssue: issue.getSubTaskObjects()){
        literals.add(new QueryLiteral(functionOperand, subIssue.getKey()));
    return literals;
  private Collection<MutableIssue> getIssuesByJQL(String jql, ApplicationUser user) {
    JqlQueryParser jqlQueryParser = ComponentAccessor.getComponent(JqlQueryParser.class);
    SearchProvider searchProvider = ComponentAccessor.getComponent(SearchProvider.class);
    IssueManager issueManager = ComponentAccessor.getIssueManager();
      Query query = jqlQueryParser.parseQuery(jql);
      Collection<MutableIssue>  issues = new ArrayList<>();
      IssueIdCollector collector = new IssueIdCollector();
      searchProvider.search(query, user, collector);
      logger.error("query:{}, user:{}, collector:{}, IssueIds:{} ", query, user, collector, collector.getIssueIds());
      for(String issueId: collector.getIssueIds()){
        logger.error("issueId:{}, issue:{}",issueId, issueManager.getIssueObject(new Long(issueId)));
        // issues.add(issueManager.getIssueObject(issueId));
        issues.add(issueManager.getIssueObject(new Long(issueId)));
      return issues;
    }catch (JqlParseException jqlParseException){
      System.out.println("jqlParseException:" + jqlParseException);
    }catch (Exception exception){
      System.out.println("exception:" + exception);
    return null;

效果如下:

JiraMyGroovy脚本git@github.com:mailru/jira-scripts.git样例代码如下:import com.atlassian.jira.JiraDataType;import com.atlassian.jira.JiraDataTypesimport com.atlassian.jira.component.ComponentAccessorimport com.atlassian.jira.issue.MutableIss... JIRA的高级搜索功能类似于SQL查询,是使用Jira查询语言(JQL)构建结构化查询来搜索问题。可以指定无法在快速或基本搜索中定义的条件(例如, ORDER BY 句)。 注意,即使JQL使用类似SQL的语法,它也不是数据库查询语言。 一、如何执行高级搜索? 导航到Issues > Search for Issues 如果存在现有搜索条件,请单击“ New filter” 按钮以重置搜索条 不断的总结,才能不断的提高;不断的思考,才能不断的进步! 上面是我收集的一些视频资源,在这个过程中帮到了我很多。如果你不想再体验一次自学时找不到资料,没人解答问题,坚持几天便放弃的感受的话,可以加入我们群【902061117】,里面有各种软件测试资源和技术讨论。 当然还有面试,面试一般分为技术面和hr面,形式的话很少有群面.
通过故事而不是任务进行交流 上一次我谈论代码段之间的接口 。 今天,我想讨论参与开发软件的人群之间的接口。 有两个基本组:开发软件的人和协调开发的人。 用敏捷术语来说,这些小组一方面是开发团队,另一方面是产品所有者和其他利益相关者。 说相同的语言 这两个小组需要沟通,因此当每个人都讲相同的语言时,他们会做到最好。 首先要说相同的“自然”语言,例如英语。 对于将要给定的大多数团队,但...
使用jira管理Scrum敏捷项目(五)使用jira对项目、产品的全生命周期的管理、迭代前言一、自定义jira看板二、分享我的技术团队中的看板设置总结 jira环境搭建请参考我的另外一篇文章:链接: 使用docker搭建jira环境. jira是一款非常适合敏捷开发团队使用的一款事务管理软件。很多大型互联网公司都在使用,既然好用,那我们尽管用就好了,小公司就可以按照专栏第一篇文章,搭建一下环境白嫖一把就好了。 在这里简单介绍一下jira的几个特性: 1.需求管理 2.BUG管理、缺陷跟踪 3.任务管理
获取jira任务的信息1.背景2.探究3.解决4.总结 最近做一个demo项目,需要能够显示jira任务的状态信息,所以就稍微探究了一下jira的api和一些发请求的方法。 一开始发现jira提供的jira-client-api中有jiraclient类,通过它很容易就可以获取到对应的任务的信息,但是如果依赖jar,存在一个问题,就是该jar中依赖到的jar都必须要依赖,所以只引入一个client-api.jar是远远不够的,运行时会报错,之后就根据报错去maven仓库搜,再这样操作引入
拖放以重新排序任务。 “ JIRA任务可排序”是JIRA任务的细微增强。这使您可以通过拖放来移动它们,而不是使用烦人的小箭头。将任务拖动到所需位置后,其位置将透明保存,因此不需要重新加载。 支持语言:English,한국어
- 【设计出图】@{summary} / issueType:"简单任务" component:"@inherit" assignee:"xxx" fixversion:"@inherit" 需求复杂度:"@inherit" - 【测试用例】@{summary} / issueType:"简单任务" component:"@inherit" assignee:"xxx" fixversion:"