Maven 与 Git 完美整合:从代码管理到自动化构建的全流程实战指南

引言:为什么需要 Maven 与 Git 的整合?
在现代软件开发中,代码管理和自动化构建是两个核心环节。Git 作为分布式版本控制系统,已经成为代码管理的标准工具;而 Maven 作为 Java 项目管理和构建工具,提供了强大的依赖管理和构建生命周期。将两者完美整合,可以实现从代码提交到自动构建、部署的全流程自动化,极大提升开发效率和团队协作能力。
整合的核心价值
版本控制与构建的无缝衔接
:代码提交后自动触发构建
依赖管理的版本化
:Maven 依赖版本与 Git 标签同步
构建产物的可追溯性
:每个构建都能对应到具体的代码提交
团队协作效率提升
:标准化的开发流程和构建流程
第一部分:Git 基础与最佳实践
Git 工作流规范
在 Maven 项目中,推荐使用 Git Flow 工作流,它定义了严格的分支管理策略:
# 主要分支
– main/master: 生产环境代码,稳定版本
– develop: 开发分支,最新开发进度
– feature/*: 功能分支,从 develop 创建
– release/*: 发布分支,准备发布的版本
– hotfix/*: 热修复分支,生产环境紧急修复

# 创建功能分支示例
git checkout -b feature/user-authentication develop

# 完成功能并合并到 develop
git checkout develop
git merge –no-ff feature/user-authentication
git branch -d feature/user-authentication
Maven 项目的 .gitignore 配置
Maven 项目需要忽略特定的文件和目录,避免将构建产物提交到版本库:
# Maven 构建产物
target/
*.jar
*.war
*.ear

# Maven 配置文件(如果包含敏感信息)
settings.xml

# IDE 配置文件
.idea/
*.iml
.project
.classpath
.settings/

# 临时文件
*.tmp
*.log

# 操作系统文件
.DS_Store
Thumbs.db

# 测试报告
test-results/
提交信息规范
采用语义化提交信息,便于自动化工具解析和生成变更日志:
# 格式:<类型>(<范围>): <主题>

# 示例
feat(auth): 添加 JWT 认证支持
fix(database): 修复连接池泄漏问题
docs(api): 更新 REST API 文档
style(ui): 调整按钮样式
refactor(service): 重构用户服务逻辑
test(unit): 添加用户服务单元测试
chore(deps): 升级 Spring Boot 到 2.7.0

# 破坏性变更需要在正文中说明
BREAKING CHANGE: 移除了旧的认证 API,需要更新客户端代码
第二部分:Maven 项目配置优化
1. Maven 项目结构标准化
一个标准的 Maven 项目结构应该如下:
my-project/
├── pom.xml
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── myproject/
│ │ │ ├── Application.java
│ │ │ ├── controller/
│ │ │ ├── service/
│ │ │ └── model/
│ │ ├── resources/
│ │ │ ├── application.properties
│ │ │ ├── logback-spring.xml
│ │ │ └── static/
│ │ └── webapp/
│ └── test/
│ ├── java/
│ └── resources/
├── .gitignore
├── README.md
└── .git/
2. 精心设计的 POM 文件
POM(Project Object Model)是 Maven 的核心配置文件。以下是一个生产级的 POM 配置示例:

4.0.0


com.example
my-spring-boot-app
1.0.0-SNAPSHOT jar

My Spring Boot Application
Demo project for Spring Boot with Maven and Git

17
1717 UTF-8 2.7.0
3.10.1
3.0.0-M7
3.2.2
3.3.2





org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import






org.springframework.boot
spring-boot-starter-web



org.springframework.boot
spring-boot-starter-data-jpa



mysql
mysql-connector-java
runtime



org.springframework.boot
spring-boot-starter-test
test



org.projectlombok
lomboktrue



org.springframework.boot
spring-boot-starter-actuator



${project.artifactId}-${project.version}

org.apache.maven.plugins
maven-compiler-plugin
${maven.compiler.plugin.version}
${java.version}
${java.version}
${project.build.sourceEncoding}
org.projectlombok
lombok
1.18.24

org.springframework.boot
spring-boot-maven-plugin
${spring-boot.version}

com.example.myproject.Application
true




repackage


org.apache.maven.plugins
maven-surefire-plugin
${maven.surefire.plugin.version}

false

**/*Test.java


**/*IntegrationTest.java

org.apache.maven.plugins
maven-failsafe-plugin
3.0.0-M7



integration-test
verify





**/*IntegrationTest.java

org.apache.maven.plugins
maven-javadoc-plugin
3.4.1


attach-javadocs

jar




${project.build.sourceEncoding}
${project.build.sourceEncoding}

org.apache.maven.plugins
maven-source-plugin
3.2.1


attach-sources

jar





src/main/resources
true

**/*.properties
**/*.xml



src/main/resources
false

**/*.properties
**/*.xml





src/test/resources
true


dev dev
true

test test

prod prod




central
Maven Central Repository
https://repo.maven.apache.org/maven2

true


false




company-repo
Company Internal Repository
https://repo.company.com/maven2

true


true
always


central
Maven Central Repository
https://repo.maven.apache.org/maven2

true


false
3. 多模块项目配置
对于大型项目,推荐使用 Maven 多模块结构:
4.0.0
com.example
my-project
1.0.0 pom


my-project-common
my-project-core
my-project-web
my-project-service






com.example
my-project-common
${project.version}



com.example
my-project
1.0.0

my-project-core jar



com.example
my-project-common

第三部分:Git 与 Maven 的版本管理整合
1. 使用 Git 标签管理 Maven 版本
Git 标签是发布版本的重要标记,可以与 Maven 版本完美对应:
# 1. 准备发布版本
git checkout develop
git pull origin develop

# 2. 创建发布分支
git checkout -b release/1.0.0 develop

# 3. 更新版本号(移除 SNAPSHOT)
mvn versions:set -DnewVersion=1.0.0
# 或者手动修改 pom.xml

# 4. 提交版本变更
git add pom.xml
git commit -m “release: prepare release 1.0.0”

# 5. 创建 Git 标签
git tag -a v1.0.0 -m “Release version 1.0.0”

# 6. 合并到 main 和 develop
git checkout main
git merge –no-ff release/1.0.0
git checkout develop
git merge –no-ff release/1.0.0

# 7. 推送
git push origin main
git push origin develop
git push origin v1.0.0

# 8. 删除发布分支
git branch -d release/1.0.0
2. 自动化版本管理插件
使用
versions-maven-plugin
自动化版本管理:
org.codehaus.mojo
versions-maven-plugin
2.12.0

false
常用命令:
# 设置新版本
mvn versions:set -DnewVersion=2.0.0-SNAPSHOT

# 提交版本变更
mvn versions:commit

# 回滚版本变更
mvn versions:revert

# 更新快照版本到最新
mvn versions:use-latest-versions

# 检查可用更新
mvn versions:display-dependency-updates
mvn versions:display-plugin-updates
3. 基于 Git 提交的版本号生成
在 CI/CD 环境中,可以使用 Git 提交信息生成构建版本号:
#!/bin/bash
# generate-version.sh

# 获取 Git 提交哈希
GIT_COMMIT=$(git rev-parse –short HEAD)

# 获取 Git 标签
GIT_TAG=$(git describe –tags –abbrev=0 2>/dev/null || echo “0.0.0”)

# 获取分支名
GIT_BRANCH=$(git rev-parse –abbrev-ref HEAD)

# 生成版本号:标签-分支-提交哈希
VERSION=”${GIT_TAG}-${GIT_BRANCH}-${GIT_COMMIT}”

echo $VERSION
在 Maven 中使用:
mvn clean install -Dversion.suffix=$(./generate-version.sh)
第四部分:Git Hooks 与 Maven 的自动化整合
1. 预提交钩子(pre-commit)
创建
.git/hooks/pre-commit
文件:
#!/bin/bash
# .git/hooks/pre-commit

echo “Running pre-commit checks…”

# 检查是否有未提交的 pom.xml 变更
if git diff –cached –name-only | grep -q “pom.xml”; then
echo “POM file changed. Running Maven validation…”

# 运行 Maven 验证
if ! mvn clean validate; then
echo “Maven validation failed. Commit aborted.”
exit 1
fi
fi

# 检查代码格式(如果使用 Checkstyle)
echo “Running code style checks…”
if ! mvn checkstyle:check; then
echo “Code style check failed. Commit aborted.”
exit 1
fi

# 运行单元测试
echo “Running unit tests…”
if ! mvn test -DskipITs=true; then
echo “Unit tests failed. Commit aborted.”
exit 1
fi

echo “Pre-commit checks passed!”
exit 0
使钩子可执行:
chmod +x .git/hooks/pre-commit
2. 提交后钩子(post-commit)
创建
.git/hooks/post-commit
:
#!/bin/bash
# .git/hooks/post-commit

# 获取提交信息
COMMIT_MSG=$(cat .git/COMMIT_EDITMSG)

# 检查是否是版本发布提交
if echo “$COMMIT_MSG” | grep -q “release:”; then
echo “Detected release commit. Triggering build…”

# 触发本地构建
mvn clean deploy -Pprod
fi
3. 推送前钩子(pre-push)
创建
.git/hooks/pre-push
:
#!/bin/bash
# .git/hooks/pre-push

echo “Running pre-push checks…”

# 运行完整的测试套件
echo “Running full test suite…”
if ! mvn clean verify; then
echo “Full test suite failed. Push aborted.”
exit 1
fi

# 检查代码覆盖率
echo “Checking code coverage…”
if ! mvn jacoco:check; then
echo “Code coverage check failed. Push aborted.”
exit 1
fi

echo “Pre-push checks passed!”
exit 0
第五部分:CI/CD 集成实战
1. Jenkins Pipeline 配置
创建
Jenkinsfile
在项目根目录:
pipeline {
agent any

environment {
MAVEN_OPTS = ‘-Dmaven.repo.local=.m2/repository -Xmx1024m’
DOCKER_REGISTRY = ‘registry.company.com’
APP_NAME = ‘my-spring-boot-app’
}

stages {
stage(‘Checkout’) {
steps {
checkout scm
script {
// 获取 Git 信息
GIT_COMMIT = sh(script: ‘git rev-parse –short HEAD’, returnStdout: true).trim()
GIT_BRANCH = sh(script: ‘git rev-parse –abbrev-ref HEAD’, returnStdout: true).trim()
GIT_TAG = sh(script: ‘git describe –tags –abbrev=0 2>/dev/null || echo “dev”‘, returnStdout: true).trim()
}
}
}

stage(‘Build’) {
steps {
sh “””
mvn clean compile -Dmaven.test.skip=true
“””
}
}

stage(‘Unit Tests’) {
steps {
sh “””
mvn test -DskipITs=true
“””
}
post {
always {
junit ‘**/target/surefire-reports/*.xml’
jacoco execPattern: ‘**/target/jacoco.exec’
}
}
}

stage(‘Integration Tests’) {
steps {
sh “””
mvn verify -DskipUnitTests=true
“””
}
post {
always {
junit ‘**/target/failsafe-reports/*.xml’
}
}
}

stage(‘Static Analysis’) {
steps {
sh “””
mvn checkstyle:check
mvn pmd:pmd
“””
}
post {
always {
publishHTML([
allowMissing: false,
alwaysLinkToLastBuild: true,
keepAll: true,
reportDir: ‘target/pmd’,
reportFiles: ‘pmd.html’,
reportName: ‘PMD Report’
])
}
}
}

stage(‘Package’) {
steps {
sh “””
mvn clean package -DskipTests -Dmaven.test.skip=true
“””
}
post {
success {
archiveArtifacts artifacts: ‘target/*.jar’, fingerprint: true
}
}
}

stage(‘Build Docker Image’) {
when {
anyOf {
branch ‘main’
branch ‘develop’
buildingTag()
}
}
steps {
script {
def imageTag = “${GIT_TAG}-${GIT_COMMIT}”
if (env.BRANCH_NAME == ‘main’) {
imageTag = “${GIT_TAG}”
} else if (env.BRANCH_NAME == ‘develop’) {
imageTag = “latest”
}

sh “””
docker build -t ${DOCKER_REGISTRY}/${APP_NAME}:${imageTag} .
docker tag ${DOCKER_REGISTRY}/${APP_NAME}:${imageTag} ${DOCKER_REGISTRY}/${APP_NAME}:latest
“””
}
}
}

stage(‘Push Docker Image’) {
when {
anyOf {
branch ‘main’
branch ‘develop’
buildingTag()
}
}
steps {
withCredentials([usernamePassword(credentialsId: ‘docker-registry-creds’, usernameVariable: ‘DOCKER_USER’, passwordVariable: ‘DOCKER_PASS’)]) {
sh “””
docker login -u ${DOCKER_USER} -p ${DOCKER_PASS} ${DOCKER_REGISTRY}
docker push ${DOCKER_REGISTRY}/${APP_NAME}:latest
docker push ${DOCKER_REGISTRY}/${APP_NAME}:${GIT_TAG}-${GIT_COMMIT}
“””
}
}
}

stage(‘Deploy to Staging’) {
when {
branch ‘develop’
}
steps {
sh “””
# 部署到测试环境
kubectl apply -f k8s/staging/deployment.yaml
kubectl rollout status deployment/${APP_NAME} -n staging
“””
}
}

stage(‘Deploy to Production’) {
when {
branch ‘main’
}
steps {
input message: ‘Deploy to production?’, ok: ‘Deploy’
sh “””
# 部署到生产环境
kubectl apply -f k8s/production/deployment.yaml
kubectl rollout status deployment/${APP_NAME} -n production
“””
}
}
}

post {
always {
// 清理工作空间
cleanWs()
}
success {
emailext (
subject: “SUCCESS: Job ‘${env.JOB_NAME} [${env.BUILD_NUMBER}]’”,
body: “Check console output at ‘${env.BUILD_URL}’”,
to: “dev-team@company.com”
)
}
failure {
emailext (
subject: “FAILURE: Job ‘${env.JOB_NAME} [${env.BUILD_NUMBER}]’”,
body: “Check console output at ‘${env.BUILD_URL}’”,
to: “dev-team@company.com”
)
}
}
}
2. GitHub Actions 配置
创建
.github/workflows/maven-ci-cd.yml
:
name: Maven CI/CD Pipeline

on:
push:
branches: [ main, develop ]
tags: [ ‘v*.*.*’ ]
pull_request:
branches: [ main, develop ]

env:
MAVEN_OPTS: -Dmaven.repo.local=.m2/repository -Xmx1024m
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
test:
name: Test
runs-on: ubuntu-latest

steps:
– name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0 # 获取完整 Git 历史以支持版本生成

– name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: ’17’
distribution: ‘temurin’
cache: maven

– name: Cache Maven dependencies
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles(‘**/pom.xml’) }}
restore-keys: |
${{ runner.os }}-maven-

– name: Run unit tests
run: mvn test -DskipITs=true –batch-mode

– name: Generate test report
uses: dorny/test-reporter@v1
if: success() || failure()
with:
name: Maven Tests
path: ‘**/target/surefire-reports/*.xml’
reporter: java-junit

– name: Run integration tests
run: mvn verify -DskipUnitTests=true –batch-mode

– name: Run static analysis
run: |
mvn checkstyle:check –batch-mode
mvn pmd:pmd –batch-mode

– name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
files: ./target/site/jacoco/jacoco.xml
flags: unittests
name: codecov-umbrella

– name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: jar-files
path: target/*.jar

build:
name: Build and Push
needs: test
runs-on: ubuntu-latest
if: github.event_name != ‘pull_request’

outputs:
image_tag: ${{ steps.meta.outputs.tags }}

steps:
– name: Checkout code
uses: actions/checkout@v3

– name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: ’17’
distribution: ‘temurin’
cache: maven

– name: Build JAR
run: mvn clean package -DskipTests –batch-mode

– name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

– name: Log in to Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

– name: Extract metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-

– name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max

– name: Generate SBOM
uses: anchore/sbom-action@v0
with:
image: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ steps.meta.outputs.version }}
format: spdx-json
output-file: sbom.spdx.json

– name: Upload SBOM
uses: actions/upload-artifact@v3
with:
name: sbom
path: sbom.spdx.json

deploy-staging:
name: Deploy to Staging
needs: build
runs-on: ubuntu-latest
if: github.ref == ‘refs/heads/develop’
environment: staging

steps:
– name: Checkout code
uses: actions/checkout@v3

– name: Deploy to Kubernetes
uses: azure/k8s-deploy@v4
with:
namespace: staging
manifests: |
k8s/staging/deployment.yaml
k8s/staging/service.yaml
images: |
${{ needs.build.outputs.image_tag }}
strategy: rolling

– name: Verify deployment
run: |
kubectl rollout status deployment/my-spring-boot-app -n staging –timeout=300s

– name: Run smoke tests
run: |
# 等待服务就绪
sleep 30
curl -f http://staging-app.company.com/actuator/health

deploy-production:
name: Deploy to Production
needs: build
runs-on: ubuntu-latest
if: startsWith(github.ref, ‘refs/tags/v’)
environment: production

steps:
– name: Checkout code
uses: actions/checkout@v3

– name: Create GitHub Release
uses: actions/create-release@v1
with:
tag_name: ${{ github.ref_name }}
release_name: Release ${{ github.ref_name }}
body: |
Changes in this Release:
– ${{ github.event.head_commit.message }}
draft: false
prerelease: false

– name: Deploy to Production
uses: azure/k8s-deploy@v4
with:
namespace: production
manifests: |
k8s/production/deployment.yaml
k8s/production/service.yaml
images: |
${{ needs.build.outputs.image_tag }}
strategy: rolling

– name: Verify production deployment
run: |
kubectl rollout status deployment/my-spring-boot-app -n production –timeout=600s

– name: Run production smoke tests
run: |
sleep 30
curl -f https://app.company.com/actuator/health

– name: Notify Slack
uses: 8398a7/action-slack@v3
with:
status: success
text: ‘🚀 Production deployment successful! ${{ github.ref_name }}’
webhook_url: ${{ secrets.SLACK_WEBHOOK }}
3. GitLab CI/CD 配置
创建
.gitlab-ci.yml
:
image: maven:3.8.6-openjdk-17

variables:
MAVEN_OPTS: “-Dmaven.repo.local=.m2/repository -Xmx1024m”
DOCKER_REGISTRY: “registry.company.com”
APP_NAME: “my-spring-boot-app”

cache:
paths:
– .m2/repository/
– target/

stages:
– test
– build
– package
– deploy

before_script:
– echo “Setting up environment…”
– export GIT_COMMIT_SHORT=$(git rev-parse –short HEAD)
– export GIT_TAG=$(git describe –tags –abbrev=0 2>/dev/null || echo “dev”)

unit_tests:
stage: test
script:
– mvn test -DskipITs=true
artifacts:
reports:
junit: target/surefire-reports/TEST-*.xml
paths:
– target/site/jacoco/
coverage: ‘/Total.*?([0-9]{1,3})%/’
only:
– develop
– main
– merge_requests

integration_tests:
stage: test
script:
– mvn verify -DskipUnitTests=true
artifacts:
reports:
junit: target/failsafe-reports/TEST-*.xml
only:
– develop
– main

static_analysis:
stage: test
script:
– mvn checkstyle:check
– mvn pmd:pmd
artifacts:
paths:
– target/pmd/
only:
– develop
– main

build_jar:
stage: build
script:
– mvn clean package -DskipTests
artifacts:
paths:
– target/*.jar
expire_in: 1 week
only:
– develop
– main
– tags

build_docker:
stage: package
image: docker:20.10
services:
– docker:20.10-dind
variables:
DOCKER_TLS_CERTDIR: “/certs”
before_script:
– docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $DOCKER_REGISTRY
script:
– |
if [ “$CI_COMMIT_BRANCH” == “main” ]; then
IMAGE_TAG=”$GIT_TAG”
elif [ “$CI_COMMIT_BRANCH” == “develop” ]; then
IMAGE_TAG=”latest”
else
IMAGE_TAG=”$GIT_TAG-$GIT_COMMIT_SHORT”
fi
– docker build -t $DOCKER_REGISTRY/$APP_NAME:$IMAGE_TAG .
– docker tag $DOCKER_REGISTRY/$APP_NAME:$IMAGE_TAG $DOCKER_REGISTRY/$APP_NAME:latest
– docker push $DOCKER_REGISTRY/$APP_NAME:$IMAGE_TAG
– docker push $DOCKER_REGISTRY/$APP_NAME:latest
only:
– develop
– main
– tags

deploy_staging:
stage: deploy
image: bitnami/kubectl:latest
script:
– kubectl config use-context staging
– kubectl apply -f k8s/staging/
– kubectl rollout status deployment/$APP_NAME -n staging
environment:
name: staging
url: https://staging-app.company.com
only:
– develop

deploy_production:
stage: deploy
image: bitnami/kubectl:latest
script:
– kubectl config use-context production
– kubectl apply -f k8s/production/
– kubectl rollout status deployment/$APP_NAME -n production
environment:
name: production
url: https://app.company.com
when: manual
only:
– main
only:
– tags

notify_success:
stage: deploy
script:
– ‘curl -X POST -H “Content-type: application/json” –data “{\”text\”:\”🚀 Deployment successful! Version: $GIT_TAG\”}” $SLACK_WEBHOOK’
when: on_success
only:
– main
– develop
第六部分:Docker 与 Maven 整合
1. Dockerfile 优化
# 多阶段构建
FROM maven:3.8.6-openjdk-17 AS builder

WORKDIR /app

# 复制 pom.xml 并下载依赖(利用 Docker 缓存)
COPY pom.xml .
RUN mvn dependency:go-offline -B

# 复制源代码
COPY src ./src

# 构建应用
RUN mvn clean package -DskipTests

# 运行时镜像
FROM openjdk:17-jdk-slim

# 安装必要的工具
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*

WORKDIR /app

# 从构建阶段复制 JAR 文件
COPY –from=builder /app/target/*.jar app.jar

# 创建非 root 用户
RUN groupadd -r appuser && useradd -r -g appuser appuser
RUN chown -R appuser:appuser /app
USER appuser

# 暴露端口
EXPOSE 8080

# 健康检查
HEALTHCHECK –interval=30s –timeout=3s –start-period=5s –retries=3 \
CMD curl -f http://localhost:8080/actuator/health || exit 1

# 启动命令
ENTRYPOINT [“java”, “-jar”, “app.jar”]
2. Docker Compose 配置
创建
docker-compose.yml
用于本地开发:
version: ‘3.8’

services:
app:
build:
context: .
dockerfile: Dockerfile
container_name: my-spring-boot-app
ports:
– “8080:8080”
environment:
– SPRING_PROFILES_ACTIVE=docker
– SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/myapp
– SPRING_DATASOURCE_USERNAME=root
– SPRING_DATASOURCE_PASSWORD=password
depends_on:
– mysql
– redis
volumes:
– ./logs:/app/logs
networks:
– app-network

mysql:
image: mysql:8.0
container_name: myapp-mysql
environment:
MYSQL_ROOT_PASSWORD: password
MYSQL_DATABASE: myapp
ports:
– “3306:3306”
volumes:
– mysql-data:/var/lib/mysql
networks:
– app-network

redis:
image: redis:7-alpine
container_name: myapp-redis
ports:
– “6379:6379”
volumes:
– redis-data:/data
networks:
– app-network

# 用于测试的容器
test-runner:
build:
context: .
dockerfile: Dockerfile.test
depends_on:
– app
networks:
– app-network

networks:
app-network:
driver: bridge

volumes:
mysql-data:
redis-data:
3. Maven 插件集成 Docker
使用
dockerfile-maven-plugin
: com.spotify
dockerfile-maven-plugin
1.4.13


default

build
push




registry.company.com/my-spring-boot-app
${project.version}

target/${project.build.finalName}.jar

使用方式:
# 构建并推送 Docker 镜像
mvn dockerfile:build dockerfile:push

# 或者在 package 阶段自动执行
mvn package
第七部分:依赖管理与版本控制最佳实践
1. 使用 Maven BOM 统一管理依赖
创建 BOM(Bill of Materials)项目:
4.0.0
com.example
my-project-bom
1.0.0 pom 2.7.0
2021.0.3
2.13.3
1.18.24





org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import



org.springframework.cloud
spring-cloud-dependencies
${spring-cloud.version}
pom
import



com.fasterxml.jackson
jackson-bom
${jackson.version}
pom
import



org.projectlombok
lombok
${lombok.version}
provided



com.example
common-utils
2.1.0


在业务项目中使用: com.example
my-project-bom
1.0.0




org.springframework.boot
spring-boot-starter-web


com.example
common-utils

2. 依赖版本与 Git 标签同步
创建脚本
sync-version.sh
:
#!/bin/bash
# sync-version.sh

# 获取当前 Git 标签
GIT_TAG=$(git describe –tags –abbrev=0)

# 检查是否为有效版本
if [[ ! $GIT_TAG =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
echo “Error: Invalid Git tag format: $GIT_TAG”
exit 1
fi

# 提取版本号(去掉 v 前缀)
VERSION=${GIT_TAG#v}

# 更新 POM 版本
mvn versions:set -DnewVersion=$VERSION

# 更新所有子模块版本
mvn versions:update-child-modules

# 提交变更
git add pom.xml */pom.xml
git commit -m “chore: sync version to $VERSION”

# 创建新的 Git 标签
git tag -a $GIT_TAG -m “Version $VERSION”

echo “Version synchronized: $VERSION”
3. 依赖漏洞扫描
集成 OWASP Dependency-Check: org.owasp
dependency-check-maven
7.1.1



check
verify



7
dependency-check-suppressions.xml
在 CI 中运行:
mvn dependency-check:check
第八部分:高级整合技巧
1. 使用 Git Submodule 管理共享配置
对于多项目共享的 Maven 配置:
# 添加共享配置仓库作为子模块
git submodule add https://github.com/company/maven-shared-config.git .mvn/shared

# 在父 POM 中引用

.mvn/shared
app1
app2

2. 基于 Git 工作流的环境配置
创建环境特定的配置文件:
src/main/resources/
├── application.properties
├── application-dev.properties
├── application-test.properties
└── application-prod.properties
在 POM 中配置资源过滤: dev dev


src/main/resources
true

application.properties
application-dev.properties



3. Git Hooks 实现版本自动更新
创建
.git/hooks/post-merge
:
#!/bin/bash
# .git/hooks/post-merge

# 检查是否是主分支合并
CURRENT_BRANCH=$(git rev-parse –abbrev-ref HEAD)
if [ “$CURRENT_BRANCH” == “main” ]; then
echo “Main branch updated. Checking version…”

# 获取最新标签
LATEST_TAG=$(git describe –tags –abbrev=0)

# 检查 POM 版本是否匹配
POM_VERSION=$(mvn help:evaluate -Dexpression=project.version -q -DforceStdout)

if [ “v$POM_VERSION” != “$LATEST_TAG” ]; then
echo “Version mismatch. Updating POM…”
mvn versions:set -DnewVersion=${LATEST_TAG#v}
git add pom.xml
git commit -m “chore: auto-update version to $LATEST_TAG”
fi
fi
第九部分:监控与日志整合
1. 应用日志与 Git 信息关联
在应用启动时记录 Git 信息:
@Component
public class GitInfoLogger {

@Value(“${git.commit.id:unknown}”)
private String gitCommitId;

@Value(“${git.branch:unknown}”)
private String gitBranch;

@Value(“${git.tags:unknown}”)
private String gitTags;

@PostConstruct
public void logGitInfo() {
Logger.info(“Application started with Git Info: branch={}, commit={}, tags={}”,
gitBranch, gitCommitId, gitTags);
}
}
在
pom.xml
中配置 Git 插件: pl.project13.maven
git-commit-id-plugin
4.9.10



revision




true
${project.build.outputDirectory}/git.properties

^git.build.*$
^git.commit.id.abbrev$
^git.branch$
^git.tags$

2. 分布式追踪与版本关联
使用 Spring Cloud Sleuth 与 Git 信息整合:
# application.yml
spring:
application:
name: my-spring-boot-app
sleuth:
sampler:
probability: 1.0
baggage:
remote-fields:
– git-commit
– git-branch
在日志中自动注入 Git 信息:
@Configuration
public class TracingConfiguration {

@Bean
public SpanCustomizer gitInfoSpanCustomizer(@Value(“${git.commit.id.abbrev:unknown}”) String commitId,
@Value(“${git.branch:unknown}”) String branch) {
return span -> {
span.setTag(“git.commit”, commitId);
span.setTag(“git.branch”, branch);
};
}
}
第十部分:故障排查与最佳实践
1. 常见问题及解决方案
问题 1:Maven 依赖冲突
症状
:
NoClassDefFoundError
或
ClassNotFoundException
解决方案
:
# 1. 分析依赖树
mvn dependency:tree -Dverbose > dependencies.txt

# 2. 排除冲突依赖

org.example
problematic-lib


conflicting-group
conflicting-artifact


# 3. 使用 dependency:analyze
mvn dependency:analyze
问题 2:Git Hook 不执行
症状
:钩子脚本没有运行
解决方案
:
# 1. 检查钩子权限
ls -la .git/hooks/

# 2. 确保钩子有执行权限
chmod +x .git/hooks/pre-commit

# 3. 检查钩子内容
cat .git/hooks/pre-commit

# 4. 测试钩子
GIT_TRACE=1 git commit -m “test”
问题 3:CI/CD 构建缓慢
症状
:构建时间过长
解决方案
:
# 1. 启用 Maven 并行构建
mvn -T 4 clean install

# 2. 使用构建缓存
# 在 CI 配置中缓存 .m2/repository

# 3. 跳过不必要的步骤
mvn clean package -DskipTests -DskipITs

# 4. 使用增量构建
mvn compile -Dincremental
2. 性能优化建议
Maven 性能优化

performance true
false
true

Git 性能优化
# 1. 定期清理
git gc –aggressive –prune=now

# 2. 浅克隆(CI 环境)
git clone –depth 1 https://github.com/user/repo.git

# 3. 部分克隆(大仓库)
git clone –filter=blob:none https://github.com/user/repo.git
3. 安全最佳实践
1. 敏感信息保护
永远不要
在 Git 中提交敏感信息:
# 如果已经提交,需要从历史中删除
git filter-branch –force –index-filter \
‘git rm –cached –ignore-unmatch src/main/resources/application-prod.properties’ \
–prune-empty –tag-name-filter cat — –all

# 使用 git-secrets 防止误提交
git secrets –install
git secrets –register-aws
2. Maven 仓库安全


central
https://repo.maven.apache.org/maven2

true
fail


3. 依赖扫描
集成 Snyk 或 OWASP 进行依赖漏洞扫描:
# Snyk 扫描
mvn snyk:test

# OWASP 扫描
mvn dependency-check:check
第十一部分:实战案例:完整项目示例
项目结构
spring-boot-maven-git-demo/
├── .github/
│ └── workflows/
│ └── ci-cd.yml
├── .gitignore
├── .gitattributes
├── README.md
├── pom.xml
├── docker-compose.yml
├── Dockerfile
├── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── demo/
│ │ │ ├── Application.java
│ │ │ ├── config/
│ │ │ ├── controller/
│ │ │ ├── service/
│ │ │ └── model/
│ │ └── resources/
│ │ ├── application.properties
│ │ ├── application-dev.properties
│ │ ├── application-prod.properties
│ │ └── logback-spring.xml
│ └── test/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── demo/
│ │ ├── unit/
│ │ └── integration/
│ └── resources/
│ └── test-application.properties
├── k8s/
│ ├── staging/
│ │ ├── deployment.yaml
│ │ └── service.yaml
│ └── production/
│ ├── deployment.yaml
│ └── service.yaml
└── scripts/
├── pre-commit
├── generate-version.sh
└── sync-version.sh
完整 POM 文件

4.0.0

com.example
spring-boot-maven-git-demo
1.0.0-SNAPSHOT jar

Spring Boot Maven Git Demo
Demo project showing Maven and Git integration

17
1717 UTF-8


2.7.0


3.10.1
2.7.0
3.0.0-M7
3.0.0-M7
3.4.1
3.2.1
3.2.0
3.18.0
0.8.8
4.9.10
1.4.13
2.12.0
7.1.1




org.springframework.boot
spring-boot-dependencies
${spring-boot.version}
pom
import





org.springframework.boot
spring-boot-starter-web


org.springframework.boot
spring-boot-starter-data-jpa


org.springframework.boot
spring-boot-starter-actuator


org.springframework.boot
spring-boot-starter-validation



mysql
mysql-connector-java
runtime



org.projectlombok
lomboktrue


org.apache.commons
commons-lang3



org.springframework.boot
spring-boot-starter-test
test


org.testcontainers
junit-jupiter
test


org.testcontainers
mysql
test


${project.artifactId}-${project.version}

org.apache.maven.plugins
maven-compiler-plugin
${maven.compiler.plugin.version}
${java.version}
${java.version}
${project.build.sourceEncoding}
org.projectlombok
lombok
1.18.24

org.springframework.boot
spring-boot-maven-plugin
${spring-boot-maven-plugin.version}

com.example.demo.Application
true

paketobuildpacks/builder-jammy-base





repackage


org.apache.maven.plugins
maven-surefire-plugin
${maven-surefire-plugin.version}

false

**/*Test.java


**/*IntegrationTest.java


target/jacoco.exec

org.apache.maven.plugins
maven-failsafe-plugin
${maven-failsafe-plugin.version}



integration-test
verify





**/*IntegrationTest.java

org.jacoco
jacoco-maven-plugin
${jacoco-maven-plugin.version}


prepare-agent

prepare-agent



report test
report



check

check




PACKAGE LINE
COVEREDRATIO
0.80
BRANCH
COVEREDRATIO
0.70




org.apache.maven.plugins
maven-checkstyle-plugin
${maven-checkstyle-plugin.version}

google_checks.xml
UTF-8
true
true false



validate validate
check


org.apache.maven.plugins
maven-pmd-plugin
${maven-pmd-plugin.version}

${java.version}

rulesets/java/maven-pmd-plugin-default.xml
false


verify
pmd
cpd


org.apache.maven.plugins
maven-javadoc-plugin
${maven-javadoc-plugin.version}


attach-javadocs

jar




${project.build.sourceEncoding}
${project.build.sourceEncoding}
none

org.apache.maven.plugins
maven-source-plugin
${maven-source-plugin.version}


attach-sources

jar


pl.project13.maven
git-commit-id-plugin
${git-commit-id-plugin.version}



revision




true
${project.build.outputDirectory}/git.properties

^git.build.*$
^git.commit.id.abbrev$
^git.branch$
^git.tags$

false

org.codehaus.mojo
versions-maven-plugin
${versions-maven-plugin.version}

false

com.spotify
dockerfile-maven-plugin
${dockerfile-maven-plugin.version}


default

build
push




registry.company.com/spring-boot-maven-git-demo
${project.version}

target/${project.build.finalName}.jar

org.owasp
dependency-check-maven
${dependency-check-maven-plugin.version}



check
verify



7
dependency-check-suppressions.xml
ALL




src/main/resources
true

**/*.properties
**/*.xml



src/main/resources
false

**/*.properties
**/*.xml




src/test/resources
true


dev dev
true
test test prod prod

ci true
true
false




central
Maven Central
https://repo.maven.apache.org/maven2

true


false


central
Maven Central
https://repo.maven.apache.org/maven2

true


false
Git Hooks 脚本集合
pre-commit
#!/bin/bash
# scripts/pre-commit

echo “🔍 Running pre-commit checks…”

# Colors for output
RED=’\033[0;31m’
GREEN=’\033[0;32m’
YELLOW=’\033[1;33m’
NC=’\033[0m’ # No Color

# Function to print status
print_status() {
echo -e “${GREEN}✓${NC} $1”
}

print_error() {
echo -e “${RED}✗${NC} $1”
}

print_warning() {
echo -e “${YELLOW}⚠${NC} $1”
}

# Check if Maven is available
if ! command -v mvn &> /dev/null; then
print_error “Maven is not installed or not in PATH”
exit 1
fi

# 1. Check for trailing whitespace
echo “Checking for trailing whitespace…”
if git diff –cached –name-only | xargs grep -l “[[:space:]]$” 2>/dev/null; then
print_error “Found trailing whitespace. Please fix before committing.”
exit 1
fi
print_status “No trailing whitespace”

# 2. Check for large files
echo “Checking for large files…”
LARGE_FILES=$(git diff –cached –name-only –diff-filter=A | xargs ls -l 2>/dev/null | awk ‘$5 > 10485760 {print $9}’)
if [ -n “$LARGE_FILES” ]; then
print_error “Files larger than 10MB found:”
echo “$LARGE_FILES”
exit 1
fi
print_status “No large files”

# 3. Validate POM if changed
if git diff –cached –name-only | grep -q “pom.xml”; then
echo “Validating POM…”
if ! mvn validate -q; then
print_error “POM validation failed”
exit 1
fi
print_status “POM validation passed”
fi

# 4. Run checkstyle
echo “Running checkstyle…”
if ! mvn checkstyle:check -q; then
print_error “Checkstyle violations found”
echo “Run ‘mvn checkstyle:check’ for details”
exit 1
fi
print_status “Checkstyle passed”

# 5. Run unit tests
echo “Running unit tests…”
if ! mvn test -DskipITs=true -q; then
print_error “Unit tests failed”
echo “Run ‘mvn test’ for details”
exit 1
fi
print_status “Unit tests passed”

# 6. Check commit message format
COMMIT_MSG_FILE=$1
if [ -f “$COMMIT_MSG_FILE” ]; then
COMMIT_MSG=$(cat “$COMMIT_MSG_FILE”)

# Check for WIP commits
if echo “$COMMIT_MSG” | grep -qi “wip\|work in progress”; then
print_warning “WIP commit detected. Are you sure?”
read -p “Continue? (y/N) ” -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
fi

# Validate conventional commit format
if ! echo “$COMMIT_MSG” | grep -qE ‘^(feat|fix|docs|style|refactor|test|chore|perf|build|ci)(\(.+\))?: .{1,50}$’; then
print_warning “Commit message doesn’t follow conventional format”
echo “Recommended format: type(scope): description”
echo “Example: feat(auth): add JWT support”
fi
fi

print_status “All pre-commit checks passed!”
exit 0
post-commit
#!/bin/bash
# scripts/post-commit

# Get commit info
COMMIT_HASH=$(git rev-parse –short HEAD)
COMMIT_MSG=$(cat .git/COMMIT_EDITMSG)

# Check if it’s a release commit
if echo “$COMMIT_MSG” | grep -q “release:”; then
echo “Release commit detected. Updating version…”

# Extract version from commit message
VERSION=$(echo “$COMMIT_MSG” | grep -oE ‘[0-9]+\.[0-9]+\.[0-9]+’)

if [ -n “$VERSION” ]; then
# Update POM version
mvn versions:set -DnewVersion=$VERSION -q

# Add and commit version change
git add pom.xml
git commit –amend –no-edit –no-verify
fi
fi

# Notify about commit
echo “Committed: $COMMIT_HASH – $COMMIT_MSG”
pre-push
#!/bin/bash
# scripts/pre-push

echo “🚀 Running pre-push checks…”

# Run full test suite
echo “Running full test suite…”
if ! mvn clean verify; then
echo “❌ Full test suite failed”
exit 1
fi

# Check code coverage
echo “Checking code coverage…”
if ! mvn jacoco:check; then
echo “❌ Code coverage check failed”
exit 1
fi

# Dependency vulnerability check
echo “Checking for vulnerable dependencies…”
if ! mvn dependency-check:check -q; then
echo “⚠️ Vulnerable dependencies found”
echo “Review dependency-check report”
fi

echo “✅ All pre-push checks passed!”
exit 0
GitHub Actions 完整工作流
name: Complete CI/CD Pipeline

on:
push:
branches: [ main, develop, ‘feature/**’ ]
tags: [ ‘v*.*.*’ ]
pull_request:
branches: [ main, develop ]

env:
MAVEN_OPTS: -Dmaven.repo.local=.m2/repository -Xmx1024m
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}

jobs:
# 1. Code Quality Check
code-quality:
name: Code Quality
runs-on: ubuntu-latest
steps:
– name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0

– name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: ’17’
distribution: ‘temurin’
cache: maven

– name: Cache Maven dependencies
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles(‘**/pom.xml’) }}
restore-keys: |
${{ runner.os }}-maven-

– name: Run Checkstyle
run: mvn checkstyle:check –batch-mode

– name: Run PMD
run: mvn pmd:pmd –batch-mode

– name: Upload PMD Report
uses: actions/upload-artifact@v3
if: failure()
with:
name: pmd-report
path: target/pmd/

# 2. Unit Tests
unit-tests:
name: Unit Tests
runs-on: ubuntu-latest
needs: code-quality
steps:
– name: Checkout code
uses: actions/checkout@v3

– name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: ’17’
distribution: ‘temurin’
cache: maven

– name: Cache Maven dependencies
uses: actions/cache@v3
with:
path: ~/.m2/repository
key: ${{ runner.os }}-maven-${{ hashFiles(‘**/pom.xml’) }}

– name: Run Unit Tests
run: mvn test -DskipITs=true –batch-mode

– name: Generate Test Report
uses: dorny/test-reporter@v1
if: success() || failure()
with:
name: Unit Tests
path: ‘**/target/surefire-reports/*.xml’
reporter: java-junit

– name: Upload Coverage
uses: codecov/codecov-action@v3
with:
files: ./target/site/jacoco/jacoco.xml
flags: unittests
name: codecov-umbrella

# 3. Integration Tests
integration-tests:
name: Integration Tests
runs-on: ubuntu-latest
needs: unit-tests
services:
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: testdb
ports:
– 3306:3306
options: –health-cmd=”mysqladmin ping” –health-interval=10s –health-timeout=5s –health-retries=3

steps:
– name: Checkout code
uses: actions/checkout@v3

– name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: ’17’
distribution: ‘temurin’
cache: maven

– name: Wait for MySQL
run: |
while ! mysqladmin ping -h”127.0.0.1″ -P”3306″ –silent; do
echo “Waiting for MySQL…”
sleep 2
done

– name: Run Integration Tests
env:
SPRING_DATASOURCE_URL: jdbc:mysql://localhost:3306/testdb
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: rootpassword
run: mvn verify -DskipUnitTests=true –batch-mode

– name: Upload Integration Test Report
uses: actions/upload-artifact@v3
if: failure()
with:
name: integration-test-report
path: target/failsafe-reports/

# 4. Dependency Check
security-scan:
name: Security Scan
runs-on: ubuntu-latest
needs: unit-tests
steps:
– name: Checkout code
uses: actions/checkout@v3

– name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: ’17’
distribution: ‘temurin’
cache: maven

– name: Run OWASP Dependency Check
run: mvn dependency-check:check –batch-mode

– name: Upload Dependency Check Report
uses: actions/upload-artifact@v3
if: failure()
with:
name: dependency-check-report
path: target/dependency-check-report.html

# 5. Build and Package
build:
name: Build and Package
runs-on: ubuntu-latest
needs: [integration-tests, security-scan]
if: github.event_name != ‘pull_request’
outputs:
version: ${{ steps.version.outputs.version }}
commit: ${{ steps.version.outputs.commit }}

steps:
– name: Checkout code
uses: actions/checkout@v3
with:
fetch-depth: 0

– name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: ’17’
distribution: ‘temurin’
cache: maven

– name: Generate Version
id: version
run: |
GIT_TAG=$(git describe –tags –abbrev=0 2>/dev/null || echo “0.0.0”)
GIT_COMMIT=$(git rev-parse –short HEAD)
GIT_BRANCH=$(git rev-parse –abbrev-ref HEAD)

if [ “${{ github.ref }}” == “refs/heads/main” ]; then
VERSION=”${GIT_TAG#v}”
elif [ “${{ github.ref }}” == “refs/heads/develop” ]; then
VERSION=”1.0.0-SNAPSHOT”
else
VERSION=”${GIT_TAG#v}-${GIT_BRANCH}-${GIT_COMMIT}”
fi

echo “version=$VERSION” >> $GITHUB_OUTPUT
echo “commit=$GIT_COMMIT” >> $GITHUB_OUTPUT
echo “Building version: $VERSION”

– name: Build JAR
run: mvn clean package -DskipTests –batch-mode

– name: Upload JAR Artifact
uses: actions/upload-artifact@v3
with:
name: app-jar
path: target/*.jar

– name: Generate SBOM
uses: anchore/sbom-action@v0
with:
image: ${{ env.IMAGE_NAME }}:${{ steps.version.outputs.version }}
format: spdx-json
output-file: sbom.spdx.json

– name: Upload SBOM
uses: actions/upload-artifact@v3
with:
name: sbom
path: sbom.spdx.json

# 6. Build and Push Docker Image
docker-build:
name: Docker Build & Push
runs-on: ubuntu-latest
needs: build
if: github.event_name != ‘pull_request’
outputs:
image_tag: ${{ steps.meta.outputs.tags }}

steps:
– name: Checkout code
uses: actions/checkout@v3

– name: Download JAR
uses: actions/download-artifact@v3
with:
name: app-jar
path: target/

– name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

– name: Log in to Container Registry
uses: docker/login-action@v2
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

– name: Extract metadata
id: meta
uses: docker/metadata-action@v4
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=ref,event=pr
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix=sha-
type=raw,value=latest,enable={{is_default_branch}}

– name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
platforms: linux/amd64,linux/arm64

# 7. Deploy to Staging
deploy-staging:
name: Deploy to Staging
runs-on: ubuntu-latest
needs: docker-build
if: github.ref == ‘refs/heads/develop’
environment: staging

steps:
– name: Checkout code
uses: actions/checkout@v3

– name: Deploy to Kubernetes
uses: azure/k8s-deploy@v4
with:
namespace: staging
manifests: |
k8s/staging/deployment.yaml
k8s/staging/service.yaml
k8s/staging/ingress.yaml
images: |
${{ needs.docker-build.outputs.image_tag }}
strategy: rolling

– name: Verify Deployment
run: |
kubectl rollout status deployment/spring-boot-maven-git-demo -n staging –timeout=300s

– name: Run Smoke Tests
run: |
sleep 30
curl -f http://staging-app.company.com/actuator/health
curl -f http://staging-app.company.com/actuator/info

– name: Notify Slack
uses: 8398a7/action-slack@v3
with:
status: success
text: “✅ Staging deployment successful! ${{ needs.docker-build.outputs.image_tag }}”
webhook_url: ${{ secrets.SLACK_WEBHOOK }}

# 8. Deploy to Production
deploy-production:
name: Deploy to Production
runs-on: ubuntu-latest
needs: docker-build
if: startsWith(github.ref, ‘refs/tags/v’)
environment: production

steps:
– name: Checkout code
uses: actions/checkout@v3

– name: Create GitHub Release
uses: actions/create-release@v1
with:
tag_name: ${{ github.ref_name }}
release_name: Release ${{ github.ref_name }}
body: |
## Changes
${{ github.event.head_commit.message }}

## Docker Image
`${{ needs.docker-build.outputs.image_tag }}`

## Build Info
– Commit: ${{ github.sha }}
– Actor: ${{ github.actor }}
draft: false
prerelease: false

– name: Deploy to Kubernetes
uses: azure/k8s-deploy@v4
with:
namespace: production
manifests: |
k8s/production/deployment.yaml
k8s/production/service.yaml
k8s/production/ingress.yaml
images: |
${{ needs.docker-build.outputs.image_tag }}
strategy: rolling

– name: Verify Production Deployment
run: |
kubectl rollout status deployment/spring-boot-maven-git-demo -n production –timeout=600s

– name: Production Smoke Tests
run: |
sleep 30
curl -f https://app.company.com/actuator/health
curl -f https://app.company.com/actuator/info

– name: Notify Production Deploy
uses: 8398a7/action-slack@v3
with:
status: success
text: “🚀 Production deployment successful! ${{ github.ref_name }}”
webhook_url: ${{ secrets.SLACK_WEBHOOK }}

# 9. Cleanup
cleanup:
name: Cleanup
runs-on: ubuntu-latest
needs: [deploy-staging, deploy-production]
if: always()

steps:
– name: Clean up Docker images
run: |
docker system prune -af
总结
通过本文的详细指南,您已经掌握了 Maven 与 Git 完美整合的全流程。从基础配置到高级实践,从本地开发到 CI/CD 自动化,这套方案可以帮助团队建立高效、可靠的开发流程。
关键要点回顾
标准化项目结构
:使用统一的 Maven 项目结构和 Git 工作流
自动化版本管理
:Git 标签与 Maven 版本同步
质量保障
:代码检查、测试覆盖率、安全扫描
CI/CD 自动化
:从代码提交到生产部署的全流程自动化
监控与追踪
:构建信息与运行时监控的关联
持续改进
定期审查和优化构建性能
监控依赖更新和安全漏洞
根据团队反馈调整工作流程
保持文档和示例的更新
这套整合方案将显著提升您的开发效率和软件质量,为团队带来长期价值。