ACK One workflow clusters run hosted Argo Workflows with built-in elasticity and auto scaling. This topic shows you how to set up a Continuous Integration (CI) pipeline that clones a Go repository, runs tests, builds a container image, and pushes it to a registry — with two layers of persistent caching to keep each run fast.
How it works
The pipeline uses a predefined ClusterWorkflowTemplate named ci-go-v1. Each run executes three steps as a directed acyclic graph (DAG):
-
Git clone and checkout — clones the repository, checks out the target branch, and writes the short commit ID to a shared file.
-
Go test — runs
go test -v ./...against the cloned source. The Go module cache is stored in the/pkg/moddirectory on a NAS file system. Modules downloaded in one run are reused in the next, sogo testandgo buildskip re-downloading dependencies. -
Build and push image — uses
buildctl-daemonless.sh(BuildKit) to build the image and push it to Container Registry Enterprise Edition (ACR EE). BuildKit caches image layers in the registry under the:buildcachetag. Unchanged layers are not rebuilt on subsequent runs.
Both caches persist across pipeline runs: the Go module cache on NAS is shared across all tasks within a single run, and the BuildKit layer cache lives in the registry between runs.
Prerequisites
Before you begin, ensure that you have:
-
A workflow cluster. See Create a workflow cluster.
-
kubectl connected to the workflow cluster using its kubeconfig file. See Connect to a cluster using kubectl.
-
The Alibaba Cloud Argo CLI installed. See Install the Argo CLI.
-
RAM user authorization completed. See Authorize a RAM user.
-
A File Storage NAS file system created. See Create a NAS file system.
-
An ACR EE instance created. See Create an ACR EE instance.
Step 1: Create registry credentials in the workflow cluster
BuildKit pulls and pushes images using a Secret named docker-config. Create it in the namespace where you plan to submit pipelines.
The Secret and the NAS volume (created in Step 2) must belong to the same namespace as the pipeline you submit.
-
Configure access credentials for your ACR EE instance. See Configure access credentials.
-
Run the following command to create the Secret. Replace
$repositoryDomain,$username, and$passwordwith your ACR EE domain and credentials.kubectl create secret generic docker-config \ --from-literal="config.json={\"auths\": {\"$repositoryDomain\": {\"auth\": \"$(echo -n $username:$password|base64)\"}}}"
Step 2: Mount a NAS volume to the workflow cluster
The NAS volume serves two purposes:
-
Data sharing between tasks: the cloned repository and commit ID file are written here by the git-checkout-pr task and read by downstream tasks.
-
Go module cache persistence: the cache in
/pkg/modis reused across pipeline runs. The first run downloads modules; subsequent runs skip that step.
NAS uses ReadWriteMany access mode so all pipeline tasks can read and write the volume concurrently.
-
Get the mount target address of your NAS file system. See Manage mount targets.
-
Apply the following manifest to create a persistent volume (PV) and persistent volume claim (PVC) in the workflow cluster. Replace
<your nas filesystem mount point address>with your actual mount target address. For more information, see Use NAS volumes.apiVersion: v1 kind: PersistentVolume metadata: name: pv-nas labels: alicloud-pvname: pv-nas spec: capacity: storage: 100Gi accessModes: - ReadWriteMany # Required: all pipeline tasks read and write this volume concurrently csi: driver: nasplugin.csi.alibabacloud.com volumeHandle: pv-nas volumeAttributes: server: <your nas filesystem mount point address> path: "/" mountOptions: - nolock,tcp,noresvport - vers=3 --- kind: PersistentVolumeClaim apiVersion: v1 metadata: name: pvc-nas # The predefined template references this name — do not change it spec: accessModes: - ReadWriteMany resources: requests: storage: 100Gi selector: matchLabels: alicloud-pvname: pv-nas
Step 3: Submit a pipeline
The predefined ci-go-v1 template is available in all workflow clusters. Use the Argo workbench or the Argo CLI to submit a pipeline run.
The examples below use a public Git repository. For a private repository, add a step that clones using stored credentials before the git clone and checkout step.
Submit from the Argo workbench
-
Log on to the ACK One console. In the left-side navigation pane, choose the workflow cluster you created.
-
On the Cluster Information page, click the Basic Information tab. In the Common Operations section, click Workflow Console (Argo).
-
In the Argo workbench, click Cluster Workflow Templates in the left-side navigation pane, then click the template named ci-go-v1.

-
Click + SUBMIT in the upper-right corner. Configure the parameters in the panel that appears (see Template parameters for descriptions), then click + SUBMIT.

-
You can view the status of the pipeline on the Workflows details page.

Submit using the Argo CLI
-
Create a file named
workflow.yamlwith the following content. Update the parameter values to match your environment.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 -
Submit the pipeline:
argo submit workflow.yaml
Template parameters
The ci-go-v1 template accepts the following parameters.
| Parameter | Description | Default | Example |
|---|---|---|---|
repo_url |
URL of the Git repository | — | https://github.com/ivan-cai/echo-server.git |
repo_name |
Repository name (used as the local directory name) | — | echo-server |
target_branch |
Branch to check out | main |
main |
container_image |
Image to build and push. Format: <ACR EE domain>/<namespace>/<repository> |
— | test-registry.cn-hongkong.cr.aliyuncs.com/acs/echo-server |
container_tag |
Base image tag | v1.0.0 |
v1.0.0 |
dockerfile |
Relative path to the Dockerfile from the repository root | ./Dockerfile |
./Dockerfile |
enable_suffix_commitid |
Append the short commit ID to the image tag, producing <container_tag>-<commit_id>. Set to false to use the base tag only. |
true |
true |
enable_test |
Run the Go test step. Set to false to skip testing and go straight to build. |
true |
true |
Predefined template reference
The full template is provided below for customization. Key sections are annotated.
apiVersion: argoproj.io/v1alpha1
kind: ClusterWorkflowTemplate
metadata:
name: ci-go-v1
spec:
entrypoint: main
volumes:
- name: run-test
emptyDir: {} # Temporary volume scoped to the run-test task
- name: workdir
persistentVolumeClaim:
claimName: pvc-nas # NAS volume: shared across all tasks, persists Go module cache
- name: docker-config
secret:
secretName: docker-config # Registry credentials created in Step 1
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" # Skipped when enable_test=false
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 # Point Go to the NAS-backed module cache
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 # e.g. v1.0.0-abc1234
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}} \
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 \ # Save layer cache to registry
--import-cache type=registry,ref={{workflow.parameters.container_image}}:buildcache # Reuse layer cache from previous runs
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
What's next
-
Customize
ci-go-v1— copy the template and modify steps (for example, add a lint step or change the Go version) to create your ownClusterWorkflowTemplate. -
Trigger pipelines automatically — integrate
argo submitwith your Git platform's webhook to run the pipeline on every push or pull request.