diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index bc1a3416f..3ae57d600 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -1,9 +1,9 @@ -# 触发条件:push到main分支、手动触发 +# 触发条件(旧版语法) when: event: [push, manual] branch: main -# 克隆配置:启用SSH拉取代码 +# 克隆配置(旧版仍支持) clone: git: image: woodpeckerci/plugin-git @@ -12,192 +12,178 @@ clone: lfs: false use-ssh: true -# 全局环境变量 -environment: - CGO_ENABLED: 0 - GO111MODULE: on - GOSUMDB: off - SCREEN_NAME: logic_service # screen会话名称(全局统一) - REMOTE_EXE_DIR: /opt/logic # 远程服务器程序存放目录 - JSON_CONFIG_URL: "https://xxx.com/deploy-config.json" # 替换为你的JSON配置地址 - # JSON字段名(与你的JSON对应,无需修改) - JSON_FIELD_ADDR: "loginaddr" - JSON_FIELD_USER: "user" - JSON_FIELD_PASS: "password" - JSON_FIELD_ONLINEID: "online_id" # 新增:解析JSON中的online_id字段 - -# 流水线核心步骤 -pipeline: - # 1. 缓存Go依赖 - cache-go-mod: - image: woodpeckerci/plugin-cache - settings: - mount: - - ~/go/pkg/mod - - ~/.cache/go-build - key: ${CI_OS}-go-${CI_COMMIT_SHA:0:8} - restore_keys: - - ${CI_OS}-go- - - # 2. 配置Go环境并预下载依赖 - prepare-go: - image: golang:1.25 - commands: - - go version - - go mod download -x - - # 3. 生成构建版本号 - set-version: - image: golang:1.25 - commands: - - VERSION="v$(git rev-parse --short=8 HEAD)" - - echo "BUILD_VERSION=${VERSION}" >> $CI_ENV_FILE - - echo "构建版本号:${VERSION}" - - # 4. 编译Go服务 - build-logic: - image: golang:1.25 - commands: - - mkdir -p build - - BIN_NAME="logic_${BUILD_VERSION}" - - echo "BIN_NAME=${BIN_NAME}" >> $CI_ENV_FILE - - go build -v \ - -p=4 \ - -trimpath \ - -buildvcs=false \ - -ldflags "-s -w -buildid= -extldflags '-static'" \ - -o ./build/${BIN_NAME} \ - ./logic - - if [ ! -f ./build/${BIN_NAME} ]; then - echo "❌ 编译失败:产物${BIN_NAME}不存在" - exit 1 - fi - - ls -lh ./build/ - - echo "产物名称:${BIN_NAME}" - - # 5. 获取并解析JSON配置【核心修改:新增解析online_id】 - fetch-deploy-config: - image: alpine:latest - commands: - - apk add --no-cache curl jq - - echo "从${JSON_CONFIG_URL}拉取部署配置..." - - curl -sSL ${JSON_CONFIG_URL} -o /tmp/deploy-config.json - - if [ ! -f /tmp/deploy-config.json ]; then - echo "❌ 拉取JSON配置失败" - exit 1 - fi - # 检测JSON格式(数组/对象),新增解析online_id - - | - JSON_TYPE=$(jq -r 'type' /tmp/deploy-config.json) - if [ "$JSON_TYPE" = "array" ]; then - # 多服务器:提取所有地址、用户名、密码、online_id(逗号分隔,一一对应) - REMOTE_HOSTS=$(jq -r ".[].${JSON_FIELD_ADDR}" /tmp/deploy-config.json | tr '\n' ',' | sed 's/,$//') - REMOTE_USERS=$(jq -r ".[].${JSON_FIELD_USER}" /tmp/deploy-config.json | tr '\n' ',' | sed 's/,$//') - REMOTE_PASSWORDS=$(jq -r ".[].${JSON_FIELD_PASS}" /tmp/deploy-config.json | tr '\n' ',' | sed 's/,$//') - REMOTE_ONLINE_IDS=$(jq -r ".[].${JSON_FIELD_ONLINEID}" /tmp/deploy-config.json | tr '\n' ',' | sed 's/,$//') - else - # 单服务器:直接提取所有字段 - REMOTE_HOSTS=$(jq -r ".${JSON_FIELD_ADDR}" /tmp/deploy-config.json) - REMOTE_USERS=$(jq -r ".${JSON_FIELD_USER}" /tmp/deploy-config.json) - REMOTE_PASSWORDS=$(jq -r ".${JSON_FIELD_PASS}" /tmp/deploy-config.json) - REMOTE_ONLINE_IDS=$(jq -r ".${JSON_FIELD_ONLINEID}" /tmp/deploy-config.json) - fi - # 输出解析结果(调试用) - - echo "解析出的服务器地址:${REMOTE_HOSTS}" - - echo "解析出的用户名:${REMOTE_USERS}" - - echo "解析出的OnlineID:${REMOTE_ONLINE_IDS}" - # 写入环境文件供后续使用 - - echo "REMOTE_HOSTS=${REMOTE_HOSTS}" >> $CI_ENV_FILE - - echo "REMOTE_USERS=${REMOTE_USERS}" >> $CI_ENV_FILE - - echo "REMOTE_PASSWORDS=${REMOTE_PASSWORDS}" >> $CI_ENV_FILE - - echo "REMOTE_ONLINE_IDS=${REMOTE_ONLINE_IDS}" >> $CI_ENV_FILE - - # 6. SCP推送程序文件到远程服务器(密码认证,无修改) - scp-exe-to-servers: - image: appleboy/drone-scp - settings: - host: ${REMOTE_HOSTS} - username: ${REMOTE_USERS} - password: ${REMOTE_PASSWORDS} - source: ./build/${BIN_NAME} - target: ${REMOTE_EXE_DIR}/ - strip_components: 1 - skip_verify: true - environment: - - BIN_NAME=${BIN_NAME} - - REMOTE_EXE_DIR=${REMOTE_EXE_DIR} - depends_on: [build-logic, fetch-deploy-config] - - # 7. 远程部署【核心修改:使用动态online_id启动程序】 - deploy-to-servers: - image: appleboy/drone-ssh - settings: - host: ${REMOTE_HOSTS} - username: ${REMOTE_USERS} - password: ${REMOTE_PASSWORDS} - skip_verify: true - # 脚本新增:读取当前服务器的online_id,动态拼接启动参数 - script: - # 第一步:检查并安装screen(无修改) - - | - echo "检查Screen是否已安装..." - if command -v screen &> /dev/null; then - echo "=== Screen已安装,跳过 ===" - else - echo "=== Screen未安装,开始安装 ===" - if command -v apt &> /dev/null; then - apt update -y && apt install -y screen - elif command -v yum &> /dev/null; then - yum install -y screen - elif command -v dnf &> /dev/null; then - dnf install -y screen - elif command -v pacman &> /dev/null; then - pacman -S --noconfirm screen - else - echo "❌ 不支持的包管理器,无法安装Screen" - exit 1 - fi - command -v screen || { echo "❌ Screen安装失败"; exit 1; } +# 旧版:顶层是 workflow,不是 pipeline +workflow "my-first-workflow": + steps: + # ------------------------------ + # 1. 编译 Go 程序 + # ------------------------------ + - name: build-logic + image: golang:1.25 + commands: + - export CGO_ENABLED=0 + - export GO111MODULE=on + - export GOSUMDB=off + - VERSION="v$(git rev-parse --short=8 HEAD)" + - echo "BUILD_VERSION=$VERSION" > .env + - mkdir -p build + - BIN_NAME="logic_$VERSION" + - echo "BIN_NAME=$BIN_NAME" >> .env + - go build -v \ + -p=4 \ + -trimpath \ + -buildvcs=false \ + -ldflags "-s -w -buildid= -extldflags '-static'" \ + -o ./build/$BIN_NAME \ + ./logic + - if [ ! -f ./build/$BIN_NAME ]; then + echo "❌ 编译失败:产物 $BIN_NAME 不存在" + exit 1 fi - # 第二步:设置程序执行权限(无修改) - - mkdir -p ${REMOTE_EXE_DIR} - - chmod +x ${REMOTE_EXE_DIR}/${BIN_NAME} || { echo "❌ 设置权限失败"; exit 1; } - # 第三步:停止旧会话(无修改) - - screen -S ${SCREEN_NAME} -X quit || true - # 第四步:启动新程序【核心修改:使用JSON解析的online_id】 + - ls -lh ./build/ + + # ------------------------------ + # 2. 获取并解析 JSON 配置(含 online_id) + # ------------------------------ + - name: fetch-deploy-config + image: alpine:latest + commands: + - apk add --no-cache curl jq + - source .env + - JSON_CONFIG_URL="https://xxx.com/deploy-config.json" # 替换为你的地址 + - JSON_FIELD_ADDR="loginaddr" + - JSON_FIELD_USER="user" + - JSON_FIELD_PASS="password" + - JSON_FIELD_ONLINEID="online_id" + + - echo "从 $JSON_CONFIG_URL 拉取配置..." + - curl -sSL "$JSON_CONFIG_URL" -o /tmp/deploy-config.json + - if [ ! -f /tmp/deploy-config.json ]; then + echo "❌ 拉取配置失败" + exit 1 + fi + - | - echo "启动Screen会话[${SCREEN_NAME}],OnlineID:${REMOTE_ONLINE_IDS}" - screen -dmS ${SCREEN_NAME} bash -c "\"${REMOTE_EXE_DIR}/${BIN_NAME}\" -id=${REMOTE_ONLINE_IDS} | tee -a \"\$HOME/run.log\"" - - sleep 2 - if screen -ls | grep -q "${SCREEN_NAME}"; then - echo "✅ 程序启动成功!会话:${SCREEN_NAME} | OnlineID:${REMOTE_ONLINE_IDS}" - screen -ls + JSON_TYPE=$(jq -r 'type' /tmp/deploy-config.json) + if [ "$JSON_TYPE" = "array" ]; then + REMOTE_HOSTS=$(jq -r ".[].$JSON_FIELD_ADDR" /tmp/deploy-config.json | tr '\n' ',' | sed 's/,$//') + REMOTE_USERS=$(jq -r ".[].$JSON_FIELD_USER" /tmp/deploy-config.json | tr '\n' ',' | sed 's/,$//') + REMOTE_PASSWORDS=$(jq -r ".[].$JSON_FIELD_PASS" /tmp/deploy-config.json | tr '\n' ',' | sed 's/,$//') + REMOTE_ONLINE_IDS=$(jq -r ".[].$JSON_FIELD_ONLINEID" /tmp/deploy-config.json | tr '\n' ',' | sed 's/,$//') else - echo "❌ 程序启动失败,未创建[${SCREEN_NAME}]会话" + REMOTE_HOSTS=$(jq -r ".$JSON_FIELD_ADDR" /tmp/deploy-config.json) + REMOTE_USERS=$(jq -r ".$JSON_FIELD_USER" /tmp/deploy-config.json) + REMOTE_PASSWORDS=$(jq -r ".$JSON_FIELD_PASS" /tmp/deploy-config.json) + REMOTE_ONLINE_IDS=$(jq -r ".$JSON_FIELD_ONLINEID" /tmp/deploy-config.json) + fi + + echo "REMOTE_HOSTS=$REMOTE_HOSTS" >> .env + echo "REMOTE_USERS=$REMOTE_USERS" >> .env + echo "REMOTE_PASSWORDS=$REMOTE_PASSWORDS" >> .env + echo "REMOTE_ONLINE_IDS=$REMOTE_ONLINE_IDS" >> .env + echo "REMOTE_EXE_DIR=/opt/logic" >> .env + echo "SCREEN_NAME=logic_service" >> .env + + - cat .env + + # ------------------------------ + # 3. SCP 推送程序到服务器(密码登录) + # ------------------------------ + - name: scp-exe + image: appleboy/drone-scp + settings: + host: ${REMOTE_HOSTS} + username: ${REMOTE_USERS} + password: ${REMOTE_PASSWORDS} + source: ./build/${BIN_NAME} + target: ${REMOTE_EXE_DIR}/ + strip_components: 1 + skip_verify: true + environment: + - BIN_NAME=${BIN_NAME} + - REMOTE_EXE_DIR=${REMOTE_EXE_DIR} + when: + - success + + # ------------------------------ + # 4. 远程部署:安装 screen + 启动程序(带 -id=online_id) + # ------------------------------ + - name: deploy-to-servers + image: appleboy/drone-ssh + settings: + host: ${REMOTE_HOSTS} + username: ${REMOTE_USERS} + password: ${REMOTE_PASSWORDS} + skip_verify: true + script: + - | + # 加载变量(旧版 drone-ssh 会自动把环境变量带过去) + source /dev/stdin << 'EOF' + export BIN_NAME="${BIN_NAME}" + export SCREEN_NAME="${SCREEN_NAME}" + export REMOTE_EXE_DIR="${REMOTE_EXE_DIR}" + export ONLINE_ID="${REMOTE_ONLINE_IDS}" + EOF + + # 检查并安装 screen + echo "检查 Screen..." + if ! command -v screen &> /dev/null; then + echo "安装 screen..." + if command -v apt &> /dev/null; then + apt update -y && apt install -y screen + elif command -v yum &> /dev/null; then + yum install -y screen + elif command -v dnf &> /dev/null; then + dnf install -y screen + elif command -v pacman &> /dev/null; then + pacman -S --noconfirm screen + else + echo "❌ 不支持的包管理器" + exit 1 + fi + fi + + # 赋权 + mkdir -p "$REMOTE_EXE_DIR" + chmod +x "$REMOTE_EXE_DIR/$BIN_NAME" || { echo "❌ 赋权失败"; exit 1; } + + # 停止旧会话 + screen -S "$SCREEN_NAME" -X quit || true + + # 启动新程序(带 -id=$ONLINE_ID) + echo "启动 $SCREEN_NAME with -id=$ONLINE_ID" + screen -dmS "$SCREEN_NAME" bash -c "\"$REMOTE_EXE_DIR/$BIN_NAME\" -id=$ONLINE_ID | tee -a \"\$HOME/run.log\"" + + sleep 2 + if screen -ls | grep -q "$SCREEN_NAME"; then + echo "✅ 启动成功:$SCREEN_NAME (id=$ONLINE_ID)" + screen -ls + else + echo "❌ 启动失败" screen -ls exit 1 - fi - environment: - - BIN_NAME=${BIN_NAME} - - SCREEN_NAME=${SCREEN_NAME} - - REMOTE_EXE_DIR=${REMOTE_EXE_DIR} - - REMOTE_ONLINE_IDS=${REMOTE_ONLINE_IDS} # 传递解析的online_id - depends_on: scp-exe-to-servers + fi + environment: + - BIN_NAME=${BIN_NAME} + - SCREEN_NAME=${SCREEN_NAME} + - REMOTE_EXE_DIR=${REMOTE_EXE_DIR} + - REMOTE_ONLINE_IDS=${REMOTE_ONLINE_IDS} + when: + - success - # 8. 打印部署完成信息【新增:显示online_id】 - print-deploy-info: - image: alpine:latest - commands: - - echo "======================================" - - echo "✅ 部署完成!" - - echo "版本号:${BUILD_VERSION}" - - echo "触发方式:${CI_EVENT_NAME}" - - echo "程序名称:${BIN_NAME}" - - echo "远程部署目录:${REMOTE_EXE_DIR}" - - echo "Screen会话名:${SCREEN_NAME}" - - echo "部署服务器:${REMOTE_HOSTS}" - - echo "服务器OnlineID:${REMOTE_ONLINE_IDS}" # 新增显示online_id - - echo "对应Commit:${CI_COMMIT_SHA}" - - echo "======================================" - depends_on: deploy-to-servers + # ------------------------------ + # 5. 打印结果 + # ------------------------------ + - name: print-info + image: alpine:latest + commands: + - source .env + - echo "======================================" + - echo "✅ 部署完成" + - echo "版本:$BUILD_VERSION" + - echo "程序:$BIN_NAME" + - echo "服务器:$REMOTE_HOSTS" + - echo "OnlineID:$REMOTE_ONLINE_IDS" + - echo "======================================" + when: + - success