Skip to content

Commit 42f02f1

Browse files
committed
Fix integration changelog registry coverage
1 parent cf3bcee commit 42f02f1

3 files changed

Lines changed: 129 additions & 13 deletions

File tree

hindsight-dev/hindsight_dev/generate_changelog.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ class IntegrationMeta:
4242
"pydantic-ai": IntegrationMeta("hindsight-pydantic-ai", "Pydantic AI"),
4343
"crewai": IntegrationMeta("hindsight-crewai", "CrewAI"),
4444
"agent-framework": IntegrationMeta("hindsight-agent-framework", "Microsoft Agent Framework"),
45+
"agno": IntegrationMeta("hindsight-agno", "Agno"),
4546
"ag2": IntegrationMeta("hindsight-ag2"),
4647
"ai-sdk": IntegrationMeta("@vectorize-io/hindsight-ai-sdk", "AI SDK"),
4748
"chat": IntegrationMeta("@vectorize-io/hindsight-chat", "Chat SDK"),
@@ -76,6 +77,7 @@ class IntegrationMeta:
7677
"roo-code": IntegrationMeta("hindsight-roo-code", "Roo Code"),
7778
"omo": IntegrationMeta("hindsight-omo", "OMO"),
7879
"composio": IntegrationMeta("hindsight-composio", "Composio"),
80+
"continue": IntegrationMeta("hindsight-continue", "Continue"),
7981
}
8082

8183
VALID_INTEGRATIONS = list(INTEGRATIONS.keys())
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
"""Regression tests for integration changelog registry coverage."""
2+
3+
import subprocess
4+
import tomllib
5+
from pathlib import Path
6+
7+
from hindsight_dev.generate_changelog import INTEGRATIONS
8+
9+
REPO_ROOT = Path(__file__).resolve().parents[2]
10+
RELEASE_SCRIPT = REPO_ROOT / "scripts" / "release-integration.sh"
11+
NEW_PYTHON_INTEGRATIONS = {"agno", "continue"}
12+
13+
14+
def _release_script_integrations():
15+
result = subprocess.run(
16+
["bash", str(RELEASE_SCRIPT), "--list-integrations"],
17+
check=True,
18+
capture_output=True,
19+
cwd=REPO_ROOT,
20+
text=True,
21+
)
22+
return result.stdout.splitlines()
23+
24+
25+
def _validate_release_path(slug):
26+
subprocess.run(
27+
["bash", str(RELEASE_SCRIPT), "--validate-only", slug],
28+
check=True,
29+
capture_output=True,
30+
cwd=REPO_ROOT,
31+
text=True,
32+
)
33+
34+
35+
def test_release_script_integrations_match_changelog_metadata():
36+
release_integrations = _release_script_integrations()
37+
38+
assert len(release_integrations) == len(set(release_integrations))
39+
assert set(release_integrations) == set(INTEGRATIONS)
40+
assert NEW_PYTHON_INTEGRATIONS <= set(release_integrations)
41+
42+
43+
def test_python_integration_metadata_matches_package_manifests():
44+
pyproject_slugs = {path.parent.name for path in (REPO_ROOT / "hindsight-integrations").glob("*/pyproject.toml")}
45+
assert NEW_PYTHON_INTEGRATIONS <= pyproject_slugs
46+
47+
for slug, meta in INTEGRATIONS.items():
48+
pyproject = REPO_ROOT / "hindsight-integrations" / slug / "pyproject.toml"
49+
if not pyproject.exists():
50+
continue
51+
manifest = tomllib.loads(pyproject.read_text())
52+
53+
assert meta.package_name == manifest["project"]["name"]
54+
55+
56+
def test_new_integration_display_names_match_user_facing_brands():
57+
assert INTEGRATIONS["agno"].display_name == "Agno"
58+
assert INTEGRATIONS["continue"].display_name == "Continue"
59+
60+
61+
def test_new_integration_release_paths_validate_before_mutation():
62+
for slug in NEW_PYTHON_INTEGRATIONS:
63+
_validate_release_path(slug)

scripts/release-integration.sh

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,26 @@ usage() {
2828
exit 1
2929
}
3030

31-
if [ -z "$1" ] || [ -z "$2" ]; then
31+
if [ "${1:-}" = "--list-integrations" ] && [ "$#" -eq 1 ]; then
32+
printf "%s\n" "${VALID_INTEGRATIONS[@]}"
33+
exit 0
34+
fi
35+
36+
VALIDATE_ONLY=false
37+
if [ "${1:-}" = "--validate-only" ]; then
38+
VALIDATE_ONLY=true
39+
shift
40+
if [ -z "${1:-}" ] || [ "$#" -ne 1 ]; then
41+
usage
42+
fi
43+
fi
44+
45+
if [ -z "$1" ] || { [ "$VALIDATE_ONLY" = false ] && [ -z "$2" ]; }; then
3246
usage
3347
fi
3448

3549
INTEGRATION=$1
36-
VERSION_ARG=$2
50+
VERSION_ARG=${2:-}
3751

3852
# Validate integration name
3953
VALID=false
@@ -77,6 +91,54 @@ bump_version() {
7791
esac
7892
}
7993

94+
validate_manifest_version_field() {
95+
local manifest=$1
96+
python3 - "$manifest" <<'PY'
97+
import json
98+
import sys
99+
from pathlib import Path
100+
101+
path = Path(sys.argv[1])
102+
if path.name == "pyproject.toml":
103+
import tomllib
104+
105+
data = tomllib.loads(path.read_text())
106+
version = data.get("project", {}).get("version")
107+
else:
108+
data = json.loads(path.read_text())
109+
version = data.get("version")
110+
111+
if not isinstance(version, str) or not version:
112+
raise SystemExit(f"Could not read a top-level release version from {path}")
113+
PY
114+
}
115+
116+
INTEGRATION_DIR="hindsight-integrations/$INTEGRATION"
117+
118+
if [ ! -d "$INTEGRATION_DIR" ]; then
119+
print_error "Integration directory not found: $INTEGRATION_DIR"
120+
exit 1
121+
fi
122+
123+
if [ -f "$INTEGRATION_DIR/pyproject.toml" ]; then
124+
MANIFEST_PATH="$INTEGRATION_DIR/pyproject.toml"
125+
elif [ -f "$INTEGRATION_DIR/package.json" ]; then
126+
MANIFEST_PATH="$INTEGRATION_DIR/package.json"
127+
elif [ -f "$INTEGRATION_DIR/.claude-plugin/plugin.json" ]; then
128+
MANIFEST_PATH="$INTEGRATION_DIR/.claude-plugin/plugin.json"
129+
elif [ -f "$INTEGRATION_DIR/settings.json" ] && grep -q '"version"' "$INTEGRATION_DIR/settings.json"; then
130+
MANIFEST_PATH="$INTEGRATION_DIR/settings.json"
131+
else
132+
print_error "No pyproject.toml, package.json, plugin.json, or versioned settings.json found in $INTEGRATION_DIR"
133+
exit 1
134+
fi
135+
136+
if [ "$VALIDATE_ONLY" = true ]; then
137+
validate_manifest_version_field "$MANIFEST_PATH"
138+
print_info "Validated $INTEGRATION release path via $MANIFEST_PATH"
139+
exit 0
140+
fi
141+
80142
# Resolve version: either an explicit semver or a bump keyword
81143
if [[ "$VERSION_ARG" =~ ^(patch|minor|major)$ ]]; then
82144
CURRENT_VERSION=$(get_current_version)
@@ -135,14 +197,6 @@ if [ -z "$OPENAI_API_KEY" ]; then
135197
exit 1
136198
fi
137199

138-
# Determine integration type and update version
139-
INTEGRATION_DIR="hindsight-integrations/$INTEGRATION"
140-
141-
if [ ! -d "$INTEGRATION_DIR" ]; then
142-
print_error "Integration directory not found: $INTEGRATION_DIR"
143-
exit 1
144-
fi
145-
146200
if [ -f "$INTEGRATION_DIR/pyproject.toml" ]; then
147201
print_info "Updating version in $INTEGRATION_DIR/pyproject.toml"
148202
sed -i.bak "s/^version = \".*\"/version = \"$VERSION\"/" "$INTEGRATION_DIR/pyproject.toml"
@@ -159,9 +213,6 @@ elif [ -f "$INTEGRATION_DIR/settings.json" ] && grep -q '"version"' "$INTEGRATIO
159213
print_info "Updating version in $INTEGRATION_DIR/settings.json"
160214
sed -i.bak "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" "$INTEGRATION_DIR/settings.json"
161215
rm "$INTEGRATION_DIR/settings.json.bak"
162-
else
163-
print_error "No pyproject.toml, package.json, plugin.json, or versioned settings.json found in $INTEGRATION_DIR"
164-
exit 1
165216
fi
166217

167218
# Generate changelog entry using LLM

0 commit comments

Comments
 (0)