diff --git a/CHANGELOG.md b/CHANGELOG.md index 3107f8d..04627fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 _No changelog was maintained before v0.2.0._ +## [0.4.0] 2026-05-29 + +### Fixed + +- **Path-keyed mount format compatibility**. The executor now correctly reads the `volume` field + (introduced in Fuzzball v4 path-keyed mount format) when filtering persistent volume mounts for + child jobs. Previously the executor compared container paths against volume names, producing an + empty mount set. +- **Unknown API fields no longer crash the executor**. All generated model classes now carry + `@JsonIgnoreProperties(ignoreUnknown = true)` so future additive API changes don't cause + deserialization failures. + +### Changed + +- **SDK schema updated** to reflect the path-keyed mount format: `WorkflowDefinition.Job.Mount` + field renamed from `location` to `volume`. + ## [0.3.0] 2026-04-28 ### Added diff --git a/build.gradle b/build.gradle index efb1c93..5e094ae 100644 --- a/build.gradle +++ b/build.gradle @@ -21,7 +21,7 @@ test { // plugin version - gradle by convention seems to not use v prefixes. That does // cause some issues in other places but we'll stick with convention -version = '0.3.0' +version = '0.4.0' nextflowPlugin { // minimum nextflow version diff --git a/code-generation/groovy-okhttp-sync/model.mustache b/code-generation/groovy-okhttp-sync/model.mustache index ad02b79..3c6b4f4 100644 --- a/code-generation/groovy-okhttp-sync/model.mustache +++ b/code-generation/groovy-okhttp-sync/model.mustache @@ -5,6 +5,7 @@ import groovy.transform.CompileStatic import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule import com.fasterxml.jackson.annotation.JsonProperty +import com.fasterxml.jackson.annotation.JsonIgnoreProperties {{#imports}} import {{import}}; diff --git a/code-generation/groovy-okhttp-sync/modelClass.mustache b/code-generation/groovy-okhttp-sync/modelClass.mustache index f411811..bee68ca 100644 --- a/code-generation/groovy-okhttp-sync/modelClass.mustache +++ b/code-generation/groovy-okhttp-sync/modelClass.mustache @@ -2,6 +2,7 @@ @Canonical @CompileStatic +@JsonIgnoreProperties(ignoreUnknown = true) class {{classname}} { {{#vars}} diff --git a/code-generation/schemas/fuzzball-v3.3-openapi.json b/code-generation/schemas/fuzzball-v3.3-openapi.json index aa3d999..19b9e0a 100644 --- a/code-generation/schemas/fuzzball-v3.3-openapi.json +++ b/code-generation/schemas/fuzzball-v3.3-openapi.json @@ -9053,7 +9053,7 @@ "fuzzball.api.v3.WorkflowDefinition.Defaults.Job.Mount": { "type": "object", "properties": { - "location": { + "volume": { "type": "string", "description": "location specifies the destination within the container filesystem to\nmount a volume directory. This must be an absolute path." } @@ -9243,7 +9243,7 @@ "fuzzball.api.v3.WorkflowDefinition.Job.Mount": { "type": "object", "properties": { - "location": { + "volume": { "type": "string", "description": "location specifies the destination within the container filesystem to\nmount a volume directory. This must be an absolute path." } @@ -9625,7 +9625,7 @@ }, "readiness-probe": { "$ref": "#/definitions/fuzzball.api.v3.WorkflowDefinition.Probe", - "title": "readinessProbe controls the STARTED → RUNNING transition of the service (required for proper lifecycle monitoring)" + "title": "readinessProbe controls the STARTED \u2192 RUNNING transition of the service (required for proper lifecycle monitoring)" } } }, @@ -10325,4 +10325,4 @@ } } } -} +} \ No newline at end of file diff --git a/src/main/groovy/com/ciq/fuzzball/FuzzballExecutor.groovy b/src/main/groovy/com/ciq/fuzzball/FuzzballExecutor.groovy index 8a4f08f..a9eca22 100644 --- a/src/main/groovy/com/ciq/fuzzball/FuzzballExecutor.groovy +++ b/src/main/groovy/com/ciq/fuzzball/FuzzballExecutor.groovy @@ -99,9 +99,10 @@ class FuzzballExecutor extends Executor implements ExtensionPoint { loadEphemeralStorageClasses() volumes = filterEphemeralVolumes(allVolumes) - // Filter mounts to only include those with persistent volumes - mounts = allMounts.findAll { mountName, mount -> - volumes.containsKey(mountName) + // Filter mounts to only include those with persistent volumes. + // Path-keyed format (current): map key = container path, mount.volume = volume name. + mounts = allMounts.findAll { mountPath, mount -> + volumes.containsKey(mount.volume) } }