clouddreamai-cicd-setup 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,171 @@
1
+ # GitLab CI/CD 配置文件 - Vue/React 项目(GitLab Container Registry)
2
+ stages:
3
+ - lint
4
+ - build
5
+ - deploy
6
+
7
+ # 全局变量
8
+ variables:
9
+ DOCKER_DRIVER: overlay2
10
+ NODE_VERSION: "20"
11
+ APP_NAME: "{{APP_NAME}}"
12
+ GIT_STRATEGY: fetch
13
+ GIT_SSL_NO_VERIFY: "true"
14
+ DOCKER_PULL_POLICY: if-not-present
15
+ # 使用 GitLab Container Registry
16
+ DOCKER_IMAGE: $CI_REGISTRY_IMAGE
17
+
18
+ # 全局缓存配置
19
+ cache:
20
+ key: ${CI_COMMIT_REF_SLUG}-${CI_JOB_NAME}
21
+ paths:
22
+ - node_modules/
23
+ - .npm/
24
+
25
+ # 代码质量检查阶段
26
+ lint:
27
+ stage: lint
28
+ image:
29
+ name: node:20-alpine
30
+ pull_policy: if-not-present
31
+ cache:
32
+ key: ${CI_COMMIT_REF_SLUG}-node-modules
33
+ paths:
34
+ - node_modules/
35
+ - .npm/
36
+ policy: pull-push
37
+ before_script:
38
+ - apk add --no-cache git curl
39
+ - git --version
40
+ - echo "Setting up Git authentication..."
41
+ - git config --global http.sslVerify false
42
+ - git config --global url."https://oauth2:${GITLAB_ACCESS_TOKEN}@{{GITLAB_HOST}}".insteadOf "http://{{GITLAB_HOST}}"
43
+ - git config --global url."https://oauth2:${GITLAB_ACCESS_TOKEN}@{{GITLAB_HOST}}".insteadOf "https://{{GITLAB_HOST}}"
44
+ - npm ci --cache .npm --prefer-offline
45
+ script:
46
+ - {{LINT_COMMAND}}
47
+ only:
48
+ - merge_requests
49
+ - main
50
+ - develop
51
+
52
+ # 构建阶段(使用 GitLab Container Registry)
53
+ build:
54
+ stage: build
55
+ cache: {}
56
+ image:
57
+ name: docker:24.0.5
58
+ pull_policy: if-not-present
59
+ before_script:
60
+ - docker info
61
+ - echo "登录到 GitLab Container Registry..."
62
+ # 使用 GitLab CI 预定义变量登录
63
+ - echo "$CI_REGISTRY_PASSWORD" | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
64
+ script:
65
+ - echo "尝试拉取最新镜像作为缓存..."
66
+ - docker pull $DOCKER_IMAGE:latest || true
67
+ - echo "构建Docker镜像..."
68
+ - docker build --build-arg BUILDKIT_INLINE_CACHE=1 --cache-from $DOCKER_IMAGE:latest -t $DOCKER_IMAGE:$CI_COMMIT_SHA -t $DOCKER_IMAGE:latest .
69
+ - echo "推送镜像到 GitLab Container Registry..."
70
+ - docker push $DOCKER_IMAGE:$CI_COMMIT_SHA
71
+ - docker push $DOCKER_IMAGE:latest
72
+ only:
73
+ - main
74
+ - develop
75
+
76
+ # 开发环境部署(develop 分支自动触发)
77
+ deploy_dev:
78
+ stage: deploy
79
+ image:
80
+ name: alpine:latest
81
+ pull_policy: if-not-present
82
+ variables:
83
+ ENV_TYPE: "development"
84
+ ENV_FILE_CONTENT: $DEV_ENV_FILE
85
+ DEPLOY_DIR: "{{DEPLOY_DIR}}"
86
+ APP_PORT: "{{DEV_PORT}}"
87
+ cache: {}
88
+ before_script:
89
+ - apk add --no-cache openssh-client docker-compose bash openssl rsync
90
+ - eval $(ssh-agent -s)
91
+ - mkdir -p ~/.ssh
92
+ - chmod 700 ~/.ssh
93
+ - # 加载 SSH 私钥(PEM 格式原始内容)
94
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
95
+ - ssh-keyscan $TEST_SERVER_HOST >> ~/.ssh/known_hosts
96
+ - chmod 644 ~/.ssh/known_hosts
97
+ script:
98
+ - ssh root@$TEST_SERVER_HOST "mkdir -p $DEPLOY_DIR"
99
+ - ssh root@$TEST_SERVER_HOST "which rsync || apk add --no-cache rsync"
100
+ - rsync -avz --delete --exclude='.git/' --exclude='node_modules/' . root@$TEST_SERVER_HOST:$DEPLOY_DIR/
101
+ # 传递 GitLab Registry 凭据到部署服务器
102
+ - ssh root@$TEST_SERVER_HOST "export REGISTRY_URL='$CI_REGISTRY' && export REGISTRY_USERNAME='$CI_REGISTRY_USER' && export REGISTRY_PASSWORD='$CI_REGISTRY_PASSWORD' && export APP_PORT='$APP_PORT' && cd $DEPLOY_DIR && chmod +x ci/deploy.sh && bash ci/deploy.sh $ENV_TYPE gitlab"
103
+ environment:
104
+ name: development
105
+ url: {{DEV_URL}}
106
+ only:
107
+ - develop
108
+
109
+ # 生产环境部署(main 分支手动触发)
110
+ deploy_prod:
111
+ stage: deploy
112
+ image:
113
+ name: alpine:latest
114
+ pull_policy: if-not-present
115
+ variables:
116
+ ENV_TYPE: "production"
117
+ ENV_FILE_CONTENT: $PROD_ENV_FILE
118
+ DEPLOY_DIR: "{{DEPLOY_DIR}}"
119
+ APP_PORT: "{{PROD_PORT}}"
120
+ cache: {}
121
+ before_script:
122
+ - apk add --no-cache openssh-client docker-compose bash openssl rsync
123
+ - eval $(ssh-agent -s)
124
+ - mkdir -p ~/.ssh
125
+ - chmod 700 ~/.ssh
126
+ - # 加载 SSH 私钥(PEM 格式原始内容)
127
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
128
+ - ssh-keyscan $PROD_SERVER_HOST >> ~/.ssh/known_hosts
129
+ - chmod 644 ~/.ssh/known_hosts
130
+ script:
131
+ - ssh root@$PROD_SERVER_HOST "mkdir -p $DEPLOY_DIR"
132
+ - ssh root@$PROD_SERVER_HOST "which rsync || apk add --no-cache rsync"
133
+ - rsync -avz --delete --exclude='.git/' --exclude='node_modules/' . root@$PROD_SERVER_HOST:$DEPLOY_DIR/
134
+ # 传递 GitLab Registry 凭据到部署服务器
135
+ - ssh root@$PROD_SERVER_HOST "export REGISTRY_URL='$CI_REGISTRY' && export REGISTRY_USERNAME='$CI_REGISTRY_USER' && export REGISTRY_PASSWORD='$CI_REGISTRY_PASSWORD' && export APP_PORT='$APP_PORT' && cd $DEPLOY_DIR && chmod +x ci/deploy.sh && bash ci/deploy.sh $ENV_TYPE gitlab"
136
+ environment:
137
+ name: production
138
+ url: {{PROD_URL}}
139
+ only:
140
+ - main
141
+ when: manual
142
+
143
+ # 回滚部署(可选)
144
+ rollback:
145
+ stage: deploy
146
+ image:
147
+ name: alpine:latest
148
+ pull_policy: if-not-present
149
+ variables:
150
+ DEPLOY_DIR: "{{DEPLOY_DIR}}"
151
+ APP_PORT: "{{PROD_PORT}}"
152
+ cache: {}
153
+ before_script:
154
+ - apk add --no-cache openssh-client openssl
155
+ - eval $(ssh-agent -s)
156
+ - mkdir -p ~/.ssh
157
+ - chmod 700 ~/.ssh
158
+ - # 加载 SSH 私钥(PEM 格式原始内容)
159
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add -
160
+ - ssh-keyscan $PROD_SERVER_HOST >> ~/.ssh/known_hosts
161
+ - chmod 644 ~/.ssh/known_hosts
162
+ script:
163
+ - ssh root@$PROD_SERVER_HOST "cd $DEPLOY_DIR && export APP_PORT=$APP_PORT && docker-compose down"
164
+ - ssh root@$PROD_SERVER_HOST "cd $DEPLOY_DIR && export APP_PORT=$APP_PORT && docker-compose pull"
165
+ - ssh root@$PROD_SERVER_HOST "cd $DEPLOY_DIR && export APP_PORT=$APP_PORT && docker-compose up -d"
166
+ environment:
167
+ name: production
168
+ url: {{PROD_URL}}
169
+ when: manual
170
+ only:
171
+ - main
@@ -83,6 +83,7 @@ deploy_dev:
83
83
  ENV_FILE_CONTENT: $DEV_ENV_FILE
84
84
  DEPLOY_DIR: "{{DEPLOY_DIR}}"
85
85
  APP_PORT: "{{DEV_PORT}}"
86
+ REGISTRY_TYPE: "{{REGISTRY_TYPE}}"
86
87
  cache: {}
87
88
  before_script:
88
89
  - apk add --no-cache openssh-client docker-compose bash openssl rsync
@@ -96,8 +97,7 @@ deploy_dev:
96
97
  - ssh root@$TEST_SERVER_HOST "mkdir -p $DEPLOY_DIR"
97
98
  - ssh root@$TEST_SERVER_HOST "which rsync || apk add --no-cache rsync"
98
99
  - rsync -avz --delete --exclude='.git/' --exclude='node_modules/' . root@$TEST_SERVER_HOST:$DEPLOY_DIR/
99
- - ssh root@$TEST_SERVER_HOST "export DOCKER_HUB_USERNAME='$DOCKER_HUB_USERNAME' && export DOCKER_HUB_PASSWORD='$DOCKER_HUB_PASSWORD' && export APP_PORT='$APP_PORT' && cd $DEPLOY_DIR && chmod +x ci/deploy.sh && bash ci/deploy.sh $ENV_TYPE"
100
- - ssh root@$TEST_SERVER_HOST "sleep 30 && curl -f http://localhost:$APP_PORT/ || exit 1"
100
+ - ssh root@$TEST_SERVER_HOST "export DOCKER_HUB_USERNAME='$DOCKER_HUB_USERNAME' && export DOCKER_HUB_PASSWORD='$DOCKER_HUB_PASSWORD' && export APP_PORT='$APP_PORT' && cd $DEPLOY_DIR && chmod +x ci/deploy.sh && bash ci/deploy.sh $ENV_TYPE $REGISTRY_TYPE"
101
101
  environment:
102
102
  name: development
103
103
  url: {{DEV_URL}}
@@ -115,6 +115,7 @@ deploy_prod:
115
115
  ENV_FILE_CONTENT: $PROD_ENV_FILE
116
116
  DEPLOY_DIR: "{{DEPLOY_DIR}}"
117
117
  APP_PORT: "{{PROD_PORT}}"
118
+ REGISTRY_TYPE: "{{REGISTRY_TYPE}}"
118
119
  cache: {}
119
120
  before_script:
120
121
  - apk add --no-cache openssh-client docker-compose bash openssl rsync
@@ -128,8 +129,7 @@ deploy_prod:
128
129
  - ssh root@$PROD_SERVER_HOST "mkdir -p $DEPLOY_DIR"
129
130
  - ssh root@$PROD_SERVER_HOST "which rsync || apk add --no-cache rsync"
130
131
  - rsync -avz --delete --exclude='.git/' --exclude='node_modules/' . root@$PROD_SERVER_HOST:$DEPLOY_DIR/
131
- - ssh root@$PROD_SERVER_HOST "export DOCKER_HUB_USERNAME='$DOCKER_HUB_USERNAME' && export DOCKER_HUB_PASSWORD='$DOCKER_HUB_PASSWORD' && export APP_PORT='$APP_PORT' && cd $DEPLOY_DIR && chmod +x ci/deploy.sh && bash ci/deploy.sh $ENV_TYPE"
132
- - ssh root@$PROD_SERVER_HOST "sleep 30 && curl -f http://localhost:$APP_PORT/ || exit 1"
132
+ - ssh root@$PROD_SERVER_HOST "export DOCKER_HUB_USERNAME='$DOCKER_HUB_USERNAME' && export DOCKER_HUB_PASSWORD='$DOCKER_HUB_PASSWORD' && export APP_PORT='$APP_PORT' && cd $DEPLOY_DIR && chmod +x ci/deploy.sh && bash ci/deploy.sh $ENV_TYPE $REGISTRY_TYPE"
133
133
  environment:
134
134
  name: production
135
135
  url: {{PROD_URL}}
@@ -9,16 +9,76 @@ set -e
9
9
  APP_NAME="{{APP_NAME}}"
10
10
  DEPLOY_PATH="{{DEPLOY_DIR}}"
11
11
  ENV_TYPE=${1:-development}
12
+ REGISTRY_TYPE=${2:-dockerhub} # 镜像仓库类型: gitlab, dockerhub, custom, none
12
13
 
13
- # 根据环境设置端口
14
+ # 根据环境设置端口和域名
14
15
  if [ "$ENV_TYPE" = "production" ]; then
15
16
  export APP_PORT={{PROD_PORT}}
17
+ export DOMAIN="{{PROD_DOMAIN}}"
16
18
  else
17
19
  export APP_PORT={{DEV_PORT}}
20
+ export DOMAIN="{{DEV_DOMAIN}}"
18
21
  fi
19
22
 
20
23
  echo "开始部署 $APP_NAME 到 $ENV_TYPE 环境 (端口: $APP_PORT)..."
21
24
 
25
+ # Nginx 反向代理配置函数
26
+ configure_nginx_proxy() {
27
+ local DOMAIN=$1
28
+ local PORT=$2
29
+
30
+ if [ -z "$DOMAIN" ]; then
31
+ echo "跳过 Nginx 配置(未提供域名)"
32
+ return
33
+ fi
34
+
35
+ echo "配置 Nginx 反向代理: $DOMAIN -> localhost:$PORT"
36
+
37
+ # 检查宝塔是否安装
38
+ if [ ! -d "/www/server/panel/vhost/nginx" ]; then
39
+ echo "警告:未检测到宝塔面板,跳过 Nginx 配置"
40
+ return
41
+ fi
42
+
43
+ # 创建 Nginx 配置
44
+ cat > /www/server/panel/vhost/nginx/${DOMAIN}.conf << EOF
45
+ # 由 CloudDreamAI CI/CD 自动生成 - $(date)
46
+ server {
47
+ listen 80;
48
+ server_name ${DOMAIN};
49
+
50
+ access_log /www/wwwlogs/${DOMAIN}.log;
51
+ error_log /www/wwwlogs/${DOMAIN}.error.log;
52
+
53
+ location / {
54
+ proxy_pass http://127.0.0.1:${PORT};
55
+ proxy_set_header Host \$host;
56
+ proxy_set_header X-Real-IP \$remote_addr;
57
+ proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
58
+ proxy_set_header X-Forwarded-Proto \$scheme;
59
+
60
+ # WebSocket 支持
61
+ proxy_http_version 1.1;
62
+ proxy_set_header Upgrade \$http_upgrade;
63
+ proxy_set_header Connection "upgrade";
64
+
65
+ # 超时设置
66
+ proxy_connect_timeout 60s;
67
+ proxy_send_timeout 60s;
68
+ proxy_read_timeout 60s;
69
+ }
70
+ }
71
+ EOF
72
+
73
+ # 重载 Nginx
74
+ if command -v nginx &> /dev/null; then
75
+ nginx -t && nginx -s reload
76
+ echo "✓ Nginx 配置已更新并重载"
77
+ else
78
+ echo "警告:未找到 nginx 命令,请手动重载 Nginx"
79
+ fi
80
+ }
81
+
22
82
  # 确保目录存在
23
83
  mkdir -p $DEPLOY_PATH
24
84
 
@@ -96,35 +156,78 @@ fi
96
156
  # 拉取最新镜像并启动Docker容器
97
157
  echo "拉取最新镜像并启动Docker容器..."
98
158
 
99
- # 登录Docker Hub(如果设置了凭据)
100
- if [ -n "$DOCKER_HUB_USERNAME" ] && [ -n "$DOCKER_HUB_PASSWORD" ]; then
101
- echo "登录Docker Hub..."
102
- echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_USERNAME" --password-stdin
159
+ # 根据Registry类型登录
160
+ if [ "$REGISTRY_TYPE" = "gitlab" ]; then
161
+ # GitLab Container Registry
162
+ if [ -n "$REGISTRY_URL" ] && [ -n "$REGISTRY_USERNAME" ] && [ -n "$REGISTRY_PASSWORD" ]; then
163
+ echo "登录 GitLab Container Registry: $REGISTRY_URL"
164
+ echo "$REGISTRY_PASSWORD" | docker login -u "$REGISTRY_USERNAME" --password-stdin "$REGISTRY_URL"
165
+ else
166
+ echo "警告:未设置 GitLab Registry 凭据"
167
+ fi
168
+ elif [ "$REGISTRY_TYPE" = "dockerhub" ]; then
169
+ # Docker Hub
170
+ if [ -n "$DOCKER_HUB_USERNAME" ] && [ -n "$DOCKER_HUB_PASSWORD" ]; then
171
+ echo "登录 Docker Hub..."
172
+ echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_USERNAME" --password-stdin
173
+ else
174
+ echo "未设置 Docker Hub 凭据,尝试匿名拉取镜像..."
175
+ fi
176
+ elif [ "$REGISTRY_TYPE" = "custom" ]; then
177
+ # 自建 Registry
178
+ if [ -n "$REGISTRY_URL" ] && [ -n "$REGISTRY_USERNAME" ] && [ -n "$REGISTRY_PASSWORD" ]; then
179
+ echo "登录自建 Registry: $REGISTRY_URL"
180
+ echo "$REGISTRY_PASSWORD" | docker login -u "$REGISTRY_USERNAME" --password-stdin "$REGISTRY_URL"
181
+ else
182
+ echo "错误:未设置自建 Registry 凭据"
183
+ exit 1
184
+ fi
185
+ elif [ "$REGISTRY_TYPE" = "none" ]; then
186
+ # 不使用 Registry,仅本地构建
187
+ echo "不使用镜像仓库,将使用本地构建..."
103
188
  else
104
- echo "未设置Docker Hub凭据,尝试匿名拉取镜像..."
189
+ echo "警告:未知的 Registry 类型: $REGISTRY_TYPE,尝试使用 Docker Hub..."
190
+ if [ -n "$DOCKER_HUB_USERNAME" ] && [ -n "$DOCKER_HUB_PASSWORD" ]; then
191
+ echo "$DOCKER_HUB_PASSWORD" | docker login -u "$DOCKER_HUB_USERNAME" --password-stdin
192
+ fi
105
193
  fi
106
194
 
107
195
  # 停止并移除旧容器
108
196
  echo "清理现有容器..."
109
197
  docker-compose down --remove-orphans || true
110
- docker container ls -a | grep '$APP_NAME' | awk '{print $1}' | xargs -r docker container rm -f
198
+ docker container ls -a | grep "$APP_NAME" | awk '{print $1}' | xargs -r docker container rm -f
111
199
 
112
- # 尝试拉取镜像
113
- echo "尝试拉取Docker Hub镜像..."
114
- if docker-compose pull; then
115
- echo "镜像拉取成功,启动容器..."
116
- APP_PORT=$APP_PORT docker-compose up -d
117
- else
118
- echo "无法从Docker Hub拉取镜像,检查是否存在Dockerfile进行本地构建..."
200
+ # 尝试拉取镜像或本地构建
201
+ if [ "$REGISTRY_TYPE" = "none" ]; then
202
+ # 仅使用本地构建
203
+ echo "使用本地构建模式..."
119
204
  if [ -f "Dockerfile" ]; then
120
205
  echo "找到Dockerfile,进行本地构建..."
121
206
  export DOCKER_IMAGE="$APP_NAME:local"
122
207
  docker build -t $DOCKER_IMAGE .
123
208
  APP_PORT=$APP_PORT docker-compose up -d
124
209
  else
125
- echo "错误:无法拉取镜像且未找到Dockerfile,部署失败"
210
+ echo "错误:未找到Dockerfile,无法本地构建"
126
211
  exit 1
127
212
  fi
213
+ else
214
+ # 尝试从Registry拉取镜像
215
+ echo "尝试从镜像仓库拉取镜像..."
216
+ if docker-compose pull; then
217
+ echo "镜像拉取成功,启动容器..."
218
+ APP_PORT=$APP_PORT docker-compose up -d
219
+ else
220
+ echo "无法从镜像仓库拉取镜像,检查是否存在Dockerfile进行本地构建..."
221
+ if [ -f "Dockerfile" ]; then
222
+ echo "找到Dockerfile,进行本地构建..."
223
+ export DOCKER_IMAGE="$APP_NAME:local"
224
+ docker build -t $DOCKER_IMAGE .
225
+ APP_PORT=$APP_PORT docker-compose up -d
226
+ else
227
+ echo "错误:无法拉取镜像且未找到Dockerfile,部署失败"
228
+ exit 1
229
+ fi
230
+ fi
128
231
  fi
129
232
 
130
233
  # 检查部署状态
@@ -138,4 +241,7 @@ else
138
241
  exit 1
139
242
  fi
140
243
 
244
+ # 配置 Nginx 反向代理
245
+ configure_nginx_proxy "$DOMAIN" "$APP_PORT"
246
+
141
247
  echo "部署完成!"