Jenkins 运行一次构建,至少涉及三件不同的事:生成产物、把产物送到目标位置、让目标环境使用它并验证健康。2018 年配置 Spring Boot 与 Angular 项目时,最容易混在一起的正是这三步。

先固定任务使用的环境

后端需要明确 JDK、Maven 或 Wrapper;前端需要匹配项目的 Node、包管理器、锁文件和 Angular CLI。管理员电脑上的环境,不等于实际构建 agent 的环境。

检查源码分支和提交、构建入口、工作目录,以及任务选择的工具配置。不要用 source /etc/profile 试图隐藏所有环境差异,也不要在 CI 中随意改项目依赖版本。

Spring Boot:先构建、测试,再确认包的形式

Shell 步骤中的 Maven 示例可以是:

./mvnw -B clean verify

项目需要已包含受信任的 Wrapper,并能使用其配置的 Maven/JDK。没有 Wrapper 时,可按任务已配置的 Maven 调用;Maven 目标输入框与 Shell 命令的写法不同,参见目标参数与 mvn 前缀。

verify 覆盖正常生命周期中配置的测试与验证,不代表项目已经配置了所有必要测试。不要默认用跳过测试参数换取“绿色构建”。

检查 pom 的 packaging 和实际 target 目录,确定产物究竟是可执行 JAR、普通 JAR 还是 WAR。不是所有 .war 都按同一种方式运行,也不能只看扩展名决定启动命令。

一个只做构建和归档的 Pipeline 示意为:

pipeline {
    agent any
    stages {
        stage('Build and test') {
            steps {
                sh './mvnw -B clean verify'
            }
        }
        stage('Archive') {
            steps {
                archiveArtifacts artifacts: 'target/*.jar, target/*.war',
                    fingerprint: true
            }
        }
    }
}

这是单模块项目的示意,目录与归档规则应匹配实际构建;它没有部署步骤,也不是完整生产流水线。Jenkinsfile 的构建、测试与部署阶段

Angular:依赖安装与目标构建配置分别确定

有兼容锁文件、Node/npm 版本的项目,可使用 npm ci 安装锁定依赖。构建则应由 package.json 脚本和 Angular 项目配置共同定义。

例如,在支持命名配置、且已配置 production 的 Angular CLI 项目里:

npm ci
npm run build -- --configuration=production

这不是给所有 2018 年项目直接替换参数的命令。旧 CLI 的 —dev 表示的历史构建语境,与当前项目配置不能混用。输出目录以该项目实际 outputPath 和构建结果为准,不一律假设是某个固定 dist 子目录。Angular 工作区构建配置

SSH 传输的四个字段怎样配合

Publish Over SSH 的配置可这样理解:

字段含义
Source files从构建工作区选择要传的文件
Remove prefix从所选源路径前部去掉的目录前缀
Remote directory相对该 SSH 配置远端基目录的目标子目录
Exec command传输后在远端执行的命令,不等于自动健康检查

假设远端基目录为 /srv/myapp,源文件是 backend/target/app.jar,移除前缀 backend/target,再指定远端子目录 releases/build-123,目标可理解为 /srv/myapp/releases/build-123/app.jar。Remove prefix 必须与全部所选文件的前缀匹配,不能靠它修复任意路径。插件字段说明 · Remove prefix 帮助

主机、凭据和目录是示例。实际任务应使用受控凭据、主机身份核验和最小权限,不默认向 root 目录上传或拼接用户输入执行命令。

上传完成后,发布还没完成

正式发布还应有不可混淆的产物版本、校验和、目标目录、激活方式和健康检查。保留可恢复的旧版本,并让回滚也恢复匹配的配置;涉及数据库兼容时,还不能只靠切换 JAR 回滚。

不要把“文件传到了”写成“服务已正确上线”。前端检查实际入口和静态资源,后端检查进程、健康状态与必要业务路径;发布失败应明确停止或回退,而不是覆盖下一次构建继续尝试。