libjenkins 0.8.1 → 0.8.2
raw patch · 14 files changed
+114/−99 lines, 14 filesdep ~http-clientdep ~http-conduitPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: http-client, http-conduit
API changes (from Hackage documentation)
Files
- CHANGELOG.markdown +5/−0
- example/discover.hs +2/−2
- example/grep-jobs.hs +1/−2
- example/rename-jobs.hs +4/−1
- example/running-jobs-count.hs +1/−1
- libjenkins.cabal +10/−4
- src/Jenkins/Discover.hs +1/−1
- src/Jenkins/Rest.hs +11/−12
- src/Jenkins/Rest/Internal.hs +11/−22
- src/Jenkins/Rest/Method.hs +22/−16
- src/Jenkins/Rest/Method/Internal.hs +25/−22
- test/Doctest.hs +1/−2
- test/Jenkins/Rest/InternalSpec.hs +1/−1
- test/Jenkins/RestSpec.hs +19/−13
CHANGELOG.markdown view
@@ -1,3 +1,8 @@+0.8.2+=====++ * Stopped using the deprecated stuff in `http-client{,-tls}`.+ 0.8.1 =====
example/discover.hs view
@@ -2,7 +2,7 @@ -- | Discover Jenkins server on the network module Main (main) where -import Data.Monoid ((<>), mempty) -- base+import Data.Monoid ((<>)) -- base import Data.Text (Text) -- text import qualified Data.Text as Text -- text import qualified Data.Text.IO as Text -- text@@ -23,7 +23,7 @@ -- | Pretty print Jenkins discovery responses pretty :: Discover -> Text pretty x = Text.unwords $- "Jenkins" : version x : maybe mempty (return . between "(" ")") (serverId x) ++ ["at", url x]+ "Jenkins" : version x : maybe [] (return . between "(" ")") (serverId x) ++ ["at", url x] where between l r t = l <> t <> r
example/grep-jobs.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} -- | Grep Jenkins instance jobs with Perl regex module Main (main) where@@ -39,7 +38,7 @@ grep :: String -> Jenkins.Master -> IO [Text] grep regex conn = do res <- Jenkins.run conn $- Jenkins.get Jenkins.json ("/" -?- "tree" -=- "jobs[name]")+ Jenkins.get Jenkins.json ("" -?- "tree" -=- "jobs[name]") filterM (match regex) (res ^.. _Right.key "jobs".values.key "name"._String) -- | Match job name again Perl regex
example/rename-jobs.hs view
@@ -1,9 +1,12 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-} -- | Rename jobs matching supplied pattern module Main (main) where +#if __GLASGOW_HASKELL__ < 710 import Control.Applicative -- base+#endif import Control.Lens -- lens import Control.Monad (when) -- base import Data.Aeson.Lens -- lens-aeson@@ -47,7 +50,7 @@ rename :: Jenkins.Master -> Text -> Text -> IO (Either JenkinsException ()) rename conf old new = Jenkins.run conf $ do -- get jobs names from jenkins "root" API- res <- Jenkins.get Jenkins.json ("/" -?- "tree" -=- "jobs[name]")+ res <- Jenkins.get Jenkins.json ("" -?- "tree" -=- "jobs[name]") let jobs = res ^.. key "jobs".values.key "name"._String for_ jobs rename_job where
example/running-jobs-count.hs view
@@ -27,7 +27,7 @@ <*> var str "JENKINS_API_TOKEN" (help "Jenkins API token") getJobs :: Jenkins ByteString-getJobs = Jenkins.get Jenkins.json ("/" -?- "tree" -=- "jobs[color]")+getJobs = Jenkins.get Jenkins.json ("" -?- "tree" -=- "jobs[color]") running :: Fold ByteString () running = key "jobs".values.key "color"._String.only "blue_anime"
libjenkins.cabal view
@@ -1,5 +1,5 @@ name: libjenkins-version: 0.8.1+version: 0.8.2 synopsis: Jenkins API interface description: Jenkins API interface. It supports REST and Discovery APIs license: BSD2@@ -26,7 +26,7 @@ source-repository this type: git location: https://github.com/supki/libjenkins- tag: 0.8.1+ tag: 0.8.2 library default-language:@@ -39,8 +39,8 @@ , conduit >= 1.2 , containers , free >= 4.10- , http-conduit >= 2.1- , http-client >= 0.4+ , http-conduit >= 2.1.8+ , http-client >= 0.4.19 , http-types >= 0.8 , monad-control >= 0.3 , profunctors >= 4.2@@ -60,6 +60,8 @@ Jenkins.Rest.Method.Internal Network.HTTP.Client.Lens Network.HTTP.Client.Lens.Internal+ ghc-options:+ -Wall test-suite doctest default-language:@@ -75,6 +77,8 @@ test main-is: Doctest.hs+ ghc-options:+ -Wall test-suite spec default-language:@@ -116,5 +120,7 @@ Jenkins.RestSpec Jenkins.Rest.InternalSpec Jenkins.Rest.Method.InternalSpec+ ghc-options:+ -Wall cpp-options: -DTEST
src/Jenkins/Discover.hs view
@@ -43,7 +43,7 @@ -> IO [Discover] discover t = do (b, addr) <- broadcastSocket- ByteString.sendTo b (ByteString.pack [0, 0, 0, 0]) addr -- does not matter what to send+ _ <- ByteString.sendTo b (ByteString.pack [0, 0, 0, 0]) addr -- does not matter what to send msgs <- while (timeout t (readAnswer b))
src/Jenkins/Rest.hs view
@@ -39,8 +39,8 @@ , Http.Request ) where -import Control.Applicative ((<$)) import qualified Control.Exception as Unlifted+import Control.Monad (void) import Control.Monad.IO.Class (MonadIO(..)) import Control.Monad.Trans.Control (MonadBaseControl(..)) import Control.Monad.Trans.Resource (MonadResource)@@ -49,7 +49,6 @@ import Data.Conduit (ResumableSource) import Data.Data (Data, Typeable) import qualified Data.Foldable as F-import Data.Monoid (mempty) import Data.Text (Text) import qualified Data.Text.Lazy as Text.Lazy import qualified Data.Text.Lazy.Encoding as Text.Lazy@@ -90,7 +89,7 @@ -- -- While the return type is /lazy/ @Bytestring@, the entire response -- sits in memory anyway: lazy I/O is not used at the least-get :: Formatter f -> (forall g. Method Complete g) -> JenkinsT m Lazy.ByteString+get :: Formatter f -> (forall g. Method 'Complete g) -> JenkinsT m Lazy.ByteString get (Formatter f) m = liftJ (Get (f m) id) -- | Perform a streaming @GET@ request@@ -98,16 +97,16 @@ -- 'stream', unlike 'get', is constant-space stream :: MonadResource m- => Formatter f -> (forall g. Method Complete g) -> JenkinsT m (ResumableSource m Strict.ByteString)+ => Formatter f -> (forall g. Method 'Complete g) -> JenkinsT m (ResumableSource m Strict.ByteString) stream (Formatter f) m = liftJ (Stream (f m) id) -- | Perform a @POST@ request-post :: (forall f. Method Complete f) -> Lazy.ByteString -> JenkinsT m Lazy.ByteString+post :: (forall f. Method 'Complete f) -> Lazy.ByteString -> JenkinsT m Lazy.ByteString post m body = liftJ (Post m body id) -- | Perform a @POST@ request without a payload-post_ :: (forall f. Method Complete f) -> JenkinsT m Lazy.ByteString-post_ m = post m mempty+post_ :: (forall f. Method 'Complete f) -> JenkinsT m Lazy.ByteString+post_ m = post m Lazy.empty -- | A simple exception handler. If an exception is raised while the action is -- executed the handler is executed with it as an argument@@ -147,14 +146,14 @@ -- -- @'traverse_' : 'Data.Foldable.traverse_' :: 'concurrently' : 'Control.Applicative.liftA2' (,)@ traverse_ :: F.Foldable f => (a -> JenkinsT m b) -> f a -> JenkinsT m ()-traverse_ f = F.foldr (\x xs -> () <$ concurrently (f x) xs) (return ())+traverse_ f = F.foldr (\x -> void . concurrently (f x)) (return ()) -- | Perform a @POST@ request to Jenkins with the XML document -- -- Sets up the correct @Content-Type@ header. Mostly useful for updating @config.xml@ -- files for jobs, views, etc-postXml :: (forall f. Method Complete f) -> Lazy.ByteString -> JenkinsT m Lazy.ByteString+postXml :: (forall f. Method 'Complete f) -> Lazy.ByteString -> JenkinsT m Lazy.ByteString postXml m = locally (\r -> r { Http.requestHeaders = xmlHeader : Http.requestHeaders r }) . post m where xmlHeader = ("Content-Type", "text/xml")@@ -174,7 +173,7 @@ -- -- Performs @/reload@ reload :: JenkinsT m ()-reload = () <$ post_ "reload"+reload = void (post_ "reload") -- | Restart jenkins safely --@@ -182,7 +181,7 @@ -- -- @/safeRestart@ allows all running jobs to complete restart :: JenkinsT m ()-restart = () <$ post_ "safeRestart"+restart = void (post_ "safeRestart") -- | Restart jenkins --@@ -191,4 +190,4 @@ -- @/restart@ restart Jenkins immediately, without waiting for the completion of -- the building and/or waiting jobs forceRestart :: JenkinsT m ()-forceRestart = () <$ post_ "restart"+forceRestart = void (post_ "restart")
src/Jenkins/Rest/Internal.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveDataTypeable #-}@@ -21,7 +22,9 @@ , iter ) where +#if __GLASGOW_HASKELL__ < 710 import Control.Applicative+#endif import Control.Concurrent.Async (Async) import qualified Control.Concurrent.Async as Unlifted import Control.Exception (Exception(..), SomeException, throwIO)@@ -91,9 +94,9 @@ data JF :: (* -> *) -> * -> * where- Get :: Method Complete f -> (ByteString -> a) -> JF m a- Stream :: MonadResource m => Method Complete f -> (ResumableSource m Strict.ByteString -> a) -> JF m a- Post :: (forall f. Method Complete f) -> ByteString -> (ByteString -> a) -> JF m a+ Get :: Method 'Complete f -> (ByteString -> a) -> JF m a+ Stream :: MonadResource m => Method 'Complete f -> (ResumableSource m Strict.ByteString -> a) -> JF m a+ Post :: (forall f. Method 'Complete f) -> ByteString -> (ByteString -> a) -> JF m a Conc :: JenkinsT m a -> JenkinsT m b -> (a -> b -> c) -> JF m c Or :: JenkinsT m a -> (JenkinsException -> JenkinsT m a) -> JF m a With :: (Request -> Request) -> JenkinsT m b -> (b -> a) -> JF m a@@ -125,16 +128,9 @@ => String -> Text -> Text -> JenkinsT m a -> m a runInternal h user token jenk = do url <- liftIO (wrapException (Http.parseUrl h))- bracket (newManager Http.conduitManagerSettings) closeManager $ \m ->- runInterpT (iterInterpT m jenk)- . Http.applyBasicAuth (Text.encodeUtf8 user) (Text.encodeUtf8 token)- $ url--newManager :: MonadIO m => Http.ManagerSettings -> m Http.Manager-newManager = liftIO . Http.newManager--closeManager :: MonadIO m => Http.Manager -> m ()-closeManager = liftIO . Http.closeManager+ man <- liftIO (Http.newManager Http.tlsManagerSettings)+ runInterpT (iterInterpT man jenk)+ (Http.applyBasicAuth (Text.encodeUtf8 user) (Text.encodeUtf8 token) url) newtype InterpT m a = InterpT { runInterpT :: Request -> m a@@ -202,13 +198,13 @@ -> InterpT m a intoM m f = InterpT $ \req -> f (\x -> runInterpT (iterInterpT m x) req) -prepareGet :: Method Complete f -> Request -> Request+prepareGet :: Method 'Complete f -> Request -> Request prepareGet m r = r { Http.method = "GET" , Http.path = Http.path r `slash` render m } -preparePost :: Method Complete f -> ByteString -> Request -> Request+preparePost :: Method 'Complete f -> ByteString -> Request -> Request preparePost m body r = r { Http.checkStatus = statusCheck , Http.redirectCount = 0@@ -250,13 +246,6 @@ mask :: MonadBaseControl IO m => ((forall a. m a -> m a) -> m b) -> m b mask f = control $ \magic -> Unlifted.mask (\g -> magic (f (liftBaseOp_ g))) {-# INLINABLE mask #-}--bracket :: (MonadBaseControl IO m) => m a -> (a -> m b) -> (a -> m c) -> m c-bracket f g h = control $ \magic ->- Unlifted.bracket (magic f)- (\b -> magic (restoreM b >>= g))- (\c -> magic (restoreM c >>= h))-{-# INLINABLE bracket #-} catch :: (MonadBaseControl IO m, Exception e) => m a -> (e -> m a) -> m a catch m h = control (\magic -> Unlifted.catch (magic m) (magic . h))
src/Jenkins/Rest/Method.hs view
@@ -68,35 +68,35 @@ -- -- >>> pp' "foo/bar" -- "foo%2Fbar"-text :: Text -> Method Complete f+text :: Text -> Method 'Complete f text = Text -- | Use an integer as an URI segment -- -- >>> pp (int 4) -- "4"-int :: Int -> Method Complete f+int :: Int -> Method 'Complete f int = fromIntegral -- | Combine two paths -- -- >>> pp ("foo" -/- "bar" -/- "baz") -- "foo/bar/baz"-(-/-) :: Method Complete f -> Method Complete f -> Method Complete f+(-/-) :: Method 'Complete f -> Method 'Complete f -> Method 'Complete f (-/-) = (:/) -- | Make a key-value pair -- -- >>> pp ("foo" -=- "bar") -- "foo=bar"-(-=-) :: Text -> Text -> Method Query f+(-=-) :: Text -> Text -> Method 'Query f x -=- y = x := Just y -- | Create the union of two queries -- -- >>> pp ("foo" -=- "bar" -&- "baz") -- "foo=bar&baz"-(-&-) :: Method Query f -> Method Query f -> Method Query f+(-&-) :: Method 'Query f -> Method 'Query f -> Method 'Query f (-&-) = (:&) -- | Take a list of key-value pairs and render them as a query@@ -106,21 +106,27 @@ -- -- >>> pp (query []) -- ""-query :: [(Text, Maybe Text)] -> Method Query f+query :: [(Text, Maybe Text)] -> Method 'Query f query = foldr ((:&) . uncurry (:=)) Empty -- | Put path and query together -- -- >>> pp ("qux" -/- "quux" -?- "foo" -=- "bar" -&- "baz") -- "qux/quux?foo=bar&baz"-(-?-) :: Method Complete f -> Method Query f -> Method Complete f+--+-- >>> pp ("" -?- "foo" -=- "bar")+-- "foo=bar"+--+-- >>> pp ("/" -?- "foo" -=- "bar")+-- "%2F?foo=bar"+(-?-) :: Method 'Complete f -> Method 'Query f -> Method 'Complete f (-?-) = (:?) -- | Append the JSON formatting request to the method URL -- -- >>> format json "foo" -- "foo/api/json"-json :: Formatter Json+json :: Formatter 'Json json = Formatter (\m -> m :@ SJson) {-# ANN json ("HLint: ignore Avoid lambda" :: String) #-} @@ -128,7 +134,7 @@ -- -- >>> format xml "foo" -- "foo/api/xml"-xml :: Formatter Xml+xml :: Formatter 'Xml xml = Formatter (\m -> m :@ SXml) {-# ANN xml ("HLint: ignore Avoid lambda" :: String) #-} @@ -136,7 +142,7 @@ -- -- >>> format python "foo" -- "foo/api/python"-python :: Formatter Python+python :: Formatter 'Python python = Formatter (\m -> m :@ SPython) {-# ANN python ("HLint: ignore Avoid lambda" :: String) #-} @@ -156,40 +162,40 @@ -- -- >>> pp (job "name" -/- "config.xml") -- "job/name/config.xml"-job :: Text -> Method Complete f+job :: Text -> Method 'Complete f job name = "job" -/- text name -- | Job build data -- -- >>> format json (build "name" 4) -- "job/name/4/api/json"-build :: Text -> Int -> Method Complete f+build :: Text -> Int -> Method 'Complete f build name num = "job" -/- text name -/- int num -- | View data -- -- >>> format xml (view "name") -- "view/name/api/xml"-view :: Text -> Method Complete f+view :: Text -> Method 'Complete f view name = "view" -/- text name -- | Build queue data -- -- >>> format python queue -- "queue/api/python"-queue :: Method Complete f+queue :: Method 'Complete f queue = "queue" -- | Server statistics -- -- >>> format xml overallLoad -- "overallLoad/api/xml"-overallLoad :: Method Complete f+overallLoad :: Method 'Complete f overallLoad = "overallLoad" -- | Nodes data -- -- >>> format python computer -- "computer/api/python"-computer :: Method Complete f+computer :: Method 'Complete f computer = "computer"
src/Jenkins/Rest/Method/Internal.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE FlexibleContexts #-}@@ -14,7 +15,9 @@ import Control.Applicative import Data.ByteString (ByteString) import Data.Data (Data, Typeable)-import Data.Monoid (Monoid(..), (<>))+#if __GLASGOW_HASKELL__ < 710+import Data.Monoid (Monoid(..))+#endif import Data.String (IsString(..)) import qualified Data.Text as Text import qualified Data.Text.Encoding as Text@@ -32,18 +35,18 @@ -- | Jenkins RESTFul API method encoding data Method :: Type -> Format -> * where- Empty :: Method Query f- Text :: Text -> Method Complete f- (:/) :: Method Complete f -> Method Complete f -> Method Complete f- (:=) :: Text -> Maybe Text -> Method Query f- (:&) :: Method Query f -> Method Query f -> Method Query f- (:?) :: Method Complete f -> Method Query f -> Method Complete f- (:@) :: Method Complete f -> SFormat f -> Method Complete f+ Empty :: Method 'Query f+ Text :: Text -> Method 'Complete f+ (:/) :: Method 'Complete f -> Method 'Complete f -> Method 'Complete f+ (:=) :: Text -> Maybe Text -> Method 'Query f+ (:&) :: Method 'Query f -> Method 'Query f -> Method 'Query f+ (:?) :: Method 'Complete f -> Method 'Query f -> Method 'Complete f+ (:@) :: Method 'Complete f -> SFormat f -> Method 'Complete f deriving instance Show (SFormat f) => Show (Method t f) -- | Only to support numeric literals-instance t ~ Complete => Num (Method t f) where+instance t ~ 'Complete => Num (Method t f) where (+) = error "Method.(+): not supposed to be used" (-) = error "Method.(-): not supposed to be used" (*) = error "Method.(*): not supposed to be used"@@ -51,10 +54,10 @@ signum = error "Method.signum: not supposed to be used" fromInteger = fromString . show -instance IsString (Method Complete f) where+instance IsString (Method 'Complete f) where fromString = Text . fromString -instance IsString (Method Query f) where+instance IsString (Method 'Query f) where fromString str = fromString str := Nothing -- | Method types@@ -66,45 +69,45 @@ deriving (Show, Eq, Typeable, Data) data SFormat :: Format -> * where- SJson :: SFormat Json- SXml :: SFormat Xml- SPython :: SFormat Python+ SJson :: SFormat 'Json+ SXml :: SFormat 'Xml+ SPython :: SFormat 'Python -- | 'Formatter's know how to append the \"api/$format\" string to the method URL newtype Formatter g = Formatter- { unFormatter :: (forall f. Method Complete f) -> Method Complete g+ { unFormatter :: (forall f. Method 'Complete f) -> Method 'Complete g } -format :: Formatter f -> (forall g. Method Complete g) -> ByteString+format :: Formatter f -> (forall g. Method 'Complete g) -> ByteString format f m = render (unFormatter f m) -- | Render 'Method' to something that can be sent over the wire-render :: Method Complete f -> ByteString+render :: Method 'Complete f -> ByteString render m = maybe id (flip (insert "?")) (renderQ m) . maybe id (flip (insert "/")) (renderF m) . renderP $ m -- | Render the method path-renderP :: Method Complete f -> ByteString+renderP :: Method 'Complete f -> ByteString renderP (Text s) = renderT s renderP (x :/ y) = renderP x `slash` renderP y renderP (x :? _) = renderP x renderP (x :@ _) = renderP x -- | Render the query string-renderQ :: Method Complete f -> Maybe ByteString+renderQ :: Method 'Complete f -> Maybe ByteString renderQ (Text _) = Nothing renderQ (q :/ q') = renderQ q <|> renderQ q' renderQ (q :@ _) = renderQ q renderQ (_ :? q) = Just (renderQ' q) -renderQ' :: Method Query f -> ByteString+renderQ' :: Method 'Query f -> ByteString renderQ' (x :& y) = insert "&" (renderQ' x) (renderQ' y) renderQ' (x := Just y) = insert "=" (renderT x) (renderT y) renderQ' (x := Nothing) = renderT x renderQ' Empty = renderT "" -- | Render the response format string-renderF :: Method Complete f -> Maybe ByteString+renderF :: Method 'Complete f -> Maybe ByteString renderF (_ :@ SJson) = Just "api/json" renderF (_ :@ SXml) = Just "api/xml" renderF (_ :@ SPython) = Just "api/python"@@ -138,4 +141,4 @@ insert t x y | x == mempty = y | y == mempty = x- | otherwise = x <> t <> y+ | otherwise = x `mappend` t `mappend` y
test/Doctest.hs view
@@ -1,6 +1,5 @@ module Main where -import Control.Applicative ((<$>)) import Control.Monad (forM, liftM) import Data.List (isSuffixOf) import System.Directory (getDirectoryContents, doesDirectoryExist)@@ -25,4 +24,4 @@ isSource path = any (`isSuffixOf` path) [".hs", ".lhs"] contents :: FilePath -> IO [FilePath]-contents dir = filter (`notElem` [".", ".."]) <$> getDirectoryContents dir+contents = fmap (filter (`notElem` [".", ".."])) . getDirectoryContents
test/Jenkins/Rest/InternalSpec.hs view
@@ -41,7 +41,7 @@ it "can catch 'HttpException' exceptions related from the queries" $ do r <- Jenkins.run master (liftJ (Or (Jenkins.get Jenkins.plain "hi" >> return 4) (\_ -> return 7)))- r `shouldPreview` 7 `through` _Right+ r `shouldPreview` (7 :: Integer) `through` _Right it "does not catch (and wrap) 'HttpException's not from the queries" $ Jenkins.run master raiseHttp `shouldThrow` _TooManyRetries
test/Jenkins/RestSpec.hs view
@@ -1,14 +1,16 @@+{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} module Jenkins.RestSpec (spec) where +#if __GLASGOW_HASKELL__ < 710 import Control.Applicative+#endif import Control.Monad.Trans.State (State, evalState, get, put) import qualified Data.ByteString as Strict import qualified Data.ByteString.Lazy as Lazy import Data.Functor.Identity (Identity)-import Data.Monoid (mempty) import Test.Hspec import qualified Jenkins.Rest as Jenkins import Jenkins.Rest.Internal@@ -20,26 +22,29 @@ context "POST requests" $ do it "post_ sends POST request with empty body" $ do interpret $ do- Jenkins.post_ "foo"- Jenkins.post_ "bar"- Jenkins.post_ "baz"+ _ <- Jenkins.post_ "foo"+ _ <- Jenkins.post_ "bar"+ _ <- Jenkins.post_ "baz"+ return () `shouldBe` [QPost 0 "" "foo", QPost 1 "" "bar", QPost 2 "" "baz"] it "post sends POST request with non-empty body" $ do interpret $ do- Jenkins.post "foo" "qux"- Jenkins.post "bar" "quux"- Jenkins.post "baz" "xyzzy"+ _ <- Jenkins.post "foo" "qux"+ _ <- Jenkins.post "bar" "quux"+ _ <- Jenkins.post "baz" "xyzzy"+ return () `shouldBe` [QPost 0 "qux" "foo", QPost 1 "quux" "bar", QPost 2 "xyzzy" "baz"] context "GET requests" $ it "get sends GET requests" $ do interpret $ do- Jenkins.get Jenkins.plain "foo"- Jenkins.get Jenkins.plain "bar"- Jenkins.get Jenkins.plain "baz"+ _ <- Jenkins.get Jenkins.plain "foo"+ _ <- Jenkins.get Jenkins.plain "bar"+ _ <- Jenkins.get Jenkins.plain "baz"+ return () `shouldBe` [QGet 0 "foo", QGet 1 "bar", QGet 2 "baz"] @@ -57,12 +62,13 @@ go :: JF Identity (State (Requests Int) [Query]) -> State (Requests Int) [Query] go (Get m n) = do r <- render QGet m- fmap (r :) (n mempty)+ fmap (r :) (n Lazy.empty) go (Post m body n) = do r <- render (\x y -> QPost x body y) m- fmap (r :) (n mempty)+ fmap (r :) (n Lazy.empty)+ go _ = error "unexpected term" -render :: (a -> Strict.ByteString -> Query) -> Jenkins.Method Method.Complete f -> State (Requests a) Query+render :: (a -> Strict.ByteString -> Query) -> Jenkins.Method 'Method.Complete f -> State (Requests a) Query render f m = do n <- next return $ f n (Method.render m)