বিল্ড কাজের অটোমেশন কোনো সফটওয়্যার প্রকল্পের জন্য অত্যন্ত গুরুত্বপূর্ণ, এবং Gradle, এর Kotlin DSL সহ, অসাধারণ নমনীয়তা প্রদান করে। আমাদের সংলাপের সময়, আমরা বিল্ড লজিককে কেন্দ্রিক ও পুন:ব্যবহারযোগ্য করার উপায় খুঁজে বের করেছি, বিশেষ করে টেস্ট রিপোর্টের জন্য, ব্যবহার করেসকল প্রকল্প, buildSrc, এবং Kotlin-এ কাস্টম টাস্ক.

allprojects` এবং subprojects ব্যবহার করে কনফিগারেশনগুলোকে কেন্দ্রীয় করুন

ব্লকগুলো`allprojects` et `subprojects`আপনার`build.gradle.kts`মূলগুলো মৌলিক আপনার মাল্টি-মডিউল প্রকল্প জুড়ে সাধারণ কনফিগারেশন প্রয়োগ করতে.

*allprojects { …​ }`প্রয়োগ করুন কনফিগারেশন কেমূল প্রকল্প এবং তার সব উপ-প্রকল্পে. একটি সংজ্ঞায়িত করার জন্য উপযুক্ত`group, একটি`version`, অথবা কিছু`repositories`সাধারন. *subprojects { …​ }`কনফিগারেশন প্রয়োগ করুনশুধু উপ-প্রকল্পগুলোরই, মূল প্রকল্প বাদ দেওয়া। উপযুক্ত, মডিউলের জন্য ویژه প্লাগইন প্রয়োগ করার জন্য (como`java ou kotlin-jvm) অথবা আপনার লাইব্রেরির সাধারণ নির্ভরতা.

এটি একটি উদাহরণমূলক উদাহরণ:

// build.gradle.kts (projet racine)
plugins {
    base // Appliqué au projet racine
}

allprojects {
    group = "com.example"
    version = "1.0.0"

    repositories {
        mavenCentral()
    }

    tasks.withType<org.gradle.api.tasks.testing.Test> {
        useJUnitPlatform() // Configuration commune des tests pour tous les projets
    }
}

subprojects {
    apply(plugin = "java")
    apply(plugin = "org.jetbrains.kotlin.jvm")

    dependencies {
        implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    }

}

\==`buildSrc`বিল্ড লজিকের সুইস আর্মি ছুরি

আপনার কাজের লজিক জটিল হয়ে গেলে অথবা এটি পুনরায় ব্যবহার করতে হলে,buildSrcপছন্দের সমাধান। এটি একটি বিশেষ Gradle মডিউল যা প্রধান বিল্ড স্ক্রিপ্টের আগে কম্পাইল করা হয়, এর ক্লাসসমূহ আপনার বিল্ডের সম্পূর্ণ classpath-এ উপলব্ধ করে।

কেন ব্যবহার`buildSrc`টাস্কগুলো জন্য?

  • পুনরায় ব্যবহারযোগ্যতাএকటి কাজ নির্ধারিত মধ্যে`buildSrc`কোনো বিল্ডের যেকোনো প্রকল্পে প্রয়োগ করা যায়।

  • সংগঠন: বিল্ড কোডকে কেন্দ্রীয় করুন, যা আরও পরিষ্কার ও রক্ষণযোগ্য করে তোলে।

  • টাইপ সেফটি এবং অটো-কম্প্লিশন: কোটলিন কোড এ`buildSrc`কম্পাইল করা হয়, আপনার IDE-র ত্রুটি যাচাই ও স্বয়ংসম্পূর্ণ করার সুবিধা প্রদান করে, উন্নয়ন অভিজ্ঞতাকে উন্নত করে।

\=== প্রবাহ ডায়াগ্রাম`buildSrc`(কোড PlantUML)

এই ডায়াগ্রাম তৈরি করতে, নিম্নলিখিত কোডটি কপি করুন এবং PlantUML সমর্থনকারী একটি টুলে এটি পেস্ট করুন।

[source,plantuml]

@startuml skinparam হাতে লিখিত সত্য skinparam একরঙ সত্য

আয়তক্ষেত্র "Gradle Build Process" { কম্পোনেন্ট "buildSrc" ως BS { file "MyCustomTask.kt" as T ফাইল "MyConventionPlugin.kt" যেমন P } component "Root Project" as RP উপাদান "Subproject A" এভাবে SA উপাদান "Subproject B" همچون SB }

T --\> P : "এখানে সংজ্ঞায়িত P -→ RP : "প্রয়োগ করা হয় P -→ SA : "প্রয়োগ করা হয় P --\> SB : "প্রয়োগ করা হয়

RP --|\> SA : "শামিল RP --|\> SB : "মিলে

RP -up-\> BS : "নির্ভর করে (বিল্ড লজিকের জন্য) SA -up→ BS : "নির্মাণ লজিকের জন্য নির্ভর করে SB -up-\> BS : "depends on (for build logic)

T- এর ডান পাশে নোট কাস্টম কাজের শ্রেণী (উদা: OpenTestReportTask) শেষ নoten

Pএর ডান পাশের নোট কনভেনশন প্লাগইন যারা কাজগুলো নিবন্ধন করে শেষ নোট

@enduml

সারাংশ প্রতিবেদন টাস্ক গঠন

পরীক্ষা প্রতিবেদন পরিচালনা করতে, আমরা একটি মডিউলার পদ্ধতি ডিজাইন করেছি একটি অ্যাবস্ট্রাক্ট টাস্ক ক্লাস ব্যবহার করে এতে`buildSrc`. আপনার প্রয়োজনের উপর নির্ভর করে, এই শ্রেণি উত্তরাধিকার পেতে পারে`DefaultTask` ou de Exec.

\=== অবস্ট্রাক্ট টাস্ক`OpenTestReportTask`(উত্তরাধিকারী`DefaultTask`)

এই পদ্ধতি সুপারিশ করা হয়, যদি আপনি কটলিনের কাস্টম লজিক প্রয়োজন হয় যা ফাইল সিস্টেমের বা Gradle-এর অন্যান্য API-এর সাথে tươngодей করে, তারপর একটি বাহ্যিক কমান্ড চালানোর জন্য।

[source,kotlin]

package com.yourpackage

import org.gradle.api.DefaultTask import org.gradle.api.tasks.Input import org.gradle.api.tasks.TaskAction import java.io.File

অ্যাবস্ট্র্যাক্ট ক্লাস OpenTestReportTask : DefaultTask() {

----
----
init {
    group = "verification"
    description = "Opens a test report in Firefox."
    dependsOn("check") // Assure que les rapports sont générés
}

@get:Input
abstract var reportPath: String

@TaskAction
fun openReport() {
    val separator = File.separator
    val reportFile = project.layout.projectDirectory.asFile.toPath()
        .resolve(reportPath.replace("/", separator))
        .toAbsolutePath()
        .toFile()

    if (!reportFile.exists()) {
        logger.warn("Report file does not exist: $reportFile. Ensure 'check' ran.")
        return
    }

    project.exec {
        commandLine("firefox", "--new-tab", reportFile.absolutePath)
    }
    logger.lifecycle("Opened test report: ${reportFile.absolutePath}")
}
----

## }

\=== বাস্তব প্রয়োগ

এই ক্লাসগুলো অবস্ট্যাক্ট কাজ থেকে উত্তরাধিকার গ্রহণ করেন এবং রিপোর্টের নির্দিষ্ট পথকে সংজ্ঞায়িত করেন।

## [source,kotlin]

প্যাকেজ com.yourpackage

abstract class ReportUnitTestsTask : OpenTestReportTask() { প্রারম্ভ { Firefox-এ ইউনিট টেস্ট রিপোর্ট খোলে। reportPath = "build/reports/tests/test/index.html } }

package com.yourpackage

## abstract class ReportFunctionalTestsTask : OpenTestReportTask() { init { description = "ফায়ারফক্সে ফাংশনাল টেস্ট রিপোর্ট খুলে।" reportPath = "build/reports/tests/functionalTest/index.html" } }

\=== টাস্ক রেকর্ডিং

এর মধ্যে`build.gradle.kts`আপনার মূল প্রকল্পের :

## [source,kotlin]

tasks.register<com.yourpackage.ReportUnitTestsTask>("reportTests") {} tasks.register<com.yourpackage.ReportFunctionalTestsTask>("reportFunctionalTests") {}

\=== রিপোর্ট টাস্কের UML ডায়াগ্রাম (PlantUML কোড)

নিম্নোক্ত কোডটি কপি করুন এবং PlantUML সমর্থনকারী একটি টুলে পেস্ট করুন।

## [source,plantuml]

@startuml skinparam handwritten true skinparam এক রঙের সত্য

অবস্ট্র্যাক্ট ক্লাস DefaultTask { }

অবস্ট্রাক্ট ক্লাস Exec { \+ commandLine(args: String...) \+ exec() }

abstract class OpenTestReportTask extends DefaultTask { \+ group: String = "verification \+ বিবরণ: String \+ dependsOn("check") \+ abstract reportPath: String \+ openReport() : void }

abstract class AbstractJbakeExecTask extends Exec { \+ গোষ্ঠী: String = "যাচাই \+ বিবরণ: String \+ dependsOn("check") \+ abstract reportRelativePath: String \+ exec() : void }

class ReportUnitTestsTask extends OpenTestReportTask { \+ reportPath: String = "build/reports/tests/test/index.html }

বর্গ ReportFunctionalTestsTask প্রসারিত করে OpenTestReportTask { \+ reportPath: String = "build/reports/tests/functionalTest/index.html }

class ReportJbakeTestsTask extends AbstractJbakeExecTask { \+ reportRelativePath: String = "build/reports/tests/test/index.html }

শ্রেণী ReportJbakeFunctionalTestsTask প্রসারিত AbstractJbakeExecTask { \+ reportRelativePath: String = "build/reports/tests/functionalTest/index.html }

OpenTestReportTask \<-- ReportUnitTestsTask খোলা পরীক্ষা প্রতিবেদন টাস্ক \<-- প্রতিবেদন কার্যক্ষম পরীক্ষা টাস্ক

AbstractJbakeExecTask \<-- ReportJbakeTestsTask AbstractJbakeExecTask <— ReportJbakeFunctionalTestsTask

DefaultTask \<|-- OpenTestReportTask Exec \<|-- AbstractJbakeExecTask ডিফল্ট টাস্ক <|-- এক্সিকিউট

## @enduml

\\== অমূরত কাজ`AbstractJbakeExecTask`(উত্তরাধিকারী হওয়া`Exec`)

যদি আপনার কাজ মূলত পরিবর্তনযোগ্য যুক্তি সহ একটি বাহ্যিক কমান্ড চালু করে হয়, তাহলে সরাসরি থেকে উত্তরাধিকার নিন**একজিকিউটিভ**এটি আরও সরাসরি।

## [source,kotlin]

package com.yourpackage

import org.gradle.api.tasks.Exec import org.gradle.api.tasks.Input import java.io.File

অবস্ট্রাক্ট ক্লাস AbstractJbakeExecTask : Exec() {

----

init { group = "verification" description = "Opens a Jbake project report in Firefox." dependsOn("check") }

@get:Input abstract var reportRelativePath: String

override fun exec() { val separator = File.separator val reportFile = project.layout.projectDirectory.asFile.toPath() .resolve(reportRelativePath.replace("/", separator)) .toAbsolutePath() .toFile()

if (!reportFile.exists()) { logger.warn("Report file does not exist: $reportFile. Ensure 'check' ran.") return }

commandLine("firefox", "--new-tab", reportFile.absolutePath) logger.lifecycle("Attempting to open report: ${reportFile.absolutePath}") super.exec() // Appelle la méthode exec() de la super-classe Exec }

## }

বাস্তব বাস্তবায়ন_groups Its for`Exec`

## [source,kotlin]

প্যাকেজ com.yourpackage

abstract class ReportJbakeTestsTask : AbstractJbakeExecTask() { প্রারম্ভ { description = "জবেক ইউনিট টেস্ট রিপোর্ট ফায়ারফক্সে খোলে। reportRelativePath = "build/reports/tests/test/index.html } }

প্যাকেজ com.yourpackage

abstract class ReportJbakeFunctionalTestsTask : AbstractJbakeExecTask() { init { description = "ফায়ারফক্সে ফাংশনাল টেস্ট রিপোর্ট খোলা." reportRelativePath = "build/reports/tests/functionalTest/index.html" } }

\== কাজের দৃশ্যমানতা`buildSrc`

আপনি যে কাজগুলো ও ক্লাসগুলো সংজ্ঞায়িত করেন**buildSrc**আছেন :

***দृশ্যমান ও ব্যবহারযোগ্য**আপনার মূল বিল্ডের (মূল ও উপ-প্রকল্প) সব প্রকল্পের দ্বারা। এজন্য আপনি ব্যবহার করতে পারেন`com.yourpackage.ReportUnitTestsTask`মধ্যে`allprojects { ... }`. * **অন-এক্সিকিউটেবল**সরাসরি buildSrc-এর কর্মেরূপে (উদাহরণস্বরূপ,`gradle :buildSrc:reportTests`�যদি কাজটি নির্দিষ্টভাবে রেকর্ড করা না হলে, এটি কাজ করবে না`buildSrc/build.gradle.kts`).`buildSrc`এটি একটি কম্পাইলেশন মডিউল, একটি এক্সিকিউটেবল অ্যাপ্লিকেশন মডিউল নয় এই বিল্ডের প্রধান কাজের জন্য।

\=== একটি প্রতিবেদন চালু করুন পরীক্ষার জন্য`buildSrc`তানেই

Si `buildSrc`এনার নিজস্ব পরীক্ষা আছে এবং রিপোর্ট তৈরি করে, আপনি রিপোর্টের কাজটি সরাসরি মধ্যে`buildSrc/build.gradle.kts`:

## [source,kotlin]

প্লাগইন { `kotlin-jvm` }

রিপোজিটরি { mavenCentral() }

tasks.withType\<Test\> { useJUnitPlatform() reports.html.outputLocation.set(layout.buildDirectory.dir("reports/tests")) }

import com.yourpackage.ReportJbakeTestsTask // আপনার টাস্ক ক্লাস আমদানি করুন

tasks.register\<ReportJbakeTestsTask\>("reportBuildSrcTests") { // Le chemin est déjà défini dans la classe, il pointera vers les rapports de buildSrc }

আপনি তারপর এটি চালু করতে পারবেন :`./gradlew :buildSrc:test`এর পরে`./gradlew :buildSrc:reportBuildSrcTests`.

এই অনুশীলনগুলো গ্রহণ করে, আপনি Kotlin DSL-এ Gradle বিল্ড সিস্টেম তৈরি করবেন, যা শুধুমাত্র শক্তিশালী নয়, বরং অসাধারণভাবে মডুলার, রক্ষণযোগ্য এবং বোঝার জন্য সহজও।

Articles connexes