Metadata-Version: 2.4
Name: mule-analysis
Version: 1.0.0
Summary: Analyze Mule application estates — call graphs, frequency analysis, curl extraction
Project-URL: Homepage, https://github.com/KongHQ-CX/mule-analysis-tools
Author: Stephen Brown
License-Expression: MIT
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.10
Requires-Dist: lxml>=5.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Description-Content-Type: text/markdown

# mule-analysis

Analyze Mule application estates — call graphs, frequency analysis, and curl extraction.

Scans Mule 4 (and 3) XML source files, resolves `${property}` placeholders from `.properties` and `.yaml` configs, and produces structured output in multiple formats.

## Quick Start (uv)

No install required — just run from the project directory:

```bash
cd mule-analysis

# Extract curl commands from a Mule app
uv run mule-curl-extract /path/to/apps -r

# Frequency analysis
uv run mule-call-frequency /path/to/apps

# Call graph
uv run mule-call-graph /path/to/apps --format dot -o graph.dot
```

`uv run` reads `pyproject.toml`, resolves dependencies into an ephemeral environment, and runs the command. Nothing is installed globally.

## Installation

### From PyPI

```bash
pip install mule-analysis

# Then run directly
mule-curl-extract /path/to/apps -r
```

### From source (development)

```bash
uv sync --extra dev
```

Requires Python 3.10+.

## CLI Tools

### `mule-curl-extract`

Extract outbound HTTP/SOAP calls from Mule apps and generate ready-to-run curl commands.

```bash
# Scan a single Mule app
uv run mule-curl-extract /path/to/mule-app

# Scan all apps under a directory
uv run mule-curl-extract /path/to/apps --recursive

# Output as YAML
uv run mule-curl-extract /path/to/apps -r --format yaml

# Write to file
uv run mule-curl-extract /path/to/apps -r -o curls.sh
```

Resolves `${property}` and `p('property')` placeholders, extracts basic/bearer auth, and converts DataWeave transform bodies into sample JSON for curl `-d` flags.

### `mule-call-frequency`

Analyze call frequency across a Mule application estate.

```bash
# Text report (default)
uv run mule-call-frequency /path/to/apps

# YAML output
uv run mule-call-frequency /path/to/apps --format yaml -o report.yaml

# Custom layer classification
uv run mule-call-frequency /path/to/apps --layer-config layers.yaml
```

Reports include:
- App inventory with layer classification (experience / process / system)
- Backend system frequency (which systems are called, how often)
- Inter-app call graph (EL → PL → SL)
- Endpoint hotspots (called from multiple apps/flows)
- Shared sub-flow usage

### `mule-call-graph`

Generate a machine-readable call graph of app-to-app and app-to-backend connections.

```bash
# Mermaid (default) — renders in GitHub, GitLab, Notion
uv run mule-call-graph /path/to/apps

# Graphviz DOT — render with: dot -Tpng graph.dot -o graph.png
uv run mule-call-graph /path/to/apps --format dot -o graph.dot

# JSON adjacency list
uv run mule-call-graph /path/to/apps --format json -o graph.json

# CSV edge list
uv run mule-call-graph /path/to/apps --format csv -o edges.csv

# Mule-to-Mule only (exclude external backends)
uv run mule-call-graph /path/to/apps --mule-only

# Custom layer classification
uv run mule-call-graph /path/to/apps --layer-config layers.yaml
```

## Package Structure

```
src/mule_analysis/
├── xml_helpers.py          # XML namespace helpers, constants
├── models/                 # Data models (dataclasses)
│   ├── app.py              # MuleApp
│   ├── backend.py          # BackendConfig, HttpRequest, SoapCall
│   ├── graph.py            # Node, Edge, CallGraph
│   └── frequency.py        # FrequencyReport, EndpointHotspot, ...
├── parsers/                # File IO → models
│   ├── app_discovery.py    # find_mule_apps()
│   ├── properties.py       # .properties + .yaml loading & resolution
│   └── mule_xml.py         # HTTP configs, requests, WSC from Mule XML
├── analysis/               # Models → models (pure functions)
│   ├── layer_classifier.py # App name → experience/process/system (configurable)
│   ├── curl_generator.py   # BackendConfig + HttpRequest → curl string
│   ├── frequency.py        # Multi-app frequency aggregation
│   └── graph_builder.py    # Multi-app call graph construction
├── output/                 # Models → formatted strings
│   ├── curl_output.py      # Shell script with curl commands
│   ├── yaml_output.py      # YAML
│   ├── text_output.py      # Human-readable tables
│   ├── dot_output.py       # Graphviz DOT
│   ├── mermaid_output.py   # Mermaid flowchart
│   ├── csv_output.py       # CSV edge list
│   └── json_output.py      # JSON
└── cli/                    # CLI entry points (thin wrappers)
    ├── curl_extract.py     # mule-curl-extract
    ├── call_frequency.py   # mule-call-frequency
    └── call_graph.py       # mule-call-graph
```

### Design Principles

- **No function does both IO and computation.** Parsers read files → return models. Analysis takes models → returns models. Output takes models → returns strings.
- **All data models are plain dataclasses** with typed fields — no methods with side effects.
- **All analysis functions are standalone** — no class methods, no inheritance.
- **Each output format is a separate module.**

## Testing

```bash
make test
```

Or directly:

```bash
uv run --extra dev python -m pytest
```

Coverage is enforced at 100% (branch coverage) via `pyproject.toml`.

## Layer Classification

Apps are classified into experience/process/system layers by splitting the app name on `-` and `_` and matching segments against known abbreviations.

### Default Segments

| Segment | Layer |
|---|---|
| `el`, `exp`, `eapi`, `xapi`, `experience` | Experience |
| `pl`, `prc`, `papi`, `process` | Process |
| `sl`, `sys`, `sapi`, `system` | System |

This means all of these classify correctly out of the box:

```
acme-el-orders       → experience    (segment: el)
acme-exp-api         → experience    (segment: exp)
orders-eapi          → experience    (segment: eapi)
acme-pl-orders       → process       (segment: pl)
customers-prc-svc    → process       (segment: prc)
orders-papi          → process       (segment: papi)
acme-sl-billing      → system        (segment: sl)
customers-sys-api    → system        (segment: sys)
billing-sapi         → system        (segment: sapi)
```

Inter-app calls are detected by matching CloudHub hostnames (`mule-worker-internal-{env}-{app}-{version}.cloudhub.io`) and ALB patterns (`mu-alb-{layer}.`).

### Custom Configuration

Override the defaults by passing a `--layer-config` YAML file to `mule-call-frequency` or `mule-call-graph`:

```bash
uv run mule-call-graph /path/to/apps --layer-config layers.yaml
```

Example `layers.yaml`:

```yaml
# Override layer segment keywords (split on - and _)
layers:
  experience: [web, frontend, ui]
  process: [orch, bpm, workflow]
  system: [db, adapter, connector]

# Override CloudHub hostname patterns (regex with capture group)
hostname_patterns:
  - 'mule-worker-(?:internal-)?(?:\\w{2,5}-)(.+?)-\\d+-\\d+\\.'
  - 'mu-alb-(\\w+)\\.'

# Override external backend hostname indicators
external_indicators:
  - oracle
  - salesforce
  - sap
```

Any section can be omitted to keep the defaults for that section. For example, to only add custom layer segments while keeping the default hostname patterns:

```yaml
layers:
  experience: [el, exp, eapi, xapi, experience, web]
  process: [pl, prc, papi, process, orch]
  system: [sl, sys, sapi, system, db]
```
