@@ -6,6 +6,7 @@ import Prelude
66
77import Affjax as AX
88import Affjax.ResponseFormat as RF
9+ import Control.Monad.Rec.Class (untilJust )
910import Data.Argonaut.Core (Json , jsonEmptyObject , stringify )
1011import Data.Argonaut.Decode (decodeJson , printJsonDecodeError , (.:))
1112import Data.Argonaut.Encode ((:=), (~>))
@@ -14,7 +15,7 @@ import Data.Array as Array
1415import Data.Either (Either (..), hush )
1516import Data.Foldable (fold )
1617import Data.Int (toNumber )
17- import Data.Maybe (Maybe (..), fromMaybe )
18+ import Data.Maybe (Maybe (..), fromMaybe , isNothing )
1819import Data.String as String
1920import Data.Traversable (for , traverse )
2021import Data.Tuple (Tuple (..))
@@ -25,13 +26,14 @@ import Effect.Aff (Aff, Error, Milliseconds(..), delay, error, throwError)
2526import Effect.Aff.Retry (RetryPolicy , RetryPolicyM , RetryStatus (..))
2627import Effect.Aff.Retry as Retry
2728import Effect.Class (liftEffect )
29+ import Effect.Ref as Ref
30+ import GitHub.Actions.Core (warning )
2831import Math (pow )
2932import Node.Encoding (Encoding (..))
3033import Node.FS.Sync (writeTextFile )
3134import Node.Path (FilePath )
3235import Setup.Data.Tool (Tool (..))
3336import Setup.Data.Tool as Tool
34- import Text.Parsing.Parser (parseErrorMessage )
3537
3638-- | Write the latest version of each supported tool
3739updateVersions :: Aff Unit
@@ -70,29 +72,71 @@ fetchLatestReleaseVersion tool = Tool.repository tool # case tool of
7072 -- TODO: These functions really ought to be in ExceptT to avoid all the
7173 -- nested branches.
7274 fetchFromGitHubReleases repo = recover do
73- let url = " https://api.github.com/repos/" <> repo.owner <> " /" <> repo.name <> " /releases/latest"
74-
75- AX .get RF .json url >>= case _ of
76- Left err -> do
77- throwError (error $ AX .printError err)
78-
79- Right { body } -> case (_ .: " tag_name" ) =<< decodeJson body of
80- Left e -> do
81- throwError $ error $ fold
82- [ " Failed to decode GitHub response. This is most likely due to a timeout.\n\n "
83- , printJsonDecodeError e
84- , stringify body
85- ]
86-
87- Right tagStr -> do
88- let tag = fromMaybe tagStr (String .stripPrefix (String.Pattern " v" ) tagStr)
89- case Version .parseVersion tag of
90- Left e ->
91- throwError $ error $ fold
92- [ " Failed to decode tag from GitHub response: " , parseErrorMessage e ]
93-
94- Right v ->
95- pure v
75+ page <- liftEffect (Ref .new 1 )
76+ untilJust do
77+ versions <- liftEffect (Ref .read page) >>= toolVersions repo
78+ case versions of
79+ Just versions' -> do
80+ let version = Array .find (not <<< Version .isPreRelease) versions'
81+ when (isNothing version) do
82+ liftEffect $ void $ Ref .modify (_ + 1 ) page
83+ pure version
84+
85+ Nothing ->
86+ throwError $ error " Could not find version that is not a pre-release version"
87+
88+ toolVersions :: Tool.ToolRepository -> Int -> Aff (Maybe (Array Version ))
89+ toolVersions repo page = do
90+ let
91+ url = " https://api.github.com/repos/" <> repo.owner <> " /" <> repo.name <> " /releases?per_page=10&page=" <> show page
92+ AX .get RF .json url
93+ >>= case _ of
94+ Left err -> throwError (error $ AX .printError err)
95+ Right { body } -> case decodeJson body of
96+ Left e -> do
97+ throwError $ error
98+ $ fold
99+ [ " Failed to decode GitHub response. This is most likely due to a timeout.\n\n "
100+ , printJsonDecodeError e
101+ , stringify body
102+ ]
103+ Right [] -> pure Nothing
104+ Right objects ->
105+ Just
106+ <$> Array .catMaybes
107+ <$> for objects \obj ->
108+ case obj .: " tag_name" of
109+ Left e ->
110+ throwError $ error $ fold
111+ [ " Failed to get tag from GitHub response: "
112+ , printJsonDecodeError e
113+ ]
114+ Right tagName ->
115+ case tagStrToVersion tagName of
116+ Left e -> do
117+ liftEffect $ warning $ fold
118+ [ " Got invalid version"
119+ , tagName
120+ , " from "
121+ , repo.name
122+ ]
123+ pure Nothing
124+ Right version -> case obj .: " draft" of
125+ Left e ->
126+ throwError $ error $ fold
127+ [ " Failed to get draft from GitHub response: "
128+ , printJsonDecodeError e
129+ ]
130+ Right isDraft ->
131+ if isDraft
132+ then pure Nothing
133+ else pure (Just version)
134+
135+ tagStrToVersion tagStr =
136+ tagStr
137+ # String .stripPrefix (String.Pattern " v" )
138+ # fromMaybe tagStr
139+ # Version .parseVersion
96140
97141 -- If a tool doesn't use GitHub releases and instead only tags versions, then
98142 -- we have to fetch the tags, parse them as appropriate versions, and then sort
@@ -114,7 +158,7 @@ fetchLatestReleaseVersion tool = Tool.repository tool # case tool of
114158
115159 Right arr -> do
116160 let
117- tags = Array .catMaybes $ map (\t -> hush $ Version .parseVersion $ fromMaybe t $ String .stripPrefix ( String.Pattern " v " ) t ) arr
161+ tags = Array .catMaybes $ map (tagStrToVersion >>> hush) arr
118162 sorted = Array .reverse $ Array .sort tags
119163
120164 case Array .head sorted of
0 commit comments