Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 55 additions & 8 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,62 @@
## What
## Description / 变更描述

<!-- briefly describe what changed -->
<!--
Describe what changed and why. / 描述本次修改内容以及原因。
Related Issue / 关联 Issue: #123
-->

## Why

<!-- why was this change needed -->
## Type of change / 变更类型

## Tested
- [ ] bugfix: Bug fix / 问题修复
- [ ] new feature: New feature / 新功能
- [ ] refactor: Code refactoring and optimization / 重构与优化
- [ ] breaking: Breaking change / 破坏性变更
- [ ] docs: Documentation / 文档更新

<!-- how did you verify it works -->
## Testing / 测试

## Checklist
<!-- Please provide test environment. / 请填写测试环境。 -->

- [ ] code style / CI green
- HA Version / HA版本:
- Add-on Version / 加载项版本:
- Test Result / 测试结果:

## Checklist / 自检清单

- [ ] Code follows project standards / 代码符合项目规范
- [ ] No debug code or unrelated files / 无调试代码或无关文件

<!--
PR Rules / PR 规范

Title / 标题:
Format / 格式:
<type>: <description>

Examples / 示例:

feat: add qoder channel support
fix: resolve checkin timezone offset
refactor: simplify pool selection
breaking: change config option format
docs: update installation guide

Branch / 分支:
Do not submit PR from main/master
禁止从 main/master 提交 PR

Change Type / 变更类型:
Select exactly one option below
请只选择一个类型

CI checks / CI 检查:
- Title / 标题
- Branch / 分支
- Description / 描述
- Change Type / 变更类型

IMPORTANT / 重要提示:
Please fill in the template as-is. Do not modify the template structure.
请严格按照模板填写,不要修改模板结构。
-->
70 changes: 70 additions & 0 deletions .github/labels.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# GitHub Labels —— 由 .github/workflows/sync-labels.yml 推送到仓库。
#
# 带 emoji 的 5 个是「变更类型」标签,必须与以下两处严格一致:
# - .github/workflows/pr-label.yml (打标)
# - .github/release.yml (release notes 分类)
# 改名字要三处同改,否则 release notes 分类会漏。
- name: "✨ Feature"
color: a2eeef
description: New feature / 新功能

- name: "🐛 Bug Fix"
color: d73a4a
description: Bug fix / 问题修复

- name: "🔧 Refactor"
color: 7057ff
description: Code refactoring and optimization / 重构与优化

- name: "⚠️ Breaking"
color: e4e669
description: Breaking change / 破坏性变更

- name: "📝 Docs"
color: 0075ca
description: Documentation / 文档更新

# === 以下为 GitHub 默认标签(保留,带中文说明)===
- name: bug
color: d73a4a
description: Something isn't working / 出现了问题或功能异常

- name: documentation
color: 0075ca
description: Improvements or additions to documentation / 文档改进或补充

- name: duplicate
color: cfd3d7
description: This issue or pull request already exists / 重复的问题或拉取请求

- name: enhancement
color: a2eeef
description: New feature or request / 新功能或改进请求

- name: good first issue
color: 7057ff
description: Good for newcomers / 适合新贡献者的简单问题

- name: help wanted
color: 008672
description: Extra attention is needed / 需要额外帮助或关注

- name: invalid
color: e4e669
description: This doesn't seem right / 内容不正确

- name: question
color: d876e3
description: Further information is requested / 需要更多信息

- name: wontfix
color: ffffff
description: This will not be worked on / 不会处理

- name: stale
color: eeeeee
description: Inactive issue / 长期无活动的问题

- name: stale-closed
color: eeeeee
description: Closed due to inactivity / 因长期无活动而关闭
25 changes: 25 additions & 0 deletions .github/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
changelog:
categories:
- title: "✨ Features / 新功能"
labels:
- "✨ Feature"

- title: "🐛 Bug Fixes / 问题修复"
labels:
- "🐛 Bug Fix"

- title: "🔧 Refactor / 重构"
labels:
- "🔧 Refactor"

- title: "📝 Documentation / 文档"
labels:
- "📝 Docs"

- title: "⚠️ Breaking Changes / 破坏性变更"
labels:
- "⚠️ Breaking"

- title: "Other Changes / 其他"
labels:
- "*"
40 changes: 40 additions & 0 deletions .github/scripts/read_addon_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env python3
"""从 HA add-on 的 config.yaml 读取 version 字段并打印。

单独成文件而非内联 `python3 -c`:内联时引号要同时穿过
YAML 块标量 + shell 双引号 + Python 字符串三层,实测会因
['\\''] 这类写法直接 SyntaxError(已在本地复现)。

用法: read_addon_version.py <path-to-config.yaml>
退出码: 0 = 成功打印版本;1 = 找不到 version 字段
"""
import re
import sys

# 兼容 version: "1.1.0b13" / version: '1.1.0' / version: 1.2.3 / 多余空格
PATTERN = re.compile(r"""^version:\s*["']?([^"'\s#]+)""")


def read_version(path: str) -> str:
with open(path, encoding="utf-8") as fh:
for line in fh:
match = PATTERN.match(line)
if match:
return match.group(1)
return ""


def main() -> int:
if len(sys.argv) != 2:
print("usage: read_addon_version.py <config.yaml>", file=sys.stderr)
return 1
version = read_version(sys.argv[1])
if not version:
print(f"no version field found in {sys.argv[1]}", file=sys.stderr)
return 1
print(version)
return 0


if __name__ == "__main__":
sys.exit(main())
129 changes: 129 additions & 0 deletions .github/workflows/build-image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
name: Build Add-on Image

# 预构建镜像(HA 官方推荐的发布方式)。
#
# 现状对比:
# 现在 = Supervisor 在用户设备上编译(拉 golang 镜像 + 编 5 个 Go 二进制),
# 树莓派上可能十几分钟,网络抖动即失败。官方称此法应"migrate away"。
# 本流程 = 在 CI 编译 amd64 + aarch64,推到 ghcr.io,用户只下载镜像。
#
# 用 HA 官方 builder actions(home-assistant/builder),而非手写 buildx:
# 它会自动注入 BUILD_ARCH / BUILD_VERSION,并写入 io.hass.* 标签。
on:
push:
branches: [main, master]
paths:
- 'config.yaml'
- 'Dockerfile'
- 'src/**'
- 'run.sh'
- 'login_ui.py'
- '.github/workflows/build-image.yml'
workflow_dispatch:
inputs:
version:
description: '要构建的版本(留空则读 config.yaml)'
required: false
type: string

permissions:
contents: read
packages: write
id-token: write

env:
ARCHITECTURES: '["amd64", "aarch64"]'
IMAGE_NAME: ai-proxy

jobs:
init:
name: Resolve version & matrix
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.matrix }}
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v4

- name: Resolve version
id: version
run: |
set -euo pipefail
if [ -n "${{ inputs.version }}" ]; then
VER="${{ inputs.version }}"
else
VER="$(python3 .github/scripts/read_addon_version.py config.yaml)"
fi
echo "version=${VER}" >> $GITHUB_OUTPUT
echo "Building version: ${VER}"

- name: Get build matrix
id: matrix
uses: home-assistant/builder/actions/prepare-multi-arch-matrix@7.2.0
with:
architectures: ${{ env.ARCHITECTURES }}
image-name: ${{ env.IMAGE_NAME }}

build:
name: Build ${{ matrix.arch }}
needs: init
runs-on: ${{ matrix.os }}
permissions:
contents: read
id-token: write
packages: write
strategy:
fail-fast: false
matrix: ${{ fromJSON(needs.init.outputs.matrix) }}
steps:
- uses: actions/checkout@v4

- name: Build image
uses: home-assistant/builder/actions/build-image@7.2.0
with:
arch: ${{ matrix.arch }}
container-registry-password: ${{ secrets.GITHUB_TOKEN }}
image: ${{ matrix.image }}
image-tags: |
${{ needs.init.outputs.version }}
latest
push: "true"
version: ${{ needs.init.outputs.version }}

manifest:
name: Publish multi-arch manifest
needs: [init, build]
runs-on: ubuntu-latest
permissions:
id-token: write
packages: write
steps:
- name: Publish multi-arch manifest
uses: home-assistant/builder/actions/publish-multi-arch-manifest@7.2.0
with:
architectures: ${{ env.ARCHITECTURES }}
container-registry-password: ${{ secrets.GITHUB_TOKEN }}
image-name: ${{ env.IMAGE_NAME }}
image-tags: |
${{ needs.init.outputs.version }}
latest

# 关键校验:config.yaml 的 version 必须与镜像 tag 一致。
# 官方文档明确:image 模式下 version "needs to match the tag of the image"。
# 不一致 = 用户拉不到镜像,且是静默的——所以在这里显式失败。
verify:
name: Verify image reachable
needs: [init, manifest]
runs-on: ubuntu-latest
steps:
- name: Verify manifest tag matches config.yaml version
run: |
set -euo pipefail
IMAGE="ghcr.io/${{ github.repository_owner }}/${IMAGE_NAME}"
VERSION="${{ needs.init.outputs.version }}"
echo "Checking ${IMAGE}:${VERSION}"
if ! docker manifest inspect "${IMAGE}:${VERSION}" >/dev/null 2>&1; then
echo "::error::Image ${IMAGE}:${VERSION} not found — config.yaml version 与镜像 tag 不一致,用户将无法安装"
exit 1
fi
echo "Image ${IMAGE}:${VERSION} is reachable"
47 changes: 47 additions & 0 deletions .github/workflows/go-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: go-ci

# 门禁:编译 + 静态检查 + 单测。
# 此前仓库无任何 CI,TECHNICAL-DOC 的审计本身是在「无 Go 工具链」下做的静态审阅,
# 改动无法自动验证。本 workflow 补上这门禁。
on:
push:
branches: [master, dev]
paths:
- 'src/**'
- 'Dockerfile'
- '.github/workflows/go-ci.yml'
pull_request:
paths:
- 'src/**'
- 'Dockerfile'
- '.github/workflows/go-ci.yml'
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: src
steps:
- uses: actions/checkout@v4

- uses: actions/setup-go@v5
with:
go-version: '1.25.x'
cache-dependency-path: src/go.sum

- name: go build
run: go build ./...

- name: go vet
run: go vet ./...

- name: go test
run: go test ./...

# addon 的构建路径与本地 go build 不同(5 个二进制 + 多架构),
# 单独确认 Dockerfile 仍能编译,避免只在 HA 构建时才发现。
- name: docker build (addon 构建路径)
working-directory: .
run: docker build --build-arg BUILD_ARCH=amd64 --build-arg BUILD_VERSION=ci .
Loading
Loading