From 4f962ab2f2fc9605ca62c7b3eb589e222a370d98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Mon, 26 Jan 2026 23:31:39 +0800 Subject: [PATCH 01/20] =?UTF-8?q?```=20chore(woodpecker):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0=E5=B7=A5=E4=BD=9C=E6=B5=81=E9=85=8D=E7=BD=AE=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E7=BB=93=E6=9E=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 重构了 .woodpecker/my-first-workflow.yaml 文件, 将 pipeline 部分重命名为 steps,并添加了 SSH 密钥配置, 同时将全局变量提取到 variables 部分使用 YAML 锚点进行统一管理。 ``` --- .woodpecker/my-first-workflow.yaml | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 1036de5a..7497cd19 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -10,18 +10,12 @@ clone: git: image: woodpeckerci/plugin-git settings: - depth: 50 - lfs: false use-ssh: true + ssh-key-private: + from_secret: WOODPECKER_SSH_KEY -# Woodpecker原生顶层字段3:核心流水线(唯一步骤容器) -pipeline: - # 全局配置(仅在pipeline内,按需修改这4项即可) - SCREEN_NAME: logic_service - REMOTE_EXE_DIR: /opt/logic - JSON_CONFIG_URL: "https://你的JSON配置地址.com/deploy.json" - LOG_PATH: "$HOME/run.log" - +# Woodpecker原生顶层字段3:流水线步骤 +steps: # 1. 缓存Go依赖(加速构建) cache-go-mod: image: woodpeckerci/plugin-cache @@ -172,3 +166,10 @@ pipeline: - echo "======================================" depends_on: - deploy-to-servers + +# 全局配置变量 +variables: + - &screen_name "logic_service" + - &remote_exe_dir "/opt/logic" + - &json_config_url "https://你的JSON配置地址.com/deploy.json" + - &log_path "$HOME/run.log" \ No newline at end of file From ea6852aa6f52e5ab474872bfe771c322cd27c730 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Mon, 26 Jan 2026 23:33:44 +0800 Subject: [PATCH 02/20] =?UTF-8?q?```=20feat(.woodpecker):=20=E6=B7=BB?= =?UTF-8?q?=E5=8A=A0SSH=E5=88=9D=E5=A7=8B=E5=8C=96=E6=AD=A5=E9=AA=A4?= =?UTF-8?q?=E5=B9=B6=E4=BC=98=E5=8C=96=E6=B5=81=E6=B0=B4=E7=BA=BF=E4=BE=9D?= =?UTF-8?q?=E8=B5=96=E5=85=B3=E7=B3=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 在Woodpecker流水线配置中添加了SSH初始化步骤,用于创建SSH目录和配置文件, 同时修正了各步骤间的依赖关系以确保正确的执行顺序: - 新增init-ssh步骤,设置SSH基础环境 - cache-go-mod依赖于init-ssh - prepare-go依赖于cache-go-mod - set-version依赖于prepare-go - build-logic依赖于set-version - fetch-deploy-config依赖于build-logic 此改动确保了流水线步骤按正确顺序执行,并为后续的SSH相关 --- .woodpecker/my-first-workflow.yaml | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 7497cd19..4d8e3e25 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -16,6 +16,14 @@ clone: # Woodpecker原生顶层字段3:流水线步骤 steps: + # SSH初始化步骤 + init-ssh: + image: alpine:latest + commands: + - mkdir -p /root/.ssh + - touch /root/.ssh/known_hosts + - chmod 600 /root/.ssh/known_hosts + # 1. 缓存Go依赖(加速构建) cache-go-mod: image: woodpeckerci/plugin-cache @@ -26,6 +34,8 @@ steps: key: ${CI_OS}-go-${CI_COMMIT_SHA:0:8} restore_keys: - ${CI_OS}-go- + depends_on: + - init-ssh # 2. 初始化Go环境 & 预下载依赖 prepare-go: @@ -33,6 +43,8 @@ steps: commands: - go version - go mod download -x + depends_on: + - cache-go-mod # 3. 生成构建版本号(8位短SHA) set-version: @@ -41,6 +53,8 @@ steps: - VERSION="v$(git rev-parse --short=8 HEAD)" - echo "BUILD_VERSION=${VERSION}" >> $CI_ENV_FILE - echo "✅ 生成版本号:${VERSION}" + depends_on: + - prepare-go # 4. 编译Go服务(静态编译,无系统依赖) build-logic: @@ -63,6 +77,8 @@ steps: fi - ls -lh ./build/ - echo "✅ Go服务编译完成" + depends_on: + - set-version # 5. 拉取JSON & 解析服务器/账号/密码/online_id fetch-deploy-config: @@ -89,6 +105,8 @@ steps: - 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 + depends_on: + - build-logic # 6. SCP推送产物到远程服务器(密码认证) scp-exe-to-servers: @@ -172,4 +190,4 @@ variables: - &screen_name "logic_service" - &remote_exe_dir "/opt/logic" - &json_config_url "https://你的JSON配置地址.com/deploy.json" - - &log_path "$HOME/run.log" \ No newline at end of file + - &log_path "$HOME/run.log" From f27a0cb86a61c9ec7c4d84a2c49a80094259e5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Mon, 26 Jan 2026 23:37:06 +0800 Subject: [PATCH 03/20] =?UTF-8?q?```=20feat(.woodpecker):=20=E9=85=8D?= =?UTF-8?q?=E7=BD=AESSH=E5=AF=86=E9=92=A5=E8=AE=A4=E8=AF=81=E5=B9=B6?= =?UTF-8?q?=E4=BC=98=E5=8C=96Git=E6=8F=92=E4=BB=B6=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 配置Woodpecker Git插件使用SSH密钥进行Git操作 - 添加known_hosts安全配置避免主机验证问题 - 在拉取部署配置时增加openssh-client依赖 - 调整Screen安装脚本的错误处理逻辑 - 移除JSON配置URL变量中的示例地址占位符 ``` --- .woodpecker/my-first-workflow.yaml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 4d8e3e25..187643cc 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -10,9 +10,13 @@ clone: git: image: woodpeckerci/plugin-git settings: + # 使用SSH密钥进行Git操作 use-ssh: true + # 确保SSH密钥私钥通过secret提供 ssh-key-private: from_secret: WOODPECKER_SSH_KEY + # 添加known_hosts配置以避免主机验证问题 + set-safe-directory: true # Woodpecker原生顶层字段3:流水线步骤 steps: @@ -23,6 +27,8 @@ steps: - mkdir -p /root/.ssh - touch /root/.ssh/known_hosts - chmod 600 /root/.ssh/known_hosts + # 如果需要的话,可以添加远程主机到known_hosts + # ssh-keyscan -H >> /root/.ssh/known_hosts # 1. 缓存Go依赖(加速构建) cache-go-mod: @@ -84,7 +90,7 @@ steps: fetch-deploy-config: image: alpine:latest commands: - - apk add --no-cache curl jq + - apk add --no-cache curl jq openssh-client - echo "🔧 拉取部署配置:${JSON_CONFIG_URL}" - curl -sSL ${JSON_CONFIG_URL} -o /tmp/deploy-config.json || { echo "❌ 拉取JSON失败"; exit 1; } - | @@ -145,10 +151,10 @@ steps: elif command -v dnf &> /dev/null; then dnf install -y screen -q else - echo "❌ 不支持的包管理器,安装失败" - exit 1 - fi - command -v screen || { echo "❌ Screen安装后检测失败"; exit 1; } + echo "❌ 不支持的包管理器,安装失败" + exit 1 + fi + command -v screen || { echo "❌ Screen安装后检测失败"; exit 1; } fi - mkdir -p ${REMOTE_EXE_DIR} - chmod +x ${REMOTE_EXE_DIR}/${BIN_NAME} || { echo "❌ 设置执行权限失败"; exit 1; } @@ -190,4 +196,4 @@ variables: - &screen_name "logic_service" - &remote_exe_dir "/opt/logic" - &json_config_url "https://你的JSON配置地址.com/deploy.json" - - &log_path "$HOME/run.log" + - &log_path "$HOME/run.log" \ No newline at end of file From e0680b3562a77d8a1cbbab9149d1f29ec854e518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Mon, 26 Jan 2026 23:45:45 +0800 Subject: [PATCH 04/20] 1 --- .woodpecker/my-first-workflow.yaml | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 187643cc..53eef905 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -22,13 +22,23 @@ clone: steps: # SSH初始化步骤 init-ssh: - image: alpine:latest + image: alpine/git:latest + environment: + WOODPECKER_SSH_KEY: + from_secret: WOODPECKER_SSH_KEY commands: - - mkdir -p /root/.ssh - - touch /root/.ssh/known_hosts - - chmod 600 /root/.ssh/known_hosts - # 如果需要的话,可以添加远程主机到known_hosts - # ssh-keyscan -H >> /root/.ssh/known_hosts + - | + # 设置SSH + mkdir -p ~/.ssh + echo "$${WOODPECKER_SSH_KEY}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H github.com >> ~/.ssh/known_hosts + ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts + ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts + + # 配置git + git config --global user.name "Woodpecker CI" + git config --global user.email "ci@example.com" # 1. 缓存Go依赖(加速构建) cache-go-mod: From a75ffc5a81ff28782c6b13b2b90ee78f5bf586c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Mon, 26 Jan 2026 23:48:02 +0800 Subject: [PATCH 05/20] =?UTF-8?q?```=20feat(.woodpecker):=20=E6=9B=B4?= =?UTF-8?q?=E6=96=B0SSH=E9=85=8D=E7=BD=AE=E4=BB=A5=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=A4=9A=E5=B9=B3=E5=8F=B0Git=E4=BB=93=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 更新了my-first-workflow.yaml文件中的SSH初始化步骤,将基础镜像从 alpine/git:latest更换为woodpeckerci/plugin-git,并调整了SSH密钥 存储路径以确保在不同环境下正确工作。现在SSH配置会同时创建 /root/.ssh和/app/.ssh目录,并将密钥文件放置在/app/.ssh目录下, 提高了与Woodpecker CI环境的兼容性。 ``` --- .woodpecker/my-first-workflow.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 53eef905..984072c5 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -22,19 +22,19 @@ clone: steps: # SSH初始化步骤 init-ssh: - image: alpine/git:latest + image: woodpeckerci/plugin-git environment: WOODPECKER_SSH_KEY: from_secret: WOODPECKER_SSH_KEY commands: - | # 设置SSH - mkdir -p ~/.ssh - echo "$${WOODPECKER_SSH_KEY}" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh-keyscan -H github.com >> ~/.ssh/known_hosts - ssh-keyscan -H bitbucket.org >> ~/.ssh/known_hosts - ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts + mkdir -p /root/.ssh /app/.ssh + echo "$${WOODPECKER_SSH_KEY}" > /app/.ssh/id_rsa + chmod 600 /app/.ssh/id_rsa + ssh-keyscan -H github.com >> /app/.ssh/known_hosts + ssh-keyscan -H bitbucket.org >> /app/.ssh/known_hosts + ssh-keyscan -H gitlab.com >> /app/.ssh/known_hosts # 配置git git config --global user.name "Woodpecker CI" From f86f1856f034212a2dc52a01b394e786335c6f55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 27 Jan 2026 00:02:38 +0800 Subject: [PATCH 06/20] 2 --- .woodpecker/archive-merged-branches.yaml | 76 +++++++++++ .woodpecker/my-first-workflow.yaml | 159 +++++++++++------------ 2 files changed, 155 insertions(+), 80 deletions(-) create mode 100644 .woodpecker/archive-merged-branches.yaml diff --git a/.woodpecker/archive-merged-branches.yaml b/.woodpecker/archive-merged-branches.yaml new file mode 100644 index 00000000..fd9b8802 --- /dev/null +++ b/.woodpecker/archive-merged-branches.yaml @@ -0,0 +1,76 @@ +when: + event: + - pull_request_close + +clone: + image: woodpeckerci/plugin-git + settings: + use-ssh: true + ssh-key-private: + from_secret: WOODPECKER_SSH_KEY + commands: + - | + # 设置SSH + mkdir -p /app/.ssh + chmod 700 /app/.ssh + echo "$${WOODPECKER_SSH_KEY}" > /app/.ssh/id_rsa + chmod 600 /app/.ssh/id_rsa + ssh-keyscan -H codeberg.org >> /app/.ssh/known_hosts + + # 配置git + git config --global user.name "Woodpecker CI" + git config --global user.email "ci@example.com" + +steps: + - name: 📦 Auto-Archive Merged Branches + image: alpine/git:latest + environment: + WOODPECKER_SSH_KEY: + from_secret: WOODPECKER_SSH_KEY + commands: + - | + # PR_TITLE=${CI_COMMIT_PULL_REQUEST_TITLE} + BRANCH_NAME=${CI_COMMIT_SOURCE_BRANCH} + DEFAULT_BRANCH=${CI_REPO_DEFAULT_BRANCH} + + # Set up SSH + mkdir -p ~/.ssh + echo "$${WOODPECKER_SSH_KEY}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H codeberg.org >> ~/.ssh/known_hosts + + # Configure git + git config --global user.name "Woodpecker CI" + git config --global user.email "ci@example.com" + + if [ "$BRANCH_NAME" = "$DEFAULT_BRANCH" ] || [[ "$BRANCH_NAME" == archived/* ]]; then + echo "⏭️ Skipping: Branch is default branch or already archived" + exit 0 + fi + + # if [[ "$PR_TITLE" == *NO_ARCHIVE* ]]; then + # echo "⏭️ Skipping: PR title contains NO_ARCHIVE" + # exit 0 + # fi + + TAG_NAME="archived/$BRANCH_NAME" + + echo "🏷️ Archiving branch: $BRANCH_NAME -> tag $TAG_NAME" + + git fetch origin --tags "$BRANCH_NAME" + + TAG_BASE="$TAG_NAME" + if git ls-remote --exit-code --tags origin "refs/tags/$TAG_BASE" >/dev/null 2>&1; then + echo "ℹ️ Tag $TAG_BASE already exists; searching for next suffix" + suffix=1 + while git ls-remote --exit-code --tags origin "refs/tags/${TAG_BASE}-${suffix}" >/dev/null 2>&1; do + suffix=$((suffix+1)) + done + TAG_NAME="${TAG_BASE}-${suffix}" + fi + + git tag "$TAG_NAME" "origin/$BRANCH_NAME" + git push origin "$TAG_NAME" + git push origin --delete "$BRANCH_NAME" + + echo "✅ Successfully archived branch as tag $TAG_NAME" \ No newline at end of file diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 984072c5..fd192ecc 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -1,47 +1,32 @@ -# Woodpecker原生顶层字段1:触发条件 +# 触发条件:仅push、manual手动触发,分支限定main when: event: - push - manual branch: main -# Woodpecker原生顶层字段2:代码克隆配置 +# 代码克隆配置:保留SSH拉取+标签/LFS支持 clone: git: image: woodpeckerci/plugin-git settings: - # 使用SSH密钥进行Git操作 use-ssh: true - # 确保SSH密钥私钥通过secret提供 ssh-key-private: from_secret: WOODPECKER_SSH_KEY - # 添加known_hosts配置以避免主机验证问题 - set-safe-directory: true + tags: true # 支持标签拉取(适配版本号生成,不用可删) + lfs: true # 支持LFS(项目无LFS可删) -# Woodpecker原生顶层字段3:流水线步骤 +# 全局配置变量(替换占位符即可使用) +variables: + SCREEN_NAME: "logic_service" + REMOTE_EXE_DIR: "/opt/logic" + JSON_CONFIG_URL: "https://你的JSON配置地址.com/deploy.json" + LOG_PATH: "$HOME/run.log" + +# 流水线核心步骤:仅保留编译+部署流程 steps: - # SSH初始化步骤 - init-ssh: - image: woodpeckerci/plugin-git - environment: - WOODPECKER_SSH_KEY: - from_secret: WOODPECKER_SSH_KEY - commands: - - | - # 设置SSH - mkdir -p /root/.ssh /app/.ssh - echo "$${WOODPECKER_SSH_KEY}" > /app/.ssh/id_rsa - chmod 600 /app/.ssh/id_rsa - ssh-keyscan -H github.com >> /app/.ssh/known_hosts - ssh-keyscan -H bitbucket.org >> /app/.ssh/known_hosts - ssh-keyscan -H gitlab.com >> /app/.ssh/known_hosts - - # 配置git - git config --global user.name "Woodpecker CI" - git config --global user.email "ci@example.com" - - # 1. 缓存Go依赖(加速构建) - cache-go-mod: + # 1. Go依赖缓存(加速构建,可选保留) + - name: cache-go-mod image: woodpeckerci/plugin-cache settings: mount: @@ -50,59 +35,73 @@ steps: key: ${CI_OS}-go-${CI_COMMIT_SHA:0:8} restore_keys: - ${CI_OS}-go- - depends_on: - - init-ssh # 2. 初始化Go环境 & 预下载依赖 - prepare-go: + - name: prepare-go image: golang:1.25 commands: - go version - go mod download -x - depends_on: - - cache-go-mod + - go mod verify # 验证依赖完整性(可选保留) - # 3. 生成构建版本号(8位短SHA) - set-version: + # 3. 生成构建版本号(优先Tag,无Tag则用8位短SHA) + - name: set-version image: golang:1.25 commands: - - VERSION="v$(git rev-parse --short=8 HEAD)" - - echo "BUILD_VERSION=${VERSION}" >> $CI_ENV_FILE - - echo "✅ 生成版本号:${VERSION}" - depends_on: - - prepare-go + - | + if [ -n "${CI_COMMIT_TAG}" ]; then + VERSION="${CI_COMMIT_TAG}" + else + VERSION="v$(git rev-parse --short=8 HEAD)" + fi + echo "BUILD_VERSION=${VERSION}" >> $CI_ENV_FILE + echo "✅ 生成版本号:${VERSION}" - # 4. 编译Go服务(静态编译,无系统依赖) - build-logic: + # 4. 直接编译Go服务(核心步骤,无测试前置) + - name: build-logic image: golang:1.25 + environment: + CGO_ENABLED: 0 + GO111MODULE: on + GOSUMDB: off commands: - mkdir -p build - BIN_NAME="logic_${BUILD_VERSION}" - echo "BIN_NAME=${BIN_NAME}" >> $CI_ENV_FILE - - > - CGO_ENABLED=0 GO111MODULE=on GOSUMDB=off 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 + - | + go build -v \ + -p=4 \ + -trimpath \ + -buildvcs=false \ + -ldflags "-s -w -buildid= -extldflags '-static' -X main.version=${BUILD_VERSION}" \ + -o ./build/${BIN_NAME} \ + ./logic + - | + if [ ! -f ./build/${BIN_NAME} ]; then echo "❌ 编译失败:产物${BIN_NAME}不存在" exit 1 fi - ls -lh ./build/ + - ./build/${BIN_NAME} -v || true # 验证程序可执行 - echo "✅ Go服务编译完成" - depends_on: - - set-version - # 5. 拉取JSON & 解析服务器/账号/密码/online_id - fetch-deploy-config: + # 5. 拉取JSON & 解析部署配置 + - name: fetch-deploy-config image: alpine:latest commands: - - apk add --no-cache curl jq openssh-client + - apk add --no-cache curl jq - echo "🔧 拉取部署配置:${JSON_CONFIG_URL}" - - curl -sSL ${JSON_CONFIG_URL} -o /tmp/deploy-config.json || { echo "❌ 拉取JSON失败"; exit 1; } + - | + # 3次重试机制,避免网络波动 + for i in 1 2 3; do + curl -sSL --connect-timeout 10 ${JSON_CONFIG_URL} -o /tmp/deploy-config.json && break + echo "⚠️ 第${i}次拉取失败,重试中..." + sleep 2 + done + if [ ! -f /tmp/deploy-config.json ]; then + echo "❌ 拉取JSON失败" + exit 1 + fi - | JSON_TYPE=$(jq -r 'type' /tmp/deploy-config.json) if [ "$JSON_TYPE" = "array" ]; then @@ -116,17 +115,22 @@ steps: REMOTE_PASSWORDS=$(jq -r '.password' /tmp/deploy-config.json) REMOTE_ONLINE_IDS=$(jq -r '.online_id' /tmp/deploy-config.json) fi + - | + # 配置非空检查 + if [ -z "$REMOTE_HOSTS" ] || [ -z "$REMOTE_USERS" ]; then + echo "❌ 解析配置失败:服务器/用户名为空" + cat /tmp/deploy-config.json + exit 1 + fi - echo "✅ 配置解析完成 | 服务器:${REMOTE_HOSTS} | 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 - depends_on: - - build-logic - # 6. SCP推送产物到远程服务器(密码认证) - scp-exe-to-servers: - image: appleboy/drone-scp + # 6. SCP推送产物到远程服务器 + - name: scp-exe-to-servers + image: appleboy/drone-scp:1.6.2 settings: host: ${REMOTE_HOSTS} username: ${REMOTE_USERS} @@ -135,21 +139,23 @@ steps: target: ${REMOTE_EXE_DIR}/ strip_components: 1 skip_verify: true + timeout: 30s depends_on: - build-logic - fetch-deploy-config - # 7. 远程部署:安装Screen + 优雅启动 + 状态验证 - deploy-to-servers: - image: appleboy/drone-ssh + # 7. 远程部署:安装Screen + 启动程序 + - name: deploy-to-servers + image: appleboy/drone-ssh:1.7.0 settings: host: ${REMOTE_HOSTS} username: ${REMOTE_USERS} password: ${REMOTE_PASSWORDS} skip_verify: true + timeout: 60s script: - | - # 检查/安装Screen(兼容apt/yum/dnf) + # 检查/安装Screen(兼容多包管理器) if command -v screen &> /dev/null; then echo "✅ Screen已安装" else @@ -161,10 +167,10 @@ steps: elif command -v dnf &> /dev/null; then dnf install -y screen -q else - echo "❌ 不支持的包管理器,安装失败" - exit 1 - fi - command -v screen || { echo "❌ Screen安装后检测失败"; exit 1; } + echo "❌ 不支持的包管理器,安装失败" + exit 1 + fi + command -v screen || { echo "❌ Screen安装后检测失败"; exit 1; } fi - mkdir -p ${REMOTE_EXE_DIR} - chmod +x ${REMOTE_EXE_DIR}/${BIN_NAME} || { echo "❌ 设置执行权限失败"; exit 1; } @@ -184,7 +190,7 @@ steps: - scp-exe-to-servers # 8. 打印部署完成汇总 - print-deploy-info: + - name: print-deploy-info image: alpine:latest commands: - echo "======================================" @@ -199,11 +205,4 @@ steps: - echo "📌 对应Commit:${CI_COMMIT_SHA}" - echo "======================================" depends_on: - - deploy-to-servers - -# 全局配置变量 -variables: - - &screen_name "logic_service" - - &remote_exe_dir "/opt/logic" - - &json_config_url "https://你的JSON配置地址.com/deploy.json" - - &log_path "$HOME/run.log" \ No newline at end of file + - deploy-to-servers \ No newline at end of file From a194d912b58cb83132581b3a6ab6758de72c4ff2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 27 Jan 2026 00:07:06 +0800 Subject: [PATCH 07/20] 1 --- .woodpecker/archive-merged-branches.yaml | 76 ------------------------ 1 file changed, 76 deletions(-) delete mode 100644 .woodpecker/archive-merged-branches.yaml diff --git a/.woodpecker/archive-merged-branches.yaml b/.woodpecker/archive-merged-branches.yaml deleted file mode 100644 index fd9b8802..00000000 --- a/.woodpecker/archive-merged-branches.yaml +++ /dev/null @@ -1,76 +0,0 @@ -when: - event: - - pull_request_close - -clone: - image: woodpeckerci/plugin-git - settings: - use-ssh: true - ssh-key-private: - from_secret: WOODPECKER_SSH_KEY - commands: - - | - # 设置SSH - mkdir -p /app/.ssh - chmod 700 /app/.ssh - echo "$${WOODPECKER_SSH_KEY}" > /app/.ssh/id_rsa - chmod 600 /app/.ssh/id_rsa - ssh-keyscan -H codeberg.org >> /app/.ssh/known_hosts - - # 配置git - git config --global user.name "Woodpecker CI" - git config --global user.email "ci@example.com" - -steps: - - name: 📦 Auto-Archive Merged Branches - image: alpine/git:latest - environment: - WOODPECKER_SSH_KEY: - from_secret: WOODPECKER_SSH_KEY - commands: - - | - # PR_TITLE=${CI_COMMIT_PULL_REQUEST_TITLE} - BRANCH_NAME=${CI_COMMIT_SOURCE_BRANCH} - DEFAULT_BRANCH=${CI_REPO_DEFAULT_BRANCH} - - # Set up SSH - mkdir -p ~/.ssh - echo "$${WOODPECKER_SSH_KEY}" > ~/.ssh/id_rsa - chmod 600 ~/.ssh/id_rsa - ssh-keyscan -H codeberg.org >> ~/.ssh/known_hosts - - # Configure git - git config --global user.name "Woodpecker CI" - git config --global user.email "ci@example.com" - - if [ "$BRANCH_NAME" = "$DEFAULT_BRANCH" ] || [[ "$BRANCH_NAME" == archived/* ]]; then - echo "⏭️ Skipping: Branch is default branch or already archived" - exit 0 - fi - - # if [[ "$PR_TITLE" == *NO_ARCHIVE* ]]; then - # echo "⏭️ Skipping: PR title contains NO_ARCHIVE" - # exit 0 - # fi - - TAG_NAME="archived/$BRANCH_NAME" - - echo "🏷️ Archiving branch: $BRANCH_NAME -> tag $TAG_NAME" - - git fetch origin --tags "$BRANCH_NAME" - - TAG_BASE="$TAG_NAME" - if git ls-remote --exit-code --tags origin "refs/tags/$TAG_BASE" >/dev/null 2>&1; then - echo "ℹ️ Tag $TAG_BASE already exists; searching for next suffix" - suffix=1 - while git ls-remote --exit-code --tags origin "refs/tags/${TAG_BASE}-${suffix}" >/dev/null 2>&1; do - suffix=$((suffix+1)) - done - TAG_NAME="${TAG_BASE}-${suffix}" - fi - - git tag "$TAG_NAME" "origin/$BRANCH_NAME" - git push origin "$TAG_NAME" - git push origin --delete "$BRANCH_NAME" - - echo "✅ Successfully archived branch as tag $TAG_NAME" \ No newline at end of file From 2920f8dcc2f09a1e505b5163756a1dc8db0efa1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 27 Jan 2026 00:44:48 +0800 Subject: [PATCH 08/20] =?UTF-8?q?```=20refactor(.woodpecker):=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=B7=A5=E4=BD=9C=E6=B5=81=E9=85=8D=E7=BD=AE=E7=AE=80?= =?UTF-8?q?=E5=8C=96CI/CD=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除默认代码克隆配置,改用skip_clone: true - 将prepare步骤改为手动git clone方式,支持SSH密钥认证 - 简化Go环境准备流程,移除依赖缓存步骤 - 调整步骤命名规范,统一使用驼峰命名 - 更新依赖关系引用,修正build_logic依赖名称 ``` --- .woodpecker/my-first-workflow.yaml | 71 ++++++++++++------------------ 1 file changed, 28 insertions(+), 43 deletions(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index fd192ecc..9686d66f 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -1,20 +1,10 @@ # 触发条件:仅push、manual手动触发,分支限定main when: - event: - - push - - manual + - event: push + - event: manual branch: main -# 代码克隆配置:保留SSH拉取+标签/LFS支持 -clone: - git: - image: woodpeckerci/plugin-git - settings: - use-ssh: true - ssh-key-private: - from_secret: WOODPECKER_SSH_KEY - tags: true # 支持标签拉取(适配版本号生成,不用可删) - lfs: true # 支持LFS(项目无LFS可删) +skip_clone: true # 全局配置变量(替换占位符即可使用) variables: @@ -25,27 +15,30 @@ variables: # 流水线核心步骤:仅保留编译+部署流程 steps: - # 1. Go依赖缓存(加速构建,可选保留) - - name: 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- + prepare: + image: debian:bookworm + secrets: [WOODPECKER_SSH_KEY] + commands: + - apt update + - apt install ca-certificates curl git -y + - mkdir -p /root/.ssh + - echo "$WOODPECKER_SSH_KEY" > /root/.ssh/id_ed25519 + - chmod 600 /root/.ssh/id_ed25519 + - ssh-keyscan codeberg.org >> /root/.ssh/known_hosts + - git init + - git remote add origin $CI_REPO_CLONE_SSH_URL + - git config core.sshCommand 'ssh -i /root/.ssh/id_ed25519' + - git fetch && git checkout $CI_REPO_DEFAULT_BRANCH + - git submodule update --init --recursive - # 2. 初始化Go环境 & 预下载依赖 - - name: prepare-go + prepare-go: image: golang:1.25 commands: - go version - go mod download -x - - go mod verify # 验证依赖完整性(可选保留) + - go mod verify - # 3. 生成构建版本号(优先Tag,无Tag则用8位短SHA) - - name: set-version + set-version: image: golang:1.25 commands: - | @@ -57,8 +50,7 @@ steps: echo "BUILD_VERSION=${VERSION}" >> $CI_ENV_FILE echo "✅ 生成版本号:${VERSION}" - # 4. 直接编译Go服务(核心步骤,无测试前置) - - name: build-logic + build_logic: image: golang:1.25 environment: CGO_ENABLED: 0 @@ -82,17 +74,15 @@ steps: exit 1 fi - ls -lh ./build/ - - ./build/${BIN_NAME} -v || true # 验证程序可执行 + - ./build/${BIN_NAME} -v || true - echo "✅ Go服务编译完成" - # 5. 拉取JSON & 解析部署配置 - - name: fetch-deploy-config + fetch-deploy-config: image: alpine:latest commands: - apk add --no-cache curl jq - echo "🔧 拉取部署配置:${JSON_CONFIG_URL}" - | - # 3次重试机制,避免网络波动 for i in 1 2 3; do curl -sSL --connect-timeout 10 ${JSON_CONFIG_URL} -o /tmp/deploy-config.json && break echo "⚠️ 第${i}次拉取失败,重试中..." @@ -116,7 +106,6 @@ steps: REMOTE_ONLINE_IDS=$(jq -r '.online_id' /tmp/deploy-config.json) fi - | - # 配置非空检查 if [ -z "$REMOTE_HOSTS" ] || [ -z "$REMOTE_USERS" ]; then echo "❌ 解析配置失败:服务器/用户名为空" cat /tmp/deploy-config.json @@ -128,8 +117,7 @@ steps: - echo "REMOTE_PASSWORDS=${REMOTE_PASSWORDS}" >> $CI_ENV_FILE - echo "REMOTE_ONLINE_IDS=${REMOTE_ONLINE_IDS}" >> $CI_ENV_FILE - # 6. SCP推送产物到远程服务器 - - name: scp-exe-to-servers + scp-exe-to-servers: image: appleboy/drone-scp:1.6.2 settings: host: ${REMOTE_HOSTS} @@ -141,11 +129,10 @@ steps: skip_verify: true timeout: 30s depends_on: - - build-logic + - build_logic - fetch-deploy-config - # 7. 远程部署:安装Screen + 启动程序 - - name: deploy-to-servers + deploy-to-servers: image: appleboy/drone-ssh:1.7.0 settings: host: ${REMOTE_HOSTS} @@ -155,7 +142,6 @@ steps: timeout: 60s script: - | - # 检查/安装Screen(兼容多包管理器) if command -v screen &> /dev/null; then echo "✅ Screen已安装" else @@ -189,8 +175,7 @@ steps: depends_on: - scp-exe-to-servers - # 8. 打印部署完成汇总 - - name: print-deploy-info + print-deploy-info: image: alpine:latest commands: - echo "======================================" From 53145a9e6bcec67efeeceb91c431f089a09f1666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 27 Jan 2026 00:47:07 +0800 Subject: [PATCH 09/20] 1 --- .woodpecker/my-first-workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 9686d66f..fbaff0c0 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -2,7 +2,7 @@ when: - event: push - event: manual - branch: main + branch: main skip_clone: true From 01eb26e6fa1e11d9e668a2861dd9c299fc32ee56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 27 Jan 2026 00:47:50 +0800 Subject: [PATCH 10/20] =?UTF-8?q?```=20refactor(.woodpecker):=20=E4=BF=AE?= =?UTF-8?q?=E6=94=B9SSH=E5=AF=86=E9=92=A5=E9=85=8D=E7=BD=AE=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 将WOODPECKER_SSH_KEY密钥从secrets字段迁移到environment.from_secret字段, 以符合新的配置格式要求 ``` --- .woodpecker/my-first-workflow.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index fbaff0c0..f419c2b4 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -17,7 +17,9 @@ variables: steps: prepare: image: debian:bookworm - secrets: [WOODPECKER_SSH_KEY] + environment: + from_secret: + WOODPECKER_SSH_KEY: WOODPECKER_SSH_KEY commands: - apt update - apt install ca-certificates curl git -y From 5ab01e3f75e4ee6c58ab84f5eae8ce8b13821e57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 27 Jan 2026 00:52:16 +0800 Subject: [PATCH 11/20] 1 --- .woodpecker/my-first-workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index f419c2b4..a794655c 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -26,7 +26,7 @@ steps: - mkdir -p /root/.ssh - echo "$WOODPECKER_SSH_KEY" > /root/.ssh/id_ed25519 - chmod 600 /root/.ssh/id_ed25519 - - ssh-keyscan codeberg.org >> /root/.ssh/known_hosts + - ssh-keyscan github.com >> /root/.ssh/known_hosts - git init - git remote add origin $CI_REPO_CLONE_SSH_URL - git config core.sshCommand 'ssh -i /root/.ssh/id_ed25519' From b0c091f81dedeb16ebe00196fabe810994f67166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 27 Jan 2026 00:57:40 +0800 Subject: [PATCH 12/20] 1 --- .woodpecker/my-first-workflow.yaml | 53 +++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index a794655c..09149cb0 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -1,4 +1,4 @@ -# 触发条件:仅push、manual手动触发,分支限定main +# 触发条件:仅push、manual手动触发,分支限定main(修正格式错误) when: - event: push - event: manual @@ -13,8 +13,9 @@ variables: JSON_CONFIG_URL: "https://你的JSON配置地址.com/deploy.json" LOG_PATH: "$HOME/run.log" -# 流水线核心步骤:仅保留编译+部署流程 +# 流水线核心步骤:理顺依赖链,确保build依赖clone结果 steps: + # ========== 1. 替代clone:拉取代码(核心依赖) ========== prepare: image: debian:bookworm environment: @@ -22,45 +23,64 @@ steps: WOODPECKER_SSH_KEY: WOODPECKER_SSH_KEY commands: - apt update - - apt install ca-certificates curl git -y - - mkdir -p /root/.ssh - - echo "$WOODPECKER_SSH_KEY" > /root/.ssh/id_ed25519 + # 安装完整依赖(解决SSH/libcrypto问题) + - apt install -y ca-certificates curl git openssh-client openssl libssl-dev + # 清理旧SSH文件,严格配置权限 + - rm -rf /root/.ssh/* + - mkdir -p /root/.ssh && chmod 700 /root/.ssh + # 写入并清理SSH密钥(去除多余换行) + - echo "$WOODPECKER_SSH_KEY" | tr -d '\r' > /root/.ssh/id_ed25519 - chmod 600 /root/.ssh/id_ed25519 - - ssh-keyscan github.com >> /root/.ssh/known_hosts + # 添加GitHub主机密钥 + - ssh-keyscan -H github.com > /root/.ssh/known_hosts && chmod 600 /root/.ssh/known_hosts + # 验证SSH连接(确保代码能拉取) + - ssh -v -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new git@github.com 2>&1 | grep "Authenticated to github.com" || { + echo "❌ SSH连接GitHub失败,请检查密钥配置"; exit 1; + } + # 拉取代码(拆分命令,避免静默失败) - git init - git remote add origin $CI_REPO_CLONE_SSH_URL - git config core.sshCommand 'ssh -i /root/.ssh/id_ed25519' - - git fetch && git checkout $CI_REPO_DEFAULT_BRANCH + - git fetch origin $CI_REPO_DEFAULT_BRANCH + - git checkout $CI_REPO_DEFAULT_BRANCH - git submodule update --init --recursive + - echo "✅ 代码拉取完成" + # ========== 2. 初始化Go环境(依赖prepare:代码拉取完成) ========== prepare-go: image: golang:1.25 + depends_on: [prepare] # 明确依赖:先拉代码,再初始化Go commands: - go version - go mod download -x - go mod verify + - echo "✅ Go环境初始化完成" + # ========== 3. 生成版本号(依赖prepare-go:Go环境就绪) ========== set-version: image: golang:1.25 + depends_on: [prepare-go] # 明确依赖:Go环境就绪后生成版本号 commands: - | if [ -n "${CI_COMMIT_TAG}" ]; then VERSION="${CI_COMMIT_TAG}" else - VERSION="v$(git rev-parse --short=8 HEAD)" + VERSION="v$(git rev-parse --short=8 HEAD)" # 依赖prepare拉取的代码 fi echo "BUILD_VERSION=${VERSION}" >> $CI_ENV_FILE echo "✅ 生成版本号:${VERSION}" + # ========== 4. 编译Go服务(核心依赖:prepare+prepare-go+set-version) ========== build_logic: image: golang:1.25 + depends_on: [set-version] # 明确依赖:版本号生成后再编译 environment: CGO_ENABLED: 0 GO111MODULE: on GOSUMDB: off commands: - mkdir -p build - - BIN_NAME="logic_${BUILD_VERSION}" + - BIN_NAME="logic_${BUILD_VERSION}" # 依赖set-version的BUILD_VERSION - echo "BIN_NAME=${BIN_NAME}" >> $CI_ENV_FILE - | go build -v \ @@ -69,7 +89,7 @@ steps: -buildvcs=false \ -ldflags "-s -w -buildid= -extldflags '-static' -X main.version=${BUILD_VERSION}" \ -o ./build/${BIN_NAME} \ - ./logic + ./logic # 依赖prepare拉取的./logic代码目录 - | if [ ! -f ./build/${BIN_NAME} ]; then echo "❌ 编译失败:产物${BIN_NAME}不存在" @@ -79,8 +99,10 @@ steps: - ./build/${BIN_NAME} -v || true - echo "✅ Go服务编译完成" + # ========== 5. 拉取部署配置(可并行,建议依赖prepare确保代码拉取完成) ========== fetch-deploy-config: image: alpine:latest + depends_on: [prepare] # 确保代码拉取完成后再拉配置 commands: - apk add --no-cache curl jq - echo "🔧 拉取部署配置:${JSON_CONFIG_URL}" @@ -119,6 +141,7 @@ steps: - 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:1.6.2 settings: @@ -134,6 +157,7 @@ steps: - build_logic - fetch-deploy-config + # ========== 7. 远程部署(依赖SCP推送) ========== deploy-to-servers: image: appleboy/drone-ssh:1.7.0 settings: @@ -174,11 +198,12 @@ steps: echo "❌ 启动失败,无${SCREEN_NAME}会话" screen -ls && exit 1 fi - depends_on: - - scp-exe-to-servers + depends_on: [scp-exe-to-servers] + # ========== 8. 打印部署汇总(依赖部署完成) ========== print-deploy-info: image: alpine:latest + depends_on: [deploy-to-servers] commands: - echo "======================================" - echo "🎉 全量部署完成!" @@ -190,6 +215,4 @@ steps: - echo "📌 程序目录:${REMOTE_EXE_DIR}" - echo "📌 日志路径:${LOG_PATH}" - echo "📌 对应Commit:${CI_COMMIT_SHA}" - - echo "======================================" - depends_on: - - deploy-to-servers \ No newline at end of file + - echo "======================================" \ No newline at end of file From c08d87342503d91b613f79ac37520e252b79ad4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 27 Jan 2026 01:01:23 +0800 Subject: [PATCH 13/20] 1 --- .woodpecker/my-first-workflow.yaml | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 09149cb0..c5d17f9d 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -28,14 +28,25 @@ steps: # 清理旧SSH文件,严格配置权限 - rm -rf /root/.ssh/* - mkdir -p /root/.ssh && chmod 700 /root/.ssh - # 写入并清理SSH密钥(去除多余换行) + # 写入并清理SSH密钥(兼容RSA/ED25519,保留原始换行) - echo "$WOODPECKER_SSH_KEY" | tr -d '\r' > /root/.ssh/id_ed25519 - chmod 600 /root/.ssh/id_ed25519 - # 添加GitHub主机密钥 - - ssh-keyscan -H github.com > /root/.ssh/known_hosts && chmod 600 /root/.ssh/known_hosts - # 验证SSH连接(确保代码能拉取) - - ssh -v -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new git@github.com 2>&1 | grep "Authenticated to github.com" || { - echo "❌ SSH连接GitHub失败,请检查密钥配置"; exit 1; + # 添加GitHub主机密钥(完整覆盖,避免重复) + - ssh-keyscan -H github.com > /root/.ssh/known_hosts + - chmod 600 /root/.ssh/known_hosts + # 增强SSH调试:输出详细日志+密钥有效性检查 + - echo "🔍 检查SSH密钥格式..." + - ssh-keygen -lf /root/.ssh/id_ed25519 || { + echo "❌ 密钥格式错误!请确认私钥完整且无密码"; + exit 1; + } + - echo "🔍 尝试SSH连接GitHub(详细日志)..." + - ssh -vvv -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new git@github.com 2>&1 | grep -E "Authenticated to github.com|successfully authenticated" || { + echo "❌ SSH连接GitHub失败,请检查:"; + echo " 1. WOODPECKER_SSH_KEY是完整的无密码私钥"; + echo " 2. 对应公钥已添加到GitHub账号(Settings → SSH and GPG keys)"; + echo " 3. CI服务器IP未被GitHub IP白名单拦截"; + exit 1; } # 拉取代码(拆分命令,避免静默失败) - git init @@ -99,7 +110,7 @@ steps: - ./build/${BIN_NAME} -v || true - echo "✅ Go服务编译完成" - # ========== 5. 拉取部署配置(可并行,建议依赖prepare确保代码拉取完成) ========== + # ========== 5. 拉取部署配置(可并行,依赖prepare确保代码拉取完成) ========== fetch-deploy-config: image: alpine:latest depends_on: [prepare] # 确保代码拉取完成后再拉配置 From 3ed8c009dbf6ef47961279eda3149e65b66e71c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 27 Jan 2026 01:10:08 +0800 Subject: [PATCH 14/20] 2 --- .woodpecker/my-first-workflow.yaml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index c5d17f9d..f59049a4 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -34,12 +34,7 @@ steps: # 添加GitHub主机密钥(完整覆盖,避免重复) - ssh-keyscan -H github.com > /root/.ssh/known_hosts - chmod 600 /root/.ssh/known_hosts - # 增强SSH调试:输出详细日志+密钥有效性检查 - - echo "🔍 检查SSH密钥格式..." - - ssh-keygen -lf /root/.ssh/id_ed25519 || { - echo "❌ 密钥格式错误!请确认私钥完整且无密码"; - exit 1; - } + - echo "🔍 尝试SSH连接GitHub(详细日志)..." - ssh -vvv -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new git@github.com 2>&1 | grep -E "Authenticated to github.com|successfully authenticated" || { echo "❌ SSH连接GitHub失败,请检查:"; From ecbed789d06e8a76324e03e8d6ac854f0bc8e4c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=94=E5=BF=B5?= <12574910+72wo@users.noreply.github.com> Date: Tue, 27 Jan 2026 02:28:38 +0800 Subject: [PATCH 15/20] 1 --- .woodpecker/my-first-workflow.yaml | 1 - 1 file changed, 1 deletion(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index f59049a4..5a242c2f 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -49,7 +49,6 @@ steps: - git config core.sshCommand 'ssh -i /root/.ssh/id_ed25519' - git fetch origin $CI_REPO_DEFAULT_BRANCH - git checkout $CI_REPO_DEFAULT_BRANCH - - git submodule update --init --recursive - echo "✅ 代码拉取完成" # ========== 2. 初始化Go环境(依赖prepare:代码拉取完成) ========== From 99672f89fc7d1de27838c12058f973af49e30b1d Mon Sep 17 00:00:00 2001 From: 72wo <1@72wo.cn> Date: Tue, 27 Jan 2026 03:30:36 +0800 Subject: [PATCH 16/20] Update my-first-workflow.yaml --- .woodpecker/my-first-workflow.yaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 5a242c2f..3243d508 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -29,7 +29,9 @@ steps: - rm -rf /root/.ssh/* - mkdir -p /root/.ssh && chmod 700 /root/.ssh # 写入并清理SSH密钥(兼容RSA/ED25519,保留原始换行) - - echo "$WOODPECKER_SSH_KEY" | tr -d '\r' > /root/.ssh/id_ed25519 + # 替换原echo "$WOODPECKER_SSH_KEY"那行,其余ssh配置不变 + - echo "$WOODPECKER_SSH_KEY" > /root/.ssh/id_ed25519 && chmod 600 /root/.ssh/id_ed25519 + - chmod 600 /root/.ssh/id_ed25519 # 添加GitHub主机密钥(完整覆盖,避免重复) - ssh-keyscan -H github.com > /root/.ssh/known_hosts @@ -220,4 +222,4 @@ steps: - echo "📌 程序目录:${REMOTE_EXE_DIR}" - echo "📌 日志路径:${LOG_PATH}" - echo "📌 对应Commit:${CI_COMMIT_SHA}" - - echo "======================================" \ No newline at end of file + - echo "======================================" From 7ffb03b2df746cb34d43db51da64405fc9981e0c Mon Sep 17 00:00:00 2001 From: 72wo <1@72wo.cn> Date: Tue, 27 Jan 2026 03:34:17 +0800 Subject: [PATCH 17/20] Update my-first-workflow.yaml --- .woodpecker/my-first-workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 3243d508..912c5adf 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -38,7 +38,7 @@ steps: - chmod 600 /root/.ssh/known_hosts - echo "🔍 尝试SSH连接GitHub(详细日志)..." - - ssh -vvv -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new git@github.com 2>&1 | grep -E "Authenticated to github.com|successfully authenticated" || { + - ssh -vvv -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new git@github.com 2>&1; exit 0 echo "❌ SSH连接GitHub失败,请检查:"; echo " 1. WOODPECKER_SSH_KEY是完整的无密码私钥"; echo " 2. 对应公钥已添加到GitHub账号(Settings → SSH and GPG keys)"; From 8630c253266c575030ade4685b37e37149c0304b Mon Sep 17 00:00:00 2001 From: 72wo <1@72wo.cn> Date: Tue, 27 Jan 2026 03:36:34 +0800 Subject: [PATCH 18/20] Update my-first-workflow.yaml From b32237c62259e1838085b33f5da4cded4f4a5430 Mon Sep 17 00:00:00 2001 From: 72wo <1@72wo.cn> Date: Tue, 27 Jan 2026 03:40:49 +0800 Subject: [PATCH 19/20] Update my-first-workflow.yaml --- .woodpecker/my-first-workflow.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 912c5adf..78e40107 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -38,7 +38,7 @@ steps: - chmod 600 /root/.ssh/known_hosts - echo "🔍 尝试SSH连接GitHub(详细日志)..." - - ssh -vvv -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new git@github.com 2>&1; exit 0 + - ssh -vvv -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new git@github.com 2>&1; exit 0; echo "❌ SSH连接GitHub失败,请检查:"; echo " 1. WOODPECKER_SSH_KEY是完整的无密码私钥"; echo " 2. 对应公钥已添加到GitHub账号(Settings → SSH and GPG keys)"; From 799b9cd64e4ada809795702979d5529ad8ec0047 Mon Sep 17 00:00:00 2001 From: 72wo <1@72wo.cn> Date: Tue, 27 Jan 2026 03:46:44 +0800 Subject: [PATCH 20/20] Update my-first-workflow.yaml --- .woodpecker/my-first-workflow.yaml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.woodpecker/my-first-workflow.yaml b/.woodpecker/my-first-workflow.yaml index 78e40107..26b64a76 100644 --- a/.woodpecker/my-first-workflow.yaml +++ b/.woodpecker/my-first-workflow.yaml @@ -38,13 +38,7 @@ steps: - chmod 600 /root/.ssh/known_hosts - echo "🔍 尝试SSH连接GitHub(详细日志)..." - - ssh -vvv -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new git@github.com 2>&1; exit 0; - echo "❌ SSH连接GitHub失败,请检查:"; - echo " 1. WOODPECKER_SSH_KEY是完整的无密码私钥"; - echo " 2. 对应公钥已添加到GitHub账号(Settings → SSH and GPG keys)"; - echo " 3. CI服务器IP未被GitHub IP白名单拦截"; - exit 1; - } + - ssh -vvv -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=accept-new git@github.com 2>&1 # 拉取代码(拆分命令,避免静默失败) - git init - git remote add origin $CI_REPO_CLONE_SSH_URL