dgp1130 / rules_prerender

A Bazel rule set for prerending HTML pages.
13 stars 0 forks source link

Diamond resource conflict in `web_resources()` #9

Closed dgp1130 closed 3 years ago

dgp1130 commented 3 years ago

Currently web_resources() will throw an error if a resource is depended upon in a "diamond" fashion. Consider this example:

load("@npm//rules_prerender:index.bzl", "web_resources", "web_resources_devserver")

web_resources(
    name = "top",
    entries = {
        "/my_file": "file.txt",
    },
)

web_resources(
    name = "left",
    deps = [":top"],
)

web_resources(
    name = "right",
    deps = [":top"],
)

web_resources(
    name = "bottom",
    deps = [":left", ":right"],
)

web_resources_devserver(
    name = "devserver",
    resources = ":bottom",
)

The /my_file path gets copied into both :left and :right. Then when :bottom builds, it sees a conflict between its two dependencies and fails, even though they came from the same file!

We will likely allow duplicate files with the same content at the same path to be allowed, even if they came from different sources. Implementing that would fix this bug.

Alternatively, we could restrict so a given file path can only be listed in a single entries dict, and all web_resources() rules must depend on that specific rule, rather than duplicating the file. This is a little more strict, so I'm inclined to go with this to start, and we can possibly expand in the future to allow duplicates as long as the file content is the same.

If we do go with the latter, I think we could implement that by making web_resources() generate two directories. The first would only contain its entries and no dependencies. The second would merge its entries directory with the entries directory of all transitive deps. Users would depend on the second directory, while the first one would be a private implementation detail. This would mean /my_file doesn't get copied to :left and :right, but rather gets copied directly to :bottom when it is used by :devserver. :bottom would still be able to check for conflicts, although it may be a little late. We could add a validation action on the second directory for all web_resources() rules, which would make any conflict fail the offending web_resources() rule.