mirror of
https://github.com/certd/certd.git
synced 2026-04-14 12:30:54 +08:00
Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37a9e6aae0 | ||
|
|
6a8a02dae5 | ||
|
|
eaee5db69e | ||
|
|
25d06904c6 | ||
|
|
fa14f87a80 | ||
|
|
4404f99642 | ||
|
|
bafab905b4 | ||
|
|
44d5e54550 | ||
|
|
a23c13d7d9 | ||
|
|
17a7a1432f | ||
|
|
26e8932b85 | ||
|
|
32beb02d40 | ||
|
|
af7177e6bb | ||
|
|
69ac0fd0a8 | ||
|
|
e0998f35e8 | ||
|
|
6d371b38c3 | ||
|
|
587f11138a | ||
|
|
aa936c279e | ||
|
|
5b11d351b2 | ||
|
|
b45b97d3c6 | ||
|
|
338eb3bdfe | ||
|
|
f059e91efc | ||
|
|
1cdf1c433f | ||
|
|
a7b8bac4c8 | ||
|
|
b7b5df0587 | ||
|
|
4060f6ecbc | ||
|
|
7cb5f21444 | ||
|
|
e5da46cfc3 | ||
|
|
eabb3e38b5 | ||
|
|
46140c8efa | ||
|
|
95d071ba56 | ||
|
|
3c9c3ca3b0 | ||
|
|
e7c4ade57d | ||
|
|
ca524657b6 | ||
|
|
bc02559bc7 | ||
|
|
741172fd98 | ||
|
|
83d0209775 | ||
|
|
6693d1acfb | ||
|
|
a2c43b50a6 | ||
|
|
f7fc06e657 | ||
|
|
b9fe3b9c87 | ||
|
|
06be993afc | ||
|
|
b6ef39fb30 | ||
|
|
0b131c00ed | ||
|
|
b6b8661c36 | ||
|
|
7bf19f8f6f | ||
|
|
c9d9c6513b | ||
|
|
4e7b7ae974 | ||
|
|
dfcabc02a4 | ||
|
|
6f2c5674c9 | ||
|
|
2877b9b505 | ||
|
|
e40bb9e14d | ||
|
|
d456ff9830 | ||
|
|
ffddb3b4ac | ||
|
|
a6113f237b | ||
|
|
093520b686 | ||
|
|
3a8d44b8e9 | ||
|
|
72bff652f7 | ||
|
|
9559bdf817 | ||
|
|
5a88b8c24e | ||
|
|
a9ebac82c7 | ||
|
|
cfd8836083 | ||
|
|
e01e59b188 | ||
|
|
d2fd729961 | ||
|
|
5d4ff2e3b7 | ||
|
|
6e5133f6b8 | ||
|
|
a96d5839b2 | ||
|
|
a827bc306a | ||
|
|
d8b3d7a6e0 | ||
|
|
b8f072909b | ||
|
|
fa48f2b2f0 | ||
|
|
019a1fe24e | ||
|
|
427620d34f | ||
|
|
a5a0c1f6e7 | ||
|
|
affef13037 | ||
|
|
4afbf20c1a | ||
|
|
0ef7b036dd | ||
|
|
17ef7b8b9e | ||
|
|
15eba52fad | ||
|
|
f2d894b036 | ||
|
|
d9da27710e | ||
|
|
981bff70c3 | ||
|
|
bb30d6e02f | ||
|
|
b09ccda54d | ||
|
|
a5de8d79ec | ||
|
|
a092a1e843 | ||
|
|
1c6740feff | ||
|
|
79c6e05e02 | ||
|
|
31e2085c16 | ||
|
|
64fda2f1a0 | ||
|
|
a674719a8b | ||
|
|
2f7ef0620b | ||
|
|
153e98b593 | ||
|
|
d62ea41671 | ||
|
|
8fcd9813d3 | ||
|
|
dcbf8c85dd | ||
|
|
ea0eafdb16 | ||
|
|
eda89a057a | ||
|
|
21e6eef1d3 | ||
|
|
54a27c1840 | ||
|
|
a3be0a1618 | ||
|
|
8e19e44f4c | ||
|
|
e5d93bd114 |
58
.github/workflows/build-image.yml
vendored
Normal file
58
.github/workflows/build-image.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
name: build-image
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ['v2']
|
||||||
|
paths:
|
||||||
|
- "build.trigger"
|
||||||
|
|
||||||
|
# schedule:
|
||||||
|
# - # 国际时间 19:17 执行,北京时间3:17 ↙↙↙ 改成你想要每天自动执行的时间
|
||||||
|
# - cron: '17 19 * * *'
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-certd-image:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Code
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
|
||||||
|
- name: get_certd_version
|
||||||
|
id: get_certd_version
|
||||||
|
uses: actions/github-script@v6
|
||||||
|
with:
|
||||||
|
result-encoding: string
|
||||||
|
script: |
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const pnpmWorkspace = "./pnpm-workspace.yaml";
|
||||||
|
fs.unlinkSync(pnpmWorkspace)
|
||||||
|
const jsonFilePath = "./packages/ui/certd-server/package.json";
|
||||||
|
const jsonContent = fs.readFileSync(jsonFilePath, 'utf-8');
|
||||||
|
const pkg = JSON.parse(jsonContent)
|
||||||
|
console.log("certd_version:",pkg.version);
|
||||||
|
return pkg.version
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to aliyun container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: registry.cn-shenzhen.aliyuncs.com
|
||||||
|
username: ${{ secrets.aliyun_cs_username }}
|
||||||
|
password: ${{ secrets.aliyun_cs_password }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6.5.0
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
context: ./packages/ui/
|
||||||
|
tags: |
|
||||||
|
registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
||||||
|
registry.cn-shenzhen.aliyuncs.com/handsfree/certd:${{steps.get_certd_version.outputs.result}}
|
||||||
2
.github/workflows/sync-to-gitee.yml
vendored
2
.github/workflows/sync-to-gitee.yml
vendored
@@ -2,8 +2,6 @@ name: sync-to-gitee
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ['v2']
|
branches: ['v2']
|
||||||
pull_request:
|
|
||||||
branches: ['v2']
|
|
||||||
# schedule:
|
# schedule:
|
||||||
# - # 国际时间 19:17 执行,北京时间3:17 ↙↙↙ 改成你想要每天自动执行的时间
|
# - # 国际时间 19:17 执行,北京时间3:17 ↙↙↙ 改成你想要每天自动执行的时间
|
||||||
# - cron: '17 19 * * *'
|
# - cron: '17 19 * * *'
|
||||||
|
|||||||
27
CHANGELOG.md
27
CHANGELOG.md
@@ -3,6 +3,33 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.22.4](https://github.com/certd/certd/compare/v1.22.3...v1.22.4) (2024-07-26)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 证书申请支持反向代理,letsencrypt无法访问时的备用方案 ([b7b5df0](https://github.com/certd/certd/commit/b7b5df0587e0f7ea288c1b2af6f87211f207395f))
|
||||||
|
* 支持arm64 ([fa14f87](https://github.com/certd/certd/commit/fa14f87a8093ef3addc5e5f3315ce1bfc9982782))
|
||||||
|
|
||||||
|
## [1.22.3](https://github.com/certd/certd/compare/v1.22.2...v1.22.3) (2024-07-25)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* lege 无执行权限问题 ([338eb3b](https://github.com/certd/certd/commit/338eb3bdfeb461e9b3bc7eee97b97a59f5642ffe))
|
||||||
|
|
||||||
|
## [1.22.2](https://github.com/certd/certd/compare/v1.22.1...v1.22.2) (2024-07-23)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复创建流水线时,无法根据dns类型默认正确的dns授权的bug ([a2c43b5](https://github.com/certd/certd/commit/a2c43b50a6069ed48958fd142844a8568c2af452))
|
||||||
|
|
||||||
|
## [1.22.1](https://github.com/certd/certd/compare/v1.22.0...v1.22.1) (2024-07-20)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 创建证书任务可以选择lege插件 ([affef13](https://github.com/certd/certd/commit/affef130378030c517250c58a4e787b0fc85d7d1))
|
||||||
|
* 创建证书任务增加定时任务和邮件通知输入 ([427620d](https://github.com/certd/certd/commit/427620d34f3b8ad6933005faf1878908441a2453))
|
||||||
|
* 支持配置启动后自动触发一次任务 ([a5a0c1f](https://github.com/certd/certd/commit/a5a0c1f6e7a3f05e581005e491d5b102ee854412))
|
||||||
|
|
||||||
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
101
README.md
101
README.md
@@ -8,16 +8,14 @@ CertD 是一个免费全自动申请和自动部署更新SSL证书的工具。
|
|||||||
## 一、特性
|
## 一、特性
|
||||||
本项目不仅支持证书申请过程自动化,还可以自动化部署更新证书,让你的证书永不过期。
|
本项目不仅支持证书申请过程自动化,还可以自动化部署更新证书,让你的证书永不过期。
|
||||||
|
|
||||||
* 全自动申请证书(支持阿里云、腾讯云、华为云、Cloudflare注册的域名)
|
* 全自动申请证书(支持阿里云、腾讯云、华为云、Cloudflare等各种途径注册的域名)
|
||||||
* 全自动部署更新证书(目前支持服务器上传部署、部署到阿里云、腾讯云等)
|
* 全自动部署更新证书(目前支持部署到主机、部署到阿里云、腾讯云等)
|
||||||
* 支持通配符域名
|
* 支持通配符域名/泛域名,支持多个域名打到一个证书上
|
||||||
* 支持多个域名打到一个证书上
|
|
||||||
* 邮件通知
|
* 邮件通知
|
||||||
* 证书自动更新
|
* 私有化部署,保障安全
|
||||||
* 免费、免费、免费([阿里云单个通配符域名证书最便宜也要1800/年](https://yundun.console.aliyun.com/?p=cas#/certExtend/buy/cn-hangzhou))
|
* 免费、免费、免费([阿里云单个通配符域名证书最便宜也要1800/年](https://yundun.console.aliyun.com/?p=cas#/certExtend/buy/cn-hangzhou))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## 二、在线体验
|
## 二、在线体验
|
||||||
|
|
||||||
官方Demo地址,自助注册后体验
|
官方Demo地址,自助注册后体验
|
||||||
@@ -40,7 +38,9 @@ https://certd.handsfree.work/
|
|||||||
-------> [点我查看详细使用步骤演示](./step.md) <--------
|
-------> [点我查看详细使用步骤演示](./step.md) <--------
|
||||||
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
|
||||||
|
|
||||||
## 四、本地docker部署
|
## 四、私有化部署
|
||||||
|
|
||||||
|
由于证书、授权信息等属于高度敏感数据,请务必私有化部署,保障数据安全
|
||||||
|
|
||||||
### 1. 安装docker、docker-compose
|
### 1. 安装docker、docker-compose
|
||||||
|
|
||||||
@@ -49,61 +49,71 @@ https://certd.handsfree.work/
|
|||||||
* 【腾讯云】云服务器2核2G,新老用户同享,99元/年,续费同价!【 [立即购买](https://cloud.tencent.com/act/cps/redirect?redirect=6094&cps_key=b3ef73330335d7a6efa4a4bbeeb6b2c9&from=console)】
|
* 【腾讯云】云服务器2核2G,新老用户同享,99元/年,续费同价!【 [立即购买](https://cloud.tencent.com/act/cps/redirect?redirect=6094&cps_key=b3ef73330335d7a6efa4a4bbeeb6b2c9&from=console)】
|
||||||
|
|
||||||
|
|
||||||
1.2 安装docker
|
1.2 安装docker
|
||||||
https://docs.docker.com/engine/install/
|
|
||||||
选择对应的操作系统,按照官方文档执行命令即可
|
|
||||||
|
|
||||||
|
https://docs.docker.com/engine/install/
|
||||||
|
选择对应的操作系统,按照官方文档执行命令即可
|
||||||
|
|
||||||
### 2. 下载docker-compose.yaml文件
|
### 2. 运行certd
|
||||||
|
|
||||||
[docker-compose.yaml下载](https://gitee.com/certd/certd/raw/v2/docker/run/docker-compose.yaml)
|
[docker-compose.yaml 下载](https://gitee.com/certd/certd/raw/v2/docker/run/docker-compose.yaml)
|
||||||
|
|
||||||
|
当前版本号: 
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# 随便创建一个目录
|
||||||
mkdir certd
|
mkdir certd
|
||||||
|
# 进入目录
|
||||||
cd certd
|
cd certd
|
||||||
# wget下载docker-compose.yaml文件
|
# 下载docker-compose.yaml文件,或者手动下载放到certd目录下
|
||||||
wget https://raw.githubusercontent.com/certd/certd/v2/docker/run/docker-compose.yaml
|
|
||||||
# 或者使用gitee地址
|
|
||||||
wget https://gitee.com/certd/certd/raw/v2/docker/run/docker-compose.yaml
|
wget https://gitee.com/certd/certd/raw/v2/docker/run/docker-compose.yaml
|
||||||
|
|
||||||
# 可以根据需要修改里面的配置
|
# 可以根据需要修改里面的配置
|
||||||
# 1.修改镜像版本号【可选】
|
# 1.修改镜像版本号【可选】
|
||||||
# 2.配置数据保存路径【可选】
|
# 2.配置数据保存路径【可选】
|
||||||
# 3.修改端口号【可选】
|
# 3.修改端口号【可选】
|
||||||
vi docker-compose.yaml
|
vi docker-compose.yaml # 【可选】
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 运行
|
|
||||||
当前版本号: 
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 设置镜像版本号环境变量,如果docker-compose.yaml中已经修改,请忽略这条命令
|
|
||||||
export CERTD_VERSION=latest # <---建议设置成固定版本号
|
|
||||||
|
|
||||||
# 启动certd
|
# 启动certd
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
|
|
||||||
```
|
```
|
||||||
如果提示 没有compose命令,请安装docker-compose
|
> 如果提示 没有compose命令,请安装docker-compose
|
||||||
https://docs.docker.com/compose/install/linux/
|
> https://docs.docker.com/compose/install/linux/
|
||||||
|
|
||||||
|
#### 镜像说明:
|
||||||
|
* certd镜像地址:
|
||||||
|
* `registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest`
|
||||||
|
|
||||||
|
* 镜像构建通过`Actions`自动执行,过程公开透明,请放心使用
|
||||||
|
* [点我查看镜像构建日志](https://github.com/certd/certd/actions/workflows/build-image.yml)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
|
||||||
|
### 3. 访问
|
||||||
### 4. 访问
|
|
||||||
|
|
||||||
http://your_server_ip:7001
|
http://your_server_ip:7001
|
||||||
默认账号密码:admin/123456
|
默认账号密码:admin/123456
|
||||||
记得修改密码
|
记得修改密码
|
||||||
|
|
||||||
|
|
||||||
### 5. 升级
|
## 五、 升级
|
||||||
|
如果使用固定版本号
|
||||||
|
1. 修改`docker-compose.yaml`中的镜像版本号
|
||||||
|
2. 运行 `docker compose up -d` 即可
|
||||||
|
|
||||||
* 修改版本号,重新运行 `docker compose up -d` 即可
|
如果使用`latest`版本
|
||||||
* 数据存在`/data/certd`目录下,不用担心数据丢失
|
1. 重新拉取镜像 `docker pull registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest`
|
||||||
|
2. 重新启动容器 `docker compose restart`
|
||||||
|
|
||||||
|
> 数据默认存在`/data/certd`目录下,不用担心数据丢失
|
||||||
|
|
||||||
|
|
||||||
## 五、一些说明
|
更新日志: [CHANGELOG](./CHANGELOG.md)
|
||||||
|
|
||||||
|
|
||||||
|
## 六、一些说明
|
||||||
* 本项目ssl证书提供商为letencrypt
|
* 本项目ssl证书提供商为letencrypt
|
||||||
* 申请过程遵循acme协议
|
* 申请过程遵循acme协议
|
||||||
* 需要验证域名所有权,一般有两种方式(目前本项目仅支持dns-01)
|
* 需要验证域名所有权,一般有两种方式(目前本项目仅支持dns-01)
|
||||||
@@ -115,14 +125,15 @@ http://your_server_ip:7001
|
|||||||
* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
* 免费证书过期时间90天,以后可能还会缩短,所以自动化部署必不可少
|
||||||
* 设置每天自动运行,当证书过期前20天,会自动重新申请证书并部署
|
* 设置每天自动运行,当证书过期前20天,会自动重新申请证书并部署
|
||||||
|
|
||||||
## 六、不同平台的设置说明
|
|
||||||
|
## 七、不同平台的设置说明
|
||||||
|
|
||||||
* [Cloudflare](./doc/cf/cf.md)
|
* [Cloudflare](./doc/cf/cf.md)
|
||||||
* [腾讯云](./doc/tencent/tencent.md)
|
* [腾讯云](./doc/tencent/tencent.md)
|
||||||
* [windows主机](./doc/host/host.md)
|
* [windows主机](./doc/host/host.md)
|
||||||
|
|
||||||
|
|
||||||
## 七、问题处理
|
## 八、问题处理
|
||||||
### 7.1 忘记管理员密码
|
### 7.1 忘记管理员密码
|
||||||
解决方法如下:
|
解决方法如下:
|
||||||
1. 修改docker-compose.yaml文件,将环境变量`certd_system_resetAdminPassword`改为`true`
|
1. 修改docker-compose.yaml文件,将环境变量`certd_system_resetAdminPassword`改为`true`
|
||||||
@@ -143,9 +154,9 @@ docker logs -f --tail 500 certd
|
|||||||
```shell
|
```shell
|
||||||
docker compose up -d
|
docker compose up -d
|
||||||
```
|
```
|
||||||
5. 使用admin/123456登录系统,请及时修改管理员密码
|
5. 使用`admin/123456`登录系统,请及时修改管理员密码
|
||||||
|
|
||||||
## 八、联系作者
|
## 九、联系作者
|
||||||
如有疑问,欢迎加入群聊(请备注certd)
|
如有疑问,欢迎加入群聊(请备注certd)
|
||||||
* QQ群:141236433
|
* QQ群:141236433
|
||||||
* 微信群:
|
* 微信群:
|
||||||
@@ -157,7 +168,7 @@ docker compose up -d
|
|||||||
<img height="230" src="./doc/images/me.png">
|
<img height="230" src="./doc/images/me.png">
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
## 九、捐赠
|
## 十、捐赠
|
||||||
媳妇儿说:“一天到晚搞开源,也不管管老婆孩子!😡😡😡”
|
媳妇儿说:“一天到晚搞开源,也不管管老婆孩子!😡😡😡”
|
||||||
拜托各位捐赠支持一下,让媳妇儿开心开心,我也能有更多时间进行开源项目,感谢🙏🙏🙏
|
拜托各位捐赠支持一下,让媳妇儿开心开心,我也能有更多时间进行开源项目,感谢🙏🙏🙏
|
||||||
<p align="center">
|
<p align="center">
|
||||||
@@ -165,16 +176,20 @@ docker compose up -d
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
## 十、贡献代码
|
## 十一、贡献代码
|
||||||
|
|
||||||
[贡献插件教程](./plugin.md)
|
[贡献插件教程](./plugin.md)
|
||||||
|
|
||||||
|
|
||||||
## 十一、我的其他项目(求Star)
|
## 十二、我的其他项目(求Star)
|
||||||
* [袖手GPT](https://ai.handsfree.work/) ChatGPT,国内可用,无需FQ,每日免费额度
|
* [袖手GPT](https://ai.handsfree.work/) ChatGPT,国内可用,无需FQ,每日免费额度
|
||||||
* [fast-crud](https://gitee.com/fast-crud/fast-crud/) 基于vue3的crud快速开发框架
|
* [fast-crud](https://gitee.com/fast-crud/fast-crud/) 基于vue3的crud快速开发框架
|
||||||
* [dev-sidecar](https://github.com/docmirror/dev-sidecar/) 直连访问github工具,无需FQ,解决github无法访问的问题
|
* [dev-sidecar](https://github.com/docmirror/dev-sidecar/) 直连访问github工具,无需FQ,解决github无法访问的问题
|
||||||
|
|
||||||
|
|
||||||
## 十二、版本更新日志
|
|
||||||
https://github.com/certd/certd/blob/v2/CHANGELOG.md
|
## 十三、更新日志
|
||||||
|
|
||||||
|
更新日志:[CHANGELOG](./CHANGELOG.md)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
1
build.trigger
Normal file
1
build.trigger
Normal file
@@ -0,0 +1 @@
|
|||||||
|
7
|
||||||
11
deploy.js
11
deploy.js
@@ -32,8 +32,9 @@ async function getPackages(directoryPath) {
|
|||||||
async function getAllPackages() {
|
async function getAllPackages() {
|
||||||
const base = await getPackages("./packages/core")
|
const base = await getPackages("./packages/core")
|
||||||
const plugins = await getPackages("./packages/plugins")
|
const plugins = await getPackages("./packages/plugins")
|
||||||
|
const libs = await getPackages("./packages/libs")
|
||||||
|
|
||||||
return base.concat(plugins)
|
return base.concat(plugins).concat(libs)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function sync() {
|
async function sync() {
|
||||||
@@ -48,7 +49,7 @@ async function sync() {
|
|||||||
data: {}
|
data: {}
|
||||||
})
|
})
|
||||||
console.log(`sync success:${pkg}`)
|
console.log(`sync success:${pkg}`)
|
||||||
await sleep(100*1000)
|
await sleep(30*1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +79,7 @@ async function triggerBuild() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
console.log(`webhook success:${webhook}`)
|
console.log(`webhook success:${webhook}`)
|
||||||
await sleep(10*60*1000)
|
await sleep(30*60*1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -86,9 +87,9 @@ async function triggerBuild() {
|
|||||||
async function start() {
|
async function start() {
|
||||||
// await build()
|
// await build()
|
||||||
console.log("等待60秒")
|
console.log("等待60秒")
|
||||||
await sleep(200 * 1000)
|
await sleep(100* 1000)
|
||||||
await sync()
|
await sync()
|
||||||
await sleep(60 * 1000)
|
await sleep(100 * 1000)
|
||||||
await triggerBuild()
|
await triggerBuild()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
BIN
doc/images/action-build.jpg
Normal file
BIN
doc/images/action-build.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 109 KiB |
@@ -1,20 +0,0 @@
|
|||||||
FROM registry.cn-shenzhen.aliyuncs.com/handsfree/node:18-alpine
|
|
||||||
EXPOSE 7001
|
|
||||||
ENV NODE_ENV production
|
|
||||||
ENV MIDWAY_SERVER_ENV production
|
|
||||||
WORKDIR /app/
|
|
||||||
#RUN npm install -g pnpm
|
|
||||||
#RUN npm install cross-env -g --registry=https://registry.npmmirror.com
|
|
||||||
#RUN npm install pm2 -g --registry=https://registry.npmmirror.com
|
|
||||||
#RUN pm2 install pm2-logrotate
|
|
||||||
ADD ./workspace/certd-server/ /app/
|
|
||||||
RUN sed -i "s/workspace://g" "/app/package.json"
|
|
||||||
RUN yarn install --production --registry=https://registry.npmmirror.com
|
|
||||||
#RUN yarn install --production
|
|
||||||
RUN npm run build
|
|
||||||
#CMD ["pm2-runtime", "start", "./bootstrap.js","--name", "certd","-i","1"]
|
|
||||||
CMD ["npm", "run","start"]
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
echo "请先输入一个版本号:"
|
|
||||||
read version
|
|
||||||
|
|
||||||
echo "您输入的版本号是: $version"
|
|
||||||
echo "登录aliyun镜像仓库"
|
|
||||||
sudo docker login --username=252959493@qq.com registry.cn-shenzhen.aliyuncs.com
|
|
||||||
|
|
||||||
build=$(pwd)
|
|
||||||
cd ../../
|
|
||||||
root=$(pwd)
|
|
||||||
echo "安装依赖"
|
|
||||||
#pnpm install --registry=https://registry.npmmirror.com
|
|
||||||
pnpm install
|
|
||||||
|
|
||||||
|
|
||||||
echo "packages build"
|
|
||||||
|
|
||||||
lerna run build
|
|
||||||
echo "packages build success"
|
|
||||||
|
|
||||||
echo "server build"
|
|
||||||
cd $root/packages/ui/certd-server
|
|
||||||
pnpm run build
|
|
||||||
echo "server build success"
|
|
||||||
|
|
||||||
echo "rm node_modules"
|
|
||||||
rm ./node_modules -rf
|
|
||||||
|
|
||||||
echo "copy to workspace"
|
|
||||||
mkdir -p $build/workspace/certd-server
|
|
||||||
\cp ./* $build/workspace/certd-server -rf
|
|
||||||
\cp ../certd-client/dist/* $build/workspace/certd-server/public/ -rf
|
|
||||||
|
|
||||||
#export TAG=$version
|
|
||||||
#sudo -E docker compose build
|
|
||||||
#sudo -E docker compose push
|
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
version: '3.3'
|
version: '3.3'
|
||||||
services:
|
services:
|
||||||
certd:
|
certd:
|
||||||
# 镜像 # ↓↓↓↓↓ --- 1、 修改镜像版本号,或者干脆写成latest(不推荐), 如果设置了环境变量 export CERTD_VERSION=xxx,这里可以不修改
|
# 镜像 # ↓↓↓↓↓ --- 1、 镜像版本号,建议改成固定版本号【可选】
|
||||||
image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:${CERTD_VERSION}
|
image: registry.cn-shenzhen.aliyuncs.com/handsfree/certd:latest
|
||||||
container_name: certd # 容器名
|
container_name: certd # 容器名
|
||||||
restart: unless-stopped # 自动重启
|
restart: unless-stopped # 自动重启
|
||||||
volumes:
|
volumes:
|
||||||
@@ -15,8 +15,10 @@ services:
|
|||||||
- TZ=Asia/Shanghai
|
- TZ=Asia/Shanghai
|
||||||
- certd_system_resetAdminPassword=false
|
- certd_system_resetAdminPassword=false
|
||||||
# ↑↑↑↑↑---------------------------4、如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false【可选】
|
# ↑↑↑↑↑---------------------------4、如果忘记管理员密码,可以设置为true,重启之后,管理员密码将改成123456,然后请及时修改回false【可选】
|
||||||
|
- certd_cron_immediateTriggerOnce=false
|
||||||
|
# ↑↑↑↑↑---------------------------5、如果设置为true,启动后所有配置了cron的流水线任务都将被立即触发一次【可选】
|
||||||
- VITE_APP_ICP_NO=
|
- VITE_APP_ICP_NO=
|
||||||
# ↑↑↑↑↑ -----------------------------------------5、这里可以设置备案号【可选】
|
# ↑↑↑↑↑ -----------------------------------------6、这里可以设置备案号【可选】
|
||||||
# 设置环境变量即可自定义certd配置
|
# 设置环境变量即可自定义certd配置
|
||||||
# 服务端配置项见: packages/ui/certd-server/src/config/config.default.ts
|
# 服务端配置项见: packages/ui/certd-server/src/config/config.default.ts
|
||||||
# 服务端配置规则: certd_ + 配置项, 点号用_代替
|
# 服务端配置规则: certd_ + 配置项, 点号用_代替
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
set -e
|
|
||||||
# 判断$CERTD_VERSION 是否存在
|
|
||||||
if [ -n "$CERTD_VERSION" ]; then
|
|
||||||
echo "CERTD_VERSION is set = $CERTD_VERSION"
|
|
||||||
else
|
|
||||||
echo "CERTD_VERSION is not set"
|
|
||||||
echo "请先输入一个版本号(如 1.0.6):"
|
|
||||||
read CERTD_VERSION
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "您输入的版本号是: $CERTD_VERSION"
|
|
||||||
sudo -E docker compose up -d
|
|
||||||
@@ -9,5 +9,5 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"npmClient": "pnpm",
|
"npmClient": "pnpm",
|
||||||
"version": "1.22.0"
|
"version": "1.22.4"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "lerna bootstrap --hoist",
|
"start": "lerna bootstrap --hoist",
|
||||||
"i-all": "lerna link && lerna exec npm install ",
|
"i-all": "lerna link && lerna exec npm install ",
|
||||||
"publish": "npm run prepublishOnly1 && lerna publish --conventional-commits && npm run afterpublishOnly && npm run deploy1",
|
"publish": "npm run prepublishOnly1 && lerna publish --conventional-commits --create-release github && npm run afterpublishOnly",
|
||||||
"afterpublishOnly": "",
|
"afterpublishOnly": "",
|
||||||
"prepublishOnly1": "npm run check && npm run before-build && lerna run build ",
|
"prepublishOnly1": "npm run check && npm run before-build && lerna run build ",
|
||||||
"before-build": "cd ./packages/core/acme-client && time /t >build.md && git add ./build.md && git commit -m \"build: prepare to build\"",
|
"before-build": "cd ./packages/core/acme-client && time /t >build.md && git add ./build.md && git commit -m \"build: prepare to build\"",
|
||||||
|
|||||||
@@ -3,6 +3,24 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.22.4](https://github.com/publishlab/node-acme-client/compare/v1.22.3...v1.22.4) (2024-07-26)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 证书申请支持反向代理,letsencrypt无法访问时的备用方案 ([b7b5df0](https://github.com/publishlab/node-acme-client/commit/b7b5df0587e0f7ea288c1b2af6f87211f207395f))
|
||||||
|
|
||||||
|
## [1.22.3](https://github.com/publishlab/node-acme-client/compare/v1.22.2...v1.22.3) (2024-07-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.22.2](https://github.com/publishlab/node-acme-client/compare/v1.22.1...v1.22.2) (2024-07-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
|
## [1.22.1](https://github.com/publishlab/node-acme-client/compare/v1.22.0...v1.22.1) (2024-07-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/acme-client
|
||||||
|
|
||||||
# [1.22.0](https://github.com/publishlab/node-acme-client/compare/v1.21.2...v1.22.0) (2024-07-19)
|
# [1.22.0](https://github.com/publishlab/node-acme-client/compare/v1.21.2...v1.22.0) (2024-07-19)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
15:27
|
20:55
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"description": "Simple and unopinionated ACME client",
|
"description": "Simple and unopinionated ACME client",
|
||||||
"private": false,
|
"private": false,
|
||||||
"author": "nmorsman",
|
"author": "nmorsman",
|
||||||
"version": "1.22.0",
|
"version": "1.22.4",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"types": "types/index.d.ts",
|
"types": "types/index.d.ts",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
@@ -59,5 +59,5 @@
|
|||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/publishlab/node-acme-client/issues"
|
"url": "https://github.com/publishlab/node-acme-client/issues"
|
||||||
},
|
},
|
||||||
"gitHead": "a31f1c7f5e71fa946de9bf0283e11d6ce049b3e9"
|
"gitHead": "e5da46cfc31b2e30a4903bcb2251b1851265ef41"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ class AcmeClient {
|
|||||||
max: this.opts.backoffMax,
|
max: this.opts.backoffMax,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.http = new HttpClient(this.opts.directoryUrl, this.opts.accountKey, this.opts.externalAccountBinding);
|
this.http = new HttpClient(this.opts.directoryUrl, this.opts.accountKey, this.opts.externalAccountBinding, this.opts.urlMapping);
|
||||||
this.api = new AcmeApi(this.http, this.opts.accountUrl);
|
this.api = new AcmeApi(this.http, this.opts.accountUrl);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,10 +12,11 @@ const httpsProxy = process.env.HTTPS_PROXY || process.env.https_proxy;
|
|||||||
let httpsAgent = null;
|
let httpsAgent = null;
|
||||||
if (httpsProxy) {
|
if (httpsProxy) {
|
||||||
httpsAgent = new HttpsProxyAgent(httpsProxy);
|
httpsAgent = new HttpsProxyAgent(httpsProxy);
|
||||||
|
log(`use https_proxy:${httpsProxy}`);
|
||||||
}
|
}
|
||||||
const axios = axios1.create({
|
const axios = axios1.create({
|
||||||
proxy: false,
|
proxy: false,
|
||||||
httpsAgent
|
httpsAgent,
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,7 +31,7 @@ const axios = axios1.create({
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class HttpClient {
|
class HttpClient {
|
||||||
constructor(directoryUrl, accountKey, externalAccountBinding = {}) {
|
constructor(directoryUrl, accountKey, externalAccountBinding = {}, urlMapping = {}) {
|
||||||
this.directoryUrl = directoryUrl;
|
this.directoryUrl = directoryUrl;
|
||||||
this.accountKey = accountKey;
|
this.accountKey = accountKey;
|
||||||
this.externalAccountBinding = externalAccountBinding;
|
this.externalAccountBinding = externalAccountBinding;
|
||||||
@@ -41,6 +42,7 @@ class HttpClient {
|
|||||||
this.directoryCache = null;
|
this.directoryCache = null;
|
||||||
this.directoryMaxAge = 86400;
|
this.directoryMaxAge = 86400;
|
||||||
this.directoryTimestamp = 0;
|
this.directoryTimestamp = 0;
|
||||||
|
this.urlMapping = urlMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -53,6 +55,16 @@ class HttpClient {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
async request(url, method, opts = {}) {
|
async request(url, method, opts = {}) {
|
||||||
|
if (this.urlMapping && this.urlMapping.enabled === true && this.urlMapping.mappings) {
|
||||||
|
// eslint-disable-next-line no-restricted-syntax
|
||||||
|
for (const key in this.urlMapping.mappings) {
|
||||||
|
if (url.includes(key)) {
|
||||||
|
const newUrl = url.replace(key, this.urlMapping.mappings[key]);
|
||||||
|
log(`use reverse proxy: ${newUrl}`);
|
||||||
|
url = newUrl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
opts.url = url;
|
opts.url = url;
|
||||||
opts.method = method;
|
opts.method = method;
|
||||||
opts.validateStatus = null;
|
opts.validateStatus = null;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"compileOnSave": false,
|
||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "commonjs",
|
"module": "commonjs",
|
||||||
"lib": ["es6"],
|
"lib": ["es6"],
|
||||||
|
|||||||
6
packages/core/acme-client/types/index.d.ts
vendored
6
packages/core/acme-client/types/index.d.ts
vendored
@@ -27,6 +27,11 @@ export interface Authorization extends rfc8555.Authorization {
|
|||||||
url: string;
|
url: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type UrlMapping={
|
||||||
|
enabled: boolean
|
||||||
|
mappings: Record<string, string>
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Client
|
* Client
|
||||||
*/
|
*/
|
||||||
@@ -39,6 +44,7 @@ export interface ClientOptions {
|
|||||||
backoffAttempts?: number;
|
backoffAttempts?: number;
|
||||||
backoffMin?: number;
|
backoffMin?: number;
|
||||||
backoffMax?: number;
|
backoffMax?: number;
|
||||||
|
urlMapping?: UrlMapping;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ClientExternalAccountBindingOptions {
|
export interface ClientExternalAccountBindingOptions {
|
||||||
|
|||||||
@@ -3,6 +3,20 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.22.3](https://github.com/certd/certd/compare/v1.22.2...v1.22.3) (2024-07-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.22.2](https://github.com/certd/certd/compare/v1.22.1...v1.22.2) (2024-07-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/pipeline
|
||||||
|
|
||||||
|
## [1.22.1](https://github.com/certd/certd/compare/v1.22.0...v1.22.1) (2024-07-20)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 创建证书任务可以选择lege插件 ([affef13](https://github.com/certd/certd/commit/affef130378030c517250c58a4e787b0fc85d7d1))
|
||||||
|
|
||||||
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/pipeline",
|
"name": "@certd/pipeline",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.22.0",
|
"version": "1.22.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -55,5 +55,5 @@
|
|||||||
"vite": "^4.3.8",
|
"vite": "^4.3.8",
|
||||||
"vue-tsc": "^1.6.5"
|
"vue-tsc": "^1.6.5"
|
||||||
},
|
},
|
||||||
"gitHead": "a31f1c7f5e71fa946de9bf0283e11d6ce049b3e9"
|
"gitHead": "e5da46cfc31b2e30a4903bcb2251b1851265ef41"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ export class Executor {
|
|||||||
}
|
}
|
||||||
if (notification.type === "email") {
|
if (notification.type === "email") {
|
||||||
try {
|
try {
|
||||||
this.options.emailService?.send({
|
await this.options.emailService?.send({
|
||||||
userId: this.pipeline.userId,
|
userId: this.pipeline.userId,
|
||||||
subject,
|
subject,
|
||||||
content,
|
content,
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ export type TaskInputDefine = FormItemProps;
|
|||||||
|
|
||||||
export type PluginDefine = Registrable & {
|
export type PluginDefine = Registrable & {
|
||||||
default?: any;
|
default?: any;
|
||||||
|
group?: string;
|
||||||
input?: {
|
input?: {
|
||||||
[key: string]: TaskInputDefine;
|
[key: string]: TaskInputDefine;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ export function IsTaskPlugin(define: PluginDefine): ClassDecorator {
|
|||||||
}
|
}
|
||||||
inputArray.push([key, _input]);
|
inputArray.push([key, _input]);
|
||||||
}
|
}
|
||||||
inputArray = _.sortBy(inputArray, (item) => item[1].order);
|
inputArray = _.sortBy(inputArray, (item: any) => item[1].order);
|
||||||
const inputMap: any = {};
|
const inputMap: any = {};
|
||||||
inputArray.forEach((item) => {
|
inputArray.forEach((item: any) => {
|
||||||
inputMap[item[0]] = item[1];
|
inputMap[item[0]] = item[1];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
25
packages/core/pipeline/src/plugin/group.ts
Normal file
25
packages/core/pipeline/src/plugin/group.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import { PluginDefine } from "./api";
|
||||||
|
|
||||||
|
export class PluginGroup {
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
desc?: string;
|
||||||
|
order: number;
|
||||||
|
plugins: PluginDefine[];
|
||||||
|
constructor(key: string, title: string, order = 0, desc = "") {
|
||||||
|
this.key = key;
|
||||||
|
this.title = title;
|
||||||
|
this.order = order;
|
||||||
|
this.desc = desc;
|
||||||
|
this.plugins = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pluginGroups = {
|
||||||
|
cert: new PluginGroup("cert", "证书申请", 1),
|
||||||
|
aliyun: new PluginGroup("aliyun", "阿里云", 2),
|
||||||
|
huawei: new PluginGroup("huawei", "华为云", 3),
|
||||||
|
tencent: new PluginGroup("tencent", "腾讯云", 4),
|
||||||
|
host: new PluginGroup("host", "主机", 5),
|
||||||
|
other: new PluginGroup("other", "其他", 7),
|
||||||
|
};
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
export * from "./api.js";
|
export * from "./api.js";
|
||||||
export * from "./registry.js";
|
export * from "./registry.js";
|
||||||
export * from "./decorator.js";
|
export * from "./decorator.js";
|
||||||
|
export * from "./group.js";
|
||||||
|
|||||||
@@ -1,4 +1,16 @@
|
|||||||
import { Registry } from "../registry/index.js";
|
import { OnRegisterContext, Registry } from "../registry/index.js";
|
||||||
import { AbstractTaskPlugin } from "./api.js";
|
import { AbstractTaskPlugin } from "./api.js";
|
||||||
|
import { pluginGroups } from "./group.js";
|
||||||
|
|
||||||
export const pluginRegistry = new Registry<AbstractTaskPlugin>("plugin");
|
const onRegister = ({ key, value }: OnRegisterContext<AbstractTaskPlugin>) => {
|
||||||
|
const group = value?.define?.group as string;
|
||||||
|
if (group) {
|
||||||
|
if (pluginGroups.hasOwnProperty(group)) {
|
||||||
|
// @ts-ignore
|
||||||
|
pluginGroups[group].plugins.push(value.define);
|
||||||
|
} else {
|
||||||
|
pluginGroups.other.plugins.push(value.define);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const pluginRegistry = new Registry<AbstractTaskPlugin>("plugin", onRegister);
|
||||||
|
|||||||
@@ -4,20 +4,31 @@ export type Registrable = {
|
|||||||
name: string;
|
name: string;
|
||||||
title: string;
|
title: string;
|
||||||
desc?: string;
|
desc?: string;
|
||||||
|
group?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RegistryItem<T> = {
|
export type RegistryItem<T> = {
|
||||||
define: Registrable;
|
define: Registrable;
|
||||||
target: T;
|
target: T;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type OnRegisterContext<T> = {
|
||||||
|
registry: Registry<T>;
|
||||||
|
key: string;
|
||||||
|
value: RegistryItem<T>;
|
||||||
|
};
|
||||||
|
export type OnRegister<T> = (ctx: OnRegisterContext<T>) => void;
|
||||||
export class Registry<T> {
|
export class Registry<T> {
|
||||||
type = "";
|
type = "";
|
||||||
storage: {
|
storage: {
|
||||||
[key: string]: RegistryItem<T>;
|
[key: string]: RegistryItem<T>;
|
||||||
} = {};
|
} = {};
|
||||||
|
|
||||||
constructor(type: string) {
|
onRegister?: OnRegister<T>;
|
||||||
|
|
||||||
|
constructor(type: string, onRegister?: OnRegister<T>) {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
this.onRegister = onRegister;
|
||||||
}
|
}
|
||||||
|
|
||||||
register(key: string, value: RegistryItem<T>) {
|
register(key: string, value: RegistryItem<T>) {
|
||||||
@@ -25,6 +36,13 @@ export class Registry<T> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.storage[key] = value;
|
this.storage[key] = value;
|
||||||
|
if (this.onRegister) {
|
||||||
|
this.onRegister({
|
||||||
|
registry: this,
|
||||||
|
key,
|
||||||
|
value,
|
||||||
|
});
|
||||||
|
}
|
||||||
logger.info(`注册插件:${this.type}:${key}`);
|
logger.info(`注册插件:${this.type}:${key}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ export function createAxiosService({ logger }: { logger: Logger }) {
|
|||||||
// case 505: error.message = 'HTTP版本不受支持'; break
|
// case 505: error.message = 'HTTP版本不受支持'; break
|
||||||
// default: break
|
// default: break
|
||||||
// }
|
// }
|
||||||
logger.error(`请求出错:url:${error?.response?.config.url},method:${error.response.config.method},status:${error?.response?.status}`);
|
logger.error(`请求出错:url:${error?.response?.config.url},method:${error?.response?.config?.method},status:${error?.response?.status}`);
|
||||||
logger.info("返回数据:", JSON.stringify(error?.response?.data));
|
logger.info("返回数据:", JSON.stringify(error?.response?.data));
|
||||||
delete error.config;
|
delete error.config;
|
||||||
delete error.response;
|
delete error.response;
|
||||||
|
|||||||
@@ -3,6 +3,10 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.22.1](https://github.com/certd/certd/compare/v1.22.0...v1.22.1) (2024-07-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-huawei
|
||||||
|
|
||||||
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-huawei",
|
"name": "@certd/lib-huawei",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.22.0",
|
"version": "1.22.1",
|
||||||
"main": "./dist/bundle.js",
|
"main": "./dist/bundle.js",
|
||||||
"module": "./dist/bundle.js",
|
"module": "./dist/bundle.js",
|
||||||
"types": "./dist/d/index.d.ts",
|
"types": "./dist/d/index.d.ts",
|
||||||
@@ -16,5 +16,5 @@
|
|||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"rollup": "^3.7.4"
|
"rollup": "^3.7.4"
|
||||||
},
|
},
|
||||||
"gitHead": "a31f1c7f5e71fa946de9bf0283e11d6ce049b3e9"
|
"gitHead": "47fe3d5826661f678d081ab53e67c847a3239d88"
|
||||||
}
|
}
|
||||||
@@ -3,6 +3,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.22.3](https://github.com/certd/certd/compare/v1.22.2...v1.22.3) (2024-07-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.22.2](https://github.com/certd/certd/compare/v1.22.1...v1.22.2) (2024-07-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
|
## [1.22.1](https://github.com/certd/certd/compare/v1.22.0...v1.22.1) (2024-07-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/lib-k8s
|
||||||
|
|
||||||
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/lib-k8s",
|
"name": "@certd/lib-k8s",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.22.0",
|
"version": "1.22.3",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -13,11 +13,11 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"dns": "^0.2.2",
|
"kubernetes-client": "^9.0.0",
|
||||||
"kubernetes-client": "^9.0.0"
|
"shelljs": "^0.8.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@certd/pipeline": "workspace:^1.22.0",
|
"@certd/pipeline": "^1.22.3",
|
||||||
"@rollup/plugin-commonjs": "^23.0.4",
|
"@rollup/plugin-commonjs": "^23.0.4",
|
||||||
"@rollup/plugin-json": "^6.0.0",
|
"@rollup/plugin-json": "^6.0.0",
|
||||||
"@rollup/plugin-node-resolve": "^15.0.1",
|
"@rollup/plugin-node-resolve": "^15.0.1",
|
||||||
@@ -38,5 +38,5 @@
|
|||||||
"tslib": "^2.5.2",
|
"tslib": "^2.5.2",
|
||||||
"typescript": "^4.8.4"
|
"typescript": "^4.8.4"
|
||||||
},
|
},
|
||||||
"gitHead": "a31f1c7f5e71fa946de9bf0283e11d6ce049b3e9"
|
"gitHead": "e5da46cfc31b2e30a4903bcb2251b1851265ef41"
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import kubernetesClient from 'kubernetes-client';
|
import kubernetesClient from 'kubernetes-client';
|
||||||
|
//@ts-ignore
|
||||||
import dns from 'dns';
|
import dns from 'dns';
|
||||||
import { logger } from '@certd/pipeline';
|
import { logger } from '@certd/pipeline';
|
||||||
|
|
||||||
@@ -3,6 +3,18 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.22.3](https://github.com/certd/certd/compare/v1.22.2...v1.22.3) (2024-07-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.22.2](https://github.com/certd/certd/compare/v1.22.1...v1.22.2) (2024-07-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
|
## [1.22.1](https://github.com/certd/certd/compare/v1.22.0...v1.22.1) (2024-07-20)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/midway-flyway-js
|
||||||
|
|
||||||
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/midway-flyway-js",
|
"name": "@certd/midway-flyway-js",
|
||||||
"version": "1.22.0",
|
"version": "1.22.3",
|
||||||
"description": "midway with flyway, sql upgrade way ",
|
"description": "midway with flyway, sql upgrade way ",
|
||||||
"private": false,
|
"private": false,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -36,6 +36,7 @@
|
|||||||
"@types/node": "16",
|
"@types/node": "16",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
"@typescript-eslint/eslint-plugin": "^5.38.1",
|
||||||
"@typescript-eslint/parser": "^5.38.1",
|
"@typescript-eslint/parser": "^5.38.1",
|
||||||
|
"better-sqlite3": "^11.1.2",
|
||||||
"cross-env": "^6.0.0",
|
"cross-env": "^6.0.0",
|
||||||
"eslint": "^8.24.0",
|
"eslint": "^8.24.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
@@ -47,10 +48,10 @@
|
|||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"rollup": "^3.7.4",
|
"rollup": "^3.7.4",
|
||||||
"rollup-plugin-visualizer": "^5.8.2",
|
"rollup-plugin-visualizer": "^5.8.2",
|
||||||
"sqlite3": "^5.0.2",
|
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"tslib": "^2.5.2",
|
"tslib": "^2.5.2",
|
||||||
"typeorm": "^0.3.11",
|
"typeorm": "^0.3.11",
|
||||||
"typescript": "~5.1.0"
|
"typescript": "~5.1.0"
|
||||||
}
|
},
|
||||||
|
"gitHead": "e5da46cfc31b2e30a4903bcb2251b1851265ef41"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -227,8 +227,10 @@ export class Flyway {
|
|||||||
if (history.hash !== hash && this.allowHashNotMatch === false) {
|
if (history.hash !== hash && this.allowHashNotMatch === false) {
|
||||||
throw new Error(file + `hash conflict ,old: ${history.hash} != new: ${hash}`);
|
throw new Error(file + `hash conflict ,old: ${history.hash} != new: ${hash}`);
|
||||||
}
|
}
|
||||||
|
this.logger.info('[ midfly ] script<' + file + '> already executed');
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
this.logger.info('[ midfly ] script<' + file + '> not yet execute');
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,26 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.22.4](https://github.com/certd/certd/compare/v1.22.3...v1.22.4) (2024-07-26)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 证书申请支持反向代理,letsencrypt无法访问时的备用方案 ([b7b5df0](https://github.com/certd/certd/commit/b7b5df0587e0f7ea288c1b2af6f87211f207395f))
|
||||||
|
|
||||||
|
## [1.22.3](https://github.com/certd/certd/compare/v1.22.2...v1.22.3) (2024-07-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.22.2](https://github.com/certd/certd/compare/v1.22.1...v1.22.2) (2024-07-23)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/plugin-cert
|
||||||
|
|
||||||
|
## [1.22.1](https://github.com/certd/certd/compare/v1.22.0...v1.22.1) (2024-07-20)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 创建证书任务可以选择lege插件 ([affef13](https://github.com/certd/certd/commit/affef130378030c517250c58a4e787b0fc85d7d1))
|
||||||
|
|
||||||
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/plugin-cert",
|
"name": "@certd/plugin-cert",
|
||||||
"private": false,
|
"private": false,
|
||||||
"version": "1.22.0",
|
"version": "1.22.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/index.js",
|
"main": "./dist/index.js",
|
||||||
"types": "./dist/index.d.ts",
|
"types": "./dist/index.d.ts",
|
||||||
@@ -13,8 +13,8 @@
|
|||||||
"preview": "vite preview"
|
"preview": "vite preview"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@certd/acme-client": "workspace:^1.22.0",
|
"@certd/acme-client": "^1.22.4",
|
||||||
"@certd/pipeline": "workspace:^1.22.0",
|
"@certd/pipeline": "^1.22.3",
|
||||||
"jszip": "^3.10.1",
|
"jszip": "^3.10.1",
|
||||||
"node-forge": "^0.10.0",
|
"node-forge": "^0.10.0",
|
||||||
"psl": "^1.9.0"
|
"psl": "^1.9.0"
|
||||||
@@ -53,5 +53,5 @@
|
|||||||
"vite": "^3.1.0",
|
"vite": "^3.1.0",
|
||||||
"vue-tsc": "^0.38.9"
|
"vue-tsc": "^0.38.9"
|
||||||
},
|
},
|
||||||
"gitHead": "a31f1c7f5e71fa946de9bf0283e11d6ce049b3e9"
|
"gitHead": "e5da46cfc31b2e30a4903bcb2251b1851265ef41"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Logger } from "log4js";
|
|||||||
import { IContext } from "@certd/pipeline";
|
import { IContext } from "@certd/pipeline";
|
||||||
import { IDnsProvider } from "../../dns-provider/index.js";
|
import { IDnsProvider } from "../../dns-provider/index.js";
|
||||||
import psl from "psl";
|
import psl from "psl";
|
||||||
import { ClientExternalAccountBindingOptions } from "@certd/acme-client";
|
import { ClientExternalAccountBindingOptions, UrlMapping } from "@certd/acme-client";
|
||||||
|
|
||||||
export type CertInfo = {
|
export type CertInfo = {
|
||||||
crt: string;
|
crt: string;
|
||||||
@@ -14,19 +14,24 @@ export type CertInfo = {
|
|||||||
csr: string;
|
csr: string;
|
||||||
};
|
};
|
||||||
export type SSLProvider = "letsencrypt" | "buypass" | "zerossl";
|
export type SSLProvider = "letsencrypt" | "buypass" | "zerossl";
|
||||||
|
type AcmeServiceOptions = {
|
||||||
|
userContext: IContext;
|
||||||
|
logger: Logger;
|
||||||
|
sslProvider: SSLProvider;
|
||||||
|
eab?: ClientExternalAccountBindingOptions;
|
||||||
|
skipLocalVerify?: boolean;
|
||||||
|
useMappingProxy?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
export class AcmeService {
|
export class AcmeService {
|
||||||
|
options: AcmeServiceOptions;
|
||||||
userContext: IContext;
|
userContext: IContext;
|
||||||
logger: Logger;
|
logger: Logger;
|
||||||
sslProvider: SSLProvider;
|
sslProvider: SSLProvider;
|
||||||
skipLocalVerify = true;
|
skipLocalVerify = true;
|
||||||
eab?: ClientExternalAccountBindingOptions;
|
eab?: ClientExternalAccountBindingOptions;
|
||||||
constructor(options: {
|
constructor(options: AcmeServiceOptions) {
|
||||||
userContext: IContext;
|
this.options = options;
|
||||||
logger: Logger;
|
|
||||||
sslProvider: SSLProvider;
|
|
||||||
eab?: ClientExternalAccountBindingOptions;
|
|
||||||
skipLocalVerify?: boolean;
|
|
||||||
}) {
|
|
||||||
this.userContext = options.userContext;
|
this.userContext = options.userContext;
|
||||||
this.logger = options.logger;
|
this.logger = options.logger;
|
||||||
this.sslProvider = options.sslProvider || "letsencrypt";
|
this.sslProvider = options.sslProvider || "letsencrypt";
|
||||||
@@ -61,6 +66,13 @@ export class AcmeService {
|
|||||||
} else {
|
} else {
|
||||||
directoryUrl = acme.directory[this.sslProvider].production;
|
directoryUrl = acme.directory[this.sslProvider].production;
|
||||||
}
|
}
|
||||||
|
const urlMapping: UrlMapping = { enabled: false, mappings: {} };
|
||||||
|
if (this.options.useMappingProxy) {
|
||||||
|
urlMapping.enabled = true;
|
||||||
|
urlMapping.mappings = {
|
||||||
|
"acme-v02.api.letsencrypt.org": "letsencrypt.proxy.handsfree.work",
|
||||||
|
};
|
||||||
|
}
|
||||||
const client = new acme.Client({
|
const client = new acme.Client({
|
||||||
directoryUrl: directoryUrl,
|
directoryUrl: directoryUrl,
|
||||||
accountKey: conf.key,
|
accountKey: conf.key,
|
||||||
@@ -69,6 +81,7 @@ export class AcmeService {
|
|||||||
backoffAttempts: 30,
|
backoffAttempts: 30,
|
||||||
backoffMin: 5000,
|
backoffMin: 5000,
|
||||||
backoffMax: 10000,
|
backoffMax: 10000,
|
||||||
|
urlMapping,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (conf.accountUrl == null) {
|
if (conf.accountUrl == null) {
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
|||||||
col: {
|
col: {
|
||||||
span: 24,
|
span: 24,
|
||||||
},
|
},
|
||||||
|
order: -1,
|
||||||
helper:
|
helper:
|
||||||
"1、支持通配符域名,例如: *.foo.com、foo.com、*.test.handsfree.work\n" +
|
"1、支持通配符域名,例如: *.foo.com、foo.com、*.test.handsfree.work\n" +
|
||||||
"2、支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)\n" +
|
"2、支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)\n" +
|
||||||
@@ -36,12 +37,14 @@ export abstract class CertApplyBasePlugin extends AbstractTaskPlugin {
|
|||||||
vModel: "value",
|
vModel: "value",
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
|
order: -1,
|
||||||
helper: "请输入邮箱",
|
helper: "请输入邮箱",
|
||||||
})
|
})
|
||||||
email!: string;
|
email!: string;
|
||||||
|
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "更新天数",
|
title: "更新天数",
|
||||||
|
value: 20,
|
||||||
component: {
|
component: {
|
||||||
name: "a-input-number",
|
name: "a-input-number",
|
||||||
vModel: "value",
|
vModel: "value",
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Decorator, IsTaskPlugin, RunStrategy, TaskInput } from "@certd/pipeline";
|
import { Decorator, IsTaskPlugin, pluginGroups, RunStrategy, TaskInput } from "@certd/pipeline";
|
||||||
import type { CertInfo, SSLProvider } from "./acme.js";
|
import type { CertInfo, SSLProvider } from "./acme.js";
|
||||||
import { AcmeService } from "./acme.js";
|
import { AcmeService } from "./acme.js";
|
||||||
import _ from "lodash-es";
|
import _ from "lodash-es";
|
||||||
@@ -11,7 +11,8 @@ export type { CertInfo };
|
|||||||
|
|
||||||
@IsTaskPlugin({
|
@IsTaskPlugin({
|
||||||
name: "CertApply",
|
name: "CertApply",
|
||||||
title: "证书申请",
|
title: "证书申请(JS版)",
|
||||||
|
group: pluginGroups.cert.key,
|
||||||
desc: "免费通配符域名证书申请,支持多个域名打到同一个证书上",
|
desc: "免费通配符域名证书申请,支持多个域名打到同一个证书上",
|
||||||
default: {
|
default: {
|
||||||
input: {
|
input: {
|
||||||
@@ -32,6 +33,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||||||
vModel: "value",
|
vModel: "value",
|
||||||
options: [
|
options: [
|
||||||
{ value: "letsencrypt", label: "Let's Encrypt" },
|
{ value: "letsencrypt", label: "Let's Encrypt" },
|
||||||
|
// { value: "letsencrypt-proxy", label: "Let's Encrypt代理,letsencrypt.org无法访问时使用" },
|
||||||
// { value: "buypass", label: "Buypass" },
|
// { value: "buypass", label: "Buypass" },
|
||||||
{ value: "zerossl", label: "ZeroSSL" },
|
{ value: "zerossl", label: "ZeroSSL" },
|
||||||
],
|
],
|
||||||
@@ -46,6 +48,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||||||
name: "pi-access-selector",
|
name: "pi-access-selector",
|
||||||
type: "eab",
|
type: "eab",
|
||||||
},
|
},
|
||||||
|
maybeNeed: true,
|
||||||
helper: "如果使用ZeroSSL证书,需要提供EAB授权, 请前往 https://app.zerossl.com/developer 生成 'EAB Credentials for ACME Clients' ",
|
helper: "如果使用ZeroSSL证书,需要提供EAB授权, 请前往 https://app.zerossl.com/developer 生成 'EAB Credentials for ACME Clients' ",
|
||||||
})
|
})
|
||||||
eabAccessId!: number;
|
eabAccessId!: number;
|
||||||
@@ -77,6 +80,17 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||||||
})
|
})
|
||||||
dnsProviderAccess!: string;
|
dnsProviderAccess!: string;
|
||||||
|
|
||||||
|
@TaskInput({
|
||||||
|
title: "使用代理",
|
||||||
|
default: false,
|
||||||
|
component: {
|
||||||
|
name: "a-switch",
|
||||||
|
vModel: "checked",
|
||||||
|
},
|
||||||
|
helper: "如果acme-v02.api.letsencrypt.org被墙无法连接访问,请尝试开启此选项",
|
||||||
|
})
|
||||||
|
useProxy = false;
|
||||||
|
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "跳过本地校验DNS",
|
title: "跳过本地校验DNS",
|
||||||
default: false,
|
default: false,
|
||||||
@@ -101,6 +115,7 @@ export class CertApplyPlugin extends CertApplyBasePlugin {
|
|||||||
sslProvider: this.sslProvider,
|
sslProvider: this.sslProvider,
|
||||||
eab,
|
eab,
|
||||||
skipLocalVerify: this.skipLocalVerify,
|
skipLocalVerify: this.skipLocalVerify,
|
||||||
|
useMappingProxy: this.useProxy,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
export const dnsList = [];
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { IsTaskPlugin, RunStrategy, sp, Step, TaskInput } from "@certd/pipeline";
|
import { IsTaskPlugin, pluginGroups, RunStrategy, sp, Step, TaskInput } from "@certd/pipeline";
|
||||||
import type { CertInfo } from "./acme.js";
|
import type { CertInfo } from "../acme.js";
|
||||||
import { CertReader } from "./cert-reader.js";
|
import { CertReader } from "../cert-reader.js";
|
||||||
import { CertApplyBasePlugin } from "./base.js";
|
import { CertApplyBasePlugin } from "../base.js";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { EabAccess } from "../../access";
|
import { EabAccess } from "../../../access/index.js";
|
||||||
import path from "path";
|
import path from "path";
|
||||||
|
|
||||||
export { CertReader };
|
export { CertReader };
|
||||||
@@ -12,7 +12,8 @@ export type { CertInfo };
|
|||||||
@IsTaskPlugin({
|
@IsTaskPlugin({
|
||||||
name: "CertApplyLego",
|
name: "CertApplyLego",
|
||||||
title: "证书申请(Lego)",
|
title: "证书申请(Lego)",
|
||||||
desc: "支持海量DNS解析提供商,推荐使用",
|
group: pluginGroups.cert.key,
|
||||||
|
desc: "支持海量DNS解析提供商,推荐使用,一样的免费通配符域名证书申请,支持多个域名打到同一个证书上",
|
||||||
default: {
|
default: {
|
||||||
input: {
|
input: {
|
||||||
renewDays: 20,
|
renewDays: 20,
|
||||||
@@ -24,12 +25,29 @@ export type { CertInfo };
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
export class CertApplyLegoPlugin extends CertApplyBasePlugin {
|
export class CertApplyLegoPlugin extends CertApplyBasePlugin {
|
||||||
|
// @TaskInput({
|
||||||
|
// title: "ACME服务端点",
|
||||||
|
// default: "https://acme-v02.api.letsencrypt.org/directory",
|
||||||
|
// component: {
|
||||||
|
// name: "a-select",
|
||||||
|
// vModel: "value",
|
||||||
|
// options: [
|
||||||
|
// { value: "https://acme-v02.api.letsencrypt.org/directory", label: "Let's Encrypt" },
|
||||||
|
// { value: "https://letsencrypt.proxy.handsfree.work/directory", label: "Let's Encrypt代理,letsencrypt.org无法访问时使用" },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// required: true,
|
||||||
|
// })
|
||||||
|
acmeServer!: string;
|
||||||
|
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "DNS类型",
|
title: "DNS类型",
|
||||||
component: {
|
component: {
|
||||||
name: "a-input",
|
name: "a-input",
|
||||||
vModel: "value",
|
vModel: "value",
|
||||||
|
placeholder: "alidns",
|
||||||
},
|
},
|
||||||
|
helper: "你的域名是通过哪家提供商进行解析的,具体应该配置什么请参考lego文档:https://go-acme.github.io/lego/dns/",
|
||||||
required: true,
|
required: true,
|
||||||
})
|
})
|
||||||
dnsType!: string;
|
dnsType!: string;
|
||||||
@@ -39,10 +57,11 @@ export class CertApplyLegoPlugin extends CertApplyBasePlugin {
|
|||||||
component: {
|
component: {
|
||||||
name: "a-textarea",
|
name: "a-textarea",
|
||||||
vModel: "value",
|
vModel: "value",
|
||||||
rows: 6,
|
rows: 4,
|
||||||
|
placeholder: "ALICLOUD_ACCESS_KEY=abcdefghijklmnopqrstuvwx\nALICLOUD_SECRET_KEY=your-secret-key",
|
||||||
},
|
},
|
||||||
required: true,
|
required: true,
|
||||||
helper: "一行一条,例如 appKeyId=xxxxx",
|
helper: "一行一条,例如 appKeyId=xxxxx,具体配置请参考lego文档:https://go-acme.github.io/lego/dns/",
|
||||||
})
|
})
|
||||||
environment!: string;
|
environment!: string;
|
||||||
|
|
||||||
@@ -52,16 +71,20 @@ export class CertApplyLegoPlugin extends CertApplyBasePlugin {
|
|||||||
name: "pi-access-selector",
|
name: "pi-access-selector",
|
||||||
type: "eab",
|
type: "eab",
|
||||||
},
|
},
|
||||||
|
maybeNeed: true,
|
||||||
helper: "如果需要提供EAB授权",
|
helper: "如果需要提供EAB授权",
|
||||||
})
|
})
|
||||||
eabAccessId!: number;
|
legoEabAccessId!: number;
|
||||||
|
|
||||||
@TaskInput({
|
@TaskInput({
|
||||||
title: "自定义LEGO参数",
|
title: "自定义LEGO参数",
|
||||||
component: {
|
component: {
|
||||||
name: "a-input",
|
name: "a-input",
|
||||||
vModel: "value",
|
vModel: "value",
|
||||||
|
placeholder: "--dns-timeout 30",
|
||||||
},
|
},
|
||||||
|
helper: "额外的lego命令行参数,参考文档:https://go-acme.github.io/lego/usage/cli/options/",
|
||||||
|
maybeNeed: true,
|
||||||
})
|
})
|
||||||
customArgs = "";
|
customArgs = "";
|
||||||
|
|
||||||
@@ -73,8 +96,8 @@ export class CertApplyLegoPlugin extends CertApplyBasePlugin {
|
|||||||
this.userContext = this.ctx.userContext;
|
this.userContext = this.ctx.userContext;
|
||||||
this.http = this.ctx.http;
|
this.http = this.ctx.http;
|
||||||
this.lastStatus = this.ctx.lastStatus as Step;
|
this.lastStatus = this.ctx.lastStatus as Step;
|
||||||
if (this.eabAccessId) {
|
if (this.legoEabAccessId) {
|
||||||
this.eab = await this.ctx.accessService.getById(this.eabAccessId);
|
this.eab = await this.ctx.accessService.getById(this.legoEabAccessId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
async onInit(): Promise<void> {}
|
async onInit(): Promise<void> {}
|
||||||
@@ -102,8 +125,14 @@ export class CertApplyLegoPlugin extends CertApplyBasePlugin {
|
|||||||
const savePathArgs = `--path "${saveDir}"`;
|
const savePathArgs = `--path "${saveDir}"`;
|
||||||
const os_type = process.platform === "win32" ? "windows" : "linux";
|
const os_type = process.platform === "win32" ? "windows" : "linux";
|
||||||
const legoPath = path.resolve("./tools", os_type, "lego");
|
const legoPath = path.resolve("./tools", os_type, "lego");
|
||||||
|
let serverArgs = "";
|
||||||
|
if (this.acmeServer) {
|
||||||
|
serverArgs = ` --server ${this.acmeServer}`;
|
||||||
|
}
|
||||||
const cmds = [
|
const cmds = [
|
||||||
`${legoPath} -a --email "${this.email}" --dns ${this.dnsType} ${keyType} ${domainArgs} ${eabArgs} ${savePathArgs} ${this.customArgs || ""} run`,
|
`${legoPath} -a --email "${this.email}" --dns ${this.dnsType} ${keyType} ${domainArgs} ${serverArgs} ${eabArgs} ${savePathArgs} ${
|
||||||
|
this.customArgs || ""
|
||||||
|
} run`,
|
||||||
];
|
];
|
||||||
|
|
||||||
await sp.spawn({
|
await sp.spawn({
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
export * from "./cert-plugin/index.js";
|
export * from "./cert-plugin/index.js";
|
||||||
export * from "./cert-plugin/lego.js";
|
export * from "./cert-plugin/lego/index.js";
|
||||||
|
|||||||
23
packages/ui/Dockerfile
Normal file
23
packages/ui/Dockerfile
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
FROM node:18-alpine AS builder
|
||||||
|
EXPOSE 7001
|
||||||
|
WORKDIR /workspace/
|
||||||
|
COPY . /workspace/
|
||||||
|
RUN npm install -g pnpm@8.15.7
|
||||||
|
|
||||||
|
RUN cd /workspace/certd-client && pnpm install && npm run build
|
||||||
|
RUN cd /workspace/certd-server && pnpm install && npm run build-on-docker
|
||||||
|
|
||||||
|
RUN cp /workspace/certd-client/dist/* /workspace/certd-server/public/ -rf
|
||||||
|
|
||||||
|
FROM node:18-alpine
|
||||||
|
WORKDIR /app/
|
||||||
|
COPY --from=builder /workspace/certd-server/ /app/
|
||||||
|
RUN chmod +x /app/tools/linux/*
|
||||||
|
ENV TZ=Asia/Shanghai
|
||||||
|
ENV NODE_ENV=production
|
||||||
|
ENV MIDWAY_SERVER_ENV=production
|
||||||
|
CMD ["npm", "run","start"]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -3,6 +3,23 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.22.3](https://github.com/certd/certd/compare/v1.22.2...v1.22.3) (2024-07-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/ui-client
|
||||||
|
|
||||||
|
## [1.22.2](https://github.com/certd/certd/compare/v1.22.1...v1.22.2) (2024-07-23)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复创建流水线时,无法根据dns类型默认正确的dns授权的bug ([a2c43b5](https://github.com/certd/certd/commit/a2c43b50a6069ed48958fd142844a8568c2af452))
|
||||||
|
|
||||||
|
## [1.22.1](https://github.com/certd/certd/compare/v1.22.0...v1.22.1) (2024-07-20)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 创建证书任务可以选择lege插件 ([affef13](https://github.com/certd/certd/commit/affef130378030c517250c58a4e787b0fc85d7d1))
|
||||||
|
* 创建证书任务增加定时任务和邮件通知输入 ([427620d](https://github.com/certd/certd/commit/427620d34f3b8ad6933005faf1878908441a2453))
|
||||||
|
|
||||||
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/ui-client",
|
"name": "@certd/ui-client",
|
||||||
"version": "1.22.0",
|
"version": "1.22.3",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "vite --open",
|
"dev": "vite --open",
|
||||||
@@ -59,7 +59,7 @@
|
|||||||
"vuedraggable": "^2.24.3"
|
"vuedraggable": "^2.24.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@certd/pipeline": "^1.22.0",
|
"@certd/pipeline": "^1.22.3",
|
||||||
"@rollup/plugin-commonjs": "^25.0.7",
|
"@rollup/plugin-commonjs": "^25.0.7",
|
||||||
"@rollup/plugin-node-resolve": "^15.2.3",
|
"@rollup/plugin-node-resolve": "^15.2.3",
|
||||||
"@types/chai": "^4.3.12",
|
"@types/chai": "^4.3.12",
|
||||||
|
|||||||
19
packages/ui/certd-client/src/use/use-refrence.ts
Normal file
19
packages/ui/certd-client/src/use/use-refrence.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import _ from "lodash-es";
|
||||||
|
import { compute } from "@fast-crud/fast-crud";
|
||||||
|
|
||||||
|
export function useReference(form: any) {
|
||||||
|
if (!form.reference) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const reference of form.reference) {
|
||||||
|
debugger;
|
||||||
|
_.set(
|
||||||
|
form,
|
||||||
|
reference.dest,
|
||||||
|
compute<any>((scope) => {
|
||||||
|
debugger;
|
||||||
|
return _.get(scope, reference.src);
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,12 +9,7 @@ const defaultInputDefine = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function GetList(query: any) {
|
function initPlugins(plugins: any) {
|
||||||
const plugins = await request({
|
|
||||||
url: apiPrefix + "/list",
|
|
||||||
method: "post",
|
|
||||||
params: query
|
|
||||||
});
|
|
||||||
for (const plugin of plugins) {
|
for (const plugin of plugins) {
|
||||||
for (const key in plugin.input) {
|
for (const key in plugin.input) {
|
||||||
const field = _.merge({}, defaultInputDefine, plugin.input[key]);
|
const field = _.merge({}, defaultInputDefine, plugin.input[key]);
|
||||||
@@ -24,7 +19,7 @@ export async function GetList(query: any) {
|
|||||||
//嵌套对象
|
//嵌套对象
|
||||||
field.key = ["input", key];
|
field.key = ["input", key];
|
||||||
if (field.required) {
|
if (field.required) {
|
||||||
delete field.required;
|
// delete field.required;
|
||||||
if (field.rules == null) {
|
if (field.rules == null) {
|
||||||
field.rules = [];
|
field.rules = [];
|
||||||
}
|
}
|
||||||
@@ -34,5 +29,28 @@ export async function GetList(query: any) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log("plugins", plugins);
|
console.log("plugins", plugins);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GetList(query: any) {
|
||||||
|
const plugins = await request({
|
||||||
|
url: apiPrefix + "/list",
|
||||||
|
method: "post",
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
initPlugins(plugins);
|
||||||
return plugins;
|
return plugins;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function GetGroups(query: any) {
|
||||||
|
const groups = await request({
|
||||||
|
url: apiPrefix + "/groups",
|
||||||
|
method: "post",
|
||||||
|
params: query
|
||||||
|
});
|
||||||
|
const plugins: any = [];
|
||||||
|
for (const groupKey in groups) {
|
||||||
|
plugins.push(...groups[groupKey].plugins);
|
||||||
|
}
|
||||||
|
initPlugins(plugins);
|
||||||
|
return groups;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,152 +1,106 @@
|
|||||||
import { compute, CreateCrudOptionsProps, CreateCrudOptionsRet } from "@fast-crud/fast-crud";
|
import { compute, CreateCrudOptionsRet, dict } from "@fast-crud/fast-crud";
|
||||||
import { Dicts } from "./dicts";
|
import { PluginGroup } from "@certd/pipeline";
|
||||||
|
import { useReference } from "/@/use/use-refrence";
|
||||||
|
import _ from "lodash-es";
|
||||||
|
|
||||||
|
export default function (certPluginGroup: PluginGroup, formWrapperRef: any): CreateCrudOptionsRet {
|
||||||
|
const inputs: any = {};
|
||||||
|
|
||||||
|
for (const plugin of certPluginGroup.plugins) {
|
||||||
|
for (const inputKey in plugin.input) {
|
||||||
|
if (inputs[inputKey]) {
|
||||||
|
inputs[inputKey].form.show = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const inputDefine = _.cloneDeep(plugin.input[inputKey]);
|
||||||
|
if (!inputDefine.required && !inputDefine.maybeNeed) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
useReference(inputDefine);
|
||||||
|
inputs[inputKey] = {
|
||||||
|
title: inputDefine.title,
|
||||||
|
form: {
|
||||||
|
...inputDefine,
|
||||||
|
show: compute((ctx) => {
|
||||||
|
console.log(formWrapperRef);
|
||||||
|
const form = formWrapperRef.value.getFormData();
|
||||||
|
if (!form) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return form?.certApplyPlugin === plugin.name;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default function (): CreateCrudOptionsRet {
|
|
||||||
return {
|
return {
|
||||||
crudOptions: {
|
crudOptions: {
|
||||||
form: {
|
form: {
|
||||||
wrapper: {
|
wrapper: {
|
||||||
width: "1150px"
|
width: "1150px",
|
||||||
|
saveRemind: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
columns: {
|
columns: {
|
||||||
domains: {
|
certApplyPlugin: {
|
||||||
title: "域名",
|
title: "证书申请插件",
|
||||||
type: "dict-select",
|
type: "dict-select",
|
||||||
search: {
|
dict: dict({
|
||||||
show: true,
|
data: [
|
||||||
component: {
|
{ value: "CertApply", label: "JS-ACME" },
|
||||||
name: "a-input"
|
{ value: "CertApplyLego", label: "Lego-ACME" }
|
||||||
}
|
]
|
||||||
},
|
}),
|
||||||
|
form: {
|
||||||
|
order: 0,
|
||||||
|
value: "CertApply",
|
||||||
|
helper: {
|
||||||
|
render: () => {
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
<li>Lego-ACME:基于Lego实现,支持海量DNS提供商</li>
|
||||||
|
<li>JS-ACME:如果你的域名DNS属于阿里云、腾讯云、Cloudflare可以选择用它来申请</li>
|
||||||
|
</ul>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
...inputs,
|
||||||
|
triggerCron: {
|
||||||
|
title: "定时触发",
|
||||||
|
type: "text",
|
||||||
form: {
|
form: {
|
||||||
col: {
|
|
||||||
span: 24
|
|
||||||
},
|
|
||||||
wrapperCol: {
|
|
||||||
span: null
|
|
||||||
},
|
|
||||||
component: {
|
component: {
|
||||||
mode: "tags",
|
placeholder: "0 0 4 * * *"
|
||||||
open: false
|
|
||||||
},
|
},
|
||||||
|
helper: "请输入cron表达式, 例如:0 0 4 * * *,每天凌晨4点触发",
|
||||||
|
order: 100
|
||||||
|
}
|
||||||
|
},
|
||||||
|
emailNotify: {
|
||||||
|
title: "失败邮件通知",
|
||||||
|
type: "dict-switch",
|
||||||
|
dict: dict({
|
||||||
|
data: [
|
||||||
|
{ value: true, label: "启用" },
|
||||||
|
{ value: false, label: "不启用" }
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
form: {
|
||||||
|
order: 101,
|
||||||
helper: {
|
helper: {
|
||||||
render: () => {
|
render: () => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div>支持通配符域名,例如: *.foo.com 、 *.test.handsfree.work</div>
|
需要配置<router-link to={{ path: "/certd/settings/email" }}>邮件服务器</router-link>才能发送邮件
|
||||||
<div>支持多个域名、多个子域名、多个通配符域名打到一个证书上(域名必须是在同一个DNS提供商解析)</div>
|
|
||||||
<div>多级子域名要分成多个域名输入(*.foo.com的证书不能用于xxx.yyy.foo.com)</div>
|
|
||||||
<div>输入一个回车之后,再输入下一个</div>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
valueResolve({ form }) {
|
|
||||||
if (form.domains instanceof String) {
|
|
||||||
form.domains = form.domains?.join(",");
|
|
||||||
}
|
|
||||||
},
|
|
||||||
rules: [{ required: true, message: "请填写域名" }]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
email: {
|
|
||||||
title: "邮箱",
|
|
||||||
type: "text",
|
|
||||||
search: { show: false },
|
|
||||||
form: {
|
|
||||||
rules: [{ required: true, type: "email", message: "请填写邮箱" }]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
blank: {
|
|
||||||
title: "占位",
|
|
||||||
type: "text",
|
|
||||||
form: {
|
|
||||||
blank: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sslProvider: {
|
|
||||||
title: "证书提供商",
|
|
||||||
type: "dict-select",
|
|
||||||
dict: Dicts.sslProviderDict
|
|
||||||
},
|
|
||||||
eabAccess: {
|
|
||||||
title: "EAB授权",
|
|
||||||
type: "dict-select",
|
|
||||||
form: {
|
|
||||||
component: {
|
|
||||||
name: "PiAccessSelector",
|
|
||||||
type: "eab",
|
|
||||||
vModel: "modelValue"
|
|
||||||
},
|
|
||||||
helper: "如果是ZeroSSL,需要配置EAB授权,https://app.zerossl.com/developer 生成 'EAB' "
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dnsProviderType: {
|
|
||||||
title: "DNS提供商",
|
|
||||||
type: "dict-select",
|
|
||||||
dict: Dicts.dnsProviderTypeDict,
|
|
||||||
form: {
|
|
||||||
value: "aliyun",
|
|
||||||
rules: [{ required: true, message: "请选择DNS提供商" }],
|
|
||||||
valueChange({ form }) {
|
|
||||||
form.dnsProviderAccess = null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
dnsProviderAccess: {
|
|
||||||
title: "DNS授权",
|
|
||||||
type: "text",
|
|
||||||
form: {
|
|
||||||
component: {
|
|
||||||
name: "PiAccessSelector",
|
|
||||||
type: compute(({ form }) => {
|
|
||||||
return form.dnsProviderType;
|
|
||||||
}),
|
|
||||||
vModel: "modelValue"
|
|
||||||
},
|
|
||||||
rules: [{ required: true, message: "请选择DNS授权" }]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
// country: {
|
|
||||||
// title: "国家",
|
|
||||||
// type: "text",
|
|
||||||
// form: {
|
|
||||||
// value: "China"
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// state: {
|
|
||||||
// title: "省份",
|
|
||||||
// type: "text",
|
|
||||||
// form: {
|
|
||||||
// value: "GuangDong"
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// locality: {
|
|
||||||
// title: "市区",
|
|
||||||
// type: "text",
|
|
||||||
// form: {
|
|
||||||
// value: "NanShan"
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// organization: {
|
|
||||||
// title: "单位",
|
|
||||||
// type: "text",
|
|
||||||
// form: {
|
|
||||||
// value: "CertD"
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// organizationUnit: {
|
|
||||||
// title: "部门",
|
|
||||||
// type: "text",
|
|
||||||
// form: {
|
|
||||||
// value: "IT Dept"
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
// remark: {
|
|
||||||
// title: "备注",
|
|
||||||
// type: "text"
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<fs-form-wrapper ref="formWrapperRef" />
|
<fs-form-wrapper v-if="formWrapperOptions" ref="formWrapperRef" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
@@ -7,28 +7,37 @@ import { useColumns, useExpose } from "@fast-crud/fast-crud";
|
|||||||
import createCrudOptions from "./crud.jsx";
|
import createCrudOptions from "./crud.jsx";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import _ from "lodash-es";
|
import _ from "lodash-es";
|
||||||
|
import * as api from "../api.plugin";
|
||||||
|
import { PluginGroup, PluginGroups } from "/@/views/certd/pipeline/pipeline/type";
|
||||||
export default {
|
export default {
|
||||||
name: "PiCertdForm",
|
name: "PiCertdForm",
|
||||||
setup(props: any, ctx: any) {
|
setup(props: any, ctx: any) {
|
||||||
// 自定义表单配置
|
|
||||||
const { buildFormOptions } = useColumns();
|
|
||||||
//使用crudOptions结构来构建自定义表单配置
|
|
||||||
let { crudOptions } = createCrudOptions();
|
|
||||||
const doSubmitRef = ref();
|
|
||||||
const formOptions = buildFormOptions(
|
|
||||||
_.merge(crudOptions, {
|
|
||||||
form: {
|
|
||||||
doSubmit({ form }: any) {
|
|
||||||
// 创建certd 的pipeline
|
|
||||||
doSubmitRef.value({ form });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}) as any
|
|
||||||
);
|
|
||||||
|
|
||||||
const formWrapperRef = ref();
|
const formWrapperRef = ref();
|
||||||
const formWrapperOptions = ref();
|
const formWrapperOptions = ref();
|
||||||
formWrapperOptions.value = formOptions;
|
const doSubmitRef = ref();
|
||||||
|
async function buildFormOptions() {
|
||||||
|
const pluginGroups: { [key: string]: PluginGroup } = await api.GetGroups({});
|
||||||
|
const certPluginGroup = pluginGroups.cert;
|
||||||
|
|
||||||
|
// 自定义表单配置
|
||||||
|
const { buildFormOptions } = useColumns();
|
||||||
|
//使用crudOptions结构来构建自定义表单配置
|
||||||
|
let { crudOptions } = createCrudOptions(certPluginGroup, formWrapperRef);
|
||||||
|
|
||||||
|
const formOptions = buildFormOptions(
|
||||||
|
_.merge(crudOptions, {
|
||||||
|
form: {
|
||||||
|
doSubmit({ form }: any) {
|
||||||
|
// 创建certd 的pipeline
|
||||||
|
doSubmitRef.value({ form });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}) as any
|
||||||
|
);
|
||||||
|
|
||||||
|
formWrapperOptions.value = formOptions;
|
||||||
|
}
|
||||||
|
buildFormOptions();
|
||||||
function open(doSubmit: any) {
|
function open(doSubmit: any) {
|
||||||
doSubmitRef.value = doSubmit;
|
doSubmitRef.value = doSubmit;
|
||||||
formWrapperRef.value.open(formWrapperOptions.value);
|
formWrapperRef.value.open(formWrapperOptions.value);
|
||||||
|
|||||||
@@ -37,6 +37,21 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp
|
|||||||
function addCertdPipeline() {
|
function addCertdPipeline() {
|
||||||
certdFormRef.value.open(async ({ form }: any) => {
|
certdFormRef.value.open(async ({ form }: any) => {
|
||||||
// 添加certd pipeline
|
// 添加certd pipeline
|
||||||
|
const triggers = [];
|
||||||
|
if (form.triggerCron) {
|
||||||
|
triggers.push({ id: nanoid(), title: "定时触发", type: "timer", props: { cron: form.triggerCron } });
|
||||||
|
}
|
||||||
|
const notifications = [];
|
||||||
|
if (form.emailNotify) {
|
||||||
|
notifications.push({
|
||||||
|
id: nanoid(),
|
||||||
|
type: "email",
|
||||||
|
when: ["error", "turnToSuccess"],
|
||||||
|
options: {
|
||||||
|
receivers: [form.email]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
const pipeline = {
|
const pipeline = {
|
||||||
title: form.domains[0] + "证书自动化",
|
title: form.domains[0] + "证书自动化",
|
||||||
stages: [
|
stages: [
|
||||||
@@ -58,13 +73,15 @@ export default function ({ crudExpose, context: { certdFormRef } }: CreateCrudOp
|
|||||||
strategy: {
|
strategy: {
|
||||||
runStrategy: 0 // 正常执行
|
runStrategy: 0 // 正常执行
|
||||||
},
|
},
|
||||||
type: "CertApply"
|
type: form.certApplyPlugin
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
triggers,
|
||||||
|
notifications
|
||||||
};
|
};
|
||||||
|
|
||||||
const id = await api.Save({
|
const id = await api.Save({
|
||||||
|
|||||||
@@ -11,14 +11,14 @@ import * as pluginApi from "./api.plugin";
|
|||||||
import * as historyApi from "./api.history";
|
import * as historyApi from "./api.history";
|
||||||
import * as api from "./api";
|
import * as api from "./api";
|
||||||
import { useRoute } from "vue-router";
|
import { useRoute } from "vue-router";
|
||||||
import { PipelineDetail, PipelineOptions, RunHistory } from "./pipeline/type";
|
import { PipelineDetail, PipelineOptions, PluginGroups, RunHistory } from "./pipeline/type";
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: "PipelineDetail",
|
name: "PipelineDetail",
|
||||||
components: { PipelineEdit },
|
components: { PipelineEdit },
|
||||||
setup() {
|
setup() {
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const pipelineId:Ref = ref(route.query.id);
|
const pipelineId: Ref = ref(route.query.id);
|
||||||
|
|
||||||
const pipelineOptions: PipelineOptions = {
|
const pipelineOptions: PipelineOptions = {
|
||||||
async getPipelineDetail({ pipelineId }) {
|
async getPipelineDetail({ pipelineId }) {
|
||||||
@@ -43,9 +43,9 @@ export default defineComponent({
|
|||||||
return detail;
|
return detail;
|
||||||
},
|
},
|
||||||
|
|
||||||
async getPlugins() {
|
async getPluginGroups() {
|
||||||
const plugins = await pluginApi.GetList({});
|
const groups = await pluginApi.GetGroups({});
|
||||||
return plugins as any[];
|
return new PluginGroups(groups);
|
||||||
},
|
},
|
||||||
|
|
||||||
async doSave(pipelineConfig: any) {
|
async doSave(pipelineConfig: any) {
|
||||||
|
|||||||
@@ -4,13 +4,9 @@
|
|||||||
<div class="title">我的流水线</div>
|
<div class="title">我的流水线</div>
|
||||||
</template>
|
</template>
|
||||||
<fs-crud ref="crudRef" v-bind="crudBinding">
|
<fs-crud ref="crudRef" v-bind="crudBinding">
|
||||||
<template #actionbar-right>
|
<template #actionbar-right> </template>
|
||||||
<!-- <span style="margin-left: 10px">出现<a-tag>Promise rejected attempt #18,retrying in 10000ms:No TXT recordsfound for name</a-tag>属于正常现象,多重试几次</span>-->
|
|
||||||
</template>
|
|
||||||
<template #form-bottom>
|
<template #form-bottom>
|
||||||
<div>
|
<div>申请证书</div>
|
||||||
申请证书
|
|
||||||
</div>
|
|
||||||
</template>
|
</template>
|
||||||
<pi-certd-form ref="certdFormRef"></pi-certd-form>
|
<pi-certd-form ref="certdFormRef"></pi-certd-form>
|
||||||
</fs-crud>
|
</fs-crud>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ["update:modelValue"],
|
emits: ["update:modelValue"],
|
||||||
setup(props:any, ctx:any) {
|
setup(props: any, ctx: any) {
|
||||||
const options = ref<any[]>([]);
|
const options = ref<any[]>([]);
|
||||||
|
|
||||||
const pipeline = inject("pipeline") as Ref<any>;
|
const pipeline = inject("pipeline") as Ref<any>;
|
||||||
@@ -23,8 +23,10 @@ export default {
|
|||||||
const currentStepIndex = inject("currentStepIndex") as Ref<number>;
|
const currentStepIndex = inject("currentStepIndex") as Ref<number>;
|
||||||
const currentTask = inject("currentTask") as Ref<any>;
|
const currentTask = inject("currentTask") as Ref<any>;
|
||||||
|
|
||||||
|
const getPluginGroups = inject("getPluginGroups") as Ref<any>;
|
||||||
|
const pluginGroups = getPluginGroups();
|
||||||
function onCreate() {
|
function onCreate() {
|
||||||
options.value = pluginManager.getPreStepOutputOptions({
|
options.value = pluginGroups.getPreStepOutputOptions({
|
||||||
pipeline: pipeline.value,
|
pipeline: pipeline.value,
|
||||||
currentStageIndex: currentStageIndex.value,
|
currentStageIndex: currentStageIndex.value,
|
||||||
currentStepIndex: currentStepIndex.value,
|
currentStepIndex: currentStepIndex.value,
|
||||||
@@ -40,14 +42,14 @@ export default {
|
|||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => {
|
() => {
|
||||||
return pluginManager.map;
|
return pluginGroups.value.map;
|
||||||
},
|
},
|
||||||
() => {
|
() => {
|
||||||
onCreate();
|
onCreate();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
function onChanged(value:any) {
|
function onChanged(value: any) {
|
||||||
ctx.emit("update:modelValue", value);
|
ctx.emit("update:modelValue", value);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-drawer v-model:open="stepDrawerVisible" placement="right" :closable="true" width="600px" @after-open-change="stepDrawerOnAfterVisibleChange">
|
<a-drawer v-model:open="stepDrawerVisible" placement="right" :closable="true" width="700px" @after-open-change="stepDrawerOnAfterVisibleChange">
|
||||||
<template #title>
|
<template #title>
|
||||||
编辑步骤
|
编辑步骤
|
||||||
<a-button v-if="editMode" @click="stepDelete()">
|
<a-button v-if="editMode" @click="stepDelete()">
|
||||||
@@ -8,30 +8,36 @@
|
|||||||
</template>
|
</template>
|
||||||
<template v-if="currentStep">
|
<template v-if="currentStep">
|
||||||
<pi-container v-if="currentStep._isAdd" class="pi-step-form">
|
<pi-container v-if="currentStep._isAdd" class="pi-step-form">
|
||||||
<a-row :gutter="10">
|
<a-tabs tab-position="left">
|
||||||
<a-col v-for="(item, index) of stepPluginDefineList" :key="index" class="step-plugin" :span="12">
|
<a-tab-pane v-for="group of pluginGroups.groups" :key="group.key" :tab="group.title">
|
||||||
<a-card
|
<a-row :gutter="10">
|
||||||
hoverable
|
<a-col v-for="item of group.plugins" :key="item.key" class="step-plugin" :span="12">
|
||||||
:class="{ current: item.name === currentStep.type }"
|
<a-card
|
||||||
@click="stepTypeSelected(item)"
|
hoverable
|
||||||
@dblclick="
|
:class="{ current: item.name === currentStep.type }"
|
||||||
stepTypeSelected(item);
|
@click="stepTypeSelected(item)"
|
||||||
stepTypeSave();
|
@dblclick="
|
||||||
"
|
stepTypeSelected(item);
|
||||||
>
|
stepTypeSave();
|
||||||
<a-card-meta>
|
"
|
||||||
<template #title>
|
>
|
||||||
<a-avatar :src="item.icon || '/images/plugin.png'" />
|
<a-card-meta>
|
||||||
<span class="title">{{ item.title }}</span>
|
<template #title>
|
||||||
</template>
|
<a-avatar :src="item.icon || '/images/plugin.png'" />
|
||||||
<template #description>
|
<span class="title">{{ item.title }}</span>
|
||||||
<span :title="item.desc">{{ item.desc }}</span>
|
</template>
|
||||||
</template>
|
<template #description>
|
||||||
</a-card-meta>
|
<span :title="item.desc">{{ item.desc }}</span>
|
||||||
</a-card>
|
</template>
|
||||||
</a-col>
|
</a-card-meta>
|
||||||
</a-row>
|
</a-card>
|
||||||
<a-button v-if="editMode" type="primary" @click="stepTypeSave"> 确定 </a-button>
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
</a-tab-pane>
|
||||||
|
</a-tabs>
|
||||||
|
<div style="padding: 20px; margin-left: 100px">
|
||||||
|
<a-button v-if="editMode" type="primary" @click="stepTypeSave"> 确定 </a-button>
|
||||||
|
</div>
|
||||||
</pi-container>
|
</pi-container>
|
||||||
<pi-container v-else class="pi-step-form">
|
<pi-container v-else class="pi-step-form">
|
||||||
<a-form ref="stepFormRef" class="step-form" :model="currentStep" :label-col="labelCol" :wrapper-col="wrapperCol">
|
<a-form ref="stepFormRef" class="step-form" :model="currentStep" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||||
@@ -91,6 +97,8 @@ import { computed, inject, Ref, ref } from "vue";
|
|||||||
import _ from "lodash-es";
|
import _ from "lodash-es";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { CopyOutlined } from "@ant-design/icons-vue";
|
import { CopyOutlined } from "@ant-design/icons-vue";
|
||||||
|
import { PluginGroups } from "/@/views/certd/pipeline/pipeline/type";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "PiStepForm",
|
name: "PiStepForm",
|
||||||
components: { CopyOutlined },
|
components: { CopyOutlined },
|
||||||
@@ -107,8 +115,8 @@ export default {
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
function useStepForm() {
|
function useStepForm() {
|
||||||
const stepPluginDefineList: any = inject("plugins");
|
const getPluginGroups: any = inject("getPluginGroups");
|
||||||
|
const pluginGroups: PluginGroups = getPluginGroups();
|
||||||
const mode: Ref = ref("add");
|
const mode: Ref = ref("add");
|
||||||
const callback: Ref = ref();
|
const callback: Ref = ref();
|
||||||
const currentStep: Ref = ref({ title: undefined, input: {} });
|
const currentStep: Ref = ref({ title: undefined, input: {} });
|
||||||
@@ -199,9 +207,7 @@ export default {
|
|||||||
|
|
||||||
const changeCurrentPlugin = (step: any) => {
|
const changeCurrentPlugin = (step: any) => {
|
||||||
const stepType = step.type;
|
const stepType = step.type;
|
||||||
const pluginDefine = stepPluginDefineList.value.find((p: any) => {
|
const pluginDefine = pluginGroups.get(stepType);
|
||||||
return p.name === stepType;
|
|
||||||
});
|
|
||||||
if (pluginDefine) {
|
if (pluginDefine) {
|
||||||
step.type = stepType;
|
step.type = stepType;
|
||||||
step._isAdd = false;
|
step._isAdd = false;
|
||||||
@@ -271,7 +277,7 @@ export default {
|
|||||||
return {
|
return {
|
||||||
stepTypeSelected,
|
stepTypeSelected,
|
||||||
stepTypeSave,
|
stepTypeSave,
|
||||||
stepPluginDefineList,
|
pluginGroups,
|
||||||
stepFormRef,
|
stepFormRef,
|
||||||
mode,
|
mode,
|
||||||
stepAdd,
|
stepAdd,
|
||||||
|
|||||||
@@ -1,5 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<a-drawer v-model:open="taskDrawerVisible" placement="right" :closable="true" width="600px" class="pi-task-form" @after-open-change="taskDrawerOnAfterVisibleChange">
|
<a-drawer
|
||||||
|
v-model:open="taskDrawerVisible"
|
||||||
|
placement="right"
|
||||||
|
:closable="true"
|
||||||
|
width="700px"
|
||||||
|
class="pi-task-form"
|
||||||
|
@after-open-change="taskDrawerOnAfterVisibleChange"
|
||||||
|
>
|
||||||
<template #title>
|
<template #title>
|
||||||
编辑任务
|
编辑任务
|
||||||
<a-button v-if="editMode" @click="taskDelete()">
|
<a-button v-if="editMode" @click="taskDelete()">
|
||||||
@@ -24,7 +31,13 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<div class="steps">
|
<div class="steps">
|
||||||
<a-form-item :value="currentTask.steps" name="steps" label="" :wrapper-col="{ span: 24 }" :rules="[{ required: true, message: '至少需要一个步骤,或者你可以点击标题右边删除按钮删除此任务' }]">
|
<a-form-item
|
||||||
|
:value="currentTask.steps"
|
||||||
|
name="steps"
|
||||||
|
label=""
|
||||||
|
:wrapper-col="{ span: 24 }"
|
||||||
|
:rules="[{ required: true, message: '至少需要一个步骤,或者你可以点击标题右边删除按钮删除此任务' }]"
|
||||||
|
>
|
||||||
<a-descriptions title="任务步骤" size="small">
|
<a-descriptions title="任务步骤" size="small">
|
||||||
<template #extra>
|
<template #extra>
|
||||||
<a-button type="primary" @click="stepAdd(currentTask)">添加步骤</a-button>
|
<a-button type="primary" @click="stepAdd(currentTask)">添加步骤</a-button>
|
||||||
@@ -70,7 +83,7 @@ import { provide, Ref, ref } from "vue";
|
|||||||
import _ from "lodash-es";
|
import _ from "lodash-es";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import PiStepForm from "../step-form/index.vue";
|
import PiStepForm from "../step-form/index.vue";
|
||||||
import { message, Modal } from "ant-design-vue";
|
import { Modal } from "ant-design-vue";
|
||||||
import { CopyOutlined } from "@ant-design/icons-vue";
|
import { CopyOutlined } from "@ant-design/icons-vue";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -88,7 +101,7 @@ export default {
|
|||||||
const stepFormRef: Ref<any> = ref(null);
|
const stepFormRef: Ref<any> = ref(null);
|
||||||
const currentStepIndex = ref(0);
|
const currentStepIndex = ref(0);
|
||||||
provide("currentStepIndex", currentStepIndex);
|
provide("currentStepIndex", currentStepIndex);
|
||||||
const stepAdd = (task: any, stepDef: any) => {
|
const stepAdd = (task: any, stepDef?: any) => {
|
||||||
currentStepIndex.value = task.steps.length;
|
currentStepIndex.value = task.steps.length;
|
||||||
stepFormRef.value.stepAdd((type: any, value: any) => {
|
stepFormRef.value.stepAdd((type: any, value: any) => {
|
||||||
if (type === "save") {
|
if (type === "save") {
|
||||||
@@ -179,7 +192,7 @@ export default {
|
|||||||
|
|
||||||
const taskAdd = (emit: any, taskMerge: any) => {
|
const taskAdd = (emit: any, taskMerge: any) => {
|
||||||
mode.value = "add";
|
mode.value = "add";
|
||||||
const blankTask = { id: nanoid(), title: "新任务", steps: [], status: null };
|
const blankTask: any = { id: nanoid(), title: "新任务", steps: [], status: null };
|
||||||
const task: any = _.merge(blankTask, taskMerge);
|
const task: any = _.merge(blankTask, taskMerge);
|
||||||
taskOpen(task, emit);
|
taskOpen(task, emit);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -223,7 +223,7 @@ import _ from "lodash-es";
|
|||||||
import { message, Modal, notification } from "ant-design-vue";
|
import { message, Modal, notification } from "ant-design-vue";
|
||||||
import { pluginManager } from "/@/views/certd/pipeline/pipeline/plugin";
|
import { pluginManager } from "/@/views/certd/pipeline/pipeline/plugin";
|
||||||
import { nanoid } from "nanoid";
|
import { nanoid } from "nanoid";
|
||||||
import { PipelineDetail, PipelineOptions, RunHistory } from "./type";
|
import { PipelineDetail, PipelineOptions, PluginGroups, RunHistory } from "./type";
|
||||||
import type { Runnable } from "@certd/pipeline";
|
import type { Runnable } from "@certd/pipeline";
|
||||||
import PiHistoryTimelineItem from "/@/views/certd/pipeline/pipeline/component/history-timeline-item.vue";
|
import PiHistoryTimelineItem from "/@/views/certd/pipeline/pipeline/component/history-timeline-item.vue";
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
@@ -348,17 +348,17 @@ export default defineComponent({
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const plugins: Ref<any> = ref([]);
|
const pluginGroupsRef: Ref<PluginGroups> = ref();
|
||||||
|
|
||||||
const fetchPlugins = async () => {
|
const fetchPlugins = async () => {
|
||||||
const list = await props.options.getPlugins();
|
pluginGroupsRef.value = await props.options.getPluginGroups();
|
||||||
plugins.value = list;
|
|
||||||
pluginManager.init(list);
|
|
||||||
};
|
};
|
||||||
fetchPlugins();
|
fetchPlugins();
|
||||||
|
|
||||||
provide("pipeline", pipeline);
|
provide("pipeline", pipeline);
|
||||||
provide("plugins", plugins);
|
provide("getPluginGroups", () => {
|
||||||
|
return pluginGroupsRef.value;
|
||||||
|
});
|
||||||
provide("currentHistory", currentHistory);
|
provide("currentHistory", currentHistory);
|
||||||
|
|
||||||
function useTask() {
|
function useTask() {
|
||||||
|
|||||||
@@ -17,49 +17,7 @@ export class PluginManager {
|
|||||||
this.map = map;
|
this.map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
get(name: string) {
|
|
||||||
return this.map[name];
|
|
||||||
}
|
|
||||||
|
|
||||||
getPreStepOutputOptions({ pipeline, currentStageIndex, currentStepIndex, currentTask }: any) {
|
|
||||||
const steps = this.collectionPreStepOutputs({
|
|
||||||
pipeline,
|
|
||||||
currentStageIndex,
|
|
||||||
currentStepIndex,
|
|
||||||
currentTask
|
|
||||||
});
|
|
||||||
const options: any[] = [];
|
|
||||||
for (const step of steps) {
|
|
||||||
const stepDefine = this.get(step.type);
|
|
||||||
for (const key in stepDefine?.output) {
|
|
||||||
options.push({
|
|
||||||
value: `step.${step.id}.${key}`,
|
|
||||||
label: `${stepDefine.output[key].title}【from:${step.title}】`,
|
|
||||||
type: step.type
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
collectionPreStepOutputs({ pipeline, currentStageIndex, currentStepIndex, currentTask }: any) {
|
|
||||||
const steps: any[] = [];
|
|
||||||
// 开始放step
|
|
||||||
for (let i = 0; i < currentStageIndex; i++) {
|
|
||||||
const stage = pipeline.stages[i];
|
|
||||||
for (const task of stage.tasks) {
|
|
||||||
for (const step of task.steps) {
|
|
||||||
steps.push(step);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//放当前任务下的step
|
|
||||||
for (let i = 0; i < currentStepIndex; i++) {
|
|
||||||
const step = currentTask.steps[i];
|
|
||||||
steps.push(step);
|
|
||||||
}
|
|
||||||
return steps;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const pluginManager = new PluginManager();
|
export const pluginManager = new PluginManager();
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Pipeline } from "@certd/pipeline";
|
import type { Pipeline } from "@certd/pipeline";
|
||||||
|
import { FormItemProps } from "@fast-crud/fast-crud";
|
||||||
export type PipelineDetail = {
|
export type PipelineDetail = {
|
||||||
pipeline: Pipeline;
|
pipeline: Pipeline;
|
||||||
};
|
};
|
||||||
@@ -10,6 +11,110 @@ export type RunHistory = {
|
|||||||
[id: string]: string[];
|
[id: string]: string[];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
export type PluginGroup = {
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
desc?: string;
|
||||||
|
order: number;
|
||||||
|
plugins: any[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type PluginDefine = {
|
||||||
|
key: string;
|
||||||
|
title: string;
|
||||||
|
desc?: string;
|
||||||
|
input: {
|
||||||
|
[key: string]: FormItemProps;
|
||||||
|
};
|
||||||
|
output: {
|
||||||
|
[key: string]: any;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export class PluginGroups {
|
||||||
|
groups: { [key: string]: PluginGroup };
|
||||||
|
map: { [key: string]: PluginDefine };
|
||||||
|
constructor(groups: { [key: string]: PluginGroup }) {
|
||||||
|
this.groups = groups;
|
||||||
|
this.initGroup(groups);
|
||||||
|
this.initMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private initGroup(groups: { [p: string]: PluginGroup }) {
|
||||||
|
const all: PluginGroup = {
|
||||||
|
key: "all",
|
||||||
|
title: "全部",
|
||||||
|
order: 0,
|
||||||
|
plugins: []
|
||||||
|
};
|
||||||
|
for (const key in groups) {
|
||||||
|
all.plugins.push(...groups[key].plugins);
|
||||||
|
}
|
||||||
|
this.groups = {
|
||||||
|
all,
|
||||||
|
...groups
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
initMap() {
|
||||||
|
const map: { [key: string]: PluginDefine } = {};
|
||||||
|
for (const key in this.groups) {
|
||||||
|
const group = this.groups[key];
|
||||||
|
for (const plugin of group.plugins) {
|
||||||
|
map[plugin.name] = plugin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.map = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
getGroups() {
|
||||||
|
return this.groups;
|
||||||
|
}
|
||||||
|
|
||||||
|
get(name: string) {
|
||||||
|
return this.map[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
getPreStepOutputOptions({ pipeline, currentStageIndex, currentStepIndex, currentTask }: any) {
|
||||||
|
const steps = this.collectionPreStepOutputs({
|
||||||
|
pipeline,
|
||||||
|
currentStageIndex,
|
||||||
|
currentStepIndex,
|
||||||
|
currentTask
|
||||||
|
});
|
||||||
|
const options: any[] = [];
|
||||||
|
for (const step of steps) {
|
||||||
|
const stepDefine = this.get(step.type);
|
||||||
|
for (const key in stepDefine?.output) {
|
||||||
|
options.push({
|
||||||
|
value: `step.${step.id}.${key}`,
|
||||||
|
label: `${stepDefine.output[key].title}【from:${step.title}】`,
|
||||||
|
type: step.type
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
collectionPreStepOutputs({ pipeline, currentStageIndex, currentStepIndex, currentTask }: any) {
|
||||||
|
const steps: any[] = [];
|
||||||
|
// 开始放step
|
||||||
|
for (let i = 0; i < currentStageIndex; i++) {
|
||||||
|
const stage = pipeline.stages[i];
|
||||||
|
for (const task of stage.tasks) {
|
||||||
|
for (const step of task.steps) {
|
||||||
|
steps.push(step);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//放当前任务下的step
|
||||||
|
for (let i = 0; i < currentStepIndex; i++) {
|
||||||
|
const step = currentTask.steps[i];
|
||||||
|
steps.push(step);
|
||||||
|
}
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export type PipelineOptions = {
|
export type PipelineOptions = {
|
||||||
doTrigger(options: { pipelineId: number }): Promise<void>;
|
doTrigger(options: { pipelineId: number }): Promise<void>;
|
||||||
@@ -17,5 +122,5 @@ export type PipelineOptions = {
|
|||||||
getPipelineDetail(query: { pipelineId: number }): Promise<PipelineDetail>;
|
getPipelineDetail(query: { pipelineId: number }): Promise<PipelineDetail>;
|
||||||
getHistoryList(query: { pipelineId: number }): Promise<RunHistory[]>;
|
getHistoryList(query: { pipelineId: number }): Promise<RunHistory[]>;
|
||||||
getHistoryDetail(query: { historyId: number }): Promise<RunHistory>;
|
getHistoryDetail(query: { historyId: number }): Promise<RunHistory>;
|
||||||
getPlugins(): Promise<Pipeline[]>;
|
getPluginGroups(): Promise<PluginGroups>;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,2 +1,3 @@
|
|||||||
koa:
|
koa:
|
||||||
port: 7001
|
port: 7001
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,27 @@
|
|||||||
All notable changes to this project will be documented in this file.
|
All notable changes to this project will be documented in this file.
|
||||||
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
||||||
|
|
||||||
|
## [1.22.4](https://github.com/certd/certd/compare/v1.22.3...v1.22.4) (2024-07-26)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/ui-server
|
||||||
|
|
||||||
|
## [1.22.3](https://github.com/certd/certd/compare/v1.22.2...v1.22.3) (2024-07-25)
|
||||||
|
|
||||||
|
**Note:** Version bump only for package @certd/ui-server
|
||||||
|
|
||||||
|
## [1.22.2](https://github.com/certd/certd/compare/v1.22.1...v1.22.2) (2024-07-23)
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* 修复创建流水线时,无法根据dns类型默认正确的dns授权的bug ([a2c43b5](https://github.com/certd/certd/commit/a2c43b50a6069ed48958fd142844a8568c2af452))
|
||||||
|
|
||||||
|
## [1.22.1](https://github.com/certd/certd/compare/v1.22.0...v1.22.1) (2024-07-20)
|
||||||
|
|
||||||
|
### Performance Improvements
|
||||||
|
|
||||||
|
* 创建证书任务可以选择lege插件 ([affef13](https://github.com/certd/certd/commit/affef130378030c517250c58a4e787b0fc85d7d1))
|
||||||
|
* 支持配置启动后自动触发一次任务 ([a5a0c1f](https://github.com/certd/certd/commit/a5a0c1f6e7a3f05e581005e491d5b102ee854412))
|
||||||
|
|
||||||
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
# [1.22.0](https://github.com/certd/certd/compare/v1.21.2...v1.22.0) (2024-07-19)
|
||||||
|
|
||||||
### Features
|
### Features
|
||||||
|
|||||||
5
packages/ui/certd-server/before-build.js
Normal file
5
packages/ui/certd-server/before-build.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import fs from 'fs';
|
||||||
|
//读取 packages/core/pipline/package.json的版本号
|
||||||
|
import { default as packageJson } from './tsconfig.json' assert { type: 'json' };
|
||||||
|
delete packageJson.references;
|
||||||
|
fs.writeFileSync('./tsconfig.json', JSON.stringify(packageJson, null, 2));
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
INSERT INTO sys_settings ("key", title, setting,access) VALUES ("sys.install","安装信息",'{"installTime":'|| (select timestamp from 'flyway_history' where id = 1 )||'}',"private");
|
INSERT INTO sys_settings ("key", title, setting,access) VALUES ('sys.install','安装信息','{"installTime":'|| (select timestamp from 'flyway_history' where id = 1 )||'}','private');
|
||||||
|
|
||||||
ALTER TABLE sys_user ADD COLUMN password_version integer DEFAULT 1;
|
ALTER TABLE sys_user ADD COLUMN password_version integer DEFAULT 1;
|
||||||
ALTER TABLE sys_user ADD COLUMN password_salt varchar(36);
|
ALTER TABLE sys_user ADD COLUMN password_salt varchar(36);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@certd/ui-server",
|
"name": "@certd/ui-server",
|
||||||
"version": "1.22.0",
|
"version": "1.22.4",
|
||||||
"description": "fast-server base midway",
|
"description": "fast-server base midway",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
@@ -13,19 +13,20 @@
|
|||||||
"lint": "mwts check",
|
"lint": "mwts check",
|
||||||
"lint:fix": "mwts fix",
|
"lint:fix": "mwts fix",
|
||||||
"ci": "npm run cov",
|
"ci": "npm run cov",
|
||||||
"build": "mwtsc --cleanOutDir",
|
"build": "mwtsc --cleanOutDir --skipLibCheck",
|
||||||
|
"build-on-docker": "node ./before-build.js && npm run build",
|
||||||
"up-mw-deps": "npx midway-version -u -w"
|
"up-mw-deps": "npx midway-version -u -w"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@alicloud/cs20151215": "^3.0.3",
|
"@alicloud/cs20151215": "^3.0.3",
|
||||||
"@alicloud/openapi-client": "^0.4.0",
|
"@alicloud/openapi-client": "^0.4.0",
|
||||||
"@alicloud/pop-core": "^1.7.10",
|
"@alicloud/pop-core": "^1.7.10",
|
||||||
"@certd/acme-client": "^1.22.0",
|
"@certd/acme-client": "^1.22.4",
|
||||||
"@certd/lib-huawei": "^1.22.0",
|
"@certd/lib-huawei": "^1.22.1",
|
||||||
"@certd/lib-k8s": "^1.22.0",
|
"@certd/lib-k8s": "^1.22.3",
|
||||||
"@certd/midway-flyway-js": "^1.22.0",
|
"@certd/midway-flyway-js": "^1.22.3",
|
||||||
"@certd/pipeline": "^1.22.0",
|
"@certd/pipeline": "^1.22.3",
|
||||||
"@certd/plugin-cert": "^1.22.0",
|
"@certd/plugin-cert": "^1.22.4",
|
||||||
"@koa/cors": "^3.4.3",
|
"@koa/cors": "^3.4.3",
|
||||||
"@midwayjs/bootstrap": "^3.16.2",
|
"@midwayjs/bootstrap": "^3.16.2",
|
||||||
"@midwayjs/cache": "^3.14.0",
|
"@midwayjs/cache": "^3.14.0",
|
||||||
@@ -39,9 +40,10 @@
|
|||||||
"@midwayjs/validate": "^3.16.4",
|
"@midwayjs/validate": "^3.16.4",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"bcryptjs": "^2.4.3",
|
"bcryptjs": "^2.4.3",
|
||||||
|
"better-sqlite3": "^11.1.2",
|
||||||
"cache-manager": "^3.6.3",
|
"cache-manager": "^3.6.3",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"glob": "^11.0.0",
|
"glob": "^10.4.5",
|
||||||
"https-proxy-agent": "^7.0.4",
|
"https-proxy-agent": "^7.0.4",
|
||||||
"iconv-lite": "^0.6.3",
|
"iconv-lite": "^0.6.3",
|
||||||
"js-yaml": "^4.1.0",
|
"js-yaml": "^4.1.0",
|
||||||
@@ -52,12 +54,12 @@
|
|||||||
"log4js": "^6.7.1",
|
"log4js": "^6.7.1",
|
||||||
"lru-cache": "^10.0.0",
|
"lru-cache": "^10.0.0",
|
||||||
"md5": "^2.3.0",
|
"md5": "^2.3.0",
|
||||||
|
"mwtsc": "^1.4.0",
|
||||||
"nanoid": "^4.0.0",
|
"nanoid": "^4.0.0",
|
||||||
"node-cron": "^3.0.2",
|
"node-cron": "^3.0.2",
|
||||||
"nodemailer": "^6.9.3",
|
"nodemailer": "^6.9.3",
|
||||||
"pg": "^8.12.0",
|
"pg": "^8.12.0",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
"sqlite3": "^5.1.4",
|
|
||||||
"ssh2": "^0.8.9",
|
"ssh2": "^0.8.9",
|
||||||
"svg-captcha": "^1.4.0",
|
"svg-captcha": "^1.4.0",
|
||||||
"tencentcloud-sdk-nodejs": "^4.0.44",
|
"tencentcloud-sdk-nodejs": "^4.0.44",
|
||||||
@@ -78,7 +80,6 @@
|
|||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"mocha": "^10.2.0",
|
"mocha": "^10.2.0",
|
||||||
"mwts": "^1.3.0",
|
"mwts": "^1.3.0",
|
||||||
"mwtsc": "^1.4.0",
|
|
||||||
"prettier": "^2.8.8",
|
"prettier": "^2.8.8",
|
||||||
"ts-node": "^10.9.2",
|
"ts-node": "^10.9.2",
|
||||||
"typescript": "~5.1.0"
|
"typescript": "~5.1.0"
|
||||||
|
|||||||
1
packages/ui/certd-server/public/index.html
Normal file
1
packages/ui/certd-server/public/index.html
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1
|
||||||
@@ -37,7 +37,9 @@ const development = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
cron: {},
|
cron: {
|
||||||
|
immediateTriggerOnce: false,
|
||||||
|
},
|
||||||
/**
|
/**
|
||||||
* 演示环境
|
* 演示环境
|
||||||
*/
|
*/
|
||||||
@@ -54,10 +56,10 @@ const development = {
|
|||||||
/**
|
/**
|
||||||
* 单数据库实例
|
* 单数据库实例
|
||||||
*/
|
*/
|
||||||
type: 'sqlite',
|
type: 'better-sqlite3',
|
||||||
database: './data/db.sqlite',
|
database: './data/db.sqlite',
|
||||||
synchronize: false, // 如果第一次使用,不存在表,有同步的需求可以写 true
|
synchronize: false, // 如果第一次使用,不存在表,有同步的需求可以写 true
|
||||||
logging: true,
|
logging: false,
|
||||||
|
|
||||||
// 配置实体模型 或者 entities: '/entity',
|
// 配置实体模型 或者 entities: '/entity',
|
||||||
entities: ['**/modules/*/entity/*.ts', '**/entity/*.js', '**/entity/*.d.ts', PipelineEntity, FlywayHistory, UserEntity],
|
entities: ['**/modules/*/entity/*.ts', '**/entity/*.js', '**/entity/*.d.ts', PipelineEntity, FlywayHistory, UserEntity],
|
||||||
@@ -84,6 +86,8 @@ const development = {
|
|||||||
resetAdminPasswd: false,
|
resetAdminPasswd: false,
|
||||||
},
|
},
|
||||||
} as MidwayConfig;
|
} as MidwayConfig;
|
||||||
|
mergeConfig(development, 'development');
|
||||||
|
|
||||||
mergeConfig(development, env);
|
mergeConfig(development, env);
|
||||||
|
|
||||||
export default development;
|
export default development;
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ const preview = {
|
|||||||
preview: {
|
preview: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
},
|
},
|
||||||
|
typeorm: {
|
||||||
|
dataSource: {
|
||||||
|
default: {
|
||||||
|
logging: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
} as MidwayConfig;
|
} as MidwayConfig;
|
||||||
|
|
||||||
mergeConfig(preview, 'preview');
|
mergeConfig(preview, 'preview');
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ const production = {
|
|||||||
preview: {
|
preview: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
},
|
},
|
||||||
|
typeorm: {
|
||||||
|
dataSource: {
|
||||||
|
default: {
|
||||||
|
logging: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
} as MidwayConfig;
|
} as MidwayConfig;
|
||||||
|
|
||||||
mergeConfig(production, 'production');
|
mergeConfig(production, 'production');
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Autoload, Init, Inject, Scope, ScopeEnum } from '@midwayjs/core';
|
import { Autoload, Config, Init, Inject, Scope, ScopeEnum } from '@midwayjs/core';
|
||||||
import { PipelineService } from '../service/pipeline-service.js';
|
import { PipelineService } from '../service/pipeline-service.js';
|
||||||
import { logger } from '../../../utils/logger.js';
|
import { logger } from '../../../utils/logger.js';
|
||||||
|
|
||||||
@@ -10,11 +10,13 @@ export class AutoRegisterCron {
|
|||||||
|
|
||||||
// @Inject()
|
// @Inject()
|
||||||
// echoPlugin: EchoPlugin;
|
// echoPlugin: EchoPlugin;
|
||||||
|
@Config('cron.immediateTriggerOnce')
|
||||||
|
private immediateTriggerOnce = false;
|
||||||
|
|
||||||
@Init()
|
@Init()
|
||||||
async init() {
|
async init() {
|
||||||
logger.info('加载定时trigger开始');
|
logger.info('加载定时trigger开始');
|
||||||
await this.pipelineService.onStartup();
|
await this.pipelineService.onStartup(this.immediateTriggerOnce);
|
||||||
// logger.info(this.echoPlugin, this.echoPlugin.test);
|
// logger.info(this.echoPlugin, this.echoPlugin.test);
|
||||||
// logger.info('加载定时trigger完成');
|
// logger.info('加载定时trigger完成');
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,11 +1,4 @@
|
|||||||
import {
|
import { ALL, Controller, Inject, Post, Provide, Query } from '@midwayjs/core';
|
||||||
ALL,
|
|
||||||
Controller,
|
|
||||||
Inject,
|
|
||||||
Post,
|
|
||||||
Provide,
|
|
||||||
Query,
|
|
||||||
} from '@midwayjs/core';
|
|
||||||
import { BaseController } from '../../../basic/base-controller.js';
|
import { BaseController } from '../../../basic/base-controller.js';
|
||||||
import { PluginService } from '../service/plugin-service.js';
|
import { PluginService } from '../service/plugin-service.js';
|
||||||
import { Constants } from '../../../basic/constants.js';
|
import { Constants } from '../../../basic/constants.js';
|
||||||
@@ -25,4 +18,11 @@ export class PluginController extends BaseController {
|
|||||||
const list = this.service.getList();
|
const list = this.service.getList();
|
||||||
return this.ok(list);
|
return this.ok(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('/groups', { summary: Constants.per.authOnly })
|
||||||
|
async groups(@Query(ALL) query) {
|
||||||
|
query.userId = this.ctx.user.id;
|
||||||
|
const group = this.service.getGroups();
|
||||||
|
return this.ok(group);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Config, Inject, Provide, Scope, ScopeEnum } from '@midwayjs/core';
|
import { Config, Inject, Provide, Scope, ScopeEnum, sleep } from '@midwayjs/core';
|
||||||
import { InjectEntityModel } from '@midwayjs/typeorm';
|
import { InjectEntityModel } from '@midwayjs/typeorm';
|
||||||
import { In, Repository } from 'typeorm';
|
import { In, Repository } from 'typeorm';
|
||||||
import { BaseService } from '../../../basic/base-service.js';
|
import { BaseService } from '../../../basic/base-service.js';
|
||||||
@@ -80,7 +80,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
/**
|
/**
|
||||||
* 应用启动后初始加载记录
|
* 应用启动后初始加载记录
|
||||||
*/
|
*/
|
||||||
async onStartup() {
|
async onStartup(immediateTriggerOnce: boolean) {
|
||||||
logger.info('加载定时trigger开始');
|
logger.info('加载定时trigger开始');
|
||||||
const idEntityList = await this.repository.find({
|
const idEntityList = await this.repository.find({
|
||||||
select: {
|
select: {
|
||||||
@@ -114,7 +114,7 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
for (const entity of list) {
|
for (const entity of list) {
|
||||||
const pipeline = JSON.parse(entity.content ?? '{}');
|
const pipeline = JSON.parse(entity.content ?? '{}');
|
||||||
try {
|
try {
|
||||||
this.registerTriggers(pipeline);
|
await this.registerTriggers(pipeline, immediateTriggerOnce);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.error('加载定时trigger失败:', e);
|
logger.error('加载定时trigger失败:', e);
|
||||||
}
|
}
|
||||||
@@ -123,13 +123,18 @@ export class PipelineService extends BaseService<PipelineEntity> {
|
|||||||
logger.info('定时器数量:', this.cron.getListSize());
|
logger.info('定时器数量:', this.cron.getListSize());
|
||||||
}
|
}
|
||||||
|
|
||||||
registerTriggers(pipeline?: Pipeline) {
|
async registerTriggers(pipeline?: Pipeline, immediateTriggerOnce = false) {
|
||||||
if (pipeline?.triggers == null) {
|
if (pipeline?.triggers == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (const trigger of pipeline.triggers) {
|
for (const trigger of pipeline.triggers) {
|
||||||
this.registerCron(pipeline.id, trigger);
|
this.registerCron(pipeline.id, trigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (immediateTriggerOnce) {
|
||||||
|
await this.trigger(pipeline.id);
|
||||||
|
await sleep(1000);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async trigger(id) {
|
async trigger(id) {
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user