diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/Bootstrap.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/Bootstrap.kt
index 04f3aaf49..0f554f56b 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/Bootstrap.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/Bootstrap.kt
@@ -18,13 +18,13 @@ import com.github.triplet.gradle.play.tasks.internal.workers.copy
 import com.github.triplet.gradle.play.tasks.internal.workers.paramsForBase
 import org.gradle.api.file.Directory
 import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.file.FileSystemOperations
 import org.gradle.api.file.RegularFile
 import org.gradle.api.file.RegularFileProperty
 import org.gradle.api.provider.Property
 import org.gradle.api.tasks.OutputDirectory
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.workers.WorkAction
 import org.gradle.workers.WorkParameters
 import org.gradle.workers.WorkerExecutor
@@ -34,6 +34,8 @@ import javax.inject.Inject
 internal abstract class Bootstrap @Inject constructor(
         extension: PlayPublisherExtension,
         optionsHolder: BootstrapOptions.Holder,
+        private val fileOps: FileSystemOperations,
+        private val executor: WorkerExecutor,
 ) : PublishTaskBase(extension), BootstrapOptions by optionsHolder {
     @get:OutputDirectory
     abstract val srcDir: DirectoryProperty
@@ -45,9 +47,8 @@ internal abstract class Bootstrap @Inject constructor(
 
     @TaskAction
     fun bootstrap() {
-        project.delete(srcDir)
+        fileOps.delete { delete(srcDir) }
 
-        val executor = project.serviceOf<WorkerExecutor>()
         if (downloadAppDetails) bootstrapAppDetails(executor)
         if (downloadListings) bootstrapListings(executor)
         if (downloadReleaseNotes) bootstrapReleaseNotes(executor)
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/CommitEdit.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/CommitEdit.kt
index 738e0b55f..effa24f4c 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/CommitEdit.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/CommitEdit.kt
@@ -7,12 +7,12 @@ import com.github.triplet.gradle.play.tasks.internal.workers.paramsForBase
 import org.gradle.api.logging.Logging
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.workers.WorkerExecutor
 import javax.inject.Inject
 
 internal abstract class CommitEdit @Inject constructor(
         extension: PlayPublisherExtension,
+        private val executor: WorkerExecutor,
 ) : PublishTaskBase(extension) {
     @TaskAction
     fun commit() {
@@ -22,7 +22,7 @@ internal abstract class CommitEdit @Inject constructor(
             return
         }
 
-        project.serviceOf<WorkerExecutor>().noIsolation().submit(Committer::class) {
+        executor.noIsolation().submit(Committer::class) {
             paramsForBase(this)
         }
     }
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/GenerateResources.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/GenerateResources.kt
index dab7ad9ce..dcf4e9614 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/GenerateResources.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/GenerateResources.kt
@@ -22,6 +22,7 @@ import org.gradle.api.file.Directory
 import org.gradle.api.file.DirectoryProperty
 import org.gradle.api.file.FileSystemOperations
 import org.gradle.api.file.FileType
+import org.gradle.api.file.ProjectLayout
 import org.gradle.api.provider.ListProperty
 import org.gradle.api.tasks.CacheableTask
 import org.gradle.api.tasks.InputFiles
@@ -32,7 +33,6 @@ import org.gradle.api.tasks.PathSensitivity
 import org.gradle.api.tasks.SkipWhenEmpty
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.work.ChangeType
 import org.gradle.work.InputChanges
 import org.gradle.workers.WorkAction
@@ -44,7 +44,10 @@ import java.util.TreeSet
 import javax.inject.Inject
 
 @CacheableTask
-internal abstract class GenerateResources : DefaultTask() {
+internal abstract class GenerateResources @Inject constructor(
+        private val layout: ProjectLayout,
+        private val executor: WorkerExecutor,
+) : DefaultTask() {
     @get:Internal
     abstract val resSrcDirs: ListProperty<Directory>
 
@@ -66,16 +69,15 @@ internal abstract class GenerateResources : DefaultTask() {
                 .filter { it.fileType == FileType.FILE }
                 .map { it.changeType to it.file }
 
-        val work = project.serviceOf<WorkerExecutor>().noIsolation()
         if (validateChanges.isNotEmpty()) {
-            work.submit(Validator::class) {
+            executor.noIsolation().submit(Validator::class) {
                 files.set(validateChanges)
                 inputDirs.set(resSrcDirs)
             }
         }
         if (generateChanges.isNotEmpty()) {
-            work.submit(Generator::class) {
-                projectDirectory.set(project.layout.projectDirectory)
+            executor.noIsolation().submit(Generator::class) {
+                projectDirectory.set(layout.projectDirectory)
                 inputDirs.set(resSrcDirs)
                 outputDir.set(resDir)
                 changedFiles.set(generateChanges)
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/InstallInternalSharingArtifact.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/InstallInternalSharingArtifact.kt
index c4b71e4c5..c76194ebb 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/InstallInternalSharingArtifact.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/InstallInternalSharingArtifact.kt
@@ -16,7 +16,6 @@ import org.gradle.api.tasks.PathSensitive
 import org.gradle.api.tasks.PathSensitivity
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.workers.WorkAction
 import org.gradle.workers.WorkParameters
 import org.gradle.workers.WorkerExecutor
@@ -26,6 +25,7 @@ import javax.inject.Inject
 
 internal abstract class InstallInternalSharingArtifact @Inject constructor(
         private val extension: AppExtension,
+        private val executor: WorkerExecutor,
 ) : DefaultTask() {
     @get:PathSensitive(PathSensitivity.RELATIVE)
     @get:InputDirectory
@@ -39,7 +39,7 @@ internal abstract class InstallInternalSharingArtifact @Inject constructor(
     @TaskAction
     fun install() {
         val uploads = uploadedArtifacts
-        project.serviceOf<WorkerExecutor>().noIsolation().submit(Installer::class) {
+        executor.noIsolation().submit(Installer::class) {
             uploadedArtifacts.set(uploads)
             adbExecutable.set(extension.adbExecutable)
             timeOutInMs.set(extension.adbOptions.timeOutInMs)
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/ProcessArtifactVersionCodes.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/ProcessArtifactVersionCodes.kt
index 402b9c25b..89ea67352 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/ProcessArtifactVersionCodes.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/ProcessArtifactVersionCodes.kt
@@ -11,13 +11,13 @@ import org.gradle.api.tasks.Input
 import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.workers.WorkerExecutor
 import javax.inject.Inject
 import kotlin.math.max
 
 internal abstract class ProcessArtifactVersionCodes @Inject constructor(
         extension: PlayPublisherExtension,
+        private val executor: WorkerExecutor,
 ) : PublishTaskBase(extension) {
     @get:Input
     internal abstract val versionCodes: ListProperty<Int>
@@ -32,7 +32,7 @@ internal abstract class ProcessArtifactVersionCodes @Inject constructor(
 
     @TaskAction
     fun process() {
-        project.serviceOf<WorkerExecutor>().noIsolation().submit(VersionCoder::class) {
+        executor.noIsolation().submit(VersionCoder::class) {
             paramsForBase(this)
             defaultVersionCodes.set(versionCodes)
             nextAvailableVersionCodes.set(playVersionCodes)
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PromoteRelease.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PromoteRelease.kt
index 0a5dad79a..188b36277 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PromoteRelease.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PromoteRelease.kt
@@ -9,13 +9,13 @@ import com.github.triplet.gradle.play.tasks.internal.workers.paramsForBase
 import org.gradle.api.file.Directory
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.workers.WorkerExecutor
 import javax.inject.Inject
 
 internal abstract class PromoteRelease @Inject constructor(
         extension: PlayPublisherExtension,
         executionDir: Directory,
+        private val executor: WorkerExecutor,
 ) : PublishArtifactTaskBase(extension),
         UpdatableTrackExtensionOptions by CliOptionsImpl(extension, executionDir) {
     init {
@@ -25,7 +25,7 @@ internal abstract class PromoteRelease @Inject constructor(
 
     @TaskAction
     fun promote() {
-        project.serviceOf<WorkerExecutor>().noIsolation().submit(Promoter::class) {
+        executor.noIsolation().submit(Promoter::class) {
             paramsForBase(this)
         }
     }
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishApk.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishApk.kt
index 9cae40a58..33a474d1f 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishApk.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishApk.kt
@@ -11,6 +11,7 @@ import com.github.triplet.gradle.play.tasks.internal.workers.paramsForBase
 import org.gradle.api.file.ConfigurableFileCollection
 import org.gradle.api.file.Directory
 import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.file.FileSystemOperations
 import org.gradle.api.file.RegularFileProperty
 import org.gradle.api.provider.ListProperty
 import org.gradle.api.tasks.InputFile
@@ -22,7 +23,6 @@ import org.gradle.api.tasks.PathSensitivity
 import org.gradle.api.tasks.SkipWhenEmpty
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.workers.WorkerExecutor
 import java.io.File
 import javax.inject.Inject
@@ -30,6 +30,8 @@ import javax.inject.Inject
 internal abstract class PublishApk @Inject constructor(
         extension: PlayPublisherExtension,
         executionDir: Directory,
+        private val fileOps: FileSystemOperations,
+        private val executor: WorkerExecutor,
 ) : PublishArtifactTaskBase(extension),
         PublishableTrackExtensionOptions by CliOptionsImpl(extension, executionDir) {
     @get:PathSensitive(PathSensitivity.RELATIVE)
@@ -55,8 +57,8 @@ internal abstract class PublishApk @Inject constructor(
 
     @TaskAction
     fun publishApks() {
-        project.delete(temporaryDir) // Make sure previous executions get cleared out
-        project.serviceOf<WorkerExecutor>().noIsolation().submit(Processor::class) {
+        fileOps.delete { delete(temporaryDir) } // Make sure previous executions get cleared out
+        executor.noIsolation().submit(Processor::class) {
             paramsForBase(this)
 
             apkFiles.set(apks)
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishBundle.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishBundle.kt
index c05e776e1..8c9cb05c2 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishBundle.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishBundle.kt
@@ -11,6 +11,7 @@ import com.github.triplet.gradle.play.tasks.internal.workers.paramsForBase
 import org.gradle.api.file.ConfigurableFileCollection
 import org.gradle.api.file.Directory
 import org.gradle.api.file.DirectoryProperty
+import org.gradle.api.file.FileSystemOperations
 import org.gradle.api.file.RegularFileProperty
 import org.gradle.api.provider.ListProperty
 import org.gradle.api.tasks.InputFiles
@@ -21,7 +22,6 @@ import org.gradle.api.tasks.PathSensitivity
 import org.gradle.api.tasks.SkipWhenEmpty
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.workers.WorkerExecutor
 import java.io.File
 import javax.inject.Inject
@@ -29,6 +29,8 @@ import javax.inject.Inject
 internal abstract class PublishBundle @Inject constructor(
         extension: PlayPublisherExtension,
         executionDir: Directory,
+        private val fileOps: FileSystemOperations,
+        private val executor: WorkerExecutor,
 ) : PublishArtifactTaskBase(extension),
         PublishableTrackExtensionOptions by CliOptionsImpl(extension, executionDir) {
     @get:PathSensitive(PathSensitivity.RELATIVE)
@@ -44,8 +46,8 @@ internal abstract class PublishBundle @Inject constructor(
 
     @TaskAction
     fun publishBundles() {
-        project.delete(temporaryDir) // Make sure previous executions get cleared out
-        project.serviceOf<WorkerExecutor>().noIsolation().submit(Processor::class) {
+        fileOps.delete { delete(temporaryDir) } // Make sure previous executions get cleared out
+        executor.noIsolation().submit(Processor::class) {
             paramsForBase(this)
 
             bundleFiles.set(bundles)
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishInternalSharingApk.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishInternalSharingApk.kt
index c81a55200..9788f885f 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishInternalSharingApk.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishInternalSharingApk.kt
@@ -19,7 +19,6 @@ import org.gradle.api.tasks.PathSensitivity
 import org.gradle.api.tasks.SkipWhenEmpty
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.workers.WorkerExecutor
 import java.io.File
 import javax.inject.Inject
@@ -27,6 +26,7 @@ import javax.inject.Inject
 internal abstract class PublishInternalSharingApk @Inject constructor(
         extension: PlayPublisherExtension,
         executionDir: Directory,
+        private val executor: WorkerExecutor,
 ) : PublishTaskBase(extension),
         ArtifactExtensionOptions by CliOptionsImpl(extension, executionDir) {
     @get:PathSensitive(PathSensitivity.RELATIVE)
@@ -39,7 +39,7 @@ internal abstract class PublishInternalSharingApk @Inject constructor(
 
     @TaskAction
     fun publishApk() {
-        project.serviceOf<WorkerExecutor>().noIsolation().submit(Processor::class) {
+        executor.noIsolation().submit(Processor::class) {
             paramsForBase(this)
 
             apkFiles.set(apks)
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishInternalSharingBundle.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishInternalSharingBundle.kt
index 32d65e43b..81ebce096 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishInternalSharingBundle.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishInternalSharingBundle.kt
@@ -19,7 +19,6 @@ import org.gradle.api.tasks.PathSensitivity
 import org.gradle.api.tasks.SkipWhenEmpty
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.workers.WorkerExecutor
 import java.io.File
 import javax.inject.Inject
@@ -27,6 +26,7 @@ import javax.inject.Inject
 internal abstract class PublishInternalSharingBundle @Inject constructor(
         extension: PlayPublisherExtension,
         executionDir: Directory,
+        private val executor: WorkerExecutor,
 ) : PublishTaskBase(extension),
         ArtifactExtensionOptions by CliOptionsImpl(extension, executionDir) {
     @get:PathSensitive(PathSensitivity.RELATIVE)
@@ -39,7 +39,7 @@ internal abstract class PublishInternalSharingBundle @Inject constructor(
 
     @TaskAction
     fun publishBundle() {
-        project.serviceOf<WorkerExecutor>().noIsolation().submit(Processor::class) {
+        executor.noIsolation().submit(Processor::class) {
             paramsForBase(this)
 
             bundleFiles.set(bundles)
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishListings.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishListings.kt
index 61aa1cf98..b3171181c 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishListings.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishListings.kt
@@ -31,7 +31,6 @@ import org.gradle.api.tasks.PathSensitivity
 import org.gradle.api.tasks.SkipWhenEmpty
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.work.Incremental
 import org.gradle.work.InputChanges
 import org.gradle.workers.WorkerExecutor
@@ -42,6 +41,7 @@ import javax.inject.Inject
 internal abstract class PublishListings @Inject constructor(
         extension: PlayPublisherExtension,
         executionDir: Directory,
+        private val executor: WorkerExecutor,
 ) : PublishTaskBase(extension),
         WriteTrackExtensionOptions by CliOptionsImpl(extension, executionDir) {
     @get:Internal
@@ -99,7 +99,7 @@ internal abstract class PublishListings @Inject constructor(
 
         if (details == null && listings.isEmpty() && media.isEmpty()) return
 
-        project.serviceOf<WorkerExecutor>().noIsolation().submit(Publisher::class) {
+        executor.noIsolation().submit(Publisher::class) {
             paramsForBase(this)
 
             this.details.set(details)
diff --git a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishProducts.kt b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishProducts.kt
index 0dd1f71a1..c5a98c3ad 100644
--- a/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishProducts.kt
+++ b/play/plugin/src/main/kotlin/com/github/triplet/gradle/play/tasks/PublishProducts.kt
@@ -17,7 +17,6 @@ import org.gradle.api.tasks.PathSensitivity
 import org.gradle.api.tasks.SkipWhenEmpty
 import org.gradle.api.tasks.TaskAction
 import org.gradle.kotlin.dsl.submit
-import org.gradle.kotlin.dsl.support.serviceOf
 import org.gradle.work.ChangeType
 import org.gradle.work.Incremental
 import org.gradle.work.InputChanges
@@ -26,6 +25,7 @@ import javax.inject.Inject
 
 internal abstract class PublishProducts @Inject constructor(
         extension: PlayPublisherExtension,
+        private val executor: WorkerExecutor,
 ) : PublishTaskBase(extension) {
     @get:Incremental
     @get:PathSensitive(PathSensitivity.RELATIVE)
@@ -47,7 +47,6 @@ internal abstract class PublishProducts @Inject constructor(
 
     @TaskAction
     fun publishProducts(changes: InputChanges) {
-        val executor = project.serviceOf<WorkerExecutor>()
         changes.getFileChanges(productsDir)
                 .filterNot { it.changeType == ChangeType.REMOVED }
                 .filter { it.fileType == FileType.FILE }