SIL-Funktionen zwischen Versionen in Jira portierbar machen

Hallo alle zusammen!

In diesem Artikel setzen wir die Diskussion über die Entwicklung eigener Funktionen für SIL fort. Der vorherige Artikel kann hier gelesen werden .

Einer der Hauptvorteile von SIL ist, dass der in SIL geschriebene Code auf allen Versionen von Jira funktioniert. Daher müssen auch unsere benutzerdefinierten Funktionen funktionieren.

Erstellen Sie ein Plugin aus dem Sil-Extension-Archetyp


Klonen Sie den Archetyp:

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

Installieren Sie den Archetyp im lokalen Repository und erstellen Sie ein Plugin aus diesem Archetyp. Weitere Details dazu finden Sie hier .

SIL-Dienste hinzufügen


Um unsere Funktion zwischen verschiedenen Versionen von Jira portierbar zu machen, werden wir die von SIL bereitgestellten Dienste nutzen. Jene. Wir werden unsere Aufrufe an die Jira Java API über SIL Java Api weiterleiten.

Aber woher wissen Sie, welche Dienstleistungen SIL anbietet?

Wir installieren SIL und gehen zu folgender Adresse:

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

Sie sehen OSGI-Informationen für alle Plugins in Jira:



Wir finden das Plugin in der KATL Commons-Liste und öffnen Registrierte Dienste:



JMUserServices, JMProjectServices sind die Dienste, die exportieren Sil.

Jetzt wissen wir, welche SIL-Dienste verfügbar sind, und anhand des Namens des Dienstes können wir dessen Zweck erraten.

Sehen wir uns den Code im erstellten Plugin an


Jetzt wissen wir, welche Dienstleistungen uns zur Verfügung stehen. Verwenden wir sie in unserem 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;
    }
}

Diese Klasse enthält alle Dienste, die wir für unsere Funktionen verwenden. Ich erstelle eine separate solche Klasse, um den Aufruf von Diensten in jeder Funktion nicht zu duplizieren.

Schauen wir uns diese Zeilen an:

@Getter
 private final KIssueService kIssueService;

GetterDies ist eine Lombok-Annotation, die eine get-Methode für die kIssueService-Eigenschaft erstellt.

Wir erstellen Klasseneigenschaften für jeden verwendeten Service. Als nächstes erhalten wir diese Dienste durch den Konstruktor.

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

Erledigt.

Fügen Sie die BeanService-Bean zur ESLauncher-Klasse hinzu und übergeben Sie diese Bean an unsere Funktionen:

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

}

Jetzt können wir BeanService in unseren Funktionen verwenden.

SayHello.java


In SayHello.java erstellen wir eine Funktion, die die E-Mail-Adresse des Benutzers akzeptiert, überprüft, ob der Benutzer, der das Administratorskript ausführt, alle vom Benutzer erstellten Tickets mit der übertragenen E-Mail-Adresse löscht.

Natürlich können wir diese Logik ausführen, ohne unsere eigene Funktion zu schreiben. Der SIL-Code sieht folgendermaßen aus:

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

Aber ich wollte ein kleines Beispiel machen, das die Grundprinzipien der Arbeit zeigt.

Hier ist der Klassentext:

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

Wir implementieren die Logik in der runRoutine-Methode:

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

    }

Ich habe den Code kommentiert.

KIssueFieldsService Service


Ich möchte separat über diesen Service sprechen. In SIL können wir bei allen Methoden, bei denen Sie ein benutzerdefiniertes Feld übertragen möchten, entweder den Feldnamen oder die Feldkennung im Format customfield_NNNNN oder den Feldalias übertragen.

Wenn wir keine SIL-Dienste verwenden würden, müssten wir diese Logik selbst implementieren. Mit dem KIssueFieldsService-Dienst verwenden wir diese Funktionalität jedoch mit einer Zeile:

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

Jetzt wissen Sie, wie Sie SIL-Funktionen erstellen, die zwischen Versionen von Jira portierbar sind.

All Articles