From c3e3351d6fd3524de2e7b7f4e52104fba70ca8a5 Mon Sep 17 00:00:00 2001 From: Spyros Date: Thu, 9 Jul 2026 15:08:25 +0100 Subject: [PATCH 1/2] fix: improve prod Docker build for #15 Exclude .venv/ from build context and install system chromium in the node build stage (mirrors PR #641) so yarn install succeeds on arm64. Co-authored-by: Cursor --- .dockerignore | 1 + Dockerfile | 1 + 2 files changed, 2 insertions(+) diff --git a/.dockerignore b/.dockerignore index bd198ffce..1c274ff64 100644 --- a/.dockerignore +++ b/.dockerignore @@ -48,6 +48,7 @@ Vagrantfile ### conventions ### venv/ +.venv/ venv-*/ v/ diff --git a/Dockerfile b/Dockerfile index 68395887a..eb382def0 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,7 @@ FROM node:lts as build LABEL org.opencontainers.image.source = "https://github.com/OWASP/OpenCRE" WORKDIR /code +RUN apt-get update && apt-get install -y chromium COPY . /code RUN yarn install && yarn build From a6949de901f8a2f613cf4de0289175a7afb0ade9 Mon Sep 17 00:00:00 2001 From: Spyros Date: Thu, 9 Jul 2026 16:29:24 +0100 Subject: [PATCH 2/2] fix: resolve prod Docker yarn build and runtime for #15 Exclude built frontend assets from tsconfig, fix TypeScript errors surfacing under node:lts, remove broken @types/minimatch stub on install, and harden prod-docker-entrypoint (alembic heads + document_metadata + upstream_sync) so the container serves standards data after startup. Co-authored-by: Cursor --- .../Explorer/visuals/force-graph/forceGraph.tsx | 2 +- .../src/pages/GapAnalysis/GapAnalysis.tsx | 6 ++++-- .../frontend/src/pages/chatbot/chatbot.tsx | 2 +- application/frontend/src/routes.tsx | 4 ++-- package.json | 2 +- scripts/prod-docker-entrypoint.sh | 16 ++++++++++++++-- tsconfig.json | 2 +- 7 files changed, 24 insertions(+), 10 deletions(-) diff --git a/application/frontend/src/pages/Explorer/visuals/force-graph/forceGraph.tsx b/application/frontend/src/pages/Explorer/visuals/force-graph/forceGraph.tsx index 0c2328cda..21d9daba5 100644 --- a/application/frontend/src/pages/Explorer/visuals/force-graph/forceGraph.tsx +++ b/application/frontend/src/pages/Explorer/visuals/force-graph/forceGraph.tsx @@ -31,7 +31,7 @@ export const ExplorerForceGraph = () => { fullLoadProgress, dataLoadError, } = useDataStore(); - const fgRef = useRef(); + const fgRef = useRef(undefined); // ADDING STATE FOR FILTERING LOGIC const [filterTypeA, setFilterTypeA] = useState(''); const [filterTypeB, setFilterTypeB] = useState(''); diff --git a/application/frontend/src/pages/GapAnalysis/GapAnalysis.tsx b/application/frontend/src/pages/GapAnalysis/GapAnalysis.tsx index 1a0a72c38..0ec5611ea 100644 --- a/application/frontend/src/pages/GapAnalysis/GapAnalysis.tsx +++ b/application/frontend/src/pages/GapAnalysis/GapAnalysis.tsx @@ -127,7 +127,7 @@ export const GapAnalysis = () => { const [loadingGA, setLoadingGA] = useState(false); const [error, setError] = useState(null); const { apiUrl } = useEnvironment(); - const timerIdRef = useRef(); + const timerIdRef = useRef | undefined>(undefined); useEffect(() => { const fetchData = async () => { @@ -173,7 +173,9 @@ export const GapAnalysis = () => { timerIdRef.current = setInterval(pollingCallback, 10000); }; const stopPolling = () => { - clearInterval(timerIdRef.current); + if (timerIdRef.current !== undefined) { + clearInterval(timerIdRef.current); + } }; if (gaJob) { diff --git a/application/frontend/src/pages/chatbot/chatbot.tsx b/application/frontend/src/pages/chatbot/chatbot.tsx index 067171189..544f126c6 100644 --- a/application/frontend/src/pages/chatbot/chatbot.tsx +++ b/application/frontend/src/pages/chatbot/chatbot.tsx @@ -105,7 +105,7 @@ export const Chatbot = () => { function processResponse(response: string) { const responses = response.split('```'); - const res: JSX.Element[] = []; + const res: React.ReactElement[] = []; responses.forEach((txt, i) => { if (i % 2 === 0) { diff --git a/application/frontend/src/routes.tsx b/application/frontend/src/routes.tsx index 5763f2e05..73110014f 100644 --- a/application/frontend/src/routes.tsx +++ b/application/frontend/src/routes.tsx @@ -1,4 +1,4 @@ -import { ReactNode } from 'react'; +import { ElementType } from 'react'; import { BROWSEROOT, @@ -34,7 +34,7 @@ const ExplorerForceGraphWithLayout = withExplorerLayout(ExplorerForceGraph); export interface IRoute { path: string; - component: ReactNode | ReactNode[]; + component: ElementType; showFilter: boolean; } export interface Capabilities { diff --git a/package.json b/package.json index f6ef1517e..a56945d76 100755 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "build": "webpack --config webpack.prod.js", "start": "webpack serve", "test:e2e": "jest", - "postinstall": "del-cli node_modules/@types/react-dom/node_modules/@types && del-cli node_modules/webpack/types.d.ts" + "postinstall": "del-cli node_modules/@types/react-dom/node_modules/@types && del-cli node_modules/webpack/types.d.ts && del-cli node_modules/@types/minimatch" }, "keywords": [], "author": "Craig Knott", diff --git a/scripts/prod-docker-entrypoint.sh b/scripts/prod-docker-entrypoint.sh index 35076fd24..077482796 100644 --- a/scripts/prod-docker-entrypoint.sh +++ b/scripts/prod-docker-entrypoint.sh @@ -2,7 +2,19 @@ export INSECURE_REQUESTS=1 export FLASK_CONFIG="production" -export FLASK_APP=`pwd`/cre.py -flask db upgrade +export FLASK_APP=`pwd`/cre.py +flask db upgrade heads +python - <<'PY' +import sqlite3 + +db_path = "/code/standards_cache.sqlite" +conn = sqlite3.connect(db_path) +for table in ("cre", "node"): + cols = {row[1] for row in conn.execute(f"PRAGMA table_info({table})")} + if "document_metadata" not in cols: + conn.execute(f"ALTER TABLE {table} ADD COLUMN document_metadata JSON") +conn.commit() +conn.close() +PY python /code/cre.py --upstream_sync gunicorn cre:app -b :5000 --timeout 90 diff --git a/tsconfig.json b/tsconfig.json index decf33d67..02fbbaa74 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -16,5 +16,5 @@ "esModuleInterop": true }, "include": ["**/*.ts", "**/*.tsx", "**/*.js", "src/**/*"], - "exclude": ["venv", "dist", "node_modules", "build", "scripts"] + "exclude": ["venv", "dist", "node_modules", "build", "scripts", "application/frontend/www"] }