Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 41 additions & 5 deletions .github/workflows/dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
- main

jobs:
# 1️⃣ Build & tests
build-and-test:
runs-on: ubuntu-latest

Expand Down Expand Up @@ -43,8 +42,48 @@
- name: Build app
run: pnpm build

# 2️⃣ Build & push Docker image
sonar-scan:
needs: build-and-test
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Setup pnpm
uses: pnpm/action-setup@v3
with:
version: 9

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'pnpm'

- name: Install dependencies
run: pnpm install --frozen-lockfile

- name: Generate Prisma Client
run: pnpm prisma generate

- name: Tests (with coverage report)
run: pnpm exec jest --runInBand --coverage --coverage-reporters=lcov --passWithNoTests

- name: SonarQube Scan
uses: SonarSource/sonarqube-scan-action@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
SONAR_HOST_URL: ${{ secrets.SONAR_HOST_URL }}
with:
args: >
-Dsonar.projectKey=WPT
-Dsonar.javascript.lcov.reportPaths=./coverage/lcov.info

docker-build-push:

Check warning

Code scanning / CodeQL

Workflow does not contain permissions Medium

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN. Consider setting an explicit permissions block, using the following as a minimal starting point: {contents: read}
runs-on: ubuntu-latest
needs: build-and-test
permissions:
Expand Down Expand Up @@ -85,7 +124,6 @@
build-args: |
NEXT_PUBLIC_ENV=develop

# 3️⃣ Deploy DEV
deploy-dev:
runs-on: self-hosted
needs: docker-build-push
Expand All @@ -109,8 +147,6 @@
echo "🔧 Deploying on DEV..."
cd /home/baptiste/Dev/WPT/dev
docker-compose pull
# stop + remove DEV containers ONLY (keeps volumes)
docker-compose down
# recreate containers, reusing existing volumes
docker-compose up -d --remove-orphans
echo "🚀 Deployed in DEV!"
3 changes: 0 additions & 3 deletions .github/workflows/prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ on:
- 'v*.*.*'

jobs:
# 1️⃣ Build & tests
build-and-test:
runs-on: ubuntu-latest

Expand Down Expand Up @@ -37,7 +36,6 @@ jobs:
- name: Build app
run: pnpm build

# 2️⃣ Build & push Docker image
docker-build-push:
runs-on: ubuntu-latest
needs: build-and-test
Expand Down Expand Up @@ -81,7 +79,6 @@ jobs:
build-args: |
NEXT_PUBLIC_ENV=production

# 3️⃣ Deploy PROD
deploy-prod:
runs-on: self-hosted
needs: docker-build-push
Expand Down
197 changes: 197 additions & 0 deletions JulienPolycarpe-CICD.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,197 @@
# CICD

## CodeQL

Added an automatic pipeline for CodeQL analysis on every push and merge-request to any branch.

## Dev
[Pipeline for dev (.github/workflows/dev.yml)](./.github/workflows/dev.yml)

On merge-request or push to `dev` and `main` branch:
- Build the application
- Run tests on the most important features [See tests (tests)](./tests)
- Run code quality checks on a private sonarqube server
- Build image using the Dockerfile and push Docker image to registry
- Deploy to staging environment on private server

Test account for sonarqube:
- link: https://sonarqube.baptiiiste.com/dashboard?id=WPT&codeScope=overall
- user: user
- password: MySuperUser1234@

Docker compose on my server:
```yml
version: '3.8'
services:
wpt-dev_postgres:
image: postgres:16
container_name: wpt-dev_postgres
restart: always
environment:
POSTGRES_USER: $POSTGRES_USER
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
POSTGRES_DB: $POSTGRES_DB
volumes:
- wpt-dev_data:/var/lib/postgresql/data
networks:
- web
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s

wpt-dev_website:
image: ghcr.io/baptiiiiste/webhookpersistenttester:dev-latest
container_name: wpt-dev_website
restart: always
environment:
NODE_ENV: production
NEXTAUTH_URL: https://wpt-dev.baptiiiste.com
API_URL: https://wpt-dev.baptiiiste.com/api
NEXTAUTH_SECRET: $NEXTAUTH_SECRET
SALT_ROUNDS: "10"
AUTH_TRUST_HOST: "true"
GOOGLE_CLIENT_ID: $GOOGLE_CLIENT_ID
GOOGLE_CLIENT_SECRET: $GOOGLE_CLIENT_SECRET
DATABASE_URL: postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@wpt-dev_postgres:5432/$POSTGRES_db
networks:
- web
depends_on:
wpt-dev_postgres:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.wpt-dev-ws.rule=Host(`wpt-dev.baptiiiste.com`)"
- "traefik.http.routers.wpt-dev-ws.entrypoints=websecure"
- "traefik.http.routers.wpt-dev-ws.tls.certresolver=letsencrypt"
- "traefik.http.services.wpt-dev-ws.loadbalancer.server.port=3000"

adminer:
image: adminer
container_name: wpt-dev_adminer
restart: always
depends_on:
- wpt-dev_postgres
networks:
- web
environment:
ADMINER_DEFAULT_SERVER: wpt-dev_postgres
labels:
- "traefik.enable=true"
- "traefik.http.routers.wpt-dev-adminer.rule=Host(`adminer-wpt-dev.baptiiiste.com`)"
- "traefik.http.routers.wpt-dev-adminer.entrypoints=websecure"
- "traefik.http.routers.wpt-dev-adminer.tls.certresolver=letsencrypt"
- "traefik.http.services.wpt-dev-adminer.loadbalancer.server.port=8080"

networks:
web:
external: true
volumes:
wpt-dev_data:
```

What is deployed here on my server:
- PostgreSQL database container
- Next.js application container
- Adminer container for database management

Access the application here:
- link: https://wpt-dev.baptiiiste.com
- user: [email protected]
- password: Test@1234

## Prod
[Pipeline for prod (.github/workflows/prod.yml)](./.github/workflows/prod.yml)

On create tag `v*.*.*`:
- Build the application
- Run tests on the most important features [See tests (./tests)](tests)
- Build image using the Dockerfile and push Docker image to registry
- Deploy to production environment on private server

Docker compose on my server:
```yml
version: '3.8'
services:
wpt_postgres:
image: postgres:16
container_name: wpt_postgres
restart: always
environment:
POSTGRES_USER: $POSTGRES_USER
POSTGRES_PASSWORD: $POSTGRES_PASSWORD
POSTGRES_DB: $POSTGRES_DB
volumes:
- wpt_data:/var/lib/postgresql/data
networks:
- web
ports:
- "5433:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 5
start_period: 30s

wpt_website:
image: ghcr.io/baptiiiiste/webhookpersistenttester:latest
container_name: wpt_website
restart: always
environment:
NODE_ENV: production
NEXTAUTH_URL: https://wpt.baptiiiste.com
API_URL: https://wpt.baptiiiste.com/api
NEXTAUTH_SECRET: $NEXTAUTH_SECRET
SALT_ROUNDS: "10"
AUTH_TRUST_HOST: "true"
GOOGLE_CLIENT_ID: $GOOGLE_CLIENT_ID
GOOGLE_CLIENT_SECRET: $GOOGLE_CLIENT_SECRET
DATABASE_URL: postgresql://$POSTGRES_USER:$POSTGRES_PASSWORD@wpt_postgres:5432/$POSTGRES_db
networks:
- web
ports:
- "3001:3000"
depends_on:
wpt_postgres:
condition: service_healthy
labels:
- "traefik.enable=true"
- "traefik.http.routers.wpt-ws.rule=Host(`wpt.baptiiiste.com`)"
- "traefik.http.routers.wpt-ws.entrypoints=websecure"
- "traefik.http.routers.wpt-ws.tls.certresolver=letsencrypt"
- "traefik.http.services.wpt-ws.loadbalancer.server.port=3000"

networks:
web:
external: true
volumes:
wpt_data:
```

What is deployed here on my server:
- PostgreSQL database container
- Next.js application container

Access the application here:
- link: https://wpt-dev.baptiiiste.com
- create your own account to test, with not sensitive information

## Deployment on Private Server

- Setup Github runners on private server
- Created a `docker-compose.yml` file for each environment (staging and production)
- Used the runner to pull the latest Docker image and restart the container

Server architecture:
- Ubuntu server
- Portainer for container management
- Traefik as reverse proxy (application are using the `web` network that is linked to my domain)
- Docker and Docker Compose for containerization
- Let's Encrypt for SSL certificates


1 change: 1 addition & 0 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- Handle stripe integration
- Handle billing page
- Handle plan selection
- Fix missing translations (Sidebar, disconnect button)

# Future features
- Auto deletion of requests after a certain period of time
Expand Down
4 changes: 2 additions & 2 deletions lib/i18n/routing.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defineRouting } from 'next-intl/routing'

export const routing = defineRouting({
locales: ['fr'],
defaultLocale: 'fr',
locales: ['fr', 'en'],
defaultLocale: 'en',
localePrefix: 'always',
})
Loading
Loading