基于Github Action 配置Java Python Go. Rust Nodejs C++ 实现自动发布功能(不基于Jenkins的快速敏捷发布体系)
- 需求:基于Github Action 配置Java Python Go. Rust Nodejs C++ 实现自动发布功能。
- 目标:基于Github+Argocd实现不基于Jenkins的快速敏捷发布体系,覆盖服务为:容器+非容器服务。
- 实现思路:容器基于github action cicd后把最新镜像版本更新到Kustomize代码仓库,非容器的基于github action 调用ansible 进行服务的分发。
- Java(以此为举例重点,其他语言可以参考做适配即可)
-
Java-Dockerfile1 # set Amazon Corretto 17 as base image 2 FROM amazoncorretto:17-al2023-jdk 3 # set working directory 4 WORKDIR /data 5 # set environment variables 6 ARG JAR_FILE=target/pb-trading-monitor-*.jar 7 # copy jar file to the container 8 COPY ${JAR_FILE} api/pb-trading-monitor.jar 9 # set environment variables 10 ENV SERVICE_NAME=pb-trading-monitor 11 12 RUN mkdir -p /data/logs 13 14 ENTRYPOINT [ \ 15 "/bin/bash", \ 16 "-c", \ 17 "java \ 18 --enable-preview \ 19 -Xms${JAVA_OPT_XMS} \ 20 -Xmx${JAVA_OPT_XMX} \ 21 -XX:+UseG1GC \ 22 -XX:MaxGCPauseMillis=100 \ 23 -Dfile.encoding=UTF-8 \ 24 -Dspring.profiles.active=${JAVA_OPT_ENV} \ 25 -Dlogging.file.path=/data/logs \ 26 -jar /data/api/pb-trading-monitor.jar" ]
.github/workflows/nonpro-cicd.yaml1 name: nonprod-cicd 2 3 on: 4 push: 5 branches: 6 - dev 7 - sit 8 - uat 9 - qa 10 - fat 11 12 jobs: 13 maven_build: 14 uses: Tech/devops-cicd/.github/workflows/javaci.yaml@main 15 with: 16 K8S: true 17 secrets: 18 SRE_LTP_TOKEN: ${{ secrets.SRE_TOKEN }} 19 deploy: 20 needs: maven_build 21 uses: Tech/devops-cicd/.github/workflows/javacd.yaml@main 22 with: 23 K8S: true 24 secrets: 25 ACCESS_TOKEN: ${{ secrets.ACCESS_TOKEN }}
-
javaci.yaml1 name: Reusable Build Template 2 3 env: 4 PROJECT_NAME: ${{ github.repository }} 5 COMMIT_ID: ${{ github.sha }} 6 BASE_DIR: /data/mnt 7 ref: ${{ github.ref_name }} 8 on: 9 workflow_call: # 允许被其他工作流调用 10 inputs: 11 JAR: 12 required: false 13 type: string 14 K8S: 15 required: false 16 type: boolean 17 default: false 18 REPO_NAME: 19 required: false 20 type: string 21 secrets: 22 SRE_LTP_TOKEN: 23 description: "Token for SRE" 24 required: true 25 26 jobs: 27 git_checkout: 28 name: Git_checkout 29 runs-on: [ self-hosted,ltp ] 30 if: ${{ !contains('qa,fat', github.ref_name) || !contains(fromJSON('["pb-trading-engine", "backend-ltp-config-project", "ltp-exchange-data-server", "pb-trading-dump", "pb-trading-engine","pb-trading-market","pb-trading-monitor","pb-trading-push","pb-trading-query","pb-trading-statistics","pb-trading-transfer","rapidtrade-data-push","rapidx-clearing-accounting","rapidx-trading-algo-server","rapidx-trading-clearing","rapidx-trading-onezero-maker","rapidx-trading-query-persistent","rapidx-trading-query-realtime"]'), github.event.repository.name) }} 31 32 steps: 33 - name: Checkout 34 uses: actions/checkout@v3 35 # with: 36 # ref: ${ref} 37 # - name: diff 38 # run: | 39 # git diff remotes/origin/main qa >diff.txt 40 41 - name: Instead of setting.xml's token 42 run: | 43 sed -i "s|SRE_LTP_TOKEN|${{secrets.SRE_TOKEN}}|g" .github/workflows/settings.xml 44 45 - name: Set Dockerfile stage 46 if: ${{ inputs.k8s == true }} 47 #后续调整为deployment内的env控制 48 run: | 49 if [[ "${{ github.ref_name }}" == "release" ]]; then 50 ref="prod" 51 elif [[ "${{ github.ref_name }}" == Uat* ]]; then 52 ref="uat" 53 elif [[ "${{ github.ref_name }}" == Prod* ]]; then 54 ref="prod" 55 elif [[ "${{ github.ref_name }}" == "feat/release_uat" ]]; then 56 ref="uat" 57 elif [[ "${{ github.ref_name }}" == "feat/shard_release_uat" ]]; then 58 ref="uat" 59 elif [[ "${{ github.ref_name }}" == *"qa"* ]]; then 60 ref="qa" 61 elif [[ "${{ github.ref_name }}" == *"sit"* ]]; then 62 ref="sit" 63 elif [[ "${{ github.ref_name }}" == *"dev"* ]]; then 64 ref="dev" 65 66 fi 67 sed -i "s/stage/${ref}/g" Dockerfile 68 69 - name: Build with Maven 70 run: mvn -B -U clean package -s .github/workflows/settings.xml 71 72 # - name: Build and Save to NFS 73 # if: ${{ inputs.k8s == false }} 74 # run: | 75 # echo $BASE_DIR/$PROJECT_NAME/$COMMIT_ID 76 # mkdir -p $BASE_DIR/$PROJECT_NAME/$COMMIT_ID 77 78 # echo "Artifact copied to $BASE_DIR/$PROJECT_NAME/$COMMIT_ID" 79 - name: Build and Save to NFS 80 run: | 81 git fetch origin release 82 git diff origin/release HEAD > diff.txt 83 # rm -rf $BASE_DIR/$PROJECT_NAME/$COMMIT_ID/ 84 mkdir -p $BASE_DIR/$PROJECT_NAME/$COMMIT_ID 85 cp -rf target/${{ inputs.REPO_NAME }}*.jar $BASE_DIR/$PROJECT_NAME/$COMMIT_ID/ || true 86 cp -rf .* $BASE_DIR/$PROJECT_NAME/$COMMIT_ID/ || true 87 88 89 - name: Configure AWS credentials 90 if: ${{ inputs.k8s == true }} 91 uses: aws-actions/configure-aws-credentials@v1 92 with: 93 aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 94 aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 95 aws-region: ap-northeast-1 96 - name: Login to Amazon ECR 97 if: ${{ inputs.k8s == true }} 98 id: login-ecr 99 uses: aws-actions/amazon-ecr-login@v1 100 - name: Build, tag, and push image to Amazon ECR 101 if: ${{ inputs.k8s == true }} 102 env: 103 ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} 104 # ECR_REPOSITORY: ${REPO_NAME} 105 IMAGE_TAG: ${{ github.sha }} 106 run: | 107 ECR_REPOSITORY=$(echo ${{ github.repository }}|cut -d'/' -f2) 108 aws ecr create-repository --repository-name ${ECR_REPOSITORY} > /dev/null 2>&1 || echo "仓库已存在,继续执行构建镜像操作" 109 docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . 110 docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG 111 - name: custom script 112 if: github.ref_name == 'fat' || github.ref_name == 'qa' 113 run: | 114 app_name=$(echo ${{ github.repository }}|cut -d'/' -f2) 115 env="${{ github.ref_name }}" 116 curl -s "http://10.18.2.11/cov/cicd?app_name=$app_name&env=${env}" > /dev/null 2>&1 & 117
javacd.yaml1 name: Reusable Build Template 2 3 env: 4 ref: ${{ github.ref_name }} 5 SRC_DIR: /data/mnt/${{ github.repository }}/${{ github.sha }}/ 6 # DIR: /data/jar/${{ github.repository }}/${{ github.sha }} 7 on: 8 workflow_call: # 允许被其他工作流调用 9 inputs: 10 IP: 11 required: false 12 type: string 13 JAR: 14 required: false 15 type: string 16 DIRECTORY: 17 required: false 18 type: string 19 default: "/data/www" 20 SCRIPT: 21 required: false 22 type: string 23 default: "start.sh" 24 K8S: 25 required: false 26 type: boolean 27 default: false 28 REPO_NAME: 29 required: false 30 type: string 31 JVM_OPTIONS: 32 required: false 33 type: string 34 default: "-Xmx2G -Xms2G -XX:+UseG1GC -XX:+UseStringDeduplication" 35 secrets: 36 ACCESS_TOKEN: 37 required: false 38 description: "Access token for Kustomize repository" 39 jobs: 40 deploy: 41 runs-on: [ self-hosted,ltp] 42 #if: (!contains('qa,fat', github.ref_name) && !contains(fromJSON('["pb-trading-engine", "backend-ltp-config-project", "ltp-exchange-data-server", "pb-trading-dump", "pb-trading-engine","pb-trading-market","pb-trading-monitor","pb-trading-push","pb-trading-query","pb-trading-statistics","pb-trading-transfer","rapidtrade-data-push","rapidx-clearing-accounting","rapidx-trading-algo-server","rapidx-trading-clearing","rapidx-trading-onezero-maker","rapidx-trading-query-persistent","rapidx-trading-query-realtime"]'), github.event.repository.name)) 43 steps: 44 - name: Copy artifact to server 45 if: ${{ inputs.k8s == false }} 46 env: 47 JVM_OPTIONS: ${{ inputs.JVM_OPTIONS }} 48 run: | 49 repo_name=$(echo ${{ github.repository }}|cut -d'/' -f2) 50 echo $repo_name 51 # 替换生产环境的env 52 if [[ "${{ github.ref_name }}" == "release" ]]; then 53 ref="prod" 54 elif [[ "${{ github.ref_name }}" == Uat* ]]; then 55 ref="uat" 56 elif [[ "${{ github.ref_name }}" == UAT* ]]; then 57 ref="uat" 58 elif [[ "${{ github.ref_name }}" == ProdJP* ]]; then 59 ref="prod" 60 elif [[ "${{ github.ref_name }}" == Prod* ]]; then 61 ref="prod" 62 elif [[ "${{ github.ref_name }}" == Mirror1* ]]; then 63 ref="mirror1" 64 elif [[ "${{ github.ref_name }}" == Mirror2* ]]; then 65 ref="mirror2" 66 elif [[ "${{ github.ref_name }}" == Mirror3* ]]; then 67 ref="mirror3" 68 elif [[ "${{ github.ref_name }}" == "feat/release_uat" ]]; then 69 ref="uat" 70 elif [[ "${{ github.ref_name }}" == "feat/shard_release_uat" ]]; then 71 ref="uat" 72 elif [[ "${{ github.ref_name }}" == *"qa"* ]]; then 73 ref="qa" 74 elif [[ "${{ github.ref_name }}" == *"sit"* ]]; then 75 ref="sit" 76 elif [[ "${{ github.ref_name }}" == *"dev"* ]]; then 77 ref="dev" 78 79 80 fi 81 82 cd /etc/ansible && ~/ansible-playbook -i inventory/$ref deploy.yml \ 83 --extra-vars "host=${repo_name} SRC_DIR=${{ env.SRC_DIR }} directory=/data/jar/${repo_name}/${{ github.sha }} script=${{ inputs.SCRIPT }} commit_id=${{ github.sha }} start_script=/data/scripts/${repo_name}.sh jvm_args='${JVM_OPTIONS}'" 84 85 - name: Checkout kustomize repo 86 if: ${{ inputs.K8S == true }} 87 uses: actions/checkout@v3 88 with: 89 repository: Tech/Kustomize 90 ref: main 91 token: ${{ secrets.ACCESS_TOKEN }} 92 - name: modify kustomize file 93 if: ${{ inputs.k8s == true }} 94 run: | 95 # REPO_NAME=$(echo ${{ github.repository }}|cut -d'/' -f2) 96 if [[ "${{ github.ref_name }}" == Uat* ]]; then 97 ref="uat" 98 elif [[ "${{ github.ref_name }}" == ProdJP* ]]; then 99 ref="prodjp" 100 elif [[ "${{ github.ref_name }}" == Prod* ]]; then 101 ref="prod" 102 elif [[ "${{ github.ref_name }}" == Mirror1* ]]; then 103 ref="mirror1" 104 elif [[ "${{ github.ref_name }}" == Mirror2* ]]; then 105 ref="mirror2" 106 elif [[ "${{ github.ref_name }}" == Mirror3* ]]; then 107 ref="mirror3" 108 elif [[ "${{ github.ref_name }}" == "feat/release_uat" ]]; then 109 ref="uat" 110 elif [[ "${{ github.ref_name }}" == "feat/shard_release_uat" ]]; then 111 ref="uat" 112 elif [[ "${{ github.ref_name }}" == *"qa"* ]]; then 113 ref="qa" 114 elif [[ "${{ github.ref_name }}" == *"sit"* ]]; then 115 ref="sit" 116 elif [[ "${{ github.ref_name }}" == *"dev"* ]]; then 117 ref="dev" 118 elif [[ "${{ github.ref_name }}" == "release" ]]; then 119 ref="prod" 120 121 fi 122 echo "Using ref: $ref" 123 if ${{ inputs.REPO_NAME != '' }} ; then 124 REPO_NAME=${{ inputs.REPO_NAME }} 125 echo $REPO_NAME 126 sed -i "s/\(newTag:\ \).*/\1\"${{ github.sha }}\"/g" backend/${REPO_NAME}/overlays/${ref}/kustomization.yaml 127 else 128 REPO_NAME=$(echo ${{ github.repository }}|cut -d'/' -f2) 129 fi 130 131 sed -i "s/\(newTag:\ \).*/\1\"${{ github.sha }}\"/g" backend/${REPO_NAME}/overlays/${ref}/kustomization.yaml 132 if [[ "$REPO_NAME" == "pb-trading-dump" && ( "$ref" == "dev" || "$ref" == "sit" ) ]] ; then 133 sed -i "s/\(newTag:\ \).*/\1\"${{ github.sha }}\"/g" backend/${REPO_NAME}/overlays/${ref}*/kustomization.yaml 134 fi 135 git config --global --add safe.directory /__w/${REPO_NAME}/${REPO_NAME} 136 git config --global user.name "${{ github.event.head_commit.author.name }}" 137 git config --global user.email ${{ github.event.head_commit.author.email }} 138 # 仅在检测到更改时提交和推送 139 git add . 140 if git diff --quiet && git diff --cached --quiet; then 141 echo "✅ 没有检测到文件更改,跳过提交步骤" 142 else 143 echo "✅ 检测到文件更改,准备提交......" 144 git commit -m "${{ github.event.head_commit.message }}" 145 git push 146 fi 147 wiz_scan: 148 name: wiz_scan 149 runs-on: [ self-hosted,ltp ] 150 if: startsWith(github.ref, 'refs/tags/Prod') 151 steps: 152 - name: wiz_scan 153 env: 154 APIIRO_API_KEY: ${{ secrets.APIIRO_API_KEY }} 155 APIIRO_API_URL: "https://app.test.com" 156 run: | 157 echo ${{ github.server_url }}/${{ github.repository }} ${{ github.ref_name }} 158 cd /data/security-scan/ 159 git pull 160 python3 securityscan.py sast --repositoryurl ${{ github.server_url }}/${{ github.repository }} --commitsha ${{ github.sha }} --branch release || true 161 # python3 securityscan.py sast --repositoryurl ${{ github.server_url }}/${{ github.repository }}.git --commitsha ${{ github.sha }} --branch ${{ github.ref_name }} --debug &
deploy.yaml1 - name: Validate host group and deploy 2 hosts: localhost 3 gather_facts: false 4 vars: 5 valid_host_groups: "{{ groups.keys() | list }}" 6 tasks: 7 - name: Check if 'host' is defined 8 fail: 9 msg: | 10 ❌ 错误: 必须提供 host 参数,联系运维人员添加,使用方式: 11 -e "host=your_group" 12 when: host is not defined 13 14 - name: Check if host group exists 15 fail: 16 msg: | 17 ❌ 错误: 主机组 '{{ host }}' 不存在!,联系运维人员添加 18 19 请检查 inventory 文件: /etc/ansible/inventory/dev 20 when: host not in valid_host_groups 21 22 - name: Check if host group has enough members 23 fail: 24 msg: | 25 ❌ 错误: 主机组 '{{ host }}' 的成员不足(至少1个),联系运维人员添加 26 当前主机组 '{{ host }}' 包含 {{ groups[host] | length }} 个主机 27 when: groups[host] | length < 1 28 29 30 - import_playbook: javacd.yml
以上通过在代码仓库定义Dockerfile+nonpro-cicd.yaml 进行自动触发到javaci.yaml进行编译后,再通过javacd.yaml进行镜像或者jar包的分发实现2种部署方式共存。仅供参考,请勿照搬。
- Python
-
Python-Dockerfile1 # 使用官方 Python 3.10 镜像作为基础镜像 2 FROM python:3.10-slim 3 4 # 设置工作目录 5 WORKDIR /app 6 7 # 设置环境变量 8 ENV PYTHONUNBUFFERED=1 \ 9 PYTHONDONTWRITEBYTECODE=1 10 11 # 安装系统依赖 12 RUN apt-get update && \ 13 apt-get install -y --no-install-recommends \ 14 gcc \ 15 && rm -rf /var/lib/apt/lists/* 16 17 # 复制依赖文件 18 COPY requirements.txt . 19 20 # 安装 Python 依赖 21 RUN pip install --no-cache-dir -r requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple 22 23 # 复制项目文件 24 COPY . . 25 26 # 创建日志目录 27 RUN mkdir -p /app/logs 28 29 # 设置启动命令 30 CMD ["python", "run_all.py"]
- Go
-
Go-dockerfile# 第一阶段:编译Go程序(builder) FROM golang:1.25 AS builder WORKDIR /src # 复制依赖文件并下载 COPY ./go.mod ./go.sum ./ RUN go mod download # 复制源代码 COPY ./ . RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -trimpath -ldflags="-s -w" -o /out/app . FROM alpine:3.20 RUN apk add --no-cache ca-certificates tzdata \ && adduser -D -H -u 10001 appuser WORKDIR / COPY --from=builder /out/app /app COPY --from=builder /src/config.json /config.json RUN chown appuser:appuser /config.json && chmod 644 /config.json USER appuser EXPOSE 8080 # Default config path expected by the app is /opt/xidp/conf/config.yml ENTRYPOINT ["/app","-env","pro"]
- Rust
-
Rust-Dockerfile1 # 使用指定版本的 bookworm 基础镜像 2 FROM rust:1.88.0-bookworm AS chef 3 RUN cargo install cargo-chef 4 5 FROM chef AS planner 6 WORKDIR /app 7 COPY . . 8 RUN cargo chef prepare --recipe-path recipe.json 9 10 FROM chef AS builder 11 WORKDIR /app 12 13 # 安装系统依赖 14 RUN apt-get update && apt-get install -y \ 15 pkg-config \ 16 libssl-dev \ 17 libsasl2-dev \ 18 ca-certificates \ 19 && rm -rf /var/lib/apt/lists/* 20 21 # 构建依赖 22 COPY --from=planner /app/recipe.json recipe.json 23 RUN cargo chef cook --release --recipe-path recipe.json 24 25 # 构建应用 26 COPY . . 27 RUN cargo build --release --bin rust_risk_manager 28 29 # 运行时镜像 - 使用相同的 bookworm 版本 30 FROM debian:bookworm-slim 31 WORKDIR /app 32 33 # 安装运行时依赖 34 RUN apt-get update && apt-get install -y \ 35 libssl3 \ 36 libsasl2-2 \ 37 ca-certificates \ 38 curl \ 39 && rm -rf /var/lib/apt/lists/* 40 41 # 复制二进制文件和配置文件 42 COPY --from=builder /app/target/release/rust_risk_manager /app/rust_risk_manager 43 COPY config/ ./config/ 44 45 # 创建必要的目录 46 RUN mkdir -p logs 47 48 # 暴露端口(根据您的应用需要调整) 49 EXPOSE 8080 50 51 # 设置环境变量 52 ENV RUST_LOG=info 53 ENV RUST_BACKTRACE=1 54 55 # 设置容器启动时运行的命令 56 CMD ["./rust_risk_manager"]
- C++
-
C++-Dockerfile1 # 运行阶段 - 使用轻量级基础镜像 2 FROM ubuntu:22.04 3 4 # 安装运行时依赖 5 RUN apt-get update && apt-get install -y \ 6 libssl3 \ 7 ca-certificates \ 8 && rm -rf /var/lib/apt/lists/* 9 10 # 创建应用用户 11 RUN useradd -r -s /bin/false appuser 12 13 # 设置工作目录 14 WORKDIR /data/app/ 15 16 # 从构建上下文复制可执行文件 17 COPY . . 18 19 # 确保可执行文件有执行权限 20 RUN chmod +x * 21 22 # 切换到非特权用户 23 USER appuser 24 25 #RUN cp yml/stage/rapidtrade_order.yml . 26 27 # 设置启动命令,其中stage通过ci脚本去动态替换为不同环境的变量 28 CMD ["nohup", "./rapidtrade_order", "rapidtrade_order.yml"]
- NodeJs
-
Node-Dockerfile1 FROM node:20-alpine AS base 2 WORKDIR /app 3 4 FROM base AS deps 5 COPY package.json yarn.lock ./ 6 RUN yarn install --frozen-lockfile 7 8 FROM base AS builder 9 COPY --from=deps /app/node_modules ./node_modules 10 COPY . . 11 ENV NEXT_TELEMETRY_DISABLED=1 12 RUN yarn build 13 14 FROM base AS runner 15 ENV NODE_ENV=production 16 ENV NEXT_TELEMETRY_DISABLED=1 17 18 # 运行时也可以覆盖 APP_ENV 19 ARG APP_ENV=qa 20 ENV APP_ENV=${APP_ENV} 21 22 WORKDIR /app 23 24 # 仅安装生产依赖,减小体积 25 COPY package.json yarn.lock ./ 26 RUN yarn install --frozen-lockfile --production 27 28 # 拷贝运行所需产物 29 COPY --from=builder /app/public ./public 30 COPY --from=builder /app/.next .//.next 31 COPY --from=builder /app/next.config.mjs ./next.config.mjs 32 33 COPY --from=builder /app/config ./config 34 35 # 非 root 运行 36 RUN addgroup -g 1001 -S nodejs && adduser -S nextjs -u 1001 37 RUN mkdir -p /app/.next/cache/fetch-cache && \ 38 chown -R nextjs:nodejs /app/.next 39 USER nextjs 40 41 CMD ["yarn", "start"]
http://www.cnblogs.com/Jame-mei
浙公网安备 33010602011771号