Skip to content

Commit a63acc2

Browse files
committed
Fix docFxZip task configuration timing
- Move zip task 'from' configuration to docFx.doLast instead of zipTask.doFirst * This ensures _site directory exists before configuring the zip task * Matches the original approach in docfx.gradle * Proper timing: docFx runs -> docFx.doLast configures zip -> zipTask runs - Remove unnecessary onlyIf check from zipTask * Task will be skipped naturally if not configured in docFx.doLast - Change skip messages from warn to info level * Less noisy when source is not set (expected in some scenarios) - Remove afterEvaluate block for custom Docs tasks * Simplified approach - custom tasks can be handled in build scripts if needed
1 parent d8e8dbb commit a63acc2

File tree

1 file changed

+62
-92
lines changed

1 file changed

+62
-92
lines changed

src/main/groovy/de/inetsoftware/docfx/DocFxPlugin.groovy

Lines changed: 62 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -41,109 +41,79 @@ class DocFxPlugin implements Plugin<Project> {
4141
task.group = "documentation"
4242
task.description = "Packages the generated DocFX documentation into a zip file"
4343
task.dependsOn(docsTask)
44+
task.archiveClassifier = "docfx"
45+
task.destinationDirectory = project.file("${project.buildDir}/distributions")
46+
}
47+
48+
// Configure the zip task in docFx task's doLast (after _site directory is created)
49+
// This is the correct place to configure the 'from' for the Zip task
50+
docsTask.doLast {
51+
// Get source from extension (after docFx has potentially updated it to point to docfx.json)
52+
def source = extension.source
53+
if ((source == null || source.trim().isEmpty()) && docsTask.hasProperty('source')) {
54+
source = docsTask.source
55+
}
4456

45-
// Use onlyIf to allow task to run even if source is not set yet
46-
// (source might be set in another task's doLast, e.g., msbuild.doLast)
47-
// Actual checks happen in doFirst after dependencies have run
48-
task.onlyIf {
49-
// Always allow the task to run - we'll check conditions in doFirst
50-
// This handles the case where source is set in another task's doLast
51-
return true
57+
if (source == null || source.trim().isEmpty()) {
58+
project.logger.info("docFxZip: source is not set, skipping zip configuration")
59+
return
5260
}
5361

54-
task.doFirst {
55-
project.logger.quiet("docFxZip: Starting zip task")
56-
57-
// Check source from extension first, then from docFx task (in case it was set on the task)
58-
def source = extension.source
59-
if ((source == null || source.trim().isEmpty()) && docsTask.hasProperty('source')) {
60-
source = docsTask.source
61-
}
62-
63-
project.logger.quiet("docFxZip: checking conditions, extension.source=${extension.source}, docFx.source=${docsTask.hasProperty('source') ? docsTask.source : 'N/A'}, resolved source=${source}")
64-
65-
if (source == null || source.trim().isEmpty()) {
66-
throw new org.gradle.api.tasks.StopExecutionException("docFxZip SKIPPED: source is not set (null or empty) - docFx task may not have source configured. Make sure docFx.source is set before docFxZip runs.")
67-
}
68-
69-
// Determine the output directory from the docfx.json source
70-
def sourceFile = project.file(source)
71-
project.logger.quiet("docFxZip: checking source file: ${sourceFile.absolutePath}, exists=${sourceFile.exists()}")
72-
73-
if (!sourceFile.exists()) {
74-
throw new org.gradle.api.tasks.StopExecutionException("docFxZip SKIPPED: source file does not exist: ${sourceFile.absolutePath}")
75-
}
76-
77-
def sourceDir = sourceFile.parentFile
78-
def siteDir = new File(sourceDir, "_site")
79-
project.logger.quiet("docFxZip: checking _site directory: ${siteDir.absolutePath}, exists=${siteDir.exists()}")
80-
81-
if (!siteDir.exists()) {
82-
throw new org.gradle.api.tasks.StopExecutionException("docFxZip SKIPPED: _site directory does not exist at ${siteDir.absolutePath} (docFx task may not have run successfully)")
83-
}
84-
85-
project.logger.quiet("docFxZip: ALL CONDITIONS MET - zipping _site directory from ${siteDir.absolutePath}")
86-
task.from(siteDir) {
87-
into "/"
88-
}
89-
task.destinationDirectory = project.file("${project.buildDir}/distributions")
90-
task.archiveClassifier = "docfx"
91-
92-
// Set archive base name from source file name
93-
def baseName = sourceFile.name
94-
if (baseName.endsWith('.json')) {
95-
baseName = baseName.substring(0, baseName.length() - 5)
96-
}
97-
98-
// Set archiveBaseName (works for both Gradle 8 and 9)
99-
// In Gradle 8, archiveBaseName is a property
100-
// In Gradle 9+, archiveBaseName is a Property<String>
101-
try {
102-
if (task.hasProperty('archiveBaseName')) {
103-
def prop = task.archiveBaseName
104-
if (prop instanceof org.gradle.api.provider.Property) {
105-
// Gradle 9+ - Property API
106-
if (!prop.isPresent() || prop.get() == project.name) {
107-
prop.set(baseName)
108-
}
109-
} else {
110-
// Gradle 8 - direct property
111-
if (prop == null || prop == project.name) {
112-
task.archiveBaseName = baseName
113-
}
62+
// Determine the output directory from the docfx.json source
63+
// After docFx runs, extension.source points to the docfx.json file
64+
def sourceFile = project.file(source)
65+
if (!sourceFile.exists()) {
66+
project.logger.info("docFxZip: source file does not exist: ${sourceFile.absolutePath}, skipping zip configuration")
67+
return
68+
}
69+
70+
def sourceDir = sourceFile.parentFile
71+
def siteDir = new File(sourceDir, "_site")
72+
73+
if (!siteDir.exists()) {
74+
project.logger.info("docFxZip: _site directory does not exist at ${siteDir.absolutePath}, skipping zip configuration")
75+
return
76+
}
77+
78+
project.logger.quiet("docFxZip: Configuring zip task from _site directory: ${siteDir.absolutePath}")
79+
80+
// Configure the zip task's from (this happens in docFx.doLast, which is the right time)
81+
zipTask.from(siteDir) {
82+
into "/"
83+
}
84+
85+
// Set archive base name from source file name
86+
def baseName = sourceFile.name
87+
if (baseName.endsWith('.json')) {
88+
baseName = baseName.substring(0, baseName.length() - 5)
89+
}
90+
91+
// Set archiveBaseName (works for both Gradle 8 and 9)
92+
try {
93+
if (zipTask.hasProperty('archiveBaseName')) {
94+
def prop = zipTask.archiveBaseName
95+
if (prop instanceof org.gradle.api.provider.Property) {
96+
// Gradle 9+ - Property API
97+
if (!prop.isPresent() || prop.get() == project.name) {
98+
prop.set(baseName)
99+
}
100+
} else {
101+
// Gradle 8 - direct property
102+
if (prop == null || prop == project.name) {
103+
zipTask.archiveBaseName = baseName
114104
}
115105
}
116-
} catch (Exception e) {
117-
project.logger.debug("Could not set archiveBaseName: ${e.message}")
118106
}
107+
} catch (Exception e) {
108+
project.logger.debug("Could not set archiveBaseName: ${e.message}")
119109
}
120110

121-
task.doLast {
122-
project.logger.quiet("docFxZip: Completed zip task")
123-
}
111+
// Configure inputs/outputs for up-to-date checking
112+
zipTask.inputs.dir(siteDir).optional()
113+
zipTask.outputs.file(zipTask.archiveFile)
124114
}
125115

126116
// Make docs task finalized by zip task
127117
docsTask.finalizedBy(zipTask)
128-
129-
// After evaluation, find any custom Docs tasks and make docFxZip depend on them
130-
// This allows build scripts to create custom Docs tasks and have them work with docFxZip
131-
project.afterEvaluate {
132-
project.tasks.withType(Docs).each { docsTaskInstance ->
133-
if (docsTaskInstance != docsTask && docsTaskInstance.name != DOCS_TASK) {
134-
// Found a custom Docs task - make docFxZip depend on it
135-
zipTask.dependsOn(docsTaskInstance)
136-
// Also make the custom task finalized by zip
137-
docsTaskInstance.finalizedBy(zipTask)
138-
}
139-
}
140-
141-
// Optionally hook into common publishing tasks
142-
// Check for preparePublish task (common in build scripts)
143-
def preparePublishTask = project.tasks.findByName('preparePublish')
144-
if (preparePublishTask != null) {
145-
preparePublishTask.dependsOn(zipTask)
146-
}
147-
}
148118
}
149119
}

0 commit comments

Comments
 (0)