Skip to content

Commit

Permalink
ci: add healthcheck (#119)
Browse files Browse the repository at this point in the history
* feat(api): add `/healthz` endpoint

* feat(web): add `/healthz` endpoint

* ci: add healthcheck to containers

* chore(release): bump versions

 - [email protected]
 - [email protected]
  • Loading branch information
lharti authored Nov 16, 2024
1 parent e5ddd7b commit f90b730
Show file tree
Hide file tree
Showing 19 changed files with 318 additions and 19 deletions.
11 changes: 11 additions & 0 deletions apps/jsonthing-api/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [0.4.0](https://github.com/lharti/jsonthing/compare/[email protected]@0.4.0) (2024-11-16)


### Features

* **api:** add `/healthz` endpoint ([217927e](https://github.com/lharti/jsonthing/commit/217927e4910e9696fcbd816d6cd483687128dcec))





# [0.3.0](https://github.com/lharti/jsonthing/compare/[email protected]@0.3.0) (2024-11-12)


Expand Down
1 change: 1 addition & 0 deletions apps/jsonthing-api/cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"dictionaries": [],
"words": [
"dtos",
"Healthz",
"jsonthing",
"mockingoose",
"nestjs",
Expand Down
3 changes: 2 additions & 1 deletion apps/jsonthing-api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsonthing-api",
"version": "0.3.0",
"version": "0.4.0",
"description": "",
"author": "",
"private": true,
Expand Down Expand Up @@ -35,6 +35,7 @@
"@nestjs/core": "^10.4.6",
"@nestjs/mongoose": "^10.1.0",
"@nestjs/platform-express": "^10.4.6",
"@nestjs/terminus": "^10.2.3",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.1",
"joi": "^17.13.3",
Expand Down
9 changes: 9 additions & 0 deletions apps/jsonthing-api/src/app.module.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { AppModule } from '@/app.module'
import { DatabaseModule } from '@/database.module'
import { DocsModule } from '@/routes/docs'
import { HealthzModule } from '@/routes/healthz'
import { ConfigModule } from '@nestjs/config'
import { Test, TestingModule } from '@nestjs/testing'

Expand Down Expand Up @@ -68,4 +69,12 @@ describe('appModule', () => {

expect(docsModule).toBeInstanceOf(DocsModule)
})

it('should import HealthzModule', () => {
expect.assertions(1)

const healthzModule = appModule.get(HealthzModule)

expect(healthzModule).toBeInstanceOf(HealthzModule)
})
})
3 changes: 2 additions & 1 deletion apps/jsonthing-api/src/app.module.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { appConfigValidationSchema } from '@/config/app.config'
import { DatabaseModule } from '@/database.module'
import { DocsModule } from '@/routes/docs'
import { HealthzModule } from '@/routes/healthz'
import { Module } from '@nestjs/common'
import { ConfigModule } from '@nestjs/config'

@Module({
imports: [
ConfigModule.forRoot({
Expand All @@ -17,6 +17,7 @@ import { ConfigModule } from '@nestjs/config'

// API ROUTES
DocsModule,
HealthzModule,
],
})
export class AppModule {}
62 changes: 62 additions & 0 deletions apps/jsonthing-api/src/routes/healthz/healthz.controller.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import {
HealthCheckService,
MongooseHealthIndicator,
} from '@nestjs/terminus'
import { Test, TestingModule } from '@nestjs/testing'
import { HealthzController } from './healthz.controller'

describe('healthzController', () => {
let testModule: TestingModule
let controller: HealthzController

beforeAll(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [HealthzController],
providers: [
{
provide: HealthCheckService,

useValue: {
check: jest.fn(checksFuncs =>
checksFuncs[0](),
),
},
},

{
provide: MongooseHealthIndicator,

useValue: {
pingCheck: jest.fn(key =>
Promise.resolve({
[key]: { status: 'up' },
}),
),
},
},
],
}).compile()

controller = module.get<HealthzController>(HealthzController)

testModule = module
})

afterAll(async () => {
await testModule.close()
})

it('should call health check service with mongoose ping check', async () => {
expect.assertions(1)

const checkResult = await controller.check()

expect(checkResult).toMatchInlineSnapshot(`
{
"mongoose": {
"status": "up",
},
}
`)
})
})
22 changes: 22 additions & 0 deletions apps/jsonthing-api/src/routes/healthz/healthz.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { Controller, Get } from '@nestjs/common'
import {
HealthCheck,
HealthCheckService,
MongooseHealthIndicator,
} from '@nestjs/terminus'

@Controller('healthz')
export class HealthzController {
constructor(
private readonly health: HealthCheckService,
private readonly mongoose: MongooseHealthIndicator,
) {}

@Get()
@HealthCheck()
check() {
return this.health.check([
() => this.mongoose.pingCheck('mongoose'),
])
}
}
34 changes: 34 additions & 0 deletions apps/jsonthing-api/src/routes/healthz/healthz.module.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { TerminusModule } from '@nestjs/terminus'
import { Test, TestingModule } from '@nestjs/testing'
import { HealthzController } from './healthz.controller'
import { HealthzModule } from './healthz.module'

describe('healthzModule', () => {
let module: TestingModule

beforeAll(async () => {
module = await Test.createTestingModule({
imports: [HealthzModule],
}).compile()
})

afterAll(async () => {
await module.close()
})

it('should import TerminusModule', () => {
expect.assertions(1)

const terminusModule = module.get(TerminusModule)

expect(terminusModule).toBeDefined()
})

it('should have HealthzController', () => {
expect.assertions(1)

const healthzController = module.get(HealthzController)

expect(healthzController).toBeDefined()
})
})
9 changes: 9 additions & 0 deletions apps/jsonthing-api/src/routes/healthz/healthz.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { Module } from '@nestjs/common'
import { TerminusModule } from '@nestjs/terminus'
import { HealthzController } from './healthz.controller'

@Module({
imports: [TerminusModule],
controllers: [HealthzController],
})
export class HealthzModule {}
1 change: 1 addition & 0 deletions apps/jsonthing-api/src/routes/healthz/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './healthz.module'
11 changes: 11 additions & 0 deletions apps/jsonthing-web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,17 @@
All notable changes to this project will be documented in this file.
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.

# [0.6.0](https://github.com/lharti/jsonthing/compare/[email protected]@0.6.0) (2024-11-16)


### Features

* **web:** add `/healthz` endpoint ([16dbded](https://github.com/lharti/jsonthing/commit/16dbdedeebd1e79dd64566e8cfd2ec6f44651ea7))





## [0.5.8](https://github.com/lharti/jsonthing/compare/[email protected]@0.5.8) (2024-11-14)


Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
import { NextConfig } from 'next'

const nextConfig: NextConfig = {
output: 'standalone',
reactStrictMode: true,

Expand Down
2 changes: 1 addition & 1 deletion apps/jsonthing-web/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "jsonthing-web",
"version": "0.5.8",
"version": "0.6.0",
"private": true,
"scripts": {
"dev": "next dev --turbo",
Expand Down
3 changes: 3 additions & 0 deletions apps/jsonthing-web/src/app/healthz/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function GET() {
return Response.json({ status: 'ok' })
}
1 change: 1 addition & 0 deletions apps/jsonthing-web/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
},
"include": [
"next-env.d.ts",
"next.config.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
Expand Down
8 changes: 7 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,13 @@
"ignorePaths": [],
"dictionaryDefinitions": [],
"dictionaries": [],
"words": ["jsonthing"],
"words": [
"healthcheck",
"Healthz",
"INITDB",
"jsonthing",
"lharti"
],
"ignoreWords": [],
"import": []
}
10 changes: 9 additions & 1 deletion docker/stack/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ http {
}

server {
listen 80;
listen 80 default_server;
server_name jsonthing.com www.jsonthing.com;

location / {
Expand All @@ -27,6 +27,14 @@ http {
proxy_read_timeout 90;
proxy_connect_timeout 90;
}

location /healthz {
access_log off;

return 200 '{"status": "OK"}';

add_header Content-Type application/json;
}
}

server {
Expand Down
37 changes: 25 additions & 12 deletions docker/stack/stack.compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,38 +16,46 @@ x-base-deploy-config: &base-deploy-config

services:
webapp:
image: lharti/jsonthing-web:tmp
restart: always
image: lharti/jsonthing-web:0.5.8
networks:
- private
environment:
- PORT=3000
- INT_API_URL=http://api:5000
depends_on:
- mongo
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/healthz"]
interval: 10s
timeout: 5s
retries: 3
deploy:
<<: *base-deploy-config

api:
image: lharti/jsonthing-api
restart: always
networks:
- private
environment:
- PORT=5000
- DB_NAME=jsonthing
env_file:
- .env
- DB_URI=${DB_URI}
depends_on:
- mongo
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:5000/healthz"]
interval: 10s
timeout: 5s
retries: 3
deploy:
<<: *base-deploy-config

mongo:
image: mongo:latest
restart: always
env_file:
- .env
environment:
- MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME}
- MONGO_INITDB_ROOT_PASSWORD=${MONGO_INITDB_ROOT_PASSWORD}
- MONGO_INITDB_DATABASE=${MONGO_INITDB_DATABASE}
networks:
- private
volumes:
Expand All @@ -67,24 +75,29 @@ services:

nginx:
image: nginx:latest
restart: always
networks:
- public
- private
ports:
- "80:80"
configs:
- source: nginx.conf
- source: nginx
target: /etc/nginx/nginx.conf
depends_on:
- webapp
- api

healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/healthz"]
interval: 10s
timeout: 5s
retries: 3
deploy:
<<: *base-deploy-config

configs:
nginx.conf:
file: ./nginx.conf
nginx:
external: true

volumes:
mongo-data:
Expand Down
Loading

0 comments on commit f90b730

Please sign in to comment.