@@ -14,8 +14,12 @@ import Control.Monad.Except
14import Control.Monad.IO.Unlift
14import Control.Monad.IO.Unlift
15import Control.Monad.Reader
15import Control.Monad.Reader
16import Control.Task.Scheduler
16import Control.Task.Scheduler
17+import Crypto.PubKey.RSA.Read
17import Data.Aeson
18import Data.Aeson
18import Data.ByteString
19import Data.ByteString
20+import qualified Data.ByteString as BS
21+import qualified Data.ByteString.Char8 as BSC
22+import qualified Data.ByteString.Lazy.Char8 as BSCL
19import qualified Data.Csv as Csv
23import qualified Data.Csv as Csv
20import Data.IORef
24import Data.IORef
21import Data.Map (Map)
25import Data.Map (Map)
@@ -30,9 +34,11 @@ import GHC.Generics
30import GitHub hiding (Accept)
34import GitHub hiding (Accept)
31import GitHub.App.Auth
35import GitHub.App.Auth
32import GitHub.App.Request
36import GitHub.App.Request
37+import GitHub.Auth (Auth (OAuth))
33import GitHub.Data.Name
38import GitHub.Data.Name
34import GitHub.Data.Webhooks.Events
39import GitHub.Data.Webhooks.Events
35import GitHub.Data.Webhooks.Payload
40import GitHub.Data.Webhooks.Payload
41+import Network.HTTP.Client.TLS (newTlsManager)
36import Network.HTTP.Media.MediaType
42import Network.HTTP.Media.MediaType
37import Network.Wai.Handler.Warp
43import Network.Wai.Handler.Warp
38import Servant
44import Servant
@@ -44,7 +50,7 @@ import Server.Schema
44import Squeal.PostgreSQL
50import Squeal.PostgreSQL
45import System.IO
51import System.IO
46import Text.Blaze.Html
52import Text.Blaze.Html
47−import UnliftIO.Exception (catch, throwIO, try)
53+import UnliftIO.Exception (catch, displayException, handleAny, throwIO, try)
50 "github-webhook"
56 "github-webhook"
@@ -161,6 +167,10 @@ runServer :: IO ()
161runServer = do
167runServer = do
162 c@Config {..} <- getConfig
168 c@Config {..} <- getConfig
170+ pem <- BS.readFile appPkPemPath
171+ appPkPem <- case readRsaPem pem of
173+ Left e -> error (show e)
164 auth <- mkInstallationAuth (AppAuth appId appPkPem) installationId
174 auth <- mkInstallationAuth (AppAuth appId appPkPem) installationId
165 ts <- newIORef mempty
175 ts <- newIORef mempty
166 pool <- createConnectionPool databseUrl 1 0.5 10
176 pool <- createConnectionPool databseUrl 1 0.5 10
@@ -173,8 +183,6 @@ runServer = do
173 serverData =
183 serverData =
174 ServerData
184 ServerData
175 { githubAppAuth = auth,
185 { githubAppAuth = auth,
176− githubUserName = GithubUserName githubUsername,
177− githubAccessToken = GithubAccessToken personalAccessToken,
178 tasks = ts,
186 tasks = ts,
179 logger = cfilter ((logSeverity <=) . msgSeverity) richMessageAction,
187 logger = cfilter ((logSeverity <=) . msgSeverity) richMessageAction,
180 baseUrl = baseSiteUrl,
188 baseUrl = baseSiteUrl,
@@ -183,17 +191,21 @@ runServer = do
183 repeatIfNotEmpty n f = f >>= \m -> do
191 repeatIfNotEmpty n f = f >>= \m -> do
184 when (m == 0) $ liftIO $ threadDelay n
192 when (m == 0) $ liftIO $ threadDelay n
185 repeatIfNotEmpty n f
193 repeatIfNotEmpty n f
195+ handleAny (logError . T.pack . displayException >=> const (return 0))
187 forkIO . repeatIfNotEmpty (10 ^ (6 :: Int))
197 forkIO . repeatIfNotEmpty (10 ^ (6 :: Int))
188 . usingConnectionPool pool
198 . usingConnectionPool pool
189 . (`runReaderT` serverData)
199 . (`runReaderT` serverData)
191 $ runTasks @'[Build] 1
202 $ runTasks @'[Build] 1
193 forkIO . repeatIfNotEmpty (10 ^ (6 :: Int))
204 forkIO . repeatIfNotEmpty (10 ^ (6 :: Int))
194 . usingConnectionPool pool
205 . usingConnectionPool pool
195 . (`runReaderT` serverData)
206 . (`runReaderT` serverData)
197 $ runTasks @'[StatusUpdate] 5
209 $ runTasks @'[StatusUpdate] 5
198 run port $ serveWithContext (Proxy @API) context $
210 run port $ serveWithContext (Proxy @API) context $
199 hoistServerWithContext
211 hoistServerWithContext
@@ -211,8 +223,6 @@ updateTasks ref path =
211data ServerData m
223data ServerData m
212 = ServerData
224 = ServerData
213 { githubAppAuth :: !InstallationAuth,
225 { githubAppAuth :: !InstallationAuth,
214− githubUserName :: !GithubUserName,
215− githubAccessToken :: !GithubAccessToken,
216 tasks :: IORef TasksConfig,
226 tasks :: IORef TasksConfig,
217 logger :: LogAction m Message,
227 logger :: LogAction m Message,
218 baseUrl :: String,
228 baseUrl :: String,
@@ -227,10 +237,18 @@ gitPolyHubKey k = PolyGitHubKey (Servant.GitHub.Webhook.gitHubKey k)
227instance HasContextEntry '[PolyGitHubKey] (GitHubKey result) where
237instance HasContextEntry '[PolyGitHubKey] (GitHubKey result) where
228 getContextEntry (PolyGitHubKey x :. _) = x
238 getContextEntry (PolyGitHubKey x :. _) = x
230−instance MonadReader (ServerData n) m => GithubCloner m where
240+instance (MonadReader (ServerData n) m, MonadIO m, MonadError ServerError m) => GithubCloner m where
231− getGithubAccessToken = asks githubAccessToken
241+ getGithubInstallationToken =
233− getGithubUserName = asks githubUserName
243+ (\e -> throwError err500 {errBody = BSCL.pack . displayException $ e})
247+ iAuth <- asks githubAppAuth
248+ manager <- newTlsManager
249+ liftIO (obtainAccessToken manager iAuth) >>= either throwError return >>= \case
250+ OAuth token -> return $ InstallationToken (BSC.unpack token)
251+ _ -> throwError $ UserError "Not OAuth token. This should never happen."
235instance (MonadIO m, MonadReader (ServerData n) m) => AppRequestable m where
253instance (MonadIO m, MonadReader (ServerData n) m) => AppRequestable m where
236 appRequest req = do
254 appRequest req = do