CI/CD Tools Compared: GitHub Actions, GitLab CI and More
Eight CI/CD tools compared by what they actually do: where the build machines run, where your code has to live, and what you maintain yourself. Fit by team size and code host, with no ranking and no prices.
7 min read
Two questions decide most CI/CD tool choices before features come into it: where does your code live, and who runs the machines that build it? If your repositories are on GitHub, GitLab or Bitbucket Cloud, each host has a CI/CD service built in, with hosted machines you never patch. Jenkins is the opposite end: you run the whole server. CircleCI, Buildkite and Azure Pipelines connect to several code hosts, and AWS CodePipeline orchestrates releases inside an AWS account. Below, each of the eight is described from its own documentation as of September 30, 2026, followed by how each fits a team’s size and code host.
This page compares tools. For what a pipeline is and how CI differs from CD, see What is a CI/CD pipeline?; for a first working pipeline on GitHub, step by step, see GitHub Actions for CI/CD.
Hosted, self-hosted, or both
Every CI/CD platform has two halves: a control plane that decides what runs and shows the results, and the machines (runners or agents) that actually run your jobs. Tools differ in which halves they will run for you.
- Hosted runners: the vendor’s machines. GitHub, GitLab and Azure Pipelines all describe fresh virtual machines per job, so nothing leaks between runs and nothing needs patching by you.
- Self-hosted runners or agents: your machines, registered with the vendor’s control plane. You pick them for special hardware, access to a private network, or because build data must stay on your side. GitHub’s page on self-hosted runners (opens in a new tab) puts the trade plainly: “You are responsible for updating the operating system and all other software.”
- Self-hosted control plane: the whole server is yours. Jenkins works only this way; GitLab Self-Managed, Azure DevOps Server, CircleCI server and GitHub Enterprise Server are self-hosted editions of hosted products.
- Hybrid by design: Buildkite runs the control plane as a service and expects you to bring the machines, with hosted agents as an option.
The eight CI/CD tools at a glance
tool config in repo hosted machines self-hosted option code hosts GitHub Actions .github/workflows/*.yml yes runners; GitHub Ent. Server GitHub GitLab CI/CD .gitlab-ci.yml yes runners; GitLab Self-Managed GitLab (+ mirrors) Jenkins Jenkinsfile no the whole server any Git CircleCI .circleci/config.yml yes runners; CircleCI server GitHub, GitLab, Bitbucket Cloud Azure Pipelines azure-pipelines.yml yes agents; Azure DevOps Server Azure Repos, GitHub, Bitbucket Cloud Bitbucket Pipelines bitbucket-pipelines.yml yes runners Bitbucket Cloud Buildkite .buildkite/pipeline.yml optional agents (the default) GitHub, GitLab, Bitbucket, other Git AWS CodePipeline set up in AWS AWS-managed no CodeCommit, S3, ECR, GitHub, GitLab, Bitbucket Cloud
Each tool, by what it does
GitHub Actions
Workflows are YAML files in .github/workflows, triggered by events in a GitHub repository. GitHub-hosted runners are new virtual machines with Ubuntu Linux, Windows or macOS; larger runners with more cores or a GPU are available on the GitHub Team and GitHub Enterprise Cloud plans. Self-hosted runners attach at the repository, organization or enterprise level. On GitHub Enterprise Server, GitHub’s docs say GitHub-hosted runners are not supported, so every job runs on your own runners.
GitLab CI/CD
Pipelines are defined in .gitlab-ci.yml at the root of the project. GitLab’s runners documentation (opens in a new tab) describes GitLab-hosted runners as fully managed, fresh VMs for each job, with Linux, Windows and macOS options, available on GitLab.com and GitLab Dedicated. Self-managed runners work on every offering, including GitLab Self-Managed, where you run the whole platform. Code that lives on GitHub, Bitbucket Cloud or another Git server can still use GitLab CI/CD through repository mirroring, a feature of the Premium and Ultimate tiers.
Jenkins
The Jenkins documentation (opens in a new tab) calls it “a self-contained, open source automation server”, installed from native packages, as a Docker container, or on any machine with a Java runtime. Pipelines are code: a Jenkinsfile committed to the repository, written in Declarative syntax (a pipeline block, easier to read) or Scripted syntax (more programmable). Almost everything else comes from plugins. Jenkins can build from any Git server, and everything about it is yours to run: the controller, the agents, the upgrades and the plugin updates.
CircleCI
Configuration lives in .circleci/config.yml. CircleCI cloud connects to GitHub.com, GitHub Enterprise Cloud and Server, GitLab.com, GitLab self-managed and Bitbucket Cloud. CircleCI server, the self-hosted installation, supports the GitHub options only. Self-hosted runners come in two forms: a machine runner for Linux, Windows or macOS machines, and a container runner for Kubernetes. They work with both cloud and server.
Azure Pipelines
Azure Pipelines is the CI/CD part of Azure DevOps, usually defined in azure-pipelines.yml at the repository root. Microsoft’s list of supported source repositories (opens in a new tab) shows YAML pipelines working with Azure Repos Git, GitHub, GitHub Enterprise Server and Bitbucket Cloud; Bitbucket Server, Subversion and TFVC need the older classic editor. Microsoft-hosted agents exist only in the cloud service; self-hosted agents run on Linux, macOS, Windows or in Docker, and are what Azure DevOps Server, the on-premises edition, uses. One retirement to know about: Microsoft has retired public projects, and existing ones keep their free parallel jobs only until they convert to private in 2027.
Bitbucket Pipelines
Atlassian describes Bitbucket Pipelines as “an integrated CI/CD service built into Bitbucket Cloud”, configured by bitbucket-pipelines.yml at the repository root. Builds run on Atlassian’s machines by default, or on self-hosted runners for Linux (Docker or shell), Windows or macOS, registered per repository or per workspace. It is for code in Bitbucket Cloud.
Buildkite
Buildkite splits the job in two. Its architecture page (opens in a new tab) says the control plane runs as a SaaS product while “you run the build environment on your own infrastructure”, and that source code and secrets stay in your environment. Buildkite hosted agents are the managed alternative, with Linux and macOS agents, and Windows in preview. Steps live in Buildkite or in .buildkite/pipeline.yml, and it connects to GitHub, GitLab, Bitbucket, Bitbucket Server and other Git servers.
AWS CodePipeline
AWS describes CodePipeline as a continuous delivery service to “model, visualize, and automate the steps required to release your software.” It orchestrates stages rather than running builds itself: AWS’s list of CodePipeline integrations (opens in a new tab) shows sources such as CodeCommit, S3, ECR and connections to GitHub, GitHub Enterprise Server, GitLab and Bitbucket Cloud (Bitbucket Server is not supported), builds in CodeBuild or Jenkins, and deploys to ECS, EKS, CloudFormation, CodeDeploy and more. A note on CodeCommit: AWS announced plans to de-emphasize it in July 2024, then reversed course on November 24, 2025, returning it to full general availability and opening it to new customers again.
Fit by where your code lives
- GitHub: GitHub Actions is already there. CircleCI, Azure Pipelines, Buildkite, Jenkins and CodePipeline all build from GitHub too.
- GitLab: GitLab CI/CD is built in. CircleCI, Buildkite, Jenkins and CodePipeline also connect.
- Bitbucket Cloud: Bitbucket Pipelines is built in. CircleCI, Azure Pipelines, Buildkite, Jenkins and CodePipeline also connect.
- Azure Repos: Azure Pipelines.
- A Git server you run yourself: Jenkins or Buildkite connect to any Git server; GitLab Premium can mirror one in.
- Everything already in an AWS account: CodePipeline with CodeBuild keeps the pipeline, its permissions and its logs inside AWS.
Fit by team size
- One to three developers: the CI/CD built into your code host, on hosted machines. There is no server to patch, the config sits next to the code, and permissions follow the repository’s.
- Four to twenty: the same, plus decisions you now need to write down: which jobs must pass before a merge, who approves production deploys, and where deploy secrets live. Add self-hosted runners only for a concrete reason, such as a build that needs a GPU or a database behind your firewall.
- Several code hosts, or a monorepo with slow builds: tools that sit outside the host, such as CircleCI or Buildkite, let one team run one pipeline setup across repositories and choose its own machines.
- Regulated, air-gapped or on-premises: a self-hosted control plane (Jenkins, GitLab Self-Managed, Azure DevOps Server, CircleCI server or GitHub Enterprise Server) keeps code and logs on machines you control, at the cost of running them.
What to check in a trial
- Build one real pipeline, not a hello world: install, test, build, deploy to a staging target.
- Put a secret in and confirm it is masked in logs and unavailable to pull requests from forks.
- Make production wait for a named person. Check which plan the approval feature needs; on some tools it differs for private repositories.
- Read how usage is counted: minutes, parallel jobs, or machines. Compare it with your current build times, not the free allowance.
- Estimate the exit. Pipeline files do not port between tools, so a large config is a switching cost.
Whatever you choose, how code reaches the main branch matters as much as the tool: git branching strategy covers that. Shipping code switched off so a deploy is not a release is covered in feature flags. The tool sits inside a wider set of choices, from infrastructure as code to on-call, covered in DevOps tools for a small team.
Tracking the work around the pipeline
A green pipeline says the build passed, not that the work behind it is finished. On a fenbs board each task has a test status and test notes, and the board filters by them, so “Completed, not tested” is one filter to read before every deploy. fenbs has no GitHub integration and no link to any CI/CD tool, so a person or a connected AI assistant sets the test status after checking; History records who did it. Put the task’s ref, such as BUG-042, in the pull request title so the two can be matched by eye.
Related
Running an AI coding assistant as a pipeline step: Claude Code GitHub Actions. What to run before a release: regression testing checklist. Measuring what the pipeline delivers: DORA metrics. fenbs for developers: fenbs for developers.