Skip to content

Commit 3a4b054

Browse files
committed
merge develop in
2 parents 828ade6 + ce26e5d commit 3a4b054

382 files changed

Lines changed: 36848 additions & 5734 deletions

File tree

Some content is hidden

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

.prettierignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
# production
1919
/build
20+
/src/*/dist
2021

2122
# misc
2223
.DS_Store

devContainerization/Dockerfile.backend.dev

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
FROM node:20-alpine
2-
WORKDIR /base
1+
FROM node:20
32

43
COPY package.json tsconfig.build.json ./
54
COPY ./src/backend/package.json ./src/backend/tsconfig.json src/backend/
@@ -15,4 +14,4 @@ COPY ./src/shared src/shared
1514
RUN yarn prisma:generate
1615

1716
EXPOSE 3001
18-
CMD [ "sh", "-c", "cd src/backend; npx prisma migrate reset --force & yarn workspace backend dev" ]
17+
CMD [ "sh", "-c", "yarn workspace backend dev" ]

devContainerization/Dockerfile.frontend.dev

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
FROM node:20-alpine
2-
WORKDIR /base
32

43
COPY package.json tsconfig.build.json ./
54
COPY ./src/frontend/package.json ./src/frontend/tsconfig.json src/frontend/

devContainerization/docker-compose.dev.yml

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name: finishline-development
22
services:
33
database:
4-
container_name: database
4+
container_name: database-dev
55
image: postgres
66
environment:
77
POSTGRES_USER: postgres
@@ -11,34 +11,41 @@ services:
1111
- '5432:5432'
1212
volumes:
1313
- pgdata:/var/lib/postgresql/data
14+
healthcheck:
15+
test: ['CMD-SHELL', 'pg_isready -U postgres -d finishline_database']
16+
interval: 5s
17+
timeout: 5s
18+
retries: 5
19+
start_period: 30s
1420

1521
backend:
16-
container_name: backend
22+
container_name: backend-dev
1723
build:
1824
context: ../
1925
dockerfile: devContainerization/Dockerfile.backend.dev
2026
ports:
2127
- '3001:3001'
2228
volumes:
23-
- ../src/backend:/base/src/backend
24-
- ../src/shared:/base/src/shared
29+
- ../src/backend:/src/backend
30+
- ../src/shared:/src/shared
2531
depends_on:
26-
- database
32+
database:
33+
condition: service_healthy
2734
env_file:
2835
- ../src/backend/.env
2936
environment:
3037
DATABASE_URL: 'postgresql://postgres:docker@database:5432/finishline_database'
3138

3239
frontend:
33-
container_name: frontend
40+
container_name: frontend-dev
3441
build:
3542
context: ../
3643
dockerfile: devContainerization/Dockerfile.frontend.dev
3744
ports:
3845
- '3000:3000'
3946
volumes:
40-
- ../src/frontend:/base/src/frontend
41-
- ../src/shared:/base/src/shared
47+
- ../src/frontend:/src/frontend
48+
- ../src/shared:/src/shared
4249
depends_on:
4350
- backend
4451

Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
const { exec, spawn } = require('child_process');
2+
const { promisify } = require('util');
3+
4+
const execAsync = promisify(exec);
5+
const COMPOSE_FILE = 'docker-compose.dev.yml';
6+
7+
async function getContainerStatus() {
8+
try {
9+
//get all containers from the compose file (running and stopped)
10+
const { stdout } = await execAsync(`docker compose -f ${COMPOSE_FILE} ps -a -q`);
11+
const containerIds = stdout
12+
.trim()
13+
.split('\n')
14+
.filter((id) => id);
15+
16+
if (containerIds.length === 0) {
17+
return { status: 'not_created', running: 0, total: 0 };
18+
}
19+
20+
//check which ones are running
21+
const runningCheck = await execAsync(`echo "${containerIds.join('\n')}" | xargs docker inspect -f '{{.State.Running}}'`);
22+
const runningStatuses = runningCheck.stdout.trim().split('\n');
23+
const runningCount = runningStatuses.filter((status) => status === 'true').length;
24+
25+
return {
26+
status: runningCount === 3 ? 'all_running' : 'some_stopped',
27+
running: runningCount,
28+
total: containerIds.length
29+
};
30+
} catch (error) {
31+
return { status: 'not_created', running: 0, total: 0 };
32+
}
33+
}
34+
35+
function runCommand(command, options = {}) {
36+
return new Promise((resolve, reject) => {
37+
const child = spawn('sh', ['-c', command], {
38+
stdio: 'inherit',
39+
...options
40+
});
41+
42+
child.on('close', (code) => {
43+
if (code === 0) resolve();
44+
else reject(new Error(`Command failed with code ${code}`));
45+
});
46+
47+
child.on('error', reject);
48+
});
49+
}
50+
51+
async function waitForBackendReady() {
52+
console.log('Waiting for backend container to be ready...');
53+
let attempts = 0;
54+
const maxAttempts = 30; //wait up to 30 seconds
55+
56+
while (attempts < maxAttempts) {
57+
try {
58+
await execAsync(`docker compose -f ${COMPOSE_FILE} exec -T backend echo "ready"`);
59+
console.log('Backend container is ready.');
60+
return;
61+
} catch (error) {
62+
attempts++;
63+
console.log(`Waiting for backend... (${attempts}/${maxAttempts})`);
64+
await new Promise((resolve) => setTimeout(resolve, 1000));
65+
}
66+
}
67+
68+
throw new Error('Backend container failed to become ready within 30 seconds');
69+
}
70+
71+
async function runMigrations() {
72+
console.log('Running database migrations and seed...');
73+
try {
74+
await runCommand(
75+
`docker compose -f ${COMPOSE_FILE} exec -T backend sh -c "cd /src/backend && npx prisma migrate reset --force"`
76+
);
77+
console.log('Database migrations and seeding completed successfully.');
78+
} catch (error) {
79+
console.error('Failed to run migrations:', error.message);
80+
throw error;
81+
}
82+
}
83+
84+
async function main() {
85+
console.log('Checking container status...');
86+
87+
const containerStatus = await getContainerStatus();
88+
89+
switch (containerStatus.status) {
90+
case 'all_running':
91+
console.log('All 3 containers are running. Following logs...');
92+
await runCommand(`docker compose -f ${COMPOSE_FILE} logs --follow`);
93+
break;
94+
95+
case 'some_stopped':
96+
console.log(
97+
`Found ${containerStatus.running}/${containerStatus.total} containers running. Starting all containers...`
98+
);
99+
await runCommand(`docker compose -f ${COMPOSE_FILE} up -d`);
100+
console.log('Containers started. Following logs...');
101+
await runCommand(`docker compose -f ${COMPOSE_FILE} logs --follow`);
102+
break;
103+
104+
case 'not_created':
105+
console.log('Containers not found. Building and starting...');
106+
await runCommand(`docker compose -f ${COMPOSE_FILE} up --build -d`);
107+
console.log('Containers built and started. Waiting for backend...');
108+
await waitForBackendReady();
109+
console.log('Running migrations...');
110+
await runMigrations();
111+
console.log('Setup complete. Following logs...');
112+
await runCommand(`docker compose -f ${COMPOSE_FILE} logs --follow`);
113+
break;
114+
115+
default:
116+
console.error('Unexpected container state. Please delete existing finishline containers.');
117+
break;
118+
}
119+
}
120+
121+
main().catch((error) => {
122+
console.error('Error:', error.message);
123+
process.exit(1);
124+
});

package.json

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,25 @@
1717
"prisma:seed": "cd src/backend; npx prisma db seed",
1818
"prisma:reset:force": "yarn workspace shared build; cd src/backend; npx prisma migrate reset --force",
1919
"prisma:reset": "yarn workspace shared build; cd src/backend; npx prisma migrate reset",
20+
"docker:prisma:reset": "cd devContainerization && docker compose -f docker-compose.dev.yml exec -T backend sh -c \"cd /src/backend && npx prisma migrate reset --force\"",
2021
"prisma:migrate": "yarn prisma:migrate:dev",
22+
"docker:prisma:migrate": "cd devContainerization && docker compose -f docker-compose.dev.yml exec -it -w /src/backend backend npx prisma migrate dev",
2123
"prisma:migrate:dev": "cd src/backend; npx prisma migrate dev",
2224
"prisma:migrate:prod": "cd src/backend; npx prisma migrate deploy",
2325
"prisma:generate": "cd src/backend; npx prisma generate",
26+
"docker:prisma:generate": "cd devContainerization && docker compose -f docker-compose.dev.yml exec -T backend sh -c \"cd /src/backend && npx prisma generate\"",
2427
"prisma:manual": "yarn workspace backend prisma:manual",
2528
"prisma:studio": "cd src/backend; npx prisma studio",
29+
"docker:prisma:studio": "cd devContainerization && docker compose -f docker-compose.dev.yml exec -T backend sh -c \"cd /src/backend && npx prisma studio\"",
2630
"containerize": "cd containerization; docker compose down && docker compose build && docker compose up -d && sleep 5 && cd ../ && yarn containerize:psql:init && yarn prisma:migrate",
2731
"containerize:psql:init": "docker exec database psql -U postgres -c \"CREATE DATABASE nerpm;\" && yarn database:setup:script",
2832
"containerize:test:e2e": "yarn containerize && yarn prisma:reset:force && yarn test:e2e",
2933
"lint": "npx eslint .",
3034
"test:e2e": "./system-tests/run.sh",
3135
"test:frontend": "yarn workspace shared build; yarn workspace frontend test",
36+
"docker:test:frontend": "cd devContainerization && docker compose -f docker-compose.dev.yml exec -T frontend sh -c \"cd /src/frontend && yarn test\"",
3237
"test:backend": "yarn workspace shared build; yarn workspace backend test",
38+
"docker:test:backend": "cd devContainerization && docker compose -f docker-compose.dev.yml exec -T backend sh -c \"cd /src/backend && yarn test\"",
3339
"test": "yarn test:backend && yarn test:frontend",
3440
"test:setup": "node scripts/test-setup.js && docker run --name finishline_test -e POSTGRES_PASSWORD=docker -p 5433:5432 -d postgres && sleep 5 && docker exec finishline_test psql -U postgres -c \"CREATE DATABASE nerpm;\" && yarn prisma:migrate",
3541
"test:teardown": "docker stop finishline_test && docker rm finishline_test && node scripts/test-teardown.js",
@@ -44,17 +50,25 @@
4450
"istart": "yarn i && yarn start",
4551
"reset": "rimraf yarn.lock; rimraf src/frontend/node_modules; rimraf src/backend/node_modules; rimraf src/shared/node_modules; rimraf ./node_modules; ",
4652
"install:hard": "yarn reset; yarn install; yarn prisma:generate",
47-
"tsc-check": "tsc --noEmit --project src/backend/tsconfig.json && tsc --noEmit --project src/frontend/tsconfig.json",
53+
"tsc-check": "tsc --noEmit --project src/frontend/tsconfig.json && tsc --noEmit --project src/backend/tsconfig.json",
4854
"docker:dev": "docker stop finishline; cd devContainerization; docker compose -f docker-compose.dev.yml down && docker compose -f docker-compose.dev.yml build && docker compose -f docker-compose.dev.yml up --watch",
4955
"exec:frontend": "docker exec -it frontend /bin/sh",
50-
"exec:backend": "docker exec -it backend /bin/sh"
56+
"exec:backend": "docker exec -it backend /bin/sh",
57+
"docker:ps": "docker compose -f devContainerization/docker-compose.dev.yml ps",
58+
"docker:start": "yarn database:setup:script && cd devContainerization && node start-containers.js",
59+
"docker:i": "cd devContainerization && docker compose -f docker-compose.dev.yml exec -T backend sh -c \"yarn install && cd src/backend && npx prisma generate\" && docker compose -f docker-compose.dev.yml exec -T frontend sh -c \"yarn install\"",
60+
"docker:test": "yarn test:setup && cd devContainerization && docker compose -f docker-compose.dev.yml exec backend bash -c \"yarn test:backend\" && docker compose -f docker-compose.dev.yml exec frontend sh -c \"yarn test:frontend\" && yarn test:teardown",
61+
"docker:rebuild": "docker compose -f devContainerization/docker-compose.dev.yml rm -f -s && yarn docker:start"
5162
},
5263
"resolutions": {
5364
"@types/react": "17.0.1",
5465
"@types/react-dom": "17.0.1"
5566
},
5667
"dependencies": {
68+
"@types/multer": "^1.4.12",
5769
"mitt": "^3.0.1",
70+
"react-hook-form-persist": "^3.0.0",
71+
"recharts": "^2.15.3",
5872
"typescript": "^5.7.3"
5973
},
6074
"devDependencies": {
@@ -70,7 +84,7 @@
7084
"eslint": "^7.0.0",
7185
"eslint-config-prettier": "^10.0.1",
7286
"eslint-config-react-app": "^7.0.1",
73-
"eslint-plugin-cypress": "latest",
87+
"eslint-plugin-cypress": "4.3.0",
7488
"eslint-plugin-prettier": "^5.2.2",
7589
"prettier": "^3.4.2",
7690
"rimraf": "^6.0.1",

scripts/database-setup.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ fs.readFile(filePath, 'utf8', (err, data) => {
1717
// Split file contents into lines
1818
const lines = data.trim().split('\n');
1919

20-
// Check if the last line matches the lineToAdd
21-
if (lines[lines.length - 1] !== lineToAdd) {
22-
// Append the line if it's not already the last line
23-
fs.appendFile(filePath, `\n${lineToAdd}`, 'utf8', (err) => {
24-
if (err) {
25-
console.error('Error appending line to file:', err);
26-
return;
27-
}
28-
});
20+
for (const line of lines) {
21+
//db url already exists, no need to add it
22+
if (line.startsWith("DATABASE_URL=")) return;
2923
}
24+
25+
fs.appendFile(filePath, `\n${lineToAdd}`, 'utf8', (err) => {
26+
if (err) {
27+
console.error('Error appending line to file:', err);
28+
return;
29+
}
30+
});
3031
});

scripts/test-setup.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,4 @@ fs.readFile(filePath, 'utf8', (err, data) => {
2222
}
2323
});
2424
}
25-
});
25+
});

scripts/test-teardown.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,4 @@ fs.readFile(filePath, 'utf8', (err, data) => {
2525
}
2626
});
2727
}
28-
});
28+
});

src/backend/.dockerignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
**/node_modules
22
**/dist
3-
**/tests
4-
**/*.test.ts
53

64
**/frontend

0 commit comments

Comments
 (0)