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 · 12 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