GitHub Actions came out of beta at the end of 2019, and in 2020 they’re becoming a real alternative to Jenkins, GitLab CI, and Azure DevOps. We tried them on three projects — here are our experiences.
Why GitHub Actions in 2020¶
Jenkins is powerful, but maintaining it is a full-time job. Plugin hell, Groovy scripts nobody wants to debug, and a UI from 2005. GitLab CI is elegant, but requires GitLab. If your code lives on GitHub — and in 2020, most teams’ code does — Actions makes perfect sense.
Key advantages:
- Native integration: CI/CD lives directly in the repository, not on a separate server
- YAML configuration: versioned, reviewable, mergeable — like code
- Marketplace: thousands of ready-made actions from the community — from caching to deployment
- Matrix builds: test on multiple OS/versions in parallel without complex configuration
- Free tier: 2,000 minutes/month for public repos, 2,000 for private (Team plan)
Anatomy of a Workflow File¶
Everything starts with a file in .github/workflows/. Basic structure for a .NET Core application:
name: CI Pipeline
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.x'
- run: dotnet restore
- run: dotnet build --no-restore
- run: dotnet test --no-build
Clear, readable, versioned. No click-through wizard, no “who changed that Jenkins job?” A pull request on the workflow file goes through the same review as application code.
Secrets Management¶
GitHub Secrets are encrypted at the repository or organization level. In workflows, they’re accessed via ${{ secrets.NAME }}. For deployment credentials (Azure service principal, AWS keys, Docker registry), it’s a clean solution without external vault systems.
For more complex scenarios — key rotation, dynamic secrets — we combine GitHub Secrets with Azure Key Vault. The azure/login@v1 action authenticates via service principal and pulls current secrets from Key Vault. Two layers of security, automatic rotation.
A Real Deployment Pipeline¶
On a project for a logistics company, we deployed a complete pipeline:
- PR check: build + unit tests + linting (ESLint, Prettier) — blocks merge on failure
- Build artifact: Docker image, push to Azure Container Registry
- Deploy to staging: automatically after merge to develop — Azure Web App for Containers
- Integration tests: Postman/Newman collection runs against the staging environment
- Deploy to production: manual approval via GitHub Environments, then rolling update
The entire pipeline from push to production: ~12 minutes. With Jenkins it was 25+ minutes and required a dedicated build server.
Matrix Strategy for Cross-Platform¶
A library we deliver to clients for integration with their systems must run on .NET Core 3.1 and .NET Framework 4.8, on both Windows and Linux. Matrix build handles this elegantly:
strategy:
matrix:
os: [ubuntu-latest, windows-latest]
dotnet: ['3.1.x', '5.0.x']
fail-fast: false
Four combinations run in parallel. Results in 4 minutes instead of 16 sequentially. And fail-fast: false means that even if one combination fails, the others complete — you know exactly where the problem is.
Self-Hosted Runners — When and Why¶
GitHub-hosted runners are convenient, but have limits: 7 GB RAM, 14 GB disk, no access to internal networks. For building large .NET solutions (50+ projects) or deploying to on-premise environments, you need a self-hosted runner.
We deployed a runner as a Docker container on Azure Container Instance — ephemeral, scalable, with access to the client’s VNet via VNet integration. The runner starts, executes the job, and terminates. Clean state for every build, no state drift.
Comparison with Jenkins and GitLab CI¶
- Jenkins: most flexibility, but most maintenance. Suitable for enterprises with a dedicated DevOps team and legacy integrations
- GitLab CI: excellent if you use GitLab. Tighter integration, built-in registry, security scanning. But vendor lock-in
- GitHub Actions: best developer experience, quick start, great for teams on GitHub. Less mature for complex enterprise scenarios (in 2020)
Actions as the Default Choice for New Projects¶
For new projects in 2020, we recommend GitHub Actions as the default CI/CD platform. Lower operational costs, better developer experience, and sufficient flexibility for most scenarios. We leave Jenkins where it’s already running and working — migration has to be worth it.
Need help with implementation?
Our experts can help with design, implementation, and operations. From architecture to production.
Contact us