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

Gradle should warn users in case of conflicting ArtifactTransform registrations #28960

Closed
britter opened this issue Apr 25, 2024 · 1 comment
Closed
Labels
a:feature A new functionality closed:duplicate Duplicated or superseeded by another issue in:artifact-transforms

Comments

@britter
Copy link
Member

britter commented Apr 25, 2024

Expected Behavior

Given I register a transform from attribute foo to attribute bar,
when I register another transform from attribute foo to attribute bar,
Gradle should fail the build, notifying me about the conflicting registrations.

Current Behavior (optional)

Boths transforms are registered. During transform execution the transform that was registered first is selected leading to surprising behavior.

Context

We have a pattern in our build for downloading and unpacking binaries. We use custom Ivy repositories to model GitHub release pages. Then in case we download an archive, we register transforms in order unpack the binary just once instead of having unpack tasks registered in each project. See the 'Modeling downloadable resources using Ivy repositories' section in this issue. Usually we create a plugin that deals with all of this logic. We might have a buildlogic.helm plugin that takes care of downloading the helm CLI, and then another plugin buildlogic.chromedriver that download chromedriver.

Recently I had to download GitHub CodeQL CLI which is provided as a Zip archive here. First I tried using org.gradle.api.internal.artifacts.transform.UnzipTransform for unpacking, because we use it in a few other places, but that didn't work, because UnzipTransform does not restore file permissions from the Zip. So I created my own transform that reads the file permissions from the archive and restores them on the file. The code looked something like this:

// contents of `buildlogic.codeql.gradle.kts`

val os = OperatingSystem.current()

val osFilenamePart =
    when {
        os.isMacOsX -> "osx64"
        os.isWindows -> "win64"
        else -> "linux64"
    }

// TODO move to commonVersions
val codeQlCliVersion = provider { "2.17.0" }

repositories {
    exclusiveContent {
        forRepository {
            ivy {
                url = uri("https://github.com/github/")
                patternLayout {
                    artifact("[organization]/releases/download/v[revision]/[artifact]-[classifier].[ext]")
                }
                metadataSources {
                    artifact()
                }
            }
        }
        filter {
            includeModule("codeql-cli-binaries", "codeql")
        }
    }
}

val codeQlBinary by configurations.creating {
    isCanBeResolved = true
    isCanBeConsumed = false
    attributes.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE)
}

dependencies {
    registerTransform(ExplodeCodeQlTransform::class) {
        from.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.ZIP_TYPE)
        to.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE)
    }
    codeQlBinary(codeQlCliVersion.map { "codeql-cli-binaries:codeql:$it:$osFilenamePart@zip" })
}

tasks.withType<CodeQlCliExec>().configureEach {
    dependsOn(codeQlBinary)
    codeQlDist.fileProvider(provider { File(codeQlBinary.singleFile, "codeql") })
    codeQlVersion = codeQlCliVersion
}

This code worked for most of the projects I applied the plugin to. However if failed for two projects reporting a file permission error. After lots of digging, I realized that for the two projects we register another "download executable plugin" and that plugin registers org.gradle.api.internal.artifacts.transform.UnzipTransform for the same attributes. Because the other plugin was registered first in the failing projects, Gradle selected the UnzipTransform and ignored the transform that would restore file permissions.

The workaround for this was to use a different to attribute setting to make transform registrations unique. However I think having multiple transforms registered for the same set of attributes should cause an error.

@britter britter added a:feature A new functionality to-triage labels Apr 25, 2024
@ov7a
Copy link
Member

ov7a commented May 7, 2024

This issue will be closed as a duplicate of

Please add your use case and 👍 to that issue.

If you think our analysis is wrong, please provide us with more detailed information explaining why.

@ov7a ov7a closed this as not planned Won't fix, can't repro, duplicate, stale May 7, 2024
@ov7a ov7a added closed:duplicate Duplicated or superseeded by another issue in:artifact-transforms and removed to-triage labels May 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
a:feature A new functionality closed:duplicate Duplicated or superseeded by another issue in:artifact-transforms
Projects
None yet
Development

No branches or pull requests

2 participants