Skip to content

Complete support for monorepos / subdir key and non-GitHub locations #750

Description

@thomashoneyman

The registry is designed not to depend directly on GitHub and to support multiple packages stored in one repository. However, we've explicitly disabled both of those behaviors for now:

Git _ -> do
-- TODO: Support non-GitHub packages. Remember subdir when doing so. (See #15)
Except.throw GitHubOnly
GitHub { owner, repo, subdir } -> do
-- TODO: Support subdir. In the meantime, we verify subdir is not present. (See #16)
when (isJust subdir) $ Except.throw NoSubdir
case pursPublishMethod of
-- This needs to be removed so that we can support non-GitHub packages (#15)
-- and monorepo packages (#16).
--
-- However, the PureScript compiler requires packages to be a Git repo
-- with a tag checked out. Until we can replace using the compiler's
-- 'publish' command for docs we have to use this hacky checkout.
LegacyPursPublish -> do

This is the overall tracking issue for removing those restrictions. There are two legacy systems we need to deal with first: Pursuit and legacy Spago package sets.

Pursuit

The current documentation pipeline runs purs publish, which requires a Git repository with a clean worktree and a SemVer-shaped tag. Pursuit itself also assumes packages are on GitHub when it fetches READMEs, builds source links, authenticates uploads, and names packages.

We're replacing that pipeline with registry-owned documentation and a new Pursuit application maintained in this repository:

A working production Pursuit is a requirement for the first monorepo or non-GitHub package. We don't want to temporarily accept packages which can be installed from the registry but are absent from Pursuit.

Once this work is complete, package documentation will be generated from the compiler output already produced during registry publication, stored by the registry, and rendered without accessing a Git forge. Source links will use the registry package viewer instead of trying to construct GitHub URLs. The registry will be the only publisher to Pursuit.

This work also addresses the remaining Pursuit-specific problems described in:

Legacy Spago package sets and manifests

We currently produce legacy packages.dhall files for the old Spago package manager. Those package sets bake in assumptions about package source being under src in a GitHub repository and can't represent all of the locations we want the registry to support.

We also still accept Bower and legacy Spago manifests as a temporary compatibility measure.

The deprecation work is already tracked separately:

August 1, 2026 is only the earliest date we said we could retire this behavior. We should do it when the prerequisites are complete rather than treating that date as an automatic cutover. The Pursuit work and this deprecation work can proceed in parallel, but both must be complete before we enable the new source locations.

Source support

Once the new Pursuit is in production and #744 / #745 are complete, the remaining implementation belongs directly in this issue.

We need to support:

  • Location.GitHub packages with a subdir;
  • public non-GitHub Location.Git sources;
  • arbitrary refs rather than requiring SemVer-shaped tags;
  • multiple packages registered from different subdirectories of one repository.

Source.fetch should return the selected package directory rather than always returning the repository root. Manifest discovery, compilation, README discovery, tarball creation, and docs generation should all run relative to that selected directory.

The resulting registry tarball should be an ordinary independent package archive. Package managers and Pursuit should not need to know that it originally came from a monorepo.

For generic Git sources we also need to define the security and reproducibility rules. At minimum we should:

  • restrict accepted Git URL schemes and reject local paths, file:, ext::, and similar unsafe transports;
  • reject absolute or traversing subdir paths;
  • ensure the selected package directory and its files can't escape the checkout through symlinks;
  • resolve and check out the submitted ref consistently;
  • preserve the registry tarball and its hash as the immutable source artifact even if the submitted ref is mutable.

Before publishing a real package using these features, the integration tests should cover:

  1. two packages published independently from separate subdirectories of one repository;
  2. a package published from a non-GitHub Git repository;
  3. interrupted and retried publication of both cases.

For each fixture we should verify that:

  • the package can be installed and compiled using ordinary registry tooling;
  • its tarball contains only the selected package;
  • its package and module documentation appears on production Pursuit;
  • its declarations appear in name and type search;
  • dependency and re-export links use the correct package versions;
  • source links open the correct file and lines in the registry package viewer.

This issue can be closed when the source restrictions are removed, these cases pass end-to-end, and we can publish the first real monorepo package without any GitHub- or purs publish-specific compatibility path 🎉

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions