CI/CD with GitHub Actions: Automate Testing and Documentation Deployment
Bonus Workshop - Self-Paced
This is an optional, self-paced workshop. You can complete it at your own speed and refer back to it as needed.
CI/CD Definitions
Continuous Integration (CI) automatically tests your code every time you make changes, catching problems early.
Continuous Deployment (CD) automatically deploys your applications when changes are merged, ensuring your users always have the latest version.
GitHub Actions is GitHub's built-in CI/CD platform that runs workflows when events happen in your repository (like pushes, pull requests, or releases).
Why Use GitHub Actions?
Catch Issues Early: Test every change before it's merged into main Automate Repetitive Tasks: No more manual testing and deployment Consistent Quality: Same checks run for everyone, every time Fast Feedback: Know immediately if your changes break something Always Up-to-Date Docs: Documentation deploys automaticallytip "Bonus Workshop - Self-Paced" This is an optional, self-paced workshop. You can complete it at your own speed and refer back to it as needed.
Learn how to automate code quality checks, testing, and documentation deployment using GitHub Actions - making your development workflow more professional and reliable.
Learning Objectives
- Understand GitHub Actions fundamentals and workflow structure
- Create automated code quality checks with Ruff and pytest
- Set up conditional documentation building and testing
- Automate documentation deployment to GitHub Pages
- Follow CI/CD best practices for Python projects
Why This Matters for RAP
Automated testing and deployment directly supports Silver RAP by ensuring code quality and Gold RAP by automating the publication process. GitHub Actions helps you maintain consistent code standards, catch issues early, and deploy documentation automatically - essential for professional analytical pipelines.
What is CI/CD?
- Continuous Integration (CI) automatically tests your code every time you make changes, catching problems early.
- Continuous Deployment (CD) automatically deploys your applications when changes are merged, ensuring your users always have the latest version.
- GitHub Actions is GitHub's built-in CI/CD platform that runs workflows when events happen in your repository (like pushes, pull requests, or releases).
Why Use GitHub Actions?
- Catch Issues Early: Test every change before it's merged into main
- Automate Repetitive Tasks: No more manual testing and deployment
- Consistent Quality: Same checks run for everyone, every time
- Fast Feedback: Know immediately if your changes break something
- Always Up-to-Date Docs: Documentation deploys automatically
Task 1: Understanding GitHub Actions Structure
Let's start by understanding how GitHub Actions workflows are organized and what we'll build.
1.1 Workflow Structure
GitHub Actions workflows are defined in YAML files stored in .github/workflows/
directory. Each workflow consists of:
- Triggers (when to run): push, pull request, schedule, etc.
- Jobs (what to do): groups of steps that run together
- Steps (individual tasks): run commands, use actions, etc.
1.2 Our CI/CD Strategy
We'll create two workflows following the KISS principle:
┌─────────────────────┐ ┌──────────────────────┐
│ Pull Request │ │ Main Branch │
│ Quality Checks │ │ Documentation │
│ │ │ Deployment │
│ ✓ Code Quality │ │ │
│ ✓ Tests │ │ ✓ Build Docs │
│ ✓ Docs Build │ │ ✓ Deploy to Pages │
└─────────────────────┘ └──────────────────────┘
Workflow 1: Quality Checks (runs on pull requests)
- Code quality with Ruff
- Run pytest test suite
- Test documentation builds (if docs changed)
Workflow 2: Deploy Documentation (runs on main branch) - Build and deploy documentation to GitHub Pages
Task 2: Setting Up Quality Checks Workflow
Let's create our first workflow to automatically check code quality when pull requests are opened.
2.1 Create the Workflows Directory
First, create the directory structure for GitHub Actions:
2.2 Create the Quality Checks Workflow
Create a new file .github/workflows/quality-checks.yml
and choose the version that matches your project setup:
Use this version if you've completed the dependency management workshop:
name: Quality Checks # (1)!
on: # (2)!
pull_request:
branches: [ main ]
push:
branches: [ main ]
jobs:
quality-checks: # (3)!
runs-on: ubuntu-latest # (4)!
steps:
- name: Checkout code # (5)!
uses: actions/checkout@v4
- name: Set up Python # (6)!
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install dependencies # (7)!
run: |
pip install ruff pytest
pip install -e .
- name: Run Ruff linting # (8)!
run: ruff check practice_level_gp_appointments/
- name: Run Ruff formatting check # (9)!
run: ruff format --check practice_level_gp_appointments/
- name: Run pytest # (10)!
run: pytest tests/ -v
docs-check: # (11)!
runs-on: ubuntu-latest
if: contains(github.event.pull_request.changed_files, 'docs/') || github.event_name == 'push' # (12)!
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install dependencies # (13)!
run: |
pip install mkdocs mkdocs-material
pip install -e .
- name: Test documentation build # (14)!
run: mkdocs build --strict
Use this version if you haven't set up pyproject.toml yet:
name: Quality Checks # (1)!
on: # (2)!
pull_request:
branches: [ main ]
push:
branches: [ main ]
jobs:
quality-checks: # (3)!
runs-on: ubuntu-latest # (4)!
steps:
- name: Checkout code # (5)!
uses: actions/checkout@v4
- name: Set up Python # (6)!
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install dependencies # (7)!
run: |
pip install ruff pytest
pip install -r requirements.txt
- name: Run Ruff linting # (8)!
run: ruff check practice_level_gp_appointments/
- name: Run Ruff formatting check # (9)!
run: ruff format --check practice_level_gp_appointments/
- name: Run pytest # (10)!
run: pytest tests/ -v
docs-check: # (11)!
runs-on: ubuntu-latest
if: contains(github.event.pull_request.changed_files, 'docs/') || github.event_name == 'push' # (12)!
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install dependencies # (13)!
run: |
pip install mkdocs mkdocs-material
pip install -r requirements.txt
- name: Test documentation build # (14)!
run: mkdocs build --strict
- Workflow name - appears in GitHub Actions UI
- Triggers - when this workflow runs (pull requests and pushes to main)
- First job - runs code quality checks
- Runner environment - uses latest Ubuntu (free for public repos)
- Checkout step - downloads your repository code
- Python setup - installs Python 3.12
- Dependencies - installs tools and your project dependencies
- Linting - checks code quality with Ruff
- Formatting - ensures consistent code formatting
- Testing - runs the test suite with pytest
- Second job - checks documentation building
- Conditional execution - only runs if docs files changed
- Documentation dependencies - installs MkDocs and your package
- Documentation test - ensures docs build without errors
2.3 Understanding the Workflow
Let's break down what this workflow does:
Two Separate Jobs
We split this into two jobs that run in parallel:
quality-checks
- Always runs, checks code and testsdocs-check
- Only runs if documentation files changed
This saves time and resources when you're only changing code (not docs).
Why --strict
for MkDocs?
The --strict
flag makes MkDocs fail if there are any warnings. This catches issues like:
- Broken internal links
- Missing pages in navigation
- Invalid markdown syntax
- Plugin configuration errors
Task 3: Creating the Documentation Deployment Workflow
Now let's create a workflow that automatically deploys documentation to GitHub Pages when changes are merged to main.
3.1 Create the Deployment Workflow
Create .github/workflows/deploy-docs.yml
:
name: Deploy Documentation # (1)!
on: # (2)!
push:
branches: [ main ]
paths: [ 'docs/**', 'mkdocs.yml', 'pyproject.toml' ]
permissions: # (3)!
contents: write
jobs:
deploy-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout code # (4)!
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python # (5)!
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install dependencies # (6)!
run: |
pip install mkdocs mkdocs-material
pip install -e .
- name: Deploy to GitHub Pages # (7)!
run: mkdocs gh-deploy --force
name: Deploy Documentation # (1)!
on: # (2)!
push:
branches: [ main ]
paths: [ 'docs/**', 'mkdocs.yml', 'requirements.txt' ]
permissions: # (3)!
contents: write
jobs:
deploy-docs:
runs-on: ubuntu-latest
steps:
- name: Checkout code # (4)!
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python # (5)!
uses: actions/setup-python@v4
with:
python-version: '3.12'
- name: Install dependencies # (6)!
run: |
pip install mkdocs mkdocs-material
pip install -r requirements.txt
- name: Deploy to GitHub Pages # (7)!
run: mkdocs gh-deploy --force
- Deployment workflow - focuses only on publishing documentation
- Specific triggers - only runs when docs-related files change on main
- Permissions - only needs write access to push to gh-pages branch
- Full git history - fetch-depth: 0 gets complete history for gh-deploy
- Python setup - installs Python 3.12
- Install dependencies - gets MkDocs and your project dependencies
- Deploy with MkDocs - builds and deploys to GitHub Pages in one command
3.2 Configure GitHub Pages
Skip This Step If...
If you've already completed the MkDocs Documentation workshop, you can skip this step as GitHub Pages is already configured for your repository.
If you haven't set up GitHub Pages yet, you need to configure it to serve from the gh-pages branch:
- Go to your repository on GitHub
- Click Settings tab
- Scroll down to Pages section
- Under "Source" select "Deploy from a branch"
- Choose "gh-pages" branch and "/ (root)" folder
- Click Save
No gh-pages Branch Yet?
Don't worry! The mkdocs gh-deploy
command will create the gh-pages branch automatically on first deployment. GitHub Pages will show an error until we deploy for the first time.
Task 4: Testing Your Workflows
Now let's test both workflows to make sure they work correctly.
4.1 Test the Quality Checks Workflow
First, let's test the quality checks by creating a pull request:
# Create a new branch
git checkout -b test-github-actions
# Add the workflow files
git add .github/workflows/
# Commit the changes
git commit -m "feat: add GitHub Actions workflows for CI/CD
- Add quality checks workflow for pull requests
- Add documentation deployment workflow
- Includes code linting, testing, and docs building"
# Push the branch
git push origin test-github-actions
Now create a pull request on GitHub:
- Go to your repository on GitHub
- Click "Compare & pull request"
- Add a title: "Add GitHub Actions CI/CD workflows"
- Add a description explaining what you've added
- Click "Create pull request"
Watch It Work
After creating the pull request, you should see the GitHub Actions workflows start running automatically. Click on the "Checks" tab to see the progress.
4.2 Trigger a Documentation Deployment
Once your pull request is merged, test the documentation deployment:
# Switch back to main and pull the changes
git checkout main
git pull origin main
# Make a small change to documentation
echo "This page was last updated: $(date)" >> docs/content/index.md
# Commit and push
git add docs/content/index.md
git commit -m "docs: add last updated timestamp"
git push origin main
This should trigger the documentation deployment workflow automatically.
4.3 Verify Everything Works
Check that both workflows are working:
- Go to Actions tab in your GitHub repository
- Verify quality checks ran on your pull request
- Verify docs deployment ran when you pushed to main
- Check your GitHub Pages site is updated
Your documentation should be available at: https://YOUR-USERNAME.github.io/package-your-code-workshop
Task 5: Understanding and Debugging Workflow Results
Let's learn how to interpret workflow results and debug issues when they occur.
5.1 Reading Workflow Status
After your workflows run, GitHub Actions provides clear visual indicators in the repository:
- Navigate to the Actions tab in your GitHub repository
- Look at the workflow status icons next to each workflow run
- Click on any workflow to see detailed results
Green checkmark - All checks passed
Your workflow completed successfully. All tests passed, code quality checks passed, and any deployment steps succeeded.
Red X - Something failed
One or more steps in your workflow failed. Click on the workflow to see which step failed and why.
Yellow dot - Workflow is running
Your workflow is currently executing. You can click to watch the progress in real-time.
Gray circle - Workflow was skipped
The workflow didn't run, usually because the trigger conditions weren't met (e.g., no documentation files changed).
5.2 Debug a Failed Workflow
When a workflow fails, follow these steps to identify and fix the problem:
- Click on the failed workflow in the Actions tab
- Click on the failed job (it will have a red X icon)
- Expand the failed step to see the detailed error output
- Look for the actual error message (often at the bottom of the log)
Common Issues and Fixes
Ruff linting fails:
# Fix locally first
ruff check practice_level_gp_appointments/ --fix
ruff format practice_level_gp_appointments/
git commit -am "fix: resolve linting issues"
Tests fail:
Documentation build fails:
5.3 Add Workflow Status Badges
Status badges show the current state of your workflows directly in your README:
- Open your README.md file
- Add badge markdown at the top of the file:
# Package Your Code Workshop


Your workshop description here...
Why Use Badges?
Status badges provide immediate visual feedback about your project's health. They show visitors whether your tests are passing and if your documentation is building successfully.
Best Practices for CI/CD
Workflow Organization
Keep It Simple
Do: - ✅ One purpose per workflow - separate quality checks from deployment - ✅ Descriptive names - "Quality Checks", not "CI" - ✅ Conditional execution - only run what's needed - ✅ Fast feedback - fail fast on code quality issues
Don't: - ❌ Monolithic workflows - one massive workflow that does everything - ❌ Unnecessary runs - testing docs when only code changed - ❌ Silent failures - always check workflow results
Security Best Practices
Security Considerations
Permissions:
- Only grant the minimum permissions needed
- Use contents: read
by default
- Only add pages: write
for deployment workflows
Secrets: - Never commit API keys or passwords - Use GitHub repository secrets for sensitive data - Prefer GitHub's built-in authentication when possible
Resource Management
GitHub Actions Limits
Public repositories get: - ✅ Unlimited minutes for public repos - ✅ 2,000 minutes/month for private repos (free tier)
Best practices: - Cache dependencies to speed up builds - Skip unnecessary jobs with conditions - Use matrix builds carefully (they multiply resource usage)
Troubleshooting
Common Workflow Issues
Workflow Not Triggering
Check:
- File is in .github/workflows/
directory
- YAML syntax is correct (use a YAML validator)
- Triggers match your intended events
- Branch names are correct
Permission Denied
For GitHub Pages deployment: - Enable GitHub Pages in repository settings - Set source to "GitHub Actions" - Check workflow permissions section
Dependencies Install Fails
Common fixes: - Ensure pyproject.toml is valid - Check all dependency groups exist - Verify UV installation completed successfully
Debugging Workflow Files
# Validate YAML syntax locally
python -c "import yaml; yaml.safe_load(open('.github/workflows/quality-checks.yml'))"
# Check file encoding (should be UTF-8)
file .github/workflows/quality-checks.yml
Checkpoint
Before finishing this workshop, verify you can:
- Create GitHub Actions workflow files in the correct directory
- Set up automated code quality checks with Ruff and pytest
- Configure conditional documentation building
- Deploy documentation automatically to GitHub Pages
- Understand workflow status and debug failures
- Apply CI/CD best practices to your projects
Next Steps
Congratulations! You've set up professional CI/CD workflows for your Python project.
Your project now automatically:
- ✅ Tests all code changes before they're merged
- ✅ Maintains code quality with automated linting
- ✅ Deploys documentation when changes are made
- ✅ Provides immediate feedback on pull requests
Continue improving your workflows:
- Add more comprehensive tests to your test suite
- Set up notifications for workflow failures
- Create workflows for releasing new versions
- Add security scanning with tools like CodeQL
Explore other workshop topics:
- Dependency Management - Modern Python dependency management
- Packaging with pyproject.toml - Professional Python packaging
- Documentation with MkDocs - Create beautiful documentation
- Pre-Commit Hooks - Catch issues before they reach CI
Additional Resources
GitHub Actions
- GitHub Actions Documentation - Complete official guide
- Workflow Syntax - YAML reference
- GitHub Actions Marketplace - Pre-built actions
- GitHub Actions Examples - Template workflows
CI/CD Best Practices
- CI/CD Best Practices - GitHub's recommendations
- Testing Python Applications - pytest documentation
- Code Coverage - Python coverage measurement
GitHub Pages
- GitHub Pages Documentation - Official GitHub Pages guide
- Custom Domains - Using your own domain
- MkDocs Deployment - MkDocs-specific deployment guide
Security
- Security Hardening - Secure workflow practices
- Encrypted Secrets - Managing sensitive data
- OIDC with GitHub Actions - Advanced authentication