Commit 9481262a authored by Pelayo Torres's avatar Pelayo Torres
Browse files

Script to build and compare versions

parent c022e60d
Loading
Loading
Loading
Loading
Loading
+118 −0
Original line number Diff line number Diff line
# CAPIF Services Scripts

This repository contains two Bash scripts to **generate CAPIF services code** from OpenAPI definitions and to **compare two versions** of the generated services.

---

## 1. `capif_build.sh`

This script wraps `openapi-generator` to build Python Flask code from the CAPIF service YAML definitions.  
It allows generating all services or just one specific service.

### Requirements
- `bash` (>= 4.0 recommended)
- [`openapi-generator`](https://openapi-generator.tech/) installed and available in `PATH`

### Usage
```bash
./capif_build.sh --route <5g_repo_path> --output <output_path> [--service <yaml_file>]
```

### Options
- `--route` : Path to the 5G repo containing the CAPIF YAML files.
- `--output`: Path to the folder where the generated code will be stored.
- `--service` *(optional)*: Name of a single YAML file to build (must match one from the CAPIF services list).  
  If omitted, **all services** will be built.
- `-h, --help`: Show help message.

### Examples
Generate all CAPIF services:
```bash
./capif_build.sh --route /path/to/5g_repo --output ./old-version
```

Generate only one service:
```bash
./capif_build.sh --route /path/to/5g_repo --output ./new-version \
  --service TS29222_CAPIF_Events_API.yaml
```

---

## 2. `make_diffs.sh`

This script compares two folders of generated CAPIF services (e.g., `old-version` vs `new-version`).  
It produces:
- A `.diff` file per service (unified diff with `diff -ruN`)
- A `.diffstat` file per service (summary of changes per file, using `diffstat` or `git --no-index --stat`)
- A `summary.txt` file listing the results for all services

### Requirements
- `sh` or `bash`  
- `diff` (standard in Unix-like systems)  
- Optional:  
  - `diffstat` → recommended for per-file summaries  
  - `git` → used as a fallback for summaries if `diffstat` is not available  

### Usage
```bash
./make_diffs.sh --old <old_dir> --new <new_dir> [--out <diffs_dir>] [--service <name>]
```

### Options
- `--old`     : Path to the folder with the old version.
- `--new`     : Path to the folder with the new version.
- `--out`     : (Optional) Output folder for diffs. Default: `./diffs`.
- `--service` : (Optional) Compare only one specific service (folder or file at top level).
- `-h, --help`: Show help message.

### Examples
Compare all services:
```bash
./make_diffs.sh --old ./old-version --new ./new-version
```

Compare only one service:
```bash
./make_diffs.sh --old ./old-version --new ./new-version --service TS29222_CAPIF_Events_API
```

Save diffs into a custom folder:
```bash
./make_diffs.sh --old ./old-version --new ./new-version --out ./diffs_run2
```

### Output
After running, the output folder will contain:
```
diffs/
├── TS29222_CAPIF_Events_API.diff
├── TS29222_CAPIF_Events_API.diffstat
├── TS29222_CAPIF_Auditing_API.diff
├── TS29222_CAPIF_Auditing_API.diffstat
...
└── summary.txt
```

---

## Typical Workflow
1. Generate services for the **old version**:
   ```bash
   ./capif_build.sh --route /path/to/5g_repo --output ./old-version
   ```
2. Generate services for the **new version**:
   ```bash
   ./capif_build.sh --route /path/to/5g_repo --output ./new-version
   ```
3. Compare them:
   ```bash
   ./make_diffs.sh --old ./old-version --new ./new-version --out ./diffs
   ```
4. Inspect the `.diff` and `.diffstat` files or open them in a diff viewer like `meld`, `kdiff3`, or `colordiff`.

---

## Tips
- For easier inspection, install GUI diff tools like [Meld](https://meldmerge.org/).  
- For API-level changes (OpenAPI/Swagger), you may also use tools like [`oasdiff`](https://github.com/Tufin/oasdiff).
+100 −0
Original line number Diff line number Diff line
#!/usr/bin/env bash
set -euo pipefail

# List of CAPIF services
SERVICES=(
  "TS29222_CAPIF_API_Invoker_Management_API.yaml"
  "TS29222_CAPIF_API_Provider_Management_API.yaml"
  "TS29222_CAPIF_Access_Control_Policy_API.yaml"
  "TS29222_CAPIF_Auditing_API.yaml"
  "TS29222_CAPIF_Discover_Service_API.yaml"
  "TS29222_CAPIF_Events_API.yaml"
  "TS29222_CAPIF_Logging_API_Invocation_API.yaml"
  "TS29222_CAPIF_Publish_Service_API.yaml"
  "TS29222_CAPIF_Routing_Info_API.yaml"
  "TS29222_CAPIF_Security_API.yaml"
)

usage() {
  cat <<EOF
Usage:
  $(basename "$0") --route <5g_repo_path> --output <output_path> [--service <yaml_file>]

Options:
  --route     Path to the 5G repo containing the YAML files.
  --output    Folder where the generated code will be stored.
  --service   (Optional) One of the following YAML files:
              ${SERVICES[*]}
  -h, --help  Show this help message.

Examples:
  $(basename "$0") --route /path/5g --output /tmp/capif
  $(basename "$0") --route /path/5g --output /tmp/capif --service TS29222_CAPIF_Events_API.yaml
EOF
}

# Argument parsing (style: --key value)
ROUTE=""
OUTPUT=""
SERVICE=""

while [[ $# -gt 0 ]]; do
  case "$1" in
    --route)  ROUTE="${2:-}"; shift 2 ;;
    --output) OUTPUT="${2:-}"; shift 2 ;;
    --service) SERVICE="${2:-}"; shift 2 ;;
    -h|--help) usage; exit 0 ;;
    *) echo "Unknown argument: $1" >&2; usage; exit 1 ;;
  esac
done

# Basic validations
[[ -z "$ROUTE"  ]] && echo "Error: --route is required."  >&2 && usage && exit 1
[[ -z "$OUTPUT" ]] && echo "Error: --output is required." >&2 && usage && exit 1

if ! command -v openapi-generator >/dev/null 2>&1; then
  echo "Error: 'openapi-generator' is not installed or not in PATH." >&2
  exit 1
fi

if [[ ! -d "$ROUTE" ]]; then
  echo "Error: the provided route '$ROUTE' does not exist." >&2
  exit 1
fi

mkdir -p "$OUTPUT"

# If a service is specified, validate it
if [[ -n "$SERVICE" ]]; then
  valid=false
  for s in "${SERVICES[@]}"; do
    if [[ "$s" == "$SERVICE" ]]; then
      valid=true
      break
    fi
  done
  if [[ "$valid" != true ]]; then
    echo "Error: the service '$SERVICE' is not valid." >&2
    echo "It must be one of: ${SERVICES[*]}" >&2
    exit 1
  fi

  path="$ROUTE/$SERVICE"
  if [[ ! -f "$path" ]]; then
    echo "Error: the service '$SERVICE' does not exist in the route '$ROUTE'." >&2
    exit 1
  fi

  base="${SERVICE%.*}"
  echo "Downloading and building service: $SERVICE"
  openapi-generator generate -i "$path" -g python-flask -o "$OUTPUT/$base"
else
  # Process all services
  for svc in "${SERVICES[@]}"; do
    path="$ROUTE/$svc"
    echo "Downloading and building service: $svc"
    openapi-generator generate -i "$path" -g python-flask -o "$OUTPUT/${svc%.*}"
  done
fi

echo "All services have been downloaded and built."
+133 −0
Original line number Diff line number Diff line
#!/bin/sh
set -eu

usage() {
  cat <<EOF
Usage:
  $(basename "$0") --old <old_dir> --new <new_dir> [--out <diffs_dir>] [--service <name>]

Options:
  --old       Path to the folder with the old version (e.g., old-version)
  --new       Path to the folder with the new version (e.g., new-version)
  --out       (Optional) Output folder for diffs. Default: ./diffs
  --service   (Optional) Single top-level service (file or directory name) to compare
  -h, --help  Show this help

Output:
  - <service>.diff       unified diff (-ruN) for the service
  - <service>.diffstat   summary (diffstat or git --no-index --stat fallback)
  - summary.txt          run summary
EOF
}

OLD=""
NEW=""
OUT="diffs"
ONLY_SERVICE=""

# Parse args
while [ $# -gt 0 ]; do
  case "$1" in
    --old) OLD=${2:-}; shift 2 ;;
    --new) NEW=${2:-}; shift 2 ;;
    --out) OUT=${2:-}; shift 2 ;;
    --service) ONLY_SERVICE=${2:-}; shift 2 ;;
    -h|--help) usage; exit 0 ;;
    *) echo "Unknown argument: $1" >&2; usage; exit 1 ;;
  esac
done

[ -n "$OLD" ] || { echo "Error: --old is required." >&2; usage; exit 1; }
[ -n "$NEW" ] || { echo "Error: --new is required." >&2; usage; exit 1; }

[ -d "$OLD" ] || { echo "Error: '$OLD' is not a directory." >&2; exit 1; }
[ -d "$NEW" ] || { echo "Error: '$NEW' is not a directory." >&2; exit 1; }

mkdir -p "$OUT"

SUMMARY_FILE="$OUT/summary.txt"
: > "$SUMMARY_FILE"   # overwrite each run

have_diffstat=0
command -v diffstat >/dev/null 2>&1 && have_diffstat=1

have_git=0
command -v git >/dev/null 2>&1 && have_git=1

# Build service list
if [ -n "$ONLY_SERVICE" ]; then
  # Validate existence in at least one side
  if [ ! -e "$OLD/$ONLY_SERVICE" ] && [ ! -e "$NEW/$ONLY_SERVICE" ]; then
    echo "Error: service '$ONLY_SERVICE' not found in either '$OLD' or '$NEW'." >&2
    exit 1
  fi
  SERVICES_LIST=$ONLY_SERVICE
else
  tmp="$(mktemp)"
  for p in "$OLD"/* "$NEW"/*; do
    [ -e "$p" ] || continue
    base=$(basename "$p")
    printf '%s\n' "$base" >> "$tmp"
  done
  SERVICES_LIST=$(sort -u "$tmp")
  rm -f "$tmp"

  # If nothing found, exit gracefully
  if [ -z "$SERVICES_LIST" ]; then
    echo "No services found in '$OLD' or '$NEW'. Nothing to diff."
    exit 0
  fi
fi

echo "Generating diffs into '$OUT'..."
echo "$SERVICES_LIST" | while IFS= read -r svc; do
  [ -n "$svc" ] || continue

  left="$OLD/$svc"
  right="$NEW/$svc"
  out_diff="$OUT/${svc}.diff"
  out_stat="$OUT/${svc}.diffstat"

  # Clean previous files to ensure overwrite
  rm -f "$out_diff" "$out_stat"

  if [ ! -e "$left" ] && [ ! -e "$right" ]; then
    echo "WARN: '$svc' missing in both sides; skipping." | tee -a "$SUMMARY_FILE"
    continue
  fi

  # 0=no changes, 1=diffs, >1=error
  if diff -ruN "$left" "$right" >"$out_diff" 2>&1; then
    echo "Service '$svc': no differences." | tee -a "$SUMMARY_FILE"
    echo "No differences" >"$out_stat"
  else
    code=$?
    if [ $code -eq 1 ]; then
      echo "Service '$svc': differences found -> $(basename "$out_diff")" | tee -a "$SUMMARY_FILE"
      if [ $have_diffstat -eq 1 ]; then
        if ! diffstat "$out_diff" >"$out_stat" 2>/dev/null; then
          echo "Failed to generate diffstat from diff file." >"$out_stat"
        fi
      elif [ $have_git -eq 1 ] && [ -e "$left" ] && [ -e "$right" ]; then
        if ! git -c color.ui=never diff --no-index --stat -- "$left" "$right" >"$out_stat" 2>/dev/null; then
          echo "Failed to generate stat with git --no-index." >"$out_stat"
        fi
      else
        {
          echo "diffstat and git not available."
          echo "Install 'diffstat' for per-file summaries, e.g.:"
          echo "  - Debian/Ubuntu: sudo apt-get install diffstat"
          echo "  - macOS (brew):  brew install diffstat"
          echo "  - Fedora/RHEL:    sudo dnf install diffstat"
        } >"$out_stat"
      fi
    else
      echo "Service '$svc': diff error (exit $code) -> $(basename "$out_diff")" | tee -a "$SUMMARY_FILE"
      echo "Diff error (exit $code). See $(basename "$out_diff") for details." >"$out_stat"
    fi
  fi
done

echo
echo "Done. Diff files are in: $OUT"
echo "Summary: $SUMMARY_FILE"