Featured image of post Continuous Integration for Go Projects with CODING

Continuous Integration for Go Projects with CODING

CODING offers excellent services with infrastructure that meets personal usage needs.

Start

  • Developed using https://github.com/gogf/gf. Modified its default Dockerfile (original requires host machine compilation for dependency caching; modified to perform all operations within the image).
###############################################################################  
#          Use first-stage image for building  
###############################################################################  
FROM golang as builder  

ENV GO111MODULE=on \  
    GOPROXY=https://goproxy.cn,direct  

WORKDIR /app  
COPY . .  

RUN go mod tidy  
# Modified for CGO dependency: CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -ldflags '-extldflags "-static"' -o main main.go  
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o main main.go  


###############################################################################  
#          Runtime image: Copy built files from builder  
###############################################################################  
# FROM scratch  
FROM alpine  

# Use domestic alpine mirror  
RUN echo http://mirrors.aliyun.com/alpine/v3.8/main/ > /etc/apk/repositories  
# Set timezone to UTC+8  
RUN apk update && apk add tzdata ca-certificates bash  
RUN rm -rf /etc/localtime && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime  
RUN echo "Asia/Shanghai" > /etc/timezone  

ENV WORKDIR /var/www  

COPY --from=builder /app/main $WORKDIR/main  
COPY --from=builder /app/i18n     $WORKDIR/i18n  
COPY --from=builder /app/public   $WORKDIR/public  
COPY --from=builder /app/config   $WORKDIR/config  
COPY --from=builder /app/template $WORKDIR/template  
COPY --from=builder /app/.env     $WORKDIR/.env  

EXPOSE 9999  

WORKDIR $WORKDIR  
CMD ["./main"]  
  • When creating a new build plan in CODING, select the CODING Docker Image Push template.
  • Basic pipeline example:
pipeline {  
  agent any  
  stages {  
    stage('Checkout') {  
      steps {  
        checkout([$class: 'GitSCM',  
        branches: [[name: GIT_BUILD_REF]],  
        userRemoteConfigs: [[  
          url: GIT_REPO_URL,  
          credentialsId: CREDENTIALS_ID  
        ]]])  
      }  
    }  
    stage('Set Environment Variables') {  
      steps {  
        writeFile(file: '.env', text: 'DATABASE_DSN=mysql:root:12345678@tcp(127.0.0.1:3306)/test2')  
      }  
    }  
    stage('Build & Push Image') {  
      steps {  
        sh "docker build -t ${CODING_DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_VERSION} -f ${DOCKERFILE_PATH} ${DOCKER_BUILD_CONTEXT}"  
        useCustomStepPlugin(key: 'codingcorp:artifact_docker_push', version: 'latest', params: [image:"${CODING_DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_VERSION}",repo:"${DOCKER_REPO_NAME}"])  
      }  
    }  
    stage('Deploy to Remote') {  
      steps {  
        script {  
          def remoteConfig = [:]  
          remoteConfig.name = "my-remote-server"  
          remoteConfig.host = "${REMOTE_HOST}"  
          remoteConfig.port = "${REMOTE_SSH_PORT}".toInteger()  
          remoteConfig.allowAnyHosts = true  

          withCredentials([  
            sshUserPrivateKey(  
              credentialsId: "${REMOTE_CRED}",  
              keyFileVariable: "privateKeyFilePath"  
            ),  
            usernamePassword(  
              credentialsId: "${CODING_ARTIFACTS_CREDENTIALS_ID}",  
              usernameVariable: 'CODING_DOCKER_REG_USERNAME',  
              passwordVariable: 'CODING_DOCKER_REG_PASSWORD'  
            )  
          ]) {  
            remoteConfig.user = "${REMOTE_USER_NAME}"  
            remoteConfig.identityFile = privateKeyFilePath  

            sshCommand(  
              remote: remoteConfig,  
              command: "docker login -u ${CODING_DOCKER_REG_USERNAME} -p ${CODING_DOCKER_REG_PASSWORD} ${CODING_DOCKER_REG_HOST}",  
              sudo: true,  
            )  

            DOCKER_IMAGE_URL = sh(  
              script: "echo ${CODING_DOCKER_REG_HOST}/${CODING_DOCKER_IMAGE_NAME}:${DOCKER_IMAGE_VERSION}",  
              returnStdout: true  
            )  

            sshCommand(  
              remote: remoteConfig,  
              command: "docker pull ${DOCKER_IMAGE_URL}",  
              sudo: true,  
            )  
            
            sshCommand(  
              remote: remoteConfig,  
              command: "docker rm -f golang-coding | true",  
              sudo: true,  
            )  

            sshCommand(  
              remote: remoteConfig,  
              command: "docker run --cpus=0.5 --memory=100m -d -p 8199:8199 --name golang-coding --restart=always ${DOCKER_IMAGE_URL}",  
              sudo: true,  
            )  

            sshCommand(  
              remote: remoteConfig,  
              command: "docker image prune -a -f",  
              sudo: true,  
            )  

            sshCommand(  
              remote: remoteConfig,  
              command: "curl -X POST -d \"title=`echo \$(curl -I 127.0.0.1:8199/ping)`&desp=Deploy success\" https://sctapi.ftqq.com/xxxx.send",  
              sudo: true,  
            )  

            echo "Deployed successfully. Preview at http://${REMOTE_HOST}:8199"  
          }  
        }  
      }  
    }  
  }  
  environment {  
    CODING_DOCKER_REG_HOST = "${CCI_CURRENT_TEAM}-docker.pkg.${CCI_CURRENT_DOMAIN}"  
    CODING_DOCKER_IMAGE_NAME = "${PROJECT_NAME.toLowerCase()}/${DOCKER_REPO_NAME}/${DOCKER_IMAGE_NAME}"  
  }  
}  

Project Repository

Reference implementation:
https://github.com/seth-shi/golang-coding