How to prevent swiftpackageindex.com from counting test/documentation dependencies?

swiftpackageindex.com is currently showing swift-json as having 2 dependencies. but one of those dependencies is just the swift-documentation-extract plugin it uses to load its symbolgraphs to generate the package docs.

how do i get the package index site to ignore the plugin dependency?

cc @finestructure

1 Like

We've started drafting how we're going to improve the dependency information we track in the Swift Package Index. Here are the two issues to follow along if you're interested:

At a glance, I don't think these efforts would change the dependency count to one for swift-json. When we started laying this out, plugins didn't exist yet but even now it's not clear to me how we would exclude such dependencies.

As far as I can tell from looking at swift-json's manifest, there's nothing there that would tell us how it's being used.

For "test dependencies", this is a bit different. Here, we can figure out if dependencies are only used in test targets and exclude them.

We also want to be careful when excluding dependencies in general. For instance, even when we start distinguishing "product" and "test" dependencies, we'll still want to show the full number of dependencies for a package (in addition to just "product" dependencies).

This is because there are two different scenarios to consider:

  1. How many dependencies do I need to deal with if I want to build my product, even if I'm willing to accept broken tests.
  2. What's my exposure to supply-chain attacks against my build/dev process in general.

For instance, if you're willing to cut some corners, a low number or "product" dependencies will be helpful if a dependency update is causing build issues: you'll have a better to chance to at least be able to build your product.

However, if you want to know what your full exposure to anything happening with your build or dev process through malicious third-party dependencies is that number alone would be misleading.

I'm not sure what the best answer is for plugins. My feeling is that there are probably different groups of plugins:

  1. source generators that generate input for a product
  2. documentation generators
  3. some other processing steps that don't affect the resulting binary or documentation

Group 1 feels like it should be a "product" dependency.

Group 2 could be either or. You could argue that if push comes to shove you can create a binary without updating the docs so it's not strictly a "product" dependency. However, if you're building for an SDK, doc updates are probably more tightly integrated and therefore the plugin could be regarded as a "product" dependency. It's a matter of policy really.

Group 3: I'm not sure what these would be exactly. Perhaps "swift-format"? That's a bit like docs: you can yank it if you need to build urgently but if it's your process then it's probably a "product" dependency.

I guess this is a long-winded way of saying: I'm not sure how we would determine what's part of the product and what isn't. Certainly from a supply-chain exposure perspective these should definitely be included, and I think the best default we could choose for the three groups I listed above would be to simply include them as "product" dependencies. It just so happens that that's pretty much the only thing we can do as well :)

I hope that makes sense!

2 Likes

is it possible for a package author to just declare the real dependencies, like through this .spi.yaml file i keep hearing about?

from the standpoint of a package author, i really don’t think this is a healthy incentive structure. since we can’t really show any information about why the dependency count is so high, or even whether the dependencies are maintained by the same author, it sounds like the only solutions here are to either:

  • “flatten” the repository and include the plugins as a submodule or directly in the repository, or

  • use build flags to disable tests + doctools by default.

in the long run, i think it will also encourage large monolithic frameworks like in the early days of swift, instead of the more atomized, modular system promoted by the SPM.

is it possible for a package author to just declare the real dependencies, like through this .spi.yaml file i keep hearing about?

It would be possible but we want to use that file to steer how we process information, not to be an override for the source of truth. It would be too easy to have it drift from the actual settings in the manifest or repository. It would also make it very easy to inject wrong information into the index.

since we can’t really show any information about why the dependency count is so high

Well, you’ve got the README, which we’re displaying prominently just below the top section :)

We'll also be adding more dependency information in the future, such that people browsing for packages can inspect what the actual dependencies are without having to drill into the package manifest.

or even that the dependencies are maintained by the same author

That is certainly information we could take into account when expanding the dependency info section.

it sounds like the only solutions here are to either:

  • “flatten” the repository and include the plugins as a submodule or directly in the repository, or
  • use build flags to disable tests + doctools by default.

in the long run, i think it will also encourage large monolithic frameworks like in the early days of swift, instead of the more atomized, modular system promoted by the SPM.

Well, all we can do is surface the information that’s there. We can make it easier to inspect what the dependencies are but absent any further semantic information what they are for we can’t really make any distinctions that I can see.

Can you think of ways to discover that which would scale across 4,500 packages? The only way I could see this working is if SPM left more details in Package.resolved or swift package show-dependencies for us to ingest.

There’s certainly one thing that would be gained if you were to “hide” a dependency from the Swift Package Index via build flags: default operations wouldn’t be (as) susceptible to supply-chain attacks. So in that regard one could argue that’s a good outcome.

Personally, I feel like optimising for zero dependencies at all cost isn’t a healthy goal either, for the reasons you outline. That just leads to less well-maintained copies of logic. And so I don’t think we should go out of our way to make that a golden standard unless it actually reflects reality.

I think if your package has one or two dependencies you’re already in a good place. If potential adopters then see that they're by the same author and one is a build plugin all should be well.

We’ll want to make that information easy to see for users. I think that’s a better outcome overall.

2 Likes

the README is the same between GitHub and the SPI site, so it wouldn’t make sense to add a prominent disclaimer to the README referencing something that is only visible on the SPI site.

right, but the SPI is structured in a way that gamifies swift packages, just like instagram gamifies images. so when you’re displaying stats like “swift-foo depends on X number of external packages”, it’s important to be mindful of what that’s incentivizing.

1 Like