GitHub Actions vs. GitLab CI vs. Jenkins: a side-by-side syntax review
An analysis of a public repository that implements the same Python test pipeline in three major CI/CD systems, focusing on syntax, maintenance overhead, and the developer experience for small teams.…
An analysis of a public repository that implements the same Python test pipeline in three major CI/CD systems, focusing on syntax, maintenance overhead, and the developer experience for small teams.
The Answer Up Front
For founders and early-stage teams building on GitHub, GitHub Actions is the pragmatic default choice for CI/CD. If your stack is built entirely on GitLab, its integrated CI is the obvious and correct path. Jenkins should be avoided for new projects unless you have a non-negotiable requirement for self-hosting and total control, and are prepared to pay the significant maintenance tax in engineering time. The bottom line is that integrated, platform-native CI is good enough and radically simpler to manage than a separate, dedicated system.
Methodology
This v0 review analyzes a public artifact: the ci-tools-demo GitHub repository created by developer Dayan Elvis Jahuira Pilco, observed on July 5, 2026. The source signal is the accompanying blog post at dev.to. We did not run these pipelines ourselves or measure their performance. This analysis focuses exclusively on the provided configuration files (workflow.yml, .gitlab-ci.yml, Jenkinsfile) to compare the developer experience, syntax, and conceptual overhead of implementing an identical, simple test pipeline across the three platforms.
What's covered is a static analysis of the configuration code for a Python project that installs dependencies, runs a pytest suite, and archives the test results. What's not covered includes pipeline execution speed, debugging workflows, scalability to more complex scenarios, or the other six CI/CD tools mentioned in the source article's summary table. This review is based on the author's published code; independent benchmarks are pending.
What It Does
The repository provides a concrete, side-by-side comparison of three distinct approaches to CI/CD configuration for the same simple task.
The common pipeline
All three configurations execute the same logic: check out the code, set up a specific Python version (3.9), install dependencies from requirements.txt, run the test suite using pytest with a JUnit XML output flag, and then archive that XML report as a build artifact. This represents a foundational continuous integration task for any software project.
GitHub Actions: declarative and marketplace-driven
The GitHub Actions implementation is a single YAML file (.github/workflows/workflow.yml). It uses a declarative, step-based syntax. Key steps rely on pre-built components from the GitHub Marketplace, like actions/checkout@v3 and actions/setup-python@v4. This abstracts away boilerplate, making the file highly readable but also dependent on third-party code. Publishing artifacts is a simple, dedicated step: actions/upload-artifact@v3.
GitLab CI: declarative and container-native
GitLab's .gitlab-ci.yml is also declarative YAML. Instead of a marketplace, its core primitive is the Docker image. The pipeline specifies image: python:3.9 at the top level, and all subsequent script commands run within a container spun up from that image. The configuration is structured around stages (e.g., build, test), and artifacts are handled with a dedicated artifacts keyword. The approach is self-contained and less reliant on external actions than GitHub's model.
Jenkins: programmatic and plugin-based
The Jenkinsfile is fundamentally different. It is not a declarative configuration file; it is a program written in a Groovy-based Domain-Specific Language (DSL). It defines the pipeline's logic through code, specifying an agent (where to run), stages, and steps. Even for this simple pipeline, the syntax is more verbose. Archiving test results requires knowing the correct plugin function, in this case junit 'reports/junit.xml'. This offers immense power and flexibility at the cost of a much steeper learning curve.
What's Interesting / What's Not
The primary value of this artifact is how clearly it illustrates the core philosophical differences between the tools. The shell commands to install and test are identical across all three; the orchestration is what you're buying into.
What's most interesting is the trade-off between abstraction and control. GitHub Actions provides the highest level of abstraction. Using actions/setup-python@v4 is simple, but you are trusting the community-maintained action to work correctly. GitLab's container-first approach is a solid middle ground, making dependencies explicit (image: python:3.9) while still managing the execution environment for you. Jenkins represents the lowest level of abstraction. You control everything, but you are responsible for everything, from managing the Jenkins server itself to ensuring plugins are compatible and secure.
The verbosity of the Jenkinsfile compared to the YAML files is striking. For a simple task, it requires significantly more code and knowledge of Groovy syntax and the Jenkins plugin ecosystem. This is the maintenance tax in plain sight. For a small team, every minute spent debugging a CI script or a plugin conflict is a minute not spent on the product.
What's not interesting is a feature-by-feature comparison for a simple use case. All three tools can run this pipeline effectively. The critical differentiator for a founder is not if it can be done, but the total cost of ownership in terms of cognitive load, configuration time, and ongoing maintenance.
Pricing
Pricing models reflect the tools' philosophies. (Snapshot: July 5, 2026)
- GitHub Actions: Free for public repositories, with generous minute allotments. For private repositories, a free tier of minutes is included, with pay-as-you-go pricing thereafter.
- GitLab CI: Offers a free tier with a monthly quota of compute minutes. Higher tiers provide more minutes and advanced features.
- Jenkins: The software is 100% free and open source. The cost is indirect but substantial: server hosting (cloud or on-premise) and the engineering time required for setup, configuration, and maintenance.
Verdict
This side-by-side comparison is a powerful decision-making tool. For a new project, the choice is clear. If your code lives on GitHub, use GitHub Actions. If it lives on GitLab, use GitLab CI. The integration is seamless, the learning curve is gentle, and the free tiers are sufficient for most early-stage projects.
Choose Jenkins only if you face a hard constraint that the platform-integrated tools cannot meet, such as needing to run on-premise in an air-gapped environment or requiring a level of customization that only a fully programmable pipeline can provide. For 99% of startups, the power of Jenkins is unnecessary, and its maintenance overhead is a dangerous distraction.
What We'd Test Next
A v2 of this analysis would require running the pipelines to gather performance data. We would test how each platform's configuration complexity scales when adding matrix builds across multiple Python versions and operating systems. We would also investigate the debugging experience by intentionally introducing failures at different stages of the pipeline. Finally, a deeper look at the security and maintenance implications of GitHub's marketplace-driven model versus GitLab's container-centric one would be valuable, especially regarding supply chain security.
The investor read
The CI/CD market illustrates the power of platform integration. GitHub (Microsoft) and GitLab have effectively commoditized baseline CI for the vast majority of new projects by bundling it with source control. This severely limits the addressable market for standalone, venture-backed CI tools, which must now compete on specialized niches like performance (CircleCI) or enterprise complexity (Harness). Jenkins' continued relevance is a testament to enterprise inertia and the long tail of complex, legacy requirements. Investment theses in this space should focus on tools that are either deeply embedded in a dominant platform's ecosystem or that solve a highly specific, high-value problem that platform defaults don't address, such as managed deployment environments or advanced security pipeline orchestration.
Pull quote: “For a small team, every minute spent debugging a CI script or a plugin conflict is a minute not spent on the product.”
- CI/CD Testing Tools Compared: the Same Pipeline in GitHub Actions, GitLab CI and Jenkins ↗
- GitHub Repository: ci-tools-demo ↗
Every claim ties to a primary source. See our methodology.