Skip to content

Commit 435afaa

Browse files
committed
Merge branch '3.8-dev'
2 parents cf5bea4 + 5f696a4 commit 435afaa

40 files changed

+2900
-33
lines changed

docs/src/dev/developer/release.asciidoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,10 @@ during this period.
138138
... All tickets not marked "Fixed", "Done", or "Implemented" for their Resolution should not have a Fix Version
139139
assigned (use common sense when reviewing these tickets before removing the Fix Version as it is possible the incorrect
140140
Resolution may have been assigned).
141+
. Determine if Upgrade Documentation requires the addition of a prompt that users can provide to an AI coding agent to
142+
help them assess their upgrade task. Check the state of `docs/upgrade/prompts` to ensure there is an
143+
`upgrade-x.y.z-helper.md` for the current version and that it is up to date/tested. When it is determined as valid,
144+
ensure the prompt is reflected in the Upgrade Documentation itself. **This process needs to be refined.**
141145
. When all documentation changes are in place, use `bin/publish-docs.sh` to deploy a final `SNAPSHOT` representation
142146
of the docs and thus validate that there are no issues with the documentation generation process. Request review
143147
of the published documentation on the dev mailing list.
@@ -221,6 +225,10 @@ current release was under development as this new release will have those change
221225
. `git diff` and review the updated files
222226
. `mvn clean install` - need to build first so that the right version of the console is used with `bin/publish-docs.sh`
223227
.. This step should update the Gremlin.Net project file and Gremlin Javascript package file with the newly bumped version.
228+
. Determine if Upgrade Documentation requires the addition of a prompt that users can provide to an AI coding agent to
229+
help them assess their upgrade task. Check the state of `docs/upgrade/prompts` to ensure there is an
230+
`upgrade-x.y.z-helper.md` for the current version and that it is up to date/tested. When it is determined as valid,
231+
ensure the prompt is reflected in the Upgrade Documentation itself. **This process needs to be refined.**
224232
. `bin/process-docs.sh` and validate the generated documentation locally. Don't rely on "BUILD SUCCESS" - scroll up
225233
through logs to ensure there were no errors and view the HTML directly. Code blocks that did not execute properly have
226234
a gray background and do not show the results of the commands. In the event of failure, especially with `GraphComputer`

docs/src/upgrade/index.asciidoc

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ TinkerPop exposes.
3030
3131
include::release-4.x.x.asciidoc[]
3232
33-
include::release-3.8.x.asciidoc[]
33+
= TinkerPop 3.8.0
34+
35+
image::gremlin-67.png[width=185]
36+
37+
*Grix Greven*
38+
39+
include::release-3.8.0.asciidoc[]
3440
3541
include::release-3.7.x.asciidoc[]
3642
Lines changed: 107 additions & 32 deletions
Large diffs are not rendered by default.

docs/upgrade/README.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<!--
2+
3+
Licensed to the Apache Software Foundation (ASF) under one
4+
or more contributor license agreements. See the NOTICE file
5+
distributed with this work for additional information
6+
regarding copyright ownership. The ASF licenses this file
7+
to you under the Apache License, Version 2.0 (the
8+
"License"); you may not use this file except in compliance
9+
with the License. You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing,
14+
software distributed under the License is distributed on an
15+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16+
KIND, either express or implied. See the License for the
17+
specific language governing permissions and limitations
18+
under the License.
19+
20+
-->
21+
# TinkerPop Upgrade Risk Assessment Guide
22+
23+
Upgrading to TinkerPop versions can sometimes be a challenging process depending on the scope of changes for a
24+
particular version and the size and complexity of a particular codebase being upgraded. While TinkerPop provides Upgrade
25+
Documentation which outlines all the changes introduced, that still leaves the reader with the heavy job of determining
26+
where in their codebase the changes will need to be applied. TinkerPop provides a purpose-built prompt designed for use
27+
with advanced coding agents, such as Claude, GitHub Copilot, or Amazon Q Developer, which can intelligently analyze your
28+
project for areas that may break or behave unexpectedly after the upgrade. Leveraging AI, minimizes time spent on manual
29+
review, reduces the likelihood of missing subtle incompatibilities, and provides actionable advice for adapting existing
30+
code to the new version. This approach enables upgrades with greater confidence, efficiency, and accuracy, ensuring that
31+
all significant compatibility issues are surfaced and addressed early in the migration process.
32+
33+
This directory contains tools and testing to help build this release version-specific prompt and has the following
34+
structure:
35+
36+
```
37+
upgrade
38+
|-java [Sample application to test prompts against]
39+
|-prompts [LLM prompts and associated context]
40+
|-spec [The specification for the sample application]
41+
```

docs/upgrade/java/README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
////
2+
Licensed to the Apache Software Foundation (ASF) under one or more
3+
contributor license agreements. See the NOTICE file distributed with
4+
this work for additional information regarding copyright ownership.
5+
The ASF licenses this file to You under the Apache License, Version 2.0
6+
(the "License"); you may not use this file except in compliance with
7+
the License. You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
////
17+
### CMDB Graph API (Java, Micronaut 4, Gremlin Server)
18+
19+
This is a language/framework example project implementing the DevOps CMDB + Incident Knowledge Graph API described in `../spec/spec.md`. It connects remotely to a Gremlin Server and does not use any embedded graph.
20+
21+
Key facts:
22+
- Java 17
23+
- Micronaut 4
24+
- Apache TinkerPop 3.7.4 (gremlin-driver)
25+
- Deterministic dataset: `../spec/cmdb-data.gremlin`
26+
27+
Quick start (Gremlin Server via Docker):
28+
- From this directory (`docs/upgrade/java`):
29+
- Make helper executable (first time only): `chmod +x ./bin/gremlin-dev.sh`
30+
- Start server: `./bin/gremlin-dev.sh up`
31+
- Wait until ready: `./bin/gremlin-dev.sh wait`
32+
- Load dataset: `./bin/gremlin-dev.sh seed`
33+
- Or all-in-one reset: `./bin/gremlin-dev.sh reset`
34+
- Stop server: `./bin/gremlin-dev.sh down`
35+
36+
TEMPORARY QUICK START STEPS ON STARTUP:
37+
```
38+
# connect to the running container after: ./bin/gremlin-dev.sh up`
39+
docker exec -it cmdb-gremlin /bin/bash
40+
41+
# run the following in the container
42+
sed -i "s#org.apache.tinkerpop.gremlin.server.channel.WebSocketChannelizer#org.apache.tinkerpop.gremlin.server.channel.WsAndHttpChannelizer#" "conf/gremlin-server.yaml"
43+
exit
44+
45+
# restart the container
46+
docker container restart cmdb-gremlin
47+
```
48+
49+
The helper uses the Docker image `tinkerpop/gremlin-server:3.7.4` and loads data by posting each line of `../spec/cmdb-data.gremlin` to the Gremlin Server HTTP endpoint. No Gremlin Console is required.
50+
51+
Manual alternative (without the helper script):
52+
- Start server: `docker run -d --name cmdb-gremlin -p 8182:8182 tinkerpop/gremlin-server:3.7.4`
53+
- Wait for readiness (simple probe): `curl -sS -H 'Content-Type: application/json' -X POST http://localhost:8182/gremlin --data '{"gremlin":"g.V().limit(1)"}'`
54+
- Load dataset lines over HTTP (bash example):
55+
```bash
56+
while IFS= read -r line; do \
57+
[[ -z "$line" || "$line" =~ ^// || "$line" =~ ^# ]] && continue; \
58+
json=$(printf '%s' "$line" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g'); \
59+
curl -sS -H 'Content-Type: application/json' -X POST http://localhost:8182/gremlin --data "{\"gremlin\":\"$json\"}" >/dev/null; \
60+
done < ../spec/cmdb-data.gremlin
61+
```
62+
63+
Build & Run API:
64+
- Build: `mvn -q -f ./pom.xml clean package`
65+
- Run: `mvn -q -f ./pom.xml mn:run`
66+
- Run Integration Tests: `mvn test -Dtest=ServiceIT`
67+
68+
Endpoints (examples):
69+
- `GET http://localhost:8080/health/ready`
70+
- `GET http://localhost:8080/incidents/{incidentId}/blastRadius?depth=2`
71+
- `GET http://localhost:8080/services/{serviceId}/dependencies?depth=2`
72+
- `GET http://localhost:8080/services/{serviceId}/owners`
73+
- `GET http://localhost:8080/deployments/{deployId}/timeline`
74+
- `POST http://localhost:8080/alerts` with JSON `{ "alertId": "a1", "source": "prom", "metric": "cpu", "firedAt": 1700000000000 }`
75+
76+
Configuration:
77+
- See `src/main/resources/application.yml` for Gremlin connection settings.
78+
79+
License:
80+
- All files in this example are licensed under the Apache License, Version 2.0.
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
#!/usr/bin/env bash
2+
# Licensed to the Apache Software Foundation (ASF) under one or more
3+
# contributor license agreements. See the NOTICE file distributed with
4+
# this work for additional information regarding copyright ownership.
5+
# The ASF licenses this file to You under the Apache License, Version 2.0
6+
# (the "License"); you may not use this file except in compliance with
7+
# the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
set -euo pipefail
18+
19+
IMAGE="tinkerpop/gremlin-server:3.7.4"
20+
CONTAINER_NAME="cmdb-gremlin"
21+
HOST="localhost"
22+
PORT="8182"
23+
24+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
25+
# Dataset lives at docs/upgrade/spec/cmdb-data.gremlin relative to this script
26+
DATASET_PATH="${SCRIPT_DIR}/../../spec/cmdb-data.gremlin"
27+
28+
usage() {
29+
cat <<EOF
30+
Usage: $(basename "$0") <command>
31+
32+
Commands:
33+
up Start Gremlin Server Docker container (${IMAGE}) on port ${PORT}
34+
wait Wait until Gremlin Server is ready to accept requests
35+
seed Load dataset from ${DATASET_PATH} into the running server
36+
reset Recreate container (down + up) and seed dataset
37+
down Stop and remove the Gremlin Server container
38+
logs Tail container logs
39+
status Show container status
40+
41+
Environment overrides:
42+
IMAGE Docker image (default: ${IMAGE})
43+
CONTAINER_NAME Container name (default: ${CONTAINER_NAME})
44+
HOST Hostname for HTTP (default: ${HOST})
45+
PORT Host port for HTTP (default: ${PORT})
46+
EOF
47+
}
48+
49+
container_exists() { docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; }
50+
container_running() { docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; }
51+
52+
cmd_up() {
53+
if container_running; then
54+
echo "[INFO] Container ${CONTAINER_NAME} already running"
55+
return 0
56+
fi
57+
if container_exists; then
58+
echo "[INFO] Starting existing container ${CONTAINER_NAME}"
59+
docker start "${CONTAINER_NAME}" >/dev/null
60+
else
61+
echo "[INFO] Pulling image ${IMAGE} (if needed)"
62+
docker pull "${IMAGE}" >/dev/null || true
63+
echo "[INFO] Creating and starting container ${CONTAINER_NAME}"
64+
docker run -d --name "${CONTAINER_NAME}" -p "${PORT}:8182" "${IMAGE}" conf/gremlin-server.yaml >/dev/null
65+
fi
66+
echo "[INFO] Container is starting..."
67+
}
68+
69+
cmd_wait() {
70+
local timeout=90
71+
local start_ts
72+
start_ts=$(date +%s)
73+
echo "[INFO] Waiting for Gremlin Server at http://${HOST}:${PORT}/gremlin (timeout ${timeout}s)"
74+
while true; do
75+
# Require explicit HTTP 200 from the /gremlin endpoint
76+
local resp
77+
resp=$(curl -sS -w "%{http_code}" -H 'Content-Type: application/json' \
78+
-X POST "http://${HOST}:${PORT}/gremlin" \
79+
--data '{"gremlin":"g.inject(1).count()"}')
80+
local http_code
81+
http_code="${resp: -3}"
82+
if [[ "$http_code" == "200" ]]; then
83+
break
84+
fi
85+
sleep 2
86+
local now
87+
now=$(date +%s)
88+
if (( now - start_ts > timeout )); then
89+
echo "[ERROR] Timed out waiting for Gremlin Server to become ready (last HTTP code: ${http_code})" >&2
90+
exit 1
91+
fi
92+
done
93+
echo "[INFO] Gremlin Server is ready"
94+
}
95+
96+
cmd_seed() {
97+
if ! container_running; then
98+
echo "[ERROR] Container ${CONTAINER_NAME} is not running; start it with: $0 up && $0 wait" >&2
99+
exit 1
100+
fi
101+
if [[ ! -f "${DATASET_PATH}" ]]; then
102+
echo "[ERROR] Dataset not found at ${DATASET_PATH}" >&2
103+
exit 1
104+
fi
105+
echo "[INFO] Loading dataset from ${DATASET_PATH}"
106+
107+
# Clear existing graph first to ensure a clean, deterministic state
108+
clear_payload=$(printf '%s' "g.V().drop().iterate()" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')
109+
clear_resp=$(curl -sS -w "%{http_code}" -H 'Content-Type: application/json' \
110+
-X POST "http://${HOST}:${PORT}/gremlin" \
111+
--data "{\"gremlin\":\"${clear_payload}\"}")
112+
clear_code="${clear_resp: -3}"
113+
clear_body="${clear_resp::-3}"
114+
if [[ "$clear_code" != "200" ]]; then
115+
echo "[ERROR] Failed to clear graph with g.V().drop().iterate()" >&2
116+
echo "[ERROR] HTTP ${clear_code} Response: ${clear_body}" >&2
117+
exit 1
118+
fi
119+
120+
# Post each non-empty, non-comment line to the /gremlin endpoint
121+
local line_no=0
122+
while IFS= read -r raw_line || [[ -n "$raw_line" ]]; do
123+
line_no=$((line_no + 1))
124+
# Trim leading/trailing whitespace
125+
line="${raw_line%%[[:space:]]*}"
126+
line="${raw_line%$'\r'}" # strip CR if present
127+
trimmed="$(echo "$raw_line" | sed -e 's/^\s\+//' -e 's/\s\+$//')"
128+
129+
# Skip empty lines and comments (// ... or # ...)
130+
if [[ -z "${trimmed}" ]] || [[ "${trimmed}" =~ ^// ]] || [[ "${trimmed}" =~ ^# ]]; then
131+
continue
132+
fi
133+
134+
# Escape JSON special chars in the Gremlin line: backslash and quotes
135+
esc_line=$(printf '%s' "$trimmed" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g')
136+
137+
# Submit
138+
resp=$(curl -sS -w "%{http_code}" -H 'Content-Type: application/json' \
139+
-X POST "http://${HOST}:${PORT}/gremlin" \
140+
--data "{\"gremlin\":\"${esc_line}\"}")
141+
142+
http_code="${resp: -3}"
143+
body="${resp::-3}"
144+
145+
if [[ "$http_code" != "200" ]]; then
146+
echo "[ERROR] Failed at line ${line_no}: ${trimmed}" >&2
147+
echo "[ERROR] HTTP ${http_code} Response: ${body}" >&2
148+
exit 1
149+
fi
150+
done < "${DATASET_PATH}"
151+
152+
echo "[INFO] Dataset load complete"
153+
}
154+
155+
cmd_reset() {
156+
cmd_down || true
157+
cmd_up
158+
cmd_wait
159+
cmd_seed
160+
}
161+
162+
cmd_down() {
163+
if container_exists; then
164+
echo "[INFO] Stopping and removing ${CONTAINER_NAME}"
165+
docker rm -f "${CONTAINER_NAME}" >/dev/null || true
166+
else
167+
echo "[INFO] No existing container named ${CONTAINER_NAME}"
168+
fi
169+
}
170+
171+
cmd_logs() {
172+
if container_exists; then
173+
docker logs -f "${CONTAINER_NAME}"
174+
else
175+
echo "[INFO] No existing container named ${CONTAINER_NAME}"
176+
fi
177+
}
178+
179+
cmd_status() {
180+
if container_running; then
181+
echo "running"
182+
elif container_exists; then
183+
echo "stopped"
184+
else
185+
echo "absent"
186+
fi
187+
}
188+
189+
main() {
190+
local cmd="${1:-}" || true
191+
case "${cmd}" in
192+
up) cmd_up ;;
193+
wait) cmd_wait ;;
194+
seed) cmd_seed ;;
195+
reset) cmd_reset ;;
196+
down) cmd_down ;;
197+
logs) cmd_logs ;;
198+
status) cmd_status ;;
199+
-h|--help|help|"") usage ;;
200+
*) echo "Unknown command: ${cmd}"; usage; exit 1 ;;
201+
esac
202+
}
203+
204+
main "$@"

0 commit comments

Comments
 (0)