@@ -5,141 +5,122 @@ A hash-friendly Haskell Package Repository.
55Foliage is a tool to create custom or private Haskell package repositories,
66in a fully reproducible way.
77
8- ## Background
9-
10- The problem of build reproducibility in the Haskell ecosystem has discussed
11- many times. Hackage does not natively offer a way to pin down the files it
12- serves.
13-
14- Although there are workarounds to obtain a fixed repository (e.g. by
15- truncating the index file, which is append only) I think we can solve this
16- at the root.
17-
188## Main idea
199
2010_ Like GitHub Pages but for Haskell Packages_
2111
22- A "Hackage repository" is collection of files (source distributions, cabal
23- files, public keys and signatures).
12+ A "Hackage repository" is collection of source distributions and cabal
13+ files. In addition, Hackage has implemented [ The Update
14+ Framework (TUF)] ( https://theupdateframework.com ) and the repository also
15+ includes cryptographic metadata (public keys and signatures).
2416
2517These files are commonly served by Hackage proper, that is the central
2618deployment of [ hackage-server] ( https://github.com/haskell/hackage-server/ ) .
2719
28- Foliage explores the idea of serving this content as a static website,
29- which is generated programmatically from a small set of input files.
20+ Foliage explores the idea of creaating and serving this content as a static
21+ website, generated programmatically from textual input files.
3022
31- Both the input files and the generated repository can be stored in a git
32- repository and referred to via stable URL corresponding to commit hashes.
23+ ## Example
3324
25+ Foliage expects a folder ` _sources ` with a subfolder per package name and
26+ version.
3427
35- ## Example
28+ E.g.
3629
37- An input file could look like the following
30+ ```
31+ _sources
32+ └── typed-protocols
33+ └── 0.1.0.0
34+ └── meta.toml
35+ ```
36+
37+ The file ` meta.toml ` describes a package and looks like this
3838
3939``` toml
40- [[sources ]]
41- url = " https://.../source1.tar.gz"
42-
43- [[sources ]]
44- url = " https://.../source2.tar.gz"
45- subdirs = [
46- " a" ,
47- " b" ,
48- " c"
49- ]
40+ timestamp = 2022-03-28T07:57:10Z
41+ url = ' https://github.com/input-output-hk/ouroboros-network/tarball/d2d219a86cda42787325bb8c20539a75c2667132'
42+ subdir = ' typed-protocols' # optional
5043```
5144
52- This file basically mirrors the functionality of
53- [ ` source-repository-package ` ] ( https:// cabal.readthedocs.io/en/3.6/cabal-project.html#specifying-packages-from-remote-version-control-locations )
54- in Cabal .
45+ Foliage will download the source url for each package (assumed to be a
46+ tarball), decompress it, make a source distribution and take the cabal
47+ file .
5548
56- For each source (and each subdir, if any is specified), foliage will
57- download the tarball and make a sdist. Foliage will then use the
58- hackage-repo-tool to create an on-disk repository (e.g. in ` _repo ` ) from
59- the collected packages. Additionally, one can specify revisions to each
60- package version.
49+ After all packages have been processed, foliage will create a repository,
50+ including the index and the TUF metadata. With the input above foliage will
51+ produce the following:
52+
53+ ```
54+ _repo
55+ ├── 01-index.tar
56+ ├── 01-index.tar.gz
57+ ├── index
58+ │ └── typed-protocols
59+ │ └── 0.1.0.0
60+ │ ├── package.json
61+ │ └── typed-protocols.cabal
62+ ├── mirrors.json
63+ ├── package
64+ │ └── typed-protocols-0.1.0.0.tar.gz
65+ ├── root.json
66+ ├── snapshot.json
67+ └── timestamp.json
68+ ```
69+
70+ * ` typed-protocols-0.1.0.0.tar.gz ` is obtained by running
71+ ` cabal sdist ` of the repository (and, optionally, subfolder) specified in
72+ ` meta.toml ` .
73+ * ` type-protocols.cabal ` is extracted from the repository.
74+ * ` 01-index.tar ` will include the cabal files and signed target file, using
75+ the timestamp in ` meta.toml ` .
76+ ``` bash
77+ $ TZ=UTC tar tvf _repo/01-index.tar
78+ -rw-r--r-- foliage/foliage 1627 2022-03-28 07:57 typed-protocols/0.1.0.0/typed-protocols.cabal
79+ -rw-r--r-- foliage/foliage 833 2022-03-28 07:57 typed-protocols/0.1.0.0/package.json
80+ ```
81+ * The TUF files (` mirrors.json ` , ` root.json ` , ` snapshot.json ` ,
82+ ` timestamp.json ` ) are signed and contains reasonable defaults.
83+
84+ ## Revisions
85+
86+ Foliage supports cabal file revisions. Adding the following snippet to a
87+ package's ` meta.toml ` , will make foliage look for a cabal file in
88+ ` <pkgName>/<pkgVersion>/revisions/1.cabal ` .
89+
90+ ```
91+ [[revisions]]
92+ number = 1
93+ timestamp = 2022-03-22T14:15:00+00:00
94+ ```
95+
96+ The revised cabal file will enter the index with the timestamp provided in
97+ ` meta.toml ` .
98+
99+ ## Using the repository with cabal
61100
62101The resulting repository can then be server through HTTPS and used with
63- cabal, e.g. in a ` cabal.project `
102+ cabal, e.g. in a ` cabal.project ` :
64103
65104```
66105repository packages.example.org
67106 url: https://packages.example.org/
68107 secure: True
69108```
70109
71- Alternatively, cabal can read the repository directly off disk
110+ Alternatively, cabal can read the repository directly off disk:
72111
73112```
74113repository packages.example.org
75114 url: file:///path/to/_repo
76115 secure: True
77116```
78117
79- ** Note:** The package id (package name + package version) is unknown at
80- download time and only known after looking at the cabal file. This is the
81- reason package names and versions do not show in the input file. Foliage
82- ensures two sources do not provide colliding package ids.
83-
84118** Note:** Hackage implements [ The Update
85119Framework] ( https://theupdateframework.io ) which requires a set of public
86120and private keys. Foliage can either generate a new set of keys or reuse a
87121pre-existing one. Cabal can either trust a repository at first use or
88122verify signatures against public keys obtained separately.
89123
90- ## GitHub
91-
92- Foliage can make use of three features supported by GitHub, to further advance automation.
93-
94- 1 . GitHub has long suppored accessing git repositories via HTTPS. E.g. one can access a blob in a git repo through the following URL.
95-
96- https://raw.githubusercontent.com/{owner}/{repo}/{ref}/path
97-
98- where ` ref ` can either be a commit hash or a branch name.
99-
100- 2 . GitHub also offer URLs of tarballs for repos at given commit, e.g.
101-
102- https://github.com/Quid2/flat/tarball/ee59880f47ab835dbd73bea0847dab7869fc20d8
103-
104- Afaik, these tarballs might not be entirely immutable (TODO)
105-
106- 3 . GitHub offers URLs for tagged releases (these tarballs are supposed to be immutable).
107-
108- 4 . GitHub Actions can be used to automate the generation
109-
110- 5 . (Perhaps optional) GitHub Pages supports publishing a git branch over HTTP.
111-
112- This means we automatically have a stable url for any package whose source is available on GitHub.
113- Also the generated repository can be committed to a git branch and be immediately available through HTTPS to cabal.
114-
115- E.g.
116-
117- This configuration
118-
119- https://github.com/andreabedini/byo-hackage/blob/933760117a3800366b420b07c8c887c1313e2b22/packages.tsv
120-
121- (warning old TSV format)
122-
123- Generated this repo https://github.com/andreabedini/byo-hackage/tree/1e8c5184836acb05972dfff00ac8edca575e1df1
124-
125- Which can be give to cabal like this
126-
127- ```
128- repository my-hackage-repo
129- url: https://raw.githubusercontent.com/andreabedini/byo-hackage/1e8c5184836acb05972dfff00ac8edca575e1df1
130- secure: True
131- ```
132-
133- ## To infinity and Beyond
134-
135- One can think of more features
136-
137- - A pretty website could be automatically generated along with the
138- repository. With a list of packages, their versions, metadata, etc
139- - The input file itself could be automatically generated, e.g. from all
140- tagged releases in a GitHub organisation. Making it a turn-key Hackage
141- repository for any GitHub Organisation.
142-
143124## Author
144125
145126- Andrea Bedini (@andreabedini )
0 commit comments