Skip to content

Commit 67b3ba7

Browse files
committed
feat(neo4j): read Neo4j connection options from env vars
The four --neo4j-* connection options now fall back to the standard NEO4J_URI / NEO4J_USERNAME / NEO4J_PASSWORD / NEO4J_DATABASE environment variables when the flag is omitted (explicit flag wins). Prefer the env var for the password so it doesn't land in shell history or the process list.
1 parent 1e5f3c9 commit 67b3ba7

3 files changed

Lines changed: 33 additions & 9 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- **`graph.cypher` snapshot** (default) — a self-contained Cypher script (constraints + indexes, a scoped wipe of the project's prior subgraph, then batched `UNWIND … MERGE`). Load it with `cypher-shell < graph.cypher`. Needs no extra dependencies.
1313
- **Live Bolt push** (`--neo4j-uri`) — an **incremental** writer: only modules whose `content_hash` changed are rewritten, and on a full run modules whose source file vanished are pruned. Requires the optional `neo4j` driver (`pip install 'codeanalyzer-python[neo4j]'`).
1414
- **`--emit schema`** — emit the machine-readable, version-stamped Neo4j schema contract (`schema.json`: node labels, relationships, properties, constraints, indexes). Needs no project; bundled in every release as a GitHub Release asset and checked in as `schema.neo4j.json`. A `schema_version` (`1.0.0`) is stamped onto every graph's `:Application` node.
15-
- **New CLI options** mirroring the TypeScript analyzer's entrypoints: `--emit {json,neo4j,schema}`, `--app-name`, `--neo4j-uri`, `--neo4j-user`, `--neo4j-password`, `--neo4j-database`. `-i/--input` is now optional (not required for `--emit schema`).
15+
- **New CLI options** mirroring the TypeScript analyzer's entrypoints: `--emit {json,neo4j,schema}`, `--app-name`, `--neo4j-uri`, `--neo4j-user`, `--neo4j-password`, `--neo4j-database`. `-i/--input` is now optional (not required for `--emit schema`). The four Neo4j connection options also read from the standard `NEO4J_URI` / `NEO4J_USERNAME` / `NEO4J_PASSWORD` / `NEO4J_DATABASE` environment variables when the flag is omitted (an explicit flag wins), so the password need not appear in shell history or the process list.
1616
- **`codeanalyzer.neo4j`** package: `catalog` (the single source-of-truth schema catalog), `project` (pure IR → graph rows), `cypher` (snapshot writer), `bolt` (incremental writer), and `rows` (the output-agnostic intermediate).
1717
- **Schema conformance test** (`test/test_neo4j_schema.py`, always runs) — asserts the emitter never produces a label/relationship/property the catalog doesn't declare, and that the checked-in `schema.neo4j.json` is regenerated.
1818
- **Neo4j Testcontainers integration test** (`test/test_neo4j_bolt.py`, opt-in via `RUN_CONTAINER_TESTS=1`) — spins up a real Neo4j and asserts the pushed graph, idempotent re-push, vanished-declaration cleanup, and full-run orphan pruning.

README.md

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,10 +95,10 @@ To view the available options and commands, run `codeanalyzer --help`. You shoul
9595
│ --emit [json|neo4j| Output target: json (analysis.json) | neo4j (graph.cypher or live │
9696
│ schema] Bolt push) | schema (the Neo4j schema.json contract). [default: json]│
9797
│ --app-name TEXT Logical application name for the graph :Application anchor. │
98-
│ --neo4j-uri TEXT Push the graph to a live Neo4j over Bolt; omit to write graph.cypher.
99-
│ --neo4j-user TEXT Neo4j username. [default: neo4j]
100-
│ --neo4j-password TEXT Neo4j password. [default: neo4j]
101-
│ --neo4j-database TEXT Neo4j database name (default: server default).
98+
│ --neo4j-uri TEXT Push the graph to a live Neo4j over Bolt. [env: NEO4J_URI]
99+
│ --neo4j-user TEXT Neo4j username. [env: NEO4J_USERNAME] [default: neo4j]
100+
│ --neo4j-password TEXT Neo4j password. [env: NEO4J_PASSWORD] [default: neo4j]
101+
│ --neo4j-database TEXT Neo4j database name. [env: NEO4J_DATABASE]
102102
│ --codeql --no-codeql Enable CodeQL-based analysis. [default: no-codeql] │
103103
│ --eager --lazy Enable eager or lazy analysis. Defaults to lazy. [default: lazy] │
104104
│ --cache-dir -c PATH Directory to store analysis cache. [default: None] │
@@ -183,6 +183,14 @@ By default this is printed to stdout in JSON; with `--output` it is written to `
183183
184184
Call-graph endpoints that aren't present in the symbol table (third-party / framework / RPC targets) are materialized as `:External` ghost nodes, mirroring the analyzer's own ghost-node behaviour.
185185
186+
The connection options also read from the standard Neo4j environment variables — `NEO4J_URI`, `NEO4J_USERNAME`, `NEO4J_PASSWORD`, `NEO4J_DATABASE` — when the corresponding flag is omitted (an explicit flag wins). Prefer the env var for the password so it doesn't land in shell history or the process list:
187+
188+
```sh
189+
export NEO4J_URI=bolt://localhost:7687
190+
export NEO4J_PASSWORD=secret
191+
codeanalyzer -i ./my-project --emit neo4j # credentials picked up from the environment
192+
```
193+
186194
### Schema contract
187195
188196
`--emit schema` writes the machine-readable, version-stamped Neo4j schema (`schema.json`: node labels, relationships, properties, constraints, and indexes). It needs no project and is checked into the repo as `schema.neo4j.json` and bundled in every release as a GitHub Release asset, so a consumer can validate producer/consumer compatibility without invoking the tool. The shape of the contract matches the [`codeanalyzer-typescript`](https://github.com/codellm-devkit/codeanalyzer-typescript) backend.

codeanalyzer/__main__.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,19 +53,35 @@ def main(
5353
Optional[str],
5454
typer.Option(
5555
"--neo4j-uri",
56+
envvar="NEO4J_URI",
5657
help="Push the graph to a live Neo4j over Bolt (incremental); omit to write "
57-
"graph.cypher.",
58+
"graph.cypher. [env: NEO4J_URI]",
5859
),
5960
] = None,
6061
neo4j_user: Annotated[
61-
str, typer.Option("--neo4j-user", help="Neo4j username.")
62+
str,
63+
typer.Option(
64+
"--neo4j-user",
65+
envvar="NEO4J_USERNAME",
66+
help="Neo4j username. [env: NEO4J_USERNAME]",
67+
),
6268
] = "neo4j",
6369
neo4j_password: Annotated[
64-
str, typer.Option("--neo4j-password", help="Neo4j password.")
70+
str,
71+
typer.Option(
72+
"--neo4j-password",
73+
envvar="NEO4J_PASSWORD",
74+
help="Neo4j password. Prefer the env var over the flag (the flag is visible in shell "
75+
"history / process list). [env: NEO4J_PASSWORD]",
76+
),
6577
] = "neo4j",
6678
neo4j_database: Annotated[
6779
Optional[str],
68-
typer.Option("--neo4j-database", help="Neo4j database name (default: server default)."),
80+
typer.Option(
81+
"--neo4j-database",
82+
envvar="NEO4J_DATABASE",
83+
help="Neo4j database name (default: server default). [env: NEO4J_DATABASE]",
84+
),
6985
] = None,
7086
using_codeql: Annotated[
7187
bool, typer.Option("--codeql/--no-codeql", help="Enable CodeQL-based analysis.")

0 commit comments

Comments
 (0)