ci

package
v1.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 21, 2026 License: MIT Imports: 2 Imported by: 0

README

GitLab Shell CI/CD Pipeline

This is the GitLab Shell project's CI/CD pipeline, imported from gitlab-org/gitlab-shell.

Overview

GitLab Shell handles SSH access for GitLab. Its pipeline demonstrates Go testing with security scanning and release automation.

Pipeline Characteristics

  • Project ID: 3828396
  • Lines of Code: ~353 lines
  • Language: Go
  • Features Demonstrated:
    • Go testing with race detection
    • Code coverage reporting
    • Security scanning (SAST, Secret Detection, Dependency Scanning)
    • Automated release creation
    • Multi-version Go testing
    • Static code analysis

Key Features

Race Detection Testing

Tests are run with Go's race detector to catch concurrency issues.

Security Scanning

Comprehensive security scanning including:

  • SAST (Static Application Security Testing)
  • Secret Detection
  • Dependency Scanning
Release Automation

Automated creation of releases when tags are pushed.

Code Quality
  • Test coverage reporting
  • Static analysis
  • Vulnerability scanning

What You Can Learn

  1. Go testing best practices - Race detection and coverage
  2. Security scanning - Full security scanning integration
  3. Release automation - Automated release workflows
  4. Multi-version testing - Testing across Go versions

Source

Building This Example

This example is imported as a single file:

# View the pipeline code
cat pipeline.go

# To create a buildable version:
mkdir my-shell-pipeline
cp pipeline.go my-shell-pipeline/
cd my-shell-pipeline
go mod init example/my-shell-pipeline
go mod tidy

Documentation

Index

Constants

This section is empty.

Variables

View Source
var DangerReview = pipeline.Job{
	Name:  "danger-review",
	Stage: "test",
}

DangerReview is a stub for a job included from a template In the original pipeline, this comes from an include directive

View Source
var IssueBot = pipeline.Job{
	Name:  "issue-bot",
	Stage: "report",
	Image: pipeline.Image{Name: "${CI_REGISTRY}/${GITLAB_NAMESPACE}/distribution/issue-bot:latest"},
	Rules: List(
		pipeline.Rule{
			If:   "$PIPELINE_TYPE =~ /DEFAULT_BRANCH_PIPELINE$/",
			When: "on_failure",
		},
		pipeline.Rule{
			If:   "$PIPELINE_TYPE =~ /STABLE_BRANCH_PIPELINE$/",
			When: "on_failure",
		},
		pipeline.Rule{
			If:   "$PIPELINE_TYPE =~ /RELEASE_PIPELINE$/",
			When: "on_failure",
		},
	),
}
View Source
var KnapsackQaReport = pipeline.Job{
	Name:         "knapsack-qa-report",
	Stage:        "report",
	Script:       List("bundle exec rake \"knapsack:upload[$QA_KNAPSACK_REPORT_FILE_PATTERN]\""),
	BeforeScript: List("cd /home/gitlab/qa"),
	Image: pipeline.Image{
		Name:       "registry.gitlab.com/gitlab-org/gitlab/gitlab-ee-qa:master",
		Entrypoint: List(""),
	},
	Variables: Json{
		"GIT_STRATEGY":                    "none",
		"QA_KNAPSACK_REPORT_FILE_PATTERN": "$CI_PROJECT_DIR/gitlab-qa-run-*/gitlab-*-qa-*/knapsack/*/*.json",
	},
	Rules: List(
		pipeline.Rule{
			If: "$PIPELINE_TYPE == \"QA_KNAPSACK_UPDATE_PIPELINE\"",
		},
	),
	AllowFailure: true,
}
View Source
var MainPipeline = pipeline.Pipeline{
	Stages: List("prepare", "test", "preflight", "approve-review-apps", "prepare-review", "review", "staging", "canary", "specs", "qa-manual", "qa", "qa-report", "staging-release", "package", "release-package", "cleanup", "report"),
	Variables: Json{
		"GIT_CLONE_PATH":                 "$CI_BUILDS_DIR/gitlab",
		"PARENT_PIPELINE_ID":             "$CI_PIPELINE_ID",
		"CANONICAL_PROJECT_PATH":         "gitlab-org/charts/gitlab",
		"NAMESPACE":                      "$KUBE_NAMESPACE",
		"CI_TOOLS_VERSION":               "4.22.0",
		"VCLUSTER_VERSION":               "0.30.0",
		"DOCKER_VERSION":                 "28.0.1",
		"RUBY_IMAGE":                     "${DOCKERHUB_PREFIX}/ruby:${RUBY_VERSION}-alpine",
		"AUTO_DEPLOY_TAG_REGEX":          "^[0-9]+\\.[0-9]+\\.[0-9]+\\+[a-z0-9]{7,}$",
		"SECURITY_PROJECT_PATH":          "gitlab-org/security/charts/gitlab",
		"QA_FULL_SUITE_OPTIONS":          "--tag ~smoke --tag ~skip_live_env --tag ~orchestrated --tag ~transient",
		"CI_TOOLS_NAMESPACE":             "gitlab-org",
		"STRICT_VERSIONS":                "true",
		"GITLAB_AUTH_TOKEN":              "$DANGER_GITLAB_API_TOKEN",
		"REVIEW_REF_PREFIX":              "",
		"DOCS_LINT_IMAGE":                "registry.gitlab.com/gitlab-org/technical-writing/docs-gitlab-com/lint-markdown:alpine-3.22-vale-3.13.0-markdownlint2-0.19.0-lychee-0.21.0",
		"STABLE_REPO_URL":                "https://charts.helm.sh/stable",
		"LIMIT_TO":                       "",
		"KUBECTL_VERSION":                "1.33.1",
		"HELM_DEFAULT_SETTINGS":          "certmanager-issuer:\n  email: support@gitlab.com\ngitlab:\n  toolbox:\n    backups:\n      cron:\n        enabled: true\n",
		"BUSYBOX_IMAGE":                  "${DOCKERHUB_PREFIX}/busybox:${BUSYBOX_VERSION}",
		"DOCKER_DIND_IMAGE":              "${DOCKERHUB_PREFIX}/docker:${DOCKER_VERSION}-dind",
		"BUSYBOX_VERSION":                "1.37",
		"HELM_MAX_HISTORY":               20,
		"GITLAB_QA_ADMIN_ACCESS_TOKEN":   "$GITLAB_ADMIN_TOKEN",
		"RUBY_VERSION":                   "3.3.7",
		"REVIEW_APPS_AUTO_STOP_IN":       "2 hours",
		"SAST_EXCLUDED_PATHS":            "/doc,/examples,/spec",
		"ISSUE_BOT_LABELS_EXTRA":         "group::operate,type::maintenance,maintenance::pipelines",
		"DOCKERHUB_PREFIX":               "docker.io",
		"QA_SANITY_SUITE_OPTIONS":        "--tag smoke --tag ~skip_live_env --tag ~orchestrated",
		"GITLAB_QA_VERSION":              "15.5.0",
		"GOOGLE_APPLICATION_CREDENTIALS": "${CI_PROJECT_DIR}/.google_keyfile.json",
		"REVIEW_ARCH":                    "amd64",
		"DEBIAN_VERSION":                 "bookworm-slim",
		"DEV_PROJECT_PATH":               "gitlab/charts/gitlab",
		"KUBE_SCORE_IMAGE":               "${DOCKERHUB_PREFIX}/zegl/kube-score:v1.19.0@sha256:94137f32ce139dc9fbdbbd380249025e4d378c282ff151a100b981cdeeb923b6",
		"KUBE_CRD_SCHEMA_URL":            "https://raw.githubusercontent.com/kubernetes/kubernetes/master/api/openapi-spec/v3/apis__apiextensions.k8s.io__v1_openapi.json",
		"GITLAB_NAMESPACE":               "gitlab-org",
		"HELM_VERSION":                   "3.18.4",
	},
}
View Source
var PinImageVersions = pipeline.Job{
	Name:   "pin_image_versions",
	Stage:  "approve-review-apps",
	Script: List("apt-get update -qq", "apt install -y bats skopeo", "bash ./scripts/ci/add_dependency_repos.sh", "bats --verbose-run ./scripts/ci/pin_image_digests.bats", "bash ./scripts/ci/pin_image_digests.sh"),
	Rules: List(
		pipeline.Rule{
			If:   "$LIMIT_TO != \"\" && $LIMIT_TO != null && $PARENT_PIPELINE_ID != $CI_PIPELINE_ID",
			When: "never",
		},
		pipeline.Rule{
			If: "$PIPELINE_TYPE =~ /DEFAULT_BRANCH_PIPELINE$/",
		},
		pipeline.Rule{
			If: "$PIPELINE_TYPE =~ /MR_PIPELINE$/",
		},
		pipeline.Rule{
			If: "$PIPELINE_TYPE =~ /STABLE_BRANCH_PIPELINE$/",
		},
		pipeline.Rule{
			If: "$PIPELINE_TYPE =~ /FEATURE_BRANCH_PIPELINE$/",
		},
		pipeline.Rule{
			If: "$PIPELINE_TYPE == \"QA_KNAPSACK_UPDATE_PIPELINE\"",
		},
	),
	Artifacts: pipeline.Artifacts{
		Paths: List("ci.digests.yaml", "skopeo_errors.log"),
		When:  "always",
	},
}
View Source
var PublishAudodeployPackage = pipeline.Job{
	Name: "publish_audodeploy_package",
	Variables: Json{
		"CHANNEL": "autodeploy",
	},
	Rules: List(
		pipeline.Rule{
			If: "$PIPELINE_TYPE == \"AUTO_DEPLOY_PIPELINE\"",
		},
	),
}
View Source
var PublishDevelPackage = pipeline.Job{
	Name: "publish_devel_package",
	Variables: Json{
		"VERSION_SUFFIX": "-${CI_PIPELINE_ID}",
		"CHANNEL":        "devel",
	},
	Rules: List(
		pipeline.Rule{
			If:   "$CI_PIPELINE_SOURCE == \"parent_pipeline\"",
			When: "never",
		},
		pipeline.Rule{
			If:   "$CI_PIPELINE_SOURCE == \"trigger\"",
			When: "never",
		},
		pipeline.Rule{
			If: "$PIPELINE_TYPE =~ /DEFAULT_BRANCH_PIPELINE$/",
		},
	),
}
View Source
var PublishTaggedPackage = pipeline.Job{
	Name: "publish_tagged_package",
	Variables: Json{
		"CHANNEL": "stable",
	},
	Rules: List(
		pipeline.Rule{
			If: "$PIPELINE_TYPE == \"RELEASE_PIPELINE\"",
		},
	),
}
View Source
var ReleasePackage = pipeline.Job{
	Name:   "release_package",
	Stage:  "release-package",
	Script: List("if [[ $CI_COMMIT_REF_NAME =~ $AUTO_DEPLOY_TAG_REGEX ]]; then\n  UNSTABLE=\"true\"\nelse\n  UNSTABLE=\"false\"\nfi\n", "bash scripts/wait_for_images.sh", "curl -fS --request POST --form \"token=${COM_CHARTS_TRIGGER_TOKEN}\" --form ref=master --form \"variables[CHART_NAME]=$CI_PROJECT_NAME\" --form \"variables[RELEASE_REF]=$CI_COMMIT_REF_NAME\" --form \"variables[UNSTABLE]=$UNSTABLE\" https://gitlab.com/api/v4/projects/2860651/trigger/pipeline"),
	Image:  pipeline.Image{Name: "${CI_REGISTRY}/${CI_TOOLS_NAMESPACE}/gitlab-omnibus-builder/distribution_ci_tools:${CI_TOOLS_VERSION}"},
	Rules: List(
		pipeline.Rule{
			If:   "$PIPELINE_TYPE == \"RELEASE_PIPELINE\"",
			When: "manual",
		},
	),
	Artifacts: pipeline.Artifacts{
		Paths:    List("./*.json", "skopeo_inspect_error.log"),
		ExpireIn: "7d",
		When:     "always",
	},
	Timeout: "2h",
}
View Source
var TagAutoDeploy = pipeline.Job{
	Name:   "tag_auto_deploy",
	Stage:  "staging-release",
	Script: List("./scripts/tag_auto_deploy.rb"),
	Rules: List(
		pipeline.Rule{
			If: "$PIPELINE_TYPE == \"AUTO_DEPLOY_TRIGGER_PIPELINE\"",
		},
	),
}
View Source
var TriggerEks133 = pipeline.Job{
	Name: "trigger-eks133",
	Variables: Json{
		"LIMIT_TO": "eks133",
	},
	Needs: []any{TriggerReviewSecondary},
}
View Source
var TriggerGke134 = pipeline.Job{
	Name: "trigger-gke134",
	Variables: Json{
		"LIMIT_TO": "gke134",
	},
	Needs: []any{TriggerReviewCurrent},
}
View Source
var TriggerReviewCurrent = pipeline.Job{
	Name:   "trigger_review_current",
	Stage:  "approve-review-apps",
	Script: List("echo \"Testing current platform.\""),
	Image:  pipeline.Image{Name: "${BUSYBOX_IMAGE}"},
	Rules: List(
		pipeline.Rule{
			If:   "$PIPELINE_TYPE =~ /DOCS_PIPELINE/",
			When: "never",
		},
		pipeline.Rule{
			If: "$CI_PIPELINE_SOURCE != \"pipeline\" && $CI_PIPELINE_SOURCE != \"parent_pipeline\" && $PIPELINE_TYPE =~ /DEFAULT_BRANCH_PIPELINE$/ ",
		},
		pipeline.Rule{
			If: "$CI_PIPELINE_SOURCE != \"pipeline\" && $CI_PIPELINE_SOURCE != \"parent_pipeline\" && $PIPELINE_TYPE =~ /STABLE_BRANCH_PIPELINE$/ ",
		},
		pipeline.Rule{
			If:           "$CI_PIPELINE_SOURCE != \"pipeline\" && $CI_PIPELINE_SOURCE != \"parent_pipeline\"",
			When:         "manual",
			AllowFailure: true,
		},
		pipeline.Rule{
			If: "$CI_PIPELINE_SOURCE == \"pipeline\" && $TEST_BRANCH == \"true\"",
		},
	),
	Needs: []any{DangerReview, PinImageVersions},
}
View Source
var TriggerReviewSecondary = pipeline.Job{
	Name:   "trigger_review_secondary",
	Stage:  "approve-review-apps",
	Script: List("echo \"Testing secondary platforms.\""),
	Image:  pipeline.Image{Name: "${BUSYBOX_IMAGE}"},
	Rules: List(
		pipeline.Rule{
			If:   "$PIPELINE_TYPE =~ /DOCS_PIPELINE/",
			When: "never",
		},
		pipeline.Rule{
			If:           "$CI_PIPELINE_SOURCE != \"pipeline\" && $CI_PIPELINE_SOURCE != \"parent_pipeline\"",
			When:         "manual",
			AllowFailure: true,
		},
		pipeline.Rule{
			If:           "$CI_PIPELINE_SOURCE == \"merge_request_event\"",
			When:         "manual",
			AllowFailure: true,
		},
		pipeline.Rule{
			If:           "$CI_PIPELINE_SOURCE == \"pipeline\" && $TEST_BRANCH == \"true\"",
			When:         "manual",
			AllowFailure: true,
		},
	),
	Needs: []any{DangerReview, PinImageVersions},
}
View Source
var TriggerV132 = pipeline.Job{
	Name: "trigger-v132",
	Variables: Json{
		"LIMIT_TO": "v132",
	},
	Needs: []any{TriggerReviewCurrent},
}
View Source
var TriggerV133 = pipeline.Job{
	Name: "trigger-v133",
	Variables: Json{
		"LIMIT_TO": "v133",
	},
	Needs: []any{TriggerReviewSecondary},
}
View Source
var TriggerV134 = pipeline.Job{
	Name: "trigger-v134",
	Variables: Json{
		"LIMIT_TO": "v134",
	},
	Needs: []any{TriggerReviewSecondary},
}
View Source
var TriggerV134EnvoyGw = pipeline.Job{
	Name: "trigger-v134-envoy-gw",
	Variables: Json{
		"LIMIT_TO": "v134gw",
	},
	Needs: []any{TriggerReviewCurrent},
}
View Source
var TriggerV134a = pipeline.Job{
	Name: "trigger-v134a",
	Variables: Json{
		"LIMIT_TO": "v134a",
	},
	Needs: []any{TriggerReviewSecondary},
}
View Source
var UpdateTriggerBranch = pipeline.Job{
	Name:   "update-trigger-branch",
	Stage:  "prepare",
	Script: List("git clone \"https://${GITLAB_TRIGGER_UPDATE_BOT_USERNAME}:${GITLAB_TRIGGER_UPDATE_BOT_PASSWORD}@${TRIGGER_PROJECT}\" update-project", "cd update-project", "git checkout -B ${TRIGGER_BRANCH}", "git reset --hard $CI_DEFAULT_BRANCH", "git push --force-with-lease=${TRIGGER_BRANCH} origin ${TRIGGER_BRANCH} -o ci.skip"),
	Variables: Json{
		"TRIGGER_PROJECT": "gitlab.com/gitlab-org/charts/gitlab.git",
		"TRIGGER_BRANCH":  "master-trigger-branch",
		"GIT_STRATEGY":    "none",
	},
	Rules: List(
		pipeline.Rule{
			If: "$PIPELINE_TYPE == \"CANONICAL_DEFAULT_BRANCH_PIPELINE\"",
		},
		pipeline.Rule{
			If: "$TRIGGER_UPDATE",
		},
	),
	AllowFailure: true,
}
View Source
var WaitForDevImages = pipeline.Job{
	Name:   "wait_for_dev_images",
	Stage:  "prepare",
	Script: List("bash scripts/wait_for_images.sh"),
	Image:  pipeline.Image{Name: "${CI_REGISTRY}/${CI_TOOLS_NAMESPACE}/gitlab-omnibus-builder/distribution_ci_tools:${CI_TOOLS_VERSION}"},
	Variables: Json{
		"CNG_REGISTRY": "dev.gitlab.org:5005/gitlab/charts/components/images",
	},
	Rules: List(
		pipeline.Rule{
			If: "$PIPELINE_TYPE == \"BUILD_STABLE_BRANCH_PIPELINE\"",
		},
	),
	Artifacts: pipeline.Artifacts{
		Paths:    List("./*.json", "skopeo_inspect_error.log"),
		ExpireIn: "7d",
		When:     "always",
	},
	Timeout: "2h",
}

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL