DevOps

GitHub Actions and GitLab CI

In 2020, a five-person team spent two hours per day on manual deploys. After setting up a CI/CD pipeline, that number dropped to zero - the pipeline builds, tests, and deploys on every push. GitHub Actions and GitLab CI are the two most widely used tools for this, and both are free for most projects.

  • **Vercel and Netlify** use GitHub Actions under the hood - every push to main deploys automatically to a CDN
  • **npm publish** for thousands of open-source packages is fully automated via GitHub Actions on GitHub Release creation
  • **GitLab CI** runs pipelines at Airbus, CERN, and NASA JPL for mission-critical software with self-hosted runners

Pipeline structure

Every time a developer pushes code, a chain of events fires automatically: build, test, lint, deploy. This chain is a **pipeline** - a sequence of automated steps that transforms a code change into a working product in production.

In GitLab CI, a pipeline lives in `.gitlab-ci.yml`. Key concepts: **stage** (a phase), **job** (a task within a stage), **runner** (the machine executing the job). Jobs within the same stage run in parallel; stages execute sequentially. The `needs:` keyword breaks the stage barrier, enabling DAG-style job ordering.

**needs:** in GitLab CI builds a DAG of explicit job dependencies, bypassing the stage barrier. A test job can start the moment its build dependency finishes, without waiting for other jobs in the build stage. This commonly cuts pipeline duration by 30-50%.

In GitLab CI, two jobs share the same stage: `lint` and `test`. How do they execute by default?

Workflows and triggers in GitHub Actions

GitHub Actions uses the term **workflow** instead of pipeline. A workflow is a YAML file in `.github/workflows/` that defines when to run (`on:`), where to run (`runs-on:`), and what to do (`steps:`). A single event can trigger multiple workflows in parallel.

The trigger system is richer than GitLab's: `push`, `pull_request`, `schedule` (cron), `workflow_dispatch` (manual run with parameters), `workflow_call` (called from another workflow), `release`, `issue_comment`. Each trigger supports filtering by branch, tag, and file path.

**Reusable workflows** (`workflow_call`) extract common logic - Docker image builds, deploy scripts, notification patterns - into a dedicated file callable from multiple workflows. This applies function-extraction principles to CI/CD, avoiding cross-repository copy-paste.

A workflow must trigger only on push to `main` or `release/*` branches, but must skip pushes that only modify `*.md` files. What configuration handles this?

Self-hosted runners

GitHub-hosted runners (ubuntu-latest, macos-latest) are convenient but constrained: 2 vCPU, 7 GB RAM, no access to private networks. A **self-hosted runner** is a machine registered with GitHub or GitLab that executes jobs. Use cases: access to on-premise resources, GPU workloads, specialized tooling, and cost reduction for high job volumes.

GitLab's equivalent is **GitLab Runner**, supporting several executors: `shell` (runs in the machine shell), `docker` (isolated container per job - recommended), `kubernetes` (one pod per job). For production, the docker executor is preferred - it isolates environment between jobs and prevents state leakage.

**Security:** self-hosted runners in public repositories are dangerous. A malicious pull request can inject arbitrary code into the runner environment. Restrict self-hosted runners to private repositories, or require approval for fork-originated pull requests.

A team needs CI jobs to reach an internal database during integration tests. What is the correct solution?

Artifacts and caching

A pipeline often runs jobs on different machines. How does a `deploy` job access the compiled binary from `build`? Through **artifacts** - files a job saves after completion that subsequent jobs or users can download.

**Cache** solves a different problem: it speeds up pipelines by reusing unchanged data between runs. `node_modules`, pip packages, Gradle caches - downloaded once, stored on the runner or in cloud storage, reused on subsequent runs. Cache is not guaranteed - the pipeline must work correctly on a cache miss.

**Artifacts vs cache:** artifacts hold job outputs (binaries, test reports, screenshots), are stored reliably, and are accessible across jobs and in the UI. Cache holds acceleration data (dependencies), may be absent (cache miss), and must never contain build outputs.

Cache and artifacts are interchangeable - both persist files between jobs

Artifacts are a guaranteed store for job results. Cache is a speed optimisation with no availability guarantees.

A cache miss is expected behavior - the pipeline must handle it gracefully. An artifact missing within its retention window is an error.

A `security-scan` job produces an HTML report that must be downloadable from the pipeline UI after the run. What should be used?

GitHub Actions and GitLab CI

  • Pipeline = stages + jobs; jobs within a stage are parallel, stages are sequential
  • GitHub Actions: rich on: triggers with branch, path, and schedule filters; reusable workflows avoid duplication
  • Self-hosted runners enable access to private networks, GPUs, specialized tooling; restrict to private repos for security
  • Artifacts store guaranteed outputs; cache accelerates with no guarantees - they serve different purposes

Related topics

CI/CD pipelines build on containers and orchestration:

  • Docker and containerisation — Most pipeline jobs execute inside Docker containers
  • Kubernetes: deployments — CI pipelines frequently conclude with a Kubernetes deployment step
  • Jenkins and advanced CI/CD — An alternative with more flexible pipeline capabilities

Вопросы для размышления

  • Why can the `needs:` keyword in GitLab CI reduce pipeline duration without changing any business logic?
  • Under what conditions is a self-hosted runner economically justified despite the administrative overhead?
  • How should cache invalidation be handled when dependencies update, without breaking concurrent pipeline runs?

Связанные уроки

  • alg-18-topological
  • sec-05
GitHub Actions and GitLab CI

0

1

Sign In