Compare commits

168 Commits

Author SHA1 Message Date
init
93c7bd5f53 change terminal 2025-08-11 11:29:50 +08:00
init
6f4a0ae8c1 change terminal 2025-07-16 22:11:32 +08:00
init
3dedd24e49 change terminal 2025-07-16 21:35:39 +08:00
init
ef6a6b3b02 Merge main 2025-07-16 20:03:42 +08:00
孟宁
dee60671e2 !85 devcontainer /root /etc/ssh 改为持久化
Merge pull request !85 from panshuxiao/fix-devcontainer
2025-07-05 02:07:48 +00:00
panshuxiao
d33b8057cb devcontainer /root /etc/ssh 改为持久化
修改open with vscode返回连接
2025-07-03 08:24:54 +08:00
孟宁
162eee261a !81 让devcontainer相关功能在 k8s上工作起来
Merge pull request !81 from panshuxiao/k8s-devcontainer
2025-06-28 06:44:20 +00:00
panshuxiao
9e568020ed devcontainer加回端口 2025-06-28 09:34:02 +08:00
away
8b77dbb369 !82 feat: 自定义logo功能
* !1 fixed-bug:更正操作结果提示信息与操作页面不一致,更改为都在/admin/config/settings 页面上
* fixed-bug:更正操作结果提示信息与操作页面不一致,更改为都在/admin/config/settings 页面上
* refactor(admin): 移动自定义logo上传表单位置
* style: 还原管理后台仪表盘模板代码格式
* style: 调整注释格式和规范国际化语言文件的标签文本
* style: 还原管理后台仪表盘模板代码格式
* feat: 添加单个设置的获取和设置函数
* feat: 自定义logo功能
2025-06-27 06:04:14 +00:00
panshuxiao
b2b80b25b9 Merge branch 'dev' into delete-nat 2025-06-25 13:19:09 +08:00
孟宁
aa01ae3e39 !74 vscode插件相关功能
Merge pull request !74 from Levi Yan/feature-vscode-home
2025-06-25 03:20:10 +00:00
panshuxiao
2403ca1c08 Merge branch 'dev' into add-nat 2025-06-19 10:14:55 +08:00
init
bf3a5db127 fix bug 2025-06-18 09:23:01 +08:00
孟宁
9fa387895c set default port is 80 2025-06-17 18:41:36 +08:00
孟宁
26c90510b3 Merge branch 'feature-vscode-home' of https://gitee.com/devstar/devstar into feature-vscode-home 2025-06-17 17:32:49 +08:00
Levi Yan
d822525bb0 Merge branch 'dev' into feature-vscode-home 2025-06-17 01:43:12 -07:00
panshuxiao
f69aaa099d 删除k8s-agent的NAT相关代码 2025-06-17 13:15:06 +08:00
孟宁
c2952ee49f !79 fixed-bug:修复持续部署CD功能,可以直接使用kubectl 升级部署DevStar到dev.devstar.cn上
Merge pull request !79 from vecmatex/fix-cd-bug
2025-06-16 02:36:14 +00:00
vecmatex
c11b6628bc 修改cd脚本bug 2025-06-16 10:29:53 +08:00
孟宁
cf375f4b59 !78 fixed-bug:修复持续部署CD功能,可以直接使用kubectl 升级部署DevStar到dev.devstar.cn上
Merge pull request !78 from vecmatex/fix_cd
2025-06-15 04:14:13 +00:00
vecmatex
e4c4e98392 修复cd脚本 2025-06-15 12:10:44 +08:00
孟宁
e5ffe7529d !77 fixed-bug:修复持续部署CD功能,可以直接使用kubectl 升级部署DevStar到dev.devstar.cn上
Merge pull request !77 from vecmatex/fix-cd
2025-06-15 02:56:36 +00:00
vecmatex
1a072589ee 修复cd脚本 2025-06-15 10:49:16 +08:00
vecmatex
7cf3bb8441 !76 修复持续部署CD功能,可以直接使用kubectl 升级部署DevStar到dev.devstar,cn上
* 修复cd功能
2025-06-14 07:09:44 +00:00
孟宁
8b9efb787d !75 实现了修改runner的标签的功能
Merge pull request !75 from vecmatex/can_change_runner_tag
2025-06-14 06:05:55 +00:00
孟宁
0d53d4fc78 Merge branch 'feature-vscode-home' of https://gitee.com/devstar/devstar into feature-vscode-home 2025-06-12 13:25:34 +08:00
Levi Yan
9bba618c1b revert: 取消功能【避免打开同一个项目】 2025-06-11 09:18:39 -07:00
孟宁
b5acc1e0f3 Merge branch 'feature-vscode-home' of https://gitee.com/devstar/devstar into feature-vscode-home 2025-06-05 14:20:24 +08:00
Levi Yan
68c9648353 feat: 根据devcontainerStatus确定容器是否准备完成 2025-06-03 20:11:57 -07:00
init
a391ae08f9 fix api bug 2025-06-03 20:11:57 -07:00
init
6b85dc6a4d feature-permission 2025-06-03 20:11:57 -07:00
Levi Yan
9fbecc81b9 feat: repolist不显示已打开项目的按钮 2025-06-03 20:11:35 -07:00
Levi Yan
214e101049 feat: create container button's disable to represent waiting when waiting project completion 2025-06-03 20:11:24 -07:00
vecmatex
25ac0b8163 实现了修改runner的标签的功能 2025-06-02 21:29:28 +08:00
vecmatex
8e960069cf 删除了不必要的内容 2025-06-02 13:03:18 +08:00
init
b61f7048df fix api bug 2025-05-29 11:13:22 +08:00
panshuxiao
72a526c65a 完善了webterminal功能 2025-05-28 01:30:51 +08:00
init
4f195b16e0 feature-permission 2025-05-27 23:58:00 +08:00
panshuxiao
475b1d0c22 添加了devcontainer的NAT映射 2025-05-26 10:20:57 +08:00
Levi Yan
092d46fcaf Merge branch 'feature-vscode-home' of https://gitee.com/devstar/devstar into feature-vscode-home 2025-05-22 03:24:43 -07:00
Levi Yan
13d926316c feat: provide repo name for firstOpenProject in vscode 2025-05-22 03:17:18 -07:00
Levi Yan
0bebc5c0b0 Merge branch 'feature-vscode-home' of https://gitee.com/devstar/devstar into feature-vscode-home 2025-05-22 01:23:54 +08:00
Levi Yan
501bdbae0d feat: create container button's disable to represent waiting when waiting project completion 2025-05-22 00:55:48 +08:00
Levi Yan
5e0031e26a feat: language support for zh-cn and english 2025-05-22 00:55:48 +08:00
Levi Yan
3eb2c6f11a refactor: keep footer code in devstar-home-vscode.tmpl 2025-05-22 00:55:48 +08:00
Levi Yan
24a16e92b5 refactor: separate js code from html 2025-05-22 00:55:48 +08:00
Levi Yan
9f69cd4cc1 feat: create container button's disable to represent waiting when waiting project completion 2025-05-21 09:31:22 -07:00
Levi Yan
070acc8483 feat: language support for zh-cn and english 2025-05-21 09:31:22 -07:00
Levi Yan
500245ca01 refactor: keep footer code in devstar-home-vscode.tmpl 2025-05-21 09:31:22 -07:00
Levi Yan
63566f4ad5 refactor: separate js code from html 2025-05-21 09:31:22 -07:00
panshuxiao
b68457f442 Merge branch 'dev' into fix-online-devcontainer 2025-05-20 12:08:32 +08:00
panshuxiao
404132dac5 修复devcontainer配置加载和controller-manager的问题
•增添了日志
2025-05-20 12:06:35 +08:00
孟宁
b9720a9419 !73 单机部署环境下实现Web界面上启动和删除runner
Merge pull request !73 from vecmatex/can_create_runner
2025-05-19 08:52:52 +00:00
vecmatex
cf787b837c fixbug 2025-05-19 16:40:56 +08:00
nimesulide
6c5aef664b 添加删除runner功能 2025-05-17 22:15:29 +08:00
vecmatex
76f87176d0 修改部分文本 2025-05-14 16:46:16 +08:00
vecmatex
04c8eb59e1 再次修改了布局 2025-05-14 16:37:47 +08:00
vecmatex
35e5d763cf 修改了一下页面布局 2025-05-14 16:36:03 +08:00
vecmatex
f8a8af4ec6 添加从页面注册runner功能 2025-05-14 15:35:15 +08:00
孟宁
2923b1bbd8 !72 暂时删除了modules/k8s/controller/devcontainer/suite_test
Merge pull request !72 from panshuxiao/devcontainer-on-k8s
2025-05-14 02:37:35 +00:00
panshuxiao
81fd66e634 暂时删除了modules/k8s/controller/devcontainer/suite_test 2025-05-14 10:25:03 +08:00
孟宁
1150dfd408 !71 将make test 从CI脚本中移除,恢复到Dockerfile.rootless中,原因是CI脚本的执行环境中缺少开发环境
Merge pull request !71 from 孟宁/dev-for-ci-make-test
2025-05-13 11:28:26 +00:00
孟宁
491f3cc447 update Dockerfile.rootless.
Signed-off-by: 孟宁 <mengning997@163.com>
2025-05-13 11:27:21 +00:00
孟宁
00fce5c941 update .gitea/workflows/devstar-studio-dev-ci.yaml.
Signed-off-by: 孟宁 <mengning997@163.com>
2025-05-13 11:26:49 +00:00
孟宁
62d9c893be !70 将make test 从CI脚本中移除,恢复到Dockerfile.rootless中,原因是CI脚本的执行环境中缺少开发环境
Merge pull request !70 from 孟宁/devcontainer-on-k8s
2025-05-13 11:07:01 +00:00
孟宁
fb508af19a update Dockerfile.rootless.
Signed-off-by: 孟宁 <mengning997@163.com>
2025-05-13 11:03:55 +00:00
孟宁
b12e64ccc8 update .gitea/workflows/devstar-studio-dev-ci.yaml.
Signed-off-by: 孟宁 <mengning997@163.com>
2025-05-13 11:02:58 +00:00
panshuxiao
33a4a54e85 !68 添加了devcontainer在k8s下的重启、暂停、webTerminal功能
* 修复k8s/devcontainer/suite_test
* 改进了DevStar Controller Manager镜像相关代码
* 修改了Dockerfile.rootless以解决go版本问题
* 移动Dockerfile.cotroller-manager位置
* Merge remote-tracking branch 'origin/dev' into devcontainer-on-k8s
* Merge remote-tracking branch 'origin/add_k8s' into AppOnK8s
* Merge remote-tracking branch 'origin/add-dockerfile-method-and-start-s…
*  添加了k8s下的停止、重启devcontainer和webterminal
* Merge branch 'add-dockerfile-method-and-start-stop-container' of https…
* 更新了容器镜像方式的构建、安装和使用方法,但是devcontainer功能还有问题
* fix run postCreateCommand bug
* sh文件方式管理启动脚本
* Merge branch 'add-dockerfile-method-and-start-stop-container' of https…
* add restart command and fix bug
* chore: 补充添加k8s controller的go.mod和go.sum文件
* Merge branch 'add-dockerfile-method-and-start-stop-container' of https…
* 为devstar添加k8s上的controller-manager
* add dockerfile method to create container and save container .restart …
2025-05-13 10:50:26 +00:00
panshuxiao
d506f11dd3 修复k8s/devcontainer/suite_test
• 添加了测试需要的bin
• 补充了devcontainer crd定义文件
2025-05-13 13:27:59 +08:00
孟宁
b938e71a82 改进了DevStar Controller Manager镜像相关代码 2025-05-12 19:24:35 +08:00
panshuxiao
3fbd87746e 修改了Dockerfile.rootless以解决go版本问题
• 取消了make test
2025-05-12 17:58:45 +08:00
Levi Yan
bec104a44c feat: create container button's disable to represent waiting when waiting project completion 2025-05-11 20:34:28 +08:00
Levi Yan
f95a209bc1 feat: language support for zh-cn and english 2025-05-11 20:34:28 +08:00
Levi Yan
bac5754314 refactor: keep footer code in devstar-home-vscode.tmpl 2025-05-11 20:34:28 +08:00
Levi Yan
e0b5450e99 refactor: separate js code from html 2025-05-11 20:34:28 +08:00
panshuxiao
d237dbe201 移动Dockerfile.cotroller-manager位置
• 添加了controller-manager的README.md
2025-05-08 19:44:21 +08:00
panshuxiao
d2c2a6e363 Merge remote-tracking branch 'origin/dev' into devcontainer-on-k8s 2025-05-08 10:16:12 +08:00
xinitx
02baa3b7af !67 增加了重启停止容器、dockerfile方式创建保存容器功能
* change initializeScript path
* Merge branch 'add-dockerfile-method-and-start-stop-container' of https…
* 更新了容器镜像方式的构建、安装和使用方法,但是devcontainer功能还有问题
* fix run postCreateCommand bug
* sh文件方式管理启动脚本
* add restart command and fix bug
* add dockerfile method to create container and save container .restart …
2025-05-07 11:10:30 +00:00
孟宁
fbd405af67 !69 修改ci脚本能让其自动更新dev.devstar.cn
Merge pull request !69 from vecmatex/add_k8s
2025-05-07 10:56:27 +00:00
panshuxiao
685878afd1 Merge remote-tracking branch 'origin/add_k8s' into AppOnK8s 2025-05-06 10:13:01 +08:00
panshuxiao
574ebd7f61 Merge remote-tracking branch 'origin/add-dockerfile-method-and-start-stop-container' into AppOnK8s 2025-05-06 10:12:48 +08:00
nimesulide
9293b45886 修改ci脚本能让其自动更新dev.devstar.cn 2025-04-30 16:01:40 +08:00
panshuxiao
234a5087fc 添加了k8s下的停止、重启devcontainer和webterminal
• 修改了Makefile添加了controller-manager
• 添加了controller-manager的Dockerfile
2025-04-29 20:18:28 +08:00
孟宁
16c75737f0 Merge branch 'add-dockerfile-method-and-start-stop-container' of https://gitee.com/devstar/devstar into add-dockerfile-method-and-start-stop-container 2025-04-29 16:52:01 +08:00
孟宁
4cc2aa5419 更新了容器镜像方式的构建、安装和使用方法,但是devcontainer功能还有问题 2025-04-29 16:51:26 +08:00
init
3d19432e47 fix run postCreateCommand bug 2025-04-29 16:43:11 +08:00
init
324c85215c sh文件方式管理启动脚本 2025-04-28 21:28:16 +08:00
panshuxiao
a28f802bd8 Merge branch 'add-dockerfile-method-and-start-stop-container' of https://gitee.com/devstar/devstar into AppOnK8s 2025-04-28 10:14:01 +08:00
init
d5f6a103e8 add restart command and fix bug 2025-04-22 22:24:16 +08:00
panshuxiao
3b81b02a66 chore: 补充添加k8s controller的go.mod和go.sum文件 2025-04-19 16:55:14 +08:00
panshuxiao
76974d2067 Merge branch 'add-dockerfile-method-and-start-stop-container' of https://gitee.com/devstar/devstar into AppOnK8s 2025-04-19 16:50:48 +08:00
panshuxiao
73935fba8e 为devstar添加k8s上的controller-manager
• manager入口为modules/k8s/cmd/controller-manager/controller-manager.go
• 修改了k8s.go的 CreateDevcontainer 函数以本地测试
2025-04-19 16:41:17 +08:00
init
03c76a7212 add dockerfile method to create container and save container .restart container.stop container 2025-04-16 23:25:04 +08:00
Levi Yan
cd2d2a4d25 devcontainer works
- localhost doesn't work,you should config domain name or IP Address
2025-03-29 06:26:42 +00:00
江舟水洲
4907b3cc4f !64 update public/assets/install.sh.
* update public/assets/install.sh.
* 用户可以使用--ssh-port参数指定端口号,默认2222
* update public/assets/install.sh.
2025-03-19 07:17:56 +00:00
xinitx
cd856c72bc !62 json管理和日志输出
* 合并输出按阶段显示
* ttyd初始目录
* 访问数据库放在services层
* 端口指定映射
* vscode链接
* 去掉devstar字符串
* Devcontainer前端页面显示进行了整理优化
* 修复 数据库 bug
* 增加容器output
2025-03-18 15:52:08 +00:00
孟宁
40258dbdfe !63 fixed-bug:在devstar.cn上微信二维码扫码查询用户时错误处理了已绑定用户
Merge pull request !63 from 孟宁/fixed-wechat-login-bug
2025-03-13 07:24:16 +00:00
孟宁
9512382ff7 fixed-bug:在devstar.cn上微信二维码扫码查询用户时错误处理了已绑定用户 2025-03-13 15:22:11 +08:00
孟宁
72e38d0913 !61 启动时能够自动启动act_runner
Merge pull request !61 from vecmatex/feature_add_runner
2025-02-20 01:28:04 +00:00
vecmatex
c944cd0e2a 启动时能够自动启动act_runner 2025-02-19 20:06:33 +08:00
孟宁
635238b3b7 !60 让运行时环境支持docker客户端,以便可以创建devcontainer
Merge pull request !60 from 孟宁/for-runtime-docker
2025-02-19 09:47:45 +00:00
孟宁
bc492dc881 让运行时环境支持docker客户端,以便可以创建devcontainer 2025-02-19 17:42:21 +08:00
孟宁
5cfec8e7b8 !59 !58 docker.io无法访问,换成devstar.cn上的容器镜像来运行CI脚本,但是ubuntu-latest是匹配runner的标签,还不能直接写完整的镜像地址;
Merge pull request !59 from 孟宁/revert-merge-57-dev
2025-02-18 10:47:25 +00:00
孟宁
51462e8538 回退 'Pull Request !57 : docker.io无法访问,换成devstar.cn上的容器镜像来运行CI脚本' 2025-02-18 10:45:48 +00:00
孟宁
90b3742145 !58 增加了将devstar-studio:latest同步到docker.io的触发Github工作流的脚本
* 增加了将devstar-studio:latest同步到docker.io的触发Github工作流的脚本
* docker.io无法访问,换成devstar.cn上的容器镜像来运行CI脚本,但是ubuntu-latest是匹配runner的标签,还不能直接写完整的镜像地址;
2025-02-18 10:41:19 +00:00
孟宁
b1c7db5255 !57 docker.io无法访问,换成devstar.cn上的容器镜像来运行CI脚本
* docker.io无法访问,换成devstar.cn上的容器镜像来运行CI脚本
2025-02-18 09:07:00 +00:00
孟宁
333a30ccf3 !56 fixed bug:误修改了测试用例导致make test无法通过
Merge pull request !56 from 孟宁/reset-for-make-test-pass
2025-02-18 03:57:51 +00:00
孟宁
d8d6c5e8ec fixed bug:误修改了测试用例导致make test无法通过 2025-02-18 10:46:29 +08:00
孟宁
ff588d6257 !55 fixed bug 安装后跳转到微信登录路径有误
Merge pull request !55 from 孟宁/fixed-install-bug-wechat

1. fixed bug 安装后跳转到微信登录路径有误

将.../wechat/official-account 相关路径简化为.../wechat
2025-02-18 02:36:30 +00:00
孟宁
675f337e50 fixed bug 安装后跳转到微信登录路径有误 2025-02-18 10:33:40 +08:00
孟宁
8f2a6dd48d !54 gitea.com相关链接无法访问,替换为gitea.cn
* https://gitea.com相关链接无法访问,替换为https://gitea.cn 部分替换为了https://devstar.cn
* https://docs.gitea.com相关链接无法访问,替换为https://docs.gitea.cn
2025-02-18 02:11:43 +00:00
孟宁
75343aca1e !53 整理了devcontainer的部分代码,只是修改了文件目录结构和命名,没有对代码进行本质上的改动
* fixed /api/devcontainer/user
* 修改了models/devcontainer目录下的文件命名
* 整理了devcontainer的部分代码,只是修改了文件目录结构和命名,没有对代码进行本质上的改动
2025-02-17 05:36:49 +00:00
孟宁
0557a744c0 !52 通过场景码SceneStr区分用户登录不同的部署版本,优化了代码
* 修改了微信公众号关注事件和文本消息的响应
* 通过场景码SceneStr区分用户登录不同的部署版本,优化了代码
* 兼容线上/api/wechat/official-account相关API
* 对第三方依赖中的PowerWeChat和officialAccount等字符串进行了本地化抽象,以Wechat和wechat_sdk命名可读性更好
* Merge branch 'dev' into refactoring-wechat-qr-code
* 梳理了routers到auth_service的代码,wechat_service还需要进一步整理
* 对代码文件目录结构进行了重构,内在逻辑还没有重构
* wechat相关路径中删掉了无意义的official-account字符串
2025-02-14 10:41:45 +00:00
xinitx
e31075b296 !50 devcontainer页面功能实现及代码结构优化
### devcontainer页面功能实现

- devcontainer.json 可以正常编辑
- 可以创建devcontainer, **但是首次创建需要docker pull 容器镜像会造成系统卡死的情况,需要后续优化** 
- 可以open with WebTerminal, **但是进入的WebTerminal当前目录并不是当前项目目录下**
- 修改后的容器可以docker commit为新的容器镜像

### devcontainer代码结构优化

docker相关操作都放在了modules/docker/docker_api.go
2025-02-13 05:56:32 +00:00
Levi Yan
82fc70a29a !49 [VSCode] DevStar Home
* clean: remove unused function openProject
* refactor: refactor the repo list loading, adjust button display based …
* format: align divs
* perf: prioritize loading the content that users can see first
* refactor: separate the openDevContainer function
* refactor: createDevContainer return Promise
* fix: hasDevContainer function doesn't work
* clean: remove useless function that get default public key from vscode
* refactor: apply new notification method
* refactor: add prefix for all vscode login tokens' name
* feat: show all notification by vscode and add new communication method…
* refactor: remove global error notification from gitea
2025-01-22 02:02:35 +00:00
孟宁
0442763bd9 !48 [VSCode] DevStar Home
Merge pull request !48 from Levi Yan/feature-devstar-home-vscode
2025-01-09 10:25:45 +00:00
Levi Yan
ca0f0885e5 Merge remote-tracking branch 'origin/feature-devstar-home-vscode' into feature-devstar-home-vscode 2025-01-08 09:27:20 +08:00
Levi Yan
c1b17a6ae3 feat: ssh key title format: username-machine-timestamp 2025-01-08 01:17:46 +08:00
Levi Yan
e67b621288 Merge branch 'dev' into feature-devstar-home-vscode 2025-01-07 12:27:26 +08:00
xinitx
e6d1dbb381 !46 [DIP-2][DevContainer] 添加 WebSSH 和 保存镜像功能、更新了DevContainer相关的配置
* 合并devcontainer web相关的源文件,简化目录结构
* devcontainer、ssh_key_pair和devcontainer.cloud
* fixed bug:创建容器时Host为localhost时创建失败的问题
* 删除了死代码,更新了一些命名(主要是去掉devstar字符串)
* 常量名全大写
* devcontainer HOST改为用户设置的域名或IP
* 安装时如没有配置devcontainer则默认设置为docker方式
* 直接使用kubernetes和docker简化代码提高可读性
* 去除services/devstar_devcontainer文件夹名中不必要的devstar字符串
* 去除services/devstar_devcontainer文件夹名中不必要的devstar字符串
* 文件名中去掉不必要的devstar字符串
* 变量名中删除不必要的Devstar字符串
* Merge branch 'dev' into feature-websshAndUpdateImage
* change pages style
* change Structure
* fix bug
* websshAndUpdateImage
2025-01-07 01:25:54 +00:00
Levi Yan
4496c4ba0a Merge branch 'dev' into feature-devstar-home-vscode
# Conflicts:
#	templates/devstar-home-vscode.tmpl
2025-01-06 19:42:31 +08:00
Levi Yan
d36c073f2a fix: the close icon for loginModal does not disappear after the interface is stretched 2025-01-02 11:03:53 +08:00
Levi Yan
ac2a063ad7 feat: focus message when it appear 2025-01-02 10:47:45 +08:00
Levi Yan
04b71a37a6 feat: add varible DEVSTAR_DOMAIN_TEST_URL to facilitate development 2025-01-01 23:38:49 +08:00
Levi Yan
171bc80cd7 [DIP-3][VSCode] Add DevStar Home Web UI For VSCode Extension
* use single quote
* fix: incorrectly set up devstar domain
* fix: incorrectly set up devstar domain
* clean: remove unused code
* fix: the close icon does not disappear after the interface is stretched
* refactor: unify style and call of message notification
* temporarily does not support signup-link
* refactor: replace DEVSTAR_HOME with DEVSTAR_DOMAIN, and read it from c…
* refactor: remove auto_init option for user
* temporarily does not support private
* [Fix] auto repo initialization after creation
* refactor: unified the interface changes after the login status change
* clean: remove unused code
* feat: the interface for creating a repository is similar to that on th…
* merge code from home.html
* en route /devstar-home
* init devstar-home-vscode.tmpl
2024-12-27 06:56:36 +00:00
Levi Yan
edc921239a fix: incorrectly set up devstar domain 2024-12-27 13:13:24 +08:00
Levi Yan
7cf0cb776c fix: incorrectly set up devstar domain 2024-12-27 13:00:28 +08:00
Levi Yan
5b45eaa30f clean: remove unused code 2024-12-27 12:37:10 +08:00
Levi Yan
d2684ce73f fix: the close icon does not disappear after the interface is stretched 2024-12-27 12:36:33 +08:00
Levi Yan
080e113d79 refactor: unify style and call of message notification 2024-12-27 12:30:41 +08:00
Levi Yan
a02a9a22a6 temporarily does not support signup-link 2024-12-27 12:25:20 +08:00
Levi Yan
7550f6a13f refactor: replace DEVSTAR_HOME with DEVSTAR_DOMAIN, and read it from config in vscode 2024-12-27 12:24:06 +08:00
Levi Yan
55b2bc6d06 refactor: remove auto_init option for user 2024-12-27 12:18:34 +08:00
Levi Yan
83d45c06d6 temporarily does not support private 2024-12-27 12:03:38 +08:00
戴明辰
46337e8077 [Fix] auto repo initialization after creation
auto init repo after creating it
2024-12-25 09:25:59 +00:00
Levi Yan
2cf41279a4 refactor: unified the interface changes after the login status change 2024-12-25 08:26:20 +00:00
Levi Yan
ac76dec6dc clean: remove unused code 2024-12-25 08:26:20 +00:00
Levi Yan
4dfb8c97fa feat: the interface for creating a repository is similar to that on the web (except for the interface after choosing repo template) 2024-12-25 08:26:20 +00:00
Levi Yan
36a2f71dc7 merge code from home.html 2024-12-25 08:26:20 +00:00
DAI Mingchen
52fbc5c556 en route /devstar-home 2024-12-25 08:26:20 +00:00
Levi Yan
4e509e94c2 init devstar-home-vscode.tmpl 2024-12-25 08:26:20 +00:00
戴明辰
90a460599b [Feature] Added DevContainerJSON to unmarshal /.devcontainer/devcontainer.json
* fix `nil` parsed of `postCreateCommand`
* parse undefined fields to `nil` ptr
* Added JSON Unmarshaler with default values
* Refactored DevContainer Model Errors
* Added `DevContainerJSON` to unmarshal devcontainer.json
2024-12-25 04:13:51 +00:00
孟宁
de546fd294 [DIP-1] 完善微信二维码安装跳转用户注册过程
* 完善了微信扫码注册流程,注册过程中绑定微信用户可见
* 安装完成后可以直接跳转到二维码登录,完善了enable/disable微信二维码功能
2024-12-24 07:25:30 +00:00
戴明辰
0f3ad27e7f [Feature][API] Added GET /api/v1/label/templates2
* Added GET /api/v1/label/templates2
2024-12-24 03:07:04 +00:00
戴明辰
40a41ac3e2 [Feature][API] 增加API用于创建仓库获取预定义选项列表:ReadMe, Object Format
* Added APIs to display creating repo option lists
2024-12-23 08:46:56 +00:00
孟宁
47d7a1cc04 [Chore] public/assets/install.sh: 指定版本镜像拉取,用户数据目录权限问题
* 支持docker.io镜像拉取和指定镜像版本;fixed bug: 用户数据目录权限问题
* fixed bug: 用户数据目录权限问题
* 支持docker.io镜像拉取和指定镜像版本
* add install.sh
2024-12-21 11:32:45 +00:00
戴明辰
9c4131623b [Chore] Use Tabao NPM Mirror in CI
* Updated `.npmrc`: add Tabao NPM Mirror
* Updated `Makefile`: display npm config list to validate NODE_MIRROR
* Updated `Dockerfile.rootless`: Removed trivial NPM Mirror settings, and added reference to `/.npmrc`::`registry`
2024-12-20 02:27:19 +00:00
孟宁
cd3bf834ac [Chore] 添加DevStar安装使用脚本
* add install.sh
2024-12-19 09:54:21 +00:00
孟宁
a57b4af354 [Doc] 更新REAME.md中的开发构建流程
* 更新REAME.md中的开发流程,放弃本地构建容器镜像
2024-12-11 10:25:05 +00:00
戴明辰
8123bdf277 [Fix] Cloud NAT Rule Deletion Upon DevContainer Deletion
* NAT Rule deletion upon DevContainer deletion
* NAT Port query and delete
2024-12-11 02:55:26 +00:00
孟宁
3edc4ce1e4 [DIP-1] 微信公众号二维码登录:本地部署与线上部署双端共用代码
* 恢复误删了的从未登录状态下的页面登录后跳转到当前页的功能
* secret是敏感信息,不能打印在日志里面
* fixed bug: 根据配置AppID和AppSecret来createPowerWechatApp
* 完成本地部署微信二维码登录功能,用户设置绑定微信的功能本地测试正常
* 本地部署可以扫码跳转注册页面,尚未查询用户数据
* 本地部署的后端已经可以和devstar.cn上的微信代理API打通,但是还没有调用本地用户认证相关代码,功能上还不完整
* 优化了signin navbar前端显示逻辑,根据app.ini配置使能wechat qr和openid
* 增加wechat配置项,以便同时支持直接和间接的微信二维码登录
* 恢复openid原有的初始配置方法
* 默认支持微信二维码登录(仅在安装配置上实现,功能上尚未实现),默认disabled openid
* "Initial commit from " + gitURL + " ( " + sha1 + " ) "
2024-12-10 08:41:20 +00:00
孟宁
4a55a192bb [Fix] 修复repo/migrate页面报错 Uncaught TypeError: Cannot read properties of undefined (reading 'match')
* 修复repo/migrate页面报错repo-template.js:22 Uncaught TypeError: Cannot read …
2024-12-05 08:31:14 +00:00
戴明辰
294175a836 !31 [Chore] Use CI Actions Proxy
* 使用 GitHub Actions 本地镜像代理
2024-12-05 07:16:03 +00:00
孟宁
72adae1757 [Fix][DIP-4] 修复了devstar.cn上的js bug及增加了模板创建仓库时提交日志中记录版本号
* commit msg中增加了模板仓库的版本号
* fixed bug in devstar.cn but not test
2024-12-05 06:42:57 +00:00
孟宁
b23094d410 [DIP-4]支持DevStar模板及Git URL作为模板及其他杂项
* 支持从Git URL初始化新建的仓库
* 前端支持Git URL commit id为模板创建项目,并优化了前端代码footer等
* 在DevStar.cn上不必支持DevStar Template
* 在前端扩展方式支持了DevStar Template
* 增加了数据持久化存储配置方法
* 本地部署时不显示底部的API及devstar.cn的网站备案号
* update LICENSE
* 完善README.md 恢复了可执行文件名称gitea
2024-12-02 01:43:39 +00:00
戴明辰
1a0bb2f28a Revert "!28 [Refactor][Doc][Chore] 将Gitea改名为Devstar,补充README.md开发环境安装指南"
This reverts commit 05e37d8da7.
2024-11-19 09:58:22 +00:00
孟宁
05e37d8da7 !28 [Refactor][Doc][Chore] 将Gitea改名为Devstar,补充README.md开发环境安装指南
* 名称改为devstar,并在README.md中添加了开发环境的安装指南
2024-11-19 09:25:17 +00:00
孟宁
d919045a41 update README.md.
Signed-off-by: 孟宁 <mengning997@163.com>
2024-11-10 02:17:09 +00:00
孟宁
f15d1f25d7 update docs/content/installation/on-kubernetes.zh-cn.md.
Signed-off-by: 孟宁 <mengning997@163.com>
2024-11-10 02:01:24 +00:00
戴明辰
2da936ba8c [DIP-1][Fix][WeChat] SignUp before Sending Activation Email
* [Fix] wechat signup before sending activation email
2024-11-08 04:03:21 +00:00
戴明辰
c96928b972 [DIP-1][WeChat] WeChat QR Signup, Login, and Unbind
* WeChat QR Sign Up, Login, and Unbind
* Add QR Refresh Icon
* refactor wechat QR login, and apply Gitea `APIContexter`
* GET /api/wechat/official-account/generate-qr-code?qrExpireSeconds=${qrExpireSeconds}&sceneStr=${sceneStr}
2024-11-07 10:12:13 +00:00
戴明辰
09aff0c0cf !24 [Fix] Nil pointer dereference in DevContainer Docker Agent
* [Lint] Replace 4 spaces with 1 Tab (in accordance with `/.editorconfig`)
* [Fix] Fix nullptr dereference
2024-11-06 10:05:11 +00:00
xinitx
b5f8d41d34 !20 [Fix] OpenDevcontainer docker获取端口号
* add error info
* change readme
* change readme
* add docker getting api
2024-11-05 12:13:42 +00:00
xinitx
71e6803a6d !19 [Doc][Fix] 修改 ReadMe 和 CORS相关代码
* change ReadMe
* change cors api
2024-11-05 01:36:52 +00:00
戴明辰
a6dbe1f813 !18 [Fix][CI] Invalid CI Workflow YAML
* [Fix] indentation error
* [Fix] yaml: line 22: did not find expected key
* [Fix] Replaced ambiguous Unicode characters
2024-10-31 08:39:42 +00:00
戴明辰
009fd55b89 !17 [CI] Renamed tag of output artifact
* [CI] delete obsolete CI Workflow
* [CI] define default branch as `dev`
* [CI] rename tag of output artifact, and add `latest`
2024-10-31 07:37:36 +00:00
xinitx
8d5b34e07e !16 [Feature] DevContainer 适配 Docker
* [Chore] format code style
* [Chore] go mod tidy
* remove deprecated config
* Update services/devstar_devcontainer/docker_agent/AssignDevcontainerCr…
2024-10-31 03:00:11 +00:00
戴明辰
c92eeecf06 !15 [Fix] WeChat QR Login
* [Fix] QR Expiration Mask too dark
* [Refactor] Deprecated in-memory cache, ready for Redis
* [Doc] Resolve WeChat QR config conflict in k8s mode
* [Fix] WeChat QR Login by default
2024-10-30 01:17:59 +00:00
repo.diff.stats_desc%!(EXTRA int=325, int=14670, int=4376)

repo.diff.view_file

@@ -5,7 +5,7 @@ repo: go-gitea/gitea
service: github
# Base URL for Gitea instance if using gitea service type (optional)
# Default: https://gitea.com
# Default: https://devstar.com
base-url:
# Changelog groups and which labeled PRs to add to each group

repo.diff.view_file

@@ -5,7 +5,7 @@
2. Please ask questions or configuration/deploy problems on our Discord
server (https://discord.gg/gitea) or forum (https://forum.gitea.com).
3. Please take a moment to check that your issue doesn't already exist.
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.com/help/faq)
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.cn/help/faq)
5. Please give all relevant information below for bug reports, because
incomplete details will be handled as an invalid report.
-->
@@ -26,7 +26,7 @@
- [ ] No
- Log gist:
<!-- It really is important to provide pertinent logs -->
<!-- Please read https://docs.gitea.com/administration/logging-config#collecting-logs-for-help -->
<!-- Please read https://docs.gitea.cn/administration/logging-config#collecting-logs-for-help -->
<!-- In addition, if your problem relates to git commands set `RUN_MODE=dev` at the top of app.ini -->
## Description

repo.diff.view_file

@@ -1,65 +0,0 @@
#
# Add secrets of Remote Git Repository Panel:
# - ${{ secrets.DOCKER_REGISTRY_USERNAME }}: username of Docker Registry
# - ${{ secrets.DOCKER_REGISTRY_PASSWORD }}: password corresponding to the Docker Registry username
# Add variables of Remote Git Repository Panel:
# - ${{ vars.DOCKER_REGISTRY_ADDRESS }}: the address for Docker Registry
# - ${{ vars.DOCKER_REPOSITORY_ARTIFACT}}: the artifact $name:$version, e.g., `devstar/devstar-studio:latest-rootless`
# Artifact命名规则 ${{ vars.DOCKER_REPOSITORY_ARTIFACT}}-build-${{ gitea.sha }}, e.g., www.devstar.cn/devstar/devstar-studio:rootless-build-0047d315a3f73cca0c18c641d24b0347456618d5
# DOCKER_REPOSITORY_ARTIFACT = www.devstar.cn/devstar/devstar-studio:rootless表示 Artifact 名称
# build 表示分支类别:正式发行分支
# ${{ gitea.sha }} 表示触发 CI Workflow 的 commit SHA
# 特别注意:如果使用 devstar.cn 作为 Docker Registry需要设置 Gitea Actions Runner 变量 DOCKER_REGISTRY_ADDRESS = www.devstar.cn若没有www前缀会导致上传失败Ingress重定向规则导致暂时无解
# 上传 Artifact 必须加上 www前缀而拉取时不需要加 www 前缀,例如:
# 上传前 artifact 名称: docker push www.devstar.cn/devstar/devstar-studio:rootless-build-0047d315a3f73cca0c18c641d24b0347456618d5
# 拉取 artifact 只需要: docker pull devstar.cn/devstar/devstar-studio:rootless-build-0047d315a3f73cca0c18c641d24b0347456618d5
name: DevStar Studio CI Pipeline - master branch
on:
pull_request:
branches:
- master
jobs:
build-and-push-x86-64-docker-image:
# TODO: 使用私有 registry 绕过默认 docker.io
runs-on: ubuntu-latest # Actual image: docker.io/library/gitea/runner_image:ubuntu-latest
steps:
- name: 🔍 Check out repository code
uses: actions/checkout@v4
with:
ref: master
- name: 🔧 Test Codes and Build an Artifact
run: |
echo "Prepare to build repository code ${{ gitea.repository }}:${{ gitea.ref }}."
make docker
- name: 🚀 Push Artifact to Docker Registry
run: |
docker tag devstar-studio:latest ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT }}-build-${{ gitea.sha }}
echo "${{ secrets.DOCKER_REGISTRY_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_REGISTRY_USERNAME }} ${{ vars.DOCKER_REGISTRY_ADDRESS }} --password-stdin
docker push ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT }}-build-${{ gitea.sha }}
- name: 🍏 Job Status Report
run: |
echo "🍏 This job's status is ${{ job.status }}."
echo "Output Artifact: ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}-build-${{ gitea.sha }}"
#
# P.S.:
################################################################################
# 1. How to config runner:
# $ docker run \
# --name gitea-act-runner-repo-devstar-studio \
# -d \
# -e GITEA_INSTANCE_URL=https://www.devstar.cn \
# -e GITEA_RUNNER_REGISTRATION_TOKEN=${YOUR_GITEA_RUNNER_REGISTRATION_TOKEN} \
# -v /var/run/docker.sock:/var/run/docker.sock \
# gitea/act_runner:latest
#
# 2. To clean the docker cache:
# $ docker builder prune --force
# $ if [ "$(docker volume ls -qf dangling=true)" ]; then docker volume rm $(docker volume ls -qf dangling=true); fi
#

repo.diff.view_file

@@ -1,21 +1,24 @@
# devstar-studio-dev-ci.yaml
# DevStar 测试并构建制品 CI 工作流定义 (默认分支 dev)
#
# Artifact命名规则:
# 1. ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}:latest
# e.g., devstar.cn/devstar/devstar-studio:latest
# 2. ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}:rootless-dev-${{ gitea.sha }}
# e.g., devstar.cn/devstar/devstar-studio:rootless-dev-0047d315a3f73cca0c18c641d24b0347456618d5
# 其中,
# - rootless 表示非 root 权限容器
# - dev 表示分支类别: dev 分支(默认分支)
# - ${{ gitea.sha }} 表示触发 CI Workflow 的 commit SHA
#
# 构建参数设置
# 点击仓库 > 设置 > Actions > 密钥:
# - ${{ secrets.DOCKER_REGISTRY_USERNAME }}: Docker Registry 用户名
# - ${{ secrets.DOCKER_REGISTRY_PASSWORD }}: Docker Registry 密码
# 点击仓库 > 设置 > Actions > 变量:
# - ${{ vars.DOCKER_REGISTRY_ADDRESS }}: Docker Registry 域名, e.g., `devstar.cn`
# - ${{ vars.DOCKER_REPOSITORY_ARTIFACT}}: 制品名称, e.g., `devstar/devstar-studio`
#
# Add secrets of Remote Git Repository Panel:
# - ${{ secrets.DOCKER_REGISTRY_USERNAME }}: username of Docker Registry
# - ${{ secrets.DOCKER_REGISTRY_PASSWORD }}: password corresponding to the Docker Registry username
# Add variables of Remote Git Repository Panel:
# - ${{ vars.DOCKER_REGISTRY_ADDRESS }}: the address for Docker Registry
# - ${{ vars.DOCKER_REPOSITORY_ARTIFACT}}: the artifact $name:$version, e.g., `devstar/devstar-studio:rootless`
# Artifact命名规则 ${{ vars.DOCKER_REPOSITORY_ARTIFACT}}-dev-${{ gitea.sha }}, e.g., www.devstar.cn/devstar/devstar-studio:rootless-dev-0047d315a3f73cca0c18c641d24b0347456618d5
# DOCKER_REPOSITORY_ARTIFACT = www.devstar.cn/devstar/devstar-studio:rootless表示 Artifact 名称
# dev 表示分支类别:临时开发分支
# ${{ gitea.sha }} 表示触发 CI Workflow 的 commit SHA
# 特别注意:如果使用 devstar.cn 作为 Docker Registry需要设置 Gitea Actions Runner 变量 DOCKER_REGISTRY_ADDRESS = www.devstar.cn若没有www前缀会导致上传失败Ingress重定向规则导致暂时无解
# 上传 Artifact 必须加上 www前缀而拉取时不需要加 www 前缀,例如:
# 上传前 artifact 名称: docker push www.devstar.cn/devstar/devstar-studio:rootless-dev-0047d315a3f73cca0c18c641d24b0347456618d5
# 拉取 artifact 只需要: docker pull devstar.cn/devstar/devstar-studio:rootless-dev-0047d315a3f73cca0c18c641d24b0347456618d5
name: DevStar Studio CI Pipeline - dev branch
on:
@@ -28,26 +31,48 @@ on:
jobs:
build-and-push-x86-64-docker-image:
# TODO: 使用私有 registry 绕过默认 docker.io
runs-on: ubuntu-latest # Actual image: docker.io/library/gitea/runner_image:ubuntu-latest
# Actual runs-on image: docker.io/library/gitea/runner_image:ubuntu-latest
runs-on: ubuntu-latest
steps:
- name: 🔍 Check out repository code
uses: actions/checkout@v4
uses: https://devstar.cn/actions/checkout@v4
with:
ref: dev
- name: 🔧 Test Codes and Build an Artifact
run: |
echo "Prepare to build repository code ${{ gitea.repository }}:${{ gitea.ref }}."
make docker
- name: 🚀 Push Artifact to Docker Registry
- name: 🚀 Push Artifact to devstar.cn and docker.io Registry
run: |
docker tag devstar-studio:latest ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}-dev-${{ gitea.sha }}
docker tag devstar-studio:latest ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}:rootless-dev-${{ gitea.sha }}
docker tag devstar-studio:latest ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}:latest
echo "${{ secrets.DOCKER_REGISTRY_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_REGISTRY_USERNAME }} ${{ vars.DOCKER_REGISTRY_ADDRESS }} --password-stdin
docker push ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}-dev-${{ gitea.sha }}
docker push ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}:rootless-dev-${{ gitea.sha }}
docker push ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}:latest
GITHUB_TOKEN="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"; REPO="mengning/DevStar"; WORKFLOW_FILE="PushDevStarImage2DockerHub.yml"; BRANCH="main"; URL="https://api.github.com/repos/$REPO/actions/workflows/$WORKFLOW_FILE/dispatches"; response=$(curl -s -o /dev/null -w "%{http_code}" -X POST "$URL" -H "Authorization: token $GITHUB_TOKEN" -H "Accept: application/vnd.github.v3+json" -d "{\"ref\":\"$BRANCH\"}"); if [ "$response" -eq 204 ]; then echo "将devstar-studio:latest同步到docker.io的Github工作流触发成功"; else echo "将devstar-studio:latest同步到docker.io的Github工作流触发失败HTTP 状态码 $response"; fi
docker tag devstar-controller-manager:latest ${{ vars.DOCKER_REGISTRY_ADDRESS }}/devstar/devstar-controller-manager:rootless-dev-${{ gitea.sha }}
docker tag devstar-controller-manager:latest ${{ vars.DOCKER_REGISTRY_ADDRESS }}/devstar/devstar-controller-manager:latest
echo "${{ secrets.DOCKER_REGISTRY_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_REGISTRY_USERNAME }} ${{ vars.DOCKER_REGISTRY_ADDRESS }} --password-stdin
docker push ${{ vars.DOCKER_REGISTRY_ADDRESS }}/devstar/devstar-controller-manager:rootless-dev-${{ gitea.sha }}
docker push ${{ vars.DOCKER_REGISTRY_ADDRESS }}/devstar/devstar-controller-manager:latest
- name: 🍏 Job Status Report
run: |
echo "🍏 This job's status is ${{ job.status }}."
echo "Output Artifact: ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}-dev-${{ gitea.sha }}"
echo "Output Artifact: ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}:rootless-dev-${{ gitea.sha }}"
echo "=> Artifact Tag: latest"
echo "=> Artifact Tag: rootless-dev-${{ gitea.sha }}"
echo "Output Artifact: ${{ vars.DOCKER_REGISTRY_ADDRESS }}/devstar/devstar-controller-manager:rootless-dev-${{ gitea.sha }}"
echo "=> Artifact Tag: latest"
echo "=> Artifact Tag: rootless-dev-${{ gitea.sha }}"
- name: 📝 Update dev.devstar.cn
run: |
curl -LO https://mirrors.ustc.edu.cn/kubernetes/core%3A/stable%3A/v1.28/deb/amd64/kubectl_1.28.0-1.1_amd64.deb
sudo dpkg -i kubectl_1.28.0-1.1_amd64.deb
kubectl config set-cluster remote-cluster --server=${{ secrets.K8S_URL }} --insecure-skip-tls-verify=true
kubectl config set-credentials token-user --token=${{ secrets.K8S_TOKEN }}
kubectl config set-context remote-context --cluster=remote-cluster --user=token-user
kubectl config use-context remote-context
kubectl set image deployment/dev-devstar-studio-gitea gitea=${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}:rootless-dev-${{ gitea.sha }} -n devstar-studio-ns
#

repo.diff.view_file

@@ -1,66 +0,0 @@
#
# Add secrets of Remote Git Repository Panel:
# - ${{ secrets.DOCKER_REGISTRY_USERNAME }}: username of Docker Registry
# - ${{ secrets.DOCKER_REGISTRY_PASSWORD }}: password corresponding to the Docker Registry username
# Add variables of Remote Git Repository Panel:
# - ${{ vars.DOCKER_REGISTRY_ADDRESS }}: the address for Docker Registry
# - ${{ vars.DOCKER_REPOSITORY_ARTIFACT}}: the artifact $name:$version, e.g., `devstar/devstar-studio:rootless`
# Artifact命名规则 ${{ vars.DOCKER_REPOSITORY_ARTIFACT}}-feature-${{ gitea.sha }}, e.g., www.devstar.cn/devstar/devstar-studio:rootless-feature-0047d315a3f73cca0c18c641d24b0347456618d5
# DOCKER_REPOSITORY_ARTIFACT = www.devstar.cn/devstar/devstar-studio:rootless表示 Artifact 名称
# feature 表示分支类别:临时测试分支
# ${{ gitea.sha }} 表示触发 CI Workflow 的 commit SHA
# 特别注意:如果使用 devstar.cn 作为 Docker Registry需要设置 Gitea Actions Runner 变量 DOCKER_REGISTRY_ADDRESS = www.devstar.cn若没有www前缀会导致上传失败Ingress重定向规则导致暂时无解
# 上传 Artifact 必须加上 www前缀而拉取时不需要加 www 前缀,例如:
# 上传前 artifact 名称: docker push www.devstar.cn/devstar/devstar-studio:rootless-feature-0047d315a3f73cca0c18c641d24b0347456618d5
# 拉取 artifact 只需要: docker pull devstar.cn/devstar/devstar-studio:rootless-feature-0047d315a3f73cca0c18c641d24b0347456618d5
# k8s Operator 功能临时测试 CI脚本正式发行版不应该有此文件
name: DevStar Studio CI Pipeline - branch feature-k8s-operator-agent
on:
push:
branches:
- feature-k8s-operator-agent
jobs:
build-and-push-x86-64-docker-image:
runs-on: ubuntu-latest
steps:
- name: 🔍 Check out repository code
uses: actions/checkout@v4
with:
ref: feature-k8s-operator-agent
- name: 🔧 Test Codes and Build an Artifact
run: |
echo "Prepare to build repository code ${{ gitea.repository }}:${{ gitea.ref }}."
make docker
- name: 🚀 Push Artifact to Docker Registry
run: |
docker tag devstar-studio:latest ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}-feature-${{ gitea.sha }}
echo "${{ secrets.DOCKER_REGISTRY_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_REGISTRY_USERNAME }} ${{ vars.DOCKER_REGISTRY_ADDRESS }} --password-stdin
docker push ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}-feature-${{ gitea.sha }}
- name: 🍏 Job Status Report
run: |
echo "🍏 This job's status is ${{ job.status }}."
echo "Output Artifact: ${{ vars.DOCKER_REGISTRY_ADDRESS }}/${{ vars.DOCKER_REPOSITORY_ARTIFACT}}-feature-${{ gitea.sha }}"
#
# P.S.:
################################################################################
# 1. How to config runner:
# $ docker run \
# --name gitea-act-runner-repo-devstar-studio \
# -d \
# -e GITEA_INSTANCE_URL=https://www.devstar.cn \
# -e GITEA_RUNNER_REGISTRATION_TOKEN=${YOUR_GITEA_RUNNER_REGISTRATION_TOKEN} \
# -v /var/run/docker.sock:/var/run/docker.sock \
# gitea/act_runner:latest
#
# 2. To clean the docker cache:
# $ docker builder prune --force
# $ if [ "$(docker volume ls -qf dangling=true)" ]; then docker volume rm $(docker volume ls -qf dangling=true); fi
#

repo.diff.view_file

@@ -14,8 +14,8 @@ body:
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
3. Make sure you are using the latest release and
take a moment to check that your issue hasn't been reported before.
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.com/help/faq)
5. It's really important to provide pertinent details and logs (https://docs.gitea.com/help/support),
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.cn/help/faq)
5. It's really important to provide pertinent details and logs (https://docs.gitea.cn/help/support),
incomplete details will be handled as an invalid report.
- type: textarea
id: description
@@ -47,7 +47,7 @@ body:
attributes:
value: |
It's really important to provide pertinent logs
Please read https://docs.gitea.com/administration/logging-config#collecting-logs-for-help
Please read https://docs.gitea.cn/administration/logging-config#collecting-logs-for-help
In addition, if your problem relates to git commands set `RUN_MODE=dev` at the top of app.ini
- type: input
id: logs

2
.github/ISSUE_TEMPLATE/config.yml repo.diff.vendored
repo.diff.view_file

@@ -10,7 +10,7 @@ contact_links:
url: https://discourse.gitea.io
about: Questions and configuration or deployment problems can also be discussed on our forum.
- name: Frequently Asked Questions
url: https://docs.gitea.com/help/faq
url: https://docs.gitea.cn/help/faq
about: Please check if your question isn't mentioned here.
- name: Crowdin Translations
url: https://crowdin.com/project/gitea

repo.diff.view_file

@@ -13,12 +13,12 @@ body:
2. Please ask questions or configuration/deploy problems on our Discord
server (https://discord.gg/gitea) or forum (https://discourse.gitea.io).
3. Please take a moment to check that your issue doesn't already exist.
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.com/help/faq)
4. Make sure it's not mentioned in the FAQ (https://docs.gitea.cn/help/faq)
5. Please give all relevant information below for bug reports, because
incomplete details will be handled as an invalid report.
6. In particular it's really important to provide pertinent logs. If you are certain that this is a javascript
error, show us the javascript console. If the error appears to relate to Gitea the server you must also give us
DEBUG level logs. (See https://docs.gitea.com/administration/logging-config#collecting-logs-for-help)
DEBUG level logs. (See https://docs.gitea.cn/administration/logging-config#collecting-logs-for-help)
- type: textarea
id: description
attributes:

2
.github/pull_request_template.md repo.diff.vendored
repo.diff.view_file

@@ -2,7 +2,7 @@
Please check the following:
1. Make sure you are targeting the `main` branch, pull requests on release branches are only allowed for backports.
2. Make sure you have read contributing guidelines: https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md .
3. For documentations contribution, please go to https://gitea.com/gitea/docs
3. For documentations contribution, please go to https://gitea.cn/gitea/docs
4. Describe what your pull request does and which issue you're targeting (if any).
5. It is recommended to enable "Allow edits by maintainers", so maintainers can help more easily.
6. Your input here will be included in the commit message when this PR has been merged. If you don't want some content to be included, please separate them with a line like `---`.

4
.gitignore repo.diff.vendored
repo.diff.view_file

@@ -48,6 +48,7 @@ cpu.out
*.log.*.gz
/gitea
/devstar
/gitea-vet
/debug
/integrations.test
@@ -114,3 +115,6 @@ prime/
# Manpage
/man
#k8s测试使用的模拟集群
modules/k8s/bin/

1
.npmrc
repo.diff.view_file

@@ -4,3 +4,4 @@ update-notifier=false
package-lock=true
save-exact=true
lockfile-version=3
registry=https://registry.npmmirror.com/

repo.diff.view_file

@@ -62,7 +62,7 @@
## Introduction
This document explains how to contribute changes to the Gitea project. \
It assumes you have followed the [installation instructions](https://docs.gitea.com/category/installation). \
It assumes you have followed the [installation instructions](https://docs.gitea.cn/category/installation). \
Sensitive security-related issues should be reported to [security@gitea.io](mailto:security@gitea.io).
For configuring IDEs for Gitea development, see the [contributed IDE configurations](contrib/ide/).
@@ -113,7 +113,7 @@ If further discussion is needed, we encourage you to open a new issue instead an
## Building Gitea
See the [development setup instructions](https://docs.gitea.com/development/hacking-on-gitea).
See the [development setup instructions](https://docs.gitea.cn/development/hacking-on-gitea).
## Dependencies
@@ -139,9 +139,9 @@ The same restrictions apply for frontend dependencies as for backend dependencie
Depending on your change, please read the
- [backend development guideline](https://docs.gitea.com/contributing/guidelines-backend)
- [frontend development guideline](https://docs.gitea.com/contributing/guidelines-frontend)
- [refactoring guideline](https://docs.gitea.com/contributing/guidelines-refactoring)
- [backend development guideline](https://docs.gitea.cn/contributing/guidelines-backend)
- [frontend development guideline](https://docs.gitea.cn/contributing/guidelines-frontend)
- [refactoring guideline](https://docs.gitea.cn/contributing/guidelines-refactoring)
## Styleguide
@@ -358,12 +358,12 @@ $REWRITTEN_PR_SUMMARY
## Documentation
If you add a new feature or change an existing aspect of Gitea, the documentation for that feature must be created or updated in another PR at [https://gitea.com/gitea/docs](https://gitea.com/gitea/docs).
If you add a new feature or change an existing aspect of Gitea, the documentation for that feature must be created or updated in another PR at [https://gitea.cn/gitea/docs](https://gitea.cn/gitea/docs).
**The docs directory on main repository will be removed at some time. We will have a yaml file to store configuration file's meta data. After that completed, configuration documentation should be in the main repository.**
## API v1
The API is documented by [swagger](https://gitea.com/api/swagger) and is based on [the GitHub API](https://docs.github.com/en/rest).
The API is documented by [swagger](https://devstar.com/api/swagger) and is based on [the GitHub API](https://docs.github.com/en/rest).
### GitHub API compatibility
@@ -522,27 +522,27 @@ If an elected member that accepts the seat does not have 2FA configured yet, the
- 2024-01-01 ~ 2024-12-31
- Company
- [Jason Song](https://gitea.com/wolfogre) <i@wolfogre.com>
- [Lunny Xiao](https://gitea.com/lunny) <xiaolunwen@gmail.com>
- [Matti Ranta](https://gitea.com/techknowlogick) <techknowlogick@gitea.com>
- [Jason Song](https://gitea.cn/wolfogre) <i@wolfogre.com>
- [Lunny Xiao](https://gitea.cn/lunny) <xiaolunwen@gmail.com>
- [Matti Ranta](https://gitea.cn/techknowlogick) <techknowlogick@gitea.com>
- Community
- [6543](https://gitea.com/6543) <6543@obermui.de>
- [delvh](https://gitea.com/delvh) <dev.lh@web.de>
- [John Olheiser](https://gitea.com/jolheiser) <john.olheiser@gmail.com>
- [6543](https://gitea.cn/6543) <6543@obermui.de>
- [delvh](https://gitea.cn/delvh) <dev.lh@web.de>
- [John Olheiser](https://gitea.cn/jolheiser) <john.olheiser@gmail.com>
### Previous TOC/owners members
Here's the history of the owners and the time they served:
- [Lunny Xiao](https://gitea.com/lunny) - 2016, 2017, [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [Lunny Xiao](https://gitea.cn/lunny) - 2016, 2017, [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [Kim Carlbäcker](https://github.com/bkcsoft) - 2016, 2017
- [Thomas Boerger](https://gitea.com/tboerger) - 2016, 2017
- [Lauris Bukšis-Haberkorns](https://gitea.com/lafriks) - [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801)
- [Matti Ranta](https://gitea.com/techknowlogick) - [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [Andrew Thornton](https://gitea.com/zeripath) - [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [6543](https://gitea.com/6543) - 2023
- [John Olheiser](https://gitea.com/jolheiser) - 2023
- [Jason Song](https://gitea.com/wolfogre) - 2023
- [Thomas Boerger](https://gitea.cn/tboerger) - 2016, 2017
- [Lauris Bukšis-Haberkorns](https://gitea.cn/lafriks) - [2018](https://github.com/go-gitea/gitea/issues/3255), [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801)
- [Matti Ranta](https://gitea.cn/techknowlogick) - [2019](https://github.com/go-gitea/gitea/issues/5572), [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [Andrew Thornton](https://gitea.cn/zeripath) - [2020](https://github.com/go-gitea/gitea/issues/9230), [2021](https://github.com/go-gitea/gitea/issues/13801), [2022](https://github.com/go-gitea/gitea/issues/17872), 2023
- [6543](https://gitea.cn/6543) - 2023
- [John Olheiser](https://gitea.cn/jolheiser) - 2023
- [Jason Song](https://gitea.cn/wolfogre) - 2023
## Governance Compensation
@@ -599,7 +599,7 @@ be reviewed by two maintainers and must pass the automatic tests.
- Add a tag as `git tag -s -F release.notes v$vmaj.$vmin.$`, release.notes file could be a temporary file to only include the changelog this version which you added to `CHANGELOG.md`.
- And then push the tag as `git push origin v$vmaj.$vmin.$`. Drone CI will automatically create a release and upload all the compiled binary. (But currently it doesn't add the release notes automatically. Maybe we should fix that.)
- If needed send a frontport PR for the changelog to branch `main` and update the version in `docs/config.yaml` to refer to the new version.
- Send PR to [blog repository](https://gitea.com/gitea/blog) announcing the release.
- Send PR to [blog repository](https://gitea.cn/gitea/blog) announcing the release.
- Verify all release assets were correctly published through CI on dl.gitea.com and GitHub releases. Once ACKed:
- bump the version of https://dl.gitea.com/gitea/version.json
- merge the blog post PR

repo.diff.view_file

@@ -2,18 +2,19 @@ ARG DOCKER_REGISTRY_ADDRESS="devstar.cn"
ARG DOCKER_REGISTRY_USERNAME="devstar"
ARG DEV_CONTAINER="gitea-dev-container:v1.0"
ARG RUNTIME_CONTAINER="gitea-runtime-container:v1.0"
ARG RUNTIME_CONTAINER="gitea-runtime-container:v1.1"
###########################################################
# stage1: Building Stage
FROM ${DOCKER_REGISTRY_ADDRESS}/${DOCKER_REGISTRY_USERNAME}/${DEV_CONTAINER} AS build-env
# 设置 Go 代理
ARG GOPROXY="https://goproxy.cn"
ARG NODEJS_PROXY="http://mirrors.cloud.tencent.com/nodejs-release/"
ENV GOPROXY=${GOPROXY:-direct}
ENV NODE_MIRROR=${NODEJS_PROXY}
# 注:对于 NPM 代理/镜像, 参考仓库 `/.npmrc` 文件下的 `registry` 变量,推荐使用淘宝镜像,即 `registry=https://registry.npmmirror.com/`
# 允许使用自动版本
ENV GOTOOLCHAIN=auto
ARG GITEA_VERSION
# TODO: 适配 https://devstar.cn
@@ -75,6 +76,8 @@ RUN mkdir -p /var/lib/gitea /etc/gitea
RUN chown git:git /var/lib/gitea /etc/gitea
COPY --from=build-env /tmp/local /
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/devcontainer_init.sh /app/gitea/devcontainer_init.sh
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/devcontainer_restart.sh /app/gitea/devcontainer_restart.sh
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/gitea /app/gitea/gitea
COPY --from=build-env --chown=root:root /go/src/code.gitea.io/gitea/environment-to-ini /usr/local/bin/environment-to-ini
COPY --from=build-env /go/src/code.gitea.io/gitea/contrib/autocompletion/bash_autocomplete /etc/profile.d/gitea_bash_autocomplete.sh

repo.diff.view_file

@@ -15,6 +15,7 @@ RUN apk --no-cache add \
sqlite \
su-exec \
gnupg \
docker-cli \
&& rm -rf /var/cache/apk/*
# To acquire Gitea base runtime container:

708
LICENSE
repo.diff.view_file

@@ -1,3 +1,711 @@
项目新增部分AGPL 3.0许可及版权放弃声明
项目名称DevStar Studio
发布日期2024年11月1日
项目社区发起者:梦宁软件
一、项目背景与目的
本项目旨在通过社区协作共同开发并维护一套高质量的软件产品。为了促进社区的健康发展确保代码的开放性和透明度项目社区决定对新增部分采用Affero General Public License, version 3.0以下简称“AGPL 3.0”进行发布。同时为了保障社区发起者梦宁软件的商业利益社区贡献者在提交代码时即放弃版权并授权社区及梦宁软件以AGPL 3.0使用并进行商业活动。
二、新增部分定义
本声明所称“新增部分”,是指自本声明发布之日起,由社区贡献者向本项目提交的所有代码、文档、测试数据等原创性成果。
三、版权放弃与授权
1. 版权放弃:所有社区贡献者在此声明,其向本项目提交的新增部分,在提交之时即视为已放弃对该新增部分的独占性版权。贡献者同意,在不违反法律法规的前提下,不对新增部分主张任何形式的版权保护。
2. 授权使用社区贡献者特此授权本项目社区及梦宁软件在遵守AGPL 3.0许可证条款的前提下,对新增部分进行使用、复制、修改、合并、发布、分发及再授权等操作。
3. 商业使用授权在遵守AGPL 3.0许可证条款的前提下,社区贡献者特此授权梦宁软件对新增部分进行商业使用,包括但不限于将新增部分用于商业产品开发、销售、提供服务或进行其他形式的商业活动。
四、原有代码与组件许可证保持不变
本声明仅适用于新增部分。对于本项目在发布本声明之前已存在的代码和组件,其许可证保持不变,继续按照原有的许可证条款进行使用和分发。
五、合规性要求
1. 所有社区贡献者在提交新增部分时,应确保该新增部分不侵犯任何第三方的知识产权,包括但不限于版权、商标、专利等。
2. 梦宁软件及本项目社区在使用、修改、分发或再授权新增部分时应遵守AGPL 3.0许可证的所有条款和条件,确保所有操作均合法合规。
3. 如因新增部分引发任何知识产权纠纷或法律诉讼,相关责任应由提交该新增部分的社区贡献者承担。
六、免责声明
本项目社区及梦宁软件不对因使用新增部分而产生的任何直接、间接、附带、特殊、惩罚性或后果性的损害赔偿承担责任。同时,本项目社区及梦宁软件不保证新增部分在任何特定用途下的适用性、可靠性或准确性。
七、其他
本声明自发布之日起生效,并构成社区贡献者与本项目社区及梦宁软件之间关于新增部分版权及使用的完整协议。如有任何争议,应首先通过友好协商解决;协商不成的,任何一方均有权向中国江苏省苏州市相关法律机构提起仲裁或诉讼。
Copyright (c) 2024 The DevStar Authors and Mengning Software
GNU AFFERO GENERAL PUBLIC LICENSE
Version 3, 19 November 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU Affero General Public License is a free, copyleft license for
software and other kinds of works, specifically designed to ensure
cooperation with the community in the case of network server software.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
our General Public Licenses are intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
Developers that use our General Public Licenses protect your rights
with two steps: (1) assert copyright on the software, and (2) offer
you this License which gives you legal permission to copy, distribute
and/or modify the software.
A secondary benefit of defending all users' freedom is that
improvements made in alternate versions of the program, if they
receive widespread use, become available for other developers to
incorporate. Many developers of free software are heartened and
encouraged by the resulting cooperation. However, in the case of
software used on network servers, this result may fail to come about.
The GNU General Public License permits making a modified version and
letting the public access it on a server without ever releasing its
source code to the public.
The GNU Affero General Public License is designed specifically to
ensure that, in such cases, the modified source code becomes available
to the community. It requires the operator of a network server to
provide the source code of the modified version running there to the
users of that server. Therefore, public use of a modified version, on
a publicly accessible server, gives the public access to the source
code of the modified version.
An older license, called the Affero General Public License and
published by Affero, was designed to accomplish similar goals. This is
a different license, not a version of the Affero GPL, but Affero has
released a new version of the Affero GPL which permits relicensing under
this license.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU Affero General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Remote Network Interaction; Use with the GNU General Public License.
Notwithstanding any other provision of this License, if you modify the
Program, your modified version must prominently offer all users
interacting with it remotely through a computer network (if your version
supports such interaction) an opportunity to receive the Corresponding
Source of your version by providing access to the Corresponding Source
from a network server at no charge, through some standard or customary
means of facilitating copying of software. This Corresponding Source
shall include the Corresponding Source for any work covered by version 3
of the GNU General Public License that is incorporated pursuant to the
following paragraph.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the work with which it is combined will remain governed by version
3 of the GNU General Public License.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU Affero General Public License from time to time. Such new versions
will be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU Affero General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU Affero General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU Affero General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published
by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If your software can interact with users remotely through a computer
network, you should also make sure that it provides a way for users to
get its source. For example, if your program is a web application, its
interface could display a "Source" link that leads users to an archive
of the code. There are many ways you could offer source, and different
solutions will be better for different programs; see section 13 for the
specific requirements.
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU AGPL, see
<http://www.gnu.org/licenses/>.
Copyright (c) 2016 The Gitea Authors
Copyright (c) 2015 The Gogs Authors

repo.diff.view_file

@@ -192,6 +192,7 @@ help:
@echo "Make Routines:"
@echo " - \"\" equivalent to \"build\""
@echo " - build build everything"
@echo " - build-debug build everything to debug"
@echo " - frontend build frontend files"
@echo " - backend build backend files"
@echo " - watch watch everything and continuously rebuild"
@@ -249,6 +250,9 @@ help:
@echo " - tidy run go mod tidy"
@echo " - test[\#TestSpecificName] run unit test"
@echo " - test-sqlite[\#TestSpecificName] run integration test for sqlite"
@echo " - controller-manager build controller-manager"
@echo " - controller-manager-debug build controller-manager with debug info"
@echo " - k8s-download-test-bins download Kubernetes test binaries (etcd, kube-apiserver, kubectl)"
.PHONY: go-check
go-check:
@@ -769,6 +773,16 @@ install: $(wildcard *.go)
.PHONY: build
build: frontend backend
# 添加一个新目标,用于构建带有调试信息的二进制文件
.PHONY: build-debug
build-debug: frontend backend-debug
.PHONY: backend-debug
backend-debug: go-check generate-backend $(EXECUTABLE)-debug
$(EXECUTABLE)-debug: $(GO_SOURCES) $(TAGS_PREREQ)
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o $@
.PHONY: frontend
frontend: $(WEBPACK_DEST)
@@ -874,6 +888,7 @@ deps-tools:
$(GO) install $(GOPLS_PACKAGE)
node_modules: package-lock.json
npm config list
npm install --no-save
@touch node_modules
@@ -981,9 +996,46 @@ generate-manpage:
.PHONY: docker
docker:
docker build -t devstar-studio:latest -f Dockerfile.rootless .
docker build -t devstar-controller-manager:latest -f modules/k8s/Dockerfile.controller-manager .
# docker build --disable-content-trust=false -t $(DOCKER_REF) .
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify" .
# 添加一个新目标,用于构建 controller-manager
.PHONY: controller-manager
controller-manager: go-check
@echo "Building controller-manager..."
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '-s -w $(LDFLAGS)' -o controller-manager modules/k8s/cmd/controller-manager/controller-manager.go
# 添加调试版本的编译目标
.PHONY: controller-manager-debug
controller-manager-debug: go-check
@echo "Building controller-manager with debug info..."
CGO_CFLAGS="$(CGO_CFLAGS)" $(GO) build $(GOFLAGS) $(EXTRA_GOFLAGS) -tags '$(TAGS)' -ldflags '$(LDFLAGS)' -o controller-manager-debug modules/k8s/cmd/controller-manager/controller-manager.go
# K8S 测试环境配置
K8S_BIN_DIR := modules/k8s/bin
K8S_LOCALBIN := $(K8S_BIN_DIR)
K8S_ENVTEST_K8S_VERSION := 1.31.0
K8S_ENVTEST_VERSION ?= release-0.19
K8S_ENVTEST ?= $(K8S_LOCALBIN)/setup-envtest
.PHONY: k8s-download-test-bins
k8s-download-test-bins: ## 下载 Kubernetes 测试二进制文件 (etcd, kube-apiserver, kubectl)
@echo "下载 Kubernetes $(K8S_ENVTEST_K8S_VERSION) 测试二进制文件..."
@mkdir -p $(K8S_LOCALBIN)
@# 首先下载 setup-envtest 工具
@[ -f "$(K8S_ENVTEST)" ] || GOBIN=$(shell pwd)/$(K8S_LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@$(K8S_ENVTEST_VERSION)
@# 然后使用该工具下载 K8S 测试二进制文件
@$(K8S_ENVTEST) use $(K8S_ENVTEST_K8S_VERSION) --bin-dir $(K8S_LOCALBIN)
@# 验证文件是否存在 - 根据实际输出调整路径检查
@if [ -d "$(K8S_LOCALBIN)/k8s/$(K8S_ENVTEST_K8S_VERSION)-$(shell go env GOOS)-$(shell go env GOARCH)" ]; then \
echo "测试二进制文件已下载到: $(K8S_LOCALBIN)/$(K8S_ENVTEST_K8S_VERSION)-$(shell go env GOOS)-$(shell go env GOARCH)/"; \
ls -la $(K8S_LOCALBIN)/k8s/$(K8S_ENVTEST_K8S_VERSION)-$(shell go env GOOS)-$(shell go env GOARCH)/; \
else \
echo "提示: 未在预期路径找到测试二进制文件,但可能已下载到其他位置。列出 $(K8S_LOCALBIN) 内容:"; \
find $(K8S_LOCALBIN) -type f -name "kube-apiserver" | grep -q . && echo "找到 kube-apiserver 文件,下载应该成功了。"; \
ls -la $(K8S_LOCALBIN)/; \
fi
# This endif closes the if at the top of the file
endif

174
README.md
repo.diff.view_file

@@ -1,139 +1,99 @@
# Gitea
# DevStar Studio
[![](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml/badge.svg?branch=main)](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly")
[![](https://img.shields.io/discord/322538954119184384.svg?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea")
[![](https://goreportcard.com/badge/code.gitea.io/gitea)](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card")
[![](https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg)](https://pkg.go.dev/code.gitea.io/gitea "GoDoc")
[![](https://img.shields.io/github/release/go-gitea/gitea.svg)](https://github.com/go-gitea/gitea/releases/latest "GitHub release")
[![](https://www.codetriage.com/go-gitea/gitea/badges/users.svg)](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
[![](https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen)](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
[![](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT "License: MIT")
[![Contribute with Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod&color=green)](https://gitpod.io/#https://github.com/go-gitea/gitea)
[![](https://badges.crowdin.net/gitea/localized.svg)](https://crowdin.com/project/gitea "Crowdin")
DevStar Studio 是一个Gitea 发行版在Git代码仓库托管的基础上提供了开发环境DevEnv执行引擎与VS Code插件或自定义IDE深度融合形成灵活适配基础软件工具的生态平台从而为开发者用户提供智能代码大模型AI+、安全完全云原生、一站式开箱即用的CI/CD全生命周期研发平台。
[View this document in Chinese](./README_ZH.md)
DevStar Studio是一个通用的一站式软件研发平台但它最初的目标是服务于汽车软件、消费电子、智能制造等嵌入式软件研发场景中的开发者。
## Purpose
DevStar Studio的愿景服务全球软件开发者
The goal of this project is to make the easiest, fastest, and most
painless way of setting up a self-hosted Git service.
如果你想试用在线演示或者使用免费的DevStar服务有数量限制请访问 [devstar.cn](https://devstar.cn/)。
As Gitea is written in Go, it works across **all** the platforms and
architectures that are supported by Go, including Linux, macOS, and
Windows on x86, amd64, ARM and PowerPC architectures.
This project has been
[forked](https://blog.gitea.com/welcome-to-gitea/) from
[Gogs](https://gogs.io) since November of 2016, but a lot has changed.
如果你想快速本地部署自己的DevStar实例免费试用或者报告问题请访问 [https://github.com/mengning/DevStar](https://github.com/mengning/DevStar)。
For online demonstrations, you can visit [demo.gitea.com](https://demo.gitea.com).
如果你是云服务厂商想为您的客户提供DevStar实例请联系contact@mengning.com.cn
For accessing free Gitea service (with a limited number of repositories), you can visit [gitea.com](https://gitea.com/user/login).
## Quick Start from source code
To quickly deploy your own dedicated Gitea instance on Gitea Cloud, you can start a free trial at [cloud.gitea.com](https://cloud.gitea.com).
如果您是在Windows环境下请在cmd命令行下先运行如下命令
## Building
```
wsl --install -d Ubuntu-20.04 && wsl --setdefault Ubuntu-20.04
```
From the root of the source tree, run:
在Ubuntu-20.04下完成安装:
TAGS="bindata" make build
```bash
# download and install go
wget -c https://go.dev/dl/go1.23.3.linux-amd64.tar.gz
sudo rm -rf /usr/local/go && sudo tar -C /usr/local -xzf go1.23.3.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin
go version
or if SQLite support is required:
# download and install Node.js
wget -c https://nodejs.org/dist/v22.11.0/node-v22.11.0-linux-x64.tar.xz
sudo tar -xf node-v22.11.0-linux-x64.tar.xz -C /usr/local/
echo 'export PATH=/usr/local/node-v22.11.0-linux-x64/bin:$PATH' >> ~/.bashrc
source ~/.bashrc
node -v # should print `v22.11.0`
npm -v # should print `10.9.0`
TAGS="bindata sqlite sqlite_unlock_notify" make build
The `build` target is split into two sub-targets:
- `make backend` which requires [Go Stable](https://go.dev/dl/), the required version is defined in [go.mod](/go.mod).
- `make frontend` which requires [Node.js LTS](https://nodejs.org/en/download/) or greater.
```
Internet connectivity is required to download the go and npm modules. When building from the official source tarballs which include pre-built frontend files, the `frontend` target will not be triggered, making it possible to build without Node.js.
### 提交代码Pull Request
More info: https://docs.gitea.com/installation/install-from-source
在DevStar Git仓库创建分支
```
git clone https://gitee.com/devstar/devstar.git
git checkout -b YOUR_BRANCH
code devstar
## Using
# in VS Code Terminal
TAGS="timetzdata sqlite sqlite_unlock_notify" make watch # for debuging
make test # testing
TAGS="bindata timetzdata sqlite sqlite_unlock_notify" make build # 生成可执行文件
./gitea
./gitea web
# 提交代码
git add FILES
git commit -m "commit log"
git push
```
> [!NOTE]
> If you're interested in using our APIs, we have experimental support with [documentation](https://docs.gitea.com/api).
#### Start from Container Image
## Contributing
```
make docker
public/assets/install.sh start --image=devstar-studio:latest
Expected workflow is: Fork -> Patch -> Push -> Pull Request
# 查看日志
public/assets/install.sh logs
# 停止并删除devstar-studio容器
public/assets/install.sh clean
# 删除所有容器
sudo docker stop $(docker ps -aq) && sudo docker rm -f $(docker ps -aq)
```
> [!NOTE]
>
> 1. **YOU MUST READ THE [CONTRIBUTORS GUIDE](CONTRIBUTING.md) BEFORE STARTING TO WORK ON A PULL REQUEST.**
> 2. If you have found a vulnerability in the project, please write privately to **security@gitea.io**. Thanks!
在DevStar Git仓库发起Pull Request合并代码后会自动触发CI流水线完成容器镜像的构建并上传到devstar.cn/devstar/devstar-studio:latest
## Translating
```
public/assets/install.sh start
```
Translations are done through Crowdin. If you want to translate to a new language ask one of the managers in the Crowdin project to add a new language there.
## 提示
You can also just create an issue for adding a language or ask on discord on the #translation channel. If you need context or find some translation issues, you can leave a comment on the string or ask on Discord. For general translation questions there is a section in the docs. Currently a bit empty but we hope to fill it as questions pop up.
1. **开始贡献代码之前请确保你已经看过了 [贡献者向导(英文)](CONTRIBUTING.md)**.
2. 所有的安全问题,请私下发送邮件给 **contact@mengning.com.cn**。谢谢!
https://docs.gitea.com/contributing/localization
## 文档
[![Crowdin](https://badges.crowdin.net/gitea/localized.svg)](https://crowdin.com/project/gitea)
关于如何安装请访问我们的 [文档站](https://github.com/mengning/DevStar),如果没有找到对应的文档,请私下发送邮件给 **contact@mengning.com.cn**和我们交流。
## Further information
## 贡献流程
For more information and instructions about how to install Gitea, please look at our [documentation](https://docs.gitea.com/).
If you have questions that are not covered by the documentation, you can get in contact with us on our [Discord server](https://discord.gg/Gitea) or create a post in the [discourse forum](https://forum.gitea.com/).
Fork -> Patch -> Push -> Pull Request
We maintain a list of Gitea-related projects at [gitea/awesome-gitea](https://gitea.com/gitea/awesome-gitea).
## 授权许可
The official Gitea CLI is developed at [gitea/tea](https://gitea.com/gitea/tea).
## Authors
- [Maintainers](https://github.com/orgs/go-gitea/people)
- [Contributors](https://github.com/go-gitea/gitea/graphs/contributors)
- [Translators](options/locale/TRANSLATORS)
## Backers
Thank you to all our backers! 🙏 [[Become a backer](https://opencollective.com/gitea#backer)]
<a href="https://opencollective.com/gitea#backers" target="_blank"><img src="https://opencollective.com/gitea/backers.svg?width=890"></a>
## Sponsors
Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [[Become a sponsor](https://opencollective.com/gitea#sponsor)]
<a href="https://opencollective.com/gitea/sponsor/0/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/0/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/1/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/1/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/2/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/2/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/3/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/3/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/4/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/4/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/5/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/5/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/6/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/6/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/7/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/7/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/8/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/8/avatar.svg"></a>
<a href="https://opencollective.com/gitea/sponsor/9/website" target="_blank"><img src="https://opencollective.com/gitea/sponsor/9/avatar.svg"></a>
## FAQ
**How do you pronounce Gitea?**
Gitea is pronounced [/ɡɪti:/](https://youtu.be/EM71-2uDAoY) as in "gi-tea" with a hard g.
**Why is this not hosted on a Gitea instance?**
We're [working on it](https://github.com/go-gitea/gitea/issues/1029).
## License
This project is licensed under the MIT License.
See the [LICENSE](https://github.com/go-gitea/gitea/blob/main/LICENSE) file
for the full license text.
## Screenshots
Looking for an overview of the interface? Check it out!
|![Dashboard](https://dl.gitea.com/screenshots/home_timeline.png)|![User Profile](https://dl.gitea.com/screenshots/user_profile.png)|![Global Issues](https://dl.gitea.com/screenshots/global_issues.png)|
|:---:|:---:|:---:|
|![Branches](https://dl.gitea.com/screenshots/branches.png)|![Web Editor](https://dl.gitea.com/screenshots/web_editor.png)|![Activity](https://dl.gitea.com/screenshots/activity.png)|
|![New Migration](https://dl.gitea.com/screenshots/migration.png)|![Migrating](https://dl.gitea.com/screenshots/migration.gif)|![Pull Request View](https://image.ibb.co/e02dSb/6.png)|
|![Pull Request Dark](https://dl.gitea.com/screenshots/pull_requests_dark.png)|![Diff Review Dark](https://dl.gitea.com/screenshots/review_dark.png)|![Diff Dark](https://dl.gitea.com/screenshots/diff_dark.png)|
本项目的单机发行版授权个人、非盈利性组织、用户数50人以下的商业组织永久免费使用云服务厂商、大型商业组织或基于Kubernetes云原生环境部署的客户请私下发送邮件给 **contact@mengning.com.cn**获取商业使用授权。谢谢!

repo.diff.view_file

@@ -1,430 +0,0 @@
# DevStar Studio
DevStar Studio 是 Gitea 发行版
## 1. 快速开始
编译、打包成为镜像:代码目录执行 `make docker` 命令
### 1.1 单机版部署
使用docker-compose部署DevStar Studio需要参考官方网站
https://docs.gitea.com/zh-cn/next/installation/install-with-docker-rootless
下列以SQLite db本地最小安装为例首先初次启动复制配置信息
```bash
docker run \
--restart=always \
--name devstar-studio \
-d \
-p 3000:3000 \
devstar-studio:latest
```
浏览器打开 http://localhost:3000执行安装操作记录下列路径名记录下来准备后续映射文件夹
需要复制的配置信息如下:
- 数据库文件路径名字
- 仓库根路径名字
- LFS根目录名字
- 日志路径名字
将容器内 `/etc/gitea/app.ini` 复制出来,参考[官网文档](https://docs.gitea.com/administration/config-cheat-sheet) 进行自定义
```bash
docker cp devstar-studio:/etc/gitea/app.ini ./app.ini
```
然后 添加/修改 下列小节键:
```ini
[wechat]
WECHAT_OFFICIAL_ACCOUNT_TEMP_QR_EXPIRE_SECONDS=60
WECHAT_OFFICIAL_ACCOUNT_APP_ID=<微信公众号APPID>
WECHAT_OFFICIAL_ACCOUNT_APP_SECRET=<微信公众号SECRET>
WECHAT_OFFICIAL_ACCOUNT_MESSAGE_TOKEN = <微信公众号自定义Token>
WECHAT_OFFICIAL_ACCOUNT_MESSAGE_AES_KEY = <微信公众号AES加密密钥>
[database]
CHARSET_COLLATION = utf8mb4_bin
[cors]
CONTENT_SECURITY_POLICY = default-src 'self' data: 'unsafe-inline' https://mp.weixin.qq.com; img-src * data:
[ui.admin]
;; Dev Container 分页参数(每页展示 DevContainer 个数),若未指定,默认值 50
DEV_CONTAINERS_PAGING_NUM = 50
[devstar.devcontainer]
ENABLED = true
AGENT = docker
TIMEOUT_SECONDS = 120
HOST = 127.0.0.1
[devstar.ssh_key_pair]
KEY_SIZE = <写入希望生成的SSH密钥长度比如 4096 ,默认值 2048>
```
正式部署单机版
```bash
docker stop devstar-studio && docker rm devstar-studio
docker run \
--restart=always \
--name devstar-studio \
-d \
-p 3000:3000 \
-p 2222:2222 \
-v 本地数据库文件路径:容器内数据库文件路径 \
-v 本地仓库根路径:容器内仓库根路径 \
-v 本地LFS根目录:容器内LFS路径 \
-v 本地日志路径:容器内日志路径 \
devstar-studio:latest
```
### 1.2 Kubernetes 集群部署
DevStar Studio 在 Kubernetes集群中部署需要使用 Helm Charts可参考 [官方示例](https://gitea.com/gitea/helm-chart) 。
推荐将 DevStar Studio 与 Dev Container 进行基于 namespace 的资源 **隔离**:
*由于 k8s RBAC 限制,建议将 DevStar Studio 的主应用程序,数据库和缓存 与 Dev Container 部署在同一个 namespace 下*
- `devstar-studio-ns`:
- **指定方式**:部署 Helm Charts 时候执行
```bash
helm install devstar-studio . --namespace devstar-studio-ns --create-namespace
```
- **引用方式**`{{ .Release.Namespace }}`,例如:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: devstar-studio-gitea-repository-app-ini-configmap
namespace: {{ .Release.Namespace }}
data:
repository: |
MAX_CREATION_LIMIT = 0
```
#### 1.2.1 client-go 版本适配 Kubernetes 集群
**注意**:部署在 k8s 之上要根据 Kubernetes 版本调整 `k8s.io/client-go` 版本。例如部署在 **Kubernetes 1.23.10** 之上,需要执行下列指令调整 go packages:
```bash
# 移除旧版本 client-go 的信息
go get k8s.io/client-go@none
# 安装适配于 Kubernetes 1.23.10 版本的 client-go
go get k8s.io/client-go@kubernetes-1.23.10
```
#### 1.2.2 应用配置 `app.ini` 信息挂载
在 Helm Charts 目录下创建文件夹 `templates/devstar-studio-app.ini/`,用于存储 Gitea 配置信息,请参考 Docker 版 `ini` 配置文件字段,使用 `ConfigMaps` 或者 `Secrets` 类型资源描述。
对于 `ConfigMaps` 类型,参考:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: devstar-studio-gitea-app-ini-configmap
namespace: {{ .Release.Namespace }}
data:
database: |
CHARSET_COLLATION = utf8mb4_bin
wechat: |
WECHAT_OFFICIAL_ACCOUNT_TEMP_QR_EXPIRE_SECONDS=60
WECHAT_OFFICIAL_ACCOUNT_APP_ID=<微信公众号APPID>
WECHAT_OFFICIAL_ACCOUNT_APP_SECRET=<微信公众号SECRET>
WECHAT_OFFICIAL_ACCOUNT_MESSAGE_TOKEN = <微信公众号自定义Token>
WECHAT_OFFICIAL_ACCOUNT_MESSAGE_AES_KEY = <微信公众号AES加密密钥>
cors: |
CONTENT_SECURITY_POLICY = default-src 'self' data: 'unsafe-inline' https://mp.weixin.qq.com; img-src * data:
ui.admin: |
DEV_CONTAINERS_PAGING_NUM = 50
devstar.devcontainer: |
ENABLED = true
AGENT = k8s
TIMEOUT_SECONDS = 120
HOST = <k8s 暴露访问域名或IP比如 devcontainer.devstar.cn >
NAMESPACE = <k8s DevStar Studio 部署 namespace比如 devstar-studio-ns >
devstar.ssh_key_pair: |
KEY_SIZE = <写入希望生成的SSH密钥长度比如 4096 ,默认值 2048>
devstar.cloud: |
ENABLED = true
PROVIDER = tencent
```
对于 `Secrets` 类型,参考:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: devstar-studio-gitea-app-ini-secrets
namespace: {{ .Release.Namespace }}
type: Opaque
stringData:
wechat: |
WECHAT_OFFICIAL_ACCOUNT_TEMP_QR_EXPIRE_SECONDS=60
WECHAT_OFFICIAL_ACCOUNT_APP_ID=<微信公众号APPID>
WECHAT_OFFICIAL_ACCOUNT_APP_SECRET=<微信公众号SECRET>
WECHAT_OFFICIAL_ACCOUNT_MESSAGE_TOKEN = <微信公众号自定义Token>
WECHAT_OFFICIAL_ACCOUNT_MESSAGE_AES_KEY = <微信公众号AES加密密钥>
devstar.cloud.tencent: |
ENDPOINT = <API访问端点名称例如 vpc.tencentcloudapi.com>
REGION = <区域代码,例如 ap-shanghai>
NAT_GATEWAY_ID = <腾讯云控制台使用的 NAT网关 ID>
PUBLIC_IP_ADDRESS = <公网IP>
PRIVATE_IP_ADDRESS = <内网IP>
IP_PROTOCOL = TCP
SECRET_ID = <腾讯云密钥ID>
SECRET_KEY = <腾讯云密钥内容>
```
为了使 Gitea启动时能将配置信息同步到 `app.ini` 文件中,需要在 Helm Charts `/values.yaml` 中的 `additionalConfigSources` 中挂载创建的 `ConfigMaps` 与 `Secrets` 资源,示例格式:
```yaml
## @param gitea.additionalConfigSources Additional configuration from secret or configmap
additionalConfigSources:
- secret:
secretName: devstar-studio-gitea-app-ini-secrets
- configMap:
name: devstar-studio-gitea-app-ini-configmap
```
#### 1.2.3 Kubernetes RBAC 配置
为了能够在运行时创建 Dev Container需要配置**基于角色的访问控制**(Role-Based Access Control, RBAC)。
首先需要再 DevStar Studio 的 Helm Chart 中指定名称为 `devstar-studio-gitea-serviceaccount` 的 ServiceAccount
修改 `values.yaml` 文件内容如下:
```bash
## @section ServiceAccount
## @param serviceAccount.create Enable the creation of a ServiceAccount
## @param serviceAccount.name Name of the created ServiceAccount, defaults to release name. Can also link to an externally provided ServiceAccount that should be used.
## @param serviceAccount.automountServiceAccountToken Enable/disable auto mounting of the service account token
## @param serviceAccount.imagePullSecrets Image pull secrets, available to the ServiceAccount
## @param serviceAccount.annotations Custom annotations for the ServiceAccount
## @param serviceAccount.labels Custom labels for the ServiceAccount
serviceAccount:
create: true
name: "devstar-studio-gitea-serviceaccount"
automountServiceAccountToken: true
imagePullSecrets: []
# - name: private-registry-access
annotations: {}
labels: {}
```
当 Helm Chart 部署成功后,可通过下列命令查看 `devstar-studio-gitea-serviceaccount` 的实际内容:
```bash
kubectl get serviceaccount -n devstar-studio-ns devstar-studio-gitea-serviceaccount -o yaml
```
```yaml
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
annotations:
meta.helm.sh/release-name: devstar-studio
meta.helm.sh/release-namespace: devstar-studio-ns
creationTimestamp: "2024-10-01T06:49:56Z"
labels:
app: gitea
app.kubernetes.io/instance: devstar-studio
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: gitea
app.kubernetes.io/version: rootless-dev-1fa57bca2dc6922b093157e17f16d5652de1420d
helm.sh/chart: gitea-0.0.0
version: rootless-dev-1fa57bca2dc6922b093157e17f16d5652de1420d
name: devstar-studio-gitea-serviceaccount
namespace: devstar-studio-ns
resourceVersion: "92197844"
uid: 71960972-c76e-4b6a-98b5-9f66f90aefca
secrets:
- name: devstar-studio-gitea-serviceaccount-token-d499q
```
下一步,需要创建关联该 ServiceAccount 的 RoleBinding
1. ClusterRole
通过运行命令查看编辑 DevcontainerApp 的 ClusterRole
```bash
kubectl get clusterrole devcontainer-operator-devcontainerapp-editor-role -o yaml
```
显示结果如下
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: devcontainer-operator
name: devcontainer-operator-devcontainerapp-editor-role
rules:
- apiGroups:
- devcontainer.devstar.cn
resources:
- devcontainerapps
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- devcontainer.devstar.cn
resources:
- devcontainerapps/status
verbs:
- get
```
上述结果表明ClusterRole `devcontainer-operator-devcontainerapp-editor-role` 具有如下权限:
- 对于 k8s CRD 资源 `DevcontainerApp`:创建、删除、获取、列举、部分更新、全量更新、监听
- 对于 k8s CRD 资源 `DevcontainerApp` 的 status 域: 获取
2. 创建 ClusterRoleBinding
在 Helm Charts 目录下 创建文件夹 `templates/devstar-devcontainer-rbac/`,创建下列 ClusterRoleBinding
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/name: devcontainer-operator
app.kubernetes.io/managed-by: kustomize
name: devstar-devcontainerapps-editor-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: devcontainer-operator-devcontainerapp-editor-role
subjects:
- kind: ServiceAccount
name: {{ include "gitea.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
```
**注意** RBAC 应当对 Gitea 透明,即不得将 RBAC 信息挂载到 `/values.yaml` 中如 1.2.2 小节所示的 `additionalConfigSources` 字段
至此DevStar Studio 已被赋予 k8s CRD 资源 `DevcontainerApp` 的操作权限,即可操作集群,创建或修改 DevContainer
> **补充** DevStar Studio 获取集群的控制权限
>
> ```go
> // GetKubernetesClient
> func GetKubernetesClient(ctx *context.Context) (dynamicclient.Interface, error) {
>
> // 1. 尝试从集群外获取 kubectl 配置信息
> config, err := clientcmd.BuildConfigFromFlags("", clientgocmdtools.RecommendedHomeFile)
> if err != nil {
> // 1.1 集群外尝试失败,改从集群内获取 kubectl 配置信息
> log.Warn("Failed to obtain Kubernetes config outside of cluster: " + clientgocmdtools.RecommendedHomeFile)
> config, err = clientgorest.InClusterConfig()
> if err != nil {
> log.Error("Failed to obtain Kubernetes config both inside/outside of cluster, the DevContainer is Disabled")
> setting.Devstar.Devcontainer.Enabled = false
> return nil, err
> }
> }
>
> // 2. 根据 k8s 配置信息构建 ClientSet
> dynamicClient, err := dynamicclient.NewForConfig(config)
> if err != nil {
> return nil, err
> }
> return dynamicClient, err
> }
>
> ```
>
> 上述代码考虑了集群内、外两种情况配置 k8s 连接信息:
> - 集群之外/Pod 之外:通过 `~/.kube/config` 获取 Token 与 CA 证书文件
> - 集群 Pod 之内:通过 Pod 内部密钥挂载目录 `/var/run/secrets/kubernetes.io/serviceaccount/` 获取 Token 与 CA 证书文件
>
--------------------
## Gitea
[![](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml/badge.svg?branch=main)](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly")
[![](https://img.shields.io/discord/322538954119184384.svg?logo=discord&logoColor=white&label=Discord&color=5865F2)](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea")
[![](https://goreportcard.com/badge/code.gitea.io/gitea)](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card")
[![](https://pkg.go.dev/badge/code.gitea.io/gitea?status.svg)](https://pkg.go.dev/code.gitea.io/gitea "GoDoc")
[![](https://img.shields.io/github/release/go-gitea/gitea.svg)](https://github.com/go-gitea/gitea/releases/latest "GitHub release")
[![](https://www.codetriage.com/go-gitea/gitea/badges/users.svg)](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
[![](https://opencollective.com/gitea/tiers/backers/badge.svg?label=backers&color=brightgreen)](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
[![](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT "License: MIT")
[![Contribute with Gitpod](https://img.shields.io/badge/Contribute%20with-Gitpod-908a85?logo=gitpod&color=green)](https://gitpod.io/#https://github.com/go-gitea/gitea)
[![](https://badges.crowdin.net/gitea/localized.svg)](https://crowdin.com/project/gitea "Crowdin")
[View this document in English](./README.md)
## 目标
Gitea 的首要目标是创建一个极易安装,运行非常快速,安装和使用体验良好的自建 Git 服务。我们采用 Go 作为后端语言,这使我们只要生成一个可执行程序即可。并且他还支持跨平台,支持 Linux, macOS 和 Windows 以及各种架构,除了 x86amd64还包括 ARM 和 PowerPC。
如果你想试用在线演示和报告问题,请访问 [demo.gitea.com](https://demo.gitea.com/)。
如果你想使用免费的 Gitea 服务(有仓库数量限制),请访问 [gitea.com](https://gitea.com/user/login)。
如果你想在 Gitea Cloud 上快速部署你自己独享的 Gitea 实例,请访问 [cloud.gitea.com](https://cloud.gitea.com) 开始免费试用。
## 提示
1. **开始贡献代码之前请确保你已经看过了 [贡献者向导(英文)](CONTRIBUTING.md)**.
2. 所有的安全问题,请私下发送邮件给 **security@gitea.io**。谢谢!
3. 如果你要使用API请参见 [API 文档](https://godoc.org/code.gitea.io/sdk/gitea).
## 文档
关于如何安装请访问我们的 [文档站](https://docs.gitea.com/zh-cn/category/installation),如果没有找到对应的文档,你也可以通过 [Discord - 英文](https://discord.gg/gitea) 和 QQ群 328432459 来和我们交流。
## 贡献流程
Fork -> Patch -> Push -> Pull Request
## 翻译
多语言翻译是基于Crowdin进行的.
[![Crowdin](https://badges.crowdin.net/gitea/localized.svg)](https://crowdin.com/project/gitea)
## 作者
* [Maintainers](https://github.com/orgs/go-gitea/people)
* [Contributors](https://github.com/go-gitea/gitea/graphs/contributors)
* [Translators](options/locale/TRANSLATORS)
## 授权许可
本项目采用 MIT 开源授权许可证,完整的授权说明已放置在 [LICENSE](https://github.com/go-gitea/gitea/blob/main/LICENSE) 文件中。
## 截图
|![Dashboard](https://dl.gitea.com/screenshots/home_timeline.png)|![User Profile](https://dl.gitea.com/screenshots/user_profile.png)|![Global Issues](https://dl.gitea.com/screenshots/global_issues.png)|
|:---:|:---:|:---:|
|![Branches](https://dl.gitea.com/screenshots/branches.png)|![Web Editor](https://dl.gitea.com/screenshots/web_editor.png)|![Activity](https://dl.gitea.com/screenshots/activity.png)|
|![New Migration](https://dl.gitea.com/screenshots/migration.png)|![Migrating](https://dl.gitea.com/screenshots/migration.gif)|![Pull Request View](https://image.ibb.co/e02dSb/6.png)|
|![Pull Request Dark](https://dl.gitea.com/screenshots/pull_requests_dark.png)|![Diff Review Dark](https://dl.gitea.com/screenshots/review_dark.png)|![Diff Dark](https://dl.gitea.com/screenshots/diff_dark.png)|

repo.diff.view_file

@@ -10,7 +10,7 @@ fi
echo "check uid ..."
# the uid of gitea defined in "https://gitea.com/gitea/test-env" is 1000
# the uid of gitea defined in "https://gitea.cn/gitea/test-env" is 1000
gitea_uid=$(id -u gitea)
if [ "$gitea_uid" != "1000" ]; then
echo "The uid of linux user 'gitea' is expected to be 1000, but it is $gitea_uid"

repo.diff.view_file

@@ -108,7 +108,7 @@ func runDumpRepository(ctx *cli.Context) error {
serviceStr = "github"
} else if strings.HasPrefix(strings.ToLower(cloneAddr), "https://gitlab.com/") {
serviceStr = "gitlab"
} else if strings.HasPrefix(strings.ToLower(cloneAddr), "https://gitea.com/") {
} else if strings.HasPrefix(strings.ToLower(cloneAddr), "https://devstar.cn/") {
serviceStr = "gitea"
}
if serviceStr == "" {

repo.diff.view_file

@@ -7,7 +7,7 @@
dashboardTimezone: 'default',
dashboardRefresh: '1m',
// please see https://docs.gitea.com/administration/config-cheat-sheet#metrics-metrics
// please see https://docs.gitea.cn/administration/config-cheat-sheet#metrics-metrics
// Show issue by repository metrics with format gitea_issues_by_repository{repository="org/repo"} 5.
// Requires Gitea 1.16.0 with ENABLED_ISSUE_BY_REPOSITORY set to true.
showIssuesByRepository: true,

repo.diff.view_file

@@ -37,7 +37,7 @@
<h3>With your Consent</h3>
<p>We share your User Personal Information, if you consent, after letting you know what information will be shared, with whom, and why. For example, if you allow third party applications to access your Account using <a href="https://docs.gitea.com/development/oauth2-provider">OAuth2 providers</a>, we share all information associated with your Account, including private repos and organizations. You may also direct us through your action on Your Gitea Instance to share your User Personal Information, such as when joining an Organization.</p>
<p>We share your User Personal Information, if you consent, after letting you know what information will be shared, with whom, and why. For example, if you allow third party applications to access your Account using <a href="https://docs.gitea.cn/development/oauth2-provider">OAuth2 providers</a>, we share all information associated with your Account, including private repos and organizations. You may also direct us through your action on Your Gitea Instance to share your User Personal Information, such as when joining an Organization.</p>
<h3>With Service Providers</h3>
@@ -144,7 +144,7 @@
<h3>Data Portability</h3>
<p>As a Your Gitea Instance User, you can always take your data with you. You can clone your repositories to your computer, or you can <a href="https://docs.gitea.com/development/migrations-interfaces">perform migrations using the provided interfaces</a>, for example.</p>
<p>As a Your Gitea Instance User, you can always take your data with you. You can clone your repositories to your computer, or you can <a href="https://docs.gitea.cn/development/migrations-interfaces">perform migrations using the provided interfaces</a>, for example.</p>
<h3>Data Retention and Deletion of Data</h3>

repo.diff.view_file

@@ -0,0 +1 @@
ls

74
devcontainer_init.sh Normal file
repo.diff.view_file

@@ -0,0 +1,74 @@
#!/bin/bash
# Copyright 2025 Mengning Software All rights reserved.
# Exit immediately if a command exits with a non-zero status
set -e
# Colors for output
GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m' # No Color
# Function to display success message
function success {
echo -e "${GREEN}$1${NC}"
}
# Function to display failure message
function failure {
echo -e "${RED}$1${NC}"
}
# Detect the OS type and install dependencies
function install_dependencies {
# Install dependencies based on the OS type
success "dependencies install begin: "
OS_ID=$(grep '^ID=' /etc/os-release | cut -d= -f2 | tr -d '"')
case $OS_ID in
ubuntu|debian)
sudo apt-get update -y
sudo apt-get install ssh -y
;;
centos)
# sudo yum update -y
# sudo yum install -y epel-release
# sudo yum groupinstall -y "Development Tools"
# sudo yum install -y yaml-cpp yaml-cpp-devel
;;
fedora)
# sudo dnf update -y
# sudo dnf group install -y "Development Tools"
# sudo dnf install -y yaml-cpp yaml-cpp-devel
;;
*)
failure "Unsupported OS: $OS_ID"
exit 1
;;
esac
}
install_dependencies
echo -e "PubkeyAuthentication yes\nPermitRootLogin yes\n" | tee -a /etc/ssh/sshd_config
rm -f /etc/ssh/ssh_host_*; ssh-keygen -A; service ssh restart
if [ -z "${host_docker_internal+x}" ]; then
echo "$HOST_DOCKER_INTERNAL host.docker.internal" | tee -a /etc/hosts;
fi
if [ ! -d "$WORKDIR" ]; then
git clone $REPO_URL $WORKDIR && echo "Git Repository cloned.";
else
echo "Folder already exists.";
fi
mkdir -p ~/test
mkdir -p ~/.ssh
chmod 700 ~/.ssh
echo "$AUTHORIZED_KEYS" > ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
git clone "https://devstar.cn/init/ttyd.git" "/usr/bin/ttyd"
apt-get install -y build-essential cmake git libjson-c-dev libwebsockets-dev
/usr/bin/ttyd/ttyd/ttyd -W -w $WORKDIR bash &

5
devcontainer_restart.sh Normal file
repo.diff.view_file

@@ -0,0 +1,5 @@
#!/bin/bash
# Copyright 2025 Mengning Software All rights reserved.
service ssh restart
/usr/bin/ttyd/ttyd/ttyd -W -w $WORKDIR bash &

repo.diff.view_file

@@ -4,4 +4,4 @@ Dockerfile is found in the root of the repository.
Docker image can be found on [docker hub](https://hub.docker.com/r/gitea/gitea).
Documentation on using docker image can be found on [Gitea Docs site](https://docs.gitea.com/installation/install-with-docker-rootless).
Documentation on using docker image can be found on [Gitea Docs site](https://docs.gitea.cn/installation/install-with-docker-rootless).

repo.diff.view_file

@@ -32,7 +32,7 @@ if [ ! -f ${GITEA_CUSTOM}/conf/app.ini ]; then
fi
# Substitute the environment variables in the template
APP_NAME=${APP_NAME:-"Gitea: Git with a cup of tea"} \
APP_NAME=${APP_NAME:-"DevStar Studio"} \
RUN_MODE=${RUN_MODE:-"prod"} \
DOMAIN=${DOMAIN:-"localhost"} \
SSH_DOMAIN=${SSH_DOMAIN:-"localhost"} \

repo.diff.view_file

@@ -26,7 +26,7 @@ if [ ! -f ${GITEA_APP_INI} ]; then
fi
# Substitute the environment variables in the template
APP_NAME=${APP_NAME:-"Gitea: Git with a cup of tea"} \
APP_NAME=${APP_NAME:-"DevStar Studio"} \
RUN_MODE=${RUN_MODE:-"prod"} \
RUN_USER=${USER:-"git"} \
SSH_DOMAIN=${SSH_DOMAIN:-"localhost"} \

repo.diff.view_file

@@ -1,6 +1,6 @@
# Gitea: Docs
These docs are ingested by our [docs repo](https://gitea.com/gitea/gitea-docusaurus).
These docs are ingested by our [docs repo](https://gitea.cn/gitea/gitea-docusaurus).
## Authors

repo.diff.view_file

@@ -1,6 +1,6 @@
# Gitea: 文档
https://gitea.com/gitea/gitea-docusaurus
https://gitea.cn/gitea/gitea-docusaurus
## 关于我们

repo.diff.view_file

@@ -66,7 +66,7 @@ In addition, there is _`StaticRootPath`_ which can be set as a built-in at build
## Overall (`DEFAULT`)
- `APP_NAME`: **Gitea: Git with a cup of tea**: Application name, used in the page title.
- `APP_NAME`: **DevStar Studio**: Application name, used in the page title.
- `RUN_USER`: **_current OS username_/`$USER`/`$USERNAME` e.g. git**: The user Gitea will run as.
This should be a dedicated system (non-user) account. Setting this incorrectly will cause Gitea
to not start.
@@ -1457,10 +1457,10 @@ Please note that using `self` is not recommended for most cases, as it could mak
Additionally, it requires you to mirror all the actions you need to your Gitea instance, which may not be worth it.
Therefore, please use `self` only if you understand what you are doing.
In earlier versions (`<= 1.19`), `DEFAULT_ACTIONS_URL` could be set to any custom URLs like `https://gitea.com` or `http://your-git-server,https://gitea.com`, and the default value was `https://gitea.com`.
In earlier versions (`<= 1.19`), `DEFAULT_ACTIONS_URL` could be set to any custom URLs like `https://devstar.cn` or `http://your-git-server,https://gitea.cn`, and the default value was `https://devstar.cn`.
However, later updates removed those options, and now the only options are `github` and `self`, with the default value being `github`.
However, if you want to use actions from other git server, you can use a complete URL in `uses` field, it's supported by Gitea (but not GitHub).
Like `uses: https://gitea.com/actions/checkout@v4` or `uses: http://your-git-server/actions/checkout@v4`.
Like `uses: https://gitea.cn/actions/checkout@v4` or `uses: http://your-git-server/actions/checkout@v4`.
## Other (`other`)

repo.diff.view_file

@@ -66,7 +66,7 @@ menu:
## Overall (`DEFAULT`)
- `APP_NAME`: **Gitea: Git with a cup of tea** 应用名称,在网页的标题中显示。
- `APP_NAME`: **DevStar Studio** 应用名称,在网页的标题中显示。
- `RUN_USER`: **_current OS username_/`$USER`/`$USERNAME` e.g. git**: 运行Gitea的用户
应当是一个专用的系统账户(非用户使用,推荐创建一个专用的`git`用户). 如果在你自己的个人电脑使用改成你自己的用户名。
该配置如果设置不正确Gitea可能崩溃。
@@ -1347,10 +1347,10 @@ PROXY_HOSTS = *.github.com
此外,它要求您将所有所需的操作镜像到您的 Gitea 实例,这可能不值得。
因此,请仅在您了解自己在做什么的情况下使用 `self`
在早期版本(`<= 1.19`)中,`DEFAULT_ACTIONS_URL` 可以设置为任何自定义 URL例如 `https://gitea.com``http://your-git-server,https://gitea.com`,默认值为 `https://gitea.com`
在早期版本(`<= 1.19`)中,`DEFAULT_ACTIONS_URL` 可以设置为任何自定义 URL例如 `https://devstar.cn``http://your-git-server,https://gitea.cn`,默认值为 `https://gitea.cn`
然而,后来的更新删除了这些选项,现在唯一的选项是 `github``self`,默认值为 `github`
但是,如果您想要使用其他 Git 服务器中的操作,您可以在 `uses` 字段中使用完整的 URLGitea 支持此功能GitHub 不支持)。
例如 `uses: https://gitea.com/actions/checkout@v4``uses: http://your-git-server/actions/checkout@v4`
例如 `uses: https://devstar.cn/actions/checkout@v4``uses: http://your-git-server/actions/checkout@v4`
## 其他 (`other`)

repo.diff.view_file

@@ -142,7 +142,7 @@ You can add [PlantUML](https://plantuml.com/) support to Gitea's markdown by usi
The data is encoded and sent to the PlantUML server which generates the picture. There is an online
demo server at http://www.plantuml.com/plantuml, but if you (or your users) have sensitive data you
can set up your own [PlantUML server](https://plantuml.com/server) instead. To set up PlantUML rendering,
copy JavaScript files from https://gitea.com/davidsvantesson/plantuml-code-highlight and put them in your
copy JavaScript files from https://gitea.cn/davidsvantesson/plantuml-code-highlight and put them in your
`$GITEA_CUSTOM/public/assets/` folder. Then add the following to `custom/footer.tmpl`:
```html
@@ -366,7 +366,7 @@ To change reaction emoji's you can set allowed reactions at app.ini
REACTIONS = +1, -1, laugh, confused, heart, hooray, eyes
```
A full list of supported emoji's is at [emoji list](https://gitea.com/gitea/gitea.com/issues/8)
A full list of supported emoji's is at [emoji list](https://gitea.cn/gitea/gitea.com/issues/8)
## Customizing the look of Gitea
@@ -383,7 +383,7 @@ To make a custom theme available to all users:
The value of `$GITEA_CUSTOM` of your instance can be queried by calling `gitea help` and looking up the value of "CustomPath".
2. Add `<theme-name>` to the comma-separated list of setting `THEMES` in `app.ini`, or leave `THEMES` empty to allow all themes.
Community themes are listed in [gitea/awesome-gitea#themes](https://gitea.com/gitea/awesome-gitea#themes).
Community themes are listed in [gitea/awesome-gitea#themes](https://gitea.cn/gitea/awesome-gitea#themes).
The default theme sources can be found [here](https://github.com/go-gitea/gitea/blob/main/web_src/css/themes).

repo.diff.view_file

@@ -117,7 +117,7 @@ curl -v "http://localhost/api/v1/repos/search?limit=1"
API Reference guide is auto-generated by swagger and available on:
`https://gitea.your.host/api/swagger`
or on the
[Gitea instance](https://gitea.com/api/swagger)
[Gitea instance](https://devstar.cn/api/swagger)
The OpenAPI document is at:
`https://gitea.your.host/swagger.v1.json`
@@ -128,5 +128,5 @@ The API allows admin users to sudo API requests as another user. Simply add eith
## SDKs
- [Official go-sdk](https://gitea.com/gitea/go-sdk)
- [more](https://gitea.com/gitea/awesome-gitea#user-content-sdk)
- [Official go-sdk](https://gitea.cn/gitea/go-sdk)
- [more](https://gitea.cn/gitea/awesome-gitea#user-content-sdk)

repo.diff.view_file

@@ -20,12 +20,12 @@ menu:
Gitea has a wonderful community of third-party integrations, as well as first-class support in various other
projects.
We are curating a list over at [awesome-gitea](https://gitea.com/gitea/awesome-gitea) to track these!
We are curating a list over at [awesome-gitea](https://gitea.cn/gitea/awesome-gitea) to track these!
If you are looking for [CI/CD](https://gitea.com/gitea/awesome-gitea#user-content-devops),
an [SDK](https://gitea.com/gitea/awesome-gitea#user-content-sdk),
or even some extra [themes](https://gitea.com/gitea/awesome-gitea#user-content-themes),
you can find them listed in the [awesome-gitea](https://gitea.com/gitea/awesome-gitea) repository!
If you are looking for [CI/CD](https://gitea.cn/gitea/awesome-gitea#user-content-devops),
an [SDK](https://gitea.cn/gitea/awesome-gitea#user-content-sdk),
or even some extra [themes](https://gitea.cn/gitea/awesome-gitea#user-content-themes),
you can find them listed in the [awesome-gitea](https://gitea.cn/gitea/awesome-gitea) repository!
## Pre-Fill New File name and contents

repo.diff.view_file

@@ -19,12 +19,12 @@ menu:
Gitea拥有一个出色的第三方集成社区以及在其他各种项目中的一流支持。
我们正在[awesome-gitea](https://gitea.com/gitea/awesome-gitea)上整理一个列表来跟踪这些集成!
我们正在[awesome-gitea](https://gitea.cn/gitea/awesome-gitea)上整理一个列表来跟踪这些集成!
如果你正在寻找[CI/CD](https://gitea.com/gitea/awesome-gitea#user-content-devops)
一个[SDK](https://gitea.com/gitea/awesome-gitea#user-content-sdk)
甚至一些额外的[主题](https://gitea.com/gitea/awesome-gitea#user-content-themes)
你可以在[awesome-gitea](https://gitea.com/gitea/awesome-gitea)中找到它们的列表!
如果你正在寻找[CI/CD](https://gitea.cn/gitea/awesome-gitea#user-content-devops)
一个[SDK](https://gitea.cn/gitea/awesome-gitea#user-content-sdk)
甚至一些额外的[主题](https://gitea.cn/gitea/awesome-gitea#user-content-themes)
你可以在[awesome-gitea](https://gitea.cn/gitea/awesome-gitea)中找到它们的列表!
## 预填新文件名和内容

repo.diff.view_file

@@ -86,7 +86,7 @@ Gitea creates OAuth applications for the following services by default on startu
|-----------|-----------|---------|
|[git-credential-oauth](https://github.com/hickford/git-credential-oauth)|Git credential helper|`a4792ccc-144e-407e-86c9-5e7d8d9c3269`|
|[Git Credential Manager](https://github.com/git-ecosystem/git-credential-manager)|Git credential helper|`e90ee53c-94e2-48ac-9358-a874fb9e0662`|
|[tea](https://gitea.com/gitea/tea)|tea|`d57cb8c4-630c-4168-8324-ec79935e18d4`|
|[tea](https://gitea.cn/gitea/tea)|tea|`d57cb8c4-630c-4168-8324-ec79935e18d4`|
To prevent unexpected behavior, they are being displayed as locked in the UI and their creation can instead be controlled by the `DEFAULT_APPLICATIONS` parameter in `app.ini`.

repo.diff.view_file

@@ -0,0 +1,117 @@
---
date: "2024-12-22:44:00+01:00"
title: "微信二维码登录"
slug: "wechat-qr-login"
sidebar_position: 42
toc: false
draft: false
aliases:
- /zh-cn/wechat-qr-login
menu:
sidebar:
parent: "development"
name: "微信二维码登录"
sidebar_position: 42
identifier: "/zh-cn/wechat-qr-login"
---
# 微信二维码登录
Gitea 支持微信二维码登录允许本地部署间接使用devstar.cn完成微信二维码登录也可以本地部署配置自己的微信公众号实现微信二维码登录。
## 微信二维码服务相关端点和API
| Web API | URL |
| ------------------------ | ------------------------------------- |
| Show WeChat QR | `/user/login/wechat` |
| WeChat QR Login | `/user/login/wechat/success` |
| 带参数临时二维码登录 | `/api/wechat/login/qr/check-status` |
routers/web/auth/auth.go
```
// for `/user/login/wechat` 用于获取临时二维码
func SignInWechatQr(ctx *context.Context) // Show QR Code in WeChat SignIn Page
...
wechatQrTicket, wechatQrCodeUrl, err := auth_service.GetWechatQRTicket(ctx) // Call WeChat API for Ticket and QR Code URL
...
```
routers/web/auth/wechat_qr_auth.go
```
func WechatQrSignInSuccess(ctx *context.Context) // 扫码事件后,完成用户验证和登录
...
qrStatusVO, err := wechat_service.GetWechatQrStatusByTicket(wechatQrTicket) // 获取扫码状态
// 查询数据库扫码人信息
user, err := wechat_model.QueryUserByOpenid(ctx, qrStatusVO.OpenId)
```
routers/web/user/setting/wechat.go
```
func BindWechatQR(ctx *context.Context) {
qrStatusVO, err := wechat_service.GetWechatQrStatusByTicket(wechatQrTicket)
_ = wechat_service.DeleteWechatQrByTicket(wechatQrTicket)
err = wechat_model.UpdateOrCreateWechatUser(ctx, user, qrStatusVO.OpenId)
...
func UnbindWechatQR(ctx *context.Context) {
_ = wechat_model.DeleteWechatUser(ctx, ctx.Doer)
...
```
services/auth/wechat_qr.go // auth_service
```
// Call WeChat API for Ticket and QR Code URL
func GetWechatQRTicket(ctx *context.Context) (wechatQrTicket string, QRImageURL string, errorGenerateQr error)
// Call WeChat API for QR Code Scan Status并保存扫码状态
func checkWechatQrTicketStatus(ctx *context.Context, qrTicket string, quit chan bool)
```
## wechat_service API
| API | URL |
| ------------------------ | ----------------------------------------------- |
| 微信服务器回调接口API | Get/Post `/api/wechat/callback/message` |
| 带参数临时二维码生成 | Get `/api/wechat/login/qr/generate` |
| 带参数临时二维码登录 | Get `/api/wechat/login/qr/check-status` |
routers/api/wechat/init-wechat-routes.go
```
// 微信服务器回调接口
wechatWebRouter.Group("/callback", func() {
wechatWebRouter.Get("/message", wechat_service.CallbackVerifyMessage)
wechatWebRouter.Post("/message", wechat_service.CallbackNotifyEvents)
})
// 微信公众号带参数临时二维码登录
wechatWebRouter.Group("/login/qr", func() {
wechatWebRouter.Get("/generate", wechat_service.GenerateWechatQrCode)
wechatWebRouter.Get("/check-status", wechat_service.QrCheckCodeStatus)
})
```
services/wechat/*.go
services/auth/wechat_qr.go
models/wechat/wechat.go
## 微信二维码登录开发环境配置方法
app.ini配置文件中的相关配置项
申请测试号https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index
appID和appsecret填入app.ini配置文件的对应项中。
```
[wechat]
ENABLED_WECHAT_QR_SIGNIN = true
WECHAT_QR_SERVICE_DOMAIN_NAME = de694c2.r25.cpolar.top
WECHAT_OFFICIAL_ACCOUNT_TEMP_QR_EXPIRE_SECONDS = 60
WECHAT_OFFICIAL_ACCOUNT_REGISTERATION_EXPIRE_SECONDS = 86400
WECHAT_OFFICIAL_ACCOUNT_APP_ID = wx659ca7ccef87005c
WECHAT_OFFICIAL_ACCOUNT_APP_SECRET = f231dcff9992de1bfb62fdf142cb3832
WECHAT_OFFICIAL_ACCOUNT_REDIS_ADDR =
WECHAT_OFFICIAL_ACCOUNT_MESSAGE_TOKEN = your-token
WECHAT_OFFICIAL_ACCOUNT_MESSAGE_AES_KEY =
```
配置内网穿透https://dashboard.cpolar.com/get-started 可以得到类似de694c2.r25.cpolar.top 这样的域名访问内网服务
https://24a099f.r25.cpolar.top/api/wechat/callback/message 回调URL + your-token Token 就可以作为接口信息配置到微信测试号管理界面上。

repo.diff.view_file

@@ -137,9 +137,9 @@ All Gitea instances have the built-in API and there is no way to disable it comp
You can, however, disable showing its documentation by setting `ENABLE_SWAGGER` to `false` in the `api` section of your `app.ini`.
For more information, refer to Gitea's [API docs](development/api-usage.md).
You can see the latest API (for example) on https://gitea.com/api/swagger
You can see the latest API (for example) on https://devstar.cn/api/swagger
You can also see an example of the `swagger.json` file at https://gitea.com/swagger.v1.json
You can also see an example of the `swagger.json` file at https://devstar.cn/swagger.v1.json
## Adjusting your server for public/private use

repo.diff.view_file

@@ -141,9 +141,9 @@ Gitea不提供内置的Pages服务器。您需要一个专用的域名来提供
但是您可以在app.ini的api部分将ENABLE_SWAGGER设置为false以禁用其文档显示。
有关更多信息请参阅Gitea的[API文档](development/api-usage.md)。
您可以在上查看最新的API例如https://gitea.com/api/swagger
您可以在上查看最新的API例如https://devstar.cn/api/swagger
您还可以在上查看`swagger.json`文件的示例 https://gitea.com/swagger.v1.json
您还可以在上查看`swagger.json`文件的示例 https://devstar.cn/swagger.v1.json
## 调整服务器用于公共/私有使用

repo.diff.view_file

@@ -45,7 +45,7 @@ You can try it out using [the online demo](https://demo.gitea.com).
- Multilingual Support: Gitea provides interfaces in multiple languages, catering to users globally and promoting internationalization and localization.
Additional Features: For more detailed information, please refer to: https://docs.gitea.com/installation/comparison#general-features
Additional Features: For more detailed information, please refer to: https://docs.gitea.cn/installation/comparison#general-features
## System Requirements
@@ -83,4 +83,4 @@ Additional Features: For more detailed information, please refer to: https://doc
## Integrated support
Please visit [Awesome Gitea](https://gitea.com/gitea/awesome-gitea/) to get more third-party integrated support
Please visit [Awesome Gitea](https://gitea.cn/gitea/awesome-gitea/) to get more third-party integrated support

repo.diff.view_file

@@ -36,7 +36,7 @@ Gitea的首要目标是创建一个极易安装运行非常快速安装和
- 开源社区支持: Gitea 是一个基于 MIT 许可证的开源项目,Gitea 拥有一个活跃的开源社区,能够持续地进行开发和改进,同时也积极接受社区贡献,保持了平台的更新和创新。
- 多语言支持: Gitea 提供多种语言界面,适应全球范围内的用户,促进了国际化和本地化。
更多功能特性详见https://docs.gitea.com/installation/comparison#general-features
更多功能特性详见https://docs.gitea.cn/installation/comparison#general-features
## 系统要求
@@ -74,4 +74,4 @@ Gitea的首要目标是创建一个极易安装运行非常快速安装和
## 集成支持
请访问 [Awesome Gitea](https://gitea.com/gitea/awesome-gitea/) 获得更多的第三方集成支持
请访问 [Awesome Gitea](https://gitea.cn/gitea/awesome-gitea/) 获得更多的第三方集成支持

repo.diff.view_file

@@ -209,6 +209,6 @@ remote: ./hooks/pre-receive.d/gitea: line 2: [...]: No such file or directory
如果您没有使用 Gitea 内置的 SSH 服务器,您还需要通过在管理选项中运行任务 `Update the '.ssh/authorized_keys' file with Gitea SSH keys.` 来重新编写授权密钥文件。
> 更多经验总结,请参考英文版 [Troubleshooting](https://docs.gitea.com/installation/install-from-binary#troubleshooting)
> 更多经验总结,请参考英文版 [Troubleshooting](https://docs.gitea.cn/installation/install-from-binary#troubleshooting)
如果从本页中没有找到你需要的内容,请访问 [帮助页面](help/support.md)

repo.diff.view_file

@@ -113,6 +113,6 @@ To enable Gitea to run as a service, run `sysrc gitea_enable=YES` and start it w
### Others
Various other third-party packages of Gitea exist.
To see a curated list, head over to [awesome-gitea](https://gitea.com/gitea/awesome-gitea/src/branch/master/README.md#user-content-packages).
To see a curated list, head over to [awesome-gitea](https://gitea.cn/gitea/awesome-gitea/src/branch/master/README.md#user-content-packages).
Do you know of an existing package that isn't on the list? Send in a PR to get it added!

repo.diff.view_file

@@ -106,6 +106,6 @@ make install clean
## 第三方
如果这里没有找到你喜欢的包管理器,可以使用 Gitea 第三方软件包。这里有一个完整的列表: [awesome-gitea](https://gitea.com/gitea/awesome-gitea/src/branch/master/README.md#user-content-packages)。
如果这里没有找到你喜欢的包管理器,可以使用 Gitea 第三方软件包。这里有一个完整的列表: [awesome-gitea](https://gitea.cn/gitea/awesome-gitea/src/branch/master/README.md#user-content-packages)。
如果你知道其他 Gitea 第三方软件包,请发送 PR 来添加它。

repo.diff.view_file

@@ -26,7 +26,7 @@ helm repo add gitea-charts https://dl.gitea.com/charts/
helm install gitea gitea-charts/gitea
```
If you would like to customize your install, which includes kubernetes ingress, please refer to the complete [Gitea helm chart configuration details](https://gitea.com/gitea/helm-chart/)
If you would like to customize your install, which includes kubernetes ingress, please refer to the complete [Gitea helm chart configuration details](https://gitea.cn/gitea/helm-chart/)
## Health check endpoint
@@ -51,7 +51,7 @@ HTTP/1.1 200 OK
{
"status": "pass",
"description": "Gitea: Git with a cup of tea",
"description": "DevStar Studio",
"checks": {
"cache:ping": [
{

repo.diff.view_file

@@ -1,3 +1,283 @@
### Kubernetes 集群部署
DevStar Studio 在 Kubernetes集群中部署需要使用 Helm Charts可参考 [官方示例](https://gitea.cn/gitea/helm-chart) 。
推荐将 DevStar Studio 与 Dev Container 进行基于 namespace 的资源 **隔离**:
*由于 k8s RBAC 限制,建议将 DevStar Studio 的主应用程序,数据库和缓存 与 Dev Container 部署在同一个 namespace 下*
- `devstar-studio-ns`:
- **指定方式**:部署 Helm Charts 时候执行
```bash
helm install devstar-studio . --namespace devstar-studio-ns --create-namespace
```
- **引用方式**`{{ .Release.Namespace }}`,例如:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: devstar-studio-gitea-repository-app-ini-configmap
namespace: {{ .Release.Namespace }}
data:
repository: |
MAX_CREATION_LIMIT = 0
```
#### 1.2.1 client-go 版本适配 Kubernetes 集群
**注意**:部署在 k8s 之上要根据 Kubernetes 版本调整 `k8s.io/client-go` 版本。例如部署在 **Kubernetes 1.23.10** 之上,需要执行下列指令调整 go packages:
```bash
# 移除旧版本 client-go 的信息
go get k8s.io/client-go@none
# 安装适配于 Kubernetes 1.23.10 版本的 client-go
go get k8s.io/client-go@kubernetes-1.23.10
```
#### 1.2.2 应用配置 `app.ini` 信息挂载
在 Helm Charts 目录下创建文件夹 `templates/devstar-studio-app.ini/`,用于存储 Gitea 配置信息,请参考 Docker 版 `ini` 配置文件字段,使用 `ConfigMaps` 或者 `Secrets` 类型资源描述。
对于 `ConfigMaps` 类型,参考:
```yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: devstar-studio-gitea-app-ini-configmap
namespace: {{ .Release.Namespace }}
data:
database: |
CHARSET_COLLATION = utf8mb4_bin
cors: |
CONTENT_SECURITY_POLICY = default-src 'self' data: 'unsafe-inline' https://mp.weixin.qq.com; img-src * data:
ui.admin: |
DEV_CONTAINERS_PAGING_NUM = 50
devcontainer: |
ENABLED = true
AGENT = k8s
TIMEOUT_SECONDS = 120
HOST = <k8s 暴露访问域名或IP比如 devcontainer.devstar.cn >
NAMESPACE = <k8s DevStar Studio 部署 namespace比如 devstar-studio-ns >
ssh_key_pair: |
KEY_SIZE = <写入希望生成的SSH密钥长度比如 4096 ,默认值 2048>
devcontainer.cloud: |
ENABLED = true
PROVIDER = tencent
```
对于 `Secrets` 类型,参考:
```yaml
apiVersion: v1
kind: Secret
metadata:
name: devstar-studio-gitea-app-ini-secrets
namespace: {{ .Release.Namespace }}
type: Opaque
stringData:
wechat: |
WECHAT_OFFICIAL_ACCOUNT_TEMP_QR_EXPIRE_SECONDS=60
WECHAT_OFFICIAL_ACCOUNT_APP_ID=<微信公众号APPID>
WECHAT_OFFICIAL_ACCOUNT_APP_SECRET=<微信公众号SECRET>
WECHAT_OFFICIAL_ACCOUNT_MESSAGE_TOKEN = <微信公众号自定义Token>
WECHAT_OFFICIAL_ACCOUNT_MESSAGE_AES_KEY = <微信公众号AES加密密钥>
devcontainer.cloud.tencent: |
ENDPOINT = <API访问端点名称例如 vpc.tencentcloudapi.com>
REGION = <区域代码,例如 ap-shanghai>
NAT_GATEWAY_ID = <腾讯云控制台使用的 NAT网关 ID>
PUBLIC_IP_ADDRESS = <公网IP>
PRIVATE_IP_ADDRESS = <内网IP>
IP_PROTOCOL = TCP
SECRET_ID = <腾讯云密钥ID>
SECRET_KEY = <腾讯云密钥内容>
```
为了使 Gitea启动时能将配置信息同步到 `app.ini` 文件中,需要在 Helm Charts `/values.yaml` 中的 `additionalConfigSources` 中挂载创建的 `ConfigMaps` 与 `Secrets` 资源,示例格式:
```yaml
## @param gitea.additionalConfigSources Additional configuration from secret or configmap
additionalConfigSources:
- secret:
secretName: devstar-studio-gitea-app-ini-secrets
- configMap:
name: devstar-studio-gitea-app-ini-configmap
```
#### 1.2.3 Kubernetes RBAC 配置
为了能够在运行时创建 Dev Container需要配置**基于角色的访问控制**(Role-Based Access Control, RBAC)。
首先需要再 DevStar Studio 的 Helm Chart 中指定名称为 `devstar-studio-gitea-serviceaccount` 的 ServiceAccount
修改 `values.yaml` 文件内容如下:
```bash
## @section ServiceAccount
## @param serviceAccount.create Enable the creation of a ServiceAccount
## @param serviceAccount.name Name of the created ServiceAccount, defaults to release name. Can also link to an externally provided ServiceAccount that should be used.
## @param serviceAccount.automountServiceAccountToken Enable/disable auto mounting of the service account token
## @param serviceAccount.imagePullSecrets Image pull secrets, available to the ServiceAccount
## @param serviceAccount.annotations Custom annotations for the ServiceAccount
## @param serviceAccount.labels Custom labels for the ServiceAccount
serviceAccount:
create: true
name: "devstar-studio-gitea-serviceaccount"
automountServiceAccountToken: true
imagePullSecrets: []
# - name: private-registry-access
annotations: {}
labels: {}
```
当 Helm Chart 部署成功后,可通过下列命令查看 `devstar-studio-gitea-serviceaccount` 的实际内容:
```bash
kubectl get serviceaccount -n devstar-studio-ns devstar-studio-gitea-serviceaccount -o yaml
```
```yaml
apiVersion: v1
automountServiceAccountToken: true
kind: ServiceAccount
metadata:
annotations:
meta.helm.sh/release-name: devstar-studio
meta.helm.sh/release-namespace: devstar-studio-ns
creationTimestamp: "2024-10-01T06:49:56Z"
labels:
app: gitea
app.kubernetes.io/instance: devstar-studio
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: gitea
app.kubernetes.io/version: rootless-dev-1fa57bca2dc6922b093157e17f16d5652de1420d
helm.sh/chart: gitea-0.0.0
version: rootless-dev-1fa57bca2dc6922b093157e17f16d5652de1420d
name: devstar-studio-gitea-serviceaccount
namespace: devstar-studio-ns
resourceVersion: "92197844"
uid: 71960972-c76e-4b6a-98b5-9f66f90aefca
secrets:
- name: devstar-studio-gitea-serviceaccount-token-d499q
```
下一步,需要创建关联该 ServiceAccount 的 RoleBinding
1. ClusterRole
通过运行命令查看编辑 DevcontainerApp 的 ClusterRole
```bash
kubectl get clusterrole devcontainer-operator-devcontainerapp-editor-role -o yaml
```
显示结果如下
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: devcontainer-operator
name: devcontainer-operator-devcontainerapp-editor-role
rules:
- apiGroups:
- devcontainer.devstar.cn
resources:
- devcontainerapps
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- devcontainer.devstar.cn
resources:
- devcontainerapps/status
verbs:
- get
```
上述结果表明ClusterRole `devcontainer-operator-devcontainerapp-editor-role` 具有如下权限:
- 对于 k8s CRD 资源 `DevcontainerApp`:创建、删除、获取、列举、部分更新、全量更新、监听
- 对于 k8s CRD 资源 `DevcontainerApp` 的 status 域: 获取
2. 创建 ClusterRoleBinding
在 Helm Charts 目录下 创建文件夹 `templates/devstar-devcontainer-rbac/`,创建下列 ClusterRoleBinding
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/name: devcontainer-operator
app.kubernetes.io/managed-by: kustomize
name: devstar-devcontainerapps-editor-role-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: devcontainer-operator-devcontainerapp-editor-role
subjects:
- kind: ServiceAccount
name: {{ include "gitea.serviceAccountName" . }}
namespace: {{ .Release.Namespace | quote }}
```
**注意** RBAC 应当对 Gitea 透明,即不得将 RBAC 信息挂载到 `/values.yaml` 中如 1.2.2 小节所示的 `additionalConfigSources` 字段
至此DevStar Studio 已被赋予 k8s CRD 资源 `DevcontainerApp` 的操作权限,即可操作集群,创建或修改 DevContainer
> **补充** DevStar Studio 获取集群的控制权限
>
> ```go
> // GetKubernetesClient
> func GetKubernetesClient(ctx *context.Context) (dynamicclient.Interface, error) {
>
> // 1. 尝试从集群外获取 kubectl 配置信息
> config, err := clientcmd.BuildConfigFromFlags("", clientgocmdtools.RecommendedHomeFile)
> if err != nil {
> // 1.1 集群外尝试失败,改从集群内获取 kubectl 配置信息
> log.Warn("Failed to obtain Kubernetes config outside of cluster: " + clientgocmdtools.RecommendedHomeFile)
> config, err = clientgorest.InClusterConfig()
> if err != nil {
> log.Error("Failed to obtain Kubernetes config both inside/outside of cluster, the DevContainer is Disabled")
> setting.Devcontainer.Enabled = false
> return nil, err
> }
> }
>
> // 2. 根据 k8s 配置信息构建 ClientSet
> dynamicClient, err := dynamicclient.NewForConfig(config)
> if err != nil {
> return nil, err
> }
> return dynamicClient, err
> }
>
> ```
>
> 上述代码考虑了集群内、外两种情况配置 k8s 连接信息:
> - 集群之外/Pod 之外:通过 `~/.kube/config` 获取 Token 与 CA 证书文件
> - 集群 Pod 之内:通过 Pod 内部密钥挂载目录 `/var/run/secrets/kubernetes.io/serviceaccount/` 获取 Token 与 CA 证书文件
>
---
date: "2020-03-19T19:27:00+02:00"
title: "在 Kubernetes 中安装 Gitea"
@@ -27,7 +307,7 @@ helm repo update
helm install gitea gitea/gitea
```
如果采用默认安装指令Helm 会部署单实例的 Gitea, PostgreSQL, Memcached。若您想实现自定义安装包括配置 Gitea 集群、NGINX Ingress、MySQL、MariaDB、持久存储等请前往阅读[Gitea Helm Chart](https://gitea.com/gitea/helm-chart/)
如果采用默认安装指令Helm 会部署单实例的 Gitea, PostgreSQL, Memcached。若您想实现自定义安装包括配置 Gitea 集群、NGINX Ingress、MySQL、MariaDB、持久存储等请前往阅读[Gitea Helm Chart](https://gitea.cn/gitea/helm-chart/)
您也可以通过 `helm show` 命令导出 `README.md` 和配置文件 `values.yaml` 进行学习和编辑,例如:
@@ -62,7 +342,7 @@ HTTP/1.1 200 OK
{
"status": "pass",
"description": "Gitea: Git with a cup of tea",
"description": "DevStar Studio",
"checks": {
"cache:ping": [
{

repo.diff.view_file

@@ -26,7 +26,7 @@ menu:
## 在控制面板中检查过期的配置项
一些配置项可能会在后续版本中过期,你需要在控制面板中检查他们。如果不解决过期的配置项,
Gitea也许会在升级后无法重启。你可以访问 https://docs.gitea.com 获得要升级的版本
Gitea也许会在升级后无法重启。你可以访问 https://docs.gitea.cn 获得要升级的版本
对应的文档来修改你的配置文件。
## 降级前的备份

repo.diff.view_file

@@ -236,7 +236,7 @@ MySQL 或 PostgreSQL 容器将需要分别创建。
(默认值以**粗体**显示)
- `APP_NAME`**“Gitea: Git with a cup of tea”**:应用程序名称,在页面标题中使用。
- `APP_NAME`**“DevStar Studio”**:应用程序名称,在页面标题中使用。
- `RUN_MODE`**prod**:应用程序运行模式,会影响性能和调试。"dev""prod"或"test"。
- `DOMAIN`**localhost**:此服务器的域名,用于 Gitea UI 中显示的 http 克隆 URL。
- `SSH_DOMAIN`**localhost**:该服务器的域名,用于 Gitea UI 中显示的 ssh 克隆 URL。如果启用了安装页面则 SSH 域服务器将采用以下形式的 DOMAIN 值(保存时将覆盖此设置)。

repo.diff.view_file

@@ -15,7 +15,7 @@ menu:
# Act Runner
This page will introduce the [act runner](https://gitea.com/gitea/act_runner) in detail, which is the runner of Gitea Actions.
This page will introduce the [act runner](https://gitea.cn/gitea/act_runner) in detail, which is the runner of Gitea Actions.
## Requirements
@@ -32,7 +32,7 @@ There are multiple ways to install the act runner.
### Download the binary
You can download the binary from the [release page](https://gitea.com/gitea/act_runner/releases).
You can download the binary from the [release page](https://gitea.cn/gitea/act_runner/releases).
However, if you want to use the latest nightly build, you can download it from the [download page](https://dl.gitea.com/act_runner/).
When you download the binary, please make sure that you have downloaded the correct one for your platform.
@@ -138,7 +138,7 @@ Alternatively, you can use the `--config` option to specify the configuration fi
You will be asked to input the registration information step by step. Includes:
- The Gitea instance URL, like `https://gitea.com/` or `http://192.168.8.8:3000/`.
- The Gitea instance URL, like `https://devstar.cn/` or `http://192.168.8.8:3000/`.
- The registration token.
- The runner name, which is optional. If you leave it blank, the hostname will be used.
- The runner labels, which is optional. If you leave it blank, the default labels will be used.
@@ -277,7 +277,7 @@ It is also possible to run act-runner as a [systemd](https://en.wikipedia.org/wi
```ini
[Unit]
Description=Gitea Actions runner
Documentation=https://gitea.com/gitea/act_runner
Documentation=https://gitea.cn/gitea/act_runner
After=docker.service
[Service]

repo.diff.view_file

@@ -15,7 +15,7 @@ menu:
# Act Runner
本页面将详细介绍[Act Runner](https://gitea.com/gitea/act_runner)这是Gitea Actions的Runner。
本页面将详细介绍[Act Runner](https://gitea.cn/gitea/act_runner)这是Gitea Actions的Runner。
## 要求
@@ -32,7 +32,7 @@ menu:
### 下载二进制文件
您可以从[发布页面](https://gitea.com/gitea/act_runner/releases)下载二进制文件。
您可以从[发布页面](https://gitea.cn/gitea/act_runner/releases)下载二进制文件。
然而,如果您想使用最新的夜间构建版本,可以从[下载页面](https://dl.gitea.com/act_runner/)下载。
下载二进制文件时,请确保您已经下载了适用于您的平台的正确版本。
@@ -131,7 +131,7 @@ Runner级别决定了从哪里获取注册令牌。
您将逐步输入注册信息,包括:
- Gitea 实例的 URL例如 `https://gitea.com/``http://192.168.8.8:3000/`
- Gitea 实例的 URL例如 `https://devstar.cn/``http://192.168.8.8:3000/`
- 注册令牌。
- Runner名称可选。如果留空将使用主机名。
- Runner标签可选。如果留空将使用默认标签。

repo.diff.view_file

@@ -91,7 +91,7 @@ See [Expressions](https://docs.github.com/en/actions/learn-github-actions/expres
Gitea Actions doesn't support it now, if you use it, the result will always be empty string.
As a workaround, you can use [go-hashfiles](https://gitea.com/actions/go-hashfiles) instead.
As a workaround, you can use [go-hashfiles](https://gitea.cn/actions/go-hashfiles) instead.
## Missing features
@@ -126,12 +126,12 @@ Services steps don't have their own section in the job log user interface.
### Downloading actions
Previously (Pre 1.21.0), `[actions].DEFAULT_ACTIONS_URL` defaulted to `https://gitea.com`.
Previously (Pre 1.21.0), `[actions].DEFAULT_ACTIONS_URL` defaulted to `https://gitea.cn`.
We have since restricted this option to only allow two values (`github` and `self`).
When set to `github`, the new default, Gitea will download non-fully-qualified actions from `https://github.com`.
For example, if you use `uses: actions/checkout@v4`, it will download the checkout repository from `https://github.com/actions/checkout.git`.
If you want to download an action from another git hoster, you can use an absolute URL, e.g. `uses: https://gitea.com/actions/checkout@v4`.
If you want to download an action from another git hoster, you can use an absolute URL, e.g. `uses: https://gitea.cn/actions/checkout@v4`.
If your Gitea instance is in an intranet or a restricted area, you can set the URL to `self` to only download actions from your own instance by default.
Of course, you can still use absolute URLs in workflows.

repo.diff.view_file

@@ -91,7 +91,7 @@ Gitea Actions目前不支持此功能。
Gitea Actions目前不支持此功能如果使用它结果将始终为空字符串。
作为解决方法,您可以使用[go-hashfiles](https://gitea.com/actions/go-hashfiles)。
作为解决方法,您可以使用[go-hashfiles](https://gitea.cn/actions/go-hashfiles)。
## 缺失的功能
@@ -128,7 +128,7 @@ Gitea Actions目前不支持此功能。
`[actions].DEFAULT_ACTIONS_URL` 保持默认值为 `github`Gitea将会从 https://github.com 下载相对路径的actions。比如
如果你使用 `uses: actions/checkout@v4`Gitea将会从 https://github.com/actions/checkout.git 下载这个 actions 项目。
如果你想要从另外一个 Git服务下载actions你只需要使用绝对URL `uses: https://gitea.com/actions/checkout@v4` 来下载。
如果你想要从另外一个 Git服务下载actions你只需要使用绝对URL `uses: https://gitea.cn/actions/checkout@v4` 来下载。
如果你的 Gitea 实例是部署在一个互联网限制的网络中,也可以使用绝对地址来下载 actions。你也可以将配置项修改为 `[actions].DEFAULT_ACTIONS_URL = self`。这样所有的相对路径的actions引用将不再会从 github.com 去下载,而会从这个 Gitea 实例自己的仓库中去下载。例如: `uses: actions/checkout@v4` 将会从 `[server].ROOT_URL`/actions/checkout.git 这个地址去下载 actions。

repo.diff.view_file

@@ -23,7 +23,7 @@ The [nektos/act](https://github.com/nektos/act) project is an excellent tool tha
We were inspired by this and wondered if it would be possible to run actions for Gitea.
However, while [nektos/act](https://github.com/nektos/act) is designed as a command line tool, what we actually needed was a Go library with modifications specifically for Gitea.
So we forked it as [gitea/act](https://gitea.com/gitea/act).
So we forked it as [gitea/act](https://gitea.cn/gitea/act).
This is a soft fork that will periodically follow the upstream.
Although some custom commits have been added, we will try our best to avoid changing too much of the original code.
@@ -76,7 +76,7 @@ However, we did not think it was a good idea to have Gitea listen on a new port.
Instead, we wanted to reuse the HTTP port, which means we needed a protocol that is compatible with HTTP.
We chose to use gRPC over HTTP.
We use [actions-proto-def](https://gitea.com/gitea/actions-proto-def) and [actions-proto-go](https://gitea.com/gitea/actions-proto-go) to wire them up.
We use [actions-proto-def](https://gitea.cn/gitea/actions-proto-def) and [actions-proto-go](https://gitea.cn/gitea/actions-proto-go) to wire them up.
More information about gRPC can be found on [its website](https://grpc.io/).
## Network architecture

repo.diff.view_file

@@ -23,7 +23,7 @@ Gitea Actions由多个组件组成。本文档将对它们进行逐个描述。
我们受到了它的启发并思考它是否可能为Gitea运行Actions。
然而,尽管[nektos/act](https://github.com/nektos/act)被设计为一个命令行工具但我们实际上需要的是一个专为Gitea修改的Go库。
因此,我们在[gitea/act](https://gitea.com/gitea/act)基础上进行了分叉。
因此,我们在[gitea/act](https://gitea.cn/gitea/act)基础上进行了分叉。
这是一个软分叉,将定期跟进上游。
虽然添加了一些自定义提交,但我们会尽力避免对原始代码进行太多更改。
@@ -77,7 +77,7 @@ act 也支持直接在主机上运行Job。
相反我们希望重用HTTP端口这意味着我们需要一个与HTTP兼容的协议。
因此我们选择使用基于HTTP的gRPC。
我们使用[actions-proto-def](https://gitea.com/gitea/actions-proto-def) 和 [actions-proto-go](https://gitea.com/gitea/actions-proto-go) 进行连接。
我们使用[actions-proto-def](https://gitea.cn/gitea/actions-proto-def) 和 [actions-proto-go](https://gitea.cn/gitea/actions-proto-go) 进行连接。
有关 gRPC 的更多信息,请访问[其官方网站](https://grpc.io/)。
## 网络架构

repo.diff.view_file

@@ -52,7 +52,7 @@ The good news is that you can specify the URL prefix to use actions from anywher
This is an extra syntax in Gitea Actions.
For example:
- `uses: https://gitea.com/xxx/xxx@xxx`
- `uses: https://devstar.cn/xxx/xxx@xxx`
- `uses: https://github.com/xxx/xxx@xxx`
- `uses: http://your_gitea_instance.com/xxx@xxx`
@@ -108,7 +108,7 @@ defaults:
## Why choose GitHub Actions? Why not something compatible with GitLab CI/CD?
[@lunny](https://gitea.com/lunny) has explained this in the [issue to implement actions](https://github.com/go-gitea/gitea/issues/13539).
[@lunny](https://gitea.cn/lunny) has explained this in the [issue to implement actions](https://github.com/go-gitea/gitea/issues/13539).
Furthermore, Actions is not only a CI/CD system but also an automation tool.
There have also been numerous [marketplace actions](https://github.com/marketplace?type=actions) implemented in the open-source world.
@@ -134,7 +134,7 @@ We also need to re-design how tasks are assigned to runners.
A runner with `ubuntu`, `centos`, or `with-gpu` does not necessarily indicate that it can accept jobs with `[centos, with-gpu]`.
Therefore, the runner should inform the Gitea instance that it can only accept jobs with `[ubuntu]`, `[centos]`, `[with-gpu]`, and `[ubuntu, with-gpu]`.
This is not a technical problem, it was just overlooked in the early design.
See [runtime.go#L65](https://gitea.com/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L65).
See [runtime.go#L65](https://gitea.cn/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L65).
Currently, the act runner attempts to match everyone in the labels and uses the first match it finds.
@@ -149,7 +149,7 @@ However, the design here needs improvement, as it currently has some rough edges
You can add a custom label such as `centos` to a registered runner, which means the runner will receive jobs with `runs-on: centos`.
However, the runner may not know which environment to use for this label, resulting in it using a default image or leading to a logical dead end.
This default may not match user expectations.
See [runtime.go#L71](https://gitea.com/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L71).
See [runtime.go#L71](https://gitea.cn/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L71).
In the meantime, we suggest that you re-register your runner if you want to change its labels.

repo.diff.view_file

@@ -53,7 +53,7 @@ GitHub 上有成千上万个 [Actions 脚本](https://github.com/marketplace?typ
这是Gitea Actions中的额外语法。
例如:
- `uses: https://gitea.com/xxx/xxx@xxx`
- `uses: https://devstar.cn/xxx/xxx@xxx`
- `uses: https://github.com/xxx/xxx@xxx`
- `uses: http://your_gitea_instance.com/xxx@xxx`
@@ -109,7 +109,7 @@ defaults:
## 为什么选择GitHub Actions为什么不选择与GitLab CI/CD兼容的工具
[@lunny](https://gitea.com/lunny)在实现Actions的[问题](https://github.com/go-gitea/gitea/issues/13539)中已经解释过这个问题。
[@lunny](https://gitea.cn/lunny)在实现Actions的[问题](https://github.com/go-gitea/gitea/issues/13539)中已经解释过这个问题。
此外Actions不仅是一个CI/CD 系统,还是一个自动化工具。
在开源世界中,已经有许多[市场上的Actions](https://github.com/marketplace?type=actions)实现了。
@@ -135,7 +135,7 @@ defaults:
具有`ubuntu``centos``with-gpu`的Runner并不一定表示它可以接受`[centos, with-gpu]`的Job。
因此Runner应该通知Gitea实例它只能接受具有 `[ubuntu]``[centos]``[with-gpu]``[ubuntu, with-gpu]`的Job。
这不是一个技术问题,只是在早期设计中被忽视了。
参见[runtime.go#L65](https://gitea.com/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L65)。
参见[runtime.go#L65](https://gitea.cn/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L65)。
目前act runner尝试匹配标签中的每一个并使用找到的第一个匹配项。
@@ -150,7 +150,7 @@ defaults:
您可以向已注册的Runner添加自定义标签比如 `centos`这意味着该Runner将接收具有`runs-on: centos`的Job。
然而Runner可能不知道要使用哪个环境来执行该标签导致它使用默认镜像或导致逻辑死胡同。
这个默认值可能与用户的期望不符。
参见[runtime.go#L71](https://gitea.com/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L71)。
参见[runtime.go#L71](https://gitea.cn/gitea/act_runner/src/commit/90b8cc6a7a48f45cc28b5ef9660ebf4061fcb336/runtime/runtime.go#L71)。
与此同时如果您想更改Runner的标签我们建议您重新注册Runner。

repo.diff.view_file

@@ -30,8 +30,8 @@ To avoid confusion, we have clarified the spelling here:
## Runners
Just like other CI/CD solutions, Gitea doesn't run the jobs itself, but delegates the jobs to runners.
The runner of Gitea Actions is called [act runner](https://gitea.com/gitea/act_runner), it is a standalone program and also written in Go.
It is based on a [fork](https://gitea.com/gitea/act) of [nektos/act](http://github.com/nektos/act).
The runner of Gitea Actions is called [act runner](https://gitea.cn/gitea/act_runner), it is a standalone program and also written in Go.
It is based on a [fork](https://gitea.cn/gitea/act) of [nektos/act](http://github.com/nektos/act).
Because the runner is deployed independently, there could be potential security issues.
To avoid them, please follow two simple rules:
@@ -40,7 +40,7 @@ To avoid them, please follow two simple rules:
- Don't provide a runner to a repository, organization or instance you don't trust.
For Gitea instances used internally, such as instances used by enterprises or individuals, neither of these two rules is a problem, they are naturally so.
However, for public Gitea instances, such as [gitea.com](https://gitea.com), these two rules should be kept in mind when adding or using runners.
However, for public Gitea instances, such as [gitea.com](https://gitea.cn), these two rules should be kept in mind when adding or using runners.
## Status

repo.diff.view_file

@@ -30,8 +30,8 @@ Gitea Actions与[GitHub Actions](https://github.com/features/actions)相似且
## Runner
和其他CI/CD解决方案一样Gitea不会自己运行Job而是将Job委托给Runner。
Gitea Actions的Runner被称为[act runner](https://gitea.com/gitea/act_runner)它是一个独立的程序也是用Go语言编写的。
它是基于[nektos/act](http://github.com/nektos/act)的一个[分支](https://gitea.com/gitea/act) 。
Gitea Actions的Runner被称为[act runner](https://gitea.cn/gitea/act_runner)它是一个独立的程序也是用Go语言编写的。
它是基于[nektos/act](http://github.com/nektos/act)的一个[分支](https://gitea.cn/gitea/act) 。
由于Runner是独立部署的可能存在潜在的安全问题。
为了避免这些问题,请遵循两个简单的规则:
@@ -40,7 +40,7 @@ Gitea Actions的Runner被称为[act runner](https://gitea.com/gitea/act_runner)
- 不要为你不信任的仓库、组织或实例提供Runner。
对于内部使用的Gitea实例比如企业或个人使用的实例这两个规则不是问题它们自然而然就是如此。
然而对于公共的Gitea实例比如[gitea.com](https://gitea.com)在添加或使用Runner时应当牢记这两个规则。
然而对于公共的Gitea实例比如[gitea.com](https://gitea.cn)在添加或使用Runner时应当牢记这两个规则。
## 状态

repo.diff.view_file

@@ -34,7 +34,7 @@ If you want to learn more or encounter any problems while configuring it, please
### Set up runner
Gitea Actions requires [act runner](https://gitea.com/gitea/act_runner) to run the jobs.
Gitea Actions requires [act runner](https://gitea.cn/gitea/act_runner) to run the jobs.
In order to avoid consuming too many resources and affecting the Gitea instance, it is recommended to start runners on separate machines from the Gitea instance.
You can use the [pre-built binaries](http://dl.gitea.com/act_runner) or the [docker images](https://hub.docker.com/r/gitea/act_runner/tags) to set up the runner.
@@ -54,7 +54,7 @@ Before running a runner, you should first register it to your Gitea instance usi
There are two arguments required, `instance` and `token`.
`instance` refers to the address of your Gitea instance, like `http://192.168.8.8:3000` or `https://gitea.com`.
`instance` refers to the address of your Gitea instance, like `http://192.168.8.8:3000` or `https://devstar.cn`.
The runner and job containers (which are started by the runner to execute jobs) will connect to this address.
This means that it could be different from the `ROOT_URL` of your Gitea instance, which is configured for web access.
It is always a bad idea to use a loopback address such as `127.0.0.1` or `localhost`.

repo.diff.view_file

@@ -34,7 +34,7 @@ ENABLED=true
### 设置Runner
Gitea Actions需要[act runner](https://gitea.com/gitea/act_runner) 来运行Job。
Gitea Actions需要[act runner](https://gitea.cn/gitea/act_runner) 来运行Job。
为了避免消耗过多资源并影响Gitea实例建议您在与Gitea实例分开的机器上启动Runner。
您可以使用[预构建的二进制文件](http://dl.gitea.com/act_runner)或[容器镜像](https://hub.docker.com/r/gitea/act_runner/tags)来设置Runner。
@@ -54,7 +54,7 @@ Gitea Actions需要[act runner](https://gitea.com/gitea/act_runner) 来运行Job
需要两个必需的参数:`instance``token`
`instance`是您的Gitea实例的地址`http://192.168.8.8:3000``https://gitea.com`
`instance`是您的Gitea实例的地址`http://192.168.8.8:3000``https://devstar.cn`
Runner和Job容器由Runner启动以执行Job将连接到此地址。
这意味着它可能与用于Web访问的`ROOT_URL`不同。
使用回环地址(例如 `127.0.0.1``localhost`)是一个不好的选择。

repo.diff.view_file

@@ -308,7 +308,7 @@ This is a example for a issue config file
blank_issues_enabled: true
contact_links:
- name: Gitea
url: https://gitea.com
url: https://gitea.cn
about: Visit the Gitea Website
```

repo.diff.view_file

@@ -44,7 +44,7 @@ You can use the following variables enclosed in `${}` inside these templates whi
- PullRequestIndex: Pull request's index number
- PullRequestReference: Pull request's reference char with index number. i.e. #1, !2
- ClosingIssues: return a string contains all issues which will be closed by this pull request i.e. `close #1, close #2`
- ReviewedOn: Which pull request this commit belongs to. For example `Reviewed-on: https://gitea.com/foo/bar/pulls/1`
- ReviewedOn: Which pull request this commit belongs to. For example `Reviewed-on: https://gitea.cn/foo/bar/pulls/1`
- ReviewedBy: Who approved the pull request before the merge. For example `Reviewed-by: Jane Doe <jane.doe@example.com>`
## Rebase

120
go.mod
repo.diff.view_file

@@ -1,6 +1,8 @@
module code.gitea.io/gitea
go 1.22
go 1.23.0
toolchain go1.23.3
require (
code.gitea.io/actions-proto-go v0.4.0
@@ -30,6 +32,8 @@ require (
github.com/dimiro1/reply v0.0.0-20200315094148-d0136a4c9e21
github.com/djherbis/buffer v1.2.0
github.com/djherbis/nio/v3 v3.0.1
github.com/docker/docker v24.0.7+incompatible
github.com/docker/go-connections v0.4.0
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5
github.com/dustin/go-humanize v1.0.1
github.com/editorconfig/editorconfig-core-go/v2 v2.6.2
@@ -58,7 +62,7 @@ require (
github.com/gogs/go-gogs-client v0.0.0-20210131175652-1d7215cd8d85
github.com/golang-jwt/jwt/v5 v5.2.1
github.com/google/go-github/v61 v61.0.0
github.com/google/pprof v0.0.0-20240618054019-d3b898a103f8
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6
github.com/google/uuid v1.6.0
github.com/gorilla/feeds v1.2.0
github.com/gorilla/sessions v1.3.0
@@ -111,42 +115,83 @@ require (
github.com/yuin/goldmark v1.7.2
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
github.com/yuin/goldmark-meta v1.1.0
golang.org/x/crypto v0.24.0
golang.org/x/crypto v0.36.0
golang.org/x/image v0.15.0
golang.org/x/net v0.26.0
golang.org/x/oauth2 v0.21.0
golang.org/x/sys v0.21.0
golang.org/x/text v0.16.0
golang.org/x/tools v0.22.0
google.golang.org/grpc v1.62.1
google.golang.org/protobuf v1.34.2
golang.org/x/net v0.37.0
golang.org/x/oauth2 v0.23.0
golang.org/x/sys v0.32.0
golang.org/x/text v0.23.0
golang.org/x/tools v0.31.0
google.golang.org/grpc v1.65.0
google.golang.org/protobuf v1.36.5
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
gopkg.in/ini.v1 v1.67.0
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.23.10
k8s.io/apimachinery v0.23.10
k8s.io/api v0.32.3
k8s.io/apimachinery v0.32.3
k8s.io/kubectl v0.32.3
mvdan.cc/xurls/v2 v2.5.0
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
xorm.io/builder v0.3.13
xorm.io/xorm v1.3.8
)
require (
cel.dev/expr v0.18.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/evanphx/json-patch/v5 v5.9.11 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/google/btree v1.1.3 // indirect
github.com/google/cel-go v0.22.0 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/gorilla/websocket v1.5.0 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/moby/spdystream v0.5.0 // indirect
github.com/moby/term v0.5.0 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect
github.com/stoewer/go-strcase v1.3.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.53.0 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.28.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.27.0 // indirect
go.opentelemetry.io/otel/metric v1.28.0 // indirect
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240826202546-f6391c0de4c7 // indirect
gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect
k8s.io/apiextensions-apiserver v0.32.1 // indirect
k8s.io/apiserver v0.32.1 // indirect
k8s.io/kube-openapi v0.0.0-20241105132330-32ad38e42d3f // indirect
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.31.0 // indirect
)
require (
github.com/ArtisanCloud/PowerSocialite/v3 v3.0.7 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-cmp v0.7.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
golang.org/x/term v0.21.0 // indirect
golang.org/x/term v0.30.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
k8s.io/client-go v0.23.10
k8s.io/klog/v2 v2.30.0 // indirect
k8s.io/utils v0.0.0-20211116205334-6203023598ed // indirect
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
k8s.io/client-go v0.32.3
k8s.io/klog/v2 v2.130.1
k8s.io/utils v0.0.0-20241104100929-3ea5e8cea738 // indirect
sigs.k8s.io/json v0.0.0-20241010143419-9aa6b5e7a4b3 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)
require (
@@ -195,7 +240,7 @@ require (
github.com/couchbase/go-couchbase v0.1.1 // indirect
github.com/couchbase/gomemcached v0.3.1 // indirect
github.com/couchbase/goutils v0.1.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
github.com/cyphar/filepath-securejoin v0.2.5 // indirect
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/davidmz/go-pageant v1.0.2 // indirect
@@ -204,7 +249,7 @@ require (
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect
github.com/fatih/color v1.17.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fxamacker/cbor/v2 v2.6.0 // indirect
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
github.com/go-ap/errors v0.0.0-20240304112515-6077fa9c17b0 // indirect
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
github.com/go-enry/go-oniguruma v1.2.1 // indirect
@@ -241,7 +286,7 @@ require (
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jessevdk/go-flags v1.5.0 // indirect
github.com/jessevdk/go-flags v1.6.1 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/kevinburke/ssh_config v1.2.0 // indirect
github.com/klauspost/pgzip v1.2.6 // indirect
@@ -267,13 +312,15 @@ require (
github.com/oklog/ulid v1.3.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/ginkgo/v2 v2.23.4 // indirect
github.com/onsi/gomega v1.37.0 // indirect
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
github.com/pierrec/lz4/v4 v4.1.21 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/prometheus/client_model v0.6.0 // indirect
github.com/prometheus/common v0.50.0 // indirect
github.com/prometheus/procfs v0.13.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/rhysd/actionlint v1.7.1 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/rogpeppe/go-internal v1.12.0 // indirect
@@ -288,7 +335,8 @@ require (
github.com/sourcegraph/conc v0.3.0 // indirect
github.com/spf13/afero v1.11.0 // indirect
github.com/spf13/cast v1.6.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.6
github.com/spf13/viper v1.18.2 // indirect
github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect
github.com/subosito/gotenv v1.6.0 // indirect
@@ -304,19 +352,21 @@ require (
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
go.etcd.io/bbolt v1.3.10 // indirect
go.etcd.io/bbolt v1.3.11 // indirect
go.mongodb.org/mongo-driver v1.14.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/x/exp v0.0.0-20240314144324-c7f7c6466f7f // indirect
golang.org/x/mod v0.18.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240314234333-6e1732d8331c // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/mod v0.24.0 // indirect
golang.org/x/sync v0.12.0 // indirect
golang.org/x/time v0.7.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240826202546-f6391c0de4c7 // indirect
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/component-base v0.32.3
sigs.k8s.io/controller-runtime v0.20.4
)
replace github.com/hashicorp/go-version => github.com/6543/go-version v1.3.1
@@ -335,3 +385,5 @@ exclude github.com/gofrs/uuid v4.0.0+incompatible
exclude github.com/goccy/go-json v0.4.11
exclude github.com/satori/go.uuid v1.2.0
replace github.com/docker/distribution => github.com/distribution/distribution v2.8.0+incompatible

681
go.sum

repo.diff.file_suppressed repo.diff.load

repo.diff.view_file

@@ -1,19 +1,20 @@
package devstar_devcontainer
package devcontainer
import (
"code.gitea.io/gitea/models/db"
)
// DevstarDevcontainer devContainer 关联 代码仓库 和 用户
// Devcontainer devContainer 关联 代码仓库 和 用户
//
// TODO 移除 port 信息需要前端主动连接时候实时获取最新分配结果可以考虑给用户API提供选项是否阻塞等待
//
// 遵循gonic规则映射数据库表 `devstar_devcontainer`,各字段注解见 https://xorm.io/docs/chapter-02/4.columns/
type DevstarDevcontainer struct {
// 遵循gonic规则映射数据库表 `devcontainer`,各字段注解见 https://xorm.io/docs/chapter-02/4.columns/
type Devcontainer struct {
Id int64 `xorm:"BIGINT pk NOT NULL autoincr 'id' comment('主键devContainerId')"`
Name string `xorm:"VARCHAR(64) charset=utf8mb4 collate=utf8mb4_bin UNIQUE NOT NULL 'name' comment('devContainer名称自动生成')"`
DevcontainerHost string `xorm:"VARCHAR(256) charset=utf8mb4 collate=utf8mb4_bin NOT NULL 'devcontainer_host' comment('SSH Host')"`
DevcontainerPort uint16 `xorm:"SMALLINT UNSIGNED NOT NULL 'devcontainer_port' comment('SSH Port')"`
DevcontainerStatus uint16 `xorm:"SMALLINT UNSIGNED NOT NULL 'devcontainer_status' comment('SSH Status')"`
DevcontainerUsername string `xorm:"VARCHAR(32) charset=utf8mb4 collate=utf8mb4_bin NOT NULL 'devcontainer_username' comment('SSH Username')"`
DevcontainerWorkDir string `xorm:"VARCHAR(256) charset=utf8mb4 collate=utf8mb4_bin NOT NULL 'devcontainer_work_dir' comment('SSH 工作路径,典型值 ~/${project_name}256字节以内')"`
RepoId int64 `xorm:"BIGINT NOT NULL 'repo_id' comment('repository表主键')"`
@@ -22,6 +23,17 @@ type DevstarDevcontainer struct {
UpdatedUnix int64 `xorm:"BIGINT 'updated_unix' comment('更新时间戳')"`
}
func init() {
db.RegisterModel(new(DevstarDevcontainer))
type DevcontainerOutput struct {
Id int64 `xorm:"BIGINT pk NOT NULL autoincr 'id' comment('主键devContainerId')"`
RepoId int64 `xorm:"BIGINT NOT NULL unique(uniquename) 'repo_id' comment('repository表主键')"`
UserId int64 `xorm:"BIGINT NOT NULL unique(uniquename) 'user_id' comment('user表主键')"`
Status string `xorm:"VARCHAR(255) charset=utf8mb4 collate=utf8mb4_bin NOT NULL 'status' comment('status')"`
Output string `xorm:"TEXT 'output' comment('output')"`
Command string `xorm:"TEXT 'command' comment('command')"`
ListId int64 `xorm:"BIGINT NOT NULL unique(uniquename) 'list_id' comment('list_id')"`
}
func init() {
db.RegisterModel(new(Devcontainer))
db.RegisterModel(new(DevcontainerOutput))
}

repo.diff.view_file

@@ -0,0 +1,290 @@
package devcontainer
import (
"code.gitea.io/gitea/modules/json"
)
// DevContainerJSON 用于反序列化仓库中的 DevContainer 配置信息
// `.devcontainer/devcontainer.json` or `.devcontainer.json` in project root.
// ref: https://containers.dev/implementors/json_reference
type DevContainerJSON struct {
/***********************************************************************************
* BEGIN General devcontainer.json properties
* https://containers.dev/implementors/json_reference/#general-properties
***********************************************************************************/
// Name A name for the dev container displayed in the UI.
Name string `json:"name"`
// ForwardPorts An array of port numbers or "host:port" values (e.g. [3000, "db:5432"])
// that should always be forwarded from inside the primary container to the local machine (including on the web).
ForwardPorts []interface{} `json:"forwardPorts,omitempty"`
// PortsAttributes Object that maps a port number, "host:port" value, range, or regular expression
// to a set of default options.
PortsAttributes map[string]PortAttributeType `json:"portsAttributes,omitempty"`
// OtherPortsAttributes Default options for ports, port ranges, and hosts that arent configured using portsAttributes.
OtherPortsAttributes *PortAttributeType `json:"otherPortsAttributes,omitempty"`
// ContainerEnv A set of name-value pairs that sets or overrides environment variables for the container.
ContainerEnv map[string]string `json:"containerEnv,omitempty"`
// RemoteEnv A set of name-value pairs that sets or overrides environment variables
// for the devcontainer.json supporting service / tool (or sub-processes like terminals)
// but not the container as a whole.
RemoteEnv map[string]interface{} `json:"remoteEnv,omitempty"`
// RemoteUser Overrides the user for all operations run as inside the container.
// Default to either `root` or the last USER instruction in the related Dockerfile used to create the image.
RemoteUser *string `json:"remoteUser,omitempty"`
// ContainerUser
// Defaults to either root or the last USER instruction in the related Dockerfile used to create the image.
ContainerUser *string `json:"containerUser,omitempty"`
// UpdateRemoteUserUID On Linux, if containerUser or remoteUser is specified,
// the users UID/GID will be updated to match the local users UID/GID to avoid permission problems with bind mounts.
UpdateRemoteUserUID bool `json:"updateRemoteUserUID"`
// UserEnvProbe Indicates the type of shell to use to “probe” for user environment variables
// to include in devcontainer.json supporting services / tools processes:
// none, interactiveShell, loginShell, or loginInteractiveShell (default).
UserEnvProbe UserEnvProbeType `json:"userEnvProbe"`
// OverrideCommand Tells devcontainer.json supporting services / tools
// whether they should run /bin/sh -c "while sleep 1000; do :; done" when starting the container
// instead of the containers default command (since the container can shut down if the default command fails).
// Set to false if the default command must run for the container to function properly.
// Default to `true` for when using an image Dockerfile and `false` when referencing a Docker Compose file.
OverrideCommand bool `json:"overrideCommand,omitempty"`
// ShutdownAction Indicates whether devcontainer.json supporting tools should stop the containers
// when the related tool window is closed / shut down.
// Values are `none`, `stopContainer`(default for image/Dockerfile), and `stopCompose`(default for Docker Compose).
ShutdownAction ShutdownActionType `json:"shutdownAction,omitempty"`
// Init Defaults to false.
// Cross-orchestrator way to indicate whether the tini init process should be used to help deal with zombie processes.
Init bool `json:"init"`
// Privileged Defaults to false. Cross-orchestrator way to cause the container to run in privileged mode (--privileged).
// Required for things like Docker-in-Docker, but has security implications particularly when running directly on Linux.
Privileged bool `json:"privileged"`
// CapAdd Defaults to []. Cross-orchestrator way to add capabilities typically disabled for a container.
// Most often used to add the *ptrace* capability required to debug languages like C++, Go, and Rust.
CapAdd []string `json:"capAdd"`
// SecurityOpt Defaults to []. Cross-orchestrator way to set container security options.
SecurityOpt []string `json:"securityOpt"`
// Mounts Cross-orchestrator way to add additional mounts to a container.
// Each value is a string that accepts the same values as the Docker CLI --mount flag.
// Environment and pre-defined variables may be referenced in the value.
Mounts []interface{} `json:"mounts,omitempty"`
// Features An object of Dev Container Feature IDs and related options to be added into your primary container.
// The specific options that are available varies by feature, so see its documentation for additional details.
Features map[string]interface{} `json:"features,omitempty"`
// OverrideFeatureInstallOrder allows you to override the Feature install order when needed.
OverrideFeatureInstallOrder []interface{} `json:"overrideFeatureInstallOrder,omitempty"`
// Customizations Product specific properties, defined in https://containers.dev/supporting#visual-studio-code
Customizations map[string]interface{} `json:"customizations,omitempty"`
/***********************************************************************************
* END General devcontainer.json properties
* https://containers.dev/implementors/json_reference/#general-properties
***********************************************************************************/
/***********************************************************************************
* BEGIN Scenario specific properties
* https://containers.dev/implementors/json_reference/#scenario-specific
***********************************************************************************/
// Image Required when using an image. The name of an image in a container registry
// that devcontainer.json supporting services/tools should use to create the DevContainer.
Image string `json:"image"`
// Build Docker build specific properties
Build *DockerBuildType `json:"build,omitempty"`
// AppPort accepts a port or array of ports that should be published locally when the container is running.
AppPort *interface{} `json:"appPort"`
// WorkspaceMount Requires workspaceFolder be set as well.
// Overrides the default local mount point for the workspace when the container is created.
// Supports the same values as the Docker CLI --mount flag.
// Environment and pre-defined variables may be referenced in the value.
WorkspaceMount *string `json:"workspaceMount,omitempty"`
// WorkspaceFolder Requires workspaceMount be set. Sets the default path that devcontainer.json supporting services / tools should open when connecting to the container. Defaults to the automatic source code mount location.
WorkspaceFolder *string `json:"workspaceFolder,omitempty"`
// RunArgs An array of Docker CLI arguments that should be used when running the container.
RunArgs []string `json:"runArgs,omitempty"`
// DockerComposeFile Required when using Docker Compose.
// Path or an ordered list of paths to Docker Compose files relative to the devcontainer.json file.
DockerComposeFile *interface{} `json:"dockerComposeFile,omitempty"`
// Service Required when using Docker Compose.
// The name of the service devcontainer.json supporting services / tools should connect to once running.
Service *string `json:"service,omitempty"`
// RunServices An array of services in your Docker Compose configuration
// that should be started by devcontainer.json supporting services / tools.
// These will also be stopped when you disconnect unless "shutdownAction" is "none". Defaults to all services.
RunServices []interface{} `json:"runServices,omitempty"`
// WorkspaceFolder Sets the default path that devcontainer.json
// supporting services/tools should open when connecting to the container
// (which is often the path to a volume mount where the source code can be found in the container).
// Defaults to "/".
//WorkspaceFolder string `json:"workspaceFolder"`
/***********************************************************************************
* END Scenario specific properties
* https://containers.dev/implementors/json_reference/#scenario-specific
***********************************************************************************/
/***********************************************************************************
* BEGIN Tool-specific properties
* https://containers.dev/implementors/json_reference/#tool-specific
***********************************************************************************/
// InitializedCommand A command string or list of command arguments to run on the host machine during initialization,
// including during container creation and on subsequent starts.
// The command may run more than once during a given session.
// ⚠ The command is run wherever the source code is located on the host. For cloud services, this is in the cloud.
// Note that the array syntax will execute the command without a shell.
// You can learn more about formatting string vs array vs object properties.
InitializeCommand interface{} `json:"initializeCommand,omitempty"`
// OnCreateCommand is the first of three (along with updateContentCommand and postCreateCommand)
// that finalizes container setup when a dev container is created.
// It and subsequent commands execute inside the container immediately after it has started for the first time.
// Cloud services can use this command when caching or prebuilding a container.
// This means that it will not typically have access to user-scoped assets or secrets.
// Note that the array syntax will execute the command without a shell.
OnCreateCommand interface{} `json:"onCreateCommand"`
UpdateContentCommand interface{} `json:"updateContentCommand "`
PostCreateCommand interface{} `json:"postCreateCommand"`
PostStartCommand interface{} `json:"postStartCommand"`
PostAttachCommand interface{} `json:"postAttachCommand"`
WaitFor DevContainerConfigCommandType `json:"waitFor,omitempty"`
HostRequirements *HostRequirementsType `json:"hostRequirements,omitempty"`
/***********************************************************************************
* END Tool-specific properties
* https://containers.dev/implementors/json_reference/#tool-specific
***********************************************************************************/
}
type DevContainerConfigCommandType string
const (
InitializeCommand DevContainerConfigCommandType = "initializeCommand"
OnCreateCommand DevContainerConfigCommandType = "onCreateCommand"
UpdateContentCommand DevContainerConfigCommandType = "updateContentCommand"
PostCreateCommand DevContainerConfigCommandType = "postCreateCommand"
PostStartCommand DevContainerConfigCommandType = "postStartCommand"
PostAttachCommand DevContainerConfigCommandType = "postAttachCommand"
)
type ShutdownActionType string
const (
NoneShutdownActionType ShutdownActionType = "none"
StopContainerShutdownActionType ShutdownActionType = "stopContainer"
StopComposeShutdownActionType ShutdownActionType = "stopCompose"
)
type UserEnvProbeType string
const (
NoneUserEnvProbeType UserEnvProbeType = "none"
LoginShellUserEnvProbeType UserEnvProbeType = "loginShell"
InteractiveShellUserEnvProbeType UserEnvProbeType = "interactiveShell"
LoginInteractiveShellUserEnvProbeType UserEnvProbeType = "loginInteractiveShell"
)
// DockerBuildType Docker build specific properties
type DockerBuildType struct {
// Dockerfile Required when using a Dockerfile.
// The location of a Dockerfile that defines the contents of the container.
// The path is relative to the devcontainer.json file.
Dockerfile string `json:"dockerfile,omitempty"`
// Path that the Docker build should be run from relative to devcontainer.json.
Context string `json:"context"`
// Args A set of name-value pairs containing Docker image build arguments that should be passed when building a Dockerfile.
// Environment and pre-defined variables may be referenced in the values.
Args map[string]string `json:"args,omitempty"`
// Options An array of Docker image build options that passed to the build command when building a Dockerfile.
Options []string `json:"options"`
// Target A string that specifies a Docker image build target that should be passed when building a Dockerfile.
Target string `json:"target,omitempty"`
// CacheFrom A string or array of strings that specify one or more images to use as caches when building the image.
// Cached image identifiers are passed to the docker build command with --cache-from.
CacheFrom interface{} `json:"cacheFrom"`
}
// ProtocolType Enum values for Protocol
type ProtocolType string
const (
ProtocolTCP ProtocolType = "tcp"
ProtocolHTTP ProtocolType = "http"
ProtocolHTTPS ProtocolType = "https"
)
// OnAutoForwardType Enum for OnAutoForward
type OnAutoForwardType string
const (
OnAutoForwardNotify OnAutoForwardType = "notify"
OnAutoForwardOpenBrowser OnAutoForwardType = "openBrowser"
OnAutoForwardOpenBrowserOnce OnAutoForwardType = "openBrowserOnce"
OnAutoForwardOpenPreview OnAutoForwardType = "openPreview"
OnAutoForwardSilent OnAutoForwardType = "silent"
OnAutoForwardIgnore OnAutoForwardType = "ignore"
)
// PortAttributeType
//
// ref: https://containers.dev/implementors/json_reference/#port-attributes
type PortAttributeType struct {
Label string `json:"label,omitempty"`
Protocol ProtocolType `json:"protocol,omitempty"`
OnAutoForward OnAutoForwardType `json:"onAutoForward,omitempty"`
RequireLocalPort bool `json:"requireLocalPort,omitempty"`
ElevateIfNeeded bool `json:"elevateIfNeeded,omitempty"`
}
type HostGPURequirements struct {
cores *uint64 `json:"cores"`
memory *string `json:"memory"`
}
type HostRequirementsType struct {
CPUs int `json:"cpus,omitempty"`
Memory string `json:"memory,omitempty"`
Storage string `json:"storage,omitempty"`
GPU interface{} `json:"gpu,omitempty"` // Could be bool, 'optional', or HostGPURequirements
}
// Unmarshal 反序列化JSON返回带有默认值的 DevContainerJSON
func Unmarshal(devcontainerJSONContent string) (*DevContainerJSON, error) {
// 1. 初始化
devcontainerJSON := &DevContainerJSON{}
// 2. JSON 反序列化
err := json.Unmarshal([]byte(devcontainerJSONContent), devcontainerJSON)
if err != nil {
return nil, err
}
// 3. 返回
return devcontainerJSON, err
}

repo.diff.view_file

@@ -0,0 +1,15 @@
package errors
import (
"fmt"
)
// ErrFailedToOperateDevcontainerDB 错误类型:打开数据库失败
type ErrFailedToOperateDevcontainerDB struct {
Action string
Message string
}
func (err ErrFailedToOperateDevcontainerDB) Error() string {
return fmt.Sprintf("Failed to %v in DevStar DevContainer DB: %v", err.Action, err.Message)
}

repo.diff.view_file

@@ -1,15 +0,0 @@
package devstar_devcontainer
import (
"fmt"
)
// ErrFailedToOperateDevstarDevcontainerDB 错误类型:打开数据库失败
type ErrFailedToOperateDevstarDevcontainerDB struct {
Action string
Message string
}
func (err ErrFailedToOperateDevstarDevcontainerDB) Error() string {
return fmt.Sprintf("Failed to %v in DevStar DevContainer DB: %v", err.Action, err.Message)
}

repo.diff.view_file

@@ -8,11 +8,11 @@ import (
"xorm.io/xorm"
)
// AddDBWeChatOfficialAccountUser 创建微信公众号二维码登录所需要的数据库字段
func AddDBWeChatOfficialAccountUser(x *xorm.Engine) error {
// AddDBWeChatUser 创建微信公众号二维码登录所需要的数据库字段
func AddDBWeChatUser(x *xorm.Engine) error {
// 创建数据库表格
err := x.Sync(new(wechat_models.UserWechatOfficialAccountOpenid))
err := x.Sync(new(wechat_models.UserWechatOpenid))
if err != nil {
return ErrMigrateDevstarDatabase{
Step: "create table 'user_wechat_official_account_openid'",

repo.diff.view_file

@@ -4,7 +4,7 @@ package devstar_v1_0
// 从 dv1 到 dv2
import (
devcontainer_models "code.gitea.io/gitea/models/devstar_devcontainer"
devcontainer_model "code.gitea.io/gitea/models/devcontainer"
"xorm.io/xorm"
)
@@ -14,20 +14,20 @@ func InitializeDevContainerDbTables(x *xorm.Engine) error {
var err error
// 1. 初始化 devContainer 表
if err = addDBDevStarDevContainer(x); err != nil {
if err = addDBDevcontainer(x); err != nil {
return err
}
return nil
}
// addDBDevStarDevContainer 1. 初始化 devContainer 与 Repository 一对一关系表
func addDBDevStarDevContainer(x *xorm.Engine) error {
// addDBDevcontainer 1. 初始化 devContainer 与 Repository 一对一关系表
func addDBDevcontainer(x *xorm.Engine) error {
err := x.Sync(new(devcontainer_models.DevstarDevcontainer))
err := x.Sync(new(devcontainer_model.Devcontainer))
if err != nil {
return ErrMigrateDevstarDatabase{
Step: "create table 'devstar_devcontainer'",
Step: "create table 'devcontainer'",
Message: err.Error(),
}
}

repo.diff.view_file

@@ -1,4 +1,4 @@
-
id: 1
description: the badge
image_url: https://gitea.com/myimage.png
image_url: https://gitea.cn/myimage.png

repo.diff.view_file

@@ -5,10 +5,11 @@
package migrations
import (
"code.gitea.io/gitea/models/migrations/devstar_v1_0"
"context"
"fmt"
"code.gitea.io/gitea/models/migrations/devstar_v1_0"
"code.gitea.io/gitea/models/migrations/v1_10"
"code.gitea.io/gitea/models/migrations/v1_11"
"code.gitea.io/gitea/models/migrations/v1_12"
@@ -596,7 +597,7 @@ var migrations = []Migration{
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
// 下面是 创建新数据库表语句: 从 Gitea 迁移到 DevStar Studio
// v300 -> dv1 (Devstar studio Version #1)
NewMigration("Add Support for WeChat Official Account Login", devstar_v1_0.AddDBWeChatOfficialAccountUser),
NewMigration("Add Support for WeChat Official Account Login", devstar_v1_0.AddDBWeChatUser),
// dv1 -> dv2
NewMigration("Added Support for devContainer", devstar_v1_0.InitializeDevContainerDbTables),

repo.diff.view_file

@@ -99,6 +99,21 @@ func SetSettings(ctx context.Context, settings map[string]string) error {
})
}
func SetSetting(ctx context.Context, key, value string) error {
return SetSettings(ctx, map[string]string{key: value})
}
func GetSetting(ctx context.Context, key string) (string, error) {
setting, exist, err := db.Get[Setting](ctx, builder.Eq{"setting_key": key})
if err != nil {
return "", err
}
if !exist {
return "", nil
}
return setting.SettingValue, nil
}
type dbConfigCachedGetter struct {
mu sync.RWMutex

repo.diff.view_file

@@ -1,25 +0,0 @@
package wechat
import (
"fmt"
)
// ErrFailedToOperateWechatOfficialAccountUserDB 错误类型:打开数据库失败
type ErrFailedToOperateWechatOfficialAccountUserDB struct {
Action string
Message string
}
func (err ErrFailedToOperateWechatOfficialAccountUserDB) Error() string {
return fmt.Sprintf("Failed to %v in WeChat Official Account DB: %v", err.Action, err.Message)
}
// ErrWechatOfficialAccountUserNotExist 错误类型:找不到对应的微信公众号用户
type ErrWechatOfficialAccountUserNotExist struct {
AppID string
OpenID string
}
func (err ErrWechatOfficialAccountUserNotExist) Error() string {
return fmt.Sprintf("WeChat Official Account User not found: AppID = %v, OpenID = %v", err.AppID, err.OpenID)
}

repo.diff.view_file

@@ -1,38 +1,59 @@
package wechat
import (
"context"
"fmt"
"code.gitea.io/gitea/models/db"
user_model "code.gitea.io/gitea/models/user"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"context"
"fmt"
)
// UserWechatOfficialAccountOpenid 用户ID与微信公众号openid一对一关联表
// ErrFailedToOperateWechatOfficialAccountUserDB 错误类型:打开数据库失败
type ErrFailedToOperateWechatOfficialAccountUserDB struct {
Action string
Message string
}
func (err ErrFailedToOperateWechatOfficialAccountUserDB) Error() string {
return fmt.Sprintf("Failed to %v in WeChat Official Account DB: %v", err.Action, err.Message)
}
// ErrWechatOfficialAccountUserNotExist 错误类型:找不到对应的微信公众号用户
type ErrWechatOfficialAccountUserNotExist struct {
AppID string
OpenID string
}
func (err ErrWechatOfficialAccountUserNotExist) Error() string {
return fmt.Sprintf("WeChat Official Account User not found: AppID = %v, OpenID = %v", err.AppID, err.OpenID)
}
// UserWechatOpenid 用户ID与微信公众号openid一对一关联表
// 数据库指定schema下 必须存在 `user_wechat_official_account_openid`,否则报错 ERROR 1146 (42S02): Table does not exist
//
// 遵循gonic规则映射数据库表 `user_wechat_official_account_openid`,各字段注解见 https://xorm.io/docs/chapter-02/4.columns/
type UserWechatOfficialAccountOpenid struct {
Id int64 `xorm:"BIGINT pk NOT NULL autoincr 'id' comment('主键')"`
Uid int64 `xorm:"BIGINT UNIQUE NOT NULL 'uid' comment('user表主键')"`
OfficialAccountAppid string `xorm:"VARCHAR(50) charset=utf8mb4 collate=utf8mb4_bin NOT NULL 'official_account_appid' comment('微信公众号关联的AppID便于区分不同公众号用户、便于后期公众号迁移')"`
Openid string `xorm:"VARCHAR(50) charset=utf8mb4 collate=utf8mb4_bin UNIQUE NOT NULL 'openid' comment('微信公众号粉丝OpenID')"`
type UserWechatOpenid struct {
Id int64 `xorm:"BIGINT pk NOT NULL autoincr 'id' comment('主键')"`
Uid int64 `xorm:"BIGINT UNIQUE NOT NULL 'uid' comment('user表主键')"`
WechatAppid string `xorm:"VARCHAR(50) charset=utf8mb4 collate=utf8mb4_bin NOT NULL 'official_account_appid' comment('微信公众号关联的AppID便于区分不同公众号用户、便于后期公众号迁移')"`
Openid string `xorm:"VARCHAR(50) charset=utf8mb4 collate=utf8mb4_bin UNIQUE NOT NULL 'openid' comment('微信公众号粉丝OpenID')"`
}
// Use `charset=utf8mb4 collate=utf8mb4_bin` to fix log.Error: There are 2 table columns(`official_account_appid`, `openid`) using inconsistent collation, they should use "utf8mb4_bin". Please go to admin panel Self Check page
func init() {
db.RegisterModel(new(UserWechatOfficialAccountOpenid))
db.RegisterModel(new(UserWechatOpenid))
}
// QueryUserByOpenid 根据微信公众号用户openid查询 `user` 表用户
func QueryUserByOpenid(ctx context.Context, openid string) (*user_model.User, error) {
// 1. 根据公众号 AppID 和 OpenID 查询数据库中 user表 主键ID
wechatUser := &UserWechatOfficialAccountOpenid{
OfficialAccountAppid: setting.Wechat.OfficialAccount.UserConfig.AppID,
Openid: openid,
wechatUser := &UserWechatOpenid{
WechatAppid: setting.Wechat.UserConfig.AppID,
Openid: openid,
}
var user *user_model.User
@@ -50,7 +71,7 @@ func QueryUserByOpenid(ctx context.Context, openid string) (*user_model.User, er
if !exist {
return ErrWechatOfficialAccountUserNotExist{
AppID: wechatUser.OfficialAccountAppid,
AppID: wechatUser.WechatAppid,
OpenID: wechatUser.Openid,
}
}
@@ -76,15 +97,15 @@ func QueryUserByOpenid(ctx context.Context, openid string) (*user_model.User, er
return user, err
}
// UpdateOrCreateWechatOfficialAccountUser 更新/新建用户微信
func UpdateOrCreateWechatOfficialAccountUser(ctx context.Context, user *user_model.User, openid string) error {
// UpdateOrCreateWechatUser 更新/新建用户微信
func UpdateOrCreateWechatUser(ctx context.Context, user *user_model.User, openid string) error {
// 1. 构造查询条件DevStar 用户ID即 UID
wechatUser := &UserWechatOfficialAccountOpenid{
wechatUser := &UserWechatOpenid{
Uid: user.ID,
}
officialAccountAppid := setting.Wechat.OfficialAccount.UserConfig.AppID
WechatAppid := setting.Wechat.UserConfig.AppID
// 2. 开启数据库事务,保证数据库表 `user_wechat_official_account_openid` 原子操作(出错时候自动进行 transaction Rollback
err := db.WithTx(ctx, func(ctx context.Context) error {
@@ -98,12 +119,12 @@ func UpdateOrCreateWechatOfficialAccountUser(ctx context.Context, user *user_mod
}
// 2.2 数据库更新或插入新记录
if has && wechatUser.OfficialAccountAppid == officialAccountAppid && wechatUser.Openid == openid {
if has && wechatUser.WechatAppid == WechatAppid && wechatUser.Openid == openid {
// 有用户记录,且未发生变化,直接返回,结束事务
return nil
} else if has && (wechatUser.OfficialAccountAppid != officialAccountAppid || wechatUser.Openid != openid) {
} else if has && (wechatUser.WechatAppid != WechatAppid || wechatUser.Openid != openid) {
// 有用户记录,但公众号主体 AppId 或者 关联的用户号 OpenID 发生变化
wechatUser.OfficialAccountAppid = officialAccountAppid
wechatUser.WechatAppid = WechatAppid
wechatUser.Openid = openid
_, err = db.GetEngine(ctx).ID(wechatUser.Id).Update(wechatUser)
if err != nil {
@@ -114,7 +135,7 @@ func UpdateOrCreateWechatOfficialAccountUser(ctx context.Context, user *user_mod
}
} else {
// 没有用户记录,需要插入新纪录
wechatUser.OfficialAccountAppid = officialAccountAppid
wechatUser.WechatAppid = WechatAppid
wechatUser.Openid = openid
_, err = db.GetEngine(ctx).Insert(wechatUser)
if err != nil {
@@ -137,3 +158,35 @@ func UpdateOrCreateWechatOfficialAccountUser(ctx context.Context, user *user_mod
log.Info("微信公众号绑定成功: (UID, User.Name, OpenID) = (%v, %v, %v)", user.ID, user.Name, openid)
return nil
}
// DeleteWechatUser 清空当前用户的微信公众号绑定信息
func DeleteWechatUser(ctx context.Context, user *user_model.User) error {
// 0. 检查参数
if user == nil || user.ID <= 0 {
return ErrFailedToOperateWechatOfficialAccountUserDB{
Action: "Find User",
Message: "User and its ID cannot be nil",
}
}
// 1. 构造查询条件DevStar 用户ID即 UID
wechatUser := &UserWechatOpenid{
Uid: user.ID,
}
// 2. 开启数据库事务,删除数据库表 `user_wechat_official_account_openid` 中 user.ID 对应条目
err := db.WithTx(ctx, func(ctx context.Context) error {
// 2.1 根据 UID 查询数据库
_, err := db.GetEngine(ctx).Delete(wechatUser)
if err != nil {
return ErrFailedToOperateWechatOfficialAccountUserDB{
Action: fmt.Sprintf("Delete WeChat Official Account Binding for User '%v'(ID = %v)", user.Name, user.ID),
Message: err.Error(),
}
}
return nil
})
return err
}

repo.diff.view_file

@@ -1,149 +0,0 @@
package k8s_agent
import (
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/services/devstar_cloud_provider"
"code.gitea.io/gitea/services/devstar_devcontainer/errors"
"context"
"encoding/json"
"fmt"
devcontainer_api_v1 "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/api/v1"
devcontainer_dto "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/dto"
devcontainer_k8s_agent_modules_errors "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/errors"
apimachinery_apis_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apimachinery_apis_v1_unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
apimachinery_watch "k8s.io/apimachinery/pkg/watch"
dynamic_client "k8s.io/client-go/dynamic"
)
// CreateDevcontainer 创建开发容器
func CreateDevcontainer(ctx *context.Context, client dynamic_client.Interface, opts *devcontainer_dto.CreateDevcontainerOptions) (*devcontainer_api_v1.DevcontainerApp, error) {
if ctx == nil || opts == nil {
return nil, devcontainer_k8s_agent_modules_errors.ErrIllegalDevcontainerParameters{
FieldList: []string{"ctx", "opts"},
Message: "cannot be nil",
}
}
devcontainerApp := &devcontainer_api_v1.DevcontainerApp{
TypeMeta: apimachinery_apis_v1.TypeMeta{
Kind: "DevcontainerApp",
APIVersion: "devcontainer.devstar.cn/v1",
},
ObjectMeta: apimachinery_apis_v1.ObjectMeta{
Name: opts.Name,
Namespace: opts.Namespace,
},
Spec: devcontainer_api_v1.DevcontainerAppSpec{
StatefulSet: devcontainer_api_v1.StatefulSetSpec{
Image: opts.Image,
Command: opts.CommandList,
ContainerPort: opts.ContainerPort,
SSHPublicKeyList: opts.SSHPublicKeyList,
GitRepositoryURL: opts.GitRepositoryURL,
},
},
}
jsonData, err := json.Marshal(devcontainerApp)
if err != nil {
return nil, devcontainer_k8s_agent_modules_errors.ErrOperateDevcontainer{
Action: "Marshal JSON",
Message: err.Error(),
}
}
unstructuredObj := &apimachinery_apis_v1_unstructured.Unstructured{}
_, _, err = apimachinery_apis_v1_unstructured.UnstructuredJSONScheme.Decode(jsonData, &groupVersionKind, unstructuredObj)
if err != nil {
return nil, devcontainer_k8s_agent_modules_errors.ErrOperateDevcontainer{
Action: "build unstructured obj",
Message: err.Error(),
}
}
// 创建 DevContainer Status.nodePortAssigned 信息
_, err = client.Resource(groupVersionResource).Namespace(opts.Namespace).Create(*ctx, unstructuredObj, opts.CreateOptions)
if err != nil {
return nil, devcontainer_k8s_agent_modules_errors.ErrOperateDevcontainer{
Action: "create DevContainer via Dynamic Client",
Message: err.Error(),
}
}
// 注册 watcher 监听 DevContainer Status.nodePortAssigned 信息
watcherTimeoutSeconds := int64(3)
watcher, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Watch(*ctx, apimachinery_apis_v1.ListOptions{
FieldSelector: fmt.Sprintf("metadata.name=%s", opts.Name),
//Watch: false,
TimeoutSeconds: &watcherTimeoutSeconds,
Limit: 1,
})
if err != nil {
return nil, devcontainer_k8s_agent_modules_errors.ErrOperateDevcontainer{
Action: "register watcher of DevContainer NodePort",
Message: err.Error(),
}
}
defer watcher.Stop()
//log.Info(" ===== 开始监听 DevContainer NodePort 分配信息 =====")
var nodePortAssigned int64
for event := range watcher.ResultChan() {
switch event.Type {
case apimachinery_watch.Modified:
if devcontainerUnstructured, ok := event.Object.(*apimachinery_apis_v1_unstructured.Unstructured); ok {
statusDevcontainer, ok, err := apimachinery_apis_v1_unstructured.NestedMap(devcontainerUnstructured.Object, "status")
if err == nil && ok {
nodePortAssigned = statusDevcontainer["nodePortAssigned"].(int64)
if 30000 <= nodePortAssigned && nodePortAssigned <= 32767 {
devcontainerApp.Status.NodePortAssigned = uint16(nodePortAssigned)
//log.Info("DevContainer NodePort Status 更新完成,最新 NodePort = %v", nodePortAssigned)
//break
// 收到 NodePort Service MODIFIED 消息后,更新 NodePort直接返回不再处理后续 Event (否则必须超时3秒才得到 NodePort)
natRuleDescription := "DevContainer: " + devcontainerApp.Name
privatePort := uint64(nodePortAssigned)
publicPort := privatePort
err = devstar_cloud_provider.CreateNATRulePort(privatePort, publicPort, natRuleDescription)
return devcontainerApp, err
}
}
}
}
}
//log.Info(" ===== 结束监听 DevContainer NodePort 分配信息 =====")
/*
// 目前需要更新的字段只有 devcontainerInCluster.Status.NodePortAssigned
// 如果后续有其他较多的需要更新的字段,可以考虑重新查询,目前,暂时只考虑 直接更新内存缓存对象,然后返回即可
// 避免对 k8s API Server 造成访问压力
//response, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Get(*ctx, opts.Name, apimachinery_apis_v1.GetOptions{})
//jsonData, err = response.MarshalJSON()
//devcontainerInCluster := &devcontainer_api_v1.DevcontainerApp{}
//err = json.Unmarshal(jsonData, devcontainerInCluster)
//if err != nil {
// return nil, devcontainer_errors.ErrOperateDevcontainer{
// Action: "parse response result of in-cluster DevContainer",
// Message: err.Error(),
// }
//}
*/
// 如果执行到这里,说明 k8s 集群中 DevcontainerApp 初始化失败,比如执行下列命令查看出错原因如下:
// $ kubectl get pod -n devstar-studio-ns test-mockrepo1-6c5369588f8911e-0
// NAME READY STATUS RESTARTS AGE
// test-mockrepo1-6c5369588f8911e-0 0/1 Init:CrashLoopBackOff 1 (5s ago) 7s
// 需要删除刚刚创建的 k8s CRD然后返回 DevContainer 初始化失败
optsDeleteInitFailed := &devcontainer_dto.DeleteDevcontainerOptions{
Namespace: setting.Devstar.Devcontainer.Namespace,
Name: devcontainerApp.Name,
}
_ = DeleteDevcontainer(ctx, client, optsDeleteInitFailed)
return nil, errors.ErrOperateDevcontainer{
Action: "Initialize DevContainer",
Message: fmt.Sprintf("DevContainer %v failed to initialize and is thus purged.", devcontainerApp.Name),
}
}

repo.diff.view_file

@@ -1,29 +0,0 @@
package k8s_agent
import (
devcontainer_dto "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/dto"
devcontainer_errors "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/errors"
"code.gitea.io/gitea/modules/log"
"context"
"fmt"
dynamic_client "k8s.io/client-go/dynamic"
)
func DeleteDevcontainer(ctx *context.Context, client dynamic_client.Interface, opts *devcontainer_dto.DeleteDevcontainerOptions) error {
if ctx == nil || opts == nil || len(opts.Namespace) == 0 || len(opts.Name) == 0 {
return devcontainer_errors.ErrIllegalDevcontainerParameters{
FieldList: []string{"ctx", "opts", "opts.Name", "opts.Namespace"},
Message: "cannot be nil",
}
}
err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Delete(*ctx, opts.Name, opts.DeleteOptions)
if err != nil {
log.Warn("Failed to delete DevcontainerApp '%s' in namespace '%s': %s", opts.Name, opts.Namespace, err.Error())
return devcontainer_errors.ErrOperateDevcontainer{
Action: fmt.Sprintf("delete devcontainer '%s' in namespace '%s'", opts.Name, opts.Namespace),
Message: err.Error(),
}
}
return nil
}

repo.diff.view_file

@@ -1,159 +0,0 @@
package k8s_agent
import (
devcontainer_api_v1 "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/api/v1"
devcontainer_dto "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/dto"
devcontainer_errors "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/errors"
devcontainer_module_utils "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/utils"
devcontainer_agent_module_vo "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/vo"
"code.gitea.io/gitea/modules/setting"
"context"
"fmt"
apimachinery_api_metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apimachinery_apis_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apimachinery_apis_v1_unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
apimachinery_runtime_utils "k8s.io/apimachinery/pkg/runtime"
apimachinery_watch "k8s.io/apimachinery/pkg/watch"
dynamic_client "k8s.io/client-go/dynamic"
)
func GetDevcontainer(ctx *context.Context, client dynamic_client.Interface, opts *devcontainer_dto.GetDevcontainerOptions) (*devcontainer_api_v1.DevcontainerApp, error) {
// 0. 检查参数
if ctx == nil || opts == nil || len(opts.Namespace) == 0 || len(opts.Name) == 0 {
return nil, devcontainer_errors.ErrIllegalDevcontainerParameters{
FieldList: []string{"ctx", "opts", "opts.Name", "opts.Namespace"},
Message: "cannot be nil",
}
}
// 1. 获取 k8s CRD 资源 DevcontainerApp
devcontainerUnstructured, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Get(*ctx, opts.Name, opts.GetOptions)
if err != nil {
return nil, devcontainer_errors.ErrOperateDevcontainer{
Action: "Get DevcontainerApp thru k8s API Server",
Message: err.Error(),
}
}
// 2. 解析 DevcontainerApp Status 域,装填 VO
devcontainerApp := &devcontainer_api_v1.DevcontainerApp{}
err = apimachinery_runtime_utils.DefaultUnstructuredConverter.FromUnstructured(devcontainerUnstructured.Object, &devcontainerApp)
if err != nil {
return nil, devcontainer_errors.ErrOperateDevcontainer{
Action: "Convert k8s API Server unstructured response into DevcontainerApp",
Message: err.Error(),
}
}
// 3. 检查 Devcontainer 是否就绪
if !devcontainer_module_utils.IsK8sDevcontainerStatusReady(&devcontainerApp.Status) {
// 3.1 检查 Wait 参数,若用户不需要阻塞式等待,直接返回 “DevContainer 未就绪” 错误
if opts.Wait == false {
return nil, devcontainer_errors.ErrK8sDevcontainerNotReady{
Name: opts.Name,
Namespace: opts.Namespace,
Wait: opts.Wait,
}
}
// 3.2 执行阻塞式等待
devcontainerStatusVO, err := waitUntilDevcontainerReadyWithTimeout(ctx, client, opts)
if err != nil {
return nil, devcontainer_errors.ErrOperateDevcontainer{
Action: "wait for k8s DevContainer to be ready",
Message: err.Error(),
}
}
devcontainerApp.Status.Ready = devcontainerStatusVO.Ready
devcontainerApp.Status.NodePortAssigned = devcontainerStatusVO.NodePortAssigned
}
// 4. 将就绪的 DevContainer Status VO 返回
return devcontainerApp, nil
}
// waitUntilDevcontainerReadyWithTimeout 辅助方法:在超时时间内阻塞等待 DevContainer 就绪
func waitUntilDevcontainerReadyWithTimeout(ctx *context.Context, client dynamic_client.Interface, opts *devcontainer_dto.GetDevcontainerOptions) (*devcontainer_agent_module_vo.DevcontainerStatusK8sAgentVO, error) {
// 0. 检查参数
if ctx == nil || client == nil || opts == nil || len(opts.Name) == 0 || len(opts.Namespace) == 0 {
return nil, devcontainer_errors.ErrIllegalDevcontainerParameters{
FieldList: []string{"ctx", "client", "opts", "opts.Name", "opts.Namespace"},
Message: "could not be nil",
}
}
// 1. 注册 watcher 监听 DevContainer Status 变化
watcherTimeoutSeconds := setting.Devstar.Devcontainer.TimeoutSeconds
watcher, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).Watch(*ctx, apimachinery_apis_v1.ListOptions{
FieldSelector: fmt.Sprintf("metadata.name=%s", opts.Name),
Watch: true,
TimeoutSeconds: &watcherTimeoutSeconds,
})
if err != nil {
return nil, devcontainer_errors.ErrOperateDevcontainer{
Action: "register watcher of DevContainer Readiness",
Message: err.Error(),
}
}
defer watcher.Stop()
// 2. 当 DevContainer Watcher 事件处理
devcontainerStatusVO := &devcontainer_agent_module_vo.DevcontainerStatusK8sAgentVO{}
for event := range watcher.ResultChan() {
switch event.Type {
case apimachinery_watch.Added:
// 2.1 监听 DevcontainerApp ADDED 事件,直接 fallthrough 到 MODIFIED 事件合并处理
fallthrough
case apimachinery_watch.Modified:
// 2.2 监听 DevcontainerApp MODIFIED 事件
if devcontainerUnstructured, ok := event.Object.(*apimachinery_apis_v1_unstructured.Unstructured); ok {
// 2.2.1 解析 status 域
statusDevcontainer, ok, err := apimachinery_apis_v1_unstructured.NestedMap(devcontainerUnstructured.Object, "status")
if err == nil && ok {
devcontainerCurrentStatus := &devcontainer_api_v1.DevcontainerAppStatus{
Ready: statusDevcontainer["ready"].(bool),
NodePortAssigned: uint16(statusDevcontainer["nodePortAssigned"].(int64)),
}
// 2.2.2 当 Status 达到就绪状态后,返回
if devcontainer_module_utils.IsK8sDevcontainerStatusReady(devcontainerCurrentStatus) {
devcontainerStatusVO.Ready = devcontainerCurrentStatus.Ready
devcontainerStatusVO.NodePortAssigned = devcontainerCurrentStatus.NodePortAssigned
return devcontainerStatusVO, nil
}
}
}
case apimachinery_watch.Error:
// 2.3 监听 DevcontainerApp ERROR 事件,返回报错信息
apimachineryApiMetav1Status, ok := event.Object.(*apimachinery_api_metav1.Status)
if !ok {
return nil, devcontainer_errors.ErrOperateDevcontainer{
Action: fmt.Sprintf("wait for Devcontainer '%s' in namespace '%s' to be ready", opts.Name, opts.Namespace),
Message: fmt.Sprintf("An error occurred in k8s CRD DevcontainerApp Watcher: \n"+
" Code: %v (status = %v)\n"+
"Message: %v\n"+
" Reason: %v\n"+
"Details: %v",
apimachineryApiMetav1Status.Code, apimachineryApiMetav1Status.Status,
apimachineryApiMetav1Status.Message,
apimachineryApiMetav1Status.Reason,
apimachineryApiMetav1Status.Details),
}
}
case apimachinery_watch.Deleted:
// 2.4 监听 DevcontainerApp DELETED 事件,返回报错信息
return nil, devcontainer_errors.ErrOperateDevcontainer{
Action: fmt.Sprintf("Open DevContainer '%s' in namespace '%s'", opts.Name, opts.Namespace),
Message: fmt.Sprintf("'%s' of Kind DevcontainerApp has been Deleted", opts.Name),
}
}
}
// 3. k8s CRD DevcontainerApp Watcher 超时关闭处理:直接返回超时错误
return nil, devcontainer_errors.ErrOpenDevcontainerTimeout{
Name: opts.Name,
Namespace: opts.Namespace,
TimeoutSeconds: setting.Devstar.Devcontainer.TimeoutSeconds,
}
}

repo.diff.view_file

@@ -1,48 +0,0 @@
package k8s_agent
import (
"context"
"encoding/json"
"fmt"
dynamic_client "k8s.io/client-go/dynamic"
devcontainer_api_v1 "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/api/v1"
devcontainer_dto "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/dto"
devcontainer_errors "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/errors"
)
// ListDevcontainers 根据条件列举 DevContainer
func ListDevcontainers(ctx *context.Context, client dynamic_client.Interface, opts *devcontainer_dto.ListDevcontainersOptions) (*devcontainer_api_v1.DevcontainerAppList, error) {
if ctx == nil || opts == nil || len(opts.Namespace) == 0 {
return nil, devcontainer_errors.ErrIllegalDevcontainerParameters{
FieldList: []string{"ctx", "namespace"},
Message: "cannot be empty",
}
}
list, err := client.Resource(groupVersionResource).Namespace(opts.Namespace).List(*ctx, opts.ListOptions)
if err != nil {
return nil, devcontainer_errors.ErrOperateDevcontainer{
Action: fmt.Sprintf("List Devcontainer in namespace '%s'", opts.Namespace),
Message: err.Error(),
}
}
// JSON 反序列化为 DevcontainerAppList
jsonData, err := list.MarshalJSON()
if err != nil {
return nil, devcontainer_errors.ErrOperateDevcontainer{
Action: "verify JSON data of Devcontainer List",
Message: err.Error(),
}
}
devcontainerList := &devcontainer_api_v1.DevcontainerAppList{}
if err := json.Unmarshal(jsonData, devcontainerList); err != nil {
return nil, devcontainer_errors.ErrOperateDevcontainer{
Action: "deserialize Devcontainer List data",
Message: err.Error(),
}
}
return devcontainerList, nil
}

repo.diff.view_file

@@ -1,19 +0,0 @@
package dto
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// CreateDevcontainerOptions 定义创建开发容器选项
type CreateDevcontainerOptions struct {
metav1.CreateOptions
Name string `json:"name"`
Namespace string `json:"namespace"`
Image string `json:"image"`
CommandList []string `json:"command"`
ContainerPort uint16 `json:"containerPort"`
ServicePort uint16 `json:"servicePort"`
SSHPublicKeyList []string `json:"sshPublicKeyList"`
GitRepositoryURL string `json:"gitRepositoryURL"`
}

repo.diff.view_file

@@ -1,12 +0,0 @@
package dto
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type DeleteDevcontainerOptions struct {
metav1.DeleteOptions
Name string `json:"name"`
Namespace string `json:"namespace"`
}

repo.diff.view_file

@@ -1,11 +0,0 @@
package dto
import metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
type GetDevcontainerOptions struct {
metav1.GetOptions
Name string `json:"name"`
Namespace string `json:"namespace"`
Wait bool `json:"wait"`
}

repo.diff.view_file

@@ -1,11 +0,0 @@
package dto
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type ListDevcontainersOptions struct {
metav1.ListOptions
Namespace string `json:"namespace"`
}

repo.diff.view_file

@@ -1,14 +0,0 @@
package errors
import (
"fmt"
)
type ErrIllegalDevcontainerParameters struct {
FieldList []string
Message string
}
func (err ErrIllegalDevcontainerParameters) Error() string {
return fmt.Sprintf("Illegal DevContainer parameters detected: %v (%s)", err.FieldList, err.Message)
}

repo.diff.view_file

@@ -1,16 +0,0 @@
package errors
import (
"fmt"
)
type ErrK8sDevcontainerNotReady struct {
Name string
Namespace string
Wait bool
}
func (err ErrK8sDevcontainerNotReady) Error() string {
return fmt.Sprintf("Failed to open k8s Devcontainer '%s' in namespace '%s': DevContainer Not Ready (Wait = %v)",
err.Name, err.Namespace, err.Wait)
}

repo.diff.view_file

@@ -1,18 +0,0 @@
package errors
import (
"fmt"
)
// ErrOpenDevcontainerTimeout 阻塞式等待 DevContainer 超时
type ErrOpenDevcontainerTimeout struct {
Name string
Namespace string
TimeoutSeconds int64
}
func (err ErrOpenDevcontainerTimeout) Error() string {
return fmt.Sprintf("Failed to open DevContainer '%s' in namespace '%s': waiting timeout limit of %d seconds has been exceeded.",
err.Name, err.Namespace, err.TimeoutSeconds,
)
}

repo.diff.view_file

@@ -1,14 +0,0 @@
package errors
import (
"fmt"
)
type ErrOperateDevcontainer struct {
Action string
Message string
}
func (err ErrOperateDevcontainer) Error() string {
return fmt.Sprintf("Failed to %v in DevStar DevContainer DB: %v", err.Action, err.Message)
}

repo.diff.view_file

@@ -1,19 +0,0 @@
package k8s_agent
import (
devcontainer_api_v1 "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/api/v1"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// groupVersionResource 用于描述 CRD供 dynamic Client 交互使用
var groupVersionResource = schema.GroupVersionResource{
Group: devcontainer_api_v1.GroupVersion.Group,
Version: devcontainer_api_v1.GroupVersion.Version,
Resource: "devcontainerapps",
}
var groupVersionKind = schema.GroupVersionKind{
Group: devcontainer_api_v1.GroupVersion.Group,
Version: devcontainer_api_v1.GroupVersion.Version,
Kind: "DevcontainerApp",
}

repo.diff.view_file

@@ -1,34 +0,0 @@
package k8s_agent
import (
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"context"
dynamicclient "k8s.io/client-go/dynamic"
clientgorest "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientgocmdtools "k8s.io/client-go/tools/clientcmd"
)
// GetKubernetesClient
func GetKubernetesClient(ctx *context.Context) (dynamicclient.Interface, error) {
// 1.0 尝试从集群外获取 kubectl 配置信息
config, err := clientcmd.BuildConfigFromFlags("", clientgocmdtools.RecommendedHomeFile)
if err != nil {
// 1.1 集群外尝试失败,改从集群内获取 kubectl 配置信息
log.Warn("Failed to obtain Kubernetes config outside of cluster: " + clientgocmdtools.RecommendedHomeFile)
config, err = clientgorest.InClusterConfig()
if err != nil {
log.Error("Failed to obtain Kubernetes config both inside/outside of cluster, the DevContainer is Disabled")
setting.Devstar.Devcontainer.Enabled = false
return nil, err
}
}
// 2. 根据 k8s 配置信息构建 ClientSet
dynamicClient, err := dynamicclient.NewForConfig(config)
if err != nil {
return nil, err
}
return dynamicClient, err
}

repo.diff.view_file

@@ -1,15 +0,0 @@
package utils
import (
devcontainer_api_v1 "code.gitea.io/gitea/modules/devstar_devcontainer/k8s_agent/api/v1"
)
// IsK8sDevcontainerStatusReady 工具类方法,判断给定的 DevcontainerApp.Status 是否达到就绪状态
// 1. DevcontainerApp.Status.Ready == true
// 2. DevcontainerApp.Status.NodePortAssigned 介于闭区间 [30000, 32767]
func IsK8sDevcontainerStatusReady(devcontainerAppStatus *devcontainer_api_v1.DevcontainerAppStatus) bool {
return devcontainerAppStatus != nil &&
devcontainerAppStatus.Ready &&
devcontainerAppStatus.NodePortAssigned >= 30000 &&
devcontainerAppStatus.NodePortAssigned <= 32767
}

repo.diff.view_file

@@ -1,9 +0,0 @@
package vo
type DevcontainerStatusK8sAgentVO struct {
// CRD Controller 向 DevcontainerApp.Status.NodePortAssigned 写入了最新的 NodePort 端口值,当且仅当 Service 被调度且分配了最新的 NodePort
NodePortAssigned uint16 `json:"nodePortAssigned"`
// CRD Controller 向 DevcontainerApp.Status.Ready 写入了 true当且仅当 StatefulSet 控制下的 Pod 中的 Readiness Probe 返回 true
Ready bool `json:"ready"`
}

repo.diff.view_file

@@ -0,0 +1,333 @@
package docker
import (
"archive/tar"
"context"
"fmt"
"net"
"os"
"os/exec"
"path/filepath"
"strings"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy"
)
func CreateDockerClient(ctx *context.Context) (*client.Client, error) {
log.Info("检查 Docker 环境")
// 1. 检查 Docker 环境
dockerSocketPath, err := GetDockerSocketPath()
if err != nil {
return nil, err
}
log.Info("dockerSocketPath: %s", dockerSocketPath)
// 2. 创建docker client 并且检查是否运行
cli, err := checkIfDockerRunning(*ctx, dockerSocketPath)
if err != nil {
return nil, err
}
return cli, nil
}
var commonSocketPaths = []string{
"/var/run/docker.sock",
"/run/podman/podman.sock",
"$HOME/.colima/docker.sock",
"$XDG_RUNTIME_DIR/docker.sock",
"$XDG_RUNTIME_DIR/podman/podman.sock",
`\\.\pipe\docker_engine`,
"$HOME/.docker/run/docker.sock",
}
// 优先级配置文件的DockerHost字段 > DOCKER_HOST环境变量 > docker普通默认路径
func GetDockerSocketPath() (string, error) {
// 校验DockerHost配置
if setting.Devcontainer.DockerHost != "" && net.ParseIP(setting.Devcontainer.DockerHost) != nil {
return setting.Devcontainer.DockerHost, nil
}
// 检查环境变量
socket, found := os.LookupEnv("DOCKER_HOST")
if found {
return socket, nil
}
// 测试Docker默认路径
for _, p := range commonSocketPaths {
if _, err := os.Lstat(os.ExpandEnv(p)); err == nil {
if strings.HasPrefix(p, `\\.\`) {
return "npipe://" + filepath.ToSlash(os.ExpandEnv(p)), nil
}
return "unix://" + filepath.ToSlash(os.ExpandEnv(p)), nil
}
}
return "", fmt.Errorf("Docker未安装")
}
func checkIfDockerRunning(ctx context.Context, configDockerHost string) (*client.Client, error) {
opts := []client.Opt{
client.FromEnv,
}
if configDockerHost != "" {
opts = append(opts, client.WithHost(configDockerHost))
}
cli, err := client.NewClientWithOpts(opts...)
if err != nil {
return nil, err
}
_, err = cli.Ping(ctx)
if err != nil {
return nil, fmt.Errorf("docker未运行, %w", err)
}
return cli, nil
}
// 获取容器端口映射到了主机哪个端口,参数: DockerClient、containerID、容器端口号
func GetMappedPort(cli *client.Client, containerID string, port string) (string, error) {
// 获取容器详细信息
containerJSON, err := cli.ContainerInspect(context.Background(), containerID)
if err != nil {
return "", err
}
// 获取端口映射信息
portBindings := containerJSON.NetworkSettings.Ports
for containerPort, bindings := range portBindings {
for _, binding := range bindings {
log.Info("容器端口 %s 映射到主机 %s 端口 %s \n", containerPort, binding.HostIP, binding.HostPort)
if containerPort.Port() == port {
return binding.HostPort, nil
}
}
}
return "", fmt.Errorf("容器未开放端口" + port)
}
func GetAllMappedPort(cli *client.Client, containerID string) (string, error) {
var result string = "\n"
// 获取容器详细信息
containerJSON, err := cli.ContainerInspect(context.Background(), containerID)
if err != nil {
return "", err
}
// 获取端口映射信息
portBindings := containerJSON.NetworkSettings.Ports
for containerPort, bindings := range portBindings {
for _, binding := range bindings {
result += fmt.Sprintf("容器端口 %s 映射到主机 %s 端口 %s \n", containerPort, binding.HostIP, binding.HostPort)
}
}
return result, nil
}
func PushImage(dockerHost string, username string, password string, registryUrl string, imageRef string) error {
script := "docker " + "-H " + dockerHost + " login -u " + username + " -p " + password + " " + registryUrl + " "
cmd := exec.Command("sh", "-c", script)
_, err := cmd.CombinedOutput()
if err != nil {
return err
}
// 推送到仓库
script = "docker " + "-H " + dockerHost + " push " + imageRef
cmd = exec.Command("sh", "-c", script)
_, err = cmd.CombinedOutput()
if err != nil {
return err
}
return nil
}
func GetContainerID(cli *client.Client, containerName string) (string, error) {
containerJSON, err := cli.ContainerInspect(context.Background(), containerName)
if err != nil {
return "", err
}
return containerJSON.ID, nil
}
func GetContainerStatus(cli *client.Client, containerID string) (string, error) {
containerInfo, err := cli.ContainerInspect(context.Background(), containerID)
if err != nil {
return "", err
}
state := containerInfo.State
return state.Status, nil
}
func ExecCommandInContainer(ctx *context.Context, cli *client.Client, containerID string, command string) (string, error) {
cmdList := []string{"sh", "-c", command}
execConfig := types.ExecConfig{
Cmd: cmdList,
AttachStdout: true,
AttachStderr: true,
}
// 创建执行实例
exec, err := cli.ContainerExecCreate(context.Background(), containerID, execConfig)
if err != nil {
log.Info("创建执行实例失败", err)
return "", err
}
// 附加到执行实例
resp, err := cli.ContainerExecAttach(context.Background(), exec.ID, types.ExecStartCheck{})
if err != nil {
log.Info("命令附加到执行实例失败", err)
return "", err
}
defer resp.Close()
// 启动执行实例
err = cli.ContainerExecStart(context.Background(), exec.ID, types.ExecStartCheck{})
if err != nil {
log.Info("启动执行实例失败", err)
return "", err
}
// 自定义缓冲区
var outBuf, errBuf strings.Builder
// 读取输出
_, err = stdcopy.StdCopy(&outBuf, &errBuf, resp.Reader)
if err != nil {
log.Info("Error reading output for command %v: %v\n", command, err)
return "", err
}
return outBuf.String() + errBuf.String(), nil
}
func DeleteContainer(cli *client.Client, containerID string) error {
// 删除容器
options := types.ContainerRemoveOptions{
Force: true, // 强制删除正在运行的容器
RemoveVolumes: true, // 删除数据卷
RemoveLinks: false, // 删除链接(已弃用)
}
if err := cli.ContainerRemove(context.Background(), containerID, options); err != nil {
log.Info("删除 %s 容器失败: %v", containerID, err)
return err
}
log.Info("容器 %s 已成功删除\n", containerID)
return nil
}
// pullImage 用于拉取指定的 Docker 镜像
func PullImageSync(cli *client.Client, dockerHost string, image string) error {
script := "docker " + "-H " + dockerHost + " pull " + image
cmd := exec.Command("sh", "-c", script)
output, err := cmd.CombinedOutput()
log.Info(string(output))
if err != nil {
return err
}
return nil
}
func CreateAndStartContainer(cli *client.Client, opts *CreateDevcontainerOptions) error {
ctx := context.Background()
// 创建容器配置
config := &container.Config{
Image: opts.Image,
Cmd: opts.CommandList,
Env: opts.ContainerEnv,
AttachStdout: true,
AttachStderr: true,
Tty: true,
OpenStdin: true,
ExposedPorts: opts.ForwardPorts,
}
// 设置容器配置
hostConfig := &container.HostConfig{
//Hosts
//ExtraHosts: []string{"host.docker.internal:" + host},
PublishAllPorts: true,
Binds: nil,
RestartPolicy: container.RestartPolicy{
Name: "always",
},
PortBindings: opts.PortBindings,
}
if len(opts.Binds) > 0 {
hostConfig.Binds = opts.Binds
}
// 创建容器
resp, err := cli.ContainerCreate(ctx, config, hostConfig, nil, nil, opts.Name)
if err != nil {
log.Info("fail to create container %v", err)
return err
}
// 启动容器
err = cli.ContainerStart(ctx, resp.ID, types.ContainerStartOptions{})
if err != nil {
log.Info("fail to start container %v", err)
return err
}
return nil
}
// addFileToTar 将文件添加到 tar 归档
func addFileToTar(tw *tar.Writer, filename string, content string, mode int64) error {
hdr := &tar.Header{
Name: filename,
Mode: mode,
Size: int64(len(content)),
}
if err := tw.WriteHeader(hdr); err != nil {
return err
}
if _, err := tw.Write([]byte(content)); err != nil {
return err
}
return nil
}
// ImageExists 检查指定镜像是否存在
// 返回值:
// - bool: 镜像是否存在true=存在false=不存在)
// - error: 非空表示检查过程中发生错误
func ImageExists(imageName string) (bool, error) {
// 上下文
ctx := context.Background()
// 创建 Docker 客户端
cli, err := CreateDockerClient(&ctx)
if err != nil {
return false, err // 其他错误
}
// 获取镜像信息
_, _, err = cli.ImageInspectWithRaw(ctx, imageName)
if err != nil {
return false, err // 其他错误
}
return true, nil // 镜像存在
}
func CheckDirExists(cli *client.Client, containerID, dirPath string) (bool, error) {
// 创建 exec 配置
execConfig := types.ExecConfig{
Cmd: []string{"test", "-d", dirPath}, // 检查目录是否存在
AttachStdout: true,
AttachStderr: true,
}
// 创建 exec 实例
execResp, err := cli.ContainerExecCreate(context.Background(), containerID, execConfig)
if err != nil {
return false, fmt.Errorf("创建 exec 实例失败: %v", err)
}
// 执行命令
var exitCode int
err = cli.ContainerExecStart(context.Background(), execResp.ID, types.ExecStartCheck{})
if err != nil {
return false, fmt.Errorf("启动 exec 命令失败: %v", err)
}
// 获取命令执行结果
resp, err := cli.ContainerExecInspect(context.Background(), execResp.ID)
if err != nil {
return false, fmt.Errorf("获取 exec 结果失败: %v", err)
}
exitCode = resp.ExitCode
return exitCode == 0, nil // 退出码为 0 表示目录存在
}

repo.diff.view_file

@@ -0,0 +1,25 @@
package docker
import (
"github.com/docker/go-connections/nat"
)
// CreateDevcontainerOptions 定义创建开发容器选项
type CreateDevcontainerOptions struct {
DockerfileContent string
Name string `json:"name"`
Namespace string `json:"namespace"`
Image string `json:"image"`
CommandList []string `json:"command"`
ContainerPort uint16 `json:"containerPort"`
ServicePort uint16 `json:"servicePort"`
SSHPublicKeyList []string `json:"sshPublicKeyList"`
GitRepositoryURL string `json:"gitRepositoryURL"`
RepoId int64
UserId int64
ForwardPorts nat.PortSet
ContainerEnv []string
PostCreateCommand []string
Binds []string
PortBindings nat.PortMap
}

repo.diff.view_file

@@ -27,7 +27,7 @@ func TestGetRefURL(t *testing.T) {
{"ssh://git@try.gitea.io:9999/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "", "https://try.gitea.io/go-gitea/gitea"},
{"git://git@try.gitea.io:9999/go-gitea/gitea", "https://try.gitea.io/", "go-gitea/sdk", "", "https://try.gitea.io/go-gitea/gitea"},
{"ssh://git@127.0.0.1:9999/go-gitea/gitea", "https://127.0.0.1:3000/", "go-gitea/sdk", "", "https://127.0.0.1:3000/go-gitea/gitea"},
{"https://gitea.com:3000/user1/repo1.git", "https://127.0.0.1:3000/", "user/repo2", "", "https://gitea.com:3000/user1/repo1"},
{"https://gitea.cn:3000/user1/repo1.git", "https://127.0.0.1:3000/", "user/repo2", "", "https://gitea.cn:3000/user1/repo1"},
{"https://example.gitea.com/gitea/user1/repo1.git", "https://example.gitea.com/gitea/", "", "user/repo2", "https://example.gitea.com/gitea/user1/repo1"},
{"https://username:password@github.com/username/repository.git", "/", "username/repository2", "", "https://username:password@github.com/username/repository"},
{"somethingbad", "https://127.0.0.1:3000/go-gitea/gitea", "/", "", ""},

repo.diff.view_file

@@ -142,7 +142,7 @@ func Valid(data []byte) bool {
return json.Valid(data)
}
// UnmarshalHandleDoubleEncode - due to a bug in xorm (see https://gitea.com/xorm/xorm/pulls/1957) - it's
// UnmarshalHandleDoubleEncode - due to a bug in xorm (see https://gitea.cn/xorm/xorm/pulls/1957) - it's
// possible that a Blob may be double encoded or gain an unwanted prefix of 0xff 0xfe.
func UnmarshalHandleDoubleEncode(bs []byte, v any) error {
err := json.Unmarshal(bs, v)

repo.diff.view_file

@@ -0,0 +1,44 @@
FROM golang:1.23 AS builder
WORKDIR /workspace
# 创建临时目录结构
RUN mkdir -p modules/k8s
# Copy the Go Modules manifests
COPY go.mod go.mod
COPY go.sum go.sum
# 禁用所有代理
ENV HTTP_PROXY=""
ENV HTTPS_PROXY=""
ENV http_proxy=""
ENV https_proxy=""
ENV GOPROXY=https://goproxy.cn,direct
# 下载依赖
RUN go mod download
# Copy the Go source code
COPY modules/k8s/ modules/k8s/
# Build the controller-manager binary
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o controller-manager modules/k8s/cmd/controller-manager/controller-manager.go
# Build a small image
FROM alpine:3.18
WORKDIR /
# 创建非 root 用户
RUN addgroup -g 65532 nonroot && \
adduser -u 65532 -G nonroot -D nonroot
COPY --from=builder /workspace/modules/k8s/controller/ modules/k8s/controller/
COPY --from=builder /workspace/controller-manager .
USER 65532:65532
ENTRYPOINT ["/controller-manager"]
# $ docker build -t devstar-controller-manager:latest -f modules/k8s/Dockerfile.controller-manager .

18
modules/k8s/README.md Normal file
repo.diff.view_file

@@ -0,0 +1,18 @@
# DevStar Controller Manager
本目录包含 DevStar Controller Manager 的源代码和构建所需的 Dockerfile。Controller Manager 负责管理 Kubernetes 中的 DevContainer 自定义资源。
## 构建 Docker 镜像
### 构建方法
由于项目结构原因,构建 Docker 镜像必须从项目根目录执行:
```bash
# 切换到项目根目录make docker 或者 使用如下命令单独构建devstar-controller-manager镜像
docker build -t devstar-controller-manager:latest -f modules/k8s/Dockerfile.controller-manager .
# 合并代码时由CI脚本负责构建和推送镜像devstar.cn/devstar/devstar-controller-manager:latest
```
此镜像由devstar的helm chart的子chart devstar-controller-manager使用若要使用新的镜像请修改helm chart中的values.yaml

repo.diff.view_file

@@ -24,6 +24,39 @@ import (
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized.
// ExtraPortSpec 定义额外端口配置
type ExtraPortSpec struct {
// Name 是端口的名称
// +optional
Name string `json:"name,omitempty"`
// ContainerPort 是容器内的端口号
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=65535
ContainerPort uint16 `json:"containerPort"`
// ServicePort 是服务暴露的端口号
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=65535
ServicePort uint16 `json:"servicePort"`
}
// ExtraPortAssigned 定义已分配的额外端口信息
type ExtraPortAssigned struct {
// Name 是端口的名称
// +optional
Name string `json:"name,omitempty"`
// ContainerPort 是容器内的端口号
ContainerPort uint16 `json:"containerPort"`
// ServicePort 是服务暴露的端口号
ServicePort uint16 `json:"servicePort"`
// NodePort 是 Kubernetes 分配的 NodePort
NodePort uint16 `json:"nodePort"`
}
// DevcontainerAppSpec defines the desired state of DevcontainerApp
type DevcontainerAppSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
@@ -86,6 +119,10 @@ type ServiceSpec struct {
// +kubebuilder:validation:Minimum=1
// +optional
ServicePort uint16 `json:"servicePort,omitempty"`
// ExtraPorts 定义额外的端口配置
// +optional
ExtraPorts []ExtraPortSpec `json:"extraPorts,omitempty"`
}
// DevcontainerAppStatus defines the observed state of DevcontainerApp
@@ -105,6 +142,10 @@ type DevcontainerAppStatus struct {
// +optional
NodePortAssigned uint16 `json:"nodePortAssigned"`
// ExtraPortsAssigned 存储额外端口映射的 NodePort
// +optional
ExtraPortsAssigned []ExtraPortAssigned `json:"extraPortsAssigned,omitempty"`
// Ready 标识 DevcontainerApp 管理的 Pod 的 Readiness Probe 是否达到就绪状态
// +optional
Ready bool `json:"ready"`
@@ -130,3 +171,7 @@ type DevcontainerAppList struct {
metav1.ListMeta `json:"metadata,omitempty"`
Items []DevcontainerApp `json:"items"`
}
func init() {
SchemeBuilder.Register(&DevcontainerApp{}, &DevcontainerAppList{})
}

repo.diff.view_file

@@ -21,9 +21,16 @@ package v1
import (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
var (
// GroupVersion is group version used to register these objects
GroupVersion = schema.GroupVersion{Group: "devcontainer.devstar.cn", Version: "v1"}
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}
// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)

repo.diff.too_many_files repo.diff.show_more