All Products
Search
Document Center

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

Last Updated:Aug 31, 2026

Workflow clusters are a fully managed Argo Workflows service built on the open-source Argo Workflows project, offering elastic scaling and zero O&M overhead for simpler, lower-cost, high-efficiency CI pipelines. This topic describes how to build a Golang CI pipeline on a workflow cluster using BuildKit caching and NAS-stored Go module cache.workflow cluster with BuildKit caching and NAS-stored Go module cache.

Solution overview

On a workflow cluster, the pipeline uses BuildKit to build and push container images, BuildKit Cache to accelerate builds, and NAS-stored Go mod cache to speed up go test and go build.

image

Preset workflow template

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

Use the preset template directly or customize it for your CI workflow.

The preset template includes these steps:

  1. Git clone & checkout

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

    • Retrieves the commit ID and appends it to the image tag.

  2. Run go test

    • Runs all test cases in the Go project by default.

    • Use enable_test to control whether to run this step.

    • Stores the Go mod cache in /pkg/mod on NAS to accelerate go test and go build.

  3. Build & push image

    • Builds and pushes the container image with BuildKit, using a registry-type cache to accelerate builds.

    • Default image tag format: {container_tag}-{commit_id}. A workflow parameter controls whether to append the commit ID.

    • Also pushes a latest-tagged image, overwriting the previous 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 template parameters.

Parameter

Description

Example

entrypoint

The entrypoint template.

main

repo_url

Git repository URL.

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

repo_name

Repository name.

echo-server

target_branch

Target branch.

Default: main.

main

container_image

Image to build. Format:

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

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

container_tag

Image tag.

Default: v1.0.0.

v1.0.0

dockerfile

Dockerfile path relative to the project root.

Default: ./Dockerfile.

./Dockerfile

enable_suffix_commitid

Whether to append the commit ID to the image tag.

  • true: Appends the commit ID.

  • false: Does not append the commit ID.

Default: true.

true

enable_test

Whether to run the Go Test step.

  • true: Runs the step.

  • false: Does not run the step.

Default: 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 ACR EE instance. For Virtual Private Cloud (VPC) domain access, ensure the cluster and the registry are in the same VPC. For public domain access, configure public access control.

  3. Replace USER_NAME:PASSWORD with your ACR EE access credential and run the command to create a Secret in the workflow cluster for BuildKit.

    The Secret and 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

A NAS volume shares data between workflow tasks, such as cloned repository data, and stores the Go mod cache to accelerate go test and go build.

  1. Log on to the NAS console.

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

  3. In the top navigation bar, select the resource group and region where your file system resides.

  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, record the NAS mount point.

  6. Save the following YAML as pv-nas.yaml, replace MOUNT_POINT with your NAS mount point, and run 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, then click ci-go-v1.

  4. On the template details page, click + SUBMIT. Enter the required parameters in the panel and click + SUBMIT.

    Set parameters based on the parameter description.

    In the Submit Workflow panel, set Entrypoint to main and specify the following parameters:

    • repo_url: the URL of the Git repository, for example https://github.com/ivan-cai/echo-server.git.

    • repo_name: the repository name, for example echo-server.

    • target_branch: the target branch, for example main.

    • container_image: the URL of the container image.

    • container_tag: the image tag, for example v1.0.0.

    • dockerfile: the path to the Dockerfile, for example ./Dockerfile.

    • enable_suffix_commitid: whether to append the commit ID to the image tag, for example true.

    • enable_test: whether to run the test step, for example true.

    After you specify the parameters, click +SUBMIT at the bottom of the panel to submit the workflow.

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

    After the workflow is submitted, the workflow DAG is displayed on the Workflows details page. The step nodes from top to bottom are git-checkout-pr, run-test, and build-push-image. A green checkmark on every node indicates that the workflow succeeded.

Argo CLI

  1. Install the Argo CLI.

  2. Update parameter values based on the parameter description. Save the following YAML as workflow.yaml, then run 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