Compare commits
63 Commits
feature/ap
...
tests
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c181be2292 | ||
|
|
49009eb9a2 | ||
|
|
0ea42c04f5 | ||
|
|
3567148061 | ||
|
|
8e5edc714f | ||
|
|
ac1d22708f | ||
|
|
d22a2f30c2 | ||
|
|
67d8b8b36d | ||
|
|
8de8c86976 | ||
|
|
1f16d76d96 | ||
|
|
decbb3336e | ||
|
|
adcddd551e | ||
|
|
63fb8120c9 | ||
|
|
dd60ca2100 | ||
|
|
2795a67741 | ||
|
|
641a76b773 | ||
|
|
c3b8d4612b | ||
|
|
6ffbe8d5e4 | ||
|
|
a57ed29d28 | ||
|
|
50d912e652 | ||
|
|
bab3befa45 | ||
|
|
166113b07d | ||
|
|
74b0fb4912 | ||
|
|
ed573cc83b | ||
|
|
96005ac630 | ||
|
|
e1137bd7c3 | ||
|
|
04b17516e4 | ||
|
|
0acecaad5f | ||
|
|
80276e54f9 | ||
|
|
72dfb0aeaf | ||
|
|
15a471f247 | ||
|
|
d1187fd712 | ||
|
|
b3e31dcefd | ||
|
|
65e7506979 | ||
|
|
b80c358fda | ||
|
|
3d678a982b | ||
|
|
c03be52914 | ||
|
|
cfffaa1960 | ||
|
|
dfcf75d7d1 | ||
|
|
7d06daf606 | ||
|
|
5e2987d135 | ||
|
|
8d1f62028c | ||
|
|
446e343eab | ||
|
|
109fdd8136 | ||
|
|
b3fe3a78e0 | ||
|
|
c6ad67556b | ||
|
|
5918d57139 | ||
|
|
6b4feabe81 | ||
|
|
fb1637a0f4 | ||
|
|
1fc326dbae | ||
|
|
25ebc112d1 | ||
|
|
5cba473dd8 | ||
|
|
087519a372 | ||
|
|
a556d823e2 | ||
|
|
b0ec1135c0 | ||
|
|
257941c5e5 | ||
|
|
16c817fa9b | ||
|
|
d3f24edcbc | ||
|
|
a99c05bd6e | ||
|
|
38908ac0aa | ||
|
|
b33e4adbe1 | ||
|
|
cc7f5ccff9 | ||
|
|
4d4faf5103 |
@@ -60,6 +60,9 @@ cpu.out
|
||||
/tests/e2e/reports
|
||||
/tests/e2e/test-artifacts
|
||||
/tests/e2e/test-snapshots
|
||||
/tests/e2e/test-data
|
||||
/tests/e2e/package-lock.json
|
||||
/tests/e2e/node_modules/
|
||||
/tests/*.ini
|
||||
/node_modules
|
||||
/yarn.lock
|
||||
|
||||
82
.gitea/workflows/devstar-studio-e2e.yaml
Normal file
@@ -0,0 +1,82 @@
|
||||
name: DevStar E2E Test
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize]
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
jobs:
|
||||
e2e-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out repository code
|
||||
uses: actions/checkout@v4
|
||||
- name: build Devstar Image
|
||||
run: |
|
||||
make devstar
|
||||
- name: Install Network Tools
|
||||
run: |
|
||||
echo "正在安装 ip 命令..."
|
||||
sudo apt-get update && sudo apt-get install -y iproute2
|
||||
- name: start DevStar Container
|
||||
run: |
|
||||
# 启动容器,这里的话需要预先的创建宿主机的对应文件夹
|
||||
LOGS=$(public/assets/install.sh start \
|
||||
--port=8082 \
|
||||
--ssh-port=2224 \
|
||||
--data-dir=/tmp/devstar_ci \
|
||||
--image=devstar-studio:latest 2>&1)
|
||||
echo "$LOGS"
|
||||
TARGET_URL=$(echo "$LOGS" | grep -o 'http://[^ ]*' | tail -1 | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[mGK]//g")
|
||||
echo "TARGET_URL=$TARGET_URL" >> $GITHUB_ENV
|
||||
- name: Run E2E Tests
|
||||
run: |
|
||||
make e2e-test TARGET_URL="$TARGET_URL"
|
||||
env:
|
||||
GITEA_I_AM_BEING_UNSAFE_RUNNING_AS_ROOT: "true"
|
||||
- name: Upload E2E Test Report
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: e2e-test-report
|
||||
path: tests/e2e/reports/
|
||||
- name: Post Test Results
|
||||
if: always() && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v6
|
||||
env:
|
||||
# 传入任务状态,success 或 failure
|
||||
TEST_RESULT: ${{ job.status }}
|
||||
with:
|
||||
script: |
|
||||
const testResult = process.env.TEST_RESULT || '未知';
|
||||
const isSuccess = testResult === 'success';
|
||||
|
||||
// 动态生成构建链接
|
||||
const runUrl = `${context.payload.repository.html_url}/actions/runs/${context.runId}`;
|
||||
|
||||
const comment = `
|
||||
## 📋 E2E 测试结果报告
|
||||
|
||||
### 测试状态
|
||||
${isSuccess ? '✅ **通过 (Passed)**' : '❌ **失败 (Failed)**'}
|
||||
|
||||
### 🔍 详细报告
|
||||
HTML 报告已上传至 Artifacts,请点击下方链接查看。
|
||||
👉 [查看运行日志与下载报告](${runUrl})
|
||||
|
||||
### 🏗️ 构建信息
|
||||
- **工作流**: ${context.workflow}
|
||||
- **提交**: ${context.payload.pull_request.head.sha.slice(0, 7)}
|
||||
- **触发者**: @${context.actor}
|
||||
|
||||
---
|
||||
> *此评论由 DevStar Actions 自动生成,用于 PR 质量检查。*
|
||||
`;
|
||||
|
||||
// 发送评论
|
||||
github.rest.issues.createComment({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: comment
|
||||
});
|
||||
3
.gitignore
repo.diff.vendored
@@ -69,6 +69,9 @@ cpu.out
|
||||
/tests/e2e/gitea-e2e-*
|
||||
/tests/e2e/indexers-*
|
||||
/tests/e2e/reports
|
||||
/tests/e2e/node_modules/
|
||||
/tests/e2e/package-lock.json
|
||||
/tests/e2e/test-data
|
||||
/tests/e2e/test-artifacts
|
||||
/tests/e2e/test-snapshots
|
||||
/tests/*.ini
|
||||
|
||||
9
Makefile
@@ -963,11 +963,16 @@ devstar:
|
||||
echo "Successfully build devstar.cn/devstar/devstar-runtime-container:latest"; \
|
||||
fi
|
||||
docker build -t devstar-studio:latest -f docker/Dockerfile.devstar .
|
||||
|
||||
.PHONY: docker
|
||||
docker:
|
||||
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" .
|
||||
# support also build args docker build --build-arg GITEA_VERSION=v1.2.3 --build-arg TAGS="bindata sqlite sqlite_unlock_notify"
|
||||
|
||||
.PHONY: e2e-test
|
||||
e2e-test:
|
||||
@echo "正在启动E2E-TEST..."
|
||||
@TARGET_URL=$(TARGET_URL) E2E_USERNAME=$(E2E_USERNAME) E2E_PASSWORD=$(E2E_PASSWORD) ./tests/e2e/run-e2e-tests.sh
|
||||
|
||||
|
||||
# This endif closes the if at the top of the file
|
||||
endif
|
||||
|
||||
208
README.md
@@ -1,47 +1,29 @@
|
||||
# DevStar
|
||||
|
||||
[](https://github.com/mengning/DevStar/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly")
|
||||
[](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea")
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card")
|
||||
[](https://pkg.go.dev/code.gitea.io/gitea "GoDoc")
|
||||
[](https://github.com/mengning/DevStar/releases/latest "GitHub release")
|
||||
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
||||
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
||||
[](https://opensource.org/licenses/MIT "License: MIT")
|
||||
[](https://gitpod.io/#https://github.com/mengning/DevStar)
|
||||
[](https://translate.gitea.com "Crowdin")
|
||||
|
||||
[繁體中文](./README.zh-tw.md) | [简体中文](./README.zh-cn.md)
|
||||
The Last Mile of Al for R&D
|
||||
|
||||
## Purpose
|
||||
|
||||
The goal of this project is to make the easiest, fastest, and most
|
||||
painless way of setting up a self-hosted Git service.
|
||||
DevStar Studio是为AI时代打造的新一代一站式智能研发平台,面向人类开发者和AI开发者的融合团队,专注于产品质量和团队效能,为研发部门赋能提效。
|
||||
|
||||
As Gitea is written in Go, it works across **all** the platforms and
|
||||
As [Gitea](https://github.com/go-gitea/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.
|
||||
|
||||
For online demonstrations, you can visit [DevStar.cn](https://DevStar.cn).
|
||||
|
||||
For accessing free Gitea service (with a limited number of repositories), you can visit [gitea.com](https://gitea.com/user/login).
|
||||
|
||||
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).
|
||||
|
||||
## Documentation
|
||||
|
||||
You can find comprehensive documentation on our official [documentation website](https://docs.gitea.com/).
|
||||
|
||||
It includes installation, administration, usage, development, contributing guides, and more to help you get started and explore all features effectively.
|
||||
|
||||
If you have any suggestions or would like to contribute to it, you can visit the [documentation repository](https://gitea.com/gitea/docs)
|
||||
* For online demonstrations, you can visit [DevStar.cn](https://DevStar.cn).
|
||||
* You can find comprehensive documentation on our official [documentation website](https://mengning.com.cn/src/devstar/).
|
||||
* If you have any suggestions or would like to contribute to it, you can visit [devstar/docs](/docs) and the [documentation repository](https://devstar.cn/devstar/docs)
|
||||
|
||||
## Building
|
||||
|
||||
From the root of the source tree, run:
|
||||
Build devstar-studio:latest From the root of the source tree, run::
|
||||
```
|
||||
make devstar
|
||||
```
|
||||
or Build a binary file named `gitea` From the root of the source tree, run:
|
||||
|
||||
TAGS="bindata" make build
|
||||
|
||||
@@ -60,18 +42,10 @@ More info: https://docs.gitea.com/installation/install-from-source
|
||||
|
||||
## Using
|
||||
|
||||
After building, a binary file named `gitea` will be generated in the root of the source tree by default. To run it, use:
|
||||
|
||||
./gitea web
|
||||
|
||||
> [!NOTE]
|
||||
> devcontainer相关功能不能在localhost域名下正常工作,调试环境请在custom/conf/app.ini中修改为IP地址
|
||||
> If you're interested in using our APIs, we have experimental support with [documentation](https://docs.gitea.com/api).
|
||||
|
||||
Start from Container Image:
|
||||
Build and Start from Container Image:
|
||||
|
||||
```
|
||||
make devstar
|
||||
make devstar # Build devstar-studio:latest
|
||||
public/assets/install.sh start --image=devstar-studio:latest
|
||||
|
||||
# 查看日志
|
||||
@@ -82,6 +56,13 @@ public/assets/install.sh clean
|
||||
sudo docker stop $(docker ps -aq) && sudo docker rm -f $(docker ps -aq)
|
||||
```
|
||||
|
||||
or, After building, a binary file named `gitea` will be generated in the root of the source tree by default. To run it, use:
|
||||
|
||||
./gitea web
|
||||
|
||||
> [!NOTE]
|
||||
> devcontainer相关功能不能在localhost域名下正常工作,调试环境请在custom/conf/app.ini中修改为IP地址
|
||||
|
||||
## Contributing
|
||||
|
||||
Expected workflow is: Fork -> Patch -> Push -> Pull Request
|
||||
@@ -112,7 +93,7 @@ npm -v # should print `10.9.0`
|
||||
|
||||
在DevStar Git仓库创建分支
|
||||
```
|
||||
git clone https://gitee.com/devstar/devstar.git
|
||||
git clone https://devstar.cn/devstar/devstar.git
|
||||
git checkout -b YOUR_BRANCH
|
||||
code devstar
|
||||
|
||||
@@ -122,6 +103,10 @@ make test # testing
|
||||
TAGS="bindata timetzdata sqlite sqlite_unlock_notify" make build # 生成可执行文件
|
||||
./gitea
|
||||
|
||||
# 镜像方式安装验证
|
||||
make devstar # Build devstar-studio:latest
|
||||
public/assets/install.sh start --image=devstar-studio:latest
|
||||
|
||||
# 提交代码
|
||||
git add FILES
|
||||
git commit -m "commit log"
|
||||
@@ -137,140 +122,29 @@ public/assets/install.sh start
|
||||
> [!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!
|
||||
|
||||
## Translating
|
||||
|
||||
[](https://translate.gitea.com)
|
||||
|
||||
Translations are done through [Crowdin](https://translate.gitea.com). 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.
|
||||
|
||||
Get more information from [documentation](https://docs.gitea.com/contributing/localization).
|
||||
> 2. If you have found a vulnerability in the project, please write privately to **contact@mengning.com.cn**. Thanks!
|
||||
|
||||
## Official and Third-Party Projects
|
||||
|
||||
We provide an official [go-sdk](https://gitea.com/gitea/go-sdk), a CLI tool called [tea](https://gitea.com/gitea/tea) and an [action runner](https://gitea.com/gitea/act_runner) for Gitea Action.
|
||||
* [webTerminal](https://devstar.cn/devstar/webTerminal) for DevStar devcontainer
|
||||
* [devstar-vscode](https://devstar.cn/devstar/devstar-vscode)
|
||||
* [action runner](https://devstar.cn/devstar/act_runner) for DevStar Action
|
||||
* [go-sdk](https://gitea.com/gitea/go-sdk)
|
||||
* a CLI tool called [tea](https://gitea.com/gitea/tea)
|
||||
|
||||
We maintain a list of Gitea-related projects at [gitea/awesome-gitea](https://gitea.com/gitea/awesome-gitea), where you can discover more third-party projects, including SDKs, plugins, themes, and more.
|
||||
|
||||
## Communication
|
||||
|
||||
[](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea")
|
||||
|
||||
If you have questions that are not covered by the [documentation](https://docs.gitea.com/), 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/).
|
||||
|
||||
## Authors
|
||||
|
||||
- [Maintainers](https://github.com/orgs/go-gitea/people)
|
||||
- [Contributors](https://github.com/mengning/DevStar/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/mengning/DevStar/issues/1029).
|
||||
|
||||
**Where can I find the security patches?**
|
||||
|
||||
In the [release log](https://github.com/mengning/DevStar/releases) or the [change log](https://github.com/mengning/DevStar/blob/main/CHANGELOG.md), search for the keyword `SECURITY` to find the security patches.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License.
|
||||
See the [LICENSE](https://github.com/mengning/DevStar/blob/main/LICENSE) file
|
||||
for the full license text.
|
||||
This project is licensed under the AGPL-3.0 License.
|
||||
|
||||
## Further information
|
||||
> * **Community Edition (Free):**
|
||||
> * Includes the standalone version of DevStar Studio.
|
||||
> * Free to use and deploy.
|
||||
> * Technical support is not included.
|
||||
> * **Enterprise Edition (Paid):**
|
||||
> * Requires a commercial license.
|
||||
> * Unlocks Kubernetes-related features and other advanced functionalities.
|
||||
> * Includes technical support.
|
||||
|
||||
<details>
|
||||
<summary>Looking for an overview of the interface? Check it out!</summary>
|
||||
|
||||
### Login/Register Page
|
||||
|
||||

|
||||

|
||||
|
||||
### User Dashboard
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
### User Profile
|
||||
|
||||

|
||||
|
||||
### Explore
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
### Repository
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
#### Repository Issue
|
||||
|
||||

|
||||

|
||||
|
||||
#### Repository Pull Requests
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
#### Repository Actions
|
||||
|
||||

|
||||

|
||||
|
||||
#### Repository Activity
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
### Organization
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
See the [LICENSE](https://github.com/mengning/DevStar/blob/main/LICENSE) file for the full license text.
|
||||
206
README.zh-cn.md
@@ -1,206 +0,0 @@
|
||||
# Gitea
|
||||
|
||||
[](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly")
|
||||
[](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea")
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card")
|
||||
[](https://pkg.go.dev/code.gitea.io/gitea "GoDoc")
|
||||
[](https://github.com/go-gitea/gitea/releases/latest "GitHub release")
|
||||
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
||||
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
||||
[](https://opensource.org/licenses/MIT "License: MIT")
|
||||
[](https://gitpod.io/#https://github.com/go-gitea/gitea)
|
||||
[](https://translate.gitea.com "Crowdin")
|
||||
|
||||
[English](./README.md) | [繁體中文](./README.zh-tw.md)
|
||||
|
||||
## 目的
|
||||
|
||||
这个项目的目标是提供最简单、最快速、最无痛的方式来设置自托管的 Git 服务。
|
||||
|
||||
由于 Gitea 是用 Go 语言编写的,它可以在 Go 支持的所有平台和架构上运行,包括 Linux、macOS 和 Windows 的 x86、amd64、ARM 和 PowerPC 架构。这个项目自 2016 年 11 月从 [Gogs](https://gogs.io) [分叉](https://blog.gitea.com/welcome-to-gitea/) 而来,但已经有了很多变化。
|
||||
|
||||
在线演示可以访问 [demo.gitea.com](https://demo.gitea.com)。
|
||||
|
||||
要访问免费的 Gitea 服务(有一定数量的仓库限制),可以访问 [gitea.com](https://gitea.com/user/login)。
|
||||
|
||||
要快速部署您自己的专用 Gitea 实例,可以在 [cloud.gitea.com](https://cloud.gitea.com) 开始免费试用。
|
||||
|
||||
## 文件
|
||||
|
||||
您可以在我们的官方 [文件网站](https://docs.gitea.com/) 上找到全面的文件。
|
||||
|
||||
它包括安装、管理、使用、开发、贡献指南等,帮助您快速入门并有效地探索所有功能。
|
||||
|
||||
如果您有任何建议或想要贡献,可以访问 [文件仓库](https://gitea.com/gitea/docs)
|
||||
|
||||
## 构建
|
||||
|
||||
从源代码树的根目录运行:
|
||||
|
||||
TAGS="bindata" make build
|
||||
|
||||
如果需要 SQLite 支持:
|
||||
|
||||
TAGS="bindata sqlite sqlite_unlock_notify" make build
|
||||
|
||||
`build` 目标分为两个子目标:
|
||||
|
||||
- `make backend` 需要 [Go Stable](https://go.dev/dl/),所需版本在 [go.mod](/go.mod) 中定义。
|
||||
- `make frontend` 需要 [Node.js LTS](https://nodejs.org/en/download/) 或更高版本。
|
||||
|
||||
需要互联网连接来下载 go 和 npm 模块。从包含预构建前端文件的官方源代码压缩包构建时,不会触发 `frontend` 目标,因此可以在没有 Node.js 的情况下构建。
|
||||
|
||||
更多信息:https://docs.gitea.com/installation/install-from-source
|
||||
|
||||
## 使用
|
||||
|
||||
构建后,默认情况下会在源代码树的根目录生成一个名为 `gitea` 的二进制文件。要运行它,请使用:
|
||||
|
||||
./gitea web
|
||||
|
||||
> [!注意]
|
||||
> 如果您对使用我们的 API 感兴趣,我们提供了实验性支持,并附有 [文件](https://docs.gitea.com/api)。
|
||||
|
||||
## 贡献
|
||||
|
||||
预期的工作流程是:Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
> [!注意]
|
||||
>
|
||||
> 1. **在开始进行 Pull Request 之前,您必须阅读 [贡献者指南](CONTRIBUTING.md)。**
|
||||
> 2. 如果您在项目中发现了漏洞,请私下写信给 **security@gitea.io**。谢谢!
|
||||
|
||||
## 翻译
|
||||
|
||||
[](https://translate.gitea.com)
|
||||
|
||||
翻译通过 [Crowdin](https://translate.gitea.com) 进行。如果您想翻译成新的语言,请在 Crowdin 项目中请求管理员添加新语言。
|
||||
|
||||
您也可以创建一个 issue 来添加语言,或者在 discord 的 #translation 频道上询问。如果您需要上下文或发现一些翻译问题,可以在字符串上留言或在 Discord 上询问。对于一般的翻译问题,文档中有一个部分。目前有点空,但我们希望随着问题的出现而填充它。
|
||||
|
||||
更多信息请参阅 [文件](https://docs.gitea.com/contributing/localization)。
|
||||
|
||||
## 官方和第三方项目
|
||||
|
||||
我们提供了一个官方的 [go-sdk](https://gitea.com/gitea/go-sdk),一个名为 [tea](https://gitea.com/gitea/tea) 的 CLI 工具和一个 Gitea Action 的 [action runner](https://gitea.com/gitea/act_runner)。
|
||||
|
||||
我们在 [gitea/awesome-gitea](https://gitea.com/gitea/awesome-gitea) 维护了一个 Gitea 相关项目的列表,您可以在那里发现更多的第三方项目,包括 SDK、插件、主题等。
|
||||
|
||||
## 通讯
|
||||
|
||||
[](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea")
|
||||
|
||||
如果您有任何文件未涵盖的问题,可以在我们的 [Discord 服务器](https://discord.gg/Gitea) 上与我们联系,或者在 [discourse 论坛](https://forum.gitea.com/) 上创建帖子。
|
||||
|
||||
## 作者
|
||||
|
||||
- [维护者](https://github.com/orgs/go-gitea/people)
|
||||
- [贡献者](https://github.com/go-gitea/gitea/graphs/contributors)
|
||||
- [翻译者](options/locale/TRANSLATORS)
|
||||
|
||||
## 支持者
|
||||
|
||||
感谢所有支持者! 🙏 [[成为支持者](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>
|
||||
|
||||
## 赞助商
|
||||
|
||||
通过成为赞助商来支持这个项目。您的标志将显示在这里,并带有链接到您的网站。 [[成为赞助商](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>
|
||||
|
||||
## 常见问题
|
||||
|
||||
**Gitea 怎么发音?**
|
||||
|
||||
Gitea 的发音是 [/ɡɪ’ti:/](https://youtu.be/EM71-2uDAoY),就像 "gi-tea" 一样,g 是硬音。
|
||||
|
||||
**为什么这个项目没有托管在 Gitea 实例上?**
|
||||
|
||||
我们正在 [努力](https://github.com/go-gitea/gitea/issues/1029)。
|
||||
|
||||
**在哪里可以找到安全补丁?**
|
||||
|
||||
在 [发布日志](https://github.com/go-gitea/gitea/releases) 或 [变更日志](https://github.com/go-gitea/gitea/blob/main/CHANGELOG.md) 中,搜索关键词 `SECURITY` 以找到安全补丁。
|
||||
|
||||
## 许可证
|
||||
|
||||
这个项目是根据 MIT 许可证授权的。
|
||||
请参阅 [LICENSE](https://github.com/go-gitea/gitea/blob/main/LICENSE) 文件以获取完整的许可证文本。
|
||||
|
||||
## 进一步信息
|
||||
|
||||
<details>
|
||||
<summary>寻找界面概述?查看这里!</summary>
|
||||
|
||||
### 登录/注册页面
|
||||
|
||||

|
||||

|
||||
|
||||
### 用户仪表板
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
### 用户资料
|
||||
|
||||

|
||||
|
||||
### 探索
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
### 仓库
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
#### 仓库问题
|
||||
|
||||

|
||||

|
||||
|
||||
#### 仓库拉取请求
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
#### 仓库操作
|
||||
|
||||

|
||||

|
||||
|
||||
#### 仓库活动
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
### 组织
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
206
README.zh-tw.md
@@ -1,206 +0,0 @@
|
||||
# Gitea
|
||||
|
||||
[](https://github.com/go-gitea/gitea/actions/workflows/release-nightly.yml?query=branch%3Amain "Release Nightly")
|
||||
[](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea")
|
||||
[](https://goreportcard.com/report/code.gitea.io/gitea "Go Report Card")
|
||||
[](https://pkg.go.dev/code.gitea.io/gitea "GoDoc")
|
||||
[](https://github.com/go-gitea/gitea/releases/latest "GitHub release")
|
||||
[](https://www.codetriage.com/go-gitea/gitea "Help Contribute to Open Source")
|
||||
[](https://opencollective.com/gitea "Become a backer/sponsor of gitea")
|
||||
[](https://opensource.org/licenses/MIT "License: MIT")
|
||||
[](https://gitpod.io/#https://github.com/go-gitea/gitea)
|
||||
[](https://translate.gitea.com "Crowdin")
|
||||
|
||||
[English](./README.md) | [简体中文](./README.zh-cn.md)
|
||||
|
||||
## 目的
|
||||
|
||||
這個項目的目標是提供最簡單、最快速、最無痛的方式來設置自託管的 Git 服務。
|
||||
|
||||
由於 Gitea 是用 Go 語言編寫的,它可以在 Go 支援的所有平台和架構上運行,包括 Linux、macOS 和 Windows 的 x86、amd64、ARM 和 PowerPC 架構。這個項目自 2016 年 11 月從 [Gogs](https://gogs.io) [分叉](https://blog.gitea.com/welcome-to-gitea/) 而來,但已經有了很多變化。
|
||||
|
||||
在線演示可以訪問 [demo.gitea.com](https://demo.gitea.com)。
|
||||
|
||||
要訪問免費的 Gitea 服務(有一定數量的倉庫限制),可以訪問 [gitea.com](https://gitea.com/user/login)。
|
||||
|
||||
要快速部署您自己的專用 Gitea 實例,可以在 [cloud.gitea.com](https://cloud.gitea.com) 開始免費試用。
|
||||
|
||||
## 文件
|
||||
|
||||
您可以在我們的官方 [文件網站](https://docs.gitea.com/) 上找到全面的文件。
|
||||
|
||||
它包括安裝、管理、使用、開發、貢獻指南等,幫助您快速入門並有效地探索所有功能。
|
||||
|
||||
如果您有任何建議或想要貢獻,可以訪問 [文件倉庫](https://gitea.com/gitea/docs)
|
||||
|
||||
## 構建
|
||||
|
||||
從源代碼樹的根目錄運行:
|
||||
|
||||
TAGS="bindata" make build
|
||||
|
||||
如果需要 SQLite 支援:
|
||||
|
||||
TAGS="bindata sqlite sqlite_unlock_notify" make build
|
||||
|
||||
`build` 目標分為兩個子目標:
|
||||
|
||||
- `make backend` 需要 [Go Stable](https://go.dev/dl/),所需版本在 [go.mod](/go.mod) 中定義。
|
||||
- `make frontend` 需要 [Node.js LTS](https://nodejs.org/en/download/) 或更高版本。
|
||||
|
||||
需要互聯網連接來下載 go 和 npm 模塊。從包含預構建前端文件的官方源代碼壓縮包構建時,不會觸發 `frontend` 目標,因此可以在沒有 Node.js 的情況下構建。
|
||||
|
||||
更多信息:https://docs.gitea.com/installation/install-from-source
|
||||
|
||||
## 使用
|
||||
|
||||
構建後,默認情況下會在源代碼樹的根目錄生成一個名為 `gitea` 的二進制文件。要運行它,請使用:
|
||||
|
||||
./gitea web
|
||||
|
||||
> [!注意]
|
||||
> 如果您對使用我們的 API 感興趣,我們提供了實驗性支援,並附有 [文件](https://docs.gitea.com/api)。
|
||||
|
||||
## 貢獻
|
||||
|
||||
預期的工作流程是:Fork -> Patch -> Push -> Pull Request
|
||||
|
||||
> [!注意]
|
||||
>
|
||||
> 1. **在開始進行 Pull Request 之前,您必須閱讀 [貢獻者指南](CONTRIBUTING.md)。**
|
||||
> 2. 如果您在項目中發現了漏洞,請私下寫信給 **security@gitea.io**。謝謝!
|
||||
|
||||
## 翻譯
|
||||
|
||||
[](https://translate.gitea.com)
|
||||
|
||||
翻譯通過 [Crowdin](https://translate.gitea.com) 進行。如果您想翻譯成新的語言,請在 Crowdin 項目中請求管理員添加新語言。
|
||||
|
||||
您也可以創建一個 issue 來添加語言,或者在 discord 的 #translation 頻道上詢問。如果您需要上下文或發現一些翻譯問題,可以在字符串上留言或在 Discord 上詢問。對於一般的翻譯問題,文檔中有一個部分。目前有點空,但我們希望隨著問題的出現而填充它。
|
||||
|
||||
更多信息請參閱 [文件](https://docs.gitea.com/contributing/localization)。
|
||||
|
||||
## 官方和第三方項目
|
||||
|
||||
我們提供了一個官方的 [go-sdk](https://gitea.com/gitea/go-sdk),一個名為 [tea](https://gitea.com/gitea/tea) 的 CLI 工具和一個 Gitea Action 的 [action runner](https://gitea.com/gitea/act_runner)。
|
||||
|
||||
我們在 [gitea/awesome-gitea](https://gitea.com/gitea/awesome-gitea) 維護了一個 Gitea 相關項目的列表,您可以在那裡發現更多的第三方項目,包括 SDK、插件、主題等。
|
||||
|
||||
## 通訊
|
||||
|
||||
[](https://discord.gg/Gitea "Join the Discord chat at https://discord.gg/Gitea")
|
||||
|
||||
如果您有任何文件未涵蓋的問題,可以在我們的 [Discord 服務器](https://discord.gg/Gitea) 上與我們聯繫,或者在 [discourse 論壇](https://forum.gitea.com/) 上創建帖子。
|
||||
|
||||
## 作者
|
||||
|
||||
- [維護者](https://github.com/orgs/go-gitea/people)
|
||||
- [貢獻者](https://github.com/go-gitea/gitea/graphs/contributors)
|
||||
- [翻譯者](options/locale/TRANSLATORS)
|
||||
|
||||
## 支持者
|
||||
|
||||
感謝所有支持者! 🙏 [[成為支持者](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>
|
||||
|
||||
## 贊助商
|
||||
|
||||
通過成為贊助商來支持這個項目。您的標誌將顯示在這裡,並帶有鏈接到您的網站。 [[成為贊助商](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>
|
||||
|
||||
## 常見問題
|
||||
|
||||
**Gitea 怎麼發音?**
|
||||
|
||||
Gitea 的發音是 [/ɡɪ’ti:/](https://youtu.be/EM71-2uDAoY),就像 "gi-tea" 一樣,g 是硬音。
|
||||
|
||||
**為什麼這個項目沒有託管在 Gitea 實例上?**
|
||||
|
||||
我們正在 [努力](https://github.com/go-gitea/gitea/issues/1029)。
|
||||
|
||||
**在哪裡可以找到安全補丁?**
|
||||
|
||||
在 [發佈日誌](https://github.com/go-gitea/gitea/releases) 或 [變更日誌](https://github.com/go-gitea/gitea/blob/main/CHANGELOG.md) 中,搜索關鍵詞 `SECURITY` 以找到安全補丁。
|
||||
|
||||
## 許可證
|
||||
|
||||
這個項目是根據 MIT 許可證授權的。
|
||||
請參閱 [LICENSE](https://github.com/go-gitea/gitea/blob/main/LICENSE) 文件以獲取完整的許可證文本。
|
||||
|
||||
## 進一步信息
|
||||
|
||||
<details>
|
||||
<summary>尋找界面概述?查看這裡!</summary>
|
||||
|
||||
### 登錄/註冊頁面
|
||||
|
||||

|
||||

|
||||
|
||||
### 用戶儀表板
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
### 用戶資料
|
||||
|
||||

|
||||
|
||||
### 探索
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||
### 倉庫
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
#### 倉庫問題
|
||||
|
||||

|
||||

|
||||
|
||||
#### 倉庫拉取請求
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
#### 倉庫操作
|
||||
|
||||

|
||||

|
||||
|
||||
#### 倉庫活動
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
### 組織
|
||||
|
||||

|
||||
|
||||
</details>
|
||||
15
docs/README.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# DevStar Design文档相关列表
|
||||
|
||||
设计相关的放在devstar/devstar仓库/docs目录下,用户使用相关文档放在devstar/docs仓库,并将两者对应起来如下:
|
||||
|
||||
## CI/CD Workflow ( Actions/[act_runner](https://devstar.cn/devstar/act_runner) )
|
||||
|
||||
* [安装配置和使用](https://devstar.cn/devstar/docs/)
|
||||
* 设计说明
|
||||
* actions ...
|
||||
|
||||
## 开发环境容器Devcontainer
|
||||
|
||||
* 安装配置使用说明
|
||||
* [webTerminal](https://devstar.cn/devstar/webTerminal) for DevStar devcontainer
|
||||
* [devstar-vscode](https://devstar.cn/devstar/devstar-vscode)
|
||||
@@ -1,124 +0,0 @@
|
||||
# Devstar 部署文档
|
||||
|
||||
## 1. 安装 Helm
|
||||
|
||||
在开始部署前,请先安装 Helm。建议使用官方提供的安装脚本,具体步骤可参考:安装 Helm | Helm。
|
||||
|
||||
推荐使用 `get_helm.sh`脚本进行安装,执行如下命令:
|
||||
|
||||
```
|
||||
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
|
||||
chmod 700 get_helm.sh
|
||||
./get_helm.sh
|
||||
```
|
||||
|
||||
## 2. 获取并准备部署文件
|
||||
|
||||
在待部署的机器上新建一个目录,然后将 DevStar 的 Helm Chart 仓库克隆到该目录中。请注意,该仓库为私有仓库,需先获取访问权限。
|
||||
|
||||
如部署目标为 `devstar.cn`,请确保切换到对应的分支(如图所示):
|
||||
|
||||

|
||||
|
||||
将代码仓库克隆到本地后,目录中应包含以下四个脚本文件:
|
||||
|
||||

|
||||
|
||||
## 3. 首次安装
|
||||
|
||||
执行 `step1-install-helm.sh`脚本进行首次安装。安装时间取决于网络状况和镜像拉取速度,请耐心等待。
|
||||
|
||||
安装完成后,使用以下命令检查 Pod 状态:
|
||||
|
||||
```
|
||||
kubectl get pods -n devstar-studio-ns
|
||||
```
|
||||
|
||||
如发现 Pod 状态异常,可使用如下命令排查:
|
||||
|
||||
- 查看 Pod 日志:
|
||||
|
||||
```
|
||||
kubectl logs -n devstar-studio-ns <pod名称>
|
||||
```
|
||||
|
||||
- 查看 Pod 详细信息:
|
||||
|
||||
```
|
||||
kubectl describe pod -n devstar-studio-ns <pod名称>
|
||||
```
|
||||
|
||||
首次安装时,Pod 可能处于 `Pending`状态,通常是由于 PVC(PersistentVolumeClaim)未绑定到对应的 PV(PersistentVolume)所致。请检查 PV 与 PVC 的状态:
|
||||
|
||||
```
|
||||
kubectl get pv -A
|
||||
kubectl get pvc -A
|
||||
```
|
||||
|
||||

|
||||
|
||||
如发现有 PVC 处于 `Pending`状态,请手动创建并绑定对应的 PV。以下为 PV 的示例 YAML 配置,请根据实际情况修改相应字段:
|
||||
|
||||
```
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: node2-local-pv-gitea # 请根据实际情况修改名称
|
||||
spec:
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
storageClassName: local
|
||||
persistentVolumeReclaimPolicy: Retain
|
||||
local:
|
||||
path: /mnt/datadisk/devstar/gitea-storage # 修改为实际存储路径
|
||||
nodeAffinity:
|
||||
required:
|
||||
nodeSelectorTerms:
|
||||
- matchExpressions:
|
||||
- key: kubernetes.io/hostname
|
||||
operator: In
|
||||
values:
|
||||
- node2 # 修改为实际节点名称
|
||||
volumeMode: Filesystem
|
||||
claimRef:
|
||||
name: gitea-shared-storage-claim
|
||||
namespace: devstar-studio-ns
|
||||
```
|
||||
|
||||
使用以下命令应用 PV 配置:
|
||||
|
||||
```
|
||||
kubectl apply -f <yaml文件名>
|
||||
```
|
||||
|
||||
## 4. 域名解析与证书配置
|
||||
|
||||
如部署环境为公网可访问(如 `devstar.cn`),请在腾讯云(或其他域名服务商)控制台中配置域名解析,并申请及配置 HTTPS 证书。具体操作请参考相关证书配置文档。
|
||||
|
||||
## 5. 更新部署
|
||||
|
||||
若修改了 `values.yaml`文件,请执行 `step2-upgrade-helm.sh`脚本进行更新。更新完成后,会看到类似如下提示:
|
||||
|
||||

|
||||
|
||||
更新后请再次检查 Pod 状态:
|
||||
|
||||
```
|
||||
kubectl get pods -n devstar-studio-ns
|
||||
```
|
||||
|
||||
## 6. 验证部署版本
|
||||
|
||||
您可以通过以下两种方式确认 DevStar 的版本是否更新成功:
|
||||
|
||||
1. **在 DevStar 主界面查看**登录系统后,可在主界面右下角查看当前版本号。
|
||||
|
||||

|
||||
|
||||
2. **在流水线页面查看**进入“工作流”→“流水线”,在如图所示位置也可查看版本信息:
|
||||
|
||||

|
||||
|
||||
通过比对版本号,即可确认系统是否已成功更新至目标版本。
|
||||
@@ -1,47 +0,0 @@
|
||||
# SSL 证书配置与续期指南
|
||||
|
||||
目前需要配置证书的有devstar.cn和dev.devstar.cn
|
||||
|
||||
## 一、证书申请与续期
|
||||
|
||||
腾讯云提供的免费 HTTPS 证书有效期为 **90 天**,系统会在到期前通过短信提醒您及时续期。
|
||||
|
||||
### 操作步骤:
|
||||
|
||||
登录腾讯云控制台,搜索进入 **SSL 证书**管理页面。
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
在证书列表中查看已申请证书的有效期及到期时间。
|
||||
|
||||

|
||||
|
||||
点击右侧的 **快速续期**进入续期界面。
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
选择 **自动 DNS 验证**并勾选 **自动删除旧验证记录**,提交后等待证书签发。
|
||||
|
||||
证书签发后,在下载界面选择 **Nginx**格式,下载包含 `.crt`和 `.key`文件的证书包。
|
||||
|
||||

|
||||
|
||||
在master节点登录集群,进入当前要更新的域名对应的文件夹
|
||||
|
||||

|
||||
|
||||
## 二、证书部署
|
||||
|
||||
### 部署流程:
|
||||
|
||||
登录 Kubernetes 集群的 Master 节点,进入目标域名对应的证书目录。
|
||||
|
||||
将下载的 `.crt`和 `.key`文件上传至服务器,覆盖原有证书文件。
|
||||
|
||||
执行相应的脚本完成证书更新:**首次部署**:使用 `make-k8s-tls-secret.sh`**证书续期**:使用 `update-xxx-tls-secret.sh`
|
||||
|
||||

|
||||
repo.diff.bin
docs/devstar-deploy/assets/image-20251104201036920.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 15 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104201132614.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 14 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104203152647.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 56 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104203353406.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 56 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104203454915.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 55 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104203757243.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 51 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104204421088.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 7.9 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104204424116.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 7.9 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104204453766.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 128 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104221729545.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 15 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104221749140.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 41 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104221811555.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 107 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104221928154.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 29 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104221950856.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 7.5 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104221953043.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 7.5 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104222023293.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 21 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104224918197.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 199 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104224951191.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 187 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104225007427.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 69 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104225042423.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 192 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104225305942.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 96 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104225334394.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 49 KiB |
repo.diff.bin
docs/devstar-deploy/assets/image-20251104225929257.png
|
repo.diff.file_before repo.diff.file_image_width: | repo.diff.file_image_height: | repo.diff.file_byte_size: 32 KiB |
@@ -1,98 +1,53 @@
|
||||
import {devices} from '@playwright/test';
|
||||
import {env} from 'node:process';
|
||||
import type {PlaywrightTestConfig} from '@playwright/test';
|
||||
import { devices } from '@playwright/test';
|
||||
import { env } from 'node:process';
|
||||
import type { PlaywrightTestConfig } from '@playwright/test';
|
||||
|
||||
const BASE_URL = env.GITEA_URL?.replace?.(/\/$/g, '') || 'http://localhost:3000';
|
||||
const BASE_URL = env.DEVSTAR_URL?.replace?.(/\/$/g, '') || 'http://localhost:3000';
|
||||
|
||||
export default {
|
||||
testDir: './tests/e2e/',
|
||||
testMatch: /.*\.test\.e2e\.ts/, // Match any .test.e2e.ts files
|
||||
|
||||
/* Maximum time one test can run for. */
|
||||
timeout: 30 * 1000,
|
||||
const config: PlaywrightTestConfig = {
|
||||
testDir: './specs',
|
||||
testMatch: /specs\/.*\.test\.ts/,
|
||||
|
||||
timeout: 500000,
|
||||
expect: {
|
||||
|
||||
/**
|
||||
* Maximum time expect() should wait for the condition to be met.
|
||||
* For example in `await expect(locator).toHaveText();`
|
||||
*/
|
||||
timeout: 2000,
|
||||
timeout: 15000,
|
||||
},
|
||||
|
||||
/* Fail the build on CI if you accidentally left test.only in the source code. */
|
||||
forbidOnly: Boolean(env.CI),
|
||||
|
||||
/* Retry on CI only */
|
||||
retries: env.CI ? 2 : 0,
|
||||
|
||||
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
|
||||
reporter: env.CI ? 'list' : [['list'], ['html', {outputFolder: 'tests/e2e/reports/', open: 'never'}]],
|
||||
reporter: [['html', {
|
||||
outputFolder: 'playwright-report/html',
|
||||
open: 'never'
|
||||
}]],
|
||||
|
||||
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
|
||||
use: {
|
||||
headless: true, // set to false to debug
|
||||
|
||||
locale: 'en-US',
|
||||
|
||||
/* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
|
||||
actionTimeout: 1000,
|
||||
|
||||
/* Maximum time allowed for navigation, such as `page.goto()`. */
|
||||
navigationTimeout: 5 * 1000,
|
||||
|
||||
/* Base URL to use in actions like `await page.goto('/')`. */
|
||||
baseURL: BASE_URL,
|
||||
|
||||
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
|
||||
headless: true,
|
||||
locale: 'zh-CN',
|
||||
timezoneId: 'Asia/Shanghai',
|
||||
actionTimeout: 15000,
|
||||
navigationTimeout: 15000,
|
||||
baseURL: BASE_URL,
|
||||
trace: 'on-first-retry',
|
||||
|
||||
screenshot: 'only-on-failure',
|
||||
},
|
||||
|
||||
/* Configure projects for major browsers */
|
||||
projects: [
|
||||
{
|
||||
name: 'chromium',
|
||||
|
||||
/* Project-specific settings. */
|
||||
use: {
|
||||
...devices['Desktop Chrome'],
|
||||
},
|
||||
},
|
||||
|
||||
// disabled because of https://github.com/go-gitea/gitea/issues/21355
|
||||
// {
|
||||
// name: 'firefox',
|
||||
// use: {
|
||||
// ...devices['Desktop Firefox'],
|
||||
// },
|
||||
// },
|
||||
|
||||
{
|
||||
name: 'webkit',
|
||||
use: {
|
||||
...devices['Desktop Safari'],
|
||||
},
|
||||
},
|
||||
|
||||
/* Test against mobile viewports. */
|
||||
{
|
||||
name: 'Mobile Chrome',
|
||||
use: {
|
||||
...devices['Pixel 5'],
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'Mobile Safari',
|
||||
use: {
|
||||
...devices['iPhone 12'],
|
||||
},
|
||||
},
|
||||
],
|
||||
outputDir: 'playwright-report/test-artifacts/',
|
||||
snapshotDir: 'playwright-report/test-snapshots/',
|
||||
};
|
||||
|
||||
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
|
||||
outputDir: 'tests/e2e/test-artifacts/',
|
||||
/* Folder for test artifacts such as screenshots, videos, traces, etc. */
|
||||
snapshotDir: 'tests/e2e/test-snapshots/',
|
||||
} satisfies PlaywrightTestConfig;
|
||||
const skipInstall = env.E2E_SKIP_INSTALL === 'true';
|
||||
|
||||
if (skipInstall) {
|
||||
console.log(`已跳过 global-setup.`);
|
||||
} else {
|
||||
console.log(`[Playwright Config] 探测结果: E2E_SKIP_INSTALL is not 'true'. 已启用 global-setup.`);
|
||||
config.globalSetup = require.resolve('./global-setup.ts');
|
||||
}
|
||||
export default config satisfies PlaywrightTestConfig;
|
||||
|
||||
@@ -2,14 +2,13 @@
|
||||
# Copyright 2024 Mengning Software All rights reserved.
|
||||
|
||||
# 默认值
|
||||
NAME=DevStar-Studio
|
||||
NAME="DevStar-Studio-$(date +%Y%m%d-%H-%M-%S)"
|
||||
IMAGE_REGISTRY_USER=mengning997
|
||||
IMAGE_NAME=devstar-studio
|
||||
VERSION=latest # DevStar Studio的默认版本为最新版本
|
||||
PORT=80 # 设置端口默认值为 80
|
||||
SSH_PORT=2222 # 设置ssh默认端口号2222
|
||||
DATA_DIR=${HOME}/devstar_data
|
||||
APP_INI=${DATA_DIR}/app.ini
|
||||
|
||||
# 错误处理函数
|
||||
error_handler() {
|
||||
@@ -111,25 +110,37 @@ function start {
|
||||
mkdir -p $DATA_DIR
|
||||
sudo chown 1000:1000 $DATA_DIR
|
||||
sudo chmod 666 /var/run/docker.sock
|
||||
if [ ! -f "$APP_INI" ]; then
|
||||
DOMAIN_NAME=$(hostname -I | awk '{print $1}')
|
||||
DOMAIN_NAME=$(ip route get 1 2>/dev/null | awk '{print $7; exit}')
|
||||
|
||||
if [[ -f "/.dockerenv" ]]; then
|
||||
if [[ -S "/var/run/docker.sock" ]] && command -v docker >/dev/null 2>&1; then
|
||||
if docker info 2>/dev/null | grep -q "Storage Driver: vfs"; then
|
||||
# DinD 环境 - 保持原来的容器IP
|
||||
: # 什么也不做,使用初始值
|
||||
else
|
||||
# DooD 环境 - 获取宿主机IP
|
||||
DOMAIN_NAME=$(ip route | grep default | awk '{print $3}' 2>/dev/null)
|
||||
fi
|
||||
fi
|
||||
# 普通容器环境保持原来的容器IP
|
||||
fi
|
||||
if [ ! -f "${DATA_DIR}/app.ini" ]; then
|
||||
echo "DOMAIN_NAME=$DOMAIN_NAME"
|
||||
else
|
||||
# 读取 DOMAIN 值
|
||||
DOMAIN_NAME=$(grep -E '^\s*DOMAIN\s*=' "$APP_INI" | cut -d'=' -f2 | xargs)
|
||||
DOMAIN_NAME_APP_INI=$(grep -E '^\s*DOMAIN\s*=' "${DATA_DIR}/app.ini" | cut -d'=' -f2 | xargs)
|
||||
# 检查是否成功读取到值
|
||||
if [[ -z "$DOMAIN_NAME" ]]; then
|
||||
DOMAIN_NAME="localhost"
|
||||
if [[ -n "$DOMAIN_NAME_APP_INI" ]]; then
|
||||
DOMAIN_NAME=$DOMAIN_NAME_APP_INI
|
||||
fi
|
||||
echo "DOMAIN_NAME=$DOMAIN_NAME"
|
||||
fi
|
||||
# 启动devstar-studio容器
|
||||
stop
|
||||
if [[ -z "$IMAGE_STR" ]]; then
|
||||
IMAGE_STR="$IMAGE_REGISTRY_USER/$IMAGE_NAME:$VERSION"
|
||||
fi
|
||||
echo "image=$IMAGE_STR"
|
||||
sudo docker run --restart=always --name $NAME -d -p $PORT:3000 -p $SSH_PORT:$SSH_PORT -v /var/run/docker.sock:/var/run/docker.sock -v ~/devstar_data:/var/lib/gitea -v ~/devstar_data:/etc/gitea $IMAGE_STR
|
||||
sudo docker run --restart=always --name $NAME -d -p $PORT:3000 -p $SSH_PORT:$SSH_PORT -v /var/run/docker.sock:/var/run/docker.sock -v ${DATA_DIR}:/var/lib/gitea -v ${DATA_DIR}:/etc/gitea $IMAGE_STR
|
||||
# 打开 `http://localhost:8080` 完成安装。
|
||||
success "-------------------------------------------------------"
|
||||
success "DevStar started in http://$DOMAIN_NAME:$PORT successfully!"
|
||||
@@ -139,30 +150,37 @@ function start {
|
||||
|
||||
# Function to stop
|
||||
function stop {
|
||||
if [ $(docker ps -a --filter "name=^/${NAME}$" -q | wc -l) -gt 0 ]; then
|
||||
sudo docker stop $NAME && sudo docker rm -f $NAME
|
||||
fi
|
||||
if [ $(docker ps -a --filter "name=^/devstar-studio$" -q | wc -l) -gt 0 ]; then
|
||||
sudo docker stop devstar-studio && sudo docker rm -f devstar-studio
|
||||
if [ $(docker ps -a --filter "name=^/DevStar-Studio.*|devstar-studio.*" -q | wc -l) -gt 0 ]; then
|
||||
sudo docker stop $(docker ps -a --filter "name=^/DevStar-Studio.*|devstar-studio.*" -q) && \
|
||||
sudo docker rm -f $(docker ps -a --filter "name=^/DevStar-Studio.*|devstar-studio.*" -q)
|
||||
fi
|
||||
if [ $(docker ps -a --filter "name=^/webterminal-" -q | wc -l) -gt 0 ]; then
|
||||
sudo docker stop $(docker ps -a --filter "name=^/webterminal-" -q) && sudo docker rm -f $(docker ps -a --filter "name=^/webterminal-" -q)
|
||||
fi
|
||||
if [ $(docker ps -a --filter "name=^/runner-" -q | wc -l) -gt 0 ]; then
|
||||
sudo docker stop $(docker ps -a --filter "name=^/runner-" -q) && sudo docker rm -f $(docker ps -a --filter "name=^/runner-" -q)
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to logs
|
||||
function logs {
|
||||
# 查看devstar-studio容器的运行日志
|
||||
sudo docker logs $NAME
|
||||
sudo docker ps -a --filter "name=^/DevStar-Studio.*|devstar-studio.*" --format "table {{.ID}}\t{{.Names}}" | tail -n +2 | while read container_id container_name; do
|
||||
echo "=== 容器日志: $container_name (ID: $container_id) ==="
|
||||
sudo docker logs "$container_id"
|
||||
done
|
||||
}
|
||||
|
||||
# Function to clean
|
||||
function clean {
|
||||
stop
|
||||
rm -rf $DATA_DIR
|
||||
read -p "警告:即将永久删除目录 $DATA_DIR,此操作不可恢复!请输入 'YES' 确认: " confirm
|
||||
if [[ "$confirm" == "YES" ]]; then
|
||||
rm -rf "$DATA_DIR"
|
||||
echo "目录已删除"
|
||||
else
|
||||
echo "操作已取消"
|
||||
fi
|
||||
}
|
||||
|
||||
# Function to usage help
|
||||
@@ -173,6 +191,7 @@ function usage {
|
||||
success " start Start DevStar Studio"
|
||||
success " --port=<arg> Specify the port number (default port is 80)"
|
||||
success " --ssh-port=<arg> Specify the ssh-port number (default ssh-port is 2222)"
|
||||
success " --data-dir=<arg> Specify the data directory (default data directory is ~/devstar_data)"
|
||||
success " --version=<arg> Specify the DevStar Studio Image Version (default verson is latest)"
|
||||
success " --image=<arg> Specify the DevStar Studio Image example: devstar-studio:latest "
|
||||
success " stop Stop the running DevStar Studio"
|
||||
@@ -188,7 +207,7 @@ case "$1" in
|
||||
usage
|
||||
;;
|
||||
start)
|
||||
ARGS=$(getopt --long port::,ssh-port::,version::,image:: -- "$@")
|
||||
ARGS=$(getopt --long port::,ssh-port::,data-dir::,version::,image:: -- "$@")
|
||||
if [ $? -ne 0 ]; then
|
||||
failure "ARGS ERROR!"
|
||||
exit 1
|
||||
@@ -205,6 +224,10 @@ case "$1" in
|
||||
SSH_PORT="$2"
|
||||
echo "The SSH_Port is: $SSH_PORT"
|
||||
shift 2 ;;
|
||||
--data-dir)
|
||||
DATA_DIR="$2"
|
||||
echo "The SSH_Port is: $DATA_DIR"
|
||||
shift 2 ;;
|
||||
--version)
|
||||
VERSION="$2"
|
||||
echo "The DevStar Studio Image Version is: $VERSION"
|
||||
@@ -246,5 +269,4 @@ case "$1" in
|
||||
devstar help
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
esac
|
||||
@@ -400,25 +400,25 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) {
|
||||
if ctx.Doer != nil {
|
||||
ctx.Data["AllowCreateDevcontainer"] = ctx.Doer.AllowCreateDevcontainer
|
||||
ctx.Data["AllowCreateActRunner"] = ctx.Doer.AllowCreateActRunner
|
||||
|
||||
} else {
|
||||
query := ctx.Req.URL.Query()
|
||||
userID := query.Get("user")
|
||||
userNum, err := strconv.ParseInt(userID, 10, 64)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
u, err := user_model.GetUserByID(ctx, userNum)
|
||||
if err != nil {
|
||||
if user_model.IsErrUserNotExist(err) {
|
||||
ctx.Redirect(setting.AppSubURL + "/-/admin/users")
|
||||
} else {
|
||||
ctx.ServerError("GetUserByID", err)
|
||||
if userID != "" {
|
||||
userNum, err := strconv.ParseInt(userID, 10, 64)
|
||||
if err == nil {
|
||||
u, err := user_model.GetUserByID(ctx, userNum)
|
||||
if err != nil {
|
||||
if user_model.IsErrUserNotExist(err) {
|
||||
ctx.Redirect(setting.AppSubURL + "/-/admin/users")
|
||||
} else {
|
||||
ctx.ServerError("GetUserByID", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.Data["AllowCreateDevcontainer"] = u.AllowCreateDevcontainer
|
||||
ctx.Data["AllowCreateActRunner"] = u.AllowCreateActRunner
|
||||
}
|
||||
return
|
||||
}
|
||||
ctx.Data["AllowCreateDevcontainer"] = u.AllowCreateDevcontainer
|
||||
ctx.Data["AllowCreateActRunner"] = u.AllowCreateActRunner
|
||||
}
|
||||
|
||||
if repo.IsMirror {
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
{{template "custom/extra_links" .}}
|
||||
|
||||
{{if not .IsSigned}}
|
||||
<a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com">{{ctx.Locale.Tr "help"}}</a>
|
||||
<a class="item" target="_blank" rel="noopener noreferrer" href="https://mengning.com.cn/src/devstar/">{{ctx.Locale.Tr "help"}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
{{svg "octicon-tools"}}
|
||||
{{ctx.Locale.Tr "your_settings"}}
|
||||
</a>
|
||||
<a class="item" target="_blank" rel="noopener noreferrer" href="https://docs.gitea.com">
|
||||
<a class="item" target="_blank" rel="noopener noreferrer" href="https://mengning.com.cn/src/devstar/">
|
||||
{{svg "octicon-question"}}
|
||||
{{ctx.Locale.Tr "help"}}
|
||||
</a>
|
||||
|
||||
@@ -1,92 +1,27 @@
|
||||
# End to end tests
|
||||
# E2E端到端测试
|
||||
|
||||
E2e tests largely follow the same syntax as [integration tests](../integration).
|
||||
Whereas integration tests are intended to mock and stress the back-end, server-side code, e2e tests the interface between front-end and back-end, as well as visual regressions with both assertions and visual comparisons.
|
||||
They can be run with make commands for the appropriate backends, namely:
|
||||
```shell
|
||||
make test-sqlite
|
||||
make test-pgsql
|
||||
make test-mysql
|
||||
make test-mssql
|
||||
```
|
||||
## E2E端到端测试的用法
|
||||
|
||||
Make sure to perform a clean front-end build before running tests:
|
||||
```
|
||||
make clean frontend
|
||||
```
|
||||
|
||||
## Install playwright system dependencies
|
||||
```
|
||||
npx playwright install-deps
|
||||
```
|
||||
|
||||
|
||||
## Run all tests via local act_runner
|
||||
```
|
||||
act_runner exec -W ./.github/workflows/pull-e2e-tests.yml --event=pull_request --default-actions-url="https://github.com" -i catthehacker/ubuntu:runner-latest
|
||||
```
|
||||
|
||||
## Run sqlite e2e tests
|
||||
Start tests
|
||||
```
|
||||
make test-e2e-sqlite
|
||||
```
|
||||
|
||||
## Run MySQL e2e tests
|
||||
Setup a MySQL database inside docker
|
||||
```
|
||||
docker run -e "MYSQL_DATABASE=test" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -p 3306:3306 --rm --name mysql mysql:latest #(just ctrl-c to stop db and clean the container)
|
||||
docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --rm --name elasticsearch elasticsearch:7.6.0 #(in a second terminal, just ctrl-c to stop db and clean the container)
|
||||
```
|
||||
Start tests based on the database container
|
||||
```
|
||||
TEST_MYSQL_HOST=localhost:3306 TEST_MYSQL_DBNAME=test TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-e2e-mysql
|
||||
```
|
||||
|
||||
## Run pgsql e2e tests
|
||||
Setup a pgsql database inside docker
|
||||
```
|
||||
docker run -e "POSTGRES_DB=test" -p 5432:5432 --rm --name pgsql postgres:latest #(just ctrl-c to stop db and clean the container)
|
||||
```
|
||||
Start tests based on the database container
|
||||
```
|
||||
TEST_PGSQL_HOST=localhost:5432 TEST_PGSQL_DBNAME=test TEST_PGSQL_USERNAME=postgres TEST_PGSQL_PASSWORD=postgres make test-e2e-pgsql
|
||||
```
|
||||
|
||||
## Run mssql e2e tests
|
||||
Setup a mssql database inside docker
|
||||
```
|
||||
docker run -e "ACCEPT_EULA=Y" -e "MSSQL_PID=Standard" -e "SA_PASSWORD=MwantsaSecurePassword1" -p 1433:1433 --rm --name mssql microsoft/mssql-server-linux:latest #(just ctrl-c to stop db and clean the container)
|
||||
```
|
||||
Start tests based on the database container
|
||||
```
|
||||
TEST_MSSQL_HOST=localhost:1433 TEST_MSSQL_DBNAME=gitea_test TEST_MSSQL_USERNAME=sa TEST_MSSQL_PASSWORD=MwantsaSecurePassword1 make test-e2e-mssql
|
||||
```
|
||||
|
||||
## Running individual tests
|
||||
|
||||
Example command to run `example.test.e2e.ts` test file:
|
||||
|
||||
_Note: unlike integration tests, this filtering is at the file level, not function_
|
||||
|
||||
For SQLite:
|
||||
在项目根目录下:
|
||||
|
||||
```
|
||||
make test-e2e-sqlite#example
|
||||
make devstar
|
||||
public/assets/install.sh clean # 清理已有的安装,警告:会删除已有全部数据!!!
|
||||
public/assets/install.sh start --image=devstar-studio:latest
|
||||
|
||||
make e2e-test TARGET_URL="..." # 使用默认账号testuser 密码12345678
|
||||
make e2e-test TARGET_URL="..." E2E_USERNAME="your_name" E2E_PASSWORD="your_password" # 使用已有的账号和密码
|
||||
```
|
||||
|
||||
For other databases(replace `mssql` to `mysql` or `pgsql`):
|
||||
* 通过make devstar 本地代码构建镜像devstar-studio:latest
|
||||
* public/assets/install.sh start --image=devstar-studio:latest 脚本创建容器并输出devstar的URL,比如http://192.168.234.210:80
|
||||
* make e2e-test TARGET_URL="..."中输入devstar的URL,如果首次安装会进入安装页面自动设置管理员账号密码,如果已经安装过,可以使用已有的账号密码,否则按默认账号和密码登录。
|
||||
* 注意:URL不可以是localhost,否则devcontainer容器及webterminal无法正常工作!
|
||||
|
||||
```
|
||||
TEST_MSSQL_HOST=localhost:1433 TEST_MSSQL_DBNAME=test TEST_MSSQL_USERNAME=sa TEST_MSSQL_PASSWORD=MwantsaSecurePassword1 make test-e2e-mssql#example
|
||||
```
|
||||
## 添加E2E端到端测试用例的方法
|
||||
|
||||
## Visual testing
|
||||
* 所有的测试按照功能分组:devcontainer,appstore,runner等等,每一个test函数对应一组或一个测试用例, 按照流程增加对应的测试用例和测试脚本。
|
||||
|
||||
Although the main goal of e2e is assertion testing, we have added a framework for visual regress testing. If you are working on front-end features, please use the following:
|
||||
- Check out `main`, `make clean frontend`, and run e2e tests with `VISUAL_TEST=1` to generate outputs. This will initially fail, as no screenshots exist. You can run the e2e tests again to assert it passes.
|
||||
- Check out your branch, `make clean frontend`, and run e2e tests with `VISUAL_TEST=1`. You should be able to assert you front-end changes don't break any other tests unintentionally.
|
||||
举例说明如下:
|
||||
|
||||
VISUAL_TEST=1 will create screenshots in tests/e2e/test-snapshots. The test will fail the first time this is enabled (until we get visual test image persistence figured out), because it will be testing against an empty screenshot folder.
|
||||
|
||||
ACCEPT_VISUAL=1 will overwrite the snapshot images with new images.
|
||||
todo
|
||||
|
||||
48
tests/e2e/global-setup.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
import { chromium, type FullConfig } from '@playwright/test';
|
||||
import { env } from 'node:process';
|
||||
import { URL } from 'url';
|
||||
|
||||
async function globalSetup(config: FullConfig) {
|
||||
const mode = env.E2E_MODE;
|
||||
const {baseURL} = config.projects[0].use;
|
||||
const isInstalledMode=env.E2E_SKIP_INSTALL;
|
||||
const DEFAULT_E2E_USER = 'testuser';
|
||||
const DEFAULT_E2E_PASS = '12345678';
|
||||
if (!baseURL) {
|
||||
throw new Error('[GlobalSetup] 致命错误: baseURL 或 storageState 未定义!');
|
||||
}
|
||||
const browser = await chromium.launch();
|
||||
const context = await browser.newContext({
|
||||
locale: 'zh-CN', // 强制中文
|
||||
timezoneId: 'Asia/Shanghai', // 强制时区
|
||||
});
|
||||
const page = await context.newPage();
|
||||
if (mode === 'url') {
|
||||
try {
|
||||
const url1=env.DEVSTAR_URL;
|
||||
await page.goto(url1, { timeout: 15000 });
|
||||
console.log('[GlobalSetup] 检测到安装界面!正在开始自动化安装...');
|
||||
await page.getByText('服务器和第三方服务设置').click();
|
||||
await page.getByRole('checkbox', { name: '启用通过 微信二维码 登录' }).uncheck();
|
||||
await page.getByRole('checkbox', { name: '要求在用户注册时输入预验证码' }).uncheck();
|
||||
await page.getByText('管理员帐号设置').click();
|
||||
await page.getByRole('textbox', { name: '管理员用户名' }).fill('testuser');
|
||||
await page.getByRole('textbox', { name: '邮箱地址' }).fill('ilovcatlyn750314@gmail.com');
|
||||
await page.getByRole('textbox', { name: '管理员密码', exact: true }).fill('12345678');
|
||||
await page.getByRole('textbox', { name: '确认密码' }).fill('12345678');
|
||||
await page.getByRole('button', { name: '立即安装'}).click({ timeout: 10000, noWaitAfter: true });
|
||||
console.log("安装中,请耐心等待");
|
||||
await page.waitForTimeout(90000);
|
||||
} catch (error) {
|
||||
console.error('[GlobalSetup] "URL 模式" 登录失败:', error);
|
||||
await page.screenshot({ path: 'playwright-report/global-setup-login-failure.png' });
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new Error(`[GlobalSetup] 未知的 E2E_MODE: "${mode}"`);
|
||||
}
|
||||
await browser.close();
|
||||
}
|
||||
export default globalSetup;
|
||||
20
tests/e2e/package.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "devstar-e2e-runner",
|
||||
"version": "1.0.0",
|
||||
"description": "Isolated E2E test runner for DevStar Studio",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "npx playwright test"
|
||||
},
|
||||
"keywords": [
|
||||
"playwright",
|
||||
"e2e",
|
||||
"devstar"
|
||||
],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"devDependencies": {
|
||||
"@playwright/test": "1.53.2"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
||||
126
tests/e2e/run-e2e-tests.sh
Executable file
@@ -0,0 +1,126 @@
|
||||
#!/bin/bash
|
||||
# 这是一个“一键运行”E2E 测试的脚本
|
||||
# 它会处理所有清理、权限、拉取和执行工作
|
||||
# 任何命令失败立即退出
|
||||
set -e
|
||||
|
||||
#基础配置与路径定义
|
||||
SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
|
||||
PROJECT_ROOT=$( cd -- "$SCRIPT_DIR/../.." &> /dev/null && pwd )
|
||||
export CURRENT_UID=$(id -u)
|
||||
export CURRENT_GID=$(id -g)
|
||||
|
||||
cd "$PROJECT_ROOT"
|
||||
|
||||
echo "===== [1/3] 清理旧的测试环境... ====="
|
||||
|
||||
# 如果容器已存在,强制删除
|
||||
if [ "$(docker ps -aq -f name=e2e-test-runner-container)" ]; then
|
||||
docker rm -f e2e-test-runner-container
|
||||
fi
|
||||
|
||||
# 清理悬空镜像
|
||||
docker image prune -f
|
||||
|
||||
# 清理旧报告和数据,重建目录结构
|
||||
rm -rf ./tests/e2e/reports ./tests/e2e/test-data
|
||||
mkdir -p ./tests/e2e/reports/html ./tests/e2e/test-data/devstar_data
|
||||
chmod -R 777 ./tests/e2e/reports
|
||||
|
||||
#这里添加的代码是因为需要执行npm install,我们以当前用户启动测试容器,避免root权限冲突,所以先预构建文件夹,也作为缓存,缓存npm install.
|
||||
mkdir -p ./tests/e2e/node_modules
|
||||
chmod 777 ./tests/e2e/node_modules
|
||||
LOCK_FILE="./tests/e2e/package-lock.json"
|
||||
|
||||
# 确保 lock 文件存在且可写
|
||||
if [ ! -f "$LOCK_FILE" ]; then
|
||||
echo "{}" > "$LOCK_FILE"
|
||||
fi
|
||||
chmod 666 "$LOCK_FILE"
|
||||
|
||||
echo "===== [2/3] 准备环境变量... ====="
|
||||
|
||||
export DEVSTAR_URL=$TARGET_URL
|
||||
export E2E_MODE="url"
|
||||
|
||||
if [ -n "$CI" ] || [ "$CI" = "true" ]; then
|
||||
echo " [CI环境] 检测到 CI 环境,跳过 curl 安装状态检查..."
|
||||
export E2E_SKIP_INSTALL="false"
|
||||
else
|
||||
echo " 正在检查安装状态..."
|
||||
|
||||
PATH_TO_CHECK="/user/login"
|
||||
EXPECTED_CODE_IF_INSTALLED="200"
|
||||
PROBE_URL="${TARGET_URL}${PATH_TO_CHECK}"
|
||||
|
||||
# 使用 curl 获取 HTTP 状态码
|
||||
HTTP_CODE=$(curl -L -s -o /dev/null -w "%{http_code}" "$PROBE_URL")
|
||||
|
||||
if [ "$HTTP_CODE" -eq "$EXPECTED_CODE_IF_INSTALLED" ]; then
|
||||
echo " 探测结果: 目标已安装 (在 ${PROBE_URL} 收到 HTTP ${HTTP_CODE})."
|
||||
export E2E_SKIP_INSTALL="true"
|
||||
else
|
||||
echo " 探测结果: 目标未安装 (HTTP $HTTP_CODE),将执行安装脚本!"
|
||||
export E2E_SKIP_INSTALL="false"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
|
||||
echo "===== [3/3] 启动容器并运行测试... ====="
|
||||
set +e
|
||||
|
||||
docker run -d --rm --init --ipc=host \
|
||||
--name e2e-test-runner-container \
|
||||
-u "root" \
|
||||
-e DEVSTAR_URL="$DEVSTAR_URL" \
|
||||
-e E2E_SKIP_INSTALL="$E2E_SKIP_INSTALL" \
|
||||
-e E2E_USERNAME="$E2E_USERNAME" \
|
||||
-e E2E_PASSWORD="$E2E_PASSWORD" \
|
||||
-e E2E_MODE="$E2E_MODE" \
|
||||
-e CI="$CI" \
|
||||
-e npm_config_cache=/tmp/npm-cache \
|
||||
-e HOME=/tmp \
|
||||
-w /app \
|
||||
-v /var/run/docker.sock:/var/run/docker.sock \
|
||||
mcr.microsoft.com/playwright:v1.53.2-jammy \
|
||||
tail -f /dev/null
|
||||
echo "容器已启动,正在使用 docker cp 注入代码..."
|
||||
|
||||
# 注入代码文件
|
||||
docker cp "$(pwd)/tests/e2e/package.json" e2e-test-runner-container:/app/package.json
|
||||
docker cp "$(pwd)/playwright.config.ts" e2e-test-runner-container:/app/playwright.config.ts
|
||||
docker cp "$(pwd)/tests/e2e/global-setup.ts" e2e-test-runner-container:/app/global-setup.ts
|
||||
docker cp "$(pwd)/tests/e2e/specs" e2e-test-runner-container:/app/specs
|
||||
|
||||
# 在容器内执行安装与测试
|
||||
docker exec e2e-test-runner-container bash -c "
|
||||
# 确保 node_modules 目录存在
|
||||
mkdir -p /app/node_modules
|
||||
|
||||
echo '正在安装依赖...'
|
||||
npm install --no-package-lock
|
||||
|
||||
echo '依赖安装完成,开始测试...'
|
||||
npx playwright test
|
||||
"
|
||||
EXIT_CODE=$?
|
||||
set -e
|
||||
|
||||
# 导出测试报告
|
||||
docker cp e2e-test-runner-container:/app/playwright-report/. tests/e2e/reports/html-report/
|
||||
|
||||
# 清理测试容器
|
||||
docker rm -f e2e-test-runner-container
|
||||
echo "========================================"
|
||||
if [ $EXIT_CODE -eq 0 ]; then
|
||||
echo "测试执行成功!"
|
||||
else
|
||||
echo "测试执行失败!"
|
||||
fi
|
||||
echo "========================================"
|
||||
|
||||
REPORT_DIR="./tests/e2e/reports/"
|
||||
echo "HTML 报告已生成: $REPORT_DIR"
|
||||
|
||||
echo ""
|
||||
exit $EXIT_CODE
|
||||
164
tests/e2e/specs/devcontainer.e2e.test.ts
Normal file
@@ -0,0 +1,164 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { link } from 'node:fs';
|
||||
import { env } from 'node:process';
|
||||
import { Login } from './utils.e2e';
|
||||
import { time } from 'node:console';
|
||||
|
||||
|
||||
const DEFAULT_E2E_USER = 'testuser';
|
||||
const DEFAULT_E2E_PASS = '12345678';
|
||||
const DEFAULT_ADMIN_ID = '1';
|
||||
const isAlreadyInstalled = env.E2E_SKIP_INSTALL === 'true';
|
||||
const url1=env.DEVSTAR_URL;
|
||||
const GITEA_URL = (env.E2E_MODE === 'url') ? url1 : 'http://devstar:3000';
|
||||
const TEST_USER = isAlreadyInstalled ? (env.E2E_USERNAME || DEFAULT_E2E_USER) : DEFAULT_E2E_USER;
|
||||
const TEST_PASS = isAlreadyInstalled ? (env.E2E_PASSWORD || DEFAULT_E2E_PASS) : DEFAULT_E2E_PASS;
|
||||
const TEST_ADMIN_USER_ID = isAlreadyInstalled ? (env.E2E_ADMIN_ID || DEFAULT_ADMIN_ID) : DEFAULT_ADMIN_ID;
|
||||
const repoName='e2e-test-repo';
|
||||
test.describe('devcontainer 相关测试',()=>{
|
||||
test.beforeEach(async ({ page }) => {
|
||||
|
||||
await Login(page);
|
||||
});
|
||||
test('DevContainer 功能和配置', async ({ page,context }) => {
|
||||
|
||||
console.log(`正在创建新仓库: ${repoName}`);
|
||||
await page.goto(GITEA_URL + '/repo/create');
|
||||
await page.fill('input[name="repo_name"]', repoName);
|
||||
await page.getByRole('button', { name: '创建仓库' }).click();
|
||||
await expect(page).toHaveURL(GITEA_URL + '/' + TEST_USER + '/' + repoName);
|
||||
|
||||
console.log("仓库创建成功.");
|
||||
await expect(page).toHaveURL(GITEA_URL + '/' + TEST_USER + '/' + repoName);
|
||||
|
||||
console.log("正在点击 'Dev Container' 标签页...");
|
||||
await page.getByRole('link', { name: '开发容器' }).click();
|
||||
|
||||
console.log("正在点击 'Create' (创建模板) 按钮...");
|
||||
await page.getByRole('button', { name: /Create/i }).click();
|
||||
await page.waitForTimeout(10000);
|
||||
|
||||
console.log("模板已创建. 正在点击 'Edit' 按钮...");
|
||||
//await expect(page.getByText('devcontainer.json')).toBeVisible();
|
||||
|
||||
|
||||
//转换为JSON 字符串
|
||||
//const newJsonString = JSON.stringify(newJsonAsObject);
|
||||
|
||||
// 设置焦点
|
||||
// await page.locator('.view-lines > div:nth-child(20)').click();
|
||||
//console.log("正在手动删除模板内容 ");
|
||||
//for (let i = 0; i < 500; i++) {
|
||||
// await page.keyboard.press('Backspace');
|
||||
// }
|
||||
//粘贴字符串
|
||||
//console.log("正在粘贴JSON 内容...");
|
||||
// await page.keyboard.insertText(newJsonString);
|
||||
//await page.getByRole('button', { name: 'Commit Changes' }).click();
|
||||
//console.log("devcontainer.json 修改并提交成功.");
|
||||
//console.log("正在导航回 Dev Container 标签页进行验证...");
|
||||
//await page.getByRole('link', { name: '开发容器' }).click();
|
||||
|
||||
console.log("创建开发容器");
|
||||
await page.getByRole('button', { name: '创建开发容器' }).click();
|
||||
console.log("正在创建");
|
||||
const stopButton = page.getByRole('button', { name: '停止开发容器' });
|
||||
try {
|
||||
console.log('正在等待容器创建');
|
||||
//第一阶段刷新页面
|
||||
await expect(stopButton).toBeVisible({ timeout: 60000 });
|
||||
|
||||
} catch (error) {
|
||||
//刷新第一次
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
console.log('60s,正在刷新页面...');
|
||||
//加载service可能比较慢
|
||||
await page.waitForTimeout(180000);
|
||||
console.log('刷新页面完成,继续等待 (阶段2: 60s)...');
|
||||
//第二次刷新,容器应该正常启动了
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
await expect(stopButton).toBeVisible({ timeout: 30000 });
|
||||
await page.screenshot({ path: 'playwright-report/screenshot1.png', fullPage: true });
|
||||
}
|
||||
console.log("Dev container 创建成功!");
|
||||
await page.getByRole('button',{ name: '停止开发容器'}).click();
|
||||
console.log("正在停止");
|
||||
await expect(page.getByRole('button',{ name: '启动开发容器'})).toBeVisible({ timeout: 180000});
|
||||
console.log("成功停止开发容器!");
|
||||
await page.getByRole('button',{name: '启动开发容器'}).click();
|
||||
console.log("正在启动开发容器");
|
||||
await expect(page.getByRole('button',{name:'停止开发容器'})).toBeVisible({ timeout: 180000});
|
||||
console.log("成功启动!");
|
||||
console.log("保存开发容器");
|
||||
const pagePromise = context.waitForEvent('page');
|
||||
console.log("打开webterminal");
|
||||
await page.getByRole('link',{name: 'open with WebTerminal'}).click();
|
||||
const newPage = await pagePromise;
|
||||
await newPage.waitForLoadState(); // 等待新页面加载完成
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
await page.waitForTimeout(30000);
|
||||
await page.reload({ waitUntil: 'domcontentloaded' });
|
||||
await page.screenshot({ path: 'playwright-report/screenshot2.png', fullPage: true });
|
||||
console.log("Web Terminal: 新标签页已打开!");
|
||||
//await expect(newPage.getByText('Successfully connected to the container')).toBeVisible(); //这里ttyd里的信息PlayWright看不见,容器的交互没办法自动化测试
|
||||
await page.getByRole('link', { name: '删除开发容器' }).click();
|
||||
await page.locator('#delete-repo-devcontainer-of-user-modal')
|
||||
.getByRole('button', { name: '确认操作' })
|
||||
.click();
|
||||
console.log('正在删除!,可能较慢请等待');
|
||||
await page.waitForTimeout(3000);
|
||||
await expect(page.getByRole('button', { name: '创建开发容器' })).toBeVisible();
|
||||
console.log('成功删除!');
|
||||
console.log("test1 检查通过!");
|
||||
|
||||
//console.log("test2仓库");
|
||||
//await page.goto(GITEA_URL + '/'+ TEST_REPO_EMPTY);
|
||||
//await page.getByRole('link', { name: 'Dev Container' }).click();
|
||||
//await expect(page.getByText('Oops, it looks like there is no Dev Container Setting in this repository.')).toBeVisible();
|
||||
//console.log("test2 检查通过");
|
||||
|
||||
//console.log("test3仓库");
|
||||
//await page.goto(GITEA_URL+ '/' + TEST_REPO_INVALID);
|
||||
//await page.getByRole('link', { name: 'Dev Container' }).click();
|
||||
//await expect(page.getByText(' Invalid Dev Container Configuration')).toBeVisible();
|
||||
//console.log("test3检查通过");
|
||||
});
|
||||
test('权限修改相关', async ({ page }) => {
|
||||
|
||||
console.log('权限配置');
|
||||
await page.getByRole('link', { name: '管理后台' }).click();
|
||||
await page.getByText('身份及认证').click();
|
||||
await page.getByRole('link', { name: '帐户管理' }).click();
|
||||
await page.getByRole('row')
|
||||
.filter({ hasText: TEST_USER })
|
||||
.getByRole('link', { name: '编辑' })
|
||||
.click();
|
||||
const devContainerCheckbox = page.getByLabel(/允许创建开发容器/i);
|
||||
await devContainerCheckbox.uncheck();
|
||||
await page.getByRole('button', { name: '更新帐户' }).click();
|
||||
await page.goto(GITEA_URL + '/' + "e2e-devcontainer-test");
|
||||
const devContainerLink = page.getByRole('link', { name: '开发容器' });
|
||||
await expect(devContainerLink).toBeHidden({ timeout: 10000 });
|
||||
console.log('权限设置成功!');
|
||||
|
||||
console.log('现在恢复原环境');
|
||||
await page.goto(GITEA_URL+ '/-/admin/users/' + TEST_ADMIN_USER_ID + '/edit');
|
||||
await devContainerCheckbox.check();
|
||||
await page.getByRole('button', { name: '更新帐户' }).click();
|
||||
|
||||
console.log('现在清理测试仓库');
|
||||
console.log("正在导航到仓库设置页面...");
|
||||
await page.goto(GITEA_URL + '/' + TEST_USER + '/' + repoName + '/settings');
|
||||
|
||||
console.log("正在点击 'Delete This Repository' 按钮...");
|
||||
await page.getByRole('button', { name: '删除本仓库' }).click();
|
||||
await page.locator('#delete-repo-modal').waitFor();
|
||||
console.log(`正在输入 '${repoName}' 进行确认...`);
|
||||
await page.locator('#repo_name_to_delete').fill(repoName);
|
||||
|
||||
console.log("正在点击最终的删除确认按钮...");
|
||||
await page.locator('#delete-repo-modal').getByRole('button', { name: '删除本仓库' }).click();
|
||||
});
|
||||
})
|
||||
|
||||
|
||||
68
tests/e2e/specs/utils.e2e.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { type Page, expect } from '@playwright/test';
|
||||
import { env } from 'node:process';
|
||||
|
||||
const DEFAULT_E2E_USER = 'testuser';
|
||||
const DEFAULT_E2E_PASS = '12345678';
|
||||
const mode=env.E2E_MODE;
|
||||
|
||||
export async function Login(page: Page) {
|
||||
|
||||
const isInstalled = env.E2E_SKIP_INSTALL === 'true';
|
||||
|
||||
let username: string | undefined;
|
||||
let password: string | undefined;
|
||||
let wasUsingDefault = false;
|
||||
if(mode === 'url'){
|
||||
const url1=env.DEVSTAR_URL;
|
||||
if (isInstalled) {
|
||||
// "已安装" 模式
|
||||
|
||||
username = env.E2E_USERNAME || DEFAULT_E2E_USER;
|
||||
password = env.E2E_PASSWORD || DEFAULT_E2E_PASS;
|
||||
if (!env.E2E_USERNAME) {
|
||||
wasUsingDefault = true;
|
||||
}
|
||||
console.log(`"已安装"模式, 尝试用 ${username} 登录...`);
|
||||
} else {
|
||||
// "未安装" 模式
|
||||
username = DEFAULT_E2E_USER;
|
||||
password = DEFAULT_E2E_PASS;
|
||||
wasUsingDefault=true;
|
||||
console.log(` "刚安装"模式, 尝试用 ${username} 登录...`);
|
||||
}
|
||||
try {
|
||||
await page.goto(url1 + '/user/login');
|
||||
const captchaInput = page.locator('input[name="验证码"]');
|
||||
if (await captchaInput.isVisible()) {
|
||||
throw new Error('检测到验证码 (CAPTCHA)! E2E 测试无法继续。');
|
||||
}
|
||||
await page.fill('#user_name',username);
|
||||
await page.fill('#password', password);
|
||||
await page.getByRole('button', { name: '登录' }).click();
|
||||
await expect(page).toHaveURL(url1+ '/');
|
||||
console.log(`[LoginHelper] 用户 [${username}] 登录成功!`);;
|
||||
} catch (error) {
|
||||
console.error(`[LoginHelper] 登录失败! 原始错误: ${error.message}`);
|
||||
|
||||
let hint: string;
|
||||
|
||||
if (error.message.includes('CAPTCHA')) {
|
||||
// 提示 1: 验证码
|
||||
hint = `请禁用验证码!\n` ;
|
||||
} else if (wasUsingDefault) {
|
||||
// 提示 2: 你没输入, 且默认值失败了
|
||||
hint = `1. 登录失败, 且你没有提供 README.md 里描述的环境变量。\n` +
|
||||
`2. 脚本自动尝试了默认用户 (${DEFAULT_E2E_USER}),但失败了。\n` +
|
||||
`3. 请检查默认用户 (${DEFAULT_E2E_USER}) 在该目标上是否存在, 且密码是否正确。`;
|
||||
|
||||
} else {
|
||||
hint = `1. 登录失败, 你提供了 E2E_USERNAME (${username})。\n` +
|
||||
`2. 请检查你传入的 E2E_USERNAME 和 E2E_PASSWORD 环境变量是否正确。`;
|
||||
}
|
||||
|
||||
throw new Error(
|
||||
`[LoginHelper] 登录失败。\n\n${hint}\n`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||