From 4c5ed40a9352c6088550af6801ae89ba5371c78e Mon Sep 17 00:00:00 2001 From: Thomas Honeyman Date: Wed, 9 Aug 2023 12:21:20 -0400 Subject: [PATCH 1/3] Set up healthchecks --- app/src/App/Effect/Env.purs | 9 ++++++++- app/src/App/Server.purs | 24 +++++++++++++++++++++++- lib/src/API/V1.purs | 7 +++---- 3 files changed, 34 insertions(+), 6 deletions(-) diff --git a/app/src/App/Effect/Env.purs b/app/src/App/Effect/Env.purs index 31c90362..cbf23a04 100644 --- a/app/src/App/Effect/Env.purs +++ b/app/src/App/Effect/Env.purs @@ -26,6 +26,7 @@ type ResourceEnv = , s3BucketUrl :: URL , githubApiUrl :: URL , pursuitApiUrl :: URL + , healthchecksUrl :: URL } -- | An effect for various external resources (files, databases, API endpoints, @@ -49,6 +50,7 @@ lookupResourceEnv = do s3BucketUrlEnv <- lookupWithDefault s3BucketUrl defaultS3BucketUrl githubApiUrlEnv <- lookupWithDefault githubApiUrl defaultGitHubApiUrl pursuitApiUrlEnv <- lookupWithDefault pursuitApiUrl defaultPursuitApiUrl + healthchecksUrlEnv <- lookupRequired healthchecksUrl pure { dhallTypes: dhallTypesEnv , databaseUrl: databaseUrlEnv @@ -56,6 +58,7 @@ lookupResourceEnv = do , s3BucketUrl: s3BucketUrlEnv , githubApiUrl: githubApiUrlEnv , pursuitApiUrl: pursuitApiUrlEnv + , healthchecksUrl: healthchecksUrlEnv } -- | Environment fields available in the GitHub Event environment, namely @@ -202,13 +205,17 @@ githubApiUrl = EnvKey { key: "GITHUB_API_URL", decode: pure } defaultGitHubApiUrl :: URL defaultGitHubApiUrl = "https://api.github.com" --- | The base URL of the GitHub API +-- | The base URL of the Pursuit API pursuitApiUrl :: EnvKey URL pursuitApiUrl = EnvKey { key: "PURSUIT_API_URL", decode: pure } defaultPursuitApiUrl :: URL defaultPursuitApiUrl = "https://pursuit.purescript.org" +-- | The URL of the health checks endpoint +healthchecksUrl :: EnvKey URL +healthchecksUrl = EnvKey { key: "HEALTHCHECKS_URL", decode: pure } + -- | A GitHub token for the @pacchettibotti user at the PACCHETTIBOTTI_TOKEN key. pacchettibottiToken :: EnvKey GitHubToken pacchettibottiToken = EnvKey { key: "PACCHETTIBOTTI_TOKEN", decode: decodeGitHubToken } diff --git a/app/src/App/Server.purs b/app/src/App/Server.purs index f349c137..92ab3f55 100644 --- a/app/src/App/Server.purs +++ b/app/src/App/Server.purs @@ -2,6 +2,9 @@ module Registry.App.Server where import Registry.App.Prelude hiding ((/)) +import Affjax.Node as Affjax +import Affjax.ResponseFormat as ResponseFormat +import Affjax.StatusCode (StatusCode(..)) import Control.Monad.Cont (ContT) import Data.Codec.Argonaut as CA import Data.Formatter.DateTime as Formatter.DateTime @@ -12,6 +15,7 @@ import Effect.Aff as Aff import Effect.Class.Console as Console import HTTPurple (JsonDecoder(..), JsonEncoder(..), Method(..), Request, Response) import HTTPurple as HTTPurple +import HTTPurple.Status as Status import Node.Path as Path import Node.Process as Process import Record as Record @@ -102,7 +106,14 @@ router env { route, method, body } = HTTPurple.usingCont case route, method of Right job -> do jsonOk V1.jobCodec (Record.insert (Proxy :: _ "logs") logs job) - _, _ -> HTTPurple.notFound + Status, Get -> + HTTPurple.emptyResponse Status.ok + + Status, Head -> + HTTPurple.emptyResponse Status.ok + + _, _ -> + HTTPurple.notFound where forkPipelineJob :: PackageName -> String -> JobType -> (JobId -> Run _ Unit) -> ContT Response (Run _) Response forkPipelineJob packageName ref jobType action = do @@ -224,6 +235,17 @@ main = do Console.log $ "Failed to start server: " <> Aff.message error Process.exit 1 Right env -> do + _healthcheck <- Aff.launchAff do + let + loop = do + Affjax.get ResponseFormat.ignore env.vars.resourceEnv.healthchecksUrl >>= case _ of + Left _ -> pure unit + Right { status: StatusCode status } | status /= 200 -> pure unit + Right _ -> do + Aff.delay (Aff.Milliseconds (1000.0 * 60.0 * 5.0)) + loop + loop + _close <- HTTPurple.serve { hostname: "0.0.0.0" , port: 8080 diff --git a/lib/src/API/V1.purs b/lib/src/API/V1.purs index 7c6f05e0..dcf37d12 100644 --- a/lib/src/API/V1.purs +++ b/lib/src/API/V1.purs @@ -29,10 +29,8 @@ data Route | Unpublish | Transfer | Jobs - | Job JobId - { level :: Maybe LogLevel - , since :: Maybe DateTime - } + | Job JobId { level :: Maybe LogLevel, since :: Maybe DateTime } + | Status derive instance Generic Route _ @@ -48,6 +46,7 @@ routes = Routing.root $ Routing.prefix "api" $ Routing.prefix "v1" $ RoutingG.su , since: Routing.optional <<< timestampP <<< Routing.string } ) + , "Status": "status" / RoutingG.noArgs } jobIdS :: RouteDuplex' JobId From 5cd3db6edf3c72283806fecf259ce68c0f9feebf Mon Sep 17 00:00:00 2001 From: Thomas Honeyman Date: Wed, 9 Aug 2023 16:25:40 -0400 Subject: [PATCH 2/3] Add healthcheck url to .env.example --- .env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.example b/.env.example index 9995ede5..924e9b89 100644 --- a/.env.example +++ b/.env.example @@ -23,3 +23,4 @@ GITHUB_API_URL="https://api.github.com" S3_API_URL="https://packages.registry.purescript.org" S3_BUCKET_URL="https://ams3.digitaloceanspaces.com" PURSUIT_API_URL="https://pursuit.purescript.org" +HEALTHCHECKS_URL="https://hc-ping.com/uuid-from-healthchecks" From 8028ad316fbd596ee0aef9361ba040e8a09e4b6f Mon Sep 17 00:00:00 2001 From: Thomas Honeyman Date: Wed, 9 Aug 2023 16:48:38 -0400 Subject: [PATCH 3/3] Include healthchecks url in test environment --- flake.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/flake.nix b/flake.nix index 6abfb94a..e413da82 100644 --- a/flake.nix +++ b/flake.nix @@ -195,7 +195,9 @@ cp spago.yaml spago.lock $WORKDIR cp -a app foreign lib scripts types $WORKDIR ln -s ${pkgs.registry.package-lock}/js/node_modules $WORKDIR/node_modules + pushd $WORKDIR + export HEALTHCHECKS_URL=${defaultEnv.HEALTHCHECKS_URL} ${pkgs.spago-unstable}/bin/spago test popd '';