Gradle: фильтровать и выполнять задачи из заданной задачи

#android #gradle #groovy #travis-ci

#Android #gradle #groovy #travis-ci

Вопрос:

Я хочу запустить ./gradlew verifyProjectDebug для запуска подмножества задач проверки.

verifyProjectDebug пытается извлечь подмножество задач в проекте и выполнить их.

 static def isValidTask(String name) {
    def isLint = name.matches("lint.*Debug")
    def isKtlint = name.matches("ktlint.*Debug.*Check")
    def isUnitTest = name.matches("test((?!Prod|Staging).)*DebugUnitTest")

    return (isLint || isKtlint || isUnitTest) amp;amp; !name.contains("Prod")
}

task verifyProjectDebug() {
    group = "verification"
    description = "Runs lint, ktlint and tests for all debug non-production variants"

    doLast {
        getSubprojects()
                .collect { it.tasks }
                .flatten()
                .findAll { isValidTask(it.name) }
                .each { it.execute() }
    }
}
  

К сожалению, вызов .execute() для задачи не вызывает ее зависимостей, поэтому некоторые из задач завершаются с ошибкой, поскольку ее зависимости не были вызваны.

Есть ли какой-либо способ в gradle, которым я могу этого добиться. Огромное спасибо!

Ответ №1:

execute является методом Task класса. Вы пытаетесь обойти систему сборки Gradle. Выполнение задач — это не простое дело или создание экземпляра и вызов execute . Gradle обрабатывает внедрение зависимостей, кэширование, обработку ввода и вывода и все такое прочее. Так что используйте Gradle.

1)

Создайте одну задачу жизненного цикла, которая является родительской задачей для всего, что вы хотите выполнить.

 final def verifyProject = tasks.register("verifyProject")
  

Задача жизненного цикла — это задача, которая не выполняет никакой работы, она зависит только от других задач.

2)

Вы можете ссылаться только на те задачи, которые уже созданы. Например, вы не можете ссылаться на задачу lint варианта отладки до тех пор, пока не будет создан вариант отладки.

Обработайте каждый вариант, когда он будет создан, найдите все задачи, которые вы хотите выполнить, и соедините их с главной задачей.

 android.applicationVariants.all {
    final def cappedVariantName = name.capitalize()

    // For every build variant that has build type "debug"...
    if (variant.buildType == "debug") {
        verifyProject.configure {
            dependsOn("lint$cappedVariantName")
            dependsOn("ktlint$cappedVariantName")
            dependsOn("test${cappedVariantName}UnitTest")
        }
    }
}
  

Пожалуйста, проверьте имена задач, которые вы хотите выполнить.

Теперь, когда вы запустите gradlew verifyProject , все задачи, от которых зависит эта задача, будут выполнены. Вы отвечаете за зависимости.

Если вы хотите использовать это в модуле библиотеки Android, замените android.applicationVariants на android.libraryVariants .

Код следует за предотвращением конфигурации задачи. Это означает, что определенные вами задачи не будут настроены, если вы специально не вызовете их. Это должно сэкономить ресурсы (процессор и память) при запуске сборки.

3)

Чтобы сделать это автоматически для всех модулей, выберите один или оба из следующих и поместите в свой корневой проект build.gradle .

 subprojects { project ->
    project.plugins.whenPluginAdded { plugin ->
        // For all libraries and only libraries:
        if (plugin instanceof com.android.build.gradle.LibraryPlugin) {
            project.android.libraryVariants.all { variant ->
                // See above.
            }
        }
        // For all apps and only apps:
        if (plugin instanceof com.android.build.gradle.AppPlugin) {
            project.android.applicationVariants.all { variant ->
                // See above.
            }
        }
    }
}
  

Комментарии:

1. У меня многомодульный проект, и я не хочу добавлять код ко всем файлам build.gradle для каждого модуля. Есть ли что-то, что я могу сделать, что изменяет только уровень проекта build.gradle?

2. @TusharNallan Конечно, проверьте сейчас. Вероятно, вы могли бы провести рефакторинг общего кода, но это выходит за рамки.

3. Возможно ли получить обратный вызов внутри подпроектов после создания всех задач? То есть я могу просто проверить имя задачи вместо вариантной логики? Это уже решило мою проблему, но я пытаюсь лучше понять gradle.

4. Я так не думаю, набор вариантов потенциально бесконечен, поэтому в конце нет обратного вызова. variant Объект имеет множество поставщиков задач в качестве свойств, поэтому вам не нужно находить их по имени.

5. О, и отличным источником, если вы хотите узнать больше о Gradle, является этот блог: mrhaki.blogspot.com/search/label/Gradle:Goodness

Ответ №2:

Помещение этого в файл gradle уровня проекта сделало свое дело.

 task verifyDebugProjects() {
    group = "verification"
    description = "Runs lint, ktlint and tests for all debug non-production variants"
}

static def isValidVerifyDebugTask(String name) {
    def isLint = name.matches("lint.*Debug")
    def isKtlint = name.matches("ktlint.*Debug.*Check")
    def isUnitTest = name.matches("test((?!Prod|Staging).)*DebugUnitTest")

    return (isLint || isKtlint || isUnitTest) amp;amp; !name.contains("Prod")
}

gradle.projectsEvaluated {
    getSubprojects()
            .collect { it.tasks }
            .flatten()
            .findAll { isValidVerifyDebugTask(it.name) }
            .each { verifyDebugProjects.dependsOn it }
}