Try it free
Write faster with AI writing tools
WriterPilots gives you 10+ free AI writing tools — blog writer, email writer, paraphraser, grammar fixer and more. Free to try, no credit card needed.
Try Blog Writer → Paraphraser Summarizer Grammar Fixer
AI Writing Tools

Exercises: CI/CD Basics — GitHub Actions Mini-Project for New Hires

March 21, 2026 · 7 min read · 9 views

Exercises: CI/CD Basics — GitHub Actions Mini-Project for New Hires

One-line learning outcome: Gain practical experience writing GitHub Actions workflows that run tests, lint code, build a Docker image, and deploy to a target, with verifiable checkpoints.

Estimated total time: 6–8 hours (can be split across days)

Audience: Junior developers, bootcamp grads, new hires, and mentors building onboarding exercises.

Prerequisites

  • A small app repo (Node, Python, or Go) with tests — this guide uses a Python Flask example but shows alternatives.
  • GitHub account and repository
  • Familiarity with Git and basic Docker

Exercise roadmap (4 progressive tasks)

  1. Task 1 — Run tests on pull requests (1–1.5 hrs)
  2. Task 2 — Add linting and type checks to CI (1–1.5 hrs)
  3. Task 3 — Build and publish a Docker image on merge (2 hrs)
  4. Task 4 — Deploy a built image to a host (1.5–2 hrs)

Task 1: Run tests on pull requests

Goal: Create a workflow that runs pytest (or chosen test runner) on PRs and reports status.

Hands-on lab

  1. Create workflow folder and file

    mkdir -p .github/workflows

    cat > .github/workflows/ci.yml <<'YML'

    name: CI

    on:

    pull_request:

    branches: [ main ]

    jobs:

    test:

    runs-on: ubuntu-latest

    steps:

    - uses: actions/checkout@v3

    - uses: actions/setup-python@v4

    with:

    python-version: '3.10'

    - name: Install dependencies

    run: |

    python -m pip install --upgrade pip

    pip install -r requirements.txt

    - name: Run tests

    run: pytest -q

    YML

  2. Open a pull request with a small test that fails to observe workflow reporting.

Expected outcome

The workflow runs and GitHub shows the checks on the PR; failing tests show red X and logs show pytest output.

Exercises

  1. Add a matrix strategy to test against multiple Python versions. (Medium)
  2. Make tests run on push to main with a tag naming convention. (Medium)

Checkpoint: PRs trigger CI and failing tests block merge by default (set branch protection if available).


Task 2: Add linting and type checks

Goal: Integrate linters (flake8/black) and optional type checks (mypy) into CI.

Hands-on lab

# Add to requirements-dev.txt

flake8==5.0.4

black==23.1.0

mypy==1.2.0

# Update workflow steps

- name: Lint

run: |

pip install -r requirements-dev.txt

black --check .

flake8

mypy .

Exercises

  1. Fail the workflow on lint errors and suggest fixes in PR comments using an action. (Medium)
  2. Auto-format with black in a separate workflow on push to a dev branch. (Medium)

Checkpoint: Lint and type checks run in CI; PRs with style issues fail the check.


Task 3: Build and publish a Docker image

Goal: Build an image on merge to main and push to Docker Hub or GitHub Packages.

Hands-on lab

  1. Create a Dockerfile at repo root (simple example for Flask)
    FROM python:3.10-slim
    WORKDIR /app
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    COPY . .
    CMD ["gunicorn","-w","2","-b","0.0.0.0:8080","app:app"]
  2. Add workflow steps to build and push (example uses Docker Hub secrets DOCKERHUB_USERNAME and DOCKERHUB_TOKEN)

    - name: Log in to Docker Hub

    uses: docker/login-action@v2

    with:

    username: ${{ secrets.DOCKERHUB_USERNAME }}

    password: ${{ secrets.DOCKERHUB_TOKEN }}

    - name: Build and push

    uses: docker/build-push-action@v4

    with:

    push: true

    tags: ${{ secrets.DOCKERHUB_USERNAME }}/my-app:${{ github.sha }}

Exercises

  1. Tag images with semantic versions using git tags. (Medium)
  2. Scan images for vulnerabilities using a security scanner action and fail on high severity. (Medium)

Checkpoint: A new image is visible in the registry after merging to main.


Task 4: Deploy the built image to a host

Goal: Automate deployment of the image to a host such as Render, Heroku (container registry), or a simple VM via SSH.

Hands-on lab (using Render/Heroku as example)

  1. For Render: connect repo, set service as "Web Service" and pick the Docker build option; alternatively configure the Render deploy step to pull image from Docker Hub.
  2. For Heroku Container Registry:

    - name: Deploy to Heroku

    uses: akhileshns/heroku-deploy@v3.12.12

    with:

    heroku_api_key: ${{ secrets.HEROKU_API_KEY }}

    heroku_app_name: 'my-app'

    dockerfile_path: './Dockerfile'

Exercises

  1. Implement a blue-green deployment using two services and a swap step. (Hard)
  2. Notify Slack on successful deploy with an action and include changelog summary. (Medium)

Checkpoint: Merging to main triggers a deploy and the live site shows the new version tag or commit SHA.


Testing & Assessment rubric

  • Workflow correctness (40%): workflows trigger as specified and complete successfully.
  • Reproducibility (25%): others can run the same repo locally and in CI using documented steps.
  • Security & Secrets (15%): sensitive info stored as secrets, images scanned if required.
  • Extras (20%): tagging, notifications, performance of deploys.

Sample solution sketches

See solutions/ci branch: contains one workflow for PR tests + lint + matrix; a "release" workflow that builds, tags by semver (when tag pushed), pushes image to Docker Hub, and triggers a simple deploy job.

Alternative languages & trade-offs

  • Node.js: use npm test and a Node matrix. Docker image build is similar; watch for differing base images.
  • Go: single static binary image reduces attack surface and build time in CI.

Recommended tooling & reading

  • GitHub Actions docs, docker/build-push-action, docker/login-action
  • Security scanning: Trivy, Snyk
  • Optional: Dependabot, Renovate for dependency updates

Common stumbling blocks & debugging hints

  • Secrets missing: check repo settings and ensure names match in workflow.
  • Runner caching: use actions/cache for pip/npm to speed CI.
  • Auth failures to registry: verify token permissions and correct registry URL.

Accessibility considerations

  • Include captions/transcripts for demo screencasts and use alt text for images in READMEs.
  • Provide command-line outputs in text form for screen readers.

Finish this mini-project by writing a short onboarding doc that explains how CI/CD is organized in your repo and lists how to roll back a bad deployment (30–60 minutes). That document makes an excellent interview- or onboarding artifact.

Related Posts