From bd8b5353f4649ff0c01cf6eb73d898b9a2c91424 Mon Sep 17 00:00:00 2001 From: Nani0002 Date: Tue, 11 Nov 2025 12:23:32 +0100 Subject: [PATCH 1/5] Prepare server to accept url prefix --- docker/web/entrypoint.sh | 9 +++++++++ webgui-new/src/server.ts | 15 ++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/docker/web/entrypoint.sh b/docker/web/entrypoint.sh index 8dfea219d..a7e806be0 100644 --- a/docker/web/entrypoint.sh +++ b/docker/web/entrypoint.sh @@ -9,4 +9,13 @@ if [ "$(id -u)" == '0' ]; then exec gosu codecompass "$0" "$@" fi +set -es +# Set default value for API_PREFIX if not provided +: "${API_PREFIX:=""}" + +# Create web_config.env file with the API_PREFIX +cat > ../../webgui-new/.env.local < { }, }); - app.use('/', proxyHandler); + let API_PREFIX = process.env.API_PREFIX || "/"; + + if (!API_PREFIX.startsWith("/")) { + API_PREFIX = `/${API_PREFIX}`; + } + + if (/^https?:\/\//.test(API_PREFIX)) { + console.warn( + `[WARN] API_PREFIX appears to be a full URL (${API_PREFIX}). Expected a path like "/api". Using "/" instead.` + ); + API_PREFIX = "/"; + } + + app.use(API_PREFIX, proxyHandler); app.get('*', (req, res) => nextHandler(req, res)); await nextApp.prepare(); From 64244a54a1da2cf938b56cbec27885bd09877871 Mon Sep 17 00:00:00 2001 From: Varga Istvan Date: Mon, 8 Dec 2025 22:24:36 +0100 Subject: [PATCH 2/5] Base path dynamic change --- docker/web/Dockerfile | 159 ++++---- docker/web/entrypoint.sh | 33 +- .../search/lib/java/lucene-memory-4.9.0.jar | Bin scripts/CodeCompass_logger | 56 +-- scripts/install_latest_build2.sh | 114 +++--- scripts/remover.sh | 22 +- webgui-new/next.config.js | 6 +- webgui-new/package-lock.json | 339 +++++++++++++++++- webgui-new/package.json | 1 + webgui-new/scripts/patch-basepath.js | 18 + webgui-new/src/server.ts | 81 ++--- webgui-new/thrift-codegen.sh | 106 +++--- 12 files changed, 632 insertions(+), 303 deletions(-) mode change 100755 => 100644 plugins/search/lib/java/lucene-memory-4.9.0.jar mode change 100755 => 100644 scripts/CodeCompass_logger mode change 100755 => 100644 scripts/install_latest_build2.sh mode change 100755 => 100644 scripts/remover.sh create mode 100644 webgui-new/scripts/patch-basepath.js mode change 100755 => 100644 webgui-new/thrift-codegen.sh diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile index 4780bb7ec..e9b3bd0de 100644 --- a/docker/web/Dockerfile +++ b/docker/web/Dockerfile @@ -1,79 +1,80 @@ -############################################################################### -#---------------------------- IMPORT RUNTIME -----------------------------# -############################################################################### - -FROM codecompass:runtime as runtime - -############################################################################### -#------------------------ EXECUTABLE CONTAINER --------------------------# -############################################################################### - -FROM ubuntu:22.04 - -# tzdata package is installed implicitly in the following command. This package -# sets timezone interactively during the installation process. This environment -# variable prevents this interaction. -ARG DEBIAN_FRONTEND=noninteractive - -RUN set -x && apt-get update -qq \ - && apt-get install -qqy --no-install-recommends \ - llvm-15 \ - libboost-filesystem-dev libboost-log-dev libboost-program-options-dev \ - libsqlite3-dev \ - postgresql-server-dev-14 \ - default-jre \ - libgit2-dev \ - libldap-2.5-0 \ - libssl3 \ - libgvc6 \ - libthrift-dev \ - libpq5 \ - # To switch user and exec command. - gosu \ - tini \ - curl ca-certificates gnupg \ - wget \ - gcc-11 g++-11 \ - && ln -s /usr/bin/gcc-11 /usr/bin/gcc \ - && ln -s /usr/bin/g++-11 /usr/bin/g++ \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/ \ - && set +x - -# Install NodeJS from NodeSource. -RUN mkdir -p /etc/apt/keyrings && \ - curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ - echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ - apt-get update -qq && \ - apt-get install -y nodejs && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/ - -# Copy ODB install directory. -COPY --from=runtime /opt/odb /opt/odb - -ARG CC_GID=960 -ARG CC_UID=960 - -ENV CC_GID ${CC_GID} -ENV CC_UID ${CC_UID} - -# Create user and group for CodeCompass. -RUN groupadd --system codecompass --gid ${CC_GID} && \ - useradd --system --no-log-init --no-create-home --uid ${CC_UID} --gid codecompass codecompass - -# Copy CodeCompass install directory. (Change permission of the CodeCompass package.) -# TODO: only the webserver's binaries should be included in this image. -COPY --from=runtime --chown=codecompass:codecompass /codecompass /codecompass - -ENV PATH="/codecompass/bin:/opt/odb/bin:$PATH" - -COPY --chown=codecompass:codecompass docker/web/entrypoint.sh /usr/local/bin/entrypoint.sh -RUN chmod a+x /usr/local/bin/entrypoint.sh - - -EXPOSE 8080 - -ENTRYPOINT ["tini", "--", "/usr/local/bin/entrypoint.sh"] - -CMD ["CodeCompass_webserver", "-w", "/workspace", "-p", "8080"] +############################################################################### +#---------------------------- IMPORT RUNTIME -----------------------------# +############################################################################### + +FROM codecompass:runtime as runtime + +############################################################################### +#------------------------ EXECUTABLE CONTAINER --------------------------# +############################################################################### + +FROM ubuntu:22.04 + +# tzdata package is installed implicitly in the following command. This package +# sets timezone interactively during the installation process. This environment +# variable prevents this interaction. +ARG DEBIAN_FRONTEND=noninteractive + +RUN set -x && apt-get update -qq \ + && apt-get install -qqy --no-install-recommends \ + llvm-15 \ + libboost-filesystem-dev libboost-log-dev libboost-program-options-dev \ + libsqlite3-dev \ + postgresql-server-dev-14 \ + default-jre \ + libgit2-dev \ + libldap-2.5-0 \ + libssl3 \ + libgvc6 \ + libthrift-dev \ + libpq5 \ + # To switch user and exec command. + gosu \ + tini \ + curl ca-certificates gnupg \ + wget \ + gcc-11 g++-11 \ + && ln -s /usr/bin/gcc-11 /usr/bin/gcc \ + && ln -s /usr/bin/g++-11 /usr/bin/g++ \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/ \ + && set +x + +# Install NodeJS from NodeSource. +RUN mkdir -p /etc/apt/keyrings && \ + curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ + apt-get update -qq && \ + apt-get install -y nodejs && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/ + +# Copy ODB install directory. +COPY --from=runtime /opt/odb /opt/odb + +ARG CC_GID=960 +ARG CC_UID=960 + +ENV CC_GID ${CC_GID} +ENV CC_UID ${CC_UID} + +# Create user and group for CodeCompass. +RUN groupadd --system codecompass --gid ${CC_GID} && \ + useradd --system --no-log-init --no-create-home --uid ${CC_UID} --gid codecompass codecompass + +# Copy CodeCompass install directory. (Change permission of the CodeCompass package.) +# TODO: only the webserver's binaries should be included in this image. +COPY --from=runtime --chown=codecompass:codecompass /codecompass /codecompass + +ENV PATH="/codecompass/bin:/opt/odb/bin:$PATH" + +COPY --chown=codecompass:codecompass docker/web/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod a+x /usr/local/bin/entrypoint.sh + + +EXPOSE 8080 + +ENTRYPOINT ["tini", "--", "/usr/local/bin/entrypoint.sh"] + +CMD ["sh", "-c", "node ../../webgui-new/scripts/patch-basepath.js && CodeCompass_webserver -w /workspace -p 8080"] + diff --git a/docker/web/entrypoint.sh b/docker/web/entrypoint.sh index a7e806be0..1c79a33f0 100644 --- a/docker/web/entrypoint.sh +++ b/docker/web/entrypoint.sh @@ -1,21 +1,12 @@ -#!/bin/bash - -if [ "$(id -u)" == '0' ]; then - # Change the owner of the workspace directory - mkdir -p /workspace - chown codecompass:codecompass /workspace - - # Execute this script again with codecompass user. - exec gosu codecompass "$0" "$@" -fi - -set -es -# Set default value for API_PREFIX if not provided -: "${API_PREFIX:=""}" - -# Create web_config.env file with the API_PREFIX -cat > ../../webgui-new/.env.local < \"\"" >&2 - exit 1 -fi - -binDir=$(dirname $0) -jsonFile=$1 -shift - -if [ -f $jsonFile ]; then - echo "The compilation database already exists!" >&2 - exit 1 -fi - -export LDLOGGER_HOME=$binDir - -source $binDir/../share/codecompass/setldlogenv.sh $jsonFile; \ - bash -c "$@" - -if [ ! -f $jsonFile ]; then - echo "Failed to log the build commands!" >&2 - exit 1 -elif [ $(wc -c <$jsonFile) -le 5 ]; then - echo "Failed to log the build commands: the build log is empty!" >&2 - exit 1 -fi +#!/usr/bin/env bash + +if [ $# -ne 2 ]; then + echo "Usage: $0 \"\"" >&2 + exit 1 +fi + +binDir=$(dirname $0) +jsonFile=$1 +shift + +if [ -f $jsonFile ]; then + echo "The compilation database already exists!" >&2 + exit 1 +fi + +export LDLOGGER_HOME=$binDir + +source $binDir/../share/codecompass/setldlogenv.sh $jsonFile; \ + bash -c "$@" + +if [ ! -f $jsonFile ]; then + echo "Failed to log the build commands!" >&2 + exit 1 +elif [ $(wc -c <$jsonFile) -le 5 ]; then + echo "Failed to log the build commands: the build log is empty!" >&2 + exit 1 +fi diff --git a/scripts/install_latest_build2.sh b/scripts/install_latest_build2.sh old mode 100755 new mode 100644 index 2cc8cfa78..d04d9a81e --- a/scripts/install_latest_build2.sh +++ b/scripts/install_latest_build2.sh @@ -1,57 +1,57 @@ -#!/bin/bash - -if [ $# -lt 1 ]; then - echo "No installation directory was provided for build2!" 1>&2 - exit 1 -fi - -## download phase - -install_dir=$1 -toolchain_file="toolchain.sha256" -if [ "$1" = "--version" ]; then - wget -q --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" -else - wget --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" -fi - - -version_line=$(grep -m 1 '' "$toolchain_file") -version_number=$(echo "$version_line" | awk '{print $2}') - -### Return with version string only without actually installing build2 if "--version" flag is specified. -if [ "$1" = "--version" ]; then - echo "${version_number}" - rm -f "${toolchain_file}" - exit 0 -fi - -version_to_install=build2-install-${version_number}.sh -download_url=https://download.build2.org/${version_number}/${version_to_install} -wget --no-verbose --no-clobber "${download_url}" -O "${version_to_install}" - -## sha256 check phase - -line_with_version=$(grep "$version_to_install" "$toolchain_file") -checksum_for_version=$(echo "$line_with_version" | awk '{print $1}') - -if echo "${checksum_for_version} ${version_to_install}" | sha256sum -c; then - echo "Build2 installer for version ${version_number} has been downloaded!" -else - echo "Expected checksum for build2 installer version ${version_number} doesn't match! Probably the file has been corrupted! Please install it manually!" 1>&2 - echo "Expected: ${checksum_for_version}" 1>&2 - rm "$version_to_install" "$toolchain_file" - exit 1 -fi - -## install phase - -sh ${version_to_install} --yes --trust yes --jobs $(nproc) "${install_dir}" - -## cleanup phase - -compressed_toolchain="build2-toolchain-${version_number}.tar.xz" - -rm -f "${toolchain_file}" "${version_to_install}" "${compressed_toolchain}" - -echo "Build2 version ${version_number} has been successfully installed!" +#!/bin/bash + +if [ $# -lt 1 ]; then + echo "No installation directory was provided for build2!" 1>&2 + exit 1 +fi + +## download phase + +install_dir=$1 +toolchain_file="toolchain.sha256" +if [ "$1" = "--version" ]; then + wget -q --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" +else + wget --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" +fi + + +version_line=$(grep -m 1 '' "$toolchain_file") +version_number=$(echo "$version_line" | awk '{print $2}') + +### Return with version string only without actually installing build2 if "--version" flag is specified. +if [ "$1" = "--version" ]; then + echo "${version_number}" + rm -f "${toolchain_file}" + exit 0 +fi + +version_to_install=build2-install-${version_number}.sh +download_url=https://download.build2.org/${version_number}/${version_to_install} +wget --no-verbose --no-clobber "${download_url}" -O "${version_to_install}" + +## sha256 check phase + +line_with_version=$(grep "$version_to_install" "$toolchain_file") +checksum_for_version=$(echo "$line_with_version" | awk '{print $1}') + +if echo "${checksum_for_version} ${version_to_install}" | sha256sum -c; then + echo "Build2 installer for version ${version_number} has been downloaded!" +else + echo "Expected checksum for build2 installer version ${version_number} doesn't match! Probably the file has been corrupted! Please install it manually!" 1>&2 + echo "Expected: ${checksum_for_version}" 1>&2 + rm "$version_to_install" "$toolchain_file" + exit 1 +fi + +## install phase + +sh ${version_to_install} --yes --trust yes --jobs $(nproc) "${install_dir}" + +## cleanup phase + +compressed_toolchain="build2-toolchain-${version_number}.tar.xz" + +rm -f "${toolchain_file}" "${version_to_install}" "${compressed_toolchain}" + +echo "Build2 version ${version_number} has been successfully installed!" diff --git a/scripts/remover.sh b/scripts/remover.sh old mode 100755 new mode 100644 index eb376f555..bc1fc3079 --- a/scripts/remover.sh +++ b/scripts/remover.sh @@ -1,11 +1,11 @@ -#!/bin/bash - -FILES=$(ls *.js) - -for FILE in $FILES -do - if [ -f "$FILE" ] - then - sed -i -e "/if (typeof Int64 === 'undefined' && typeof require === 'function') {/,+2 d" "$FILE" - fi -done +#!/bin/bash + +FILES=$(ls *.js) + +for FILE in $FILES +do + if [ -f "$FILE" ] + then + sed -i -e "/if (typeof Int64 === 'undefined' && typeof require === 'function') {/,+2 d" "$FILE" + fi +done diff --git a/webgui-new/next.config.js b/webgui-new/next.config.js index 6aa118faf..7733ec099 100644 --- a/webgui-new/next.config.js +++ b/webgui-new/next.config.js @@ -2,6 +2,8 @@ require('dotenv').config(); +const BASE_PLACEHOLDER = '__BASE_PATH__'; + /** @type {import('next').NextConfig} */ const nextConfig = { output: 'export', @@ -13,8 +15,8 @@ const nextConfig = { }, trailingSlash: true, ...(process.env.NODE_ENV === 'production' && { - assetPrefix: `${process.env.PUBLIC_URL || ''}/new`, - basePath: `${process.env.PUBLIC_URL || ''}/new`, + assetPrefix: `${process.env.PUBLIC_URL || ''}${BASE_PLACEHOLDER}`, + basePath: `${process.env.PUBLIC_URL || ''}${BASE_PLACEHOLDER}`, }), }; diff --git a/webgui-new/package-lock.json b/webgui-new/package-lock.json index 7ccd04977..2b5064738 100644 --- a/webgui-new/package-lock.json +++ b/webgui-new/package-lock.json @@ -31,6 +31,7 @@ "react-zoom-pan-pinch": "^3.7.0", "reactflow": "^11.11.4", "recharts": "^2.15.4", + "replace-in-file": "^8.4.0", "sass": "^1.93.2", "sharp": "^0.32.6", "thrift": "0.16.0" @@ -710,6 +711,27 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -3732,6 +3754,47 @@ "integrity": "sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==", "license": "MIT" }, + "node_modules/cliui": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-9.0.1.tgz", + "integrity": "sha512-k7ndgKhwoQveBL+/1tqGJYNz097I7WOvwbmmU2AR5+magtbjPWQTS1C5vzGkBC8Ym8UWRzfKUzUUqFLypY4Q+w==", + "license": "ISC", + "dependencies": { + "string-width": "^7.2.0", + "strip-ansi": "^7.1.0", + "wrap-ansi": "^9.0.0" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/clsx": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", @@ -3866,6 +3929,15 @@ "node": ">=10" } }, + "node_modules/cosmiconfig/node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, "node_modules/create-require": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", @@ -4583,6 +4655,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -5489,6 +5570,27 @@ "node": ">= 0.4" } }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-east-asian-width": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", + "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/get-intrinsic": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.1.tgz", @@ -6670,6 +6772,15 @@ "loose-envify": "cli.js" } }, + "node_modules/lru-cache": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -6817,6 +6928,15 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mkdirp-classic": { "version": "0.5.3", "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", @@ -7256,6 +7376,22 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "license": "MIT" }, + "node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/path-to-regexp": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", @@ -7827,6 +7963,67 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/replace-in-file": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/replace-in-file/-/replace-in-file-8.4.0.tgz", + "integrity": "sha512-D28k8jy2LtUGbCzCnR3znajaTWIjJ/Uee3UdodzcHRxE7zn6NmYW/dcSqyivnsYU3W+MxdX6SbF28NvJ0GRoLA==", + "license": "MIT", + "dependencies": { + "chalk": "^5.6.2", + "glob": "^13.0.0", + "yargs": "^18.0.0" + }, + "bin": { + "replace-in-file": "bin/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/replace-in-file/node_modules/chalk": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", + "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/replace-in-file/node_modules/glob": { + "version": "13.0.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-13.0.0.tgz", + "integrity": "sha512-tvZgpqk6fz4BaNZ66ZsRaZnbHvP/jG3uKJvAZOwEVUL4RTA5nJeeLYfyN9/VA8NX/V3IBG+hkeuGpKjvELkVhA==", + "license": "BlueOak-1.0.0", + "dependencies": { + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "path-scurry": "^2.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/replace-in-file/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/requires-port": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", @@ -8456,6 +8653,56 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-width": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", + "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^10.3.0", + "get-east-asian-width": "^1.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "10.6.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", + "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", + "license": "MIT" + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/string.prototype.includes": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/string.prototype.includes/-/string.prototype.includes-2.0.1.tgz", @@ -9352,6 +9599,62 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", + "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -9367,13 +9670,39 @@ "async-limiter": "~1.0.0" } }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "license": "ISC", "engines": { - "node": ">= 6" + "node": ">=10" + } + }, + "node_modules/yargs": { + "version": "18.0.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-18.0.0.tgz", + "integrity": "sha512-4UEqdc2RYGHZc7Doyqkrqiln3p9X2DZVxaGbwhn2pi7MrRagKaOcIKe8L3OxYcbhXLgLFUS3zAYuQjKBQgmuNg==", + "license": "MIT", + "dependencies": { + "cliui": "^9.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "string-width": "^7.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^22.0.0" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" + } + }, + "node_modules/yargs-parser": { + "version": "22.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-22.0.0.tgz", + "integrity": "sha512-rwu/ClNdSMpkSrUb+d6BRsSkLUq1fmfsY6TOpYzTwvwkg1/NRG85KBy3kq++A8LKQwX6lsu+aWad+2khvuXrqw==", + "license": "ISC", + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=23" } }, "node_modules/yn": { diff --git a/webgui-new/package.json b/webgui-new/package.json index 7878d9bee..799d1bfa0 100644 --- a/webgui-new/package.json +++ b/webgui-new/package.json @@ -52,6 +52,7 @@ "react-zoom-pan-pinch": "^3.7.0", "reactflow": "^11.11.4", "recharts": "^2.15.4", + "replace-in-file": "^8.4.0", "sass": "^1.93.2", "sharp": "^0.32.6", "thrift": "0.16.0" diff --git a/webgui-new/scripts/patch-basepath.js b/webgui-new/scripts/patch-basepath.js new file mode 100644 index 000000000..514be2ec1 --- /dev/null +++ b/webgui-new/scripts/patch-basepath.js @@ -0,0 +1,18 @@ +const { replaceInFileSync } = require('replace-in-file'); + +const PLACEHOLDER = '__BASE_PATH__'; +const NEW_BASE = process.env.APP_BASE_PATH || '/new'; + +console.log(`[patch-basepath] ${PLACEHOLDER} -> ${NEW_BASE}`); + +try { + const results = replaceInFileSync({ + files: ['out/**/*.html', 'out/**/*.js', 'out/**/*.json'], + from: new RegExp(PLACEHOLDER.replace(/\//g, '\\/'), 'g'), + to: NEW_BASE, + }); + console.log('[patch-basepath] modified files:', results.length); +} catch (err) { + console.error('[patch-basepath] error:', err); + process.exit(1); +} \ No newline at end of file diff --git a/webgui-new/src/server.ts b/webgui-new/src/server.ts index 7ee737c61..b0dbf196d 100644 --- a/webgui-new/src/server.ts +++ b/webgui-new/src/server.ts @@ -1,47 +1,34 @@ -import dotenv from 'dotenv'; -import express from 'express'; -import next from 'next'; -import { createProxyMiddleware } from 'http-proxy-middleware'; - -dotenv.config({ path: '.env.local' }); -dotenv.config(); - -const main = async () => { - const app = express(); - const port = parseInt(process.env.DEVSERVER_PORT as string); - const nextApp = next({ dev: process.env.NODE_ENV !== 'production' }); - - const nextHandler = nextApp.getRequestHandler(); - - const proxyHandler = createProxyMiddleware({ - target: process.env.BACKEND_URL, - changeOrigin: true, - pathFilter: ['**/*Service', '**/ga.txt'], - pathRewrite: { - '^/[^/]+/(.+Service)$': '/$1', - '^/ga.txt' : '/ga.txt' - }, - }); - - let API_PREFIX = process.env.API_PREFIX || "/"; - - if (!API_PREFIX.startsWith("/")) { - API_PREFIX = `/${API_PREFIX}`; - } - - if (/^https?:\/\//.test(API_PREFIX)) { - console.warn( - `[WARN] API_PREFIX appears to be a full URL (${API_PREFIX}). Expected a path like "/api". Using "/" instead.` - ); - API_PREFIX = "/"; - } - - app.use(API_PREFIX, proxyHandler); - app.get('*', (req, res) => nextHandler(req, res)); - - await nextApp.prepare(); - - app.listen(port, () => console.log(`> Ready on localhost:${port}`)); -}; - -main(); +import dotenv from 'dotenv'; +import express from 'express'; +import next from 'next'; +import { createProxyMiddleware } from 'http-proxy-middleware'; + +dotenv.config({ path: '.env.local' }); +dotenv.config(); + +const main = async () => { + const app = express(); + const port = parseInt(process.env.DEVSERVER_PORT as string); + const nextApp = next({ dev: process.env.NODE_ENV !== 'production' }); + + const nextHandler = nextApp.getRequestHandler(); + + const proxyHandler = createProxyMiddleware({ + target: process.env.BACKEND_URL, + changeOrigin: true, + pathFilter: ['**/*Service', '**/ga.txt'], + pathRewrite: { + '^/[^/]+/(.+Service)$': '/$1', + '^/ga.txt' : '/ga.txt' + }, + }); + + app.use("/", proxyHandler); + app.get('*', (req, res) => nextHandler(req, res)); + + await nextApp.prepare(); + + app.listen(port, () => console.log(`> Ready on localhost:${port}`)); +}; + +main(); diff --git a/webgui-new/thrift-codegen.sh b/webgui-new/thrift-codegen.sh old mode 100755 new mode 100644 index 17787bf43..e724487ac --- a/webgui-new/thrift-codegen.sh +++ b/webgui-new/thrift-codegen.sh @@ -1,53 +1,53 @@ -THRIFT_SOURCE="../" - -while [[ $# -gt 0 ]]; do - case "$1" in - --thrift-source) - THRIFT_SOURCE="$2" - shift 2 - ;; - *) - echo "Unknown option: $1" - exit 1 - ;; - esac -done - -rm -rf ./generated -rm -rf ./thrift - -mkdir -p thrift - -for file in $(find "$THRIFT_SOURCE/service/" -type f -name '*.thrift'); do - filename=$(basename "$file") - echo "Installing $filename" - if [ ! -f "./thrift/$filename" ]; then - cp "$file" "./thrift/" - fi -done - -for file in $(find "$THRIFT_SOURCE/plugins/" -type f -name '*.thrift'); do - filename=$(basename "$file") - echo "Installing $filename" - if [ ! -f "./thrift/$filename" ]; then - cp "$file" "./thrift/" - fi -done - -# Fix include paths -for file in $(find ./thrift -type f -name '*.thrift'); do - sed -i 's/include "\(.*\)\/\([^\/]*\)"/include "\2"/g' "$file" -done - -npm run thrift-ts -mv codegen generated -rm -rf ./thrift - -for file in $(find ./generated -type f -name '*.ts'); do - sed -i 's/import Int64 = require("node-int64");/import Int64 from "node-int64";/' "$file" -done - -# Resolve conflicting import in SearchService.ts -sed -i 's/import \* as SearchResult from "\.\/SearchResult";/import \* as SearchRes from "\.\/SearchResult";/g' ./generated/SearchService.ts -sed -i 's/SearchResult\.SearchResult/SearchRes.SearchResult/g' ./generated/SearchService.ts - +THRIFT_SOURCE="../" + +while [[ $# -gt 0 ]]; do + case "$1" in + --thrift-source) + THRIFT_SOURCE="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +rm -rf ./generated +rm -rf ./thrift + +mkdir -p thrift + +for file in $(find "$THRIFT_SOURCE/service/" -type f -name '*.thrift'); do + filename=$(basename "$file") + echo "Installing $filename" + if [ ! -f "./thrift/$filename" ]; then + cp "$file" "./thrift/" + fi +done + +for file in $(find "$THRIFT_SOURCE/plugins/" -type f -name '*.thrift'); do + filename=$(basename "$file") + echo "Installing $filename" + if [ ! -f "./thrift/$filename" ]; then + cp "$file" "./thrift/" + fi +done + +# Fix include paths +for file in $(find ./thrift -type f -name '*.thrift'); do + sed -i 's/include "\(.*\)\/\([^\/]*\)"/include "\2"/g' "$file" +done + +npm run thrift-ts +mv codegen generated +rm -rf ./thrift + +for file in $(find ./generated -type f -name '*.ts'); do + sed -i 's/import Int64 = require("node-int64");/import Int64 from "node-int64";/' "$file" +done + +# Resolve conflicting import in SearchService.ts +sed -i 's/import \* as SearchResult from "\.\/SearchResult";/import \* as SearchRes from "\.\/SearchResult";/g' ./generated/SearchService.ts +sed -i 's/SearchResult\.SearchResult/SearchRes.SearchResult/g' ./generated/SearchService.ts + From a0fad2e1fa9d6be583a42f1cfb5d92249159b7e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moln=C3=A1r=20D=C3=A1niel?= <156610265+Nani0002@users.noreply.github.com> Date: Mon, 15 Dec 2025 12:10:29 +0100 Subject: [PATCH 3/5] Update docker README to include -e option for the webgui --- docker/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docker/README.md b/docker/README.md index f830c4b08..e3b97d4ff 100644 --- a/docker/README.md +++ b/docker/README.md @@ -162,6 +162,11 @@ docker run \ CodeCompass_webserver -w /workspace ``` +If you want to edit the public URL of the web GUI, you can do this by appending the +`-e APP_BASE_PATH=/YOUR_PATH` command option to the previous run command. +Leaving this out of the command will start the web interface with no set path. +The new GUI will still be accessible in the /new path appended to the end of your URL. + # Official DockerHub images Prebuilt images can be downloaded from DockerHub, from the From 7297c1537f2d5d9e3b09cce01d62589a486b3bff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Moln=C3=A1r=20D=C3=A1niel?= <156610265+Nani0002@users.noreply.github.com> Date: Mon, 15 Dec 2025 12:10:29 +0100 Subject: [PATCH 4/5] Update BASE_PATH and replace EoL characters --- docker/web/Dockerfile | 160 +++++++++++++-------------- docker/web/entrypoint.sh | 24 ++-- scripts/CodeCompass_logger | 56 +++++----- scripts/install_latest_build2.sh | 114 +++++++++---------- scripts/remover.sh | 22 ++-- webgui-new/next.config.js | 2 +- webgui-new/scripts/patch-basepath.js | 34 +++--- webgui-new/src/server.ts | 68 ++++++------ webgui-new/thrift-codegen.sh | 106 +++++++++--------- 9 files changed, 293 insertions(+), 293 deletions(-) diff --git a/docker/web/Dockerfile b/docker/web/Dockerfile index e9b3bd0de..30b2b0687 100644 --- a/docker/web/Dockerfile +++ b/docker/web/Dockerfile @@ -1,80 +1,80 @@ -############################################################################### -#---------------------------- IMPORT RUNTIME -----------------------------# -############################################################################### - -FROM codecompass:runtime as runtime - -############################################################################### -#------------------------ EXECUTABLE CONTAINER --------------------------# -############################################################################### - -FROM ubuntu:22.04 - -# tzdata package is installed implicitly in the following command. This package -# sets timezone interactively during the installation process. This environment -# variable prevents this interaction. -ARG DEBIAN_FRONTEND=noninteractive - -RUN set -x && apt-get update -qq \ - && apt-get install -qqy --no-install-recommends \ - llvm-15 \ - libboost-filesystem-dev libboost-log-dev libboost-program-options-dev \ - libsqlite3-dev \ - postgresql-server-dev-14 \ - default-jre \ - libgit2-dev \ - libldap-2.5-0 \ - libssl3 \ - libgvc6 \ - libthrift-dev \ - libpq5 \ - # To switch user and exec command. - gosu \ - tini \ - curl ca-certificates gnupg \ - wget \ - gcc-11 g++-11 \ - && ln -s /usr/bin/gcc-11 /usr/bin/gcc \ - && ln -s /usr/bin/g++-11 /usr/bin/g++ \ - && apt-get clean \ - && rm -rf /var/lib/apt/lists/ \ - && set +x - -# Install NodeJS from NodeSource. -RUN mkdir -p /etc/apt/keyrings && \ - curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ - echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ - apt-get update -qq && \ - apt-get install -y nodejs && \ - apt-get clean && \ - rm -rf /var/lib/apt/lists/ - -# Copy ODB install directory. -COPY --from=runtime /opt/odb /opt/odb - -ARG CC_GID=960 -ARG CC_UID=960 - -ENV CC_GID ${CC_GID} -ENV CC_UID ${CC_UID} - -# Create user and group for CodeCompass. -RUN groupadd --system codecompass --gid ${CC_GID} && \ - useradd --system --no-log-init --no-create-home --uid ${CC_UID} --gid codecompass codecompass - -# Copy CodeCompass install directory. (Change permission of the CodeCompass package.) -# TODO: only the webserver's binaries should be included in this image. -COPY --from=runtime --chown=codecompass:codecompass /codecompass /codecompass - -ENV PATH="/codecompass/bin:/opt/odb/bin:$PATH" - -COPY --chown=codecompass:codecompass docker/web/entrypoint.sh /usr/local/bin/entrypoint.sh -RUN chmod a+x /usr/local/bin/entrypoint.sh - - -EXPOSE 8080 - -ENTRYPOINT ["tini", "--", "/usr/local/bin/entrypoint.sh"] - -CMD ["sh", "-c", "node ../../webgui-new/scripts/patch-basepath.js && CodeCompass_webserver -w /workspace -p 8080"] - +############################################################################### +#---------------------------- IMPORT RUNTIME -----------------------------# +############################################################################### + +FROM codecompass:runtime as runtime + +############################################################################### +#------------------------ EXECUTABLE CONTAINER --------------------------# +############################################################################### + +FROM ubuntu:22.04 + +# tzdata package is installed implicitly in the following command. This package +# sets timezone interactively during the installation process. This environment +# variable prevents this interaction. +ARG DEBIAN_FRONTEND=noninteractive + +RUN set -x && apt-get update -qq \ + && apt-get install -qqy --no-install-recommends \ + llvm-15 \ + libboost-filesystem-dev libboost-log-dev libboost-program-options-dev \ + libsqlite3-dev \ + postgresql-server-dev-14 \ + default-jre \ + libgit2-dev \ + libldap-2.5-0 \ + libssl3 \ + libgvc6 \ + libthrift-dev \ + libpq5 \ + # To switch user and exec command. + gosu \ + tini \ + curl ca-certificates gnupg \ + wget \ + gcc-11 g++-11 \ + && ln -s /usr/bin/gcc-11 /usr/bin/gcc \ + && ln -s /usr/bin/g++-11 /usr/bin/g++ \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/ \ + && set +x + +# Install NodeJS from NodeSource. +RUN mkdir -p /etc/apt/keyrings && \ + curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg --dearmor -o /etc/apt/keyrings/nodesource.gpg && \ + echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_18.x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list && \ + apt-get update -qq && \ + apt-get install -y nodejs && \ + apt-get clean && \ + rm -rf /var/lib/apt/lists/ + +# Copy ODB install directory. +COPY --from=runtime /opt/odb /opt/odb + +ARG CC_GID=960 +ARG CC_UID=960 + +ENV CC_GID ${CC_GID} +ENV CC_UID ${CC_UID} + +# Create user and group for CodeCompass. +RUN groupadd --system codecompass --gid ${CC_GID} && \ + useradd --system --no-log-init --no-create-home --uid ${CC_UID} --gid codecompass codecompass + +# Copy CodeCompass install directory. (Change permission of the CodeCompass package.) +# TODO: only the webserver's binaries should be included in this image. +COPY --from=runtime --chown=codecompass:codecompass /codecompass /codecompass + +ENV PATH="/codecompass/bin:/opt/odb/bin:$PATH" + +COPY --chown=codecompass:codecompass docker/web/entrypoint.sh /usr/local/bin/entrypoint.sh +RUN chmod a+x /usr/local/bin/entrypoint.sh + + +EXPOSE 8080 + +ENTRYPOINT ["tini", "--", "/usr/local/bin/entrypoint.sh"] + +CMD ["sh", "-c", "node ../../webgui-new/scripts/patch-basepath.js && CodeCompass_webserver -w /workspace -p 8080"] + diff --git a/docker/web/entrypoint.sh b/docker/web/entrypoint.sh index 1c79a33f0..8dfea219d 100644 --- a/docker/web/entrypoint.sh +++ b/docker/web/entrypoint.sh @@ -1,12 +1,12 @@ -#!/bin/bash - -if [ "$(id -u)" == '0' ]; then - # Change the owner of the workspace directory - mkdir -p /workspace - chown codecompass:codecompass /workspace - - # Execute this script again with codecompass user. - exec gosu codecompass "$0" "$@" -fi - -exec "$@" +#!/bin/bash + +if [ "$(id -u)" == '0' ]; then + # Change the owner of the workspace directory + mkdir -p /workspace + chown codecompass:codecompass /workspace + + # Execute this script again with codecompass user. + exec gosu codecompass "$0" "$@" +fi + +exec "$@" diff --git a/scripts/CodeCompass_logger b/scripts/CodeCompass_logger index 4ff2cd028..61282a317 100644 --- a/scripts/CodeCompass_logger +++ b/scripts/CodeCompass_logger @@ -1,28 +1,28 @@ -#!/usr/bin/env bash - -if [ $# -ne 2 ]; then - echo "Usage: $0 \"\"" >&2 - exit 1 -fi - -binDir=$(dirname $0) -jsonFile=$1 -shift - -if [ -f $jsonFile ]; then - echo "The compilation database already exists!" >&2 - exit 1 -fi - -export LDLOGGER_HOME=$binDir - -source $binDir/../share/codecompass/setldlogenv.sh $jsonFile; \ - bash -c "$@" - -if [ ! -f $jsonFile ]; then - echo "Failed to log the build commands!" >&2 - exit 1 -elif [ $(wc -c <$jsonFile) -le 5 ]; then - echo "Failed to log the build commands: the build log is empty!" >&2 - exit 1 -fi +#!/usr/bin/env bash + +if [ $# -ne 2 ]; then + echo "Usage: $0 \"\"" >&2 + exit 1 +fi + +binDir=$(dirname $0) +jsonFile=$1 +shift + +if [ -f $jsonFile ]; then + echo "The compilation database already exists!" >&2 + exit 1 +fi + +export LDLOGGER_HOME=$binDir + +source $binDir/../share/codecompass/setldlogenv.sh $jsonFile; \ + bash -c "$@" + +if [ ! -f $jsonFile ]; then + echo "Failed to log the build commands!" >&2 + exit 1 +elif [ $(wc -c <$jsonFile) -le 5 ]; then + echo "Failed to log the build commands: the build log is empty!" >&2 + exit 1 +fi diff --git a/scripts/install_latest_build2.sh b/scripts/install_latest_build2.sh index d04d9a81e..2cc8cfa78 100644 --- a/scripts/install_latest_build2.sh +++ b/scripts/install_latest_build2.sh @@ -1,57 +1,57 @@ -#!/bin/bash - -if [ $# -lt 1 ]; then - echo "No installation directory was provided for build2!" 1>&2 - exit 1 -fi - -## download phase - -install_dir=$1 -toolchain_file="toolchain.sha256" -if [ "$1" = "--version" ]; then - wget -q --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" -else - wget --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" -fi - - -version_line=$(grep -m 1 '' "$toolchain_file") -version_number=$(echo "$version_line" | awk '{print $2}') - -### Return with version string only without actually installing build2 if "--version" flag is specified. -if [ "$1" = "--version" ]; then - echo "${version_number}" - rm -f "${toolchain_file}" - exit 0 -fi - -version_to_install=build2-install-${version_number}.sh -download_url=https://download.build2.org/${version_number}/${version_to_install} -wget --no-verbose --no-clobber "${download_url}" -O "${version_to_install}" - -## sha256 check phase - -line_with_version=$(grep "$version_to_install" "$toolchain_file") -checksum_for_version=$(echo "$line_with_version" | awk '{print $1}') - -if echo "${checksum_for_version} ${version_to_install}" | sha256sum -c; then - echo "Build2 installer for version ${version_number} has been downloaded!" -else - echo "Expected checksum for build2 installer version ${version_number} doesn't match! Probably the file has been corrupted! Please install it manually!" 1>&2 - echo "Expected: ${checksum_for_version}" 1>&2 - rm "$version_to_install" "$toolchain_file" - exit 1 -fi - -## install phase - -sh ${version_to_install} --yes --trust yes --jobs $(nproc) "${install_dir}" - -## cleanup phase - -compressed_toolchain="build2-toolchain-${version_number}.tar.xz" - -rm -f "${toolchain_file}" "${version_to_install}" "${compressed_toolchain}" - -echo "Build2 version ${version_number} has been successfully installed!" +#!/bin/bash + +if [ $# -lt 1 ]; then + echo "No installation directory was provided for build2!" 1>&2 + exit 1 +fi + +## download phase + +install_dir=$1 +toolchain_file="toolchain.sha256" +if [ "$1" = "--version" ]; then + wget -q --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" +else + wget --no-verbose --no-clobber https://download.build2.org/toolchain.sha256 -O "${toolchain_file}" +fi + + +version_line=$(grep -m 1 '' "$toolchain_file") +version_number=$(echo "$version_line" | awk '{print $2}') + +### Return with version string only without actually installing build2 if "--version" flag is specified. +if [ "$1" = "--version" ]; then + echo "${version_number}" + rm -f "${toolchain_file}" + exit 0 +fi + +version_to_install=build2-install-${version_number}.sh +download_url=https://download.build2.org/${version_number}/${version_to_install} +wget --no-verbose --no-clobber "${download_url}" -O "${version_to_install}" + +## sha256 check phase + +line_with_version=$(grep "$version_to_install" "$toolchain_file") +checksum_for_version=$(echo "$line_with_version" | awk '{print $1}') + +if echo "${checksum_for_version} ${version_to_install}" | sha256sum -c; then + echo "Build2 installer for version ${version_number} has been downloaded!" +else + echo "Expected checksum for build2 installer version ${version_number} doesn't match! Probably the file has been corrupted! Please install it manually!" 1>&2 + echo "Expected: ${checksum_for_version}" 1>&2 + rm "$version_to_install" "$toolchain_file" + exit 1 +fi + +## install phase + +sh ${version_to_install} --yes --trust yes --jobs $(nproc) "${install_dir}" + +## cleanup phase + +compressed_toolchain="build2-toolchain-${version_number}.tar.xz" + +rm -f "${toolchain_file}" "${version_to_install}" "${compressed_toolchain}" + +echo "Build2 version ${version_number} has been successfully installed!" diff --git a/scripts/remover.sh b/scripts/remover.sh index bc1fc3079..eb376f555 100644 --- a/scripts/remover.sh +++ b/scripts/remover.sh @@ -1,11 +1,11 @@ -#!/bin/bash - -FILES=$(ls *.js) - -for FILE in $FILES -do - if [ -f "$FILE" ] - then - sed -i -e "/if (typeof Int64 === 'undefined' && typeof require === 'function') {/,+2 d" "$FILE" - fi -done +#!/bin/bash + +FILES=$(ls *.js) + +for FILE in $FILES +do + if [ -f "$FILE" ] + then + sed -i -e "/if (typeof Int64 === 'undefined' && typeof require === 'function') {/,+2 d" "$FILE" + fi +done diff --git a/webgui-new/next.config.js b/webgui-new/next.config.js index 7733ec099..a838558fc 100644 --- a/webgui-new/next.config.js +++ b/webgui-new/next.config.js @@ -2,7 +2,7 @@ require('dotenv').config(); -const BASE_PLACEHOLDER = '__BASE_PATH__'; +const BASE_PLACEHOLDER = '/__URL_BASE_PATH__'; /** @type {import('next').NextConfig} */ const nextConfig = { diff --git a/webgui-new/scripts/patch-basepath.js b/webgui-new/scripts/patch-basepath.js index 514be2ec1..cba9304e2 100644 --- a/webgui-new/scripts/patch-basepath.js +++ b/webgui-new/scripts/patch-basepath.js @@ -1,18 +1,18 @@ -const { replaceInFileSync } = require('replace-in-file'); - -const PLACEHOLDER = '__BASE_PATH__'; -const NEW_BASE = process.env.APP_BASE_PATH || '/new'; - -console.log(`[patch-basepath] ${PLACEHOLDER} -> ${NEW_BASE}`); - -try { - const results = replaceInFileSync({ - files: ['out/**/*.html', 'out/**/*.js', 'out/**/*.json'], - from: new RegExp(PLACEHOLDER.replace(/\//g, '\\/'), 'g'), - to: NEW_BASE, - }); - console.log('[patch-basepath] modified files:', results.length); -} catch (err) { - console.error('[patch-basepath] error:', err); - process.exit(1); +const { replaceInFileSync } = require('replace-in-file'); + +const PLACEHOLDER = '/__URL_BASE_PATH__'; +const NEW_BASE = process.env.APP_BASE_PATH || '/new'; + +console.log(`[patch-basepath] ${PLACEHOLDER} -> ${NEW_BASE}`); + +try { + const results = replaceInFileSync({ + files: ['out/**/*.html', 'out/**/*.js', 'out/**/*.json'], + from: new RegExp(PLACEHOLDER.replace(/\//g, '\\/'), 'g'), + to: NEW_BASE, + }); + console.log('[patch-basepath] modified files:', results.length); +} catch (err) { + console.error('[patch-basepath] error:', err); + process.exit(1); } \ No newline at end of file diff --git a/webgui-new/src/server.ts b/webgui-new/src/server.ts index b0dbf196d..c795bcfde 100644 --- a/webgui-new/src/server.ts +++ b/webgui-new/src/server.ts @@ -1,34 +1,34 @@ -import dotenv from 'dotenv'; -import express from 'express'; -import next from 'next'; -import { createProxyMiddleware } from 'http-proxy-middleware'; - -dotenv.config({ path: '.env.local' }); -dotenv.config(); - -const main = async () => { - const app = express(); - const port = parseInt(process.env.DEVSERVER_PORT as string); - const nextApp = next({ dev: process.env.NODE_ENV !== 'production' }); - - const nextHandler = nextApp.getRequestHandler(); - - const proxyHandler = createProxyMiddleware({ - target: process.env.BACKEND_URL, - changeOrigin: true, - pathFilter: ['**/*Service', '**/ga.txt'], - pathRewrite: { - '^/[^/]+/(.+Service)$': '/$1', - '^/ga.txt' : '/ga.txt' - }, - }); - - app.use("/", proxyHandler); - app.get('*', (req, res) => nextHandler(req, res)); - - await nextApp.prepare(); - - app.listen(port, () => console.log(`> Ready on localhost:${port}`)); -}; - -main(); +import dotenv from 'dotenv'; +import express from 'express'; +import next from 'next'; +import { createProxyMiddleware } from 'http-proxy-middleware'; + +dotenv.config({ path: '.env.local' }); +dotenv.config(); + +const main = async () => { + const app = express(); + const port = parseInt(process.env.DEVSERVER_PORT as string); + const nextApp = next({ dev: process.env.NODE_ENV !== 'production' }); + + const nextHandler = nextApp.getRequestHandler(); + + const proxyHandler = createProxyMiddleware({ + target: process.env.BACKEND_URL, + changeOrigin: true, + pathFilter: ['**/*Service', '**/ga.txt'], + pathRewrite: { + '^/[^/]+/(.+Service)$': '/$1', + '^/ga.txt' : '/ga.txt' + }, + }); + + app.use("/", proxyHandler); + app.get('*', (req, res) => nextHandler(req, res)); + + await nextApp.prepare(); + + app.listen(port, () => console.log(`> Ready on localhost:${port}`)); +}; + +main(); diff --git a/webgui-new/thrift-codegen.sh b/webgui-new/thrift-codegen.sh index e724487ac..17787bf43 100644 --- a/webgui-new/thrift-codegen.sh +++ b/webgui-new/thrift-codegen.sh @@ -1,53 +1,53 @@ -THRIFT_SOURCE="../" - -while [[ $# -gt 0 ]]; do - case "$1" in - --thrift-source) - THRIFT_SOURCE="$2" - shift 2 - ;; - *) - echo "Unknown option: $1" - exit 1 - ;; - esac -done - -rm -rf ./generated -rm -rf ./thrift - -mkdir -p thrift - -for file in $(find "$THRIFT_SOURCE/service/" -type f -name '*.thrift'); do - filename=$(basename "$file") - echo "Installing $filename" - if [ ! -f "./thrift/$filename" ]; then - cp "$file" "./thrift/" - fi -done - -for file in $(find "$THRIFT_SOURCE/plugins/" -type f -name '*.thrift'); do - filename=$(basename "$file") - echo "Installing $filename" - if [ ! -f "./thrift/$filename" ]; then - cp "$file" "./thrift/" - fi -done - -# Fix include paths -for file in $(find ./thrift -type f -name '*.thrift'); do - sed -i 's/include "\(.*\)\/\([^\/]*\)"/include "\2"/g' "$file" -done - -npm run thrift-ts -mv codegen generated -rm -rf ./thrift - -for file in $(find ./generated -type f -name '*.ts'); do - sed -i 's/import Int64 = require("node-int64");/import Int64 from "node-int64";/' "$file" -done - -# Resolve conflicting import in SearchService.ts -sed -i 's/import \* as SearchResult from "\.\/SearchResult";/import \* as SearchRes from "\.\/SearchResult";/g' ./generated/SearchService.ts -sed -i 's/SearchResult\.SearchResult/SearchRes.SearchResult/g' ./generated/SearchService.ts - +THRIFT_SOURCE="../" + +while [[ $# -gt 0 ]]; do + case "$1" in + --thrift-source) + THRIFT_SOURCE="$2" + shift 2 + ;; + *) + echo "Unknown option: $1" + exit 1 + ;; + esac +done + +rm -rf ./generated +rm -rf ./thrift + +mkdir -p thrift + +for file in $(find "$THRIFT_SOURCE/service/" -type f -name '*.thrift'); do + filename=$(basename "$file") + echo "Installing $filename" + if [ ! -f "./thrift/$filename" ]; then + cp "$file" "./thrift/" + fi +done + +for file in $(find "$THRIFT_SOURCE/plugins/" -type f -name '*.thrift'); do + filename=$(basename "$file") + echo "Installing $filename" + if [ ! -f "./thrift/$filename" ]; then + cp "$file" "./thrift/" + fi +done + +# Fix include paths +for file in $(find ./thrift -type f -name '*.thrift'); do + sed -i 's/include "\(.*\)\/\([^\/]*\)"/include "\2"/g' "$file" +done + +npm run thrift-ts +mv codegen generated +rm -rf ./thrift + +for file in $(find ./generated -type f -name '*.ts'); do + sed -i 's/import Int64 = require("node-int64");/import Int64 from "node-int64";/' "$file" +done + +# Resolve conflicting import in SearchService.ts +sed -i 's/import \* as SearchResult from "\.\/SearchResult";/import \* as SearchRes from "\.\/SearchResult";/g' ./generated/SearchService.ts +sed -i 's/SearchResult\.SearchResult/SearchRes.SearchResult/g' ./generated/SearchService.ts + From 15ffd103d71bd28bb929c142338056ecc5ceca3e Mon Sep 17 00:00:00 2001 From: Nani0002 Date: Thu, 18 Dec 2025 14:38:10 +0100 Subject: [PATCH 5/5] Fix CodeQL string escape issue --- webgui-new/scripts/patch-basepath.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/webgui-new/scripts/patch-basepath.js b/webgui-new/scripts/patch-basepath.js index cba9304e2..fc233cec1 100644 --- a/webgui-new/scripts/patch-basepath.js +++ b/webgui-new/scripts/patch-basepath.js @@ -5,11 +5,15 @@ const NEW_BASE = process.env.APP_BASE_PATH || '/new'; console.log(`[patch-basepath] ${PLACEHOLDER} -> ${NEW_BASE}`); +function escapeRegExp(s) { + return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); +} + try { const results = replaceInFileSync({ files: ['out/**/*.html', 'out/**/*.js', 'out/**/*.json'], - from: new RegExp(PLACEHOLDER.replace(/\//g, '\\/'), 'g'), - to: NEW_BASE, + from: new RegExp(escapeRegExp(PLACEHOLDER), 'g'), + to: () => NEW_BASE, }); console.log('[patch-basepath] modified files:', results.length); } catch (err) {