Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can I use Gratatouille to write task actions with side-effects? #22

Open
joffrey-bion opened this issue Dec 25, 2024 · 8 comments
Open

Comments

@joffrey-bion
Copy link

Description

I would like to try to use Gratatouille to make the Gradle GitHub Changelog plugin more correct without adding too much boilerplate.

This plugin fetches GitHub issues information from GitHub during the task execution, which is inherently a non-cacheable side-effect. Can Gratatouille be used for this too?

@martinbonnin
Copy link
Member

That's an excellent question and I haven't put too much thoughts into it.

At first sight, I'd say this is currently not working because @CacheableTask is added unconditionally. And probably (but I have not checked) Gradle fails if a task is marked @CacheableTask without declaring any output. We could probably make this a rule: if a task has no output then do not mark it cacheable. I'll take a look next year :)

@joffrey-bion
Copy link
Author

Thanks for the reply!

Actually let me amend what I said. The task fetches information from GitHub and produces a changelog file as an output. So there is an output, but part of the input comes from the internet, so it can never be up to date.

@martinbonnin
Copy link
Member

Thanks for the follow up!

Am I correct that this is about allowing non-pure functions?

You would still use Gratatouille for parallel execution (all the workers boilerplate), non-overlapping outputs, potentially classloader isolation but with non-pure functions?

I think this makes sense. One could for an example use the output of generateChangelog as input to another Gradle task.

What about adding @GNonPure to disable up-to-date-ness and cacheability?

User code:

@GTaskAction
@GNonPure
internal fun computeChangelog(output: GOutputFile) {
    TODO()
}

Generated code:

// Note no @CacheableTask here
internal abstract class GenerateChangelogTask : DefaultTask() {
  init {
    outputs.upToDateWhen {
      false
    }
  }

  @get:OutputFile
  val output: RegularFileProperty
}

// Worker, etc...

Thoughts?

@joffrey-bion
Copy link
Author

Am I correct that this is about allowing non-pure functions?

Yes, I believe we can frame it this way.

I opened this issue because the section of the docs about pure functions seemed to mentioned this as a kind of requirement (even though it's in the "features" section).

So, with that in mind, your suggestion looks good to me, but please keep in mind that I don't know all the implications, so my opinion might not bring much value on this 😅

@martinbonnin
Copy link
Member

I have added a pure: Boolean parameter to @GtaskAction. See code here (apologies I had a bunch of things in flight and this didn't turn out as a nice atomic commit).

It can be used like so:

@GTaskAction(pure = false)
internal fun impureFunction(
    input: String,
    outputFile: GOutputFile,
) {
    outputFile.writeText("${Date()}: $input")
}

@joffrey-bion
Copy link
Author

Oh nice! Thank you!

@joffrey-bion
Copy link
Author

By the way, no rush at all, this is just a side project, and I wanted to clean it up also as an excuse to try Gratatouille. I'll give it a go when you cut a release ;)

@martinbonnin
Copy link
Member

Sounds like a plan 👍

Heads up the project is still in the early days. I haven't used it in a real life plugin yet. I want to use it in Apollo at some point but there are still some deprecated features that would be awkward to use with Gratatouille (because they require internal properties and using the global classpath, namely operationOutputGenerator and packageNameGenerator).

Hopefully in 2025 🤞

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants