Summary:\n- added Codex marketplace registry plus awareness/ethics/guardrails sub-plugins\n- mirrored Claude plugin commands/scripts/hooks into codex api/ci/code/collect/coolify/core/issue/perf/qa/review/verify\n- embedded Axioms of Life ethics modal, guardrails, and kernel files under codex/ethics\n- added Codex parity report, improvements list, and MCP integration plan\n- extended Gemini MCP tools and docs for Codex awareness
169 lines
4.3 KiB
Markdown
169 lines
4.3 KiB
Markdown
---
|
|
name: compare
|
|
description: Compare versions between modules and find incompatibilities
|
|
args: "[module] [--prod]"
|
|
---
|
|
|
|
# Compare Module Versions
|
|
|
|
Compares local module versions against remote, and checks for dependency conflicts.
|
|
|
|
## Usage
|
|
|
|
```
|
|
/code:compare # Compare all modules
|
|
/code:compare core-tenant # Compare specific module
|
|
/code:compare --prod # Compare with production
|
|
```
|
|
|
|
## Action
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
|
|
# Function to compare semantic versions
|
|
# Returns:
|
|
# 0 if versions are equal
|
|
# 1 if version1 > version2
|
|
# 2 if version1 < version2
|
|
compare_versions() {
|
|
if [ "$1" == "$2" ]; then
|
|
return 0
|
|
fi
|
|
local winner=$(printf "%s\n%s" "$1" "$2" | sort -V | tail -n 1)
|
|
if [ "$winner" == "$1" ]; then
|
|
return 1
|
|
else
|
|
return 2
|
|
fi
|
|
}
|
|
|
|
# Checks if a version is compatible with a Composer constraint.
|
|
is_version_compatible() {
|
|
local version=$1
|
|
local constraint=$2
|
|
local base_version
|
|
local operator=""
|
|
|
|
if [[ $constraint == \^* ]]; then
|
|
operator="^"
|
|
base_version=${constraint:1}
|
|
elif [[ $constraint == ~* ]]; then
|
|
operator="~"
|
|
base_version=${constraint:1}
|
|
else
|
|
base_version=$constraint
|
|
compare_versions "$version" "$base_version"
|
|
if [ $? -eq 2 ]; then return 1; else return 0; fi
|
|
fi
|
|
|
|
compare_versions "$version" "$base_version"
|
|
if [ $? -eq 2 ]; then
|
|
return 1
|
|
fi
|
|
|
|
local major minor patch
|
|
IFS='.' read -r major minor patch <<< "$base_version"
|
|
local upper_bound
|
|
|
|
if [ "$operator" == "^" ]; then
|
|
if [ "$major" -gt 0 ]; then
|
|
upper_bound="$((major + 1)).0.0"
|
|
elif [ "$minor" -gt 0 ]; then
|
|
upper_bound="0.$((minor + 1)).0"
|
|
else
|
|
upper_bound="0.0.$((patch + 1))"
|
|
fi
|
|
elif [ "$operator" == "~" ]; then
|
|
upper_bound="$major.$((minor + 1)).0"
|
|
fi
|
|
|
|
compare_versions "$version" "$upper_bound"
|
|
if [ $? -eq 2 ]; then
|
|
return 0
|
|
else
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Parse arguments
|
|
TARGET_MODULE=""
|
|
ENV_FLAG=""
|
|
for arg in "$@"; do
|
|
case $arg in
|
|
--prod)
|
|
ENV_FLAG="--prod"
|
|
;;
|
|
*)
|
|
if [[ ! "$arg" == --* ]]; then
|
|
TARGET_MODULE="$arg"
|
|
fi
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Get module health data
|
|
health_data=$(core dev health $ENV_FLAG)
|
|
|
|
module_data=$(echo "$health_data" | grep -vE '^(Module|━━|Comparing)' | sed '/^$/d' || true)
|
|
if [ -z "$module_data" ]; then
|
|
echo "No module data found."
|
|
exit 0
|
|
fi
|
|
|
|
mapfile -t module_lines <<< "$module_data"
|
|
remote_versions=$(echo "$module_data" | awk '{print $1, $3}')
|
|
|
|
echo "Module Version Comparison"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
echo ""
|
|
echo "Module Local Remote Status"
|
|
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
|
|
|
for line in "${module_lines[@]}"; do
|
|
read -r module local_version remote_version _ <<< "$line"
|
|
if [ -n "$TARGET_MODULE" ] && [ "$module" != "$TARGET_MODULE" ]; then
|
|
continue
|
|
fi
|
|
|
|
compare_versions "$local_version" "$remote_version"
|
|
case $? in
|
|
0) status="✓" ;;
|
|
1) status="↑ ahead" ;;
|
|
2) status="↓ behind" ;;
|
|
esac
|
|
|
|
printf "%-15s %-9s %-9s %s\n" "$module" "$local_version" "$remote_version" "$status"
|
|
done
|
|
|
|
echo ""
|
|
echo "Dependency Check:"
|
|
|
|
for line in "${module_lines[@]}"; do
|
|
read -r module _ <<< "$line"
|
|
if [ -n "$TARGET_MODULE" ] && [ "$module" != "$TARGET_MODULE" ]; then
|
|
continue
|
|
fi
|
|
|
|
if [ -f "$module/composer.json" ]; then
|
|
dependencies=$(jq -r '.require? | select(. != null) | to_entries[] | "\(.key)@\(.value)"' "$module/composer.json")
|
|
|
|
for dep in $dependencies; do
|
|
dep_name=$(echo "$dep" | cut -d'@' -f1)
|
|
dep_constraint=$(echo "$dep" | cut -d'@' -f2)
|
|
|
|
remote_version=$(echo "$remote_versions" | grep "^$dep_name " | awk '{print $2}')
|
|
|
|
if [ -n "$remote_version" ]; then
|
|
if ! is_version_compatible "$remote_version" "$dep_constraint"; then
|
|
echo "⚠ $module requires $dep_name $dep_constraint"
|
|
echo " But production has $remote_version (incompatible)"
|
|
echo " Either:"
|
|
echo " - Deploy a compatible version of $dep_name first"
|
|
echo " - Or adjust the dependency in $module"
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
done
|
|
```
|