Hacer que las funciones SIL sean port谩tiles entre versiones en Jira

隆Hola a todos!

En este art铆culo, continuamos la discusi贸n sobre el desarrollo de nuestras propias funciones para SIL. El art铆culo anterior se puede leer aqu铆 .

Una de las principales ventajas de SIL es que el c贸digo escrito en SIL funcionar谩 en todas las versiones de Jira, por lo que necesitamos que nuestras funciones personalizadas tambi茅n funcionen.

Crear un complemento de sil-extension-archetype


Clonar el arquetipo:

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

Instale el arquetipo en el repositorio local y cree un complemento a partir de este arquetipo. Puede encontrar m谩s detalles sobre c贸mo hacer esto aqu铆 .

Agregar servicios SIL


Para que nuestra funci贸n sea port谩til entre diferentes versiones de Jira, utilizaremos los servicios que proporciona SIL. Aquellos. Proxy nuestras llamadas a la API Jira Java a trav茅s de SIL Java Api.

Pero, 驴c贸mo saber qu茅 servicios proporciona SIL?

Instalamos SIL y vamos a la siguiente direcci贸n:

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

Ver谩 la informaci贸n OSGI en todos los complementos en Jira:



encontraremos el complemento en la lista de KATL Commons y



abriremos los servicios registrados: JMUserServices, JMProjectServices son los servicios que exportan Sil.

Ahora sabemos qu茅 servicios SIL est谩n disponibles, y por el nombre del servicio podemos adivinar su prop贸sito.

Veamos el c贸digo en el complemento creado


Ahora sabemos qu茅 servicios est谩n disponibles para nosotros. Vamos a usarlos en nuestro complemento.

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 clase contiene todos los servicios que utilizaremos para nuestras funciones. Creo una clase separada para no duplicar la llamada a los servicios en cada funci贸n.

Veamos estas l铆neas:

@Getter
 private final KIssueService kIssueService;

AdquiridorEsta es una anotaci贸n de Lombok que crea un m茅todo get para la propiedad kIssueService.

Creamos propiedades de clase para cada servicio utilizado. A continuaci贸n, obtenemos estos servicios a trav茅s del constructor.

    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;
    }

Hecho.

Agregue el bean BeanService a la clase ESLauncher y pase este bean a nuestras funciones:

/*   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"));

}

Ahora podemos usar BeanService en nuestras funciones.

SayHello.java


En SayHello.java realizaremos una funci贸n que aceptar谩 la direcci贸n de correo electr贸nico del usuario, verificaremos que el usuario que ejecuta el script de administrador borre todos los tickets que fueron creados por el usuario con la direcci贸n de correo electr贸nico transmitida.

Por supuesto, podemos hacer esta l贸gica sin escribir nuestra propia funci贸n. El c贸digo SIL se ver谩 as铆:

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");

Pero quer铆a hacer un peque帽o ejemplo que mostrara los principios b谩sicos del trabajo.

Aqu铆 est谩 el texto de la clase:

@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 la l贸gica en el 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");

    }

Hice comentarios sobre el c贸digo.

Servicio KIssueFieldsService


Me gustar铆a hablar por separado sobre este servicio. En SIL, en todos los m茅todos en los que desea transferir un campo personalizado, podemos transferir el nombre del campo o el identificador de campo en el formato customfield_NNNNN o el alias de campo.

Si no utilizamos los servicios SIL, entonces tendr铆amos que implementar esta l贸gica por nuestra cuenta. Pero usando el servicio KIssueFieldsService, usamos esta funcionalidad con una l铆nea:

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

Ahora ya sabe c贸mo crear funciones SIL port谩tiles entre versiones de Jira.

All Articles