Membuat fungsi SIL portabel antar versi di Jira

Halo semuanya!

Pada artikel ini, kami melanjutkan diskusi tentang pengembangan fungsi kami sendiri untuk SIL. Artikel sebelumnya bisa dibaca di sini .

Salah satu keuntungan utama SIL adalah bahwa kode yang ditulis dalam SIL akan bekerja pada semua versi Jira, jadi kita perlu membuat fungsi kustom kita berfungsi juga.

Buat plugin dari sil-extension-archetype


Klon arketipe:

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

Instal arketipe dalam repositori lokal dan buat plugin dari arketipe ini. Rincian lebih lanjut tentang cara melakukan ini dapat ditemukan di sini .

Tambahkan Layanan SIL


Untuk membuat fungsi kami portabel antara versi Jira yang berbeda, kami akan menggunakan layanan yang disediakan SIL. Itu kami akan proksi panggilan kami ke Jira Java API melalui SIL Java Api.

Tapi bagaimana Anda tahu layanan mana yang SIL berikan?

Kami menginstal SIL dan pergi ke alamat berikut:

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

Anda akan melihat informasi OSGI pada semua plugin di Jira:



Kami akan menemukan plugin dalam daftar KATL Commons dan membuka layanan Terdaftar:



JMUserServices, JMProjectServices adalah layanan yang mengekspor Sil.

Sekarang kita tahu layanan SIL apa yang tersedia, dan berdasarkan nama layanan kita dapat menebak tujuannya.

Mari kita lihat kode di plugin yang dibuat


Sekarang kita tahu layanan apa yang tersedia bagi kita. Mari kita gunakan di plugin kami.

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

Kelas ini berisi semua layanan yang akan kita gunakan untuk fungsi kita. Saya membuat kelas yang terpisah sehingga tidak menduplikasi panggilan ke layanan di setiap fungsi.

Mari kita lihat garis-garis ini:

@Getter
 private final KIssueService kIssueService;

Getterini adalah anotasi Lombok yang membuat metode get untuk properti kIssueService.

Kami membuat properti kelas untuk setiap layanan yang digunakan. Selanjutnya, kami mendapatkan layanan ini melalui 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;
    }

Selesai

Tambahkan kacang BeanService ke kelas ESLauncher dan berikan kacang ini ke fungsi kami:

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

}

Sekarang kita bisa menggunakan BeanService dalam fungsi kita.

SayHello.java


Di SayHello.java kami akan membuat fungsi yang akan menerima alamat email pengguna, memeriksa apakah pengguna yang menjalankan skrip administrator, menghapus semua tiket yang dibuat oleh pengguna dengan alamat email yang dikirimkan.

Tentu saja, kita dapat melakukan logika ini tanpa menulis fungsi kita sendiri. Kode SIL akan terlihat seperti ini:

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

Tetapi saya ingin membuat contoh kecil yang akan menunjukkan prinsip-prinsip dasar kerja.

Ini teks kelasnya:

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

Kami menerapkan logika dalam metode 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");

    }

Saya membuat komentar pada kode.

Layanan Layanan KIssueFields


Saya ingin berbicara secara terpisah tentang layanan ini. Di SIL, di semua metode tempat Anda ingin mentransfer bidang khusus, kami dapat mentransfer nama bidang atau pengidentifikasi bidang dalam format customfield_NNNNN atau alias bidang.

Jika kami tidak menggunakan layanan SIL, maka kami harus mengimplementasikan logika ini sendiri. Tetapi menggunakan layanan KIssueFieldsService, kami menggunakan fungsi ini dengan satu baris:

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

Sekarang Anda tahu cara membuat fungsi SIL portabel antara versi Jira.

All Articles