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 CLI (glab) CI/CD Pipeline

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

Overview

GitLab CLI (glab) is an open-source GitLab command-line tool bringing GitLab to your terminal. This pipeline demonstrates cross-platform builds and comprehensive testing.

Pipeline Characteristics

  • Project ID: 34675721
  • Lines of Code: ~289 lines
  • Language: Go
  • Features Demonstrated:
    • Cross-platform builds (Linux, macOS, Windows)
    • Multi-architecture support (amd64, arm64, 386)
    • Binary artifact creation
    • Integration testing
    • Release automation

Key Features

Cross-Platform Build Matrix
// Demonstrates building for multiple OS/architecture combinations
// Linux, macOS, Windows on multiple architectures
Artifact Management

Shows proper artifact handling for CLI binaries across platforms.

Integration Testing

Comprehensive testing including unit tests and integration tests across different platforms.

Release Pipeline

Automated release process with binary distribution for multiple platforms.

What You Can Learn

  1. Cross-platform builds - Building Go binaries for multiple operating systems
  2. CLI testing - Testing command-line applications
  3. Release automation - Automating binary releases
  4. Multi-architecture support - Supporting different CPU architectures

Source

  • Original Project: gitlab-org/cli
  • Import Date: 2026-01-10
  • Branch: main

Building This Example

# View the pipeline code
cat pipeline.go

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

Documentation

Index

Constants

This section is empty.

Variables

View Source
var BuildTest = pipeline.Job{
	Name:  "build_test",
	Stage: "build",
	Rules: List(
		pipeline.Rule{
			If: "$CI_MERGE_REQUEST_EVENT_TYPE == \"merge_train\"",
		},
		pipeline.Rule{
			If: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH",
		},
		pipeline.Rule{
			If:   "$CI_COMMIT_TAG",
			When: "never",
		},
		pipeline.Rule{
			Changes: List(".goreleaser.yml", ".gitlab-ci.yml"),
		},
	),
	Needs: []any{WindowsInstaller, SignWindowsInstaller},
	Artifacts: pipeline.Artifacts{
		Paths:    List("dist/"),
		ExpireIn: "7 days",
		Name:     "goreleaser-artifacts",
	},
}
View Source
var BuildWindows = pipeline.Job{
	Name:   "build_windows",
	Stage:  "build",
	Script: List("GOOS=windows GOARCH=amd64 make build", "mv bin/glab bin/glab.exe"),
	Rules: List(
		pipeline.Rule{
			If: "$CI_COMMIT_TAG",
		},
		pipeline.Rule{
			If: "$CI_MERGE_REQUEST_EVENT_TYPE == \"merge_train\"",
		},
		pipeline.Rule{
			If: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH",
		},
		pipeline.Rule{
			Changes: List(".goreleaser.yml", ".gitlab-ci.yml"),
		},
	),
	Needs: []any{PrepareGoCache},
	Artifacts: pipeline.Artifacts{
		Paths:    List("bin/glab.exe"),
		ExpireIn: "7 days",
	},
}
View Source
var CheckDocsMarkdown = pipeline.Job{
	Name:   "check_docs_markdown",
	Script: List("vale --minAlertLevel error docs", "markdownlint-cli2 'docs/**/*.md' *.md", "lychee --offline --include-fragments docs/**/*.md *.md"),
	Image:  pipeline.Image{Name: "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"},
}
View Source
var CheckDocsUpdate = pipeline.Job{
	Name:   "check_docs_update",
	Script: List("git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME && git checkout $CI_MERGE_REQUEST_TARGET_BRANCH_NAME && git checkout $CI_COMMIT_SHA", "make gen-docs", "git status\nif [[ $(git add -A --dry-run) ]]; then\n  echo '✖ ERROR: Documentation changes detected!';\n  git diff --color --ws-error-highlight=all\n  echo '✖ These changes require a documentation update. To regenerate the docs, read https://gitlab.com/gitlab-org/cli/-/tree/main/docs#generating-the-docs.';\n  exit 1;\nelse\n  echo '✔ No documentation updates detected.';\n  exit 0;\nfi"),
}
View Source
var CheckGoGeneratedCode = pipeline.Job{
	Name:   "check_go_generated_code",
	Script: List("chmod 600 internal/config/config.yaml.lock", "make generate", "echo \"Checking git status\"\n[ -z \"$(git status --short)\" ] || {\n  echo \"Error: Files should have been generated:\";\n  git status --short; echo \"Diff:\";\n  git --no-pager diff HEAD;\n  echo \"Run \\\"make generate\\\" and try again\";\n  exit 1;\n}\n"),
	Needs:  []any{PrepareGoCache},
}
View Source
var DocsHugoBuild = pipeline.Job{
	Name:         "docs hugo_build",
	Script:       List("rm -f ../docs/index.rst ../docs/*.md", "hugo --gc --printPathWarnings --panicOnWarning  --environment test", "make check-index-pages SEARCH_DIR=\"../docs/source\""),
	BeforeScript: List("if [[ $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ [0-9]+-[0-9]+-stable ]]; then\n  BRANCH_NAME=$CI_MERGE_REQUEST_TARGET_BRANCH_NAME\n  echo \"Detected merge request to stable branch: $BRANCH_NAME\"\n# Check if we're directly on a stable branch (direct push/commit)\nelif [[ $CI_COMMIT_BRANCH =~ [0-9]+-[0-9]+-stable ]]; then\n  BRANCH_NAME=$CI_COMMIT_BRANCH\n  echo \"Detected direct commit to stable branch: $BRANCH_NAME\"\nfi\n\n# Extract version info if we found a stable branch\nif [[ -n $BRANCH_NAME ]]; then\n  MAJOR=$(echo $BRANCH_NAME | cut -d '-' -f 1)\n  MINOR=$(echo $BRANCH_NAME | cut -d '-' -f 2)\n  # Convert GitLab style (17-9-stable-ee) to Docs style (17.9)\n  DOCS_BRANCH_CANDIDATE=\"$MAJOR.$MINOR\"\n\n  # Check if the branch exists in the Docs website repo, fallback to main if not\n  if git ls-remote --heads --exit-code https://gitlab.com/gitlab-org/technical-writing/docs-gitlab-com.git \"refs/heads/$DOCS_BRANCH_CANDIDATE\" >/dev/null 2>&1; then\n    DOCS_BRANCH=\"$DOCS_BRANCH_CANDIDATE\"\n    echo \"Using docs-gitlab-com branch $DOCS_BRANCH for release branch\"\n  else\n    DOCS_BRANCH=\"main\"\n    echo \"Branch $DOCS_BRANCH_CANDIDATE does not exist, falling back to main\"\n  fi\nfi\n", "git clone --depth 1 --filter=tree:0 --branch $DOCS_BRANCH https://gitlab.com/gitlab-org/technical-writing/docs-gitlab-com.git", "cd docs-gitlab-com", "make add-latest-icons"),
	Image:        pipeline.Image{Name: "registry.gitlab.com/gitlab-org/technical-writing/docs-gitlab-com/docs-gitlab-com-builder:hugo-0.150.1"},
	Variables: Json{
		"DOCS_BRANCH": "main",
	},
}
View Source
var HomebrewRelease = pipeline.Job{
	Name:   "homebrew-release",
	Stage:  "release",
	Script: List("touch ~/.gitconfig", "git config --global user.email \"$GITHUB_EMAIL\"", "git config --global user.name \"$GITHUB_NAME\"", "brew bump-formula-pr glab --no-browse --tag=\"$CI_COMMIT_TAG\" --revision=\"$CI_COMMIT_SHA\""),
	Image:  pipeline.Image{Name: "${GITLAB_DEPENDENCY_PROXY}homebrew/brew:4.6.20"},
	Rules: List(
		pipeline.Rule{
			If: "$CI_COMMIT_TAG",
		},
	),
	Needs: []any{Release},
}
View Source
var Lint = pipeline.Job{
	Name:   "lint",
	Script: List("golangci-lint run --output.text.path=stdout --output.text.colors=false --output.text.print-issued-lines=false --output.code-climate.path=gl-code-quality-report.json"),
	Image:  pipeline.Image{Name: "${GITLAB_DEPENDENCY_PROXY}golangci/golangci-lint:v$GOLANGCI_LINT_VERSION"},
	Needs:  []any{PrepareGoCache},
	Artifacts: pipeline.Artifacts{
		Paths:    List("gl-code-quality-report.json"),
		ExpireIn: "7 days",
	},
}
View Source
var LintCommit = pipeline.Job{
	Name:   "lint_commit",
	Stage:  "test",
	Script: List("apt-get update && apt-get install -y git", "git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME $CI_COMMIT_SHA", "cd scripts/commit-lint && npm ci", "./lint.sh"),
	Image:  pipeline.Image{Name: "${GITLAB_DEPENDENCY_PROXY}node:24-slim"},
	Rules: List(
		pipeline.Rule{
			If:   "$CI_MERGE_REQUEST_IID && $CI_PROJECT_VISIBILITY == \"public\"",
			When: "always",
		},
	),
}
View Source
var MainPipeline = pipeline.Pipeline{
	Stages: List(".pre", "documentation", "test", "build", "release"),
	Variables: Json{
		"GITLAB_ADVANCED_SAST_ENABLED": "true",
		"GO_VERSION":                   "1.25.4",
		"GOLANGCI_LINT_VERSION":        "2.7.2",
	},
}
View Source
var PrepareGoCache = pipeline.Job{
	Name:   "prepare_go_cache",
	Stage:  ".pre",
	Script: List("go mod download"),
	Variables: Json{
		"GOPATH": "$CI_PROJECT_DIR/.go",
	},
	Cache: pipeline.Cache{
		Key: pipeline.CacheKey{
			Files: List("go.sum"),
		},
		Paths:  List("$CI_PROJECT_DIR/.go/pkg/mod/"),
		Policy: "pull-push",
	},
}
View Source
var Release = pipeline.Job{
	Name: "release",
	Rules: List(
		pipeline.Rule{
			If: "$CI_COMMIT_TAG",
		},
	),
}
View Source
var SecretDetection = pipeline.Job{
	Name: "secret_detection",
}
View Source
var SignWindowsGlab = pipeline.Job{
	Name:   "sign_windows_glab",
	Stage:  "build",
	Script: List("sign-windows-binaries --output-dir signed bin/glab.exe"),
	Needs:  []any{BuildWindows},
	Artifacts: pipeline.Artifacts{
		Paths: List("signed/glab.exe"),
	},
}
View Source
var SignWindowsInstaller = pipeline.Job{
	Name:   "sign_windows_installer",
	Stage:  "build",
	Script: List("sign-windows-binaries --output-dir signed bin/glab_*Windows_x86_64_installer.exe"),
	Needs:  []any{WindowsInstaller},
	Artifacts: pipeline.Artifacts{
		Paths: List("signed/glab_*Windows_x86_64_installer.exe"),
	},
}
View Source
var SnapcraftBuildEdge = pipeline.Job{
	Name:  "snapcraft_build_edge",
	Stage: "build",
	Rules: List(
		pipeline.Rule{
			If: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != \"merge_request_event\"",
		},
		pipeline.Rule{
			If: "$CI_MERGE_REQUEST_EVENT_TYPE == \"merge_train\"",
		},
		pipeline.Rule{
			Changes: List("snap/snapcraft.yaml", ".gitlab-ci.yml"),
		},
	),
}
View Source
var SnapcraftBuildStable = pipeline.Job{
	Name:  "snapcraft_build_stable",
	Stage: "build",
	Rules: List(
		pipeline.Rule{
			If: "$CI_COMMIT_TAG",
		},
	),
}
View Source
var SnapcraftReleaseEdge = pipeline.Job{
	Name:   "snapcraft_release_edge",
	Stage:  "release",
	Script: List("export SNAPCRAFT_STORE_CREDENTIALS=$(cat $SNAPCRAFT_CREDENTIALS_FILE)", "snapcraft whoami", "snapcraft upload *.snap --release=latest/edge", "snapcraft logout"),
	Image: pipeline.Image{
		Name:       "ghcr.io/canonical/snapcraft:8_core24",
		Entrypoint: List(""),
	},
	Rules: List(
		pipeline.Rule{
			If: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH",
		},
	),
	Needs: []any{SnapcraftBuildEdge},
}
View Source
var SnapcraftReleaseStable = pipeline.Job{
	Name:   "snapcraft_release_stable",
	Stage:  "release",
	Script: List("export SNAPCRAFT_STORE_CREDENTIALS=$(cat $SNAPCRAFT_CREDENTIALS_FILE)", "snapcraft whoami", "snapcraft upload *.snap --release=latest/stable", "snapcraft logout"),
	Image: pipeline.Image{
		Name:       "ghcr.io/canonical/snapcraft:8_core24",
		Entrypoint: List(""),
	},
	Rules: List(
		pipeline.Rule{
			If: "$CI_COMMIT_TAG",
		},
	),
	Needs: []any{SnapcraftBuildStable},
}
View Source
var TestsIntegration = pipeline.Job{
	Name:        "tests:integration",
	Script:      List("GITLAB_TOKEN_TEST=$GITLAB_TOKEN_TEST GITLAB_TEST_HOST=$GITLAB_TEST_HOST make integration-test-race"),
	AfterScript: List("echo -e \"\\e[0Ksection_start:`date +%s`:coverage[collapsed=true]\\r\\e[0KRunning coverage report\"", "make coverage", "echo -e \"\\e[0Ksection_end:`date +%s`:coverage\\r\\e[0K\""),
	Variables: Json{
		"CGO_ENABLED": "1",
	},
}
View Source
var TestsUnit = pipeline.Job{
	Name:        "tests:unit",
	Script:      List("make test-race"),
	AfterScript: List("echo -e \"\\e[0Ksection_start:`date +%s`:coverage[collapsed=true]\\r\\e[0KRunning coverage report\"", "make coverage", "echo -e \"\\e[0Ksection_end:`date +%s`:coverage\\r\\e[0K\""),
	Variables: Json{
		"CGO_ENABLED": "1",
	},
	Needs: []any{PrepareGoCache},
	Artifacts: pipeline.Artifacts{
		ExpireIn: "7 days",
		When:     "always",
	},
}
View Source
var WindowsInstaller = pipeline.Job{
	Name:   "windows_installer",
	Stage:  "build",
	Script: List("mv scripts/setup_windows.iss .", "iscc \"setup_windows.iss\" -DVersion=${CI_COMMIT_TAG//v}"),
	Image: pipeline.Image{
		Name:       "${GITLAB_DEPENDENCY_PROXY}amake/innosetup",
		Entrypoint: List(""),
	},
	Rules: List(
		pipeline.Rule{
			If: "$CI_COMMIT_TAG",
		},
		pipeline.Rule{
			If: "$CI_MERGE_REQUEST_EVENT_TYPE == \"merge_train\"",
		},
		pipeline.Rule{
			If: "$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH",
		},
		pipeline.Rule{
			Changes: List(".goreleaser.yml", ".gitlab-ci.yml"),
		},
	),
	Needs: []any{BuildWindows, SignWindowsGlab},
	Artifacts: pipeline.Artifacts{
		Paths:    List("bin/*"),
		ExpireIn: "7 days",
	},
}

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