GitHub Actions

Automation that turns repository events into tested, built, published artifacts.

How This Fits Our End-to-End Pipeline

GitHub Actions is documented here as part of one connected build, not as an isolated tutorial. The goal is to explain how code moved from a developer laptop into a monitored Kubernetes service.

Developer laptop
  | git add / commit / push
  v
GitHub repository
  | pull request + branch rules
  v
GitHub Actions workflow
  | test -> docker build -> tag -> push
  v
Docker Hub image registry
  | immutable image tag
  v
GitOps manifests repository/path
  | ArgoCD watches desired state
  v
Kubernetes cluster
  | app pods + services + ingress
  v
Prometheus scrapes metrics -> Grafana dashboards

Theory

GitHub Actions automates work triggered by repository events. For our pipeline, it runs tests, builds the Docker image, pushes it to Docker Hub, and updates Kubernetes manifests with the new image tag.

The workflow is CI when it validates and builds. It becomes part of CD when it publishes deployable artifacts or changes GitOps manifests that ArgoCD will sync.

Workflow Architecture

push / pull_request
      |
      v
.github/workflows/ci.yml
      |
      +-- checkout code
      +-- install dependencies
      +-- test / lint
      +-- docker login
      +-- docker build and push
      +-- update k8s image tag
      +-- commit manifest change

Implementation

name: ci-cd

on:
  pull_request:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: write
    steps:
      - uses: actions/checkout@v4

      - name: Set image tag
        run: echo "IMAGE_TAG=sha-${GITHUB_SHA::7}" >> "$GITHUB_ENV"

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push
        uses: docker/build-push-action@v6
        with:
          context: .
          push: ${{ github.ref == 'refs/heads/main' }}
          tags: ${{ secrets.DOCKERHUB_USERNAME }}/devops-demo:${{ env.IMAGE_TAG }}

Manifest Update Pattern

# Example idea used after docker push
# Replace image tag in k8s manifest, then commit the change
sed -i 's|image: .*|image: dockerhub-user/devops-demo:sha-9f3a21c|' k8s/staging/deployment.yaml
git add k8s/staging/deployment.yaml
git commit -m 'Deploy image sha-9f3a21c'
git push

Secrets

  • DOCKERHUB_USERNAME stores the registry namespace.
  • DOCKERHUB_TOKEN stores a Docker Hub access token, not the account password.
  • Secrets are referenced in workflows using ${{ secrets.NAME }}.
  • Environment secrets can separate staging and production credentials.

Commands and Files

Create workflow folder

mkdir -p .github/workflows

The conventional location for GitHub Actions workflow YAML.

Validate by push

git add .github/workflows/ci.yml
git commit -m "Add CI workflow"
git push

The workflow runs after GitHub receives the commit.

Check runs

gh run list
gh run view --log

Useful when the GitHub CLI is installed and authenticated.

Quality Gates

  • Run tests on every pull request.
  • Build images only after tests pass.
  • Push images only from trusted branches.
  • Require approvals for production environments.

Interview Notes

  • A workflow contains jobs; jobs contain steps; steps run shell commands or actions.
  • Hosted runners are convenient; self-hosted runners are useful for private networks or custom tooling.
  • Use least-privilege workflow permissions rather than broad repository write access everywhere.
  • Do not deploy from pull request workflows that can be triggered by untrusted code.
  • Artifacts, caches, and Docker layers solve different performance and handoff problems.

FAQs

Why did we update manifests instead of kubectl applying directly?

Because the GitOps model lets ArgoCD deploy from Git, preserving review history and drift detection.

Can one workflow handle CI and CD?

Yes for a learning project, but teams often split validation, release, and deployment workflows as complexity grows.

What breaks most often?

Secrets, image tags, registry permissions, YAML indentation, and missing workflow permissions.

Memorize vs Look-up

Memorize

  • Workflow, job, step, action, runner, secret, environment.
  • Common events: push, pull_request, workflow_dispatch.
  • Use commit SHA tags for traceable images.

Look Up

  • Every action version and marketplace input.
  • Complex expression syntax.
  • Matrix strategy edge cases.

Project Implementation Journal

Baseline

We first made sure the application or configuration worked before introducing GitHub Actions. A broken baseline makes every later automation failure harder to understand.

Local proof

We validated the GitHub Actions workflow locally where possible, because local feedback is faster than waiting for CI or a cluster reconciliation loop.

Repository proof

We committed the GitHub Actions change as a reviewable unit so the reason for the pipeline change was visible in Git history.

Automation handoff

We connected GitHub Actions to the next tool in the chain instead of treating it as a standalone exercise.

Failure check

We intentionally inspected the common failure signals for GitHub Actions: logs, status output, permissions, names, tags, and configuration paths.

Rollback thinking

We asked how to return to the previous working state if the GitHub Actions change caused a bad deployment.

Interview compression

We reduced GitHub Actions into a few sentences that explain purpose, implementation, and failure modes clearly.

Operations note

We documented what someone should check the day after the deployment, not only what to run during setup.

Decision Records

  • Keep GitHub Actions configuration in Git where it can be reviewed.
  • Prefer explicit names over clever names: repository, image, namespace, workflow, and application names should be searchable.
  • Use immutable versions for anything that can be deployed or rolled back.
  • Put secrets in the platform secret store, not in code, documentation screenshots, or shell history.
  • Automate only after the manual path is understood.
  • Make the happy path visible, then document the first five things to check when it fails.
  • Separate staging and production concerns before the project becomes too large.
  • Choose boring defaults unless there is a real operational reason to customize.
  • Write commands so they can be pasted into a terminal after replacing obvious placeholders.
  • Treat dashboards, manifests, and workflow files as production code once people rely on them.

Failure Modes We Learned To Recognize

Wrong name

The most ordinary failures came from mismatched names: image repository, namespace, service selector, branch, workflow file, or dashboard variable.

Wrong permission

Automation failed when a token could read but not write, push but not pull, or access staging but not production.

Wrong version

A deployment looked successful while the cluster still ran an old image tag or an image tag that had been overwritten.

Wrong assumption

A command that worked locally failed in CI because the runner had a different shell, path, network, or credential context.

Missing feedback

Without logs, status commands, metrics, or dashboards, the system gave no quick answer about what changed.

Manual drift

Manual cluster edits solved a momentary problem but made the GitOps source of truth inaccurate.

Interview Drill Questions

  • What problem does GitHub Actions solve in this pipeline?
  • What artifact or state does GitHub Actions produce?
  • Which tool consumes the output of GitHub Actions next?
  • What is the most likely beginner mistake with GitHub Actions?
  • How would you prove GitHub Actions worked without guessing?
  • How would you roll back a bad change involving GitHub Actions?
  • What should be memorized versus looked up for GitHub Actions?
  • Which security boundary matters most for GitHub Actions?
  • How would you explain GitHub Actions to someone who only knows basic Linux?
  • What metric, log, status, or command would you check first during an incident?

Glossary For This Stage

Artifact

A build output or configuration object that can be handed to another stage.

Desired state

The state declared in Git or YAML that controllers try to make real.

Reconciliation

The loop where a tool compares desired state with actual state and fixes differences.

Immutable version

A version reference that should never change meaning after publication.

Rollback

A controlled return to a previously known working state.

Drift

A difference between what Git says should exist and what is actually running.

Health

A status signal that says whether the service is ready and operating correctly.

Traceability

The ability to connect a running system back to a commit, workflow run, image, and manifest change.

Practical Runbook

Confirm source

Identify the exact repository, branch, commit, file path, or dashboard connected to GitHub Actions.

Confirm identity

Check the account, token, kube context, registry namespace, or runner label before assuming the tool is broken.

Confirm version

Write down the version or tag you expected and compare it with the version the platform reports.

Confirm status

Use the native status command or UI first; it usually tells you whether the failure is configuration, permission, or runtime.

Confirm logs

Logs explain what happened after the tool accepted the configuration but the process still failed.

Confirm network

Many CI/CD failures are actually DNS, registry, cluster, firewall, or service discovery failures.

Confirm ownership

Know whether the application team, platform team, security team, or repository owner controls the failing setting.

Confirm rollback

Before changing more things, decide whether the quickest safe move is to revert, resync, rebuild, or redeploy.

Confirm documentation

After fixing the issue, add the command, symptom, and fix to the project notes so the next run is faster.

Confirm automation

If the GitHub Actions step is repeated manually more than twice, turn it into a workflow, manifest, script, or checklist.

Verification Checklist

  • Can I point to the exact Git commit connected to this GitHub Actions change?
  • Can I explain what changed in one sentence?
  • Can I prove the change worked with a command or status screen?
  • Can I identify the next tool that consumes this output?
  • Can I identify the secret, token, or permission that would break this step?
  • Can I roll back without manually editing production state?
  • Can I tell whether the failure is build-time, deploy-time, or runtime?
  • Can I show the relevant logs or metrics?
  • Can I repeat the setup on a fresh machine or cluster?
  • Can I teach this stage without reading every command from the page?