-
Notifications
You must be signed in to change notification settings - Fork 7
Support pre-release versions for PureScript tool #27
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
Changes from 4 commits
bdfa409
05cc8f5
cdd7670
2bdff82
e7b9356
e68d290
2325aac
93b1078
406f938
604dd73
da96920
a935a5e
0dcfa89
ecf352a
38f1b1a
bb08218
85b8dd5
700c10e
25b6c93
eefd145
1d5cd86
abd548e
736b373
25dcbd5
d17111a
50d457d
3792b8e
80997ca
4d596c5
2ceffc7
a1dd73b
1ee3587
085bc4e
b3725fa
2fcfbb8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,10 @@ | ||
-- | The source used to fetch and update the latest versions in the versions.json | ||
-- | file, which records the latest version of each tool. | ||
module Setup.UpdateVersions (updateVersions) where | ||
module Setup.UpdateVersions | ||
( updateVersions | ||
, fetchFromGitHubReleases | ||
, ReleaseType(..) | ||
) where | ||
|
||
import Prelude | ||
|
||
|
@@ -19,7 +23,7 @@ import Data.Maybe (Maybe(..), fromMaybe, isNothing) | |
import Data.String as String | ||
import Data.Traversable (for, traverse) | ||
import Data.Tuple (Tuple(..)) | ||
import Data.Version (Version) | ||
import Data.Version (Version, showVersion) | ||
import Data.Version as Version | ||
import Effect (Effect) | ||
import Effect.Aff (Aff, Error, Milliseconds(..), delay, error, throwError) | ||
|
@@ -34,6 +38,13 @@ import Node.FS.Sync (writeTextFile) | |
import Node.Path (FilePath) | ||
import Setup.Data.Tool (Tool(..)) | ||
import Setup.Data.Tool as Tool | ||
import Text.Parsing.Parser (ParseError) | ||
|
||
data ReleaseType | ||
= OnlyPreReleases Version | ||
| OnlyRealReleases | ||
|
||
derive instance Eq ReleaseType | ||
|
||
-- | Write the latest version of each supported tool | ||
updateVersions :: Aff Unit | ||
|
@@ -60,115 +71,131 @@ updateVersions = do | |
-- | releases, falls back to the highest valid semantic version tag for the tool. | ||
fetchLatestReleaseVersion :: Tool -> Aff Version | ||
fetchLatestReleaseVersion tool = Tool.repository tool # case tool of | ||
PureScript -> fetchFromGitHubReleases | ||
Spago -> fetchFromGitHubReleases | ||
PureScript -> fetchFromGitHubReleases OnlyRealReleases | ||
Spago -> fetchFromGitHubReleases OnlyRealReleases | ||
Psa -> fetchFromGitHubTags | ||
PursTidy -> fetchFromGitHubTags | ||
Zephyr -> fetchFromGitHubReleases | ||
where | ||
-- TODO: These functions really ought to be in ExceptT to avoid all the | ||
-- nested branches. | ||
fetchFromGitHubReleases repo = recover do | ||
page <- liftEffect (Ref.new 1) | ||
untilJust do | ||
versions <- liftEffect (Ref.read page) >>= toolVersions repo | ||
case versions of | ||
Just versions' -> do | ||
let version = Array.find (not <<< Version.isPreRelease) versions' | ||
when (isNothing version) do | ||
liftEffect $ void $ Ref.modify (_ + 1) page | ||
pure version | ||
|
||
Nothing -> | ||
throwError $ error "Could not find version that is not a pre-release version" | ||
|
||
toolVersions :: Tool.ToolRepository -> Int -> Aff (Maybe (Array Version)) | ||
toolVersions repo page = do | ||
let | ||
url = | ||
"https://api.github.com/repos/" | ||
<> repo.owner | ||
<> "/" | ||
<> repo.name | ||
<> "/releases?per_page=10&page=" | ||
<> show page | ||
|
||
AX.get RF.json url >>= case _ of | ||
Left err -> throwError (error $ AX.printError err) | ||
Right { body } -> case decodeJson body of | ||
Left e -> do | ||
throwError $ error | ||
$ fold | ||
Zephyr -> fetchFromGitHubReleases OnlyRealReleases | ||
|
||
-- TODO: These functions really ought to be in ExceptT to avoid all the | ||
-- nested branches. | ||
fetchFromGitHubReleases :: ReleaseType -> Tool.ToolRepository -> Aff Version | ||
fetchFromGitHubReleases releaseType repo = recover do | ||
page <- liftEffect (Ref.new 1) | ||
let | ||
releaseFilter = case releaseType of | ||
OnlyRealReleases -> | ||
not <<< Version.isPreRelease | ||
OnlyPreReleases expectedV -> do | ||
let | ||
equating f a b = (f a) == (f b) | ||
majorMinorMatch v = equating Version.major expectedV v && equating Version.minor expectedV v | ||
majorMinorMatch && Version.isPreRelease | ||
JordanMartinez marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
untilJust do | ||
versions <- liftEffect (Ref.read page) >>= toolVersions repo | ||
case versions of | ||
Just versions' -> do | ||
let version = Array.find releaseFilter versions' | ||
when (isNothing version) do | ||
liftEffect $ void $ Ref.modify (_ + 1) page | ||
pure version | ||
|
||
Nothing -> | ||
case releaseType of | ||
OnlyRealReleases -> | ||
throwError $ error "Could not find version that is not a pre-release version" | ||
OnlyPreReleases v -> | ||
throwError $ error $ "Could not find a pre-release version of version, " <> showVersion v | ||
|
||
toolVersions :: Tool.ToolRepository -> Int -> Aff (Maybe (Array Version)) | ||
toolVersions repo page = do | ||
let | ||
url = | ||
"https://api.github.com/repos/" | ||
<> repo.owner | ||
<> "/" | ||
<> repo.name | ||
<> "/releases?per_page=10&page=" | ||
<> show page | ||
|
||
AX.get RF.json url >>= case _ of | ||
Left err -> throwError (error $ AX.printError err) | ||
Right { body } -> case decodeJson body of | ||
Left e -> do | ||
throwError $ error | ||
$ fold | ||
[ "Failed to decode GitHub response. This is most likely due to a timeout.\n\n" | ||
, printJsonDecodeError e | ||
, stringifyWithIndent 2 body | ||
] | ||
Right [] -> pure Nothing | ||
Right objects -> | ||
Just | ||
<$> Array.catMaybes | ||
<$> for objects \obj -> | ||
case obj .: "tag_name" of | ||
Left e -> | ||
throwError $ error $ fold | ||
[ "Failed to get tag from GitHub response: " | ||
, printJsonDecodeError e | ||
] | ||
Right tagName -> | ||
case tagStrToVersion tagName of | ||
Left _ -> do | ||
liftEffect $ warning $ fold | ||
[ "Got invalid version" | ||
, tagName | ||
, " from " | ||
, repo.name | ||
Right [] -> pure Nothing | ||
Right objects -> | ||
Just | ||
<$> Array.catMaybes | ||
<$> for objects \obj -> | ||
case obj .: "tag_name" of | ||
Left e -> | ||
throwError $ error $ fold | ||
[ "Failed to get tag from GitHub response: " | ||
, printJsonDecodeError e | ||
] | ||
Right tagName -> | ||
case tagStrToVersion tagName of | ||
Left _ -> do | ||
liftEffect $ warning $ fold | ||
[ "Got invalid version" | ||
, tagName | ||
, " from " | ||
, repo.name | ||
] | ||
pure Nothing | ||
Right version -> case obj .: "draft" of | ||
Left e -> | ||
throwError $ error $ fold | ||
[ "Failed to get draft from GitHub response: " | ||
, printJsonDecodeError e | ||
] | ||
pure Nothing | ||
Right version -> case obj .: "draft" of | ||
Left e -> | ||
throwError $ error $ fold | ||
[ "Failed to get draft from GitHub response: " | ||
, printJsonDecodeError e | ||
] | ||
Right isDraft -> | ||
pure | ||
if isDraft then Nothing | ||
else Just version | ||
|
||
tagStrToVersion tagStr = | ||
tagStr | ||
# String.stripPrefix (String.Pattern "v") | ||
# fromMaybe tagStr | ||
# Version.parseVersion | ||
|
||
-- If a tool doesn't use GitHub releases and instead only tags versions, then | ||
-- we have to fetch the tags, parse them as appropriate versions, and then sort | ||
-- them according to their semantic version to get the latest one. | ||
fetchFromGitHubTags repo = recover do | ||
let url = "https://api.github.com/repos/" <> repo.owner <> "/" <> repo.name <> "/tags" | ||
|
||
AX.get RF.json url >>= case _ of | ||
Left err -> do | ||
throwError (error $ AX.printError err) | ||
|
||
Right { body } -> case traverse (_ .: "name") =<< decodeJson body of | ||
Left e -> do | ||
throwError $ error $ fold | ||
[ "Failed to decode GitHub response. This is most likely due to a timeout.\n\n" | ||
, printJsonDecodeError e | ||
, stringifyWithIndent 2 body | ||
] | ||
|
||
Right arr -> do | ||
let | ||
tags = Array.mapMaybe (tagStrToVersion >>> hush) arr | ||
|
||
case maximum tags of | ||
Nothing -> | ||
throwError $ error "Could not download latest release version." | ||
|
||
Just v -> | ||
pure v | ||
Right isDraft -> | ||
pure | ||
if isDraft then Nothing | ||
else Just version | ||
Comment on lines
+164
to
+166
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a little clunky (I know it's not your code) -- mind updating it to use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I tried, but either implementation of
and
or
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah, the ol' |
||
|
||
tagStrToVersion :: String -> Either ParseError Version | ||
tagStrToVersion tagStr = | ||
tagStr | ||
# String.stripPrefix (String.Pattern "v") | ||
# fromMaybe tagStr | ||
# Version.parseVersion | ||
|
||
-- If a tool doesn't use GitHub releases and instead only tags versions, then | ||
-- we have to fetch the tags, parse them as appropriate versions, and then sort | ||
-- them according to their semantic version to get the latest one. | ||
fetchFromGitHubTags :: Tool.ToolRepository -> Aff Version | ||
fetchFromGitHubTags repo = recover do | ||
let url = "https://api.github.com/repos/" <> repo.owner <> "/" <> repo.name <> "/tags" | ||
|
||
AX.get RF.json url >>= case _ of | ||
Left err -> do | ||
throwError (error $ AX.printError err) | ||
|
||
Right { body } -> case traverse (_ .: "name") =<< decodeJson body of | ||
Left e -> do | ||
throwError $ error $ fold | ||
[ "Failed to decode GitHub response. This is most likely due to a timeout.\n\n" | ||
, printJsonDecodeError e | ||
, stringifyWithIndent 2 body | ||
] | ||
|
||
Right arr -> do | ||
let | ||
tags = Array.mapMaybe (tagStrToVersion >>> hush) arr | ||
|
||
case maximum tags of | ||
Nothing -> | ||
throwError $ error "Could not download latest release version." | ||
|
||
Just v -> | ||
pure v | ||
|
||
-- Attempt to recover from a failed request by re-attempting according to an | ||
-- exponential backoff strategy. | ||
|
Uh oh!
There was an error while loading. Please reload this page.