Skip to content

Commit bdee396

Browse files
committed
feat(ci): 添加 Docker 镜像构建与发布
新增 CI 与容器部署支持:添加 GitHub Actions 工作流 (.github/workflows/taoyuan.yml)、本地/CI 用 Dockerfile 与 Dockerfile.ci、nginx.conf 与 .dockerignore.ci;更新 README 增加 Docker 部署说明并把 package.json 版本提升到 2.2.0。其它改动包括: - 前端资源与静态托管:复制构建产物到 nginx,并优化缓存策略(nginx.conf)。 - Android/打包调整:android/app/build.gradle 增加产物重命名(taoyuan-<version>.apk)。 - Electron 微调:剥离 WWW-Authenticate 响应头,避免原生认证弹窗。 - UI/前端改进:新增 Divider 组件并在多处使用,更新若干 Vue 组件与样式(包括移动端安全区 safe-area 支持)、新增支付图标资源(alipay/wechat)、更新 logo。部分音效注释与文本微调(“金币”改为“铜钱”)。 总体目的:为项目提供可构建的 Docker 镜像与 CI 发布流程,优化静态托管与多平台运行体验,并做若干前端与打包体验优化。
1 parent 970351c commit bdee396

65 files changed

Lines changed: 2744 additions & 1293 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore.ci

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# CI 构建专用 dockerignore
2+
# 只保留 docs/ 和 nginx.conf,排除其他所有文件
3+
4+
*
5+
6+
!docs/
7+
!nginx.conf

.github/workflows/taoyuan.yml

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
name: 构建并发布 Docker 镜像
2+
3+
on:
4+
push:
5+
branches: [main]
6+
tags: ['v*.*.*']
7+
workflow_dispatch:
8+
9+
permissions:
10+
contents: read
11+
packages: write
12+
13+
jobs:
14+
build-and-push:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- name: 检出代码
18+
uses: actions/checkout@v6
19+
with:
20+
fetch-depth: 0
21+
22+
- name: 设置 Node.js
23+
uses: actions/setup-node@v6
24+
with:
25+
node-version: '20'
26+
27+
- name: 设置 pnpm
28+
uses: pnpm/action-setup@v4
29+
with:
30+
version: latest
31+
32+
- name: 缓存 pnpm 依赖
33+
uses: actions/cache@v5
34+
with:
35+
path: |
36+
~/.pnpm-store
37+
node_modules
38+
key: ${{ runner.os }}-pnpm-${{ hashFiles('**/pnpm-lock.yaml') }}
39+
restore-keys: |
40+
${{ runner.os }}-pnpm-
41+
42+
- name: 安装依赖
43+
run: pnpm install --frozen-lockfile
44+
45+
- name: 构建项目
46+
run: pnpm run build
47+
48+
- name: 验证构建产物
49+
run: |
50+
if [ ! -d "docs" ]; then
51+
echo "构建失败:docs 目录不存在"
52+
exit 1
53+
fi
54+
if [ ! -f "docs/index.html" ]; then
55+
echo "构建失败:docs/index.html 不存在"
56+
exit 1
57+
fi
58+
59+
BUILD_TIME=$(stat -c %Y docs/index.html 2>/dev/null || stat -f %m docs/index.html 2>/dev/null || echo "0")
60+
CURRENT_TIME=$(date +%s)
61+
TIME_DIFF=$((CURRENT_TIME - BUILD_TIME))
62+
63+
echo "构建产物信息:"
64+
echo " 时间差: ${TIME_DIFF}秒"
65+
66+
if [ $TIME_DIFF -gt 300 ]; then
67+
echo "警告: 构建产物可能不是最新的(超过5分钟)"
68+
fi
69+
70+
echo "构建产物验证通过"
71+
ls -la docs/
72+
73+
- name: 获取当前日期
74+
id: date
75+
run: echo "date=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" >> $GITHUB_OUTPUT
76+
77+
- name: 获取版本号
78+
id: version
79+
run: |
80+
VERSION=$(node -p "require('./package.json').version")
81+
echo "version=$VERSION" >> $GITHUB_OUTPUT
82+
echo "当前版本: $VERSION"
83+
84+
- name: 准备 CI 构建环境
85+
run: |
86+
cp .dockerignore.ci .dockerignore
87+
echo "已切换到 CI 构建模式"
88+
89+
- name: 设置 QEMU
90+
uses: docker/setup-qemu-action@v3
91+
92+
- name: 设置 Docker Buildx
93+
uses: docker/setup-buildx-action@v3
94+
95+
# 登录 GHCR(始终执行)
96+
- name: 登录 GitHub Container Registry
97+
uses: docker/login-action@v3
98+
with:
99+
registry: ghcr.io
100+
username: ${{ github.actor }}
101+
password: ${{ secrets.GITHUB_TOKEN }}
102+
103+
# 登录 Docker Hub(仅在配置了用户名时执行)
104+
- name: 登录 Docker Hub
105+
if: vars.DOCKERHUB_USERNAME != ''
106+
uses: docker/login-action@v3
107+
with:
108+
username: ${{ vars.DOCKERHUB_USERNAME }}
109+
password: ${{ secrets.DOCKERHUB_TOKEN }}
110+
111+
- name: 构建并推送多架构镜像
112+
uses: docker/build-push-action@v6
113+
with:
114+
context: .
115+
file: ./Dockerfile.ci
116+
platforms: linux/amd64,linux/arm64
117+
push: true
118+
no-cache: false
119+
pull: true
120+
tags: |
121+
ghcr.io/${{ github.repository_owner }}/taoyuan:latest
122+
ghcr.io/${{ github.repository_owner }}/taoyuan:${{ steps.version.outputs.version }}
123+
ghcr.io/${{ github.repository_owner }}/taoyuan:${{ github.sha }}
124+
${{ vars.DOCKERHUB_USERNAME && format('{0}/taoyuan:latest', vars.DOCKERHUB_USERNAME) || '' }}
125+
${{ vars.DOCKERHUB_USERNAME && format('{0}/taoyuan:{1}', vars.DOCKERHUB_USERNAME, steps.version.outputs.version) || '' }}
126+
${{ vars.DOCKERHUB_USERNAME && format('{0}/taoyuan:{1}', vars.DOCKERHUB_USERNAME, github.sha) || '' }}
127+
cache-from: type=gha
128+
cache-to: type=gha,mode=max
129+
build-args: |
130+
BUILD_DATE=${{ steps.date.outputs.date }}
131+
VERSION=${{ steps.version.outputs.version }}
132+
COMMIT_SHA=${{ github.sha }}
133+
labels: |
134+
org.opencontainers.image.title=桃源乡
135+
org.opencontainers.image.description=桃源乡 - 文字农场模拟游戏
136+
org.opencontainers.image.version=${{ steps.version.outputs.version }}
137+
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
138+
org.opencontainers.image.revision=${{ github.sha }}
139+
org.opencontainers.image.created=${{ steps.date.outputs.date }}

Dockerfile

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# 本地构建用的 Dockerfile
2+
# 支持完整的源代码构建流程
3+
4+
FROM node:20-alpine AS builder
5+
6+
# 设置工作目录
7+
WORKDIR /app
8+
9+
# 复制 package 文件
10+
COPY package.json pnpm-lock.yaml ./
11+
12+
# 安装 pnpm
13+
RUN npm install -g pnpm
14+
15+
# 安装依赖
16+
RUN pnpm install --frozen-lockfile
17+
18+
# 复制源代码
19+
COPY . .
20+
21+
# 构建项目
22+
RUN pnpm run build
23+
24+
# 生产阶段
25+
FROM nginx:alpine
26+
27+
# 复制 nginx 配置文件
28+
COPY nginx.conf /etc/nginx/conf.d/default.conf
29+
30+
# 清理默认的 nginx 静态文件
31+
RUN rm -rf /usr/share/nginx/html/*
32+
33+
# 复制构建产物到 nginx 静态文件目录
34+
COPY --from=builder /app/docs /usr/share/nginx/html
35+
36+
# 暴露端口
37+
EXPOSE 80
38+
39+
# 启动 nginx
40+
CMD ["nginx", "-g", "daemon off;"]

Dockerfile.ci

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# CI 专用 Dockerfile
2+
# 前端已在 CI runner 中构建完成,此处仅复制构建产物到 nginx
3+
4+
FROM nginx:alpine
5+
6+
ARG BUILD_DATE
7+
ARG VERSION
8+
ARG COMMIT_SHA
9+
10+
LABEL org.opencontainers.image.created="${BUILD_DATE}"
11+
LABEL org.opencontainers.image.version="${VERSION}"
12+
LABEL org.opencontainers.image.revision="${COMMIT_SHA}"
13+
14+
# 复制 nginx 配置
15+
COPY nginx.conf /etc/nginx/conf.d/default.conf
16+
17+
# 清理默认静态文件
18+
RUN rm -rf /usr/share/nginx/html/*
19+
20+
# 复制 CI 已构建好的产物
21+
COPY docs /usr/share/nginx/html
22+
23+
EXPOSE 80
24+
25+
CMD ["nginx", "-g", "daemon off;"]

README.md

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
<div align="center">
2-
<img src="images/logo.png" alt="桃源乡" width="128" style="image-rendering: pixelated;" />
3-
</div>
2+
<img src="images/logo.png" alt="桃源乡" width="400" />
3+
4+
# 桃源乡
45

5-
# 桃源乡
6+
> 传说在群山深处,有一处与世隔绝的村落——桃源乡。
7+
> 这里四季分明,民风淳朴,但近年来年轻人纷纷离去,村庄日渐冷清。
8+
> 你收到一封来自已故祖父的信,信中附有一把铜钥匙和一张泛黄的地契……
69
7-
> 传说在群山深处,有一处与世隔绝的村落——桃源乡。
8-
> 这里四季分明,民风淳朴,但近年来年轻人纷纷离去,村庄日渐冷清。
9-
> 你收到一封来自已故祖父的信,信中附有一把铜钥匙和一张泛黄的地契……
10+
一款文字版田园模拟经营游戏,灵感来自星露谷物语,采用像素 + 中国风视觉设计。纯客户端运行,无需后端服务器。
1011

11-
一款文字版田园模拟经营游戏,灵感来自星露谷物语,采用像素 + 中国风视觉设计。纯客户端运行,无需后端服务器。
12+
[![GitHub Release](https://img.shields.io/github/v/release/setube/taoyuan?style=flat&logo=github&label=Release)](https://github.com/setube/taoyuan/releases/latest)
13+
[![License: CC BY-NC 4.0](https://img.shields.io/badge/License-CC%20BY--NC%204.0-lightgrey.svg)](https://creativecommons.org/licenses/by-nc/4.0)
14+
[![Tap Tap](https://img.shields.io/badge/TapTap-%E6%A1%83%E6%BA%90%E4%B9%A1-18d6e0)](https://www.taptap.cn/app/816558)
15+
[![Featured|HelloGitHub](https://abroad.hellogithub.com/v1/widgets/recommend.svg?rid=e73a691ffcfa4d0e92a05912fe8c0b46&claim_uid=OCYdts5lPczHag4&theme=small)](https://hellogithub.com/repository/e73a691ffcfa4d0e92a05912fe8c0b46)
16+
</div>
1217

1318
## 游戏特色
1419

@@ -75,6 +80,22 @@ pnpm preview
7580
pnpm build:electron
7681
```
7782

83+
### Docker 部署
84+
85+
```bash
86+
# 方式一:使用预构建镜像(推荐)
87+
docker run -d -p 8080:80 ghcr.io/setube/taoyuan:latest
88+
89+
# 方式二:指定版本
90+
docker run -d -p 8080:80 ghcr.io/setube/taoyuan:<version>
91+
92+
# 方式三:本地构建镜像
93+
docker build -t taoyuan .
94+
docker run -d -p 8080:80 taoyuan
95+
```
96+
97+
访问 `http://localhost:8080` 即可开始游戏。
98+
7899
## 技术栈
79100

80101
| 技术 | 版本 | 用途 |
@@ -160,7 +181,7 @@ src/
160181

161182
## 交流
162183

163-
- QQ 群:920930589
184+
- QQ 群:[920930589](https://qm.qq.com/q/2BVaTTwDkI)
164185
- GitHub:[https://github.com/setube/taoyuan](https://github.com/setube/taoyuan)
165186

166187
## 许可证

android/app/build.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,11 @@ android {
4848
signingConfig signingConfigs.release
4949
}
5050
}
51+
applicationVariants.all { variant ->
52+
variant.outputs.all {
53+
outputFileName = "taoyuan-${variant.versionName}.apk"
54+
}
55+
}
5156
}
5257

5358
repositories {

electron/main.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ const createWindow = () => {
176176
headers['access-control-allow-origin'] = ['*']
177177
headers['access-control-allow-methods'] = ['GET, PUT, DELETE, PROPFIND, HEAD, OPTIONS']
178178
headers['access-control-allow-headers'] = ['Authorization, Content-Type, Depth']
179+
// 剥离 WWW-Authenticate 防止浏览器弹出原生认证对话框(由应用自行处理认证错误)
180+
delete headers['www-authenticate']
181+
delete headers['WWW-Authenticate']
179182
callback({ responseHeaders: headers })
180183
})
181184

images/logo.png

12.5 KB
Loading

nginx.conf

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
server {
2+
listen 80;
3+
server_name localhost;
4+
root /usr/share/nginx/html;
5+
index index.html;
6+
7+
# gzip 压缩
8+
gzip on;
9+
gzip_vary on;
10+
gzip_min_length 1024;
11+
gzip_types text/plain text/css application/json application/javascript text/xml application/xml text/javascript image/svg+xml;
12+
13+
# 静态资源缓存(带哈希的文件长期缓存)
14+
location /assets/ {
15+
expires 1y;
16+
add_header Cache-Control "public, immutable";
17+
}
18+
19+
# SPA 路由回退
20+
location / {
21+
try_files $uri $uri/ /index.html;
22+
}
23+
}

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"qq": "920930589",
55
"tapid": "816558",
66
"private": true,
7-
"version": "2.1.0",
7+
"version": "2.2.0",
88
"type": "module",
99
"main": "dist-electron/main.js",
1010
"scripts": {

0 commit comments

Comments
 (0)