Introduction to GitHub Actions
In our previous lecture, we explored the fundamental concepts of CI/CD. Today, we'll dive deeper into GitHub Actions, a powerful CI/CD platform built directly into GitHub repositories. GitHub Actions allows developers to automate workflows directly in their GitHub repositories, making it an excellent choice for implementing continuous integration pipelines.
GitHub Actions has gained significant popularity since its introduction due to its tight integration with GitHub repositories, extensive marketplace of pre-built actions, and flexible configuration options. In this lecture, we'll learn how to use GitHub Actions to create effective CI pipelines for your projects.
GitHub Actions in the CI/CD Ecosystem
GitHub Actions Key Concepts
Before diving into implementation details, let's understand the key components that make up GitHub Actions:
Workflows
A workflow is an automated process that you set up in your repository to build, test, package, release, or deploy your code. Workflows are defined in YAML files stored in the .github/workflows directory of your repository. A repository can have multiple workflows, each handling different aspects of your automation needs.
Events
Events are specific activities that trigger a workflow. For example, a workflow can be triggered when someone pushes code to a repository, opens a pull request, creates an issue, or based on a schedule. You can configure workflows to run for one or multiple events.
Common Trigger Events:
- push: When commits are pushed to the repository
- pull_request: When a pull request is opened, updated, or closed
- schedule: At a scheduled time
- workflow_dispatch: Manual trigger via GitHub UI
- repository_dispatch: External event via API call
Jobs
A job is a set of steps that execute on the same runner (a virtual machine). Jobs can run independently of each other or sequentially, depending on how they're configured. You can set up dependencies between jobs, so one job waits for another to complete before it starts.
Steps
A step is an individual task that can run commands or actions. Each job consists of one or more steps that are executed in order. Steps can run commands, setup tasks, or run an action.
Actions
Actions are reusable units of code that can be used in your workflows. Think of them as building blocks that you can combine to create custom workflows. Actions can be created by GitHub, by the community, or you can create your own.
Runners
A runner is a server that runs your workflows when they're triggered. Each runner can run a single job at a time. GitHub provides runners for Linux, Windows, and macOS, or you can host your own runners.
GitHub Actions Components
Creating Your First GitHub Actions Workflow
Let's create a simple CI workflow for a JavaScript project using GitHub Actions. This workflow will run whenever code is pushed to the repository or when a pull request is created. It will install dependencies, run linting, and execute tests.
Step 1: Create the Workflow File
In your repository, create a new file at .github/workflows/ci.yml with the following content:
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linting
run: npm run lint
- name: Run tests
run: npm test
Breaking Down the Workflow
Let's analyze each part of this workflow:
Workflow Name
name: CI
This sets the name of the workflow, which will be displayed in the GitHub UI.
Triggers
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
This configures the workflow to run on two events: when code is pushed to the main branch, and when a pull request targeting the main branch is created or updated.
Jobs
jobs:
build:
runs-on: ubuntu-latest
This defines a job named "build" that will run on the latest Ubuntu runner provided by GitHub.
Steps
steps:
- uses: actions/checkout@v3
The first step uses the checkout action to clone the repository code to the runner.
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
This step sets up Node.js on the runner, using version 18, and configures caching for npm packages to speed up future runs.
- name: Install dependencies
run: npm ci
This step installs the project dependencies using npm ci, which is a faster and more reliable way to install dependencies in CI environments than npm install.
- name: Run linting
run: npm run lint
This step runs the linting command defined in the project's package.json file.
- name: Run tests
run: npm test
This step executes the project's tests using the test command defined in the package.json file.
Advanced Workflow Configurations
Now that we understand the basics, let's explore some more advanced configurations that can make our CI workflows more powerful and efficient.
Matrix Builds
Matrix builds allow you to test your code against multiple versions of languages, operating systems, or other dependencies. This is useful for ensuring your code works across different environments.
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
node-version: [16.x, 18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
This workflow will run tests on 9 different combinations: 3 operating systems × 3 Node.js versions.
Workflow Dependencies
You can create dependencies between jobs to control the execution order. This is useful when one job depends on the output of another.
name: CI
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build-artifacts
path: build/
test:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: build-artifacts
path: build/
- name: Run tests
run: npm test
In this example, the test job will only run after the build job has successfully completed. The build artifacts are passed between jobs using the upload-artifact and download-artifact actions.
Conditional Execution
You can use conditions to control whether a job or step should run. This is useful for creating workflows that behave differently based on the event that triggered them.
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Build
run: npm run build
- name: Deploy to production
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
run: |
echo "Deploying to production..."
# Add deployment commands here
In this example, the deployment step will only run when code is pushed to the main branch, not when a pull request is created or updated.
Environment Variables
You can use environment variables to pass data between steps or to configure your workflow.
name: CI
on:
push:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
env:
NODE_ENV: production
API_URL: https://api.example.com
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Set build version
run: echo "BUILD_VERSION=$(date +'%Y.%m.%d.%H%M%S')" >> $GITHUB_ENV
- name: Build with version
run: |
echo "Building version: $BUILD_VERSION"
npm run build
env:
DEBUG: false
This workflow sets environment variables at different levels:
- Job-level environment variables (
NODE_ENVandAPI_URL) - Step-level environment variables (
DEBUG) - Dynamic environment variables set during workflow execution (
BUILD_VERSION)
Managing Secrets in GitHub Actions
Many CI/CD workflows require access to sensitive information such as API keys, passwords, or tokens. GitHub Actions provides a secure way to store and use these secrets without exposing them in your workflow files.
Adding Secrets to Your Repository
- Go to your repository on GitHub
- Click on "Settings"
- In the left sidebar, click on "Secrets and variables" then "Actions"
- Click on "New repository secret"
- Enter a name for your secret (e.g.,
API_KEY) and its value - Click "Add secret"
Using Secrets in Workflows
Once you've added a secret to your repository, you can use it in your workflows using the secrets context:
name: Deploy
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to server
uses: some-deploy-action@v1
with:
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.SERVER_PASSWORD }}
host: ${{ secrets.SERVER_HOST }}
- name: API authentication
run: |
curl -H "Authorization: Bearer ${{ secrets.API_KEY }}" https://api.example.com/deploy
⚠️ Security Warning
Always be careful when working with secrets:
- Never print secrets in logs (even masked, they can be reconstructed)
- Limit secret access to only the steps that need them
- Be cautious with third-party actions that might access your secrets
- Rotate secrets regularly
Leveraging the GitHub Actions Marketplace
One of the biggest advantages of GitHub Actions is the vast ecosystem of pre-built actions available in the GitHub Marketplace. These actions can save you time and effort by providing ready-to-use functionality for common CI/CD tasks.
Finding Actions in the Marketplace
- Go to the GitHub Marketplace
- Browse or search for actions relevant to your needs
- Click on an action to view its documentation and usage examples
- Incorporate the action into your workflow using the
useskeyword
Popular Actions for CI Workflows
Checkout
Checks out your repository so your workflow can access it.
- uses: actions/checkout@v3
Setup Node.js
Sets up a Node.js environment.
- uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
Cache
Caches dependencies and build outputs to improve workflow execution time.
- uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
Upload/Download Artifacts
actions/upload-artifact and actions/download-artifact
Share data between jobs or store outputs for later use.
- uses: actions/upload-artifact@v3
with:
name: build-artifacts
path: build/
CodeQL Analysis
Performs security analysis of your code.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: javascript
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
Optimizing CI Workflows
As your projects grow, optimizing your CI workflows becomes increasingly important to maintain fast feedback cycles and efficient resource usage.
Caching Dependencies
Caching dependencies can significantly reduce workflow execution time by reusing previously downloaded packages.
- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
💡 Pro Tip
Many setup actions (like actions/setup-node) include built-in caching capabilities. Use these when available for simpler workflows.
Selective Testing
Run tests only when relevant files have changed to save time in large projects.
name: CI
on:
push:
paths:
- 'src/**'
- 'tests/**'
- 'package.json'
- 'package-lock.json'
- '.github/workflows/**'
Parallel Jobs
Split large test suites into parallel jobs to reduce overall execution time.
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
shard: [1, 2, 3, 4]
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests (shard ${{ matrix.shard }}/4)
run: npm test -- --shard=${{ matrix.shard }}/4
Workflow Concurrency
Limit concurrent workflow runs to prevent resource contention and unnecessary executions.
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# Cancel in-progress runs when a new workflow with the same concurrency group is triggered
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
# ...
Advanced CI Patterns with GitHub Actions
Let's explore some advanced CI patterns that can be implemented with GitHub Actions to enhance your development workflow.
PR Checks and Status Reporting
GitHub Actions automatically reports the status of workflow runs on pull requests, but you can enhance this with more detailed checks.
name: PR Checks
on:
pull_request:
branches: [ main ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linting
run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
This workflow creates three separate jobs (lint, test, build) that run in parallel, providing more granular status reporting on pull requests.
Code Coverage Reporting
Integrate code coverage reporting into your CI workflow to track test coverage over time.
name: CI with Coverage
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests with coverage
run: npm test -- --coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
Scheduled Security Scans
Run security scans on a regular schedule to identify vulnerabilities.
name: Security Scan
on:
schedule:
# Run at 1:00 AM every day
- cron: '0 1 * * *'
workflow_dispatch:
jobs:
security-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run security audit
run: npm audit --audit-level=high
- name: Run SAST scan
uses: github/codeql-action/analyze@v2
with:
languages: javascript
Automated Dependency Updates
Use GitHub's Dependabot to automatically create pull requests for dependency updates.
.github/dependabot.yml
version: 2
updates:
# Enable version updates for npm
- package-ecosystem: "npm"
# Look for `package.json` and `lock` files in the `root` directory
directory: "/"
# Check for updates once a week
schedule:
interval: "weekly"
# Limit the number of open PRs
open-pull-requests-limit: 10
Real-World Example: Complete CI Pipeline
Let's put everything together and create a comprehensive CI pipeline for a modern JavaScript application.
.github/workflows/ci.yml
name: CI Pipeline
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
# Cancel in-progress runs on new pushes
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Lint code
run: npm run lint
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Set up Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests with coverage
run: npm test -- --coverage
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run security audit
run: npm audit --audit-level=high
- name: Run SAST scan
uses: github/codeql-action/init@v2
with:
languages: javascript
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
build:
needs: [lint, test, security]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build-artifacts
path: build/
deploy-staging:
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: [build]
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v3
- name: Download build artifacts
uses: actions/download-artifact@v3
with:
name: build-artifacts
path: build/
- name: Deploy to staging
run: |
echo "Deploying to staging environment..."
# Add deployment commands here
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
This comprehensive CI pipeline includes:
- Linting for code quality
- Testing across multiple Node.js versions
- Security scanning with npm audit and CodeQL
- Building the application
- Deploying to a staging environment (when pushing to main)
- Concurrency control to cancel redundant runs
- Code coverage reporting
- Environment separation for deployment
Using Self-Hosted Runners
While GitHub-hosted runners are convenient, there are cases where you might want to use self-hosted runners:
- Need for specific hardware configurations
- Access to internal resources (behind a firewall)
- Larger disk space or memory requirements
- Custom software requirements
Setting Up a Self-Hosted Runner
- Go to your repository on GitHub
- Click on "Settings"
- In the left sidebar, click on "Actions" then "Runners"
- Click "New self-hosted runner"
- Choose your operating system and architecture
- Follow the instructions to download, configure, and run the runner
Using Self-Hosted Runners in Workflows
name: CI on Self-Hosted Runner
on:
push:
branches: [ main ]
jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v3
- name: Build
run: ./build.sh
⚠️ Security Considerations
When using self-hosted runners, be aware of the following security considerations:
- Runners have access to their environment, including network, disk, and other resources
- Public repositories can submit pull requests that execute code on your self-hosted runners
- Malicious code in a workflow could compromise the runner environment
For these reasons, it's recommended to only use self-hosted runners with private repositories or with careful security controls in place.
Debugging GitHub Actions Workflows
When your workflows don't run as expected, here are some strategies for debugging:
Enabling Debug Logging
You can enable debug logging to get more detailed information about workflow execution:
- Set the
ACTIONS_RUNNER_DEBUGsecret totruein your repository - Set the
ACTIONS_STEP_DEBUGsecret totruein your repository
Adding Diagnostic Steps
Add diagnostic steps to your workflow to print information about the environment:
- name: Debug info
run: |
echo "GitHub ref: ${{ github.ref }}"
echo "GitHub event name: ${{ github.event_name }}"
echo "GitHub workspace: ${{ github.workspace }}"
echo "Job status: ${{ job.status }}"
ls -la
env
Using the GitHub CLI
The GitHub CLI can be useful for debugging workflows:
# List workflow runs
gh run list
# View details of a specific run
gh run view RUN_ID
# View logs of a specific run
gh run view RUN_ID --log
# Download logs
gh run download RUN_ID
Common Issues and Solutions
| Issue | Possible Causes | Solutions |
|---|---|---|
| Workflow not triggering |
|
|
| Steps failing |
|
|
| Slow workflows |
|
|
GitHub Actions Best Practices
To get the most out of GitHub Actions, follow these best practices:
Keep Workflows Simple and Focused
Create multiple workflows for different purposes rather than one large workflow that does everything. This makes maintenance easier and allows for more targeted executions.
Use Reusable Workflows
Extract common job patterns into reusable workflows to reduce duplication and improve maintainability.
.github/workflows/reusable-build.yml
name: Reusable build workflow
on:
workflow_call:
inputs:
node-version:
required: false
default: '18'
type: string
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: ${{ inputs.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
Using the reusable workflow
name: CI
on:
push:
branches: [ main ]
jobs:
call-build-workflow:
uses: ./.github/workflows/reusable-build.yml
with:
node-version: '20'
Pin Action Versions
Always pin actions to a specific version (preferably a SHA) to ensure consistent behavior and prevent unexpected changes.
# Good: Pinned to a specific version
- uses: actions/checkout@v3.5.3
# Better: Pinned to a specific SHA
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608
# Avoid: Using 'latest' or 'master'
- uses: actions/checkout@master # Not recommended
Minimize Secrets Usage
Limit the use of secrets to only the steps that need them, and use the least privileged tokens possible.
Implement Proper Error Handling
Use conditional steps and error handling to make workflows more robust.
- name: Build
id: build
continue-on-error: true
run: npm run build
- name: Notify on build failure
if: steps.build.outcome == 'failure'
run: |
echo "Build failed, sending notification..."
# notification logic here
Optimize for Speed
Implement caching, parallelize jobs, and use efficient testing strategies to keep workflows fast.
Document Workflows
Use comments and descriptive names for workflows, jobs, and steps to make them easier to understand and maintain.
name: CI Pipeline
# This workflow handles continuous integration for the project
# It runs linting, testing, and building on pushes to main and pull requests
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
# Run linting to ensure code quality
lint:
# ...
Practical Activity: Creating a CI Pipeline with GitHub Actions
Now it's time to apply what you've learned by creating a CI pipeline for a real project using GitHub Actions.
Prerequisites
- A GitHub account
- A JavaScript project repository (we'll use a React app for this example)
Step 1: Create a React Application
If you don't already have a React project, create one and push it to GitHub:
# Create a new React app
npx create-react-app my-ci-project
# Initialize Git repository
cd my-ci-project
git init
git add .
git commit -m "Initial commit"
# Create a repository on GitHub and push to it
git remote add origin https://github.com/yourusername/my-ci-project.git
git push -u origin main
Step 2: Create a Basic CI Workflow
Create a GitHub Actions workflow file in your repository:
# Create the workflow directory
mkdir -p .github/workflows
# Create the workflow file
touch .github/workflows/ci.yml
Add the following content to the workflow file:
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test -- --watchAll=false
- name: Build
run: npm run build
Step 3: Commit and Push the Workflow
git add .github/workflows/ci.yml
git commit -m "Add CI workflow"
git push
Step 4: Check Workflow Execution
- Go to your repository on GitHub
- Click on the "Actions" tab
- You should see your workflow running or completed
- Click on the workflow run to see details
Step 5: Enhance the Workflow
Now, enhance your workflow with additional features:
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linting
run: npm run lint
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test -- --watchAll=false --coverage
- name: Upload coverage report
uses: actions/upload-artifact@v3
with:
name: coverage-report
path: coverage/
build:
needs: [lint, test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build
path: build/
Step 6: Create a Branch and Test Pull Request Integration
# Create a new branch
git checkout -b feature/update-readme
# Make a change
echo "# CI Demo" > README.md
# Commit and push
git add README.md
git commit -m "Update README"
git push -u origin feature/update-readme
- Go to your repository on GitHub
- Create a pull request from your feature branch to main
- Observe the CI workflow running on your pull request
- Note how the workflow status is displayed on the pull request
Key Takeaways
- GitHub Actions Integration: GitHub Actions provides a tightly integrated CI/CD platform for GitHub repositories, making it easy to automate workflows directly in your repositories.
- Workflow Flexibility: With YAML-based configuration, GitHub Actions offers flexible workflow definitions that can be tailored to your project's needs.
- Extensive Ecosystem: The GitHub Marketplace provides a vast ecosystem of pre-built actions that can be easily incorporated into your workflows.
- Matrix Builds: Matrix builds enable testing across multiple environments, ensuring compatibility with different platforms and dependencies.
- Performance Optimization: Techniques like caching, selective testing, and parallel jobs can significantly improve workflow performance.
- Security Considerations: GitHub Actions provides secure ways to handle sensitive information through secrets management.
- Advanced Patterns: Advanced patterns like reusable workflows, self-hosted runners, and complex job dependencies enable sophisticated CI/CD pipelines.
Further Resources
Homework Assignment
For your homework, you'll create a comprehensive CI pipeline using GitHub Actions for your own project:
Assignment Requirements
- Choose a project to implement CI:
- Your final project application
- A personal project
- A sample application provided by the instructor
- Create a GitHub Actions workflow that includes:
- Linting for code quality
- Unit and integration tests
- Building the application
- At least two advanced features (matrix builds, caching, artifacts, environment deployments, etc.)
- Create a pull request to demonstrate CI integration:
- Branch from main/master
- Make a small change
- Create a pull request
- Show the CI workflow running on the pull request
- Document your implementation:
- Explain your workflow design
- Describe the advanced features you implemented
- Discuss any challenges you encountered and how you solved them
- Suggest future improvements to your CI pipeline
Submission Guidelines
- Link to your repository with the workflow file
- Link to a successfully completed workflow run
- Link to the pull request showing CI integration
- Documentation of your implementation (1-2 pages)
Due Date
Submit your completed assignment before our next class session.