Fortunately, I finally found an example that contained the missing pieces. After copying the following into build.gradle, the recipe above works as desired without deprecation warnings.
def gitVersionProvider = providers.exec {
commandLine "cat", "foo"
}
task testVersion(type: Exec) {
inputs.property "pipelineVersion", gitVersionProvider.standardOutput.asText.get().trim()
outputs.file "$buildDir/build.properties"
commandLine "touch", "$buildDir/build.properties"
}