From 924b21f9f1544412d02c804df253a15d129565bb Mon Sep 17 00:00:00 2001 From: attoyibi-akun utama <43211768+attoyibi@users.noreply.github.com> Date: Tue, 30 Jun 2026 13:21:16 +0000 Subject: [PATCH 1/7] Add CI workflow --- .github/workflows/ci.yml | 45 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..80e6aed --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,45 @@ +name: CI - Build and Test + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build-and-test: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v4 + + - name: Build the Docker image + run: docker build -t tutorial-app:ci . + + - name: Start a PostgreSQL database + run: | + docker run -d --name test-db \ + -e POSTGRES_USER=tutorial_user \ + -e POSTGRES_PASSWORD=tutorial_password \ + -e POSTGRES_DB=tutorial_db \ + postgres:15-alpine + + - name: Run the app container + run: | + docker run -d --name test-app \ + --link test-db:postgres \ + -e DB_HOST=postgres \ + -e DB_USER=tutorial_user \ + -e DB_PASSWORD=tutorial_password \ + -e DB_NAME=tutorial_db \ + -p 8080:8080 \ + tutorial-app:ci + + - name: Wait for the app to start + run: sleep 15 + + - name: Health check (the actual test) + run: | + curl --fail http://localhost:8080/api/tutorials || exit 1 + echo "API is responding correctly!" From ec5e096aea97b1273692a8edd722560c397f1e6e Mon Sep 17 00:00:00 2001 From: attoyibi-akun utama <43211768+attoyibi@users.noreply.github.com> Date: Tue, 30 Jun 2026 13:25:57 +0000 Subject: [PATCH 2/7] all file docker --- Dockerfile | 16 ++++++++++++++++ app/config/db.config.js | 8 ++++---- docker-compose.yml | 29 +++++++++++++++++++++++++++++ 3 files changed, 49 insertions(+), 4 deletions(-) create mode 100644 Dockerfile create mode 100644 docker-compose.yml diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..8877fbc --- /dev/null +++ b/Dockerfile @@ -0,0 +1,16 @@ +FROM node:18-alpine + +WORKDIR /app + +COPY package*.json ./ + +RUN npm install --production + +COPY . . + +ENV NODE_ENV=production +ENV PORT=8080 + +EXPOSE 8080 + +CMD ["node", "server.js"] diff --git a/app/config/db.config.js b/app/config/db.config.js index 64ba9c5..f187962 100644 --- a/app/config/db.config.js +++ b/app/config/db.config.js @@ -1,8 +1,8 @@ module.exports = { - HOST: "localhost", - USER: "postgres", - PASSWORD: "123", - DB: "testdb", + HOST: process.env.DB_HOST || "localhost", + USER: process.env.DB_USER || "postgres", + PASSWORD: process.env.DB_PASSWORD || "123456", + DB: process.env.DB_NAME || "testdb", dialect: "postgres", pool: { max: 5, diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..6d450f1 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,29 @@ + +services: + backend: + build: . + container_name: tutorial-api + ports: + - "8080:8080" + environment: + DB_HOST: postgres + DB_USER: tutorial_user + DB_PASSWORD: tutorial_password + DB_NAME: tutorial_db + DB_PORT: 5432 + depends_on: + - postgres + + postgres: + image: postgres:15-alpine + container_name: tutorial-db + environment: + POSTGRES_USER: tutorial_user + POSTGRES_PASSWORD: tutorial_password + POSTGRES_DB: tutorial_db + volumes: + - postgres_data:/var/lib/postgresql/data + +volumes: + postgres_data: + From 40f7f5c072f884609e7d8e3810e585cf2071f15d Mon Sep 17 00:00:00 2001 From: attoyibi-akun utama <43211768+attoyibi@users.noreply.github.com> Date: Tue, 30 Jun 2026 13:33:01 +0000 Subject: [PATCH 3/7] Add Render blueprint --- render.yaml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 render.yaml diff --git a/render.yaml b/render.yaml new file mode 100644 index 0000000..493391f --- /dev/null +++ b/render.yaml @@ -0,0 +1,31 @@ +services: + - type: web + name: tutorial-api + runtime: docker + dockerfilePath: ./Dockerfile + plan: free + envVars: + - key: DB_HOST + fromDatabase: + name: tutorial-db + property: host + - key: DB_PORT + fromDatabase: + name: tutorial-db + property: port + - key: DB_USER + fromDatabase: + name: tutorial-db + property: user + - key: DB_PASSWORD + fromDatabase: + name: tutorial-db + property: password + - key: DB_NAME + fromDatabase: + name: tutorial-db + property: database + +databases: + - name: tutorial-db + plan: free From 9e2536acaaf8b16f02b96fd73a0941402342b27a Mon Sep 17 00:00:00 2001 From: attoyibi-akun utama <43211768+attoyibi@users.noreply.github.com> Date: Thu, 2 Jul 2026 00:23:55 +0000 Subject: [PATCH 4/7] master branch --- .github/workflows/ci.yml | 4 ++-- .vscode/settings.json | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 .vscode/settings.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80e6aed..ab9a3af 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -2,9 +2,9 @@ name: CI - Build and Test on: push: - branches: [ main ] + branches: [ main, master ] pull_request: - branches: [ main ] + branches: [ main, master ] jobs: build-and-test: diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..6c2ff60 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,5 @@ +{ + "githubPullRequests.ignoredPullRequestBranches": [ + "master" + ] +} \ No newline at end of file From e232138da61d0df0eb8d04dc239494f4fada6a8b Mon Sep 17 00:00:00 2001 From: attoyibi-akun utama <43211768+attoyibi@users.noreply.github.com> Date: Thu, 2 Jul 2026 00:46:26 +0000 Subject: [PATCH 5/7] change ci yaml --- .github/workflows/ci.yml | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab9a3af..182e98c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,45 +1,58 @@ name: CI - Build and Test - + on: push: branches: [ main, master ] pull_request: branches: [ main, master ] - + jobs: build-and-test: runs-on: ubuntu-latest - + steps: - name: Checkout code uses: actions/checkout@v4 - + - name: Build the Docker image run: docker build -t tutorial-app:ci . - + + - name: Create a shared network + run: docker network create test-net + - name: Start a PostgreSQL database run: | - docker run -d --name test-db \ + docker run -d --name test-db --network test-net \ -e POSTGRES_USER=tutorial_user \ -e POSTGRES_PASSWORD=tutorial_password \ -e POSTGRES_DB=tutorial_db \ postgres:15-alpine - + + - name: Wait for the database to be ready + run: | + for i in $(seq 1 30); do + if docker exec test-db pg_isready -U tutorial_user; then + echo "Database is ready!" + break + fi + echo "Waiting for database... ($i)" + sleep 2 + done + - name: Run the app container run: | - docker run -d --name test-app \ - --link test-db:postgres \ - -e DB_HOST=postgres \ + docker run -d --name test-app --network test-net \ + -e DB_HOST=test-db \ -e DB_USER=tutorial_user \ -e DB_PASSWORD=tutorial_password \ -e DB_NAME=tutorial_db \ -p 8080:8080 \ tutorial-app:ci - + - name: Wait for the app to start run: sleep 15 - + - name: Health check (the actual test) run: | curl --fail http://localhost:8080/api/tutorials || exit 1 - echo "API is responding correctly!" + echo "API is responding correctly!" \ No newline at end of file From 4602babde2aaa94ffa0a421c831828526ee9c6bb Mon Sep 17 00:00:00 2001 From: attoyibi-akun utama <43211768+attoyibi@users.noreply.github.com> Date: Thu, 2 Jul 2026 01:14:12 +0000 Subject: [PATCH 6/7] Add GHCR publish step --- .github/workflows/ci.yml | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 182e98c..ee0decf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -6,6 +6,10 @@ on: pull_request: branches: [ main, master ] +permissions: # ADD THIS BLOCK + contents: read # ADD + packages: write # ADD + jobs: build-and-test: runs-on: ubuntu-latest @@ -55,4 +59,25 @@ jobs: - name: Health check (the actual test) run: | curl --fail http://localhost:8080/api/tutorials || exit 1 - echo "API is responding correctly!" \ No newline at end of file + echo "API is responding correctly!" + + # ===== NEW: publish image to GHCR ===== + - name: Log in to GitHub Container Registry + if: github.event_name == 'push' + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set lowercase image name + if: github.event_name == 'push' + run: echo "IMAGE=ghcr.io/${GITHUB_REPOSITORY,,}" >> $GITHUB_ENV + + - name: Push image to GHCR + if: github.event_name == 'push' + run: | + docker tag tutorial-app:ci $IMAGE:latest + docker tag tutorial-app:ci $IMAGE:${{ github.sha }} + docker push $IMAGE:latest + docker push $IMAGE:${{ github.sha }} From 44814caef06d89efb7221616f1e0d4c4a142cd4b Mon Sep 17 00:00:00 2001 From: attoyibi-akun utama <43211768+attoyibi@users.noreply.github.com> Date: Thu, 2 Jul 2026 01:21:50 +0000 Subject: [PATCH 7/7] /health --- app/routes/turorial.routes.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/routes/turorial.routes.js b/app/routes/turorial.routes.js index 674d3aa..fa40fd0 100644 --- a/app/routes/turorial.routes.js +++ b/app/routes/turorial.routes.js @@ -6,6 +6,9 @@ module.exports = app => { // Create a new Tutorial router.post("/", tutorials.create); + // Create a new Tutorial + router.post("/health", tutorials.create); + // Retrieve all Tutorials router.get("/", tutorials.findAll);