clouddreamai-cicd-setup 1.0.0

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.
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "clouddreamai-cicd-setup",
3
+ "version": "1.0.0",
4
+ "description": "CloudDreamAI GitLab CI/CD 自动配置工具 - 支持 NestJS/Vue/React 项目的一键 CI/CD 配置",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "bin": {
8
+ "cicd-setup": "./bin/cicd-setup.js"
9
+ },
10
+ "scripts": {
11
+ "build": "tsc",
12
+ "dev": "ts-node src/cli.ts",
13
+ "start": "node dist/cli.js",
14
+ "prepublishOnly": "npm run build"
15
+ },
16
+ "keywords": [
17
+ "gitlab",
18
+ "cicd",
19
+ "devops",
20
+ "automation",
21
+ "nestjs",
22
+ "vue",
23
+ "react",
24
+ "docker"
25
+ ],
26
+ "author": "CloudDreamAI",
27
+ "license": "MIT",
28
+ "dependencies": {
29
+ "axios": "^1.6.0",
30
+ "chalk": "^4.1.2",
31
+ "commander": "^11.1.0",
32
+ "inquirer": "^8.2.6",
33
+ "ora": "^5.4.1"
34
+ },
35
+ "devDependencies": {
36
+ "@types/inquirer": "^8.2.10",
37
+ "@types/node": "^20.10.0",
38
+ "ts-node": "^10.9.2",
39
+ "typescript": "^5.3.2"
40
+ },
41
+ "engines": {
42
+ "node": ">=18.0.0"
43
+ },
44
+ "files": [
45
+ "dist",
46
+ "bin",
47
+ "templates",
48
+ "README.md"
49
+ ]
50
+ }
@@ -0,0 +1,167 @@
1
+ # GitLab CI/CD 配置文件 - NestJS 项目
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
+ DOCKER_HUB_REGISTRY: "docker.io"
16
+ DOCKER_HUB_IMAGE: "{{DOCKER_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
+ # 构建阶段
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 "登录到Docker Hub..."
62
+ - echo "$DOCKER_HUB_PASSWORD" | docker login -u $DOCKER_HUB_USERNAME --password-stdin
63
+ script:
64
+ - echo "尝试拉取最新镜像作为缓存..."
65
+ - docker pull $DOCKER_HUB_IMAGE:latest || true
66
+ - echo "构建Docker镜像..."
67
+ - docker build --build-arg BUILDKIT_INLINE_CACHE=1 --cache-from $DOCKER_HUB_IMAGE:latest -t $DOCKER_HUB_IMAGE:$CI_COMMIT_SHA -t $DOCKER_HUB_IMAGE:latest .
68
+ - echo "推送镜像到Docker Hub..."
69
+ - docker push $DOCKER_HUB_IMAGE:$CI_COMMIT_SHA
70
+ - docker push $DOCKER_HUB_IMAGE:latest
71
+ only:
72
+ - main
73
+ - develop
74
+
75
+ # 开发环境部署(develop 分支自动触发)
76
+ deploy_dev:
77
+ stage: deploy
78
+ image:
79
+ name: alpine:latest
80
+ pull_policy: if-not-present
81
+ variables:
82
+ ENV_TYPE: "development"
83
+ ENV_FILE_CONTENT: $DEV_ENV_FILE
84
+ DEPLOY_DIR: "{{DEPLOY_DIR}}"
85
+ APP_PORT: "{{DEV_PORT}}"
86
+ cache: {}
87
+ before_script:
88
+ - apk add --no-cache openssh-client docker-compose bash openssl rsync
89
+ - eval $(ssh-agent -s)
90
+ - mkdir -p ~/.ssh
91
+ - chmod 700 ~/.ssh
92
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - 2>/dev/null || (echo "无法加载SSH密钥,尝试不同格式..." && echo "$SSH_PRIVATE_KEY" | base64 -d | ssh-add - 2>/dev/null || echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa && ssh-add ~/.ssh/id_rsa)
93
+ - ssh-keyscan $TEST_SERVER_HOST >> ~/.ssh/known_hosts
94
+ - chmod 644 ~/.ssh/known_hosts
95
+ script:
96
+ - ssh root@$TEST_SERVER_HOST "mkdir -p $DEPLOY_DIR"
97
+ - ssh root@$TEST_SERVER_HOST "which rsync || apk add --no-cache rsync"
98
+ - 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/api || exit 1"
101
+ environment:
102
+ name: development
103
+ url: {{DEV_URL}}
104
+ only:
105
+ - develop
106
+
107
+ # 生产环境部署(main 分支手动触发)
108
+ deploy_prod:
109
+ stage: deploy
110
+ image:
111
+ name: alpine:latest
112
+ pull_policy: if-not-present
113
+ variables:
114
+ ENV_TYPE: "production"
115
+ ENV_FILE_CONTENT: $PROD_ENV_FILE
116
+ DEPLOY_DIR: "{{DEPLOY_DIR}}"
117
+ APP_PORT: "{{PROD_PORT}}"
118
+ cache: {}
119
+ before_script:
120
+ - apk add --no-cache openssh-client docker-compose bash openssl rsync
121
+ - eval $(ssh-agent -s)
122
+ - mkdir -p ~/.ssh
123
+ - chmod 700 ~/.ssh
124
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - 2>/dev/null || (echo "无法加载SSH密钥,尝试不同格式..." && echo "$SSH_PRIVATE_KEY" | base64 -d | ssh-add - 2>/dev/null || echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa && ssh-add ~/.ssh/id_rsa)
125
+ - ssh-keyscan $PROD_SERVER_HOST >> ~/.ssh/known_hosts
126
+ - chmod 644 ~/.ssh/known_hosts
127
+ script:
128
+ - ssh root@$PROD_SERVER_HOST "mkdir -p $DEPLOY_DIR"
129
+ - ssh root@$PROD_SERVER_HOST "which rsync || apk add --no-cache rsync"
130
+ - 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/api || exit 1"
133
+ environment:
134
+ name: production
135
+ url: {{PROD_URL}}
136
+ only:
137
+ - main
138
+ when: manual
139
+
140
+ # 回滚部署(可选)
141
+ rollback:
142
+ stage: deploy
143
+ image:
144
+ name: alpine:latest
145
+ pull_policy: if-not-present
146
+ variables:
147
+ DEPLOY_DIR: "{{DEPLOY_DIR}}"
148
+ APP_PORT: "{{PROD_PORT}}"
149
+ cache: {}
150
+ before_script:
151
+ - apk add --no-cache openssh-client openssl
152
+ - eval $(ssh-agent -s)
153
+ - mkdir -p ~/.ssh
154
+ - chmod 700 ~/.ssh
155
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - 2>/dev/null || (echo "无法加载SSH密钥,尝试不同格式..." && echo "$SSH_PRIVATE_KEY" | base64 -d | ssh-add - 2>/dev/null || echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa && ssh-add ~/.ssh/id_rsa)
156
+ - ssh-keyscan $PROD_SERVER_HOST >> ~/.ssh/known_hosts
157
+ - chmod 644 ~/.ssh/known_hosts
158
+ script:
159
+ - ssh root@$PROD_SERVER_HOST "cd $DEPLOY_DIR && export APP_PORT=$APP_PORT && docker-compose down"
160
+ - ssh root@$PROD_SERVER_HOST "cd $DEPLOY_DIR && export APP_PORT=$APP_PORT && docker-compose pull"
161
+ - ssh root@$PROD_SERVER_HOST "cd $DEPLOY_DIR && export APP_PORT=$APP_PORT && docker-compose up -d"
162
+ environment:
163
+ name: production
164
+ url: {{PROD_URL}}
165
+ when: manual
166
+ only:
167
+ - main
@@ -0,0 +1,167 @@
1
+ # GitLab CI/CD 配置文件 - Vue 项目
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
+ DOCKER_HUB_REGISTRY: "docker.io"
16
+ DOCKER_HUB_IMAGE: "{{DOCKER_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
+ # 构建阶段
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 "登录到Docker Hub..."
62
+ - echo "$DOCKER_HUB_PASSWORD" | docker login -u $DOCKER_HUB_USERNAME --password-stdin
63
+ script:
64
+ - echo "尝试拉取最新镜像作为缓存..."
65
+ - docker pull $DOCKER_HUB_IMAGE:latest || true
66
+ - echo "构建Docker镜像..."
67
+ - docker build --build-arg BUILDKIT_INLINE_CACHE=1 --cache-from $DOCKER_HUB_IMAGE:latest -t $DOCKER_HUB_IMAGE:$CI_COMMIT_SHA -t $DOCKER_HUB_IMAGE:latest .
68
+ - echo "推送镜像到Docker Hub..."
69
+ - docker push $DOCKER_HUB_IMAGE:$CI_COMMIT_SHA
70
+ - docker push $DOCKER_HUB_IMAGE:latest
71
+ only:
72
+ - main
73
+ - develop
74
+
75
+ # 开发环境部署(develop 分支自动触发)
76
+ deploy_dev:
77
+ stage: deploy
78
+ image:
79
+ name: alpine:latest
80
+ pull_policy: if-not-present
81
+ variables:
82
+ ENV_TYPE: "development"
83
+ ENV_FILE_CONTENT: $DEV_ENV_FILE
84
+ DEPLOY_DIR: "{{DEPLOY_DIR}}"
85
+ APP_PORT: "{{DEV_PORT}}"
86
+ cache: {}
87
+ before_script:
88
+ - apk add --no-cache openssh-client docker-compose bash openssl rsync
89
+ - eval $(ssh-agent -s)
90
+ - mkdir -p ~/.ssh
91
+ - chmod 700 ~/.ssh
92
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - 2>/dev/null || (echo "无法加载SSH密钥,尝试不同格式..." && echo "$SSH_PRIVATE_KEY" | base64 -d | ssh-add - 2>/dev/null || echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa && ssh-add ~/.ssh/id_rsa)
93
+ - ssh-keyscan $TEST_SERVER_HOST >> ~/.ssh/known_hosts
94
+ - chmod 644 ~/.ssh/known_hosts
95
+ script:
96
+ - ssh root@$TEST_SERVER_HOST "mkdir -p $DEPLOY_DIR"
97
+ - ssh root@$TEST_SERVER_HOST "which rsync || apk add --no-cache rsync"
98
+ - 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"
101
+ environment:
102
+ name: development
103
+ url: {{DEV_URL}}
104
+ only:
105
+ - develop
106
+
107
+ # 生产环境部署(main 分支手动触发)
108
+ deploy_prod:
109
+ stage: deploy
110
+ image:
111
+ name: alpine:latest
112
+ pull_policy: if-not-present
113
+ variables:
114
+ ENV_TYPE: "production"
115
+ ENV_FILE_CONTENT: $PROD_ENV_FILE
116
+ DEPLOY_DIR: "{{DEPLOY_DIR}}"
117
+ APP_PORT: "{{PROD_PORT}}"
118
+ cache: {}
119
+ before_script:
120
+ - apk add --no-cache openssh-client docker-compose bash openssl rsync
121
+ - eval $(ssh-agent -s)
122
+ - mkdir -p ~/.ssh
123
+ - chmod 700 ~/.ssh
124
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - 2>/dev/null || (echo "无法加载SSH密钥,尝试不同格式..." && echo "$SSH_PRIVATE_KEY" | base64 -d | ssh-add - 2>/dev/null || echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa && ssh-add ~/.ssh/id_rsa)
125
+ - ssh-keyscan $PROD_SERVER_HOST >> ~/.ssh/known_hosts
126
+ - chmod 644 ~/.ssh/known_hosts
127
+ script:
128
+ - ssh root@$PROD_SERVER_HOST "mkdir -p $DEPLOY_DIR"
129
+ - ssh root@$PROD_SERVER_HOST "which rsync || apk add --no-cache rsync"
130
+ - 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"
133
+ environment:
134
+ name: production
135
+ url: {{PROD_URL}}
136
+ only:
137
+ - main
138
+ when: manual
139
+
140
+ # 回滚部署(可选)
141
+ rollback:
142
+ stage: deploy
143
+ image:
144
+ name: alpine:latest
145
+ pull_policy: if-not-present
146
+ variables:
147
+ DEPLOY_DIR: "{{DEPLOY_DIR}}"
148
+ APP_PORT: "{{PROD_PORT}}"
149
+ cache: {}
150
+ before_script:
151
+ - apk add --no-cache openssh-client openssl
152
+ - eval $(ssh-agent -s)
153
+ - mkdir -p ~/.ssh
154
+ - chmod 700 ~/.ssh
155
+ - echo "$SSH_PRIVATE_KEY" | tr -d '\r' | ssh-add - 2>/dev/null || (echo "无法加载SSH密钥,尝试不同格式..." && echo "$SSH_PRIVATE_KEY" | base64 -d | ssh-add - 2>/dev/null || echo "$SSH_PRIVATE_KEY" > ~/.ssh/id_rsa && chmod 600 ~/.ssh/id_rsa && ssh-add ~/.ssh/id_rsa)
156
+ - ssh-keyscan $PROD_SERVER_HOST >> ~/.ssh/known_hosts
157
+ - chmod 644 ~/.ssh/known_hosts
158
+ script:
159
+ - ssh root@$PROD_SERVER_HOST "cd $DEPLOY_DIR && export APP_PORT=$APP_PORT && docker-compose down"
160
+ - ssh root@$PROD_SERVER_HOST "cd $DEPLOY_DIR && export APP_PORT=$APP_PORT && docker-compose pull"
161
+ - ssh root@$PROD_SERVER_HOST "cd $DEPLOY_DIR && export APP_PORT=$APP_PORT && docker-compose up -d"
162
+ environment:
163
+ name: production
164
+ url: {{PROD_URL}}
165
+ when: manual
166
+ only:
167
+ - main
@@ -0,0 +1,141 @@
1
+ #!/bin/bash
2
+
3
+ # 部署脚本 - 由CI/CD自动调用
4
+ # 此脚本不需要手动执行
5
+
6
+ set -e
7
+
8
+ # 环境变量
9
+ APP_NAME="{{APP_NAME}}"
10
+ DEPLOY_PATH="{{DEPLOY_DIR}}"
11
+ ENV_TYPE=${1:-development}
12
+
13
+ # 根据环境设置端口
14
+ if [ "$ENV_TYPE" = "production" ]; then
15
+ export APP_PORT={{PROD_PORT}}
16
+ else
17
+ export APP_PORT={{DEV_PORT}}
18
+ fi
19
+
20
+ echo "开始部署 $APP_NAME 到 $ENV_TYPE 环境 (端口: $APP_PORT)..."
21
+
22
+ # 确保目录存在
23
+ mkdir -p $DEPLOY_PATH
24
+
25
+ # 当在CI/CD中执行时,文件已经通过rsync复制到部署目录,无需再次复制
26
+ if [ "$PWD" != "$DEPLOY_PATH" ]; then
27
+ echo "复制项目文件到部署目录..."
28
+ cp -r . $DEPLOY_PATH/
29
+ cd $DEPLOY_PATH
30
+ fi
31
+
32
+ # 生成环境变量文件
33
+ echo "生成环境变量文件..."
34
+ bash ci/generate-env.sh $ENV_TYPE
35
+
36
+ # 检查Docker是否已安装
37
+ if ! command -v docker &> /dev/null; then
38
+ echo "Docker未安装,尝试安装Docker..."
39
+ if command -v apt-get &> /dev/null; then
40
+ apt-get update
41
+ apt-get install -y apt-transport-https ca-certificates curl software-properties-common
42
+ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | apt-key add -
43
+ add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
44
+ apt-get update
45
+ apt-get install -y docker-ce
46
+ elif command -v yum &> /dev/null; then
47
+ yum install -y yum-utils
48
+ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
49
+ yum install -y docker-ce docker-ce-cli containerd.io
50
+ systemctl start docker
51
+ systemctl enable docker
52
+ elif command -v apk &> /dev/null; then
53
+ apk add --update docker
54
+ service docker start
55
+ else
56
+ echo "无法确定包管理器,请手动安装Docker"
57
+ exit 1
58
+ fi
59
+ fi
60
+
61
+ # 检查并安装 docker-compose
62
+ if ! command -v docker-compose &> /dev/null; then
63
+ echo "安装 docker-compose..."
64
+
65
+ if ! command -v curl &> /dev/null; then
66
+ echo "安装curl..."
67
+ if command -v apt-get &> /dev/null; then
68
+ apt-get update && apt-get install -y curl
69
+ elif command -v yum &> /dev/null; then
70
+ yum install -y curl
71
+ elif command -v apk &> /dev/null; then
72
+ apk add --no-cache curl
73
+ fi
74
+ fi
75
+
76
+ if command -v apt-get &> /dev/null; then
77
+ apt-get update && apt-get install -y docker-compose
78
+ elif command -v yum &> /dev/null; then
79
+ yum install -y docker-compose
80
+ elif command -v apk &> /dev/null; then
81
+ apk add --no-cache docker-compose
82
+ else
83
+ echo "无法确定包管理器,尝试使用pip安装..."
84
+ pip install docker-compose || pip3 install docker-compose
85
+ fi
86
+ fi
87
+
88
+ # 再次检查 docker-compose 是否已安装
89
+ if ! command -v docker-compose &> /dev/null; then
90
+ echo "无法安装 docker-compose,尝试手动安装最新版本..."
91
+ COMPOSE_VERSION=$(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep 'tag_name' | cut -d\" -f4)
92
+ curl -L "https://github.com/docker/compose/releases/download/${COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
93
+ chmod +x /usr/local/bin/docker-compose
94
+ fi
95
+
96
+ # 拉取最新镜像并启动Docker容器
97
+ echo "拉取最新镜像并启动Docker容器..."
98
+
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
103
+ else
104
+ echo "未设置Docker Hub凭据,尝试匿名拉取镜像..."
105
+ fi
106
+
107
+ # 停止并移除旧容器
108
+ echo "清理现有容器..."
109
+ docker-compose down --remove-orphans || true
110
+ docker container ls -a | grep '$APP_NAME' | awk '{print $1}' | xargs -r docker container rm -f
111
+
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进行本地构建..."
119
+ if [ -f "Dockerfile" ]; then
120
+ echo "找到Dockerfile,进行本地构建..."
121
+ export DOCKER_IMAGE="$APP_NAME:local"
122
+ docker build -t $DOCKER_IMAGE .
123
+ APP_PORT=$APP_PORT docker-compose up -d
124
+ else
125
+ echo "错误:无法拉取镜像且未找到Dockerfile,部署失败"
126
+ exit 1
127
+ fi
128
+ fi
129
+
130
+ # 检查部署状态
131
+ echo "检查部署状态..."
132
+ sleep 10
133
+ if docker-compose ps | grep -q "$APP_NAME.*Up"; then
134
+ echo "部署成功! $APP_NAME 服务已启动"
135
+ else
136
+ echo "部署失败! 请检查日志"
137
+ docker-compose logs
138
+ exit 1
139
+ fi
140
+
141
+ echo "部署完成!"
@@ -0,0 +1,84 @@
1
+ #!/bin/bash
2
+
3
+ # 环境变量生成脚本
4
+ # 用法: bash generate-env.sh [environment]
5
+ # 示例: bash generate-env.sh production
6
+
7
+ ENV_TYPE=${1:-development}
8
+ ENV_FILE=".env"
9
+
10
+ echo "正在生成 $ENV_TYPE 环境的环境变量文件..."
11
+
12
+ # 检查是否在CI环境中运行
13
+ if [ -n "$CI_ENVIRONMENT_NAME" ]; then
14
+ echo "在CI/CD环境中运行,使用CI/CD变量..."
15
+
16
+ # 检查是否有文件类型的环境变量
17
+ if [ -n "$ENV_FILE_CONTENT" ]; then
18
+ echo "检测到ENV_FILE_CONTENT变量,直接使用文件内容..."
19
+ echo "$ENV_FILE_CONTENT" > $ENV_FILE
20
+ echo "环境变量文件已生成: $ENV_FILE"
21
+ exit 0
22
+ fi
23
+
24
+ # 如果没有文件类型变量,则从单独的CI/CD变量构建
25
+ echo "# 由CI/CD自动生成的环境变量文件 - $(date)" > $ENV_FILE
26
+
27
+ # 读取.env.example作为模板
28
+ if [ -f ".env.example" ]; then
29
+ while IFS= read -r line || [[ -n "$line" ]]; do
30
+ # 跳过注释和空行
31
+ if [[ $line =~ ^#.*$ ]] || [[ -z $line ]]; then
32
+ echo "$line" >> $ENV_FILE
33
+ continue
34
+ fi
35
+
36
+ # 提取变量名
37
+ VAR_NAME=$(echo "$line" | cut -d= -f1)
38
+
39
+ # 检查CI/CD变量中是否存在该变量
40
+ VAR_VALUE=$(env | grep "^$VAR_NAME=" | cut -d= -f2-)
41
+
42
+ if [ -n "$VAR_VALUE" ]; then
43
+ echo "$VAR_NAME=$VAR_VALUE" >> $ENV_FILE
44
+ else
45
+ # 如果在CI/CD变量中找不到,保留原样
46
+ echo "$line" >> $ENV_FILE
47
+ fi
48
+ done < .env.example
49
+ else
50
+ echo "警告: 未找到 .env.example 文件,将创建一个基本的环境变量文件"
51
+ cat << EOF > $ENV_FILE
52
+ # 由CI/CD自动生成的基本环境变量文件 - $(date)
53
+ # 应用配置
54
+ NODE_ENV=$ENV_TYPE
55
+ PORT={{APP_PORT}}
56
+ EOF
57
+ fi
58
+
59
+ else
60
+ # 本地开发环境
61
+ echo "在本地环境中运行,请确保已经创建了.env文件"
62
+
63
+ if [ ! -f "$ENV_FILE" ]; then
64
+ echo "警告: $ENV_FILE 文件不存在,将从 .env.example 创建一个副本"
65
+
66
+ if [ -f ".env.example" ]; then
67
+ cp .env.example $ENV_FILE
68
+ else
69
+ echo "未找到 .env.example,创建基本环境变量文件"
70
+ cat << EOF > $ENV_FILE
71
+ # 本地开发环境变量配置 - $(date)
72
+ # 应用配置
73
+ NODE_ENV=development
74
+ PORT=3000
75
+ EOF
76
+ fi
77
+
78
+ echo "请编辑 $ENV_FILE 文件并填写必要的环境变量值"
79
+ else
80
+ echo "已检测到 $ENV_FILE 文件,将使用现有文件"
81
+ fi
82
+ fi
83
+
84
+ echo "环境变量配置完成!"