hackage-server icon indicating copy to clipboard operation
hackage-server copied to clipboard

Revise flag from `automatic` to `manual` is irreversible

Open wenkokke opened this issue 5 months ago • 12 comments

On Hackage, when revising a package metadata, revising a flag from automatic to manual is permitted, but the reverse is not. Hence, after a mistaken revision from automatic to manual, the package metadata gets stuck with the wrong setting.

Example: hs-onnxruntime-capi-0.1.0.0 is stuck with pkg-config as a manual flag, while it was an automatic flag before. (It should be manual with a default set to false, but that's now an unreachable configuration.)

wenkokke avatar Jul 30 '25 12:07 wenkokke

Going into one direction have been intentional https://github.com/haskell/hackage-server/commit/9fcef7229ce655e53cc9cc2e88963ffc28447b6f, but I'd argue that revisions should always be reversible. So if manual -> automatic is considered bad for some reason than automatic -> manual must be forbidden as well.

Sadly the commit message doesn't motivate change further. Why allowing only one direction and not other? Safe option would be to disallow both, yet I don't see a problem with allowing both if one is considered important.

IMO the reversibility of revisions (i.e. always being able to undo revisions) is the most important feature of revision system. (Otherwise Hackage Trustees cannot be trusted, they are humans and can make mistakes, which they can not undo!).

phadej avatar Jul 30 '25 13:07 phadej

The one direction of that is also documented here: https://github.com/haskell-infra/hackage-trustees/blob/master/revisions-information.md

Note that this is not the only "one way" revision -- it is also allowed to add from a very special subset of dependencies, but not to remove any dependencies at all.

I don't recall the exact logic behind this choice, but there's some related reasoning both in the linked commit and in the documentation I linked. Its something like going to manual makes things more configurable for users and is in that sense "safe", but going to automatic may make a previously working configuration unusable. Its certainly debatable whether an outright ban is the best choice -- arguably what we should do is change revisions so that not trustees but admins can override such decisions. Or maybe we should just allow one to "revert" a revision?

Note also that the heavy restrictions on revisions were largely driven by a response to user anxieties about revisions -- they didn't like the idea of things changing, and so the more we restricted the surface and vetted it, the better we could assuage that.

By the way @wenkokke you wrote "It should be manual with a default set to false, but that's now an unreachable configuration" -- did you mean it should be automatic with default false? One can always change the defaults of a manual flag, I believe.

gbaz avatar Jul 30 '25 17:07 gbaz

is in that sense "safe",

It's not "safe". Turn any automatic flag in https://hackage.haskell.org/package/transformers-compat-0.7.2 to be manual, and you will break some configurations. (Downstream would be required to flip flags manually).

it is also allowed to add from a very special subset of dependencies, but not to remove any dependencies at all.

Arguably it's a missing feature in .cabal. If .cabal had https://github.com/haskell/cabal/issues/11053, then we could add fake-depends base and base-orphans, and IMHO those fake dependencies could be added and removed safely by revisions. Then you won't need to be able to add true base and base-orphans dependencies. Those are "hacks".

phadej avatar Jul 30 '25 17:07 phadej

I suggest that we ban flag manual <-> automatic change.

Its something like going to manual makes things more configurable for users and is in that sense "safe", but going to automatic may make a previously working configuration unusable.

I'd argue that both directions may make working configurations unusable.

But so can build-depend revisions. So to me that is lacking argument. The property than you can undo revision to me is far more important. If you accidentally made revision which made something unusable, you should be able to undo it. OP wasn't warned that automatic -> manual change is irreversible.

phadej avatar Jul 30 '25 18:07 phadej

The "safe" argument is that if you have an automatic flag that is made manual, then one can locally always just force the flag to how the automatic could have resolved. I.e. you may need to change your build, but you can do so. However, if a manual flag becomes automatic, then it may always "automatically" pick the option you don't want, and you can't override that. I.e. as you write in one case "downstream would be required to flip some flags manually." Yes. However, in the other case, downstream would be unable to find any flags to flip, much worse.

If I recall, there were specific use cases where automatic -> manual was necessary, which is why it was allowed, but I don't know which ones offhand, this was all some time ago. It might be fine to just disallow again for now, then revisit if/when the need arises.

gbaz avatar Jul 30 '25 19:07 gbaz

then it may always "automatically" pick the option you don't want

You can force automatic flag to the particular value too. I.e. you can override automatic selection. That what cabal.project.freeze files do: constraint: package +automatic-flag. The same way as with manual ones.

phadej avatar Jul 30 '25 19:07 phadej

Ah, the semantics are just automatic will automatically try the negated flag if the default doesn't work (i.e. backtrack), while manual won't, but otherwise they're the same?

In that case, I can't see a good argument for allowing one but not the other, and I'm not sure how to reconstruct the logic that got us here. PR welcome to make it uniformly editable both ways.

gbaz avatar Jul 30 '25 19:07 gbaz

but otherwise they're the same?

At its simplest yes.

phadej avatar Jul 30 '25 20:07 phadej

By the way @wenkokke you wrote "It should be manual with a default set to false, but that's now an unreachable configuration" -- did you mean it should be automatic with default false? One can always change the defaults of a manual flag, I believe.

It should be manual with default false. I cannot change the default of the flag now that it is manual.

wenkokke avatar Jul 31 '25 00:07 wenkokke

If I recall, there were specific use cases where automatic -> manual was necessary, which is why it was allowed, but I don't know which ones offhand, this was all some time ago. It might be fine to just disallow again for now, then revisit if/when the need arises.

Changing the whole infrastructure to allow a particular use case seems... untenable? Wouldn't it be better to just make admins all powerful, breakage be damned, though with heavy warnings?

wenkokke avatar Jul 31 '25 00:07 wenkokke

If I recall, there were specific use cases where automatic -> manual was necessary,

I might be wrong, but the reason is probably because flags are manual: False by default, and that caused (causes?) issues, because e.g. cabal check doesn't warn that neither manual nor default settings for flags are explicitly set.

EDIT: There is soon a decade old issue about that https://github.com/haskell/cabal/issues/1890#issuecomment-276750718

phadej avatar Jul 31 '25 00:07 phadej

It should be manual with default false. I cannot change the default of the flag now that it is manual.

Ah, that's frustrating. That doesn't correspond to the documentation, which says that flag defaults should be editable. So I'll say now that three PRs would be welcome (or one PR doing three things).

First: making flag defaults editable. Second, making both sides of manual <-> auto editable. Third, giving admins but not trustees broader permissions to make much more sweeping cabal file revisions than our rules allow. The latter is the trickiest, and probably the least important, since its been very rare that any requests to extend allowed revisions have happened.

gbaz avatar Jul 31 '25 02:07 gbaz