@coffeerunhobby/mcp-ha-connect 1.5.4 → 1.5.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +70 -2
- package/Dockerfile +17 -7
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/openapi.json +1 -1
- package/package.json +1 -1
- package/src/version.ts +1 -1
package/.github/workflows/ci.yml
CHANGED
|
@@ -9,6 +9,10 @@ name: CI
|
|
|
9
9
|
on:
|
|
10
10
|
push:
|
|
11
11
|
branches: [main, dev]
|
|
12
|
+
# Version tags trigger the full gate + auto-create the GitHub Release (see
|
|
13
|
+
# the `release` job) — v1.5.4 sat tag-only for two weeks because the manual
|
|
14
|
+
# `gh release create` step kept getting skipped.
|
|
15
|
+
tags: ['v*']
|
|
12
16
|
pull_request:
|
|
13
17
|
branches: [main, dev]
|
|
14
18
|
# Lets you re-run it by hand from the Actions tab.
|
|
@@ -28,8 +32,9 @@ jobs:
|
|
|
28
32
|
# we want to see both results.
|
|
29
33
|
fail-fast: false
|
|
30
34
|
matrix:
|
|
31
|
-
# The
|
|
32
|
-
|
|
35
|
+
# The LTS lines we support (package.json engines: ">=20"). 24.x is the
|
|
36
|
+
# Docker image's actual runtime (since v1.5.6); 26 is the next LTS (2026-10).
|
|
37
|
+
node-version: ['20.x', '22.x', '24.x', '26.x']
|
|
33
38
|
|
|
34
39
|
name: node ${{ matrix.node-version }}
|
|
35
40
|
|
|
@@ -67,3 +72,66 @@ jobs:
|
|
|
67
72
|
# floor in vitest.config.ts — a coverage DROP fails the build.
|
|
68
73
|
- name: Test + coverage gate
|
|
69
74
|
run: npm run test:coverage
|
|
75
|
+
|
|
76
|
+
docker-smoke:
|
|
77
|
+
# Boot-test the ACTUAL image: build it, point it at a mock Home Assistant,
|
|
78
|
+
# and require /health to answer. Motivation: v1.5.5 shipped without ever
|
|
79
|
+
# having been run — its first boot was in production on the NAS (where the
|
|
80
|
+
# node:26 base then failed its first fetch). A release must never again be
|
|
81
|
+
# the image's first boot.
|
|
82
|
+
runs-on: ubuntu-latest
|
|
83
|
+
steps:
|
|
84
|
+
- name: Checkout
|
|
85
|
+
uses: actions/checkout@v4
|
|
86
|
+
|
|
87
|
+
- name: Build image
|
|
88
|
+
run: docker build -t mcp-smoke:ci .
|
|
89
|
+
|
|
90
|
+
- name: Boot against a mock HA and assert /health
|
|
91
|
+
run: |
|
|
92
|
+
set -eu
|
|
93
|
+
docker network create smoke
|
|
94
|
+
# Mock HA: 200 {"message":"API running."} — the same body the real
|
|
95
|
+
# /api/ startup check (checkApi) expects.
|
|
96
|
+
docker run -d --name mockha --network smoke node:24-alpine \
|
|
97
|
+
node -e 'require("http").createServer((q,s)=>{s.writeHead(200,{"Content-Type":"application/json"});s.end(JSON.stringify({message:"API running."}))}).listen(8123,()=>console.log("mock HA up"))'
|
|
98
|
+
docker run -d --name mcp --network smoke \
|
|
99
|
+
-e MCP_SERVER_USE_HTTP=true \
|
|
100
|
+
-e MCP_HTTP_PORT=3000 -e MCP_HTTP_BIND_ADDR=0.0.0.0 \
|
|
101
|
+
-e MCP_HTTP_ENABLE_HEALTHCHECK=true -e MCP_HTTP_HEALTHCHECK_PATH=/health \
|
|
102
|
+
-e MCP_AUTH_METHOD=bearer -e MCP_AUTH_SECRET=ci-smoke-dummy-secret-0123456789 \
|
|
103
|
+
-e HA_PLUGIN_ENABLED=true -e HA_URL=http://mockha:8123 -e HA_TOKEN=ci-dummy \
|
|
104
|
+
-e AI_PLUGIN_ENABLED=false -e OMADA_PLUGIN_ENABLED=false \
|
|
105
|
+
mcp-smoke:ci
|
|
106
|
+
for i in $(seq 1 15); do
|
|
107
|
+
if docker run --rm --network smoke curlimages/curl:latest -sf http://mcp:3000/health >/dev/null 2>&1; then
|
|
108
|
+
echo "smoke OK: image boots, startup HA check passes, /health answers"
|
|
109
|
+
exit 0
|
|
110
|
+
fi
|
|
111
|
+
sleep 2
|
|
112
|
+
done
|
|
113
|
+
echo "SMOKE FAILED — container logs:"
|
|
114
|
+
docker logs mcp
|
|
115
|
+
exit 1
|
|
116
|
+
|
|
117
|
+
release:
|
|
118
|
+
# Auto-create the GitHub Release when a `v*` tag passes BOTH gates above —
|
|
119
|
+
# the test matrix AND the image boot-test. Notes are auto-generated from the
|
|
120
|
+
# commits since the previous release; polish them in the web UI afterwards
|
|
121
|
+
# if the release deserves prose.
|
|
122
|
+
# Idempotent: if the Release already exists (created by hand), this no-ops.
|
|
123
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
124
|
+
needs: [build-test-lint, docker-smoke]
|
|
125
|
+
runs-on: ubuntu-latest
|
|
126
|
+
permissions:
|
|
127
|
+
contents: write
|
|
128
|
+
steps:
|
|
129
|
+
- name: Checkout
|
|
130
|
+
uses: actions/checkout@v4
|
|
131
|
+
|
|
132
|
+
- name: Create GitHub Release
|
|
133
|
+
env:
|
|
134
|
+
GH_TOKEN: ${{ github.token }}
|
|
135
|
+
run: |
|
|
136
|
+
gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1 || \
|
|
137
|
+
gh release create "$GITHUB_REF_NAME" --latest --generate-notes --title "$GITHUB_REF_NAME"
|
package/Dockerfile
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# syntax=docker/dockerfile:1.7
|
|
2
2
|
|
|
3
|
-
FROM node:
|
|
3
|
+
FROM node:24-alpine AS deps
|
|
4
4
|
WORKDIR /app
|
|
5
5
|
COPY package*.json ./
|
|
6
6
|
# npm ci installs exactly from the committed package-lock.json (reproducible) and
|
|
@@ -8,13 +8,13 @@ COPY package*.json ./
|
|
|
8
8
|
# above pulls in package-lock.json, so the lockfile is present in this stage.
|
|
9
9
|
RUN npm ci
|
|
10
10
|
|
|
11
|
-
FROM node:
|
|
11
|
+
FROM node:24-alpine AS build
|
|
12
12
|
WORKDIR /app
|
|
13
13
|
COPY --from=deps /app/node_modules ./node_modules
|
|
14
14
|
COPY . .
|
|
15
15
|
RUN npm run build
|
|
16
16
|
|
|
17
|
-
FROM node:
|
|
17
|
+
FROM node:24-alpine AS runtime
|
|
18
18
|
|
|
19
19
|
# OCI metadata labels
|
|
20
20
|
LABEL org.opencontainers.image.title="MCP-HA-Connect"
|
|
@@ -27,14 +27,24 @@ LABEL org.opencontainers.image.licenses="MIT"
|
|
|
27
27
|
|
|
28
28
|
WORKDIR /app
|
|
29
29
|
ENV NODE_ENV=production
|
|
30
|
-
|
|
30
|
+
# apk upgrade: pick up Alpine security patches even when the node base tag lags
|
|
31
|
+
# (the 2026-07 Trivy scan's 24 libssl/libcrypto CVEs were exactly this rot).
|
|
32
|
+
RUN apk upgrade --no-cache && apk add --no-cache curl
|
|
31
33
|
COPY package*.json ./
|
|
32
|
-
# Reproducible prod-only install from the lockfile (drops devDependencies)
|
|
33
|
-
|
|
34
|
+
# Reproducible prod-only install from the lockfile (drops devDependencies), then
|
|
35
|
+
# strip the package managers from the runtime image: nothing invokes npm/yarn after
|
|
36
|
+
# this line, and the npm CLI's vendored deps were the only Trivy findings left on
|
|
37
|
+
# v1.5.5 (undici 6.26.0 inside /usr/local/lib/node_modules/npm).
|
|
38
|
+
RUN npm ci --omit=dev && \
|
|
39
|
+
rm -rf /usr/local/lib/node_modules /usr/local/bin/npm /usr/local/bin/npx \
|
|
40
|
+
/usr/local/bin/corepack /opt/yarn* /usr/local/bin/yarn /usr/local/bin/yarnpkg \
|
|
41
|
+
/root/.npm
|
|
34
42
|
COPY --from=build /app/dist ./dist
|
|
35
43
|
|
|
36
44
|
# M10: drop root. The official node image ships a non-root `node` user (uid 1000).
|
|
37
45
|
# Built artifacts under /app are world-readable, so no chown is required; the
|
|
38
46
|
# server listens on 3000 (>1024) which needs no privileged capability.
|
|
39
47
|
USER node
|
|
40
|
-
|
|
48
|
+
# --experimental-quic was dropped 2026-07-10: nothing in src/ uses QUIC, and the
|
|
49
|
+
# flag tied the image to a specific Node major (25, now EOL) for no benefit.
|
|
50
|
+
CMD ["node", "dist/index.js"]
|
package/dist/version.d.ts
CHANGED
package/dist/version.js
CHANGED
package/openapi.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"openapi": "3.1.0",
|
|
3
3
|
"info": {
|
|
4
4
|
"title": "Home Assistant MCP Wrapper",
|
|
5
|
-
"version": "1.5.
|
|
5
|
+
"version": "1.5.6",
|
|
6
6
|
"description": "REST endpoints that wrap MCP tools for Home Assistant integration. Raw JSON-RPC passthrough available at POST / for n8n compatibility."
|
|
7
7
|
},
|
|
8
8
|
"servers": [
|
package/package.json
CHANGED
package/src/version.ts
CHANGED