Skip to content

Commit 3270f0e

Browse files
committed
refactor: Major refactor to support sync job
1 parent 15d1765 commit 3270f0e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1108
-147
lines changed

.github/workflows/publish-and-deploy.yml

Lines changed: 76 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ on:
1111

1212
jobs:
1313
publish:
14-
name: Publish Docker Image
14+
name: Publish Docker Images
1515
runs-on: ubuntu-latest
1616
environment: ${{ inputs.target_env }}
1717
outputs:
@@ -51,44 +51,104 @@ jobs:
5151
exit 1
5252
fi
5353
54-
- name: Backup existing image
54+
- name: Detect changed paths
55+
id: changes
56+
uses: dorny/paths-filter@v3
57+
# todo: find a way to detect changes within same branch, for now do not push to dev/prod in parallel
58+
with:
59+
filters: |
60+
api:
61+
- 'src/api/**'
62+
jobs:
63+
- 'src/jobs/**'
64+
65+
- name: Backup existing API image
5566
# Pulls the current image using the target tag and backup it with a previous tag if it exists.
67+
if: steps.changes.outputs.api == 'true'
5668
run: |
5769
OWNER="${{ github.repository_owner }}"
58-
BASE="${{ github.event.repository.name }}"
70+
BASE="${{ github.event.repository.name }}-api"
5971
IMAGE="ghcr.io/$OWNER/$BASE:${{ steps.vars.outputs.TARGET_TAG }}"
6072
BACKUP="ghcr.io/$OWNER/$BASE:${{ steps.vars.outputs.BACKUP_TAG }}"
61-
echo "Backing up image if it exists: $IMAGE → $BACKUP"
73+
echo "Backing up API image if it exists: $IMAGE → $BACKUP"
6274
if docker pull "$IMAGE"; then
6375
docker tag "$IMAGE" "$BACKUP"
6476
docker push "$BACKUP"
6577
else
66-
echo "No image to back up."
78+
echo "No API image to back up."
6779
fi
6880
69-
- name: Cleanup Old Image Digests
70-
# Cleans up old images
81+
- name: Backup existing Jobs image
82+
# Pulls the current image using the target tag and backup it with a previous tag if it exists.
83+
if: steps.changes.outputs.jobs == 'true'
84+
run: |
85+
OWNER="${{ github.repository_owner }}"
86+
BASE="${{ github.event.repository.name }}-jobs"
87+
IMAGE="ghcr.io/$OWNER/$BASE:${{ steps.vars.outputs.TARGET_TAG }}"
88+
BACKUP="ghcr.io/$OWNER/$BASE:${{ steps.vars.outputs.BACKUP_TAG }}"
89+
echo "Backing up Jobs image if it exists: $IMAGE → $BACKUP"
90+
if docker pull "$IMAGE"; then
91+
docker tag "$IMAGE" "$BACKUP"
92+
docker push "$BACKUP"
93+
else
94+
echo "No Jobs image to back up."
95+
fi
96+
97+
- name: Cleanup Old API Image Digests
98+
# Cleans up old api images
99+
if: steps.changes.outputs.api == 'true'
100+
uses: actions/delete-package-versions@v5
101+
continue-on-error: true
102+
with:
103+
package-name: ${{ github.event.repository.name }}-api
104+
package-type: container
105+
owner: ${{ github.repository_owner }}
106+
ignore-versions: "^(prod-latest|prod-previous|dev-latest|dev-previous)$" # keeps important tags (latest and previous)
107+
token: ${{ secrets.MACHINE_PAT }}
108+
109+
- name: Cleanup Old Jobs Image Digests
110+
# Cleans up old jobs images
111+
if: steps.changes.outputs.jobs == 'true'
71112
uses: actions/delete-package-versions@v5
72113
continue-on-error: true
73114
with:
74-
package-name: ${{ github.event.repository.name }}
115+
package-name: ${{ github.event.repository.name }}-jobs
75116
package-type: container
76117
owner: ${{ github.repository_owner }}
77-
min-versions-to-keep: 2 # Keeps the 2 most recent versions (latest and previous)
118+
ignore-versions: "^(prod-latest|prod-previous|dev-latest|dev-previous)$" # keeps important tags (latest and previous)
78119
token: ${{ secrets.MACHINE_PAT }}
79120

80-
- name: Build & push image
121+
- name: Build & push API image
122+
# Builds a new Docker image with the target tag and pushes it to GHCR.
123+
if: steps.changes.outputs.api == 'true'
124+
run: |
125+
OWNER=${{ github.repository_owner }}
126+
BASE=${{ github.event.repository.name }}-api
127+
TAG=${{ steps.vars.outputs.TARGET_TAG }}
128+
IMAGE=ghcr.io/$OWNER/$BASE:$TAG
129+
130+
echo "Building image with tag $IMAGE"
131+
132+
docker build \
133+
--file docker/api/Dockerfile \
134+
--tag $IMAGE \
135+
.
136+
137+
docker push $IMAGE
138+
139+
- name: Build & push Jobs image
81140
# Builds a new Docker image with the target tag and pushes it to GHCR.
141+
if: steps.changes.outputs.jobs == 'true'
82142
run: |
83143
OWNER=${{ github.repository_owner }}
84-
BASE=${{ github.event.repository.name }}
144+
BASE=${{ github.event.repository.name }}-jobs
85145
TAG=${{ steps.vars.outputs.TARGET_TAG }}
86146
IMAGE=ghcr.io/$OWNER/$BASE:$TAG
87147
88148
echo "Building image with tag $IMAGE"
89149
90150
docker build \
91-
--file docker/Dockerfile \
151+
--file docker/jobs/Dockerfile \
92152
--tag $IMAGE \
93153
.
94154
@@ -146,15 +206,17 @@ jobs:
146206
# Deploys to VPS.
147207
run: |
148208
OWNER="${{ vars.GHCR_OWNER }}"
149-
APPLICATION_IMAGE="ghcr.io/$OWNER/${{ github.event.repository.name }}:${{ needs.publish.outputs.target_tag }}"
209+
APPLICATION_API_IMAGE="ghcr.io/$OWNER/${{ github.event.repository.name }}-api:${{ needs.publish.outputs.target_tag }}"
210+
APPLICATION_JOBS_IMAGE="ghcr.io/$OWNER/${{ github.event.repository.name }}-jobs:${{ needs.publish.outputs.target_tag }}"
150211
echo "Deploying to VPS..."
151212
ssh -o StrictHostKeyChecking=no ${{ secrets.DEPLOYMENT_SSH_USER }}@${{ secrets.DEPLOYMENT_SERVER }} "\
152213
153214
# exports general variables
154215
export PROJECT_NAME='${{ vars.PROJECT_NAME }}' && \
155216
export GHCR_USER='${{ secrets.MACHINE_USER }}' && \
156217
export GHCR_PAT='${{ secrets.MACHINE_PAT }}' && \
157-
export APPLICATION_IMAGE='$APPLICATION_IMAGE' && \
218+
export APPLICATION_API_IMAGE='$APPLICATION_API_IMAGE' && \
219+
export APPLICATION_JOBS_IMAGE='$APPLICATION_JOBS_IMAGE' && \
158220
159221
# applies only to production for logging
160222
export HONEYCOMB_API_KEY='${{ secrets.HONEYCOMB_API_KEY }}' && \

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ React ChatBotify RAG API offers the following features:
5454
**API Documentation:**
5555
- `/api/v1/docs`: Interactive Swagger UI for exploring and testing all API endpoints.
5656

57+
**API Key Capabilities:**
58+
- `RAG_MANAGEMENT_API_KEY`: Can perform both management operations (creating, updating, deleting documents) and query operations.
59+
- `RAG_QUERY_API_KEY`: Can perform query operations only (generating content or streaming content generation). It cannot be used for management operations.
60+
5761
### Technologies
5862
Technologies used by React ChatBotify RAG API are as below:
5963

config/env/.env.template

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,10 @@ MONGO_INITDB_PORT=27017
4141

4242
# OpenTelemetry Configuration
4343
OTEL_SERVICE_NAME=otel-collector
44-
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
44+
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4317
45+
46+
# GitHub Configuration
47+
GITHUB_REPO_OWNER=react-chatbotify
48+
GITHUB_REPO_NAME=core-library-documentation
49+
GITHUB_DOCS_PATH='docs'
50+
GITHUB_TOKEN=GITHUB_TOKEN; # optional, unlikely needed
File renamed without changes.

docker/Dockerfile.local renamed to docker/api/Dockerfile.local

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ COPY ./package.json ./
1414
RUN npm install
1515

1616
# Copy additional files needed for runtime
17-
COPY ./nodemon.json ./
17+
COPY ./nodemon-api.json ./
1818

1919
# Command to run the application with nodemon for development
20-
CMD ["npm", "run", "start:watch"]
20+
CMD ["npm", "run", "start:watch-api"]

docker/docker-compose.dev.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# The development environment runs the live application on the development server.
22
services:
33
api:
4-
image: ${APPLICATION_IMAGE}
4+
image: ${APPLICATION_API_IMAGE}
55
environment:
66
- NODE_ENV=development
7+
8+
jobs:
9+
image: ${APPLICATION_JOBS_IMAGE}

docker/docker-compose.override.yml

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,20 @@ services:
22
api:
33
build:
44
context: ..
5-
dockerfile: ./docker/Dockerfile.local
6-
command: npm run start:watch
5+
dockerfile: ./docker/api/Dockerfile.local
6+
command: npm run start:watch-api
7+
volumes:
8+
- ..:/app
9+
- /app/node_modules
10+
11+
jobs:
12+
# build for local dev
13+
build:
14+
context: ..
15+
dockerfile: ./docker/jobs/Dockerfile.local
16+
# for hot reloading in local dev
17+
command: npm run start:watch-jobs
18+
# codebase mounted for local dev
719
volumes:
820
- ..:/app
921
- /app/node_modules

docker/docker-compose.prod.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
# The development environment runs the live application on the development server.
22
services:
33
api:
4-
image: ${APPLICATION_IMAGE}
4+
image: ${APPLICATION_API_IMAGE}
55
environment:
66
- NODE_ENV=production
77

8+
jobs:
9+
image: ${APPLICATION_JOBS_IMAGE}
10+
811
# add logging in production environment
912
otel-collector:
1013
image: otel/opentelemetry-collector:latest

docker/docker-compose.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
services:
22
api:
3-
container_name: rag-api
3+
container_name: rag-api-core
44
environment:
55
- NODE_ENV=local
66
ports:
@@ -12,6 +12,16 @@ services:
1212
networks:
1313
- core-network
1414

15+
# runs scheduled jobs on the platform
16+
jobs:
17+
container_name: rag-api-jobs
18+
env_file:
19+
- ../config/env/.env
20+
depends_on:
21+
- api
22+
networks:
23+
- core-network
24+
1525
chromadb:
1626
container_name: rag-chromadb
1727
image: chromadb/chroma

docker/jobs/Dockerfile

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Stage 1: Install dependencies
2+
FROM node:24-slim AS dependencies
3+
4+
# Maintainer information
5+
LABEL org.opencontainers.image.authors="Tan Jin (tjtanjin)"
6+
7+
# Set the working directory
8+
WORKDIR /app
9+
10+
# Copy package.json to the container
11+
COPY ./package.json ./
12+
13+
# Install the dependencies
14+
RUN npm install
15+
16+
# Stage 2: Build the application
17+
FROM node:24-slim AS build
18+
19+
# Set the working directory
20+
WORKDIR /app
21+
22+
# Copy installed dependencies from the previous stage
23+
COPY --from=dependencies /app/node_modules ./node_modules
24+
25+
# Copy specific necessary files and directories
26+
COPY ./src ./src
27+
COPY ./types ./types
28+
COPY ./config ./config
29+
COPY ./tsconfig.json ./
30+
COPY ./package.json ./
31+
32+
# Build application code
33+
RUN npm run build
34+
35+
# Stage 3: Create the final image
36+
FROM node:24-slim
37+
38+
# Set the working directory inside the container
39+
WORKDIR /app
40+
41+
# Copy built application code from the build stage
42+
COPY --from=build /app/build ./build
43+
44+
# Copy node_modules directory from the build stage
45+
COPY --from=build /app/node_modules ./node_modules
46+
47+
# Copy additional files needed for runtime
48+
COPY package.json ./
49+
50+
# Start the application
51+
CMD ["node", "./build/jobs/index.js"]

docker/jobs/Dockerfile.local

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# For development purposes, the dev docker file simply mounts the codebase with hot-reloading
2+
FROM node:24-slim
3+
4+
# Maintainer information
5+
LABEL org.opencontainers.image.authors="Tan Jin (tjtanjin)"
6+
7+
# Set the working directory
8+
WORKDIR /app
9+
10+
# Copy package.json to the container
11+
COPY ./package.json ./
12+
13+
# Install the application dependencies
14+
RUN npm install
15+
16+
# Copy additional files needed for runtime
17+
COPY nodemon-jobs.json ./
18+
19+
# Command to run the application with nodemon for development
20+
CMD ["npm", "run", "start:watch-jobs"]

nodemon-api.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"watch": [
3+
"src",
4+
"types",
5+
"config"
6+
],
7+
"ext": "ts,js,json",
8+
"ignore": [
9+
"node_modules"
10+
],
11+
"exec": "ts-node --transpile-only ./src/api/index.ts"
12+
}

nodemon.json renamed to nodemon-jobs.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,5 @@
88
"ignore": [
99
"node_modules"
1010
],
11-
"exec": "ts-node --transpile-only ./src/index.ts"
11+
"exec": "ts-node ./src/jobs/index.ts"
1212
}

0 commit comments

Comments
 (0)