diff --git a/README.md b/README.md index 5445761f..6f304a77 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ # What is Websoft9? -Websoft9 is web-based PaaS for running 200+ hot [open source application](https://github.com/Websoft9/docker-library/tree/main/apps) on your own server. +Websoft9 is web-based PaaS platform for running 200+ hot [open source application](https://github.com/Websoft9/docker-library/tree/main/apps) on your own server. Websoft9 help you running multiple applications in a single server, that means we believe Microservices on single machine is reasonable. On the contrary, it becomes more and more valuable as computing power increases @@ -44,18 +44,14 @@ You should have root privileges user to install or upgrade Websoft9, if you use wget https://websoft9.github.io/websoft9/install/install.sh && bash install.sh ``` +When installation completed, you can access it by: **http://Internet IP:9000** and using **Linux user** for login + ## Upgrade ``` curl https://websoft9.github.io/websoft9/install/update.sh | bash ``` -## Getting Started - -Using local Chrome or Firefox to visit the URL http://domain:9000 name or http://Internet IP:9000, you will enter the websoft9 - -> Login using the username and password of the Linux operating system - # Contributing Follow the [contributing guidelines](CONTRIBUTING.md) if you want to propose a change in the Websoft9 core. For more information about participating in the community and contributing to the Websoft9 project, see [this page](https://support.websoft9.com/docs/community/contributing). diff --git a/appmanage/README.md b/appmanage/README.md index 031009ec..47793165 100644 --- a/appmanage/README.md +++ b/appmanage/README.md @@ -1,4 +1,8 @@ -# 概述 +# AppManage -appmange 是软件商店的一个重要微服务,管理商店App的安装、卸载、启动、停止以及查询功能。 +AppManage is the core of Websoft9 which can manage application: Create, Stop, Uninstall, Listing + +* [API-design](docs/API-design.md) +* [Architecture](docs/architecture.md) +* [Developer](docs/developer.md) diff --git a/appmanage/docs/API-design.md b/appmanage/docs/API-design.md new file mode 100644 index 00000000..7df23080 --- /dev/null +++ b/appmanage/docs/API-design.md @@ -0,0 +1,289 @@ +# API Design + +## API 结构 + +### 请求 + +#### 请求方式 + +支持如下两种调用方式: + +- get +- post + +#### 请求头(公共参数) + +| 参数名称 | 用途 | 类型 | 必要性 | +| -------- | ------------ | ------ | ------ | +| Version | 接口版本 | string | 可选 | +| Language | 接口显示语言 | string | 可选 | + +#### 安全验证 + +本微服务没有安全验证模块,需通过 API 网关实现 + +#### 请求主体 + +[业务接口详情](#业务接口详情) + +### 响应结果 + +#### 响应头(公共参数) + +| 返回参数 | 用途 | 类型 | 必要性 | +| ----------- | ---------------------------------- | ------- | ------ | +| HTTP 状态码 | 判断接口调用是否成功(200 或 404) | Integer | 必须 | + +#### 响应主体 + +| 返回参数 | 用途 | 类型 | 必要性 | +| ------------ | -------------------- | -------------------- | ---------------------- | +| ResponseData | 各个接口的业务数据 | object(依据接口而异) | 必须 | +| Error | 错误 code 和错误信息 | ErrorInfo | 非必须 ,无错误时不返回 | + +``` +{ + "ResponseData": { + app_id: "xxxx", + StatusReason: { + Code: "Requirement.NotEnough", + Message: "Insufficient system resources (cpu, memory, disk space).", + Detail: "Error detail information" + } + }, + "Error": { + Code: "Requirement.NotEnough", + Message: "Insufficient system resources (cpu, memory, disk space).", + Detail: "Error detail information" + } +} +``` + +#### 错误代码设计 + +错误代码参考 [AWS API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html) 的分类方式: + +- Client errors: These errors are usually caused by something the client did, such as specifying an incorrect or invalid parameter in the request, or using an action or resource on behalf of a user that doesn't have permission to use the action or resource. These errors are accompanied by a 400-series HTTP response code. + +- Server errors: These errors are usually caused by an AWS server-side issue. These errors are accompanied by a 500-series HTTP response code. + +##### Client errors + +| code | message | detail | +| ------------------------------------- | -------------- | ------ | +| Client.Parameter.Blank.Error | p 必填参数为空 | null | +| Client.Parameter.Format.Error | p 参数语法不符 | null | +| Client.Parameter.Value.NotExist.Error | p 参数值错误 | null | +| Client.Parameter.Value.Repeat.Error | p 参数值重复 | null | + +##### Server errors + +| code | message | detail | +| ---------------------- | ---------------------- | ------------ | +| Server.Container.Error | Docker 返回原始错误 | 错误详细信息 | +| Server.SystemError | 系统原始错误 | 错误详细信息 | +| Server.\*\*\* | 其他可以友好提示的错误 | 错误详细信息 | + +## 业务接口详情 + +各个业务接口的详细说明,公共参数不在这里继续说明。 + +### App 安装 + +#### Action + +AppInstall + +#### 请求参数 + +| 参数名称 | 用途 | 类型 | 必要性 | +| ----------------- | ------------------ | ------ | ------ | +| app_name | 应用名称 | string | 必须 | +| customer_app_name | 用户自定义应用名称 | string | 必须 | +| app_version | 应用版本 | string | 必须 | + +#### 返回结果 + +| 返回值 | 类型 | 必要性 | +| ------------ | ------------- | ------ | +| ResponseData | String(AppID) | 必须 | +| Error | ErrorInfo | 非必须 | + +### App 卸载 + +#### Action + +AppUninstall + +#### 请求参数 + +| 参数名称 | 用途 | 类型 | 必要性 | +| -------- | ---------- | ------ | ------ | +| app_id | 卸载该 app | string | 必须 | + +#### 返回结果 + +| 返回值 | 类型 | 必要性 | +| ------------ | ------------- | ------ | +| ResponseData | String(AppID) | 必须 | +| error | ErrorInfo | 非必须 | + +### App 重启 + +#### Action + +AppRestart + +#### 请求参数 + +| 参数名称 | 用途 | 类型 | 必要性 | +| -------- | ---------- | ------ | ------ | +| app_id | 重启该 app | string | 必须 | + +#### 返回结果 + +| 返回值 | 类型 | 必要性 | +| ------------ | ------------- | ------ | +| ResponseData | String(AppID) | 必须 | +| error | ErrorInfo | 非必须 | + +### App 启动 + +#### Action + +AppStart + +#### 请求参数 + +| 参数名称 | 用途 | 类型 | 必要性 | +| -------- | ---------- | ------ | ------ | +| app_id | 启动该 app | string | 必须 | + +#### 返回结果 + +| 返回值 | 类型 | 必要性 | +| ------------ | ------------- | ------ | +| ResponseData | String(AppID) | 必须 | +| error | ErrorInfo | 非必须 | + +### App 停止 + +#### Action + +AppStop + +#### 请求参数 + +| 参数名称 | 用途 | 类型 | 必要性 | +| -------- | ---------- | ------ | ------ | +| app_id | 停止该 app | string | 必须 | + +#### 返回结果 + +| 返回值 | 类型 | 必要性 | +| ------------ | ------------- | ------ | +| ResponseData | String(AppID) | 必须 | +| error | ErrorInfo | 非必须 | + +### App 状态查询 + +#### Action + +AppStatus + +#### 请求参数 + +| 参数名称 | 用途 | 类型 | 必要性 | +| -------- | ----------------- | ------ | ------ | +| app_id | 查询该 app 的信息 | string | 必须 | + +#### 返回结果 + +| 返回值 | 类型 | 必要性 | +| ------------ | ------------- | ------ | +| ResponseData | AppStatusInfo | 必须 | +| error | ErrorInfo | 非必须 | + +AppStatusInfo 说明: + +``` +{ + +  app_id:应用ID, + +  status:应用运行状态,[installing(创建中),running(运行中),exited(停止),restarting(反复重启),failed(失败)] + + status_reason:{ // 只有failed时才有内容 + Code:错误代码 + Message:错误提示信息 + Detail:错误真实信息 + } +   +} +``` + +### App 列表查询 + +#### Action + +AppList + +#### 请求参数 + +| 参数名称 | 用途 | 类型 | 必要性 | +| -------- | -------------- | ------ | ------ | +| app_id | 查询指定的 app | string | 非必须 | + +#### 返回结果 + +| 返回值 | 类型 | 必要性 | +| ------------ | ---------------------- | ------ | +| ResponseData | Array of AppDetailInfo | 必须 | +| error | ErrorInfo | 非必须 | + +AppDetailInfo 说明: + +``` +{ + +  app_id:应用ID, + +  name:应用名, + +  customer_name:自定义应用名, + +  trade_mark:应用商标, + +  status:应用运行状态,[installing(创建中),running(运行中),exited(停止),restarting(反复重启),failed(失败)] + + status_reason:{ // 只有failed时才有内容 + Code:错误代码 + Message:错误提示信息 + Detail:错误真实信息 + }, + + official_app:是否为官方应用, + + image_url:图片路径, + + running_info: { // 只有status=running才有值,其他时候为空 + + port:应用端口, + +   compose_file:docker compose文件路径, + +   url:应用网址, + + admin_url:管理员网址, + +   user_name:用户名, + +   password:密码, + + default_domain: 默认域名, + + set_domain: 用户自定义域名, + } +   +} +``` diff --git a/appmanage/docs/administrator.md b/appmanage/docs/administrator.md deleted file mode 100644 index cdce5042..00000000 --- a/appmanage/docs/administrator.md +++ /dev/null @@ -1,22 +0,0 @@ -# Administrator 管理手册 - -## 环境 - -### 安装组件 - -1. python 环境 - 确保安装 python3.6+ - -2. python 的 pip 包 fastapi,uvicorn[standard],gunicorn - -``` -pip install -r requirements.txt -``` - -3. 安装 docker 以及 docker compose、创建 docker 网络 websoft9 - -### 启动 - -``` -git clone https://github.com/Websoft9/stackhub.git && cd stackhub/docker/appmanage && docker compose up -d -``` diff --git a/appmanage/docs/architecture.md b/appmanage/docs/architecture.md index c47b4d52..a63233ab 100644 --- a/appmanage/docs/architecture.md +++ b/appmanage/docs/architecture.md @@ -1,37 +1,82 @@ -# appmanage +# Architecture -![image](https://user-images.githubusercontent.com/43192516/231104572-a57940b1-273b-4761-ae82-7139a8966f70.png) +AppManage is develop by Python3.10, use [FastAPI](https://github.com/Websoft9/stackhub/blob/main/appmanage/docs/developer.md), [RQ](https://python-rq.org/), logging packages and Redis, Sqlite for data storage + +It have the privilege of host machine, and running below jobs on host: + +* docker and docker compose +* modify file -## RQ +## Asynchronous jobs - RQ -### 设计 +Create application by docker some time need many time, so we use [RQ](https://python-rq.org/) for queueing jobs and processing them in the background with workers -RQ 用于异步处理**创建应用**的事务任务,需保证任务成功或失败后续处理。 - -它提供的状态有: - -- creating: 创建中 -- failed: 创建失败 +![image](images/rq.png) -### RQ status +RQ sample for development: -RQ 主要解决创建应用的状态 +``` +# Job started +rq worker --url redis://websoft9-redis:6379/0 -![image](https://user-images.githubusercontent.com/43192516/231103506-22bbfc80-f31f-4ba0-a331-4a05a345ec25.png) +# RQ 队列创建: +## 指定 Redis 容器的主机名和端口 +redis_conn = Redis(host='websoft9-redis', port=6379) -## docker compose status +## 使用指定的 Redis 连接创建 RQ 队列 +q = Queue(connection=redis_conn,default_timeout=3600) -- running: 运行中 -- exited: 停止 -- restarting: 重启 -- created: 创建失败 +#RQ 队列新增排队任务: +q.enqueue(install_app_delay, app_name, customer_name, app_version, job_id=app_id) -## API status +#获取队列中任务的信息: +## 获取 StartedJobRegistry 实例 +started = StartedJobRegistry(queue=q) +finish = FinishedJobRegistry(queue=q) +deferred = DeferredJobRegistry(queue=q) +failed = FailedJobRegistry(queue=q) +scheduled = ScheduledJobRegistry(queue=q) +cancel = CanceledJobRegistry(queue=q) + +## 获取正在执行的作业 ID 列表 +run_job_ids = started.get_job_ids() +finish_job_ids = finish.get_job_ids() +wait_job_ids = deferred.get_job_ids() +failed_jobs = failed.get_job_ids() +scheduled_jobs = scheduled.get_job_ids() +cancel_jobs = cancel.get_job_ids() +``` + +## Logs partition + + ``` + logPath = 'logs/' + if not os.path.exists(logPath): + os.makedirs(logPath) + logName = 'app_manage.log' + logFile = logPath + logName + formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s') + # handler + time_rotating_file_handler = handlers.TimedRotatingFileHandler(filename=logFile, when="MIDNIGHT", interval=1, encoding='utf-8') + time_rotating_file_handler.setLevel(logging.DEBUG) + time_rotating_file_handler.setFormatter(formatter) + ``` + +## Application Status + +Application status is very import for developer to understand AppManage, it combine the [Docker compose status](https://docs.docker.com/engine/reference/commandline/compose_ps/#options) and [RQ status](https://python-rq.org/docs/job_registries/) - installing(创建中): 来源于 RQ 的queue或StartedJobRegistry, 可进行操作[无法进行任何操作] - running(运行中): 来源于docker compose,可进行操作[所有操作] - exited(停止): 来源于docker compose,可进行操作[Start,Restart,Uninstall,日志查看] - restarting(反复重启): 来源于docker compose,可进行操作[Stop,Restart,Uninstall,日志查看] - failed(失败): 来源于 docker compose 中的 created || RQ 的 FailedJobRegistry 可进行操作[Uninstall] + +> docker compose have status: [paused | restarting | removing | running | dead | created | exited] + + +## API + +FastAPI can create API and API docs of swagger, you can get [API design details](API-design.md) \ No newline at end of file diff --git a/appmanage/docs/developer.md b/appmanage/docs/developer.md index 222e6c5e..b4436265 100644 --- a/appmanage/docs/developer.md +++ b/appmanage/docs/developer.md @@ -1,289 +1,19 @@ -# API 设计文档 +# Developer -## API 结构 +## Deployment -### 请求 - -#### 请求方式 - -支持如下两种调用方式: - -- get -- post - -#### 请求头(公共参数) - -| 参数名称 | 用途 | 类型 | 必要性 | -| -------- | ------------ | ------ | ------ | -| Version | 接口版本 | string | 可选 | -| Language | 接口显示语言 | string | 可选 | - -#### 安全验证 - -本微服务没有安全验证模块,需通过 API 网关实现 - -#### 请求主体 - -[业务接口详情](#业务接口详情) - -### 响应结果 - -#### 响应头(公共参数) - -| 返回参数 | 用途 | 类型 | 必要性 | -| ----------- | ---------------------------------- | ------- | ------ | -| HTTP 状态码 | 判断接口调用是否成功(200 或 404) | Integer | 必须 | - -#### 响应主体 - -| 返回参数 | 用途 | 类型 | 必要性 | -| ------------ | -------------------- | -------------------- | ---------------------- | -| ResponseData | 各个接口的业务数据 | object(依据接口而异) | 必须 | -| Error | 错误 code 和错误信息 | ErrorInfo | 非必须 ,无错误时不返回 | +Install python3.6+ and Docker, then ``` -{ - "ResponseData": { - app_id: "xxxx", - StatusReason: { - Code: "Requirement.NotEnough", - Message: "Insufficient system resources (cpu, memory, disk space).", - Detail: "Error detail information" - } - }, - "Error": { - Code: "Requirement.NotEnough", - Message: "Insufficient system resources (cpu, memory, disk space).", - Detail: "Error detail information" - } -} +pip install -r requirements.txt +docker network create websoft9 +git clone https://github.com/Websoft9/stackhub.git && cd stackhub/docker/appmanage && docker compose up -d ``` -#### 错误代码设计 +## API UI -错误代码参考 [AWS API](https://docs.aws.amazon.com/AWSEC2/latest/APIReference/errors-overview.html) 的分类方式: +Access API by: **http://Internet IP:port/docs** -- Client errors: These errors are usually caused by something the client did, such as specifying an incorrect or invalid parameter in the request, or using an action or resource on behalf of a user that doesn't have permission to use the action or resource. These errors are accompanied by a 400-series HTTP response code. +### Test Automation -- Server errors: These errors are usually caused by an AWS server-side issue. These errors are accompanied by a 500-series HTTP response code. - -##### Client errors - -| code | message | detail | -| ------------------------------------- | -------------- | ------ | -| Client.Parameter.Blank.Error | p 必填参数为空 | null | -| Client.Parameter.Format.Error | p 参数语法不符 | null | -| Client.Parameter.Value.NotExist.Error | p 参数值错误 | null | -| Client.Parameter.Value.Repeat.Error | p 参数值重复 | null | - -##### Server errors - -| code | message | detail | -| ---------------------- | ---------------------- | ------------ | -| Server.Container.Error | Docker 返回原始错误 | 错误详细信息 | -| Server.SystemError | 系统原始错误 | 错误详细信息 | -| Server.\*\*\* | 其他可以友好提示的错误 | 错误详细信息 | - -## 业务接口详情 - -各个业务接口的详细说明,公共参数不在这里继续说明。 - -### App 安装 - -#### Action - -AppInstall - -#### 请求参数 - -| 参数名称 | 用途 | 类型 | 必要性 | -| ----------------- | ------------------ | ------ | ------ | -| app_name | 应用名称 | string | 必须 | -| customer_app_name | 用户自定义应用名称 | string | 必须 | -| app_version | 应用版本 | string | 必须 | - -#### 返回结果 - -| 返回值 | 类型 | 必要性 | -| ------------ | ------------- | ------ | -| ResponseData | String(AppID) | 必须 | -| Error | ErrorInfo | 非必须 | - -### App 卸载 - -#### Action - -AppUninstall - -#### 请求参数 - -| 参数名称 | 用途 | 类型 | 必要性 | -| -------- | ---------- | ------ | ------ | -| app_id | 卸载该 app | string | 必须 | - -#### 返回结果 - -| 返回值 | 类型 | 必要性 | -| ------------ | ------------- | ------ | -| ResponseData | String(AppID) | 必须 | -| error | ErrorInfo | 非必须 | - -### App 重启 - -#### Action - -AppRestart - -#### 请求参数 - -| 参数名称 | 用途 | 类型 | 必要性 | -| -------- | ---------- | ------ | ------ | -| app_id | 重启该 app | string | 必须 | - -#### 返回结果 - -| 返回值 | 类型 | 必要性 | -| ------------ | ------------- | ------ | -| ResponseData | String(AppID) | 必须 | -| error | ErrorInfo | 非必须 | - -### App 启动 - -#### Action - -AppStart - -#### 请求参数 - -| 参数名称 | 用途 | 类型 | 必要性 | -| -------- | ---------- | ------ | ------ | -| app_id | 启动该 app | string | 必须 | - -#### 返回结果 - -| 返回值 | 类型 | 必要性 | -| ------------ | ------------- | ------ | -| ResponseData | String(AppID) | 必须 | -| error | ErrorInfo | 非必须 | - -### App 停止 - -#### Action - -AppStop - -#### 请求参数 - -| 参数名称 | 用途 | 类型 | 必要性 | -| -------- | ---------- | ------ | ------ | -| app_id | 停止该 app | string | 必须 | - -#### 返回结果 - -| 返回值 | 类型 | 必要性 | -| ------------ | ------------- | ------ | -| ResponseData | String(AppID) | 必须 | -| error | ErrorInfo | 非必须 | - -### App 状态查询 - -#### Action - -AppStatus - -#### 请求参数 - -| 参数名称 | 用途 | 类型 | 必要性 | -| -------- | ----------------- | ------ | ------ | -| app_id | 查询该 app 的信息 | string | 必须 | - -#### 返回结果 - -| 返回值 | 类型 | 必要性 | -| ------------ | ------------- | ------ | -| ResponseData | AppStatusInfo | 必须 | -| error | ErrorInfo | 非必须 | - -AppStatusInfo 说明: - -``` -{ - -  app_id:应用ID, - -  status:应用运行状态,[installing(创建中),running(运行中),exited(停止),restarting(反复重启),failed(失败)] - - status_reason:{ // 只有failed时才有内容 - Code:错误代码 - Message:错误提示信息 - Detail:错误真实信息 - } -   -} -``` - -### App 列表查询 - -#### Action - -AppList - -#### 请求参数 - -| 参数名称 | 用途 | 类型 | 必要性 | -| -------- | -------------- | ------ | ------ | -| app_id | 查询指定的 app | string | 非必须 | - -#### 返回结果 - -| 返回值 | 类型 | 必要性 | -| ------------ | ---------------------- | ------ | -| ResponseData | Array of AppDetailInfo | 必须 | -| error | ErrorInfo | 非必须 | - -AppDetailInfo 说明: - -``` -{ - -  app_id:应用ID, - -  name:应用名, - -  customer_name:自定义应用名, - -  trade_mark:应用商标, - -  status:应用运行状态,[installing(创建中),running(运行中),exited(停止),restarting(反复重启),failed(失败)] - - status_reason:{ // 只有failed时才有内容 - Code:错误代码 - Message:错误提示信息 - Detail:错误真实信息 - }, - - official_app:是否为官方应用, - - image_url:图片路径, - - running_info: { // 只有status=running才有值,其他时候为空 - - port:应用端口, - -   compose_file:docker compose文件路径, - -   url:应用网址, - - admin_url:管理员网址, - -   user_name:用户名, - -   password:密码, - - default_domain: 默认域名, - - set_domain: 用户自定义域名, - } -   -} -``` +Coming soon... diff --git a/appmanage/docs/guide.md b/appmanage/docs/guide.md deleted file mode 100644 index 3256396f..00000000 --- a/appmanage/docs/guide.md +++ /dev/null @@ -1,9 +0,0 @@ -## 使用 - -### API - -安装 appmanage 后,可使用浏览器或Postman访问接口,自动生成文档地址:http://ip:port/redoc 或 http://ip:port/docs - -### CLI - -暂未提供 diff --git a/appmanage/docs/images/rq.png b/appmanage/docs/images/rq.png new file mode 100644 index 00000000..bed376f2 Binary files /dev/null and b/appmanage/docs/images/rq.png differ diff --git a/appmanage/test/README.md b/appmanage/test/README.md new file mode 100644 index 00000000..6ca2f2e8 --- /dev/null +++ b/appmanage/test/README.md @@ -0,0 +1,3 @@ +# Test + +Automatic testing script for API \ No newline at end of file diff --git a/docs/developer.md b/docs/developer.md index 2f99159c..3562c3f8 100644 --- a/docs/developer.md +++ b/docs/developer.md @@ -1,75 +1,6 @@ # Developer Guide -## Appmanage -### 开发环境以及组件 - -Python3.10, FastAPI, RQ, logging - -### 关键技术实现 - -#### 日志分割 - - ``` - logPath = 'logs/' - if not os.path.exists(logPath): - os.makedirs(logPath) - logName = 'app_manage.log' - logFile = logPath + logName - formatter = logging.Formatter('%(asctime)s %(levelname)s: %(message)s') - # handler - time_rotating_file_handler = handlers.TimedRotatingFileHandler(filename=logFile, when="MIDNIGHT", interval=1, encoding='utf-8') - time_rotating_file_handler.setLevel(logging.DEBUG) - time_rotating_file_handler.setFormatter(formatter) - ``` - -#### RQ - -任务管理器启动: - - ``` - rq worker --url redis://websoft9-redis:6379/0 - ``` - -RQ 队列创建: - - ``` - # 指定 Redis 容器的主机名和端口 - redis_conn = Redis(host='websoft9-redis', port=6379) - - # 使用指定的 Redis 连接创建 RQ 队列 - q = Queue(connection=redis_conn,default_timeout=3600) - ``` - -RQ 队列新增排队任务: - -``` -q.enqueue(install_app_delay, app_name, customer_name, app_version, job_id=app_id) -``` - -获取队列中任务的信息: - -``` -# 获取 StartedJobRegistry 实例 -started = StartedJobRegistry(queue=q) -finish = FinishedJobRegistry(queue=q) -deferred = DeferredJobRegistry(queue=q) -failed = FailedJobRegistry(queue=q) -scheduled = ScheduledJobRegistry(queue=q) -cancel = CanceledJobRegistry(queue=q) - -# 获取正在执行的作业 ID 列表 -run_job_ids = started.get_job_ids() -finish_job_ids = finish.get_job_ids() -wait_job_ids = deferred.get_job_ids() -failed_jobs = failed.get_job_ids() -scheduled_jobs = scheduled.get_job_ids() -cancel_jobs = cancel.get_job_ids() -``` - -### API 文档 - -[FastAPI 文档](https://github.com/Websoft9/stackhub/blob/main/appmanage/docs/developer.md) 使用 swagger 自动生成,访问地址:http://IP:PORT/docs。 ## 版本管理 diff --git a/docs/research.md b/docs/notes/research.md similarity index 100% rename from docs/research.md rename to docs/notes/research.md diff --git a/docs/软件工厂.md b/docs/notes/软件工厂.md similarity index 100% rename from docs/软件工厂.md rename to docs/notes/软件工厂.md diff --git a/tests/README.md b/tests/README.md deleted file mode 100644 index e69de29b..00000000