@@ -0,0 +1,243 @@
1+{-# OPTIONS_GHC -Wall #-}
2+{-# LANGUAGE OverloadedStrings #-}
3+module Reporting.Error.Publish
4+ ( Error(..)
5+ , toReport
6+ )
7+ where
8+
9+
10+import qualified Text.PrettyPrint.ANSI.Leijen as P
11+import Text.PrettyPrint.ANSI.Leijen ((<>))
12+
13+import Deps.Diff (Magnitude, magnitudeToString)
14+import qualified Elm.Package as Pkg
15+import qualified Reporting.Error.Help as Help
16+
17+
18+
19+-- ERRORS
20+
21+
22+data Error
23+ = Application
24+ | NotInitialVersion Pkg.Version
25+ | AlreadyPublished Pkg.Version
26+ | InvalidBump Pkg.Version Pkg.Version
27+ | BadBump Pkg.Version Pkg.Version Magnitude Pkg.Version Magnitude
28+ | NoSummary
29+ | NoExposed
30+ | NoReadme
31+ | ShortReadme
32+ | NoLicense
33+ | MissingTag Pkg.Version
34+ | NoGit
35+ | LocalChanges Pkg.Version
36+
37+
38+
39+-- TO REPORT
40+
41+
42+toReport :: Error -> Help.Report
43+toReport err =
44+ case err of
45+ Application ->
46+ Help.report "UNPUBLISHABLE" Nothing "I cannot publish applications, only packages!" []
47+
48+ NotInitialVersion vsn ->
49+ Help.docReport "INVALID VERSION" Nothing
50+ ( P.fillSep
51+ ["I","cannot","publish"
52+ ,P.red (P.text (Pkg.versionToString vsn))
53+ ,"as","the","initial","version."
54+ ]
55+ )
56+ [ P.fillSep
57+ ["Change","it","to",P.green "1.0.0","which","is"
58+ ,"the","initial","version","for","all","Elm","packages."
59+ ]
60+ ]
61+
62+ AlreadyPublished vsn ->
63+ Help.docReport "ALREADY PUBLISHED" Nothing
64+ ( P.vcat
65+ [ P.fillSep
66+ [ "Version", P.green (P.text (Pkg.versionToString vsn))
67+ , "has", "already", "been", "published.", "You", "cannot"
68+ , "publish", "it", "again!"
69+ ]
70+ , "Try using the `bump` command:"
71+ ]
72+ )
73+ [ P.dullyellow $ P.indent 4 $ P.text "elm bump"
74+ , Help.reflow $
75+ "It computes the version number based on API changes, ensuring\
76+ \ that no breaking changes end up in PATCH releases!"
77+ ]
78+
79+ InvalidBump statedVersion latestVersion ->
80+ Help.docReport "INVALID VERSION" (Just "elm.json")
81+ ( P.fillSep $
82+ ["Your","elm.json","says","the","next","version","should","be"
83+ ,P.red (P.text (Pkg.versionToString statedVersion)) <> ","
84+ ,"but","that","is","not","valid","based","on","the","previously"
85+ ,"published","versions."
86+ ]
87+ )
88+ [ P.fillSep $
89+ ["Change","the","version","back","to"
90+ ,P.green (P.text (Pkg.versionToString latestVersion))
91+ ,"which","is","the","most","recently","published","version."
92+ ,"From","there,","have","Elm","bump","the","version","by","running:"
93+ ]
94+ , P.indent 4 $ P.green "elm bump"
95+ , Help.reflow $
96+ "If you want more insight on the API changes Elm detects, you\
97+ \ can run `elm diff` at this point as well."
98+ ]
99+
100+ BadBump old new magnitude realNew realMagnitude ->
101+ Help.docReport "INVALID VERSION" (Just "elm.json")
102+ (
103+ P.fillSep $
104+ ["Your","elm.json","says","the","next","version","should","be"
105+ ,P.red (P.text (Pkg.versionToString new)) <> ","
106+ ,"indicating","a",P.text (magnitudeToString magnitude)
107+ ,"change","to","the","public","API."
108+ ,"This","does","not","match","the","API","diff","given","by:"
109+ ]
110+ )
111+ [ P.indent 4 $ P.text $
112+ "elm diff " ++ Pkg.versionToString old
113+
114+ , P.fillSep $
115+ ["This","command","says","this","is","a"
116+ ,P.text (magnitudeToString realMagnitude)
117+ ,"change,","so","the","next","version","should","be"
118+ ,P.green (P.text (Pkg.versionToString realNew)) <> "."
119+ ,"Double","check","everything","to","make","sure","you"
120+ ,"are","publishing","what","you","want!"
121+ ]
122+ , Help.reflow $
123+ "Also, next time use `elm bump` and I'll figure all this out for you!"
124+ ]
125+
126+ NoSummary ->
127+ Help.docReport "NO SUMMARY" (Just "elm.json")
128+ ( P.fillSep $
129+ [ "To", "publish", "a", "package,", "your", "elm.json", "must"
130+ , "have", "a", P.dullyellow "\"summary\"", "field", "that", "gives"
131+ , "a", "consice", "overview", "of", "your", "project."
132+ ]
133+ )
134+ [ Help.reflow $
135+ "The summary must be less than 80 characters. It should describe\
136+ \ the concrete use of your package as clearly and as plainly as possible."
137+ ]
138+
139+ NoExposed ->
140+ Help.docReport "NO EXPOSED MODULES" (Just "elm.json")
141+ ( P.fillSep $
142+ [ "To", "publish", "a", "package,", "the"
143+ , P.dullyellow "\"exposed-modules\"", "field", "of", "your"
144+ , "elm.json", "must", "list", "at", "least", "one", "module."
145+ ]
146+ )
147+ [ Help.reflow $
148+ "What is the point of a package that has no modules?!"
149+ ]
150+
151+ NoReadme ->
152+ badReadmeReport "NO README" $
153+ "Every published package must have a helpful README.md\
154+ \ file, but I do not see one in your project."
155+
156+ ShortReadme ->
157+ badReadmeReport "SHORT README" $
158+ "This README.md is too short. Having more details will help\
159+ \ people assess your package quickly and fairly."
160+
161+ NoLicense ->
162+ Help.report "NO LICENSE FILE" (Just "LICENSE")
163+ "By publishing a package you are inviting the Elm community to build\
164+ \ upon your work. But without knowing your license, we have no idea if\
165+ \ that is legal!"
166+ [ Help.reflow $
167+ "Once you pick an OSI approved license from <https://spdx.org/licenses/>,\
168+ \ you must share that choice in two places. First, the license\
169+ \ identifier must appear in your elm.json file. Second, the full\
170+ \ license text must appear in the root of your project in a file\
171+ \ named LICENSE. Add that file and you will be all set!"
172+ ]
173+
174+ MissingTag version ->
175+ let vsn = Pkg.versionToString version in
176+ Help.docReport "NO TAG" Nothing
177+ ( P.fillSep $
178+ [ "Packages", "must", "be", "tagged", "in", "git,", "but", "I"
179+ , "cannot", "find", "a", P.green (P.text vsn), "tag."
180+ ]
181+ )
182+ [ P.vcat
183+ [ "These tags make it possible to find this specific version on GitHub."
184+ , "To tag the most recent commit and push it to GitHub, run this:"
185+ ]
186+ , P.indent 4 $ P.dullyellow $ P.vcat $ map P.text $
187+ [ "git tag -a " ++ vsn ++ " -m \"release version " ++ vsn ++ "\""
188+ , "git push origin " ++ vsn
189+ ]
190+ , "The -m flag is for a helpful message. Try to make it more informative!"
191+ ]
192+
193+ NoGit ->
194+ Help.report "NO GIT" Nothing
195+ "I searched your PATH environment variable for `git` and could not\
196+ \ find it. Is it available through your PATH?"
197+ [ Help.reflow $
198+ "Who cares about this? Well, I currently use `git` to check if there\
199+ \ are any local changes in your code. Local changes are a good sign\
200+ \ that some important improvements have gotten mistagged, so this\
201+ \ check can be extremely helpful for package authors!"
202+ , Help.note $
203+ "We plan to do this without the `git` binary in a future release."
204+ ]
205+
206+ LocalChanges version ->
207+ let vsn = Pkg.versionToString version in
208+ Help.docReport "LOCAL CHANGES" Nothing
209+ ( P.fillSep $
210+ [ "The", "code", "tagged", "as", P.green (P.text vsn), "in"
211+ , "git", "does", "not", "match", "the", "code", "in", "your"
212+ , "working", "directory.", "This", "means", "you", "have"
213+ , "commits", "or", "local", "changes", "that", "are", "not"
214+ , "going", "to", "be", "published!"
215+ ]
216+ )
217+ [ Help.note $
218+ "If you are sure everything is in order, you can run `git checkout "
219+ ++ vsn ++ "` and publish your code from there."
220+ ]
221+
222+
223+badReadmeReport :: String -> String -> Help.Report
224+badReadmeReport title summary =
225+ Help.report title (Just "README.md") summary
226+ [ Help.reflow $
227+ "When people look at your README, they are wondering:"
228+ , P.vcat
229+ [ " - What does this package even do?"
230+ , " - Will it help me solve MY problems?"
231+ ]
232+ , Help.reflow $
233+ "So I recommend starting your README with a small example of the\
234+ \ most common usage scenario. Show people what they can expect if\
235+ \ they learn more!"
236+ , Help.note $
237+ "By publishing your package, you are inviting people to invest time\
238+ \ in understanding your work. Spending an hour to communicate your\
239+ \ knowledge more clearly can save the community days or weeks of time\
240+ \ in aggregate, and saving time in aggregate is the whole point of\
241+ \ publishing packages! People really appreciate it, and it makes the\
242+ \ whole ecosystem feel nicer!"
243+ ]