mirror of
https://github.com/arch3rPro/1Panel-Appstore.git
synced 2026-04-15 00:17:12 +08:00
feat: add AI-powered 1Panel app builder skill
- Add skill configuration for generating 1Panel app configs via AI - Include templates for data.yml and docker-compose.yml - Add utility scripts for app generation, icon download, and validation - Provide reference examples and usage documentation - Update .gitignore to exclude .trae directory - Update README.md with skill usage instructions
This commit is contained in:
257
skills/scripts/validate-app.sh
Normal file
257
skills/scripts/validate-app.sh
Normal file
@@ -0,0 +1,257 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# =============================================================================
|
||||
# 1Panel App Validator - 验证生成的配置是否符合规范
|
||||
# 用法:./validate-app.sh <app-directory>
|
||||
# =============================================================================
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
# 颜色定义
|
||||
RED='\033[0;31m'
|
||||
GREEN='\033[0;32m'
|
||||
YELLOW='\033[1;33m'
|
||||
BLUE='\033[0;34m'
|
||||
NC='\033[0m'
|
||||
|
||||
# 计数器
|
||||
ERRORS=0
|
||||
WARNINGS=0
|
||||
|
||||
# 打印帮助
|
||||
print_help() {
|
||||
cat << EOF
|
||||
${BLUE}1Panel App Validator${NC} - 验证应用配置是否符合规范
|
||||
|
||||
${YELLOW}用法:${NC}
|
||||
$0 <app-directory>
|
||||
|
||||
${YELLOW}检查项目:${NC}
|
||||
- 目录结构完整性
|
||||
- data.yml 格式正确性
|
||||
- docker-compose.yml 变量使用
|
||||
- logo.png 是否存在
|
||||
- README 文件是否存在
|
||||
|
||||
${YELLOW}示例:${NC}
|
||||
$0 ./apps/alist
|
||||
EOF
|
||||
}
|
||||
|
||||
# 日志函数
|
||||
log_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
|
||||
log_warn() { echo -e "${YELLOW}[WARN]${NC} $1"; ((WARNINGS++)); }
|
||||
log_error() { echo -e "${RED}[ERROR]${NC} $1"; ((ERRORS++)); }
|
||||
|
||||
# 检查目录结构
|
||||
check_directory_structure() {
|
||||
local app_dir="$1"
|
||||
local app_name
|
||||
app_name=$(basename "$app_dir")
|
||||
|
||||
log_info "检查目录结构: $app_name"
|
||||
|
||||
# 检查必需文件
|
||||
if [[ ! -f "$app_dir/data.yml" ]]; then
|
||||
log_error "缺少顶层 data.yml"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$app_dir/logo.png" ]]; then
|
||||
log_error "缺少 logo.png"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$app_dir/README.md" ]]; then
|
||||
log_warn "缺少 README.md(推荐)"
|
||||
fi
|
||||
|
||||
# 查找版本目录
|
||||
local version_dirs
|
||||
version_dirs=$(find "$app_dir" -maxdepth 1 -type d -name "v*" -o -name "latest" -o -name "[0-9]*" 2>/dev/null || echo "")
|
||||
|
||||
if [[ -z "$version_dirs" ]]; then
|
||||
log_error "未找到版本目录(如 1.0.0/, v1.0.0/, latest/)"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查每个版本目录
|
||||
for version_dir in $version_dirs; do
|
||||
log_info "检查版本目录: $(basename "$version_dir")"
|
||||
|
||||
if [[ ! -f "$version_dir/data.yml" ]]; then
|
||||
log_error "版本目录缺少 data.yml: $version_dir"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$version_dir/docker-compose.yml" ]]; then
|
||||
log_error "版本目录缺少 docker-compose.yml: $version_dir"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
# 验证顶层 data.yml
|
||||
validate_top_data_yml() {
|
||||
local data_file="$1"
|
||||
|
||||
log_info "验证顶层 data.yml"
|
||||
|
||||
if [[ ! -f "$data_file" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查必需字段
|
||||
local required_fields=("name" "title" "description")
|
||||
for field in "${required_fields[@]}"; do
|
||||
if ! grep -q "^${field}:" "$data_file"; then
|
||||
log_error "data.yml 缺少必需字段: $field"
|
||||
fi
|
||||
done
|
||||
|
||||
# 检查 additionalProperties
|
||||
if ! grep -q "additionalProperties:" "$data_file"; then
|
||||
log_error "data.yml 缺少 additionalProperties"
|
||||
fi
|
||||
|
||||
# 检查 key
|
||||
if ! grep -q "key:" "$data_file"; then
|
||||
log_error "data.yml 缺少 additionalProperties.key"
|
||||
fi
|
||||
|
||||
# 检查 tags
|
||||
if ! grep -q "tags:" "$data_file"; then
|
||||
log_warn "data.yml 缺少 tags(推荐)"
|
||||
fi
|
||||
|
||||
# 检查 architectures
|
||||
if ! grep -q "architectures:" "$data_file"; then
|
||||
log_warn "data.yml 缺少 architectures(推荐)"
|
||||
fi
|
||||
}
|
||||
|
||||
# 验证版本 data.yml
|
||||
validate_version_data_yml() {
|
||||
local data_file="$1"
|
||||
|
||||
log_info "验证版本 data.yml"
|
||||
|
||||
if [[ ! -f "$data_file" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查 formFields
|
||||
if ! grep -q "formFields:" "$data_file"; then
|
||||
log_warn "版本 data.yml 缺少 formFields(如果无可配置参数则忽略)"
|
||||
return 0
|
||||
fi
|
||||
|
||||
# 检查每个参数是否有 envKey
|
||||
local param_count
|
||||
param_count=$(grep -c "envKey:" "$data_file" 2>/dev/null || echo "0")
|
||||
|
||||
if [[ "$param_count" -eq 0 ]]; then
|
||||
log_warn "formFields 中未找到 envKey 定义"
|
||||
else
|
||||
log_info "找到 $param_count 个可配置参数"
|
||||
fi
|
||||
}
|
||||
|
||||
# 验证 docker-compose.yml
|
||||
validate_docker_compose() {
|
||||
local compose_file="$1"
|
||||
|
||||
log_info "验证 docker-compose.yml"
|
||||
|
||||
if [[ ! -f "$compose_file" ]]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# 检查 container_name 使用变量
|
||||
if grep -q "container_name:" "$compose_file"; then
|
||||
if ! grep -q 'container_name:.*\${CONTAINER_NAME}' "$compose_file"; then
|
||||
log_error "container_name 必须使用 \${CONTAINER_NAME} 变量"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 检查 networks
|
||||
if ! grep -q "1panel-network:" "$compose_file"; then
|
||||
log_error "docker-compose.yml 缺少 1panel-network"
|
||||
fi
|
||||
|
||||
if ! grep -q "external: true" "$compose_file"; then
|
||||
log_error "1panel-network 必须设置为 external: true"
|
||||
fi
|
||||
|
||||
# 检查 restart
|
||||
if ! grep -q "restart: always" "$compose_file"; then
|
||||
log_warn "建议设置 restart: always"
|
||||
fi
|
||||
|
||||
# 检查 labels
|
||||
if ! grep -q 'createdBy: "Apps"' "$compose_file"; then
|
||||
log_warn "建议添加 labels: createdBy: \"Apps\""
|
||||
fi
|
||||
|
||||
# 检查端口映射使用变量
|
||||
if grep -q "ports:" "$compose_file"; then
|
||||
if ! grep -q 'PANEL_APP_PORT_' "$compose_file"; then
|
||||
log_warn "端口映射建议使用 PANEL_APP_PORT_* 变量"
|
||||
fi
|
||||
fi
|
||||
|
||||
# 检查数据卷路径
|
||||
if grep -q "volumes:" "$compose_file"; then
|
||||
if grep -qE '^\s+- /[a-zA-Z]' "$compose_file"; then
|
||||
log_warn "检测到绝对路径的数据卷,建议使用 ./data/ 相对路径"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# 主函数
|
||||
main() {
|
||||
local app_dir="${1:-}"
|
||||
|
||||
# 参数检查
|
||||
if [[ -z "$app_dir" ]] || [[ "$app_dir" == "-h" ]] || [[ "$app_dir" == "--help" ]]; then
|
||||
print_help
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ ! -d "$app_dir" ]]; then
|
||||
log_error "目录不存在: $app_dir"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo -e "${BLUE}=== 1Panel App Validator ===${NC}"
|
||||
echo ""
|
||||
|
||||
# 执行检查
|
||||
check_directory_structure "$app_dir"
|
||||
validate_top_data_yml "$app_dir/data.yml"
|
||||
|
||||
# 查找并验证版本目录
|
||||
local version_dirs
|
||||
version_dirs=$(find "$app_dir" -maxdepth 1 -type d \( -name "v*" -o -name "latest" -o -name "[0-9]*" \) 2>/dev/null || echo "")
|
||||
|
||||
for version_dir in $version_dirs; do
|
||||
validate_version_data_yml "$version_dir/data.yml"
|
||||
validate_docker_compose "$version_dir/docker-compose.yml"
|
||||
done
|
||||
|
||||
# 输出结果
|
||||
echo ""
|
||||
echo -e "${BLUE}=== 验证结果 ===${NC}"
|
||||
echo ""
|
||||
|
||||
if [[ $ERRORS -eq 0 ]] && [[ $WARNINGS -eq 0 ]]; then
|
||||
echo -e "${GREEN}✓ 验证通过!未发现问题。${NC}"
|
||||
exit 0
|
||||
elif [[ $ERRORS -eq 0 ]]; then
|
||||
echo -e "${YELLOW}⚠ 验证通过,但有 $WARNINGS 个警告。${NC}"
|
||||
exit 0
|
||||
else
|
||||
echo -e "${RED}✗ 验证失败!发现 $ERRORS 个错误和 $WARNINGS 个警告。${NC}"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# 执行主函数
|
||||
main "$@"
|
||||
Reference in New Issue
Block a user