Skip to content

Commit 78cf7e3

Browse files
committed
Add midstream bindist proposal
1 parent f59cd98 commit 78cf7e3

File tree

1 file changed

+292
-0
lines changed

1 file changed

+292
-0
lines changed

proposals/0000-midstream-bindists.md

Lines changed: 292 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,292 @@
1+
# Midstream bindists
2+
3+
## Abstract
4+
5+
Bindists for the Haskell toolchain have been produced by upstream (the developers of each respective tool) for
6+
a long time and many tools rely on these "official" bindists (e.g. GHCup and stack).
7+
8+
We propose here that bindists are additionally built and maintained in joint effort by the projects that
9+
provide installation experiences, removing the hard dependency on upstream bindists entirely.
10+
11+
## Background
12+
13+
Historically, installers like GHCup and stack have used upstream bindists for mainly one reason: it's easy to do
14+
so and doesn't require further efforts.
15+
16+
However, using upstream bindists directly is extremely rare in the Linux world of distribution. Most distributions
17+
build, package, test and curate binary packages themselves, not only because they have custom formats, but for
18+
reasons of control, trust and quality.
19+
20+
The relationship of GHCup and bindists has also been described in the blog post
21+
[GHCup is not an installer](https://hasufell.github.io/posts/2023-11-14-ghcup-is-not-an-installer.html) recently.
22+
23+
## Problem Statement
24+
25+
From the perspective of a GHCup developer, there are several issues with relying on upstream bindists.
26+
27+
### Platform support
28+
29+
GHC and other tools have in the past dropped support for certain platforms either entirely or requested
30+
the community to step up and do the work (e.g. on GHC CI).
31+
32+
E.g. [GHC ARMv7 support was dropped silently without any call for help](https://gitlab.haskell.org/ghc/ghc/-/issues/21177#note_470440). Similarly, FreeBSD support just ceased to exist when the GHC FreeBSD CI stopped working. Later the community asked for a [revival](https://gitlab.haskell.org/groups/ghc/-/epics/5), but nothing signifcant has happened so far.
33+
GHCup still produces bindists from time to time for FreeBSD, but e.g. the [HLS release manager for 2.5.0.0 recently refused to add FreeBSD bindists](https://github.com/haskell/ghcup-metadata/pull/159).
34+
35+
Similarly, stack used to have issues with Aarch64 bindists:
36+
37+
* https://github.com/commercialhaskell/stack/issues/5709
38+
* https://github.com/commercialhaskell/stack/issues/5854
39+
* https://github.com/commercialhaskell/stack/issues/5540
40+
* https://github.com/commercialhaskell/stack/issues/5610
41+
* https://github.com/commercialhaskell/stack/issues/5619
42+
* https://github.com/commercialhaskell/stack/issues/6141
43+
* https://github.com/commercialhaskell/stack/issues/6142
44+
45+
Recently, cabal-install had issues with i386 binaries and alpine, delaying a GHCup metadata PR:
46+
47+
* https://github.com/haskell/ghcup-metadata/pull/127#issuecomment-1766020410
48+
49+
These issues are frequent and so far the GHCup developers used to single handedly fix all those missing bindists manually
50+
and provide them here: https://downloads.haskell.org/~ghcup/unofficial-bindists/
51+
52+
This is unfunded and significant work.
53+
54+
### Bindist maintenance
55+
56+
Sometimes, bindists are broken, e.g. for GHC there are a couple of instances:
57+
58+
* 9.0.2 shipping without profiling info: https://gitlab.haskell.org/ghc/ghc/-/issues/21841
59+
* DESTDIR variable ignored by `make install`: https://gitlab.haskell.org/ghc/ghc/-/issues/19646
60+
61+
Sometimes, bindists have been built for very old version of linux distros and won't run well on newer linux versions.
62+
This is currently a problem since Debian has removed ncurses5:
63+
64+
* https://github.com/haskell/ghcup-hs/issues/902
65+
* https://answers.launchpad.net/ubuntu/+source/ncurses/+question/707838
66+
* https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1025964
67+
68+
For cabal, there has been the infamous hLock issue:
69+
70+
* https://github.com/haskell/cabal/issues/7313
71+
* https://github.com/haskell/cabal/issues/7950
72+
73+
This shows that bindists, for current and historical versions, need continuous maintenance. However, upstream developers
74+
so far have very rarely engaged in this type of maintenance work, pushing it down to GHCup. As an example, here are all the
75+
manually patched and re-packaged bindists that fix the DESTDIR bug outlined above: https://downloads.haskell.org/ghcup/unofficial-bindists/ghc/curated/
76+
77+
This type of work also requires significant time.
78+
79+
### Quality gateway
80+
81+
There's something pleasing about upstream providing bindists: there's a perceived trust about it in the community,
82+
e.g. the [haskell.org committee expressed concerns about GHCup changing bindists in the past](https://github.com/haskell-infra/www.haskell.org/issues/212#issuecomment-1272312911).
83+
84+
However, rarely do upstream developers have signifcant experience in redistribution, nor do they have the time to focus
85+
on all the issues that come with it. Bindists are mostly provided "as-is" and support beyond what the release CI outputs is
86+
left to midstream (GHCup, stack, ...).
87+
88+
Conceptually, it is a good idea to separate concerns: upstream provides the sources and has tested it. Distributions build the binaries,
89+
validate that the program can be successfully built from source and make sure that the final artifacts pass the test suite.
90+
This is good, because we want to know whether end users can build e.g. a functioning GHC from source. If only the release CI outputs
91+
a GHC that passes the test suite, then something is fundamentally broken.
92+
93+
Distributors are often closer to the end-users and can provide additional support and efforts for the installation experience.
94+
95+
### Security backports
96+
97+
Cabal has recently found to be vulnerable to [HSEC-2023-0015](https://github.com/haskell/security-advisories/blob/main/advisories/hackage/cabal-install/HSEC-2023-0015.md).
98+
99+
This vulnerability [had not been communicated to the GHCup team](https://github.com/haskell/security-advisories/issues/129) prior to disclosure,
100+
causing high distress for a backport, since at the time of disclosure, cabal-3.6.2.0
101+
was still 'recommended' by GHCup, since [cabal-3.10.2.0 is still broken on windows](https://github.com/haskell/cabal/issues/9334).
102+
103+
As such, GHCup developers needed a quick and efficient way to:
104+
105+
* patch cabal
106+
* build release binaries for cabal
107+
* ship the binaries
108+
109+
This had been done as a downstream release `3.6.2.0-p1` roughly a week after the disclosure.
110+
111+
Meanwhile, cabal upstream still has not finished their backport due to issues
112+
with hackage dependencies: https://github.com/haskell/cabal/pull/9457
113+
114+
This shows that a certain amount of independences from upstream CI and upstream workflow
115+
is essential to fulfill swift security backports to potentially under-maintained
116+
branches/versions.
117+
118+
### GHC nightlies
119+
120+
As a special case, I want to point out that GHC nightlies have been frequently broken beyond repair:
121+
122+
* https://gitlab.haskell.org/ghc/ghcup-metadata/-/issues/2
123+
* https://gitlab.haskell.org/ghc/ghc/-/issues/24000
124+
125+
The breakage was left unattended and some bindists completely vanished from gitlab CI artifacts, because of misconfiguration.
126+
Here's a graph of nightlies availability: https://grafana.gitlab.haskell.org/d/ab109e66-a8a1-4ae9-b976-40e2dfe281ab/availabilitie-of-ghc-nightlies-via-ghcup?orgId=2
127+
128+
## Prior Art, Related Efforts and alternative solutions
129+
130+
So far, GHCup developers have tried to close the gap, doing signifcant work on upstream CIs and building bindists manually where
131+
necessary.
132+
133+
Bindists for cabal-install are now produced by GHCup's own CI: https://github.com/haskell/ghcup-metadata/blob/develop/.github/workflows/cabal-release.yaml
134+
135+
HLS will likely follow shortly.
136+
137+
As mentioned before, there have been attempts to improve the coordination and collaboration across the entire Haskell
138+
toolchain, view the tooling end-user experience in a holistic way and make decisions based on that end-user experience: https://github.com/haskellfoundation/tech-proposals/issues/48
139+
140+
The proposers believe that the community structure at the moment does not allow such an approach and there needs to be
141+
significant work to align goals, perception and priorities. Otherwise there will be too much friction.
142+
143+
The most important currency in the open source volunteer world is **energy**. It is not code or technical effort. As such we
144+
believe that the amount of saved energy by being more independent of upstream release processes and decisions far outweighs
145+
potential costs of technical redundancy/duplication.
146+
147+
A future proposal may very well attempt to create a unified user experience across the entire Haskell toolchain
148+
through joint management and collaboration. But that is not in the scope of this proposal and we have no concrete
149+
idea how to achieve that.
150+
151+
## Technical Content
152+
153+
We propose here to create a joint project of "installation experience" developers to get funding and maintain
154+
all tooling bindists centrally and autonomically.
155+
156+
This will allow:
157+
158+
* greater quality assurance
159+
* good platform support, we want to support at least these consistently:
160+
* more bindists for uncommon linux distros
161+
* continuously updated and maintained bindists (including historical GHC versions)
162+
* actually working nightlies
163+
164+
### Phase 1
165+
166+
In Phase 1 we will build the entire Haskell toolchain autonomically.
167+
The way this will be implemented is to start a central GitHub repository that builds bindists for releases of:
168+
169+
- GHC
170+
- HLS
171+
- cabal
172+
- stack
173+
174+
For the following platforms:
175+
176+
- FreeBSD x86_64
177+
- Linux i386
178+
- Linux x86_64
179+
- Linux armv7
180+
- Linux aarch64
181+
- Darwin x86_64
182+
- Darwin aarch64
183+
- Windows x86_64
184+
185+
For the following Linux x86_64 distros:
186+
187+
- Debian
188+
- Ubuntu
189+
- Mint
190+
- Fedora
191+
- CentOS
192+
- RedHat
193+
- Rocky Linux
194+
- Void Linux
195+
- Amazon Linux
196+
- Alpine
197+
198+
Linux i386, armv7 and aarch64 will be confined to Debian or Ubuntu.
199+
200+
### Phase 2
201+
202+
In Phase 2 we want to:
203+
204+
* enhance the quality of the bindists by
205+
- running the entire test suite for all of the tools
206+
- having a mechanism to report test failures back upstream
207+
- publishing test failures for end users to see
208+
- communicte test status of bindists clearly through e.g. GHCup
209+
- resolve GHC issues related to test bindists:
210+
* https://gitlab.haskell.org/ghc/ghc/-/issues/22726
211+
* https://gitlab.haskell.org/ghc/ghc/-/issues/22723
212+
* https://gitlab.haskell.org/ghc/ghc/-/issues/22727
213+
* make fixing bindists easier
214+
- implement revisions in GHCup: https://github.com/haskell/ghcup-hs/issues/361
215+
- make it easy to update an older GHC branch and re-run the release pipeline
216+
- Make building upstream release binaries easier
217+
* https://github.com/haskell/cabal/issues/9461
218+
* https://github.com/haskell/haskell-language-server/issues/3878
219+
220+
One main idea is that bindists should be primarily tested **on the users system**, because that is where they're going to run.
221+
It is great to know that e.g. the test suite passes on GHC CI, but that may have little value in different environments.
222+
Additionally, issues with tests can flow back to upstream developers and we may develop workflows and processes to streamline
223+
this type of feedback. Early release candidates can assist with this workflow.
224+
225+
Another perception shift necessary is that upstream projects should consider that their build system
226+
are end-user interfaces, making it easier for both distributors and end-user to build release binaries correctly themselves.
227+
228+
### Phase 3
229+
230+
In phase 3, we will mainly focus on making nightlies available for GHC and cabal. This will require
231+
coming up with a permanent storage solution and very robust nightly pipelines.
232+
233+
HLS nightlies may be added as well.
234+
235+
## Timeline
236+
237+
* phase 1 (6 months): proof of concept of a central GitHub CI building the entire toolchain
238+
* phase 2 (9 months): bindist testing workflow, automated integration with GHCup, etc.
239+
* phase 3 (12+ months): nightlies working for GHC and cabal and maybe HLS
240+
241+
## Budget
242+
243+
We would like to have a full-time developer work on this, at least partly. But at the moment,
244+
we don't have anyone to propose and hiring an external contractor for this role may or may not
245+
be helpful, since this requires significant DevX experience and commitment to the specified goals.
246+
247+
As such, we propose the "phase 1" of this proposal that focuses on advancing the existing GitHub CI
248+
support for the GitHub Haskell organization, spearheaded by @angerman (providing aarch64 linux and
249+
darwin M1 self-hosted machines). This infrastructure is already used by GHCup, HLS and other projects
250+
and needs more runners.
251+
252+
Github actions at the moment does not provide all platforms. So the budget proposal to close the platform gap on GitHub actions is as follows (all prices in USD):
253+
254+
- FreeBSD x86_64 private runner on [vultr](https://www.vultr.com/pricing/), utilizing [github-act-runner](https://github.com/ChristopherHX/github-act-runner), instance with 8vCPU, 16 GB Memory, 150GB storage
255+
* monthly: $160
256+
* yearly: $1,920
257+
- Linux aarch64 private runner on [AWS](https://aws.amazon.com/marketplace/pp/prodview-uzg6o44ep3ugw) (m6g.xlarge instance)
258+
* hourly: $0.154
259+
* monthly: $112.5
260+
* yearly: $1,350
261+
- Darwin M1 private runner on [macstadium](https://www.macstadium.com/pricing), instance with M1 8 Core, 16 GB Memory, 1 TB SSD
262+
* monthly: $179
263+
* yearly: $2,148
264+
265+
To host one additional private runner per all these platform, the yearly cost would be: **$5,418**
266+
267+
We may request more runners depending on the demand, so it may very well be 3 runners per platform, resulting in yearly cost of: $16,254
268+
269+
For FreeBSD it is also possible to buy [Cirrus CI compute credits](https://cirrus-ci.org/pricing/#compute-credits),
270+
which amount to a similar value of: $1,576.8
271+
272+
As such, we estimate the cost for phase 1 to be between 5000 to 16000 USD. The benefit of this investment is not confined to
273+
the midstream bindist proposal, but to the entirety of the GitHub Haskell organization CI infrastructure
274+
(including GHCup, HLS, Cabal, bytestring, text, unix, ...).
275+
276+
Phase 2 and 3 may need follow-up proposals with more concrete implementation strategy, cost analysis
277+
and potentially hiring a full-time employee.
278+
279+
## Stakeholders
280+
281+
* GHC developers
282+
* cabal developers
283+
* stack developers
284+
* HLS developers
285+
* VSCode Haskell developers
286+
* GHCup developers
287+
* Haskell toolchain end users
288+
289+
## Success
290+
291+
* reliable, continuously maintained bindists, readily available
292+

0 commit comments

Comments
 (0)