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

spago update command should work with solver-packages too #1001

Open
f-f opened this issue Sep 18, 2023 · 6 comments
Open

spago update command should work with solver-packages too #1001

f-f opened this issue Sep 18, 2023 · 6 comments

Comments

@f-f
Copy link
Member

f-f commented Sep 18, 2023

When the project build happens with the solver (rather than package sets), we should:

  1. try to build a plan with the latest versions on the Registry that are still compatible with the current compiler
  2. build with that plan
  3. and if all is well put the new ranges in the config file
@f-f
Copy link
Member Author

f-f commented Oct 3, 2023

Pivoting this issue to solver-projects only, since the package sets side is done

@f-f f-f changed the title Add spago update command spago update command should work with solver-packages too Oct 3, 2023
@f-f
Copy link
Member Author

f-f commented Oct 5, 2023

I think the solver will try to pick latest dependencies first, so it might be good enough to:

  • park away the current ranges
  • ask the solver to give us a plan with the widest ranges
  • union the old ranges with the new ones

I think this is blocked by #1003 #917, because we should update the lockfile when the plan is good - right now we don't use the lockfile in the right way, and there are no tests for it.

@flip111
Copy link
Contributor

flip111 commented Dec 24, 2023

label size:medium seems more applicable to me. Or perhaps somebody can provide some pointers to this issue?

@f-f
Copy link
Member Author

f-f commented Dec 25, 2023

What I really mean with the size:small label is "under 50 lines" (this one might be slightly bigger than that, but the spec is very clear so I think it's affordable) - some patches are 5-10 lines, and that would deserve a size:micro label 😄

A few pointers for this:

  • the unimplemented branch is here, so you can replace this error with the new code:
    Nothing -> die "This command is not yet implemented for projects using a solver. See https://github.com/purescript/spago/issues/1001"
  • upgrading the package set is about the whole workspace, but for upgrading solver ranges we want to deal with a single package/config file, so we'll want to select a single package like this:

    spago/bin/src/Main.purs

    Lines 753 to 767 in b450892

    selected <- case workspace.selected of
    Just s -> pure s
    Nothing ->
    let
    workspacePackages = Config.getWorkspacePackages workspace.packageSet
    in
    -- If there's only one package, select that one
    case NEA.length workspacePackages of
    1 -> pure $ NEA.head workspacePackages
    _ -> do
    logDebug $ unsafeStringify workspacePackages
    die
    [ toDoc "No package was selected for running. Please select (with -p) one of the following packages:"
    , indent (toDoc $ map _.package.name workspacePackages)
    ]
  • at this point you can look inside this selected :: WorkspacePackage, and get its Dependencies. Hold on to them because you'll need them later (e.g. in a currentDependencies variable)
  • then create new ranges for the solver run, where you take the currentDependencies, and just assign the Config.widestRange to every package
  • ...so you can call the solver to get a new plan:
    maybePlan <- Registry.Solver.loadAndSolve loader depsRanges
  • if the plan is bad then fail with the error, but if it's good we can overwrite the current ranges in the config file, as we do for the ensureRanges flag (note the call to getRangeFromPackage, we'll want to union the old Range in currentRanges with the new Range that we get from this function):
    when ensureRanges do
    { configPath, package, yamlDoc } <- getPackageConfigPath "in which to add ranges."
    logInfo $ "Adding ranges to dependencies to the config in " <> configPath
    packageDeps <- (Map.lookup package.name dependencies) `justOrDieWith`
    "Impossible: package dependencies must be in dependencies map"
    let rangeMap = map getRangeFromPackage packageDeps
    liftEffect $ Config.addRangesToConfig yamlDoc rangeMap
    liftAff $ FS.writeYamlDocFile configPath yamlDoc

@fsoikin
Copy link
Collaborator

fsoikin commented Sep 21, 2024

I don't understand the "union" step. Wouldn't it negate all the work the solver has done? Like, if I add extra versions to the range, they might not be compatible with other packages, no? Or did you mean "intersect" instead of "union"?

@f-f
Copy link
Member Author

f-f commented Sep 21, 2024

@fsoikin what I meant above is that we should not inadvertently introduce a breaking change in version ranges - e.g. if your project a is a library that is currently depending on foo at versions >=3.0.0 <4.0.0 and the update moves its range to >=4.0.0 <5.0.0, then a project b that depends on a and [email protected] won't be compatible with the new version of a.

So I mentioned unioning the ranges because then we'd get a range >=3.0.0 <5.0.0 which would not be breaking. However:

  • we would still have to validate the new ranges with the solver
  • I am not sure if unioning them is the right thing to do and it's not going to be correct all the time, but the starting point is that the solver will give us a set of exact versions and not a range. We'd then need to make it a range, which is a, uhh, "creative" operation, so we need some heuristics here
  • ultimately we don't have to do a perfect job - the baseline we need to beat is someone updating dependencies by hand in the config file. As long as we can make that job less tedious while having approximately the same amount of correctness then we're good I think

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

No branches or pull requests

3 participants