All Products
Search
Document Center

Container Service for Kubernetes:Build a Golang CI pipeline on a workflow cluster

Last Updated:May 12, 2026

A workflow cluster provides fully managed Argo Workflows built on the open-source Argo Workflows project. It is highly elastic, scales automatically, and requires no operations or maintenance, letting you build simpler, cost-effective, and efficient CI pipelines. This topic describes how to build a CI pipeline for a Golang project using a workflow cluster.

Solution overview

When building a CI pipeline with a workflow cluster, you mainly use BuildKit to build and push container images and BuildKit Cache to accelerate image builds. Storing the Go mod cache on NAS accelerates the go test and go build commands, significantly speeding up the overall CI pipeline.

image

Preset workflow template

A workflow cluster includes a preset CI workflow template (ClusterWorkflowTemplate) named ci-go-v1. This template uses BuildKit Cache and stores the Go mod cache on NAS to significantly accelerate the CI pipeline.

You can use the preset template directly or customize it to create your own CI workflow template.

The preset CI workflow template includes the following steps:

  1. Git clone & checkout

    • Clones a Git repository and checks out the target branch.

    • Retrieves the commit ID and appends it as a suffix to the image tag during the build.

  2. Run go test

    • Runs all test cases in the Git repository (Go project) by default.

    • You can use the workflow parameter enable_test to control whether to run this step.

    • The Go mod cache is stored in the /pkg/mod directory on NAS to accelerate both the go test command and the subsequent go build command.

  3. Build & push image

    • Uses BuildKit to build and push the container image, and uses a registry-type cache from BuildKit Cache to accelerate image builds.

    • By default, the image tag uses the {container_tag}-{commit_id} format. You can control whether to append the commit ID using a parameter when you submit the workflow.

    • When the new image is pushed, an image with the latest tag is also pushed, overwriting the existing one.

Full content of the preset CI workflow template

apiVersion: argoproj.io/v1alpha1
kind: ClusterWorkflowTemplate
metadata:
  name: ci-go-v1
spec:
  entrypoint: main
  volumes:
  - name: run-test
    emptyDir: {}
  - name: workdir
    persistentVolumeClaim:
      claimName: pvc-nas
  - name: docker-config
    secret:
      secretName: docker-config
  arguments:
    parameters:
    - name: repo_url
      value: ""
    - name: repo_name
      value: ""
    - name: target_branch
      value: "main"
    - name: container_image
      value: ""
    - name: container_tag
      value: "v1.0.0"
    - name: dockerfile
      value: "./Dockerfile"
    - name: enable_suffix_commitid
      value: "true"
    - name: enable_test
      value: "true"
  templates:
    - name: main
      dag:
        tasks:
          - name: git-checkout-pr
            inline:
              container:
                image: alpine:latest
                command:
                  - sh
                  - -c
                  - |
                    set -eu
                    
                    apk --update add git
          
                    cd /workdir
                    echo "Start to Clone " {{workflow.parameters.repo_url}}
                    git -C "{{workflow.parameters.repo_name}}" pull || git clone {{workflow.parameters.repo_url}} 
                    cd {{workflow.parameters.repo_name}}
          
                    echo "Start to Checkout target branch" {{workflow.parameters.target_branch}}
                    git checkout --track origin/{{workflow.parameters.target_branch}} || git checkout {{workflow.parameters.target_branch}}
                    git pull
                    
                    echo "Get commit id" 
                    git rev-parse --short origin/{{workflow.parameters.target_branch}} > /workdir/{{workflow.parameters.repo_name}}-commitid.txt
                    commitId=$(cat /workdir/{{workflow.parameters.repo_name}}-commitid.txt)
                    echo "Commit id is got: "$commitId
                                        
                    echo "Git Clone and Checkout Complete."
                volumeMounts:
                - name: "workdir"
                  mountPath: /workdir
                resources:
                  requests:
                    memory: 1Gi
                    cpu: 1
              activeDeadlineSeconds: 1200
          - name: run-test
            when: "{{workflow.parameters.enable_test}} == true"
            inline: 
              container:
                image: golang:1.22-alpine
                command:
                  - sh
                  - -c
                  - |
                    set -eu
                    
                    if [ ! -d "/workdir/pkg/mod" ]; then
                      mkdir -p /workdir/pkg/mod
                      echo "GOMODCACHE Directory /pkg/mod is created"
                    fi
                    
                    export GOMODCACHE=/workdir/pkg/mod
                    
                    cp -R /workdir/{{workflow.parameters.repo_name}} /test/{{workflow.parameters.repo_name}} 
                    echo "Start Go Test..."
                    
                    cd /test/{{workflow.parameters.repo_name}}
                    go test -v ./...
                    
                    echo "Go Test Complete."
                volumeMounts:
                - name: "workdir"
                  mountPath: /workdir
                - name: run-test
                  mountPath: /test
                resources:
                  requests:
                    memory: 4Gi
                    cpu: 2
              activeDeadlineSeconds: 1200
            depends: git-checkout-pr    
          - name: build-push-image
            inline: 
              container:
                image: moby/buildkit:v0.13.0-rootless
                command:
                  - sh
                  - -c
                  - |         
                    set -eu
                     
                    tag={{workflow.parameters.container_tag}}
                    if [ {{workflow.parameters.enable_suffix_commitid}} == "true" ]
                    then
                      commitId=$(cat /workdir/{{workflow.parameters.repo_name}}-commitid.txt)
                      tag={{workflow.parameters.container_tag}}-$commitId
                    fi
                    
                    echo "Image Tag is: "$tag
                    echo "Start to Build And Push Container Image"
                    
                    cd /workdir/{{workflow.parameters.repo_name}}
                    
                    buildctl-daemonless.sh build \
                    --frontend \
                    dockerfile.v0 \
                    --local \
                    context=. \
                    --local \
                    dockerfile=. \
                    --opt filename={{workflow.parameters.dockerfile}} \
                    --opt build-arg:GOPROXY=http://goproxy.cn,direct \
                    --output \
                    type=image,\"name={{workflow.parameters.container_image}}:${tag},{{workflow.parameters.container_image}}:latest\",push=true,registry.insecure=true \
                    --export-cache mode=max,type=registry,ref={{workflow.parameters.container_image}}:buildcache \
                    --import-cache type=registry,ref={{workflow.parameters.container_image}}:buildcache
                    
                    echo "Build And Push Container Image {{workflow.parameters.container_image}}:${tag} and {{workflow.parameters.container_image}}:latest Complete."
                env:
                  - name: BUILDKITD_FLAGS
                    value: --oci-worker-no-process-sandbox
                  - name: DOCKER_CONFIG
                    value: /.docker
                volumeMounts:
                  - name: workdir
                    mountPath: /workdir
                  - name: docker-config
                    mountPath: /.docker
                securityContext:
                  seccompProfile:
                    type: Unconfined
                  runAsUser: 1000
                  runAsGroup: 1000
                resources:
                  requests:
                    memory: 4Gi
                    cpu: 2
              activeDeadlineSeconds: 1200
            depends: run-test

The following table describes the parameters configured in the template.

Parameter

Description

Example

entrypoint

Defines the entrypoint template.

main

repo_url

The URL of the Git repository.

https://github.com/ivan-cai/echo-server.git

repo_name

The name of the repository.

echo-server

target_branch

The target branch of the repository.

Default value: main.

main

container_image

The image to build. Use the following format:

<ACR EE domain>/<ACR EE namespace>/<repository name>.

test-registry.cn-hongkong.cr.aliyuncs.com/acs/echo-server

container_tag

The tag of the image to build.

Default value: v1.0.0.

v1.0.0

dockerfile

The path to the Dockerfile, relative to the project's root directory.

Default value: ./Dockerfile.

./Dockerfile

enable_suffix_commitid

Specifies whether to append the commit ID to the image tag.

  • true: Appends the commit ID.

  • false: Does not append the commit ID.

The default value is true.

true

enable_test

Specifies whether to run the Go Test step.

  • true: Runs the step.

  • false: Does not run the step.

The default value is true.

true

Prerequisites

Step 1: Create a Container Registry access credential

  1. Obtain the kubeconfig file for the cluster and use kubectl to connect to the cluster.

  2. Configure the access credential for the Container Registry Enterprise Edition instance. If you use a VPC domain name for access, ensure that the cluster and the Container Registry repository are in the same VPC. If you use a public domain name, configure public access control.

  3. Replace USER_NAME:PASSWORD in the following command with your Container Registry Enterprise Edition instance's access credential. Then, run the command to create a Secret in the workflow cluster for BuildKit to use.

    The Secret and the mounted NAS volume must be in the same namespace as the workflow you submit.
    kubectl create secret generic docker-config --from-literal="config.json={\"auths\": {\"$repositoryDomain\": {\"auth\": \"$(echo -n USER_NAME:PASSWORD|base64)\"}}}"

Step 2: Mount a NAS volume

Use a NAS volume to share data between workflow tasks, such as cloned repository information, and to store the Go mod cache, accelerating the go test and go build commands.

  1. Log on to the NAS console.

  2. In the left-side navigation pane, choose File System > File System List.

  3. In the upper-left corner of the page, select the resource group and region where the target file system resides.

    image

  4. On the File System List page, find the target file system and click Manage in the Actions column.

  5. On the file system details page, click the Mount Targets tab. In the Mount Target section, view and record the NAS mount point.

  6. Save the following sample code as pv-nas.yaml. Replace MOUNT_POINT with your NAS mount point. Then, run the command kubectl apply -f pv-nas.yaml to create the volume.

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: pv-nas
      labels:
        alicloud-pvname: pv-nas
    spec:
      capacity:
        storage: 100Gi
      accessModes:
        - ReadWriteMany
      csi:
        driver: nasplugin.csi.alibabacloud.com
        volumeHandle: pv-nas   # Must be the same as the PV name.
        volumeAttributes:
          server: MOUNT_POINT
          path: "/"
      mountOptions:
      - nolock,tcp,noresvport
      - vers=3
    ---
    kind: PersistentVolumeClaim
    apiVersion: v1
    metadata:
      name: pvc-nas
    spec:
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: 100Gi
      selector:
        matchLabels:
          alicloud-pvname: pv-nas

Step 3: Start a workflow

Console

  1. Log on to the Argo Workflow Clusters console.

  2. On the Cluster Information page, click the Basic Information tab. In the Common Operations section, click Workflow Console (Argo).

  3. In the left-side navigation pane of the Argo UI, click Cluster Workflow Templates, and then click the name of the preset template, ci-go-v1.

    image

  4. In the upper-left corner of the template details page, click + SUBMIT. In the panel that appears, enter the required parameters, and then click + SUBMIT at the bottom of the panel.

    For information about the parameters, see the parameter description. Set the parameters to your specific values.

    image

    After submission, you can view the workflow status on the Workflows page:

    image

Argo CLI

  1. Install the Argo CLI.

  2. Update the parameter values to match your configuration, based on the parameter description. Save the following sample code as workflow.yaml. Then, run the command argo submit workflow.yaml to submit the workflow.

    apiVersion: argoproj.io/v1alpha1
    kind: Workflow
    metadata:
      generateName: ci-go-v1-
      labels:
        workflows.argoproj.io/workflow-template: ackone-ci
    spec:
      arguments:
        parameters:
        - name: repo_url
          value: https://github.com/ivan-cai/echo-server.git
        - name: repo_name
          value: echo-server
        - name: target_branch
          value: main
        - name: container_image
          value: "test-registry.cn-hongkong.cr.aliyuncs.com/acs/echo-server"
        - name: container_tag
          value: "v1.0.0"
        - name: dockerfile
          value: ./Dockerfile
        - name: enable_suffix_commitid
          value: "true"
        - name: enable_test
          value: "true"
      workflowTemplateRef:
        name: ci-go-v1
        clusterScope: true