Skip to main content
Cloud DevOps Solutions
Get a quote Talk to an engineer

CI/CD and GitOps

GitHub Actions Consulting for Secure, Fast and Maintainable Pipelines

GitHub Actions is the workflow automation built into GitHub, used to build, test, scan and deploy code on every push or pull request. We design its workflow structure, short-lived cloud credentials, runner strategy and caching so pipelines stay fast, auditable and cheap to maintain as your team and repositories grow.

Key takeaways

  • GitHub Actions is the natural default when your code already lives on GitHub, because identity, pull requests, checks and secrets are all in one place.
  • Replace long-lived cloud keys with OIDC federation so a workflow receives short-lived credentials scoped to one repository, branch or environment.
  • Reusable workflows and composite actions are what keep a hundred repositories maintainable; copy-pasted YAML is what makes them brittle.
  • Third-party actions are supply chain dependencies. Pin them to a commit SHA and restrict which ones your organisation allows.
  • Hosted runners are easy but metered. Cache well, cancel redundant runs, and move heavy or private-network jobs to self-hosted runners only when the numbers justify it.

What teams use GitHub Actions for

Build, test and scan on every pull request

Linting, unit tests, dependency and container image scanning run as required checks so nothing merges without a green, reviewable result.

Container image build and publish

Images are built with layer caching, tagged from the commit, scanned and pushed to ECR, ACR or GitHub Container Registry without stored registry passwords.

Deploying to AWS and Azure without static keys

Workflows assume a cloud role through OIDC, so there is no access key to leak or rotate.

Infrastructure pipelines for Terraform

Plans are posted to the pull request and applies run from a protected environment with required reviewers.

Release automation across many repositories

One central set of reusable workflows enforces the same build, scan and release standard everywhere.

What GitHub Actions is and why teams adopt it

GitHub Actions is the automation engine inside GitHub. A workflow is a YAML file in .github/workflows/ that reacts to an event such as a push, a pull request, a release or a schedule, and runs jobs on a runner. Because it sits next to the code, the pull request page becomes the single place where reviewers see tests, scans and deployment status.

Teams adopt it for three reasons: there is no separate CI server to maintain, identity and permissions come from GitHub itself, and the marketplace saves time on common tasks. As a GitHub Actions consulting team, we see the same pattern repeatedly. The first workflow takes an afternoon. The hundredth, copied from the previous ninety-nine, is where cost, security and maintenance problems appear. Our work is mostly about that second phase.

How we structure workflows in production

Reusable workflows over copy and paste

We keep build, test, scan and deploy logic in a central repository as reusable workflows, and each application repository calls them with a few inputs. A fix to the standard then reaches every service through a version bump.

# .github/workflows/ci.yml in an application repository
name: ci
on:
  pull_request:
  push:
    branches: [main]

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

permissions:
  contents: read

jobs:
  build:
    uses: your-org/platform-workflows/.github/workflows/build-scan.yml@v3
    with:
      image-name: payments-api
    secrets: inherit

Two details matter here. concurrency cancels superseded runs on the same branch, which saves minutes and avoids confusing results. The top-level permissions block drops the default token to read-only, and each job then asks for only what it needs.

Environments, approvals and promotion

Deployments run in GitHub Environments such as staging and production. Production requires reviewers, can be limited to the main branch, and holds its own cloud role. The same artefact is promoted between environments instead of being rebuilt, so what you tested is what you ship. We cover the wider pattern in our environment promotion gates and approvals work.

Caching and matrix builds

Caching dependencies and Docker layers is the biggest single speed gain for most repositories. Matrix builds fan tests out across versions or shards. Both are covered in parallel test execution and matrix builds and build caching strategy.

Security and access

Most GitHub Actions incidents come from three places: long-lived secrets, over-privileged tokens and untrusted third-party code.

  • OIDC instead of stored keys. The job exchanges a GitHub-issued token for short-lived AWS or Azure credentials. The cloud trust policy names the repository and the environment, so a fork or an unrelated branch cannot assume the role.
  • Least-privilege GITHUB_TOKEN. Set the organisation default to read-only and grant id-token: write or packages: write per job.
  • Pinned actions. Reference third-party actions by commit SHA and restrict the allowed list in organisation settings.
  • Careful triggers. pull_request_target and workflow_run run with more privilege than pull_request. Never check out and execute untrusted fork code in those contexts.
  • Secrets scope. Environment-level secrets with required reviewers, and a secrets manager such as Vault or AWS Secrets Manager for anything sensitive. See CI/CD secrets management with Vault.

Cost and capacity

GitHub-hosted runners are billed by the minute, with different multipliers per operating system and size, so the cheapest minute is the one you never run. Our usual order of attack is: cancel redundant runs, use path filters so documentation changes do not trigger full builds, cache aggressively, split slow suites sensibly, and only then consider bigger or self-hosted runners.

Self-hosted runners make sense for private network access, specialised hardware or sustained high volume. On Kubernetes, a runner controller such as actions-runner-controller can scale ephemeral pods on demand, so each job starts clean. Budget for the operating work: patching images, handling scale-up latency and isolating untrusted code. We would rather you keep hosted runners than run a poorly isolated fleet.

Day-2 operations

  • Observability. Track queue time, run duration and failure rate per workflow. A flaky test that fails five per cent of runs costs far more than its fix.
  • Updates. Dependabot can raise pull requests for action versions, so upgrades are small and reviewed.
  • Ownership. CODEOWNERS on the workflows directory means changes to deployment logic need a platform review.
  • Notifications. Failures and deployments post to chat, covered in deployment notifications to Slack and Teams.

Failure modes we design around

Failure modeWhat causes itWhat we do
Leaked cloud keyStatic credentials stored as secretsOIDC and short-lived roles
Supply chain compromiseActions referenced by mutable tagSHA pinning, allow list, Dependabot
Runaway billNo concurrency control, no path filtersCancel in progress, filters, caching
Slow feedbackOne long serial jobMatrix and sharding, better caching
Drift between reposCopied YAMLCentral reusable workflows with versions

When not to use GitHub Actions

If your source of truth is GitLab or Azure DevOps, use the pipeline engine that lives there; moving code just to change CI rarely pays off. If you need to build in a fully air-gapped network or you depend on years of bespoke plugins, Jenkins may stay the pragmatic choice. For Kubernetes delivery we usually pair Actions for CI with ArgoCD or Flux for deployment, so the cluster pulls its desired state instead of CI pushing credentials into it.

Working with us

We build and repair pipelines under our CI/CD pipeline service, usually starting with a short audit. If you are leaving Jenkins, our Jenkins to Actions migration plan shows how we phase it. To see how your delivery practice compares, try the DevOps maturity assessment or book a consultation.

Official documentation: docs.github.com/en/actions

How we work with GitHub Actions

  1. 01

    Audit the current pipelines

    We read your existing workflows or legacy jobs, measure run times and queue delays, and list secrets, third-party actions and permissions in use.

  2. 02

    Design the workflow architecture

    We decide what is a reusable workflow, what is a composite action, how environments and approvals map to branches, and where caching belongs.

  3. 03

    Replace static credentials with OIDC

    Cloud trust policies are scoped by repository, branch and environment, and stored secrets are removed or reduced to the unavoidable few.

  4. 04

    Build the shared library

    Central workflows for build, test, scan and deploy are versioned and consumed by thin caller workflows in each repository.

  5. 05

    Tune runners and cost

    We set concurrency rules, caching and path filters, then size hosted or self-hosted runners against real usage.

  6. 06

    Harden and hand over

    Default token permissions, allowed actions, branch protection and runbooks are documented, and we walk your engineers through ownership.

GitHub Actions compared with the alternatives

We recommend the tool that fits your team, not the one we know best. Here is when each option makes sense.

OptionChoose it when
GitHub ActionsGitHub Actions is the workflow automation built into GitHub, used to build, test, scan and deploy code on every push or pull request.
GitLab CI/CDChoose it if your source control is GitLab or you want one platform covering repositories, registry, security scanning and pipelines under a single licence.
JenkinsChoose it for heavily customised, on-premises or air-gapped delivery where you need full control of the build environment and already have the people to run it.
Azure PipelinesChoose it if your boards, repositories and release governance already live in Azure DevOps and your team prefers its release and approval model.
ArgoCD or Flux for deploymentChoose a GitOps controller for the Kubernetes deploy step, and keep GitHub Actions for build and test. They complement each other rather than compete.

Tools we use alongside GitHub Actions

Docker BuildxAmazon ECRAzure Container RegistryTerraformTrivyCodeQLDependabotactions-runner-controllerOpenID ConnectArgoCDHelmSlack

Frequently asked questions

What is GitHub Actions used for?
GitHub Actions automates tasks triggered by repository events. Teams use it to run tests on pull requests, build and scan container images, deploy to AWS, Azure or Kubernetes, publish packages and run scheduled jobs. Workflows are YAML files in the repository, so pipeline changes are reviewed like any other code.
How do you deploy to AWS from GitHub Actions securely?
Use OpenID Connect. The workflow requests a short-lived token from GitHub, and an IAM role with a trust policy restricted to your repository and branch or environment accepts it. No access keys are stored, nothing needs rotating, and each role can be limited to the minimum permissions the job needs.
Should we use GitHub-hosted or self-hosted runners?
Start with GitHub-hosted runners because they need no maintenance. Move to self-hosted when you need private network access, special hardware, larger machines or lower cost at high volume. Self-hosted runners must be ephemeral and isolated, especially for public or forked pull requests, or they become a security risk.
How do we keep GitHub Actions workflows from becoming a mess?
Centralise shared logic in reusable workflows and composite actions, version them with tags, and keep caller workflows tiny. Add a consistent naming scheme, set least-privilege token permissions by default, and review workflow changes through CODEOWNERS so one team owns the standard.
Is it safe to use third-party actions?
Treat them as dependencies that execute with your credentials. Pin to a full commit SHA rather than a tag, prefer actions from verified creators, restrict the allowed list at organisation level, and let Dependabot propose updates so changes are reviewed instead of silently inherited.
Can you migrate us from Jenkins to GitHub Actions?
Yes. We inventory jobs, convert them in order of value and risk, run old and new pipelines side by side until results match, and then retire the Jenkins jobs. Shared libraries become reusable workflows. Details are in our Jenkins to GitHub Actions migration guide.

Talk to an engineer about GitHub Actions

Book a free 30-minute call. We review your current setup and tell you honestly whether and how we can help.

Written by Saddique Khan, DevOps / SRE / Cloud Consultant Engineer. Last updated 2026-10-09.