Tornando as funções SIL portáteis entre versões no Jira

Olá a todos!

Neste artigo, continuamos a discussão sobre o desenvolvimento de nossas próprias funções para o SIL. O artigo anterior pode ser lido aqui .

Uma das principais vantagens do SIL é que o código escrito no SIL funcionará em todas as versões do Jira, por isso precisamos fazer com que nossas funções personalizadas funcionem também.

Crie um plugin a partir do sil-extension-archetype


Clone o arquétipo:

git clone https://alex1mmm@bitbucket.org/alex1mmm/sil-extension-archetype.git --branch v1 --single-branch

Instale o arquétipo no repositório local e crie um plug-in a partir desse arquétipo. Mais detalhes sobre como fazer isso podem ser encontrados aqui .

Adicionar serviços SIL


Para tornar nossa função portátil entre diferentes versões do Jira, usaremos os serviços que o SIL fornece. Essa. proxy nossas chamadas para a API Jira Java via SIL Java Api.

Mas como você sabe quais serviços a SIL oferece?

Instalamos o SIL e vamos para o seguinte endereço:

localhost : 2990 / jira / plugins / servlet / upm / osgi

Você verá informações OSGI em todos os plug-ins em Jira:



Encontraremos o plug-in na lista KATL Commons e



abriremos os serviços registrados: JMUserServices, JMProjectServices são os serviços que exportam Sil.

Agora sabemos quais serviços SIL estão disponíveis e, pelo nome do serviço, podemos adivinhar sua finalidade.

Vamos ver o código no plugin criado


Agora sabemos quais serviços estão disponíveis para nós. Vamos usá-los em nosso plugin.

BeanService.java


@Named
public class BeanService {
    @Getter
    private final KIssueService kIssueService;
    @Getter
    private final ClassLoaderService classLoaderService;
    @Getter
    private final CurrentUserHelper currentUserHelper;
    @Getter
    private final JMIssueSearchServices jmIssueSearchServices;
    @Getter
    private final UserHelper userHelper;
    @Getter
    private final JMIssueServices jmIssueServices;
    @Inject
    public BeanService(@ComponentImport KIssueService kIssueService,
                       @ComponentImport CurrentUserHelper currentUserHelper,
                       @ComponentImport JMIssueSearchServices     jmIssueSearchServices,
                       @ComponentImport UserHelper userHelper,
                       @ComponentImport JMIssueServices jmIssueServices,
                       ClassLoaderService classLoaderService) {
        this.kIssueService = kIssueService;
        this.classLoaderService = classLoaderService;
        this.currentUserHelper = currentUserHelper;
        this.jmIssueSearchServices = jmIssueSearchServices;
        this.userHelper = userHelper;
        this.jmIssueServices = jmIssueServices;
    }
}

Esta classe contém todos os serviços que usaremos para nossas funções. Crio uma classe separada para não duplicar a chamada para serviços em cada função.

Vejamos estas linhas:

@Getter
 private final KIssueService kIssueService;

Getteressa é uma anotação do Lombok que cria um método get para a propriedade kIssueService.

Criamos propriedades de classe para cada serviço usado. Em seguida, obtemos esses serviços através do construtor.

    public BeanService(@ComponentImport KIssueService kIssueService,
                       @ComponentImport CurrentUserHelper currentUserHelper,
                       @ComponentImport JMIssueSearchServices jmIssueSearchServices,
                       @ComponentImport UserHelper userHelper,
                       @ComponentImport JMIssueServices jmIssueServices,
                       ClassLoaderService classLoaderService) {
        this.kIssueService = kIssueService;
        this.classLoaderService = classLoaderService;
        this.currentUserHelper = currentUserHelper;
        this.jmIssueSearchServices = jmIssueSearchServices;
        this.userHelper = userHelper;
        this.jmIssueServices = jmIssueServices;
    }

Feito.

Adicione o bean BeanService à classe ESLauncher e passe esse bean para nossas funções:

/*   BeanService */
private final BeanService beanService;

@Inject
public ESLauncher(@ComponentImport EventPublisher eventPublisher,
                  PluginInfoService pluginInfoService,
                  @ComponentImport CommonPluginConfigurationService commonPluginConfigurationService,
                  @ComponentImport HostConfigurationProvider hostConfigurationProvider,
                  @ClasspathComponent PluginConfigurationServiceImpl pluginConfigurationService,
/*  BeanService */
                  BeanService beanService)
{
    super(eventPublisher, pluginInfoService, hostConfigurationProvider, pluginConfigurationService);

    log.error("eslauncher constructor");
    this.beanService = beanService;

}

@Override
public void doAtLaunch() {
    super.doAtLaunch();
    log.error("eslauncher doatlaunch");
    RoutineRegistry.register(new SayHello( beanService,"SayHello"));
    RoutineRegistry.register(new SayHello2( beanService,"SayHello2"));
    RoutineRegistry.register(new SayHello3( beanService,"SayHello3"));

}

Agora podemos usar o BeanService em nossas funções.

SayHello.java


No SayHello.java, criaremos uma função que aceitará o endereço de email do usuário, verificaremos se o usuário que executa o script do administrador exclui todos os tickets criados pelo usuário com o endereço de email transmitido.

Obviamente, podemos fazer essa lógica sem escrever nossa própria função. O código SIL ficará assim:

function deleteIssueForUser(string userEmail) {
  if (isUserInGroup("jira-administrators", currentUserKey())) {
    string[] issues = selectIssues("reporter = " + currentUserKey());
    for (string issue in issues) {
      deleteIssue(issue);
    }
  }
}

deleteIssueForUser("user@email.com");

Mas eu queria dar um pequeno exemplo que mostrasse os princípios básicos do trabalho.

Aqui está o texto da classe:

@Slf4j
public class SayHello extends AbstractSILRoutine<MutableString> {
    private static final SILType[][] types = {{ TypeInst.STRING }};
    private final BeanService beanService;

    public SayHello(BeanService beanService, String name) {
        super(beanService.getClassLoaderService().getPluginClassLoader(), name, types);
        this.beanService = beanService;
    }

    @Override
    public SILType<MutableString> getReturnType() {
        return TypeInst.STRING;
    }


    @Override
    protected SILValue<MutableString>  runRoutine(SILContext silContext, List<SILValue<?>> list)  {
        SILValue param = list.get(0);
        String userEmail = param.toStringValue();
        KIssueService kIssueService = beanService.getKIssueService();
        CurrentUserHelper currentUserHelper = beanService.getCurrentUserHelper();
        JMIssueSearchServices jmIssueSearchServices = beanService.getJmIssueSearchServices();
        UserHelper userHelper = beanService.getUserHelper();
        JMIssueServices jmIssueServices = beanService.getJmIssueServices();
        ApplicationUser requestedUser = userHelper.getUserByEmail(userEmail);

        if (currentUserHelper.isUserAdministrator()) {
            SearchService.ParseResult parseResult = jmIssueSearchServices.getSearchService().parseQuery(requestedUser, "reporter = " + requestedUser.getKey());
            List<Issue> issues = (List<Issue>) kIssueService.searchIssues(requestedUser, parseResult.getQuery());
            issues.stream().forEach(issue -> kIssueService.deindexIssue(jmIssueServices.getIssueManager().getIssueByCurrentKey(issue.getKey())));
        }
        return SILValueFactory.string( "issues deleted");

    }

    @Override
    public String getParams() {
        return "(userEmail)";
    }
}

Implementamos a lógica no método runRoutine:

    @Override
    protected SILValue<MutableString>  runRoutine(SILContext silContext, List<SILValue<?>> list)  {

/*     */

        SILValue param = list.get(0);
        String userEmail = param.toStringValue();

/*       SIL */

        KIssueService kIssueService = beanService.getKIssueService();
        CurrentUserHelper currentUserHelper = beanService.getCurrentUserHelper();
        JMIssueSearchServices jmIssueSearchServices = beanService.getJmIssueSearchServices();
        UserHelper userHelper = beanService.getUserHelper();
        JMIssueServices jmIssueServices = beanService.getJmIssueServices();

/*  SIL UserHelper,   ApplicationUser    */

        ApplicationUser requestedUser = userHelper.getUserByEmail(userEmail);

/*  SIL CurrentUserHelper,  ,     Jira */

        if (currentUserHelper.isUserAdministrator()) {

/*   SIL      JQL  */

            SearchService.ParseResult parseResult = jmIssueSearchServices.getSearchService().parseQuery(requestedUser, "reporter = " + requestedUser.getKey());
            List<Issue> issues = (List<Issue>) kIssueService.searchIssues(requestedUser, parseResult.getQuery());

/*    */

            issues.stream().forEach(issue -> kIssueService.deindexIssue(jmIssueServices.getIssueManager().getIssueByCurrentKey(issue.getKey())));
        }
        return SILValueFactory.string( "issues deleted");

    }

Eu fiz comentários sobre o código.

Serviço KIssueFieldsService


Eu gostaria de falar separadamente sobre este serviço. No SIL, em todos os métodos em que você deseja transferir um campo personalizado, podemos transferir o nome do campo ou o identificador do campo no formato customfield_NNNNN ou o alias do campo.

Se não utilizássemos os serviços SIL, teríamos que implementar essa lógica por conta própria. Mas, usando o serviço KIssueFieldsService, usamos essa funcionalidade com uma linha:

CustomField customField= this.kIssueFieldsService.getCustomField(customFieldName);

Agora você sabe como criar funções SIL portáteis entre as versões do Jira.

All Articles