Skip to content

Commit d64e885

Browse files
kingpanther13claude
andcommitted
chore: reset addon-repo to upstream master + PR homeassistant-ai#1126 only, dev96
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 1ac7af2 commit d64e885

105 files changed

Lines changed: 46164 additions & 5 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

FORK-DEV.md

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
# Fork Development Workflow
2+
3+
This branch (`addon-repo`) is the **default branch** on this fork. It serves as the HA add-on repository for testing PR branches on a real Home Assistant instance.
4+
5+
**PRs are NOT based on this branch.** Feature branches go to `upstream/master` independently. This branch is always force-pushed to mirror whatever feature branch is being tested.
6+
7+
> **A backup of this file lives at `~/.ha-mcp-fork-dev.md`.**
8+
> If `git reset --hard` wipes it, restore with: `cp ~/.ha-mcp-fork-dev.md ~/ha-mcp-fork/FORK-DEV.md`
9+
10+
## How It Works
11+
12+
1. HA Supervisor clones this repo's default branch (`addon-repo`)
13+
2. It finds `homeassistant-addon-dev/config.yaml` and builds the Docker image from `homeassistant-addon-dev/Dockerfile`
14+
3. The addon runs the code from `homeassistant-addon-dev/src/ha_mcp/`
15+
16+
## Dual `src/` Directories - READ THIS
17+
18+
The repo has **two separate `src/ha_mcp/` directories**:
19+
20+
```
21+
ha-mcp-fork/
22+
src/ha_mcp/ <-- repo root source (what PRs modify)
23+
homeassistant-addon-dev/src/ha_mcp/ <-- addon source (what HA actually runs)
24+
```
25+
26+
**The Dockerfile copies from `homeassistant-addon-dev/src/`, NOT from the root `src/`.** If you only edit files in the root `src/`, the addon will still run the OLD code. You must always sync changes into `homeassistant-addon-dev/src/ha_mcp/`.
27+
28+
This is the #1 cause of "I pushed but the old code is still running" issues.
29+
30+
## Switching to a Different PR Branch
31+
32+
```bash
33+
cd ~/ha-mcp-fork
34+
git checkout addon-repo
35+
36+
# Reset to the feature branch
37+
git reset --hard <feature-branch>
38+
```
39+
40+
### After `git reset --hard` - CRITICAL STEPS
41+
42+
The reset wipes addon-specific files that don't exist on feature branches. You **must** restore them:
43+
44+
```bash
45+
# 1. Restore this documentation (gets wiped by reset!)
46+
cp ~/.ha-mcp-fork-dev.md FORK-DEV.md
47+
48+
# 2. Restore the README banner
49+
# Add at the very top of README.md:
50+
# > **This is a personal fork.** See [`FORK-DEV.md`](FORK-DEV.md) for the addon-repo workflow.
51+
52+
# 3. Copy build files into the addon directory
53+
cp pyproject.toml homeassistant-addon-dev/
54+
cp uv.lock homeassistant-addon-dev/
55+
cp homeassistant-addon/start.py homeassistant-addon-dev/
56+
57+
# 4. Copy source code (the critical sync step!)
58+
cp -r src/ha_mcp/* homeassistant-addon-dev/src/ha_mcp/
59+
60+
# 5. Fix the Dockerfile (upstream references wrong path)
61+
sed -i 's|COPY homeassistant-addon/start.py|COPY start.py|' homeassistant-addon-dev/Dockerfile
62+
63+
# 6. Update config.yaml:
64+
# - Remove the `image:` line (forces local build instead of pulling from ghcr.io)
65+
# - Set name to "Fork-Dev" (distinguishes from official addon)
66+
# - Bump version (forces HA Supervisor to rebuild)
67+
```
68+
69+
### Why These Files Are Needed
70+
71+
| File | Why |
72+
|------|-----|
73+
| `homeassistant-addon-dev/pyproject.toml` | Dockerfile `COPY pyproject.toml` - needed for `uv sync` |
74+
| `homeassistant-addon-dev/uv.lock` | Dockerfile `COPY uv.lock` - pinned dependencies |
75+
| `homeassistant-addon-dev/start.py` | Dockerfile `COPY start.py /` - addon entrypoint |
76+
| `homeassistant-addon-dev/src/ha_mcp/` | Dockerfile `COPY src/` - the actual server code |
77+
| `homeassistant-addon-dev/Dockerfile` | Must use `COPY start.py /` not `COPY homeassistant-addon/start.py /` |
78+
| `FORK-DEV.md` | This file - backup at `~/.ha-mcp-fork-dev.md` |
79+
80+
The upstream Dockerfile is designed for CI builds where the build context is the repo root. When HA Supervisor builds locally, the build context is `homeassistant-addon-dev/` itself, so all paths must be relative to that directory.
81+
82+
### config.yaml: `image` Field
83+
84+
- **With `image:` field**: HA pulls a pre-built image from ghcr.io (upstream code, NOT your branch)
85+
- **Without `image:` field**: HA builds locally from the Dockerfile (your branch code)
86+
- For testing fork branches, the `image:` field **must be removed**
87+
88+
## Forcing a Rebuild
89+
90+
HA Supervisor only rebuilds when the version changes. After pushing changes:
91+
92+
```bash
93+
# Bump version in homeassistant-addon-dev/config.yaml
94+
# e.g., dev5 -> dev6
95+
96+
# Force-push (safe - this branch is never a PR base)
97+
git add -A && git commit -m "chore: sync addon-repo" && git push origin addon-repo --force
98+
```
99+
100+
Then in HA: Settings > Add-ons > Fork-Dev > Rebuild
101+
102+
## Full Deploy Workflow (Copy-Paste)
103+
104+
```bash
105+
cd ~/ha-mcp-fork
106+
git checkout addon-repo
107+
git reset --hard <feature-branch>
108+
109+
# Restore docs and addon-specific files
110+
cp ~/.ha-mcp-fork-dev.md FORK-DEV.md
111+
cp pyproject.toml homeassistant-addon-dev/
112+
cp uv.lock homeassistant-addon-dev/
113+
cp homeassistant-addon/start.py homeassistant-addon-dev/
114+
cp -r src/ha_mcp/* homeassistant-addon-dev/src/ha_mcp/
115+
sed -i 's|COPY homeassistant-addon/start.py|COPY start.py|' homeassistant-addon-dev/Dockerfile
116+
117+
# Edit config.yaml: remove image field, set name "Fork-Dev", bump version
118+
# Then:
119+
git add -A
120+
git commit -m "chore: sync addon-repo to <feature-branch>"
121+
git push origin addon-repo --force
122+
```

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
> **This is a personal fork.** See [`FORK-DEV.md`](FORK-DEV.md) for the addon-repo workflow.
2+
13
> **Breaking change (v7.3.0):** `ha_config_set_yaml` has been moved to [beta](docs/beta.md).
24
35
<div align="center">

homeassistant-addon-dev/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ WORKDIR /app
2828

2929
# Copy the virtual environment and startup script from builder
3030
COPY --from=builder /app/.venv /app/.venv
31-
COPY homeassistant-addon/start.py /
31+
COPY start.py /
3232

3333
# Activate virtual environment via PATH
3434
ENV PATH="/app/.venv/bin:$PATH"

homeassistant-addon-dev/config.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
name: "Home Assistant MCP Server (Dev)"
1+
name: "Fork-Dev"
22
description: "Development channel - AI assistant integration via MCP (unstable)"
3-
version: "7.4.1.dev262"
3+
version: "dev96"
44
slug: "ha_mcp_dev"
5-
url: "https://github.com/homeassistant-ai/ha-mcp"
5+
url: "https://github.com/kingpanther13/ha-mcp-fork"
66
stage: experimental
77
arch:
88
- aarch64
@@ -20,7 +20,6 @@ hassio_api: true
2020
hassio_role: manager
2121
homeassistant_api: true
2222
host_network: true
23-
image: "ghcr.io/homeassistant-ai/ha-mcp-addon-dev-{arch}"
2423
options:
2524
backup_hint: "normal"
2625
enable_skills: true
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
[build-system]
2+
requires = ["setuptools>=61.0", "wheel"]
3+
build-backend = "setuptools.build_meta"
4+
5+
[project]
6+
name = "ha-mcp"
7+
version = "7.4.1"
8+
description = "Home Assistant MCP Server - Complete control of Home Assistant through MCP"
9+
readme = "README.md"
10+
requires-python = ">=3.13,<3.14"
11+
license = {text = "MIT"}
12+
authors = [
13+
{name = "Julien", email = "github@qc-h.net"}
14+
]
15+
keywords = ["mcp", "home-assistant", "ai", "automation", "smart-home"]
16+
classifiers = [
17+
"Development Status :: 5 - Production/Stable",
18+
"Intended Audience :: Developers",
19+
"License :: OSI Approved :: MIT License",
20+
"Programming Language :: Python :: 3",
21+
"Programming Language :: Python :: 3.13",
22+
"Topic :: Home Automation",
23+
"Topic :: Software Development :: Libraries :: Python Modules",
24+
]
25+
26+
dependencies = [
27+
"fastmcp==3.2.4",
28+
"httpx[socks]==0.28.1",
29+
"pydantic==2.13.3",
30+
"python-dotenv==1.2.2",
31+
"truststore==0.10.4",
32+
"websockets==16.0",
33+
"cryptography==47.0.0",
34+
]
35+
36+
[project.urls]
37+
"Homepage" = "https://github.com/homeassistant-ai/ha-mcp"
38+
"Bug Tracker" = "https://github.com/homeassistant-ai/ha-mcp/issues"
39+
"Repository" = "https://github.com/homeassistant-ai/ha-mcp"
40+
41+
[project.scripts]
42+
ha-mcp = "ha_mcp.__main__:main"
43+
ha-mcp-smoke-test = "ha_mcp.smoke_test:main"
44+
hamcp-test-env = "tests.test_env_manager:main"
45+
ha-mcp-web = "ha_mcp.__main__:main_web"
46+
ha-mcp-sse = "ha_mcp.__main__:main_sse"
47+
ha-mcp-oauth = "ha_mcp.__main__:main_oauth"
48+
49+
[tool.setuptools]
50+
package-dir = {"" = "src", "tests" = "tests"}
51+
packages = { find = { where = ["src", "."], include = ["ha_mcp*", "tests"] } }
52+
53+
[tool.setuptools.package-data]
54+
ha_mcp = ["py.typed", "_pypi_marker", "resources/skills-vendor/**/*"]
55+
56+
[tool.mypy]
57+
python_version = "3.13"
58+
mypy_path = "src"
59+
# /tmp keeps the cache on Linux tmpfs — avoids the slow Windows FS in WSL2.
60+
# Windows-native contributors can remove this line or override with MYPY_CACHE_DIR.
61+
cache_dir = "/tmp/.mypy_cache"
62+
warn_return_any = true
63+
warn_unused_configs = true
64+
disallow_untyped_defs = true
65+
disallow_incomplete_defs = true
66+
check_untyped_defs = true
67+
no_implicit_optional = true
68+
warn_redundant_casts = true
69+
warn_unused_ignores = true
70+
show_error_codes = true
71+
namespace_packages = true
72+
explicit_package_bases = true
73+
74+
[[tool.mypy.overrides]]
75+
module = [
76+
"fastmcp.*",
77+
"jq",
78+
]
79+
ignore_missing_imports = true
80+
81+
[[tool.mypy.overrides]]
82+
module = [
83+
"homeassistant.*",
84+
"aiohttp",
85+
"voluptuous",
86+
"jsonschema",
87+
]
88+
ignore_missing_imports = true
89+
90+
91+
[tool.ruff]
92+
target-version = "py313"
93+
line-length = 88
94+
extend-exclude = ["tests/initial_test_state"]
95+
96+
[tool.ruff.lint]
97+
select = [
98+
"E", # pycodestyle errors
99+
"W", # pycodestyle warnings
100+
"F", # pyflakes
101+
"I", # isort
102+
"B", # flake8-bugbear
103+
"C4", # flake8-comprehensions
104+
"UP", # pyupgrade
105+
"RUF", # ruff-specific rules
106+
"PIE", # misc lints
107+
"PERF", # performance anti-patterns
108+
"ASYNC", # async best practices
109+
"A", # builtin shadowing
110+
"LOG", # logging best practices
111+
"SIM", # simplify
112+
]
113+
ignore = [
114+
"E501", # line too long — formatter handles this
115+
"B008", # function calls in defaults — FastMCP pattern
116+
"SIM102", # collapsible-if — sometimes less readable
117+
"SIM108", # ternary — sometimes less readable
118+
"SIM105", # contextlib.suppress — style preference
119+
"ASYNC109",# timeout params are standard in HA API patterns
120+
"RUF001", # ambiguous unicode — HA entity names use degree symbols etc
121+
"RUF003", # ambiguous unicode in comments
122+
"RUF010", # explicit f-string type conversion — str(x) is clearer than !s
123+
"F841", # unused variable — too many to fix now
124+
"RUF059", # unused unpacked variable
125+
"SIM118", # in-dict-keys — style preference
126+
"PIE810", # multiple-starts-ends-with — style preference
127+
"RUF005", # collection-literal-concatenation
128+
"RUF022", # unsorted-dunder-all
129+
"RUF013", # implicit-optional
130+
]
131+
132+
[tool.ruff.lint.per-file-ignores]
133+
"__init__.py" = ["F401"]
134+
"tests/**/*" = ["E501", "B011"]
135+
# C901 ignores for tools files with complex methods (see #925).
136+
# Remove lines as individual methods are simplified below threshold.
137+
"src/ha_mcp/tools/tools_addons.py" = ["C901"]
138+
"src/ha_mcp/tools/tools_config_dashboards.py" = ["C901"]
139+
"src/ha_mcp/tools/tools_config_helpers.py" = ["C901"]
140+
"src/ha_mcp/tools/tools_entities.py" = ["C901"]
141+
"src/ha_mcp/tools/tools_registry.py" = ["C901"]
142+
"src/ha_mcp/tools/tools_search.py" = ["C901"]
143+
"src/ha_mcp/tools/tools_utility.py" = ["C901"]
144+
"src/ha_mcp/tools/smart_search.py" = ["C901"]
145+
"src/ha_mcp/tools/util_helpers.py" = ["C901"]
146+
147+
[tool.pytest.ini_options]
148+
testpaths = ["tests"]
149+
python_files = ["test_*.py", "*_test.py"]
150+
python_classes = ["Test*"]
151+
python_functions = ["test_*"]
152+
addopts = [
153+
"--strict-markers",
154+
"--strict-config",
155+
"--verbose",
156+
"--tb=short",
157+
]
158+
markers = [
159+
"slow: marks tests as slow (deselect with '-m \"not slow\"')",
160+
"integration: marks tests as integration tests",
161+
"unit: marks tests as unit tests",
162+
"automation: automation lifecycle tests",
163+
"calendar: calendar event management tests",
164+
"device: device control tests",
165+
"script: script orchestration tests",
166+
"helper: helper integration tests",
167+
"convenience: convenience tools tests (scene, weather, energy, docs)",
168+
"error_handling: error handling and edge case tests",
169+
"cleanup: tests that create entities needing cleanup",
170+
"performance: performance measurement and regression tests",
171+
]
172+
asyncio_mode = "auto"
173+
174+
[dependency-groups]
175+
dev = [
176+
"build>=1.2.2",
177+
"docker>=7.1.0",
178+
"mypy>=1.17.0",
179+
"openai>=1.0.0",
180+
"psutil>=7.0.0",
181+
"pytest>=8.4.2",
182+
"pytest-asyncio>=1.1.0",
183+
"pytest-cov>=5.0.0",
184+
"pytest-xdist>=3.8.0",
185+
"requests>=2.25.0",
186+
"lefthook>=1.10.0",
187+
"ruamel.yaml>=0.18.0",
188+
"ruff>=0.12.12",
189+
"testcontainers>=4.13.0",
190+
"ast-grep-cli>=0.42.0",
191+
]
192+
193+
# Semantic versioning configuration
194+
[tool.semantic_release]
195+
version_toml = ["pyproject.toml:project.version"]
196+
version_variables = [
197+
"src/ha_mcp/__init__.py:__version__",
198+
]
199+
build_command = """
200+
pip install uv && uv lock
201+
git add uv.lock
202+
"""
203+
dist_path = "dist/"
204+
upload_to_PyPI = true
205+
upload_to_release = true
206+
remove_dist = false
207+
208+
# Commit message parsing
209+
commit_parser = "angular"
210+
commit_parser_options = { major_tags = ["BREAKING", "!"], minor_tags = ["feat"], patch_tags = ["fix", "perf", "refactor"] }
211+
212+
# Changelog configuration
213+
[tool.semantic_release.changelog]
214+
template_dir = "templates"
215+
exclude_commit_patterns = [
216+
"^.*\\(site\\).*$", # Commits with (site) scope
217+
'''chore\(addon\): [Ss]ync changelog.*''', # Changelog sync commits
218+
]
219+
220+
[tool.semantic_release.changelog.default_templates]
221+
changelog_file = "CHANGELOG.md"
222+
223+
# Version scheme
224+
major_on_zero = true
225+
allow_zero_version = false
226+
227+
# Branch and tag configuration
228+
branch = "master"
229+
230+
# Publish configuration (v10 syntax)
231+
[tool.semantic_release.publish]
232+
# GitHub release is created by build-binary.yml workflow to include binaries
233+
upload_to_vcs_release = false

0 commit comments

Comments
 (0)