Skip to content

Commit ec05454

Browse files
committed
Modularize Neo4j configuration and support profile changes
1 parent 53721dc commit ec05454

12 files changed

Lines changed: 643 additions & 98 deletions

COMMANDS.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- [Validate Links in Markdown](#validate-links-in-markdown)
2020
- [Manual Setup](#manual-setup)
2121
- [Setup Neo4j Graph Database](#setup-neo4j-graph-database)
22+
- [Change Neo4j configuration template](#change-neo4j-configuration-template)
2223
- [Start Neo4j Graph Database](#start-neo4j-graph-database)
2324
- [Setup jQAssistant Java Code Analyzer](#setup-jqassistant-java-code-analyzer)
2425
- [Download Maven Artifacts to analyze](#download-maven-artifacts-to-analyze)
@@ -51,13 +52,16 @@
5152

5253
## Start an Analysis
5354

54-
An analysis is started with the script [analyze.sh](./scripts/analysis/analyze.sh).
55+
Before starting an analysis, setup your analysis as described in the [Getting Started](./GETTING_STARTED.md) guide.
56+
An analysis is then started with the script [analyze.sh](./scripts/analysis/analyze.sh).
5557
To run all analysis steps simple execute the following command:
5658

5759
```shell
5860
./../../scripts/analysis/analyze.sh
5961
```
6062

63+
**Hint:** Within the analysis workspace directory you can simply run `analyze.sh` directly without the `../../` prefix since the script is also available in the analysis workspace.
64+
6165
👉 See [scripts/examples/analyzeAxonFramework.sh](./scripts/examples/analyzeAxonFramework.sh) as an example script that combines all the above steps for a Java Project.
6266
👉 See [scripts/examples/analyzeReactRouter.sh](./scripts/examples/analyzeReactRouter.sh) as an example script that combines all the above steps for a Typescript Project.
6367
👉 See [Code Structure Analysis Pipeline](./.github/workflows/internal-java-code-analysis.yml) on how to do this within a GitHub Actions Workflow.
@@ -183,11 +187,23 @@ If any of the script are not allowed to be executed use `chmod +x ./scripts/` fo
183187
Use [setupNeo4j.sh](./scripts/setupNeo4j.sh) to download [Neo4j](https://neo4j.com/download-center) and install the plugins [APOC](https://neo4j.com/labs/apoc/4.4) and [Graph Data Science](https://neo4j.com/product/graph-data-science).
184188
This script requires the environment variable NEO4J_INITIAL_PASSWORD to be set. It sets the initial password with a temporary `NEO4J_HOME` environment variable to not interfere with a possibly globally installed Neo4j installation.
185189

190+
### Change Neo4j configuration template
191+
192+
Use [configureNeo4j.sh](./scripts/configureNeo4j.sh) to apply a different Neo4j configuration template from the [scripts/configuration](./scripts/configuration/) directory. This can be useful to optimize Neo4j for different workloads. Example:
193+
194+
```shell
195+
NEO4J_CONFIG_TEMPLATE=template-neo4j-high-memory.conf ./scripts/configureNeo4j.sh
196+
```
197+
198+
**Hint:** In case you want to switch to the high memory profile as in the example, there is a simpler solution. Just run `useNeo4jHighMemoryProfile.sh` from the analysis workspace directory which will set the environment variable `NEO4J_CONFIG_TEMPLATE` and run `configureNeo4j.sh` for you.
199+
186200
### Start Neo4j Graph Database
187201

188202
Use [startNeo4j.sh](./scripts/startNeo4j.sh) to start the locally installed [Neo4j](https://neo4j.com/download-center) Graph database.
189203
It runs the script with a temporary `NEO4J_HOME` environment variable to not interfere with a possibly globally installed Neo4j installation.
190204

205+
**Hint:** Within the analysis workspace directory you can simply run `startNeo4j.sh` directly without the `../../` prefix since the script is also available in the analysis workspace.
206+
191207
### Setup jQAssistant Java Code Analyzer
192208

193209
Use [setupJQAssistant.sh](./scripts/setupJQAssistant.sh) to download [jQAssistant](https://jqassistant.github.io/jqassistant/current).
@@ -346,6 +362,8 @@ execute_cypher ./cypher/Get_Graph_Data_Science_Library_Version.cypher a=1
346362

347363
Use [stopNeo4j.sh](./scripts/stopNeo4j.sh) to stop the locally running Neo4j Graph Database. It does nothing if the database is already stopped. It runs the script with a temporary `NEO4J_HOME` environment variable to not interfere with a possibly globally installed Neo4j installation.
348364

365+
**Hint:** Within the analysis workspace directory you can run `startNeo4j.sh` directly without the `../../` prefix since the script is also directly available in the analysis workspace.
366+
349367
## Jupyter Notebook
350368

351369
### Create a report with executeJupyterNotebookReport.sh

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,14 @@ The [Code Structure Analysis Pipeline](./.github/workflows/internal-java-code-an
300300
./../../scripts/analysis/analyze.sh --profile Neo4j-latest-high-memory
301301
```
302302

303+
- How can i increase the memory (RAM) consumption afterwards, when the setup is already done?
304+
👉 Simply run `useNeo4jHighMemoryProfile.sh` in your analysis working directory, or:
305+
306+
```shell
307+
./../../scripts/useNeo4jHighMemoryProfile.sh
308+
```
309+
310+
303311
## 🕸 Web References
304312

305313
- [code-graph-analysis-examples](https://github.com/JohT/code-graph-analysis-examples)

init.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ mkdir -p "./${SOURCE_DIRECTORY}"
7979
createForwardingScript "./../../scripts/analysis/analyze.sh"
8080
createForwardingScript "./../../scripts/startNeo4j.sh"
8181
createForwardingScript "./../../scripts/stopNeo4j.sh"
82+
createForwardingScript "./../../scripts/useNeo4jHighMemoryProfile.sh"
8283

8384
source "${SCRIPTS_DIR}/scripts/checkCompatibility.sh"
8485

scripts/configuration/template-neo4j-high-memory.conf

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
2-
# The following static configuration entries were taken from "template-neo4j.conf".
3-
41
# Anonymous usage data reporting
52
dbms.usage_report.enabled=false
63

scripts/configuration/template-neo4j-low-memory.conf

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
2-
# The following static configuration entries were taken from "template-neo4j.conf".
3-
41
# Anonymous usage data reporting
52
dbms.usage_report.enabled=false
63

scripts/configuration/template-neo4j-v4-low-memory.conf

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
2-
# The following static configuration entries were taken from "template-neo4j.conf".
3-
41
# List of procedures and user defined functions that are allowed
52
# full access to the database through unsupported/insecure internal APIs.
63
dbms.security.procedures.unrestricted=apoc.*,gds.*

scripts/configuration/template-neo4j-v4.conf

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
2-
# The following static configuration entries were taken from "template-neo4j.conf".
3-
41
# List of procedures and user defined functions that are allowed
52
# full access to the database through unsupported/insecure internal APIs.
63
dbms.security.procedures.unrestricted=apoc.*,gds.*

scripts/configuration/template-neo4j.conf

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
2-
# The following static configuration entries were taken from "template-neo4j.conf".
3-
41
# Anonymous usage data reporting
52
dbms.usage_report.enabled=false
63

scripts/configureNeo4j.sh

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
#!/usr/bin/env bash
2+
3+
# Configures a (local) Neo4j Community Edition Graph Database (https://neo4j.com/download-center/#community).
4+
#
5+
# Main input is the environment variable NEO4J_CONFIG_TEMPLATE:
6+
# - The name of the template file ("scripts/configuration" folder) for the Neo4j configuration.
7+
# - Defaults to "template-neo4j.conf".
8+
# - The template configuration will be appended to the end of the Neo4j configuration file.
9+
#
10+
# Prerequisites:
11+
# - Intended to be sourced from within another script like the setupNeo4j.sh script
12+
# - Neo4j has been installed
13+
# - The tools directory has been created
14+
#
15+
# Example Usage:
16+
# - NEO4J_CONFIG_TEMPLATE=template-neo4j-high-memory.conf ./../../scripts/configureNeo4j.sh
17+
#
18+
# When run for the first time, the original configuration will be backed up and all configuration entries will be set.
19+
# When run again (re-configuration), the template configuration at the end if the script is executed again.
20+
#
21+
# Requires operatingSystemFunctions.sh
22+
23+
# Fail on any error ("-e" = exit on first error, "-o pipefail" exist on errors within piped commands)
24+
set -o errexit -o pipefail
25+
26+
NEO4J_EDITION=${NEO4J_EDITION:-"community"} # Choose "community" or "enterprise"
27+
NEO4J_VERSION=${NEO4J_VERSION:-"2026.01.4"}
28+
29+
DATA_DIRECTORY=${DATA_DIRECTORY:-"$( pwd -P )/data"} # Path where Neo4j writes its data to (outside tools dir)
30+
RUNTIME_DIRECTORY=${RUNTIME_DIRECTORY:-"$( pwd -P )/runtime"} # Path where Neo4j puts runtime data to (e.g. logs) (outside tools dir)
31+
# Only apply the default tools directory when TOOLS_DIRECTORY is truly unset
32+
# (so that an explicit empty value triggers validation failures in tests).
33+
if [ -z "${TOOLS_DIRECTORY+x}" ]; then
34+
TOOLS_DIRECTORY="tools"
35+
fi
36+
# IMPORT_DIRECTORY default when unset
37+
if [ -z "${IMPORT_DIRECTORY+x}" ]; then
38+
IMPORT_DIRECTORY="$( pwd -P )/import"
39+
fi
40+
# Only apply the default shared downloads directory when truly unset
41+
if [ -z "${SHARED_DOWNLOADS_DIRECTORY+x}" ]; then
42+
SHARED_DOWNLOADS_DIRECTORY="$(dirname "$( pwd )")/downloads"
43+
fi
44+
45+
NEO4J_HTTP_PORT=${NEO4J_HTTP_PORT:-"7474"} # Neo4j HTTP API port for executing queries
46+
NEO4J_HTTPS_PORT=${NEO4J_HTTPS_PORT:-"7473"} # Neo4j HTTPS port for encrypted querying
47+
NEO4J_BOLT_PORT=${NEO4J_BOLT_PORT:-"7687"} # Neo4j's own "Bolt Protocol" port
48+
49+
NEO4J_CONFIG_TEMPLATE=${NEO4J_CONFIG_TEMPLATE:-"template-neo4j.conf"} # Name of the template file ("configuration" folder) for the Neo4j configuration. Defaults to "template-neo4j.conf".
50+
51+
## Get this "scripts" directory if not already set
52+
# Even if $BASH_SOURCE is made for Bourne-like shells it is also supported by others and therefore here the preferred solution.
53+
# CDPATH reduces the scope of the cd command to potentially prevent unintended directory changes.
54+
# This way non-standard tools like readlink aren't needed.
55+
SCRIPTS_DIR=${SCRIPTS_DIR:-$( CDPATH=. cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P )} # Repository directory containing the shell scripts
56+
SCRIPT_NAME="configureNeo4j"
57+
#echo "${SCRIPT_NAME}: SCRIPTS_DIR=${SCRIPTS_DIR}"
58+
59+
# Internal constants
60+
NEO4J_INSTALLATION_NAME="neo4j-${NEO4J_EDITION}-${NEO4J_VERSION}"
61+
NEO4J_INSTALLATION_DIRECTORY="${TOOLS_DIRECTORY}/${NEO4J_INSTALLATION_NAME}"
62+
NEO4J_CONFIG="${NEO4J_INSTALLATION_DIRECTORY}/conf/neo4j.conf"
63+
NEO4J_MAJOR_VERSION_NUMBER=$(echo "${NEO4J_VERSION}" | cut -d'.' -f1) # First part of the version number (=major version number)
64+
NEO4J_CONFIG_TEMPLATE_PATH="${SCRIPTS_DIR}/configuration/${NEO4J_CONFIG_TEMPLATE}"
65+
66+
# Include operation system functions like "convertPosixToWindowsPathIfNecessary".
67+
source "${SCRIPTS_DIR}/operatingSystemFunctions.sh"
68+
69+
fail() {
70+
local ERROR_COLOR='\033[0;31m' # red
71+
local DEFAULT_COLOR='\033[0m'
72+
local errorMessage="${1}"
73+
echo -e "${ERROR_COLOR}${SCRIPT_NAME}: Error: ${errorMessage}${DEFAULT_COLOR}" >&2
74+
exit 1
75+
}
76+
77+
insert_hint_that_the_configuration_is_script_managed() {
78+
local file="$1"
79+
local tempFile
80+
tempFile="$(mktemp)"
81+
82+
awk '
83+
BEGIN {
84+
separator_count = 0
85+
separator_pattern = "^#\\*{11,}$"
86+
}
87+
{
88+
if ($0 ~ separator_pattern) {
89+
separator_count++
90+
if (separator_count == 2) {
91+
print "#"
92+
print "# This file had been configured with the configureNeo4j.sh script of code-graph-analysis-pipeline."
93+
print "# Manual changes to this file might be overwritten when the script is executed again since the script is designed to update the configuration according to the template configuration."
94+
print "# Please check the documentation of the configureNeo4j.sh script for more details."
95+
}
96+
}
97+
98+
print
99+
}
100+
' "${file}" > "${tempFile}" && mv "${tempFile}" "$file"
101+
}
102+
103+
append_configuration_from_template() {
104+
echo "${SCRIPT_NAME}: Appending configuration template ${NEO4J_CONFIG_TEMPLATE} (memory, procedure permissions, ...)"
105+
local EYE_CATCHER_COMMENT_PREFIX="# The following configuration entries were taken from"
106+
107+
# Check if a template configuration had already been appended by looking for the eye-catcher comment.
108+
# If it is already there, then delete the old template configuration including the eye-catcher and append the new one again to update it.
109+
# This way this function is idempotent, the configuration is always up to date with the template and there are no duplicate entries.
110+
if grep -q "^${EYE_CATCHER_COMMENT_PREFIX}" "${NEO4J_CONFIG}"; then
111+
echo "${SCRIPT_NAME}: Deleting old configuration that had been appended from the template before since the eye-catcher comment was found. This ensures that there are no duplicate entries and that the configuration is up to date with the template."
112+
sed -i.edit.backup "/^${EYE_CATCHER_COMMENT_PREFIX}/,/^# End of configuration from ${NEO4J_CONFIG_TEMPLATE}/d" "${NEO4J_CONFIG}"
113+
if grep -q '^$' "${NEO4J_CONFIG}"; then
114+
sed -i.edit.backup '$d' "${NEO4J_CONFIG}" # Delete the last line of the config if it is an empty line
115+
fi
116+
rm -f "${NEO4J_CONFIG}.edit.backup" # The backup is created even if not needed to be compatible with both GNU sed and BSD sed (e.g. on
117+
fi
118+
119+
# Append first an eye-catcher comment to the configuration file to indicate that the configuration is script-managed
120+
# and that manual changes might be overwritten.
121+
{
122+
echo ""
123+
echo "${EYE_CATCHER_COMMENT_PREFIX} '${NEO4J_CONFIG_TEMPLATE}' by the script ${SCRIPT_NAME}."
124+
echo "# WARNING: Manual changes below this line might be overwritten when the script is executed again."
125+
echo ""
126+
} >> "${NEO4J_CONFIG}"
127+
128+
cat "${NEO4J_CONFIG_TEMPLATE_PATH}" >> "${NEO4J_CONFIG}"
129+
}
130+
131+
NEO4J_INSTALLATION_ADVICE="Please install Neo4j first by running an analysis or by executing the setupNeo4j.sh script directly."
132+
133+
if [ -z "${TOOLS_DIRECTORY}" ]; then
134+
fail "Requires variable TOOLS_DIRECTORY to be set. If it is the current directory, then use a dot to reflect that."
135+
fi
136+
if [ ! -d "${TOOLS_DIRECTORY}" ]; then
137+
fail "Tools directory <${TOOLS_DIRECTORY}> does not exist. ${NEO4J_INSTALLATION_ADVICE}"
138+
fi
139+
140+
# Check if SHARED_DOWNLOADS_DIRECTORY variable is set
141+
if [ -z "${SHARED_DOWNLOADS_DIRECTORY}" ]; then
142+
fail "Requires variable SHARED_DOWNLOADS_DIRECTORY to be set. If it is the current directory, then use a dot to reflect that."
143+
fi
144+
if [ ! -d "${SHARED_DOWNLOADS_DIRECTORY}" ]; then
145+
fail "Shared downloads directory <${SHARED_DOWNLOADS_DIRECTORY}> does not exist. ${NEO4J_INSTALLATION_ADVICE}"
146+
fi
147+
148+
# Fail if Neo4j hadn't been downloaded yet
149+
if [ ! -d "${NEO4J_INSTALLATION_DIRECTORY}" ] ; then
150+
fail "${NEO4J_INSTALLATION_NAME} is not installed into ${TOOLS_DIRECTORY} yet. ${NEO4J_INSTALLATION_ADVICE}"
151+
fi
152+
153+
if [ ! -f "${NEO4J_CONFIG_TEMPLATE_PATH}" ]; then
154+
fail "Configuration template file ${NEO4J_CONFIG_TEMPLATE} does not exist in the scripts/configuration folder. Please make sure it exists and is correctly named:\n${NEO4J_CONFIG_TEMPLATE_PATH}"
155+
fi
156+
157+
# Create a backup of the original configuration file before any modification in case there is none yet.
158+
if [ ! -f "${NEO4J_CONFIG}.original.backup" ]; then
159+
cp "${NEO4J_CONFIG}" "${NEO4J_CONFIG}.original.backup"
160+
echo "${SCRIPT_NAME}: First time configuration. Created backup of the original configuration file at ${NEO4J_CONFIG}.original.backup"
161+
else
162+
echo "${SCRIPT_NAME}: Re-Configuration because ${NEO4J_CONFIG}.original.backup already exists."
163+
append_configuration_from_template
164+
echo "${SCRIPT_NAME}: Configuration template replaced successfully."
165+
return 0
166+
fi
167+
168+
echo "${SCRIPT_NAME}: Commenting out configuration properties that will later be replaced or are not needed"
169+
if [ "${NEO4J_MAJOR_VERSION_NUMBER}" -ge 5 ]; then
170+
sed -i.edit.backup '/^server\.directories\.import=/ s/^/# defined in the directory section further below #/' "${NEO4J_CONFIG}"
171+
sed -i.edit.backup '/^db\.tx_log\.rotation\.retention_policy=/ s/^/# defined in the transaction section further below #/' "${NEO4J_CONFIG}"
172+
else
173+
sed -i.edit.backup '/^dbms\.directories\.import=/ s/^/# defined in the directory section further below #/' "${NEO4J_CONFIG}"
174+
sed -i.edit.backup '/^dbms\.tx_log\.rotation\.retention_policy=/ s/^/# defined in the transaction section further below #/' "${NEO4J_CONFIG}"
175+
fi
176+
# Remove the edit backup file
177+
rm -f "${NEO4J_CONFIG}.edit.backup"
178+
179+
# Configure all paths with data that changes (database data, logs, ...) to be in the outside "data" directory
180+
# instead of inside the neo4j directory
181+
echo "${SCRIPT_NAME}: Configuring dynamic settings (data directories, ports, ...)"
182+
183+
neo4jDataPath=$(convertPosixToWindowsPathIfNecessary "${DATA_DIRECTORY}")
184+
neo4jLogsPath=$(convertPosixToWindowsPathIfNecessary "${RUNTIME_DIRECTORY}/logs")
185+
neo4jDumpsPath=$(convertPosixToWindowsPathIfNecessary "${RUNTIME_DIRECTORY}/dumps")
186+
neo4jRunPath=$(convertPosixToWindowsPathIfNecessary "${RUNTIME_DIRECTORY}/run")
187+
neo4jTransactionsPath=$(convertPosixToWindowsPathIfNecessary "${DATA_DIRECTORY}/transactions")
188+
neo4jImportPath=$(convertPosixToWindowsPathIfNecessary "${IMPORT_DIRECTORY}")
189+
190+
# Create import directory in case it doesn't exist.
191+
# The import needs to be configured even if its not used since it will be configured below and validated by Neo4j.
192+
mkdir -p "${IMPORT_DIRECTORY}"
193+
194+
if [ "${NEO4J_MAJOR_VERSION_NUMBER}" -ge 5 ]; then
195+
echo "setupNeo4j: Neo4j v5 or higher detected"
196+
{
197+
echo ""
198+
echo "# Paths of data directories in the installation (> v5)"
199+
echo "server.directories.data=${neo4jDataPath}"
200+
echo "server.directories.logs=${neo4jLogsPath}"
201+
echo "server.directories.dumps.root=${neo4jDumpsPath}"
202+
echo "server.directories.run=${neo4jRunPath}"
203+
echo "server.directories.transaction.logs.root=${neo4jTransactionsPath}"
204+
echo "server.directories.import=${neo4jImportPath}"
205+
echo ""
206+
echo "# Ports Configuration (> v5)"
207+
echo "server.bolt.listen_address=:${NEO4J_BOLT_PORT}"
208+
echo "server.bolt.advertised_address=:${NEO4J_BOLT_PORT}"
209+
echo "server.http.listen_address=:${NEO4J_HTTP_PORT}"
210+
echo "server.http.advertised_address=:${NEO4J_HTTP_PORT}"
211+
echo "server.https.listen_address=:${NEO4J_HTTPS_PORT}"
212+
echo "server.https.advertised_address=:${NEO4J_HTTPS_PORT}"
213+
} >> "${NEO4J_CONFIG}"
214+
else
215+
echo "setupNeo4j: Neo4j v4 or lower detected"
216+
{
217+
echo ""
218+
echo "# Paths of data directories in the installation"
219+
echo "dbms.directories.data=${neo4jDataPath}"
220+
echo "dbms.directories.logs=${neo4jLogsPath}"
221+
echo "dbms.directories.dumps.root=${neo4jDumpsPath}"
222+
echo "dbms.directories.run=${neo4jRunPath}"
223+
echo "dbms.directories.transaction.logs.root=${neo4jTransactionsPath}"
224+
echo "dbms.directories.import=${neo4jImportPath}"
225+
echo ""
226+
echo "# Ports Configuration"
227+
echo "dbms.connector.bolt.listen_address=:${NEO4J_BOLT_PORT}"
228+
echo "dbms.connector.bolt.advertised_address=:${NEO4J_BOLT_PORT}"
229+
echo "dbms.connector.http.listen_address=:${NEO4J_HTTP_PORT}"
230+
echo "dbms.connector.http.advertised_address=:${NEO4J_HTTP_PORT}"
231+
echo "dbms.connector.https.listen_address=:${NEO4J_HTTPS_PORT}"
232+
echo "dbms.connector.https.advertised_address=:${NEO4J_HTTPS_PORT}"
233+
} >> "${NEO4J_CONFIG}"
234+
fi
235+
236+
append_configuration_from_template
237+
insert_hint_that_the_configuration_is_script_managed "${NEO4J_CONFIG}"
238+
239+
echo "${SCRIPT_NAME}: Configuration successfully updated."

0 commit comments

Comments
 (0)