Create a GitHub Account and Set Up SSH Keys (Windows, macOS, Linux)

In this lesson you will create a professional GitHub account, secure it with two-factor authentication, and connect your computer to GitHub with SSH keys, so you can push and pull without typing credentials.

📖 What You’ll Learn: creating and completing a GitHub profile, two-factor authentication, HTTPS vs SSH, generating an ed25519 SSH key, the SSH agent on every operating system, adding the key to GitHub, testing the connection and fixing common SSH errors.


👤 Step 1: Create Your GitHub Account

  1. Go to github.com and click Sign up.
  2. Enter your email, a strong password and a username.
  3. Verify your email address with the code GitHub sends you.
  4. Choose the Free plan. It includes unlimited public and private repositories.

💡 Tip: Choose your username carefully: it appears in your profile URL (github.com/your-username) and in every repository link you share with recruiters. Something like asha-verma-qa looks more professional than coolcoder99.

Complete your profile

  • Add a photo, your name, a short bio (for example “QA Automation Engineer | Playwright | TypeScript”) and your location.
  • Later, create a profile README by making a public repository with the same name as your username; its README appears on your profile page.

🛡️ Step 2: Turn On Two-Factor Authentication (2FA)

GitHub requires two-factor authentication for accounts that contribute code. Set it up early:

  1. Open Settings, Password and authentication.
  2. Enable 2FA with an authenticator app (Google Authenticator, Microsoft Authenticator, Authy) or a passkey.
  3. Download and store your recovery codes in a safe place. They are the only way back in if you lose your phone.

🔐 HTTPS or SSH? How Git Talks to GitHub

When you push or pull, Git must prove who you are. There are two connection types:

HTTPSSSH
Remote URLhttps://github.com/user/repo.gitgit@github.com:user/repo.git
AuthenticationGit Credential Manager (browser sign-in) or a personal access tokenAn SSH key pair on your computer
Setup effortVery low on Windows and macOSOne-time key setup
Works through strict firewallsUsuallySometimes blocked (port 22)
Popular withBeginners, Windows usersDevelopers, Linux users, CI servers

Both are secure. Many developers use SSH so they never type credentials again. The rest of this lesson sets up SSH.


🗝️ Step 3: Check for Existing SSH Keys

Open Git Bash (Windows) or a terminal (macOS, Linux):

ls -al ~/.ssh

If you see id_ed25519 and id_ed25519.pub, you already have a key and can skip to Step 5.


🔑 Step 4: Generate a New SSH Key

ssh-keygen -t ed25519 -C "asha.verma@example.com"
  • Press Enter to accept the default file location (~/.ssh/id_ed25519).
  • Enter a passphrase (recommended) and confirm it.

This creates two files:

FileWhat it isShare it?
~/.ssh/id_ed25519Private keyNever. It stays on your computer
~/.ssh/id_ed25519.pubPublic keyYes, you add it to GitHub

🤖 Step 5: Add the Key to the SSH Agent

The SSH agent remembers your passphrase so you do not type it on every push.

macOS and Linux

eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519

On macOS you can store the passphrase in the Keychain with ssh-add --apple-use-keychain ~/.ssh/id_ed25519.

Windows (PowerShell as Administrator)

Get-Service -Name ssh-agent | Set-Service -StartupType Manual
Start-Service ssh-agent
ssh-add $env:USERPROFILE\.ssh\id_ed25519

☁️ Step 6: Add the Public Key to GitHub

  1. Copy the public key:
# Windows (Git Bash)
clip < ~/.ssh/id_ed25519.pub

# macOS
pbcopy < ~/.ssh/id_ed25519.pub

# Linux: print it and copy from the terminal
cat ~/.ssh/id_ed25519.pub
  1. On GitHub, open Settings, SSH and GPG keys, New SSH key.
  2. Title: something like “Work laptop”. Key type: Authentication Key. Paste the key and click Add SSH key.

✅ Step 7: Test the Connection

ssh -T git@github.com

The first time, type yes to trust GitHub’s host fingerprint. Success looks like:

Hi asha-verma-qa! You've successfully authenticated, but GitHub does not provide shell access.

You can now clone with SSH URLs:

git clone git@github.com:your-username/your-repo.git

Switch an existing repository from HTTPS to SSH:

git remote set-url origin git@github.com:your-username/your-repo.git

Remotes are explained in Remote repositories.


🐞 Troubleshooting

ErrorCause and fix
Permission denied (publickey)Key not added to the agent or GitHub. Run ssh-add -l to list loaded keys and check GitHub Settings, SSH keys
Could not open a connection to your authentication agentStart the agent: eval "$(ssh-agent -s)" (or Start-Service on Windows)
Connection timed out on port 22Firewall blocks SSH. Use HTTPS, or SSH over port 443 with host ssh.github.com
Host key verification failedRemove the old entry with ssh-keygen -R github.com and connect again

📝 Assignment

  1. Create a GitHub account with a professional username and complete your profile.
  2. Enable two-factor authentication and store your recovery codes safely.
  3. Generate an ed25519 SSH key with a passphrase and add it to the SSH agent.
  4. Add the public key to GitHub and confirm with ssh -T git@github.com.
  5. Create an empty public repository called git-practice on GitHub; you will use it in Module 3.

❓ FAQ

🤔 How do I set up an SSH key for GitHub?

Run ssh-keygen -t ed25519 -C "your-email", add the key to the SSH agent with ssh-add, copy the .pub file into GitHub Settings, SSH and GPG keys, then test with ssh -T git@github.com.

🤔 Should I use HTTPS or SSH with GitHub?

Both are secure. HTTPS with Git Credential Manager is easiest for beginners on Windows and macOS. SSH avoids credential prompts and is common on Linux and CI servers.

🤔 Can I use my GitHub password to push code?

No. GitHub requires Git Credential Manager, an SSH key or a personal access token for Git operations.

🤔 Is it safe to share my SSH public key?

Yes. The .pub file is meant to be shared. Never share the private key file without the .pub extension.

🤔 Can I use the same SSH key on several computers?

It is better to create one key per computer. If a laptop is lost, you delete only that key from GitHub.


🎯 Next Steps

🎬 Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

Configure Git: Name, Email, Editor, Default Branch and Aliases

Before your first commit, Git needs to know who you are and how you like to work. In this lesson you will configure Git once, the right way: identity, editor, default branch, line endings, useful defaults and time-saving aliases.

📖 What You’ll Learn: the system, global and local config levels, setting name and email, choosing an editor, the default branch name, line endings with core.autocrlf, useful extras, aliases, viewing and editing config, and credentials for GitHub.


🪪 Why Configure Git?

Every commit records who made it. Before your first commit, Git needs your name and email. A few more settings make Git friendlier: your favourite editor, the default branch name and how line endings are handled. You set these once per computer.


🧩 The Three Configuration Levels

LevelOptionApplies toStored in
System--systemEvery user on the computerGit’s installation folder
Global--globalAll repositories of your user account~/.gitconfig
Local--local (default inside a repo)One repository only.git/config in that repo

The most specific level wins: local overrides global, global overrides system. Most of the time you use --global.


👤 Step 1: Set Your Name and Email

git config --global user.name "Asha Verma"
git config --global user.email "asha.verma@example.com"

💡 Tip: Use the same email as your GitHub account (or GitHub’s private no-reply address, shown in GitHub Settings, Emails). That links your commits to your GitHub profile and contribution graph.

Need a different email for work repositories? Set it locally inside that repository:

cd path/to/work-repo
git config user.email "asha.verma@company.com"

📝 Step 2: Choose Your Editor

Git opens an editor for commit messages, merges and interactive rebases. Set VS Code:

git config --global core.editor "code --wait"

--wait tells Git to wait until you close the editor tab. Other options: "notepad" on Windows, "nano" on Linux and macOS.


🌿 Step 3: Default Branch Name

New repositories should start with main, matching GitHub:

git config --global init.defaultBranch main

↩️ Step 4: Line Endings

Windows and macOS/Linux use different line-ending characters, which can make every line look “changed” in a diff. Configure Git to normalize them:

# Windows
git config --global core.autocrlf true

# macOS and Linux
git config --global core.autocrlf input

For teams, a .gitattributes file in the repository (for example * text=auto) makes this consistent regardless of each person’s settings.


⚙️ Step 5: Useful Extras

git config --global pull.rebase false         # git pull merges (default behaviour, avoids a warning)
git config --global push.autoSetupRemote true # first push of a new branch sets its upstream automatically
git config --global color.ui auto             # coloured output (usually already on)
git config --global fetch.prune true          # remove deleted remote branches on fetch

The pull and push options are explained in fetch vs pull and clone, push and pull.


⌨️ Step 6: Aliases (Shortcuts)

Save typing with aliases:

git config --global alias.st status
git config --global alias.co checkout
git config --global alias.br branch
git config --global alias.cm "commit -m"
git config --global alias.lg "log --oneline --graph --decorate --all"

Now git st runs git status and git lg shows a compact history graph.


🔍 View and Edit Your Configuration

git config --list                     # all settings
git config --list --show-origin       # settings and the file each comes from
git config user.email                 # one setting
git config --global --edit            # open ~/.gitconfig in your editor
git config --global --unset alias.co  # remove a setting

Your global file looks like this:

[user]
	name = Asha Verma
	email = asha.verma@example.com
[core]
	editor = code --wait
	autocrlf = true
[init]
	defaultBranch = main
[alias]
	st = status
	lg = log --oneline --graph --decorate --all

🔐 Credentials for GitHub over HTTPS

When you push over HTTPS, Git needs to authenticate with GitHub. Git for Windows and recent macOS setups use Git Credential Manager, which opens the browser once and stores the token securely. On Linux you can install Git Credential Manager or use SSH keys instead, covered in the next lesson.

⚠️ Common mistake: GitHub does not accept your account password for Git operations. Use Git Credential Manager, SSH keys or a personal access token.


📝 Assignment

  1. Set your global name, email, editor (VS Code), default branch (main) and line-ending setting.
  2. Run git config --list --show-origin and find which file each of your settings is stored in.
  3. Create the aliases st and lg, and test them later in your first repository.
  4. In any repository, set a local email and confirm with git config user.email that it overrides the global one.
  5. Open ~/.gitconfig with git config --global --edit and read through it.

❓ FAQ

🤔 How do I set my username and email in Git?

Run git config --global user.name "Your Name" and git config --global user.email "you@example.com". Check with git config --list.

🤔 How do I change the default branch name to main?

git config --global init.defaultBranch main. New repositories created with git init then start on main.

🤔 Where is the Git config file?

The global file is ~/.gitconfig in your home folder; each repository also has .git/config. Run git config --list --show-origin to see every file in use.

🤔 How do I set VS Code as the Git editor?

git config --global core.editor "code --wait".

🤔 What is core.autocrlf?

It controls line-ending conversion. Use true on Windows and input on macOS and Linux to avoid noisy diffs caused by different line endings.


🎯 Next Steps

🎬 Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

How to Install Git on Windows and Linux (Step by Step)

Before you can use Git, it has to be installed on your computer. This lesson walks you through installing Git on Windows (with the installer or winget) and on the most popular Linux distributions, with the installer options that matter and fixes for common problems.

📖 What You’ll Learn: checking for an existing Git, the Git for Windows installer and its key options, installing with winget, installing on Ubuntu, Fedora, Arch and others, updating Git, and troubleshooting.


✅ Before You Start

Check whether Git is already installed. Open a terminal (Command Prompt, PowerShell or Windows Terminal on Windows; Terminal on Linux) and run:

git --version

If you see something like git version 2.47.1, Git is installed; you can still follow this lesson to update it. If you see “command not found” or “‘git’ is not recognized”, install it now.

On a Mac? Follow Install Git on macOS instead, then continue with Configure Git.


🪟 Install Git on Windows (Installer)

  1. Go to git-scm.com and click Download for Windows. Choose the 64-bit Git for Windows Setup installer.
  2. Run the installer. Most default options are fine; these are the important screens:
Installer screenRecommended choiceWhy
Choosing the default editorVisual Studio Code (or Notepad++)The default, Vim, is hard for beginners
Adjusting the name of the initial branchOverride… and use “main”GitHub uses main as the default branch name
Adjusting your PATH environmentGit from the command line and also from 3rd-party softwareLets you use git in PowerShell, CMD and VS Code
SSH executableUse bundled OpenSSHWorks with the SSH lesson
Line ending conversionsCheckout Windows-style, commit Unix-styleAvoids line-ending problems with teammates on macOS and Linux
Terminal emulatorUse MinTTYBetter Git Bash terminal
Default behaviour of git pullFast-forward or merge (default)Explained in fetch vs pull
Credential helperGit Credential ManagerSigns in to GitHub securely in the browser
  1. Click Install, then Finish.
  2. Open a new terminal and verify:
git --version

⚠️ Common mistake: If git is still “not recognized”, close every terminal and VS Code window and open them again so they pick up the updated PATH. If it still fails, re-run the installer and check the PATH option above.

What did the installer add?

  • Git Bash: a Linux-style terminal for Windows. Commands in this course such as ls, cat and touch work there. See Essential Terminal Commands for Git.
  • Git GUI: a simple graphical tool (rarely needed).
  • Git Credential Manager: stores your GitHub login securely.

⚡ Install Git on Windows with winget

Prefer the command line? Windows 10 and 11 include the winget package manager:

winget install --id Git.Git -e --source winget

Close and reopen the terminal, then run git --version. winget uses the installer defaults, so set the default branch name and editor in the next lesson.


🐧 Install Git on Linux

Use your distribution’s package manager:

# Ubuntu, Debian, Linux Mint
sudo apt update
sudo apt install git

# Fedora
sudo dnf install git

# CentOS Stream, RHEL, Rocky, AlmaLinux
sudo dnf install git

# Arch Linux, Manjaro
sudo pacman -S git

# openSUSE
sudo zypper install git

Verify:

git --version

📝 Note: Distribution packages can be a few versions behind the latest Git release. That is fine for this course. On Ubuntu you can get newer versions from the official Git PPA: sudo add-apt-repository ppa:git-core/ppa, then sudo apt update && sudo apt install git.


🔄 Updating Git Later

PlatformUpdate command
Windows (Git for Windows 2.16.1 or newer)git update-git-for-windows
Windows (winget)winget upgrade --id Git.Git
Ubuntu or Debiansudo apt update && sudo apt install --only-upgrade git
Fedorasudo dnf upgrade git

🐞 Troubleshooting

ProblemFix
'git' is not recognized on WindowsReopen the terminal; re-run the installer with the PATH option “from the command line and also from 3rd-party software”
VS Code does not find GitRestart VS Code; check Settings, git.path
Permission denied on LinuxUse sudo for the install command
Old version on LinuxUse the distribution’s backports or the Git PPA (Ubuntu)
Corporate proxy blocks downloadsAsk IT for the approved installer, or download on another network

📝 Assignment

  1. Install Git on your computer and paste the output of git --version into a notes file.
  2. On Windows, open Git Bash and run pwd, ls and cd ~. What does each command show?
  3. Open VS Code, open any folder, and check that the Source Control panel (Ctrl + Shift + G) no longer says Git is missing.
  4. Write down which line-ending option you chose during installation, and why it matters for teams.

❓ FAQ

🤔 How do I install Git on Windows?

Download Git for Windows from git-scm.com, run the installer (choose VS Code as editor, “main” as the default branch and the recommended PATH option), then check git --version in a new terminal. Or run winget install --id Git.Git -e --source winget.

🤔 How do I install Git on Ubuntu?

Run sudo apt update and sudo apt install git, then verify with git --version.

🤔 How do I check if Git is installed?

Open a terminal and run git --version. If it prints a version number, Git is installed.

🤔 What is Git Bash?

A terminal installed with Git for Windows that supports Linux-style commands such as ls, cat and rm, which makes following Git tutorials easier on Windows.

🤔 Do I need a GitHub account to install Git?

No. Git works without an account. You will create a GitHub account in Lesson 6 to share your repositories online.


🎯 Next Steps

🎬 Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

What Is Git and GitHub? Version Control Explained for Beginners

Welcome to Lesson 1 of the free Git and GitHub tutorial. Before typing any commands, you will understand what version control is, what Git and GitHub each do, how they differ, and the key words used throughout the course.

📖 What You’ll Learn: the problem version control solves, what Git is, what GitHub adds, Git vs GitHub, key terms (repository, commit, branch, merge, remote, pull request), the basic workflow, and why Git matters for testers.


🗂️ The Problem Git Solves

Have you ever had files like these?

test-plan.docx
test-plan-final.docx
test-plan-final-v2.docx
test-plan-final-v2-REALLY-FINAL.docx

That is “version control” done by hand: hard to compare, easy to overwrite, and impossible to share safely with a team. Software projects have the same problem on a much bigger scale: hundreds of files, many people editing them at the same time, and the need to know who changed what, when and why.

Version control software solves this. It records every change to your files as a series of snapshots, lets you go back to any earlier version, and lets several people work on the same project without overwriting each other.


🧠 What Is Git?

Git is the world’s most widely used version control system. It is free, open source, and runs on your own computer.

  • Created in 2005 by Linus Torvalds, the creator of Linux, to manage the Linux kernel’s source code.
  • Distributed: every developer has a full copy of the project and its complete history, so you can work offline and nothing depends on a single server.
  • Fast: most operations (commit, branch, view history) happen locally in milliseconds.
  • Safe: every snapshot is identified by a cryptographic hash, so history cannot be silently corrupted.

With Git you can:

  • Save snapshots of your project (commits) with a message explaining the change.
  • See exactly what changed between any two versions.
  • Work on new features in isolated branches and merge them when ready.
  • Undo mistakes, even days later.

☁️ What Is GitHub?

GitHub is an online platform that hosts Git repositories and adds tools for working together. It launched in 2008 and has been owned by Microsoft since 2018. It is the largest home of open-source code in the world.

GitHub adds what Git alone does not have:

GitHub featureWhat it gives you
Remote repositoriesA shared copy of your project in the cloud
Pull requestsPropose, discuss and review changes before merging
Issues and ProjectsTrack bugs, tasks and plans
GitHub ActionsAutomatically build, test and deploy (CI/CD)
GitHub PagesHost websites for free
Security toolsDependabot alerts, secret scanning, code scanning
ProfilesShow your work to recruiters and the community

⚖️ Git vs GitHub: The Key Difference

GitGitHub
What it isVersion control softwareA website and service that hosts Git repositories
Where it runsOn your computerIn the cloud (github.com)
Needs internetNoYes
Made byLinus Torvalds and the open-source communityGitHub Inc., owned by Microsoft
CostFree and open sourceFree plans, plus paid plans for teams and enterprises
AlternativesMercurial, SVN (older)GitLab, Bitbucket, Azure DevOps Repos

💡 Tip: An easy way to remember it: Git is the tool, GitHub is the place where you share what the tool tracks. You can use Git without GitHub, but GitHub is built around Git.


📚 Key Words You Will Meet in This Course

TermMeaning
Repository (repo)A project folder tracked by Git, including its full history
CommitA saved snapshot of your changes, with a message and an author
BranchAn independent line of work, e.g. a new feature
MergeCombining the changes from one branch into another
RemoteA copy of the repository on a server, such as GitHub
CloneDownloading a full copy of a remote repository
Push / PullSending your commits to the remote / getting others’ commits
Pull request (PR)A GitHub request to review and merge a branch
HEADA pointer to the commit you are currently on

🔄 How a Typical Workflow Looks

 Your computer                                         GitHub
┌──────────────────────────────────────────┐       ┌──────────────┐
│ Working folder → Staging area → Local repo │ push  │ Remote repo  │
│   (edit)         (git add)     (git commit)│ ────▶ │  (shared)    │
│                                            │ ◀──── │              │
└──────────────────────────────────────────┘ pull  └──────────────┘
  1. You edit files in your working folder.
  2. You choose which changes to save with git add (the staging area).
  3. You save a snapshot with git commit.
  4. You push commits to GitHub so others can see them, and pull their changes.

Each step has its own lesson in Modules 2 and 3.


🧪 Why Testers and QA Engineers Need Git

  • Automation frameworks, test data and CI pipelines all live in Git repositories.
  • Tests run automatically in GitHub Actions on every pull request (see Run Playwright tests in GitHub Actions).
  • Reviewing developers’ pull requests helps you test earlier.
  • Git and GitHub questions appear in almost every QA automation and SDET interview.

📝 Assignment

  1. In your own words, explain the difference between Git and GitHub to a friend in three sentences.
  2. List three problems in your current work (or studies) that version control would solve.
  3. Visit github.com/explore and find one open-source project related to testing. Note its number of stars, contributors and the date of its last commit.
  4. Write down the meaning of: repository, commit, branch, merge, push and pull.

❓ FAQ

🤔 What is Git in simple words?

Git is free software that keeps a complete history of changes to your project’s files, so you can see what changed, go back to earlier versions and work on several changes in parallel.

🤔 What is the difference between Git and GitHub?

Git is version control software that runs on your computer. GitHub is a website that hosts Git repositories online and adds collaboration features such as pull requests, issues and GitHub Actions.

🤔 Is Git free?

Yes. Git is free and open source. GitHub also has a free plan with unlimited public and private repositories.

🤔 Can I use Git without GitHub?

Yes. Git works fully on your own computer. You only need GitHub (or GitLab, Bitbucket) to share repositories and collaborate online.

🤔 Who uses Git?

Almost every software team, from startups to Microsoft and Google, as well as testers, DevOps engineers, data scientists and technical writers.


🎯 Next Steps

🎬 Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

Github Action Example Pipeline

1. Git & GitHub Fundamentals

GitHub Actions relies on Git object mechanics. Workflows are declared as code and committed directly to your repository inside the .github/workflows/ directory. GitHub observes changes to Git references (refs/heads/<branch>, refs/tags/<tag>, refs/pull/<number>/merge) to evaluate trigger rules.

How Git Mechanics Map to Actions

  • Commits & Pushes: Every git push transmits a SHA hash and branch ref that GitHub Actions uses to check out the exact state of your code.
  • Pull Requests: A PR trigger creates a virtual merge commit (refs/pull/PR_NUMBER/merge) combining your source branch with the target branch to test collision-free execution.
  • Tags & Releases: Semantic version tags (v1.0.0) trigger build, package, and publish workflows.

Bash

# Developer Workflow triggering CI
git checkout -b feature/user-auth
git commit -m "feat: implement JWT login"
git push origin feature/user-auth # Triggers push / pull_request events on GitHub

2. YAML Syntax

Workflows are written in YAML (YAML Ain’t Markup Language). YAML uses strictly spaces for indentation (tabs are forbidden) and relies on key-value pairs, scalar types, arrays, and dictionaries.

Key Syntax Rules for GitHub Actions

  • Indentation: standard is 2 spaces per level.
  • Lists/Sequences: Prefixed with a hyphen and a space (- item).
  • Multi-line Strings: Use | to preserve line breaks or > to fold line breaks into spaces.
  • Booleans & Numbers: true, false, 10, 3.14 (unquoted). Quoting forces string representation ("true").

YAML

# Demonstration of YAML data structures
string_scalar: "Hello World"
number_scalar: 42
boolean_scalar: true

# List / Array syntax
browser_list:
  - chromium
  - firefox
  - webkit

# Dictionary / Object syntax
runner_config:
  os: ubuntu-latest
  timeout: 30

# Multi-line script execution block (| preserves newlines)
multi_line_command: |
  echo "Line 1"
  echo "Line 2"
  npm test

3. Creating Your First Workflow

A minimal workflow file must be stored in .github/workflows/main.yml. It requires three root keys: name, on, and jobs.

YAML

# .github/workflows/first-workflow.yml
name: First Workflow

# Event trigger
on:
  push:
    branches: [ "main" ]

# Execution unit
jobs:
  welcome-job:
    runs-on: ubuntu-latest
    steps:
      - name: Print welcome message
        run: echo "GitHub Actions workflow executed successfully!"

      - name: Output commit metadata
        run: |
          echo "Commit SHA: ${{ github.sha }}"
          echo "Triggered by: ${{ github.actor }}"

4. Events and Triggers (on)

The on key determines when a workflow runs. You can listen to single events, array events, or apply fine-grained activity filters and path filters.

Filtering Rules

  • branches: Restrict runs to specific target branches.
  • paths / paths-ignore: Trigger only when specific files change.
  • tags: Trigger on Git tags matching glob patterns.

YAML

name: Event Trigger Masterclass

on:
  # Trigger on pushes to main or release branches, but only if code inside src/ changed
  push:
    branches:
      - main
      - 'releases/v*'
    paths:
      - 'src/**'
      - 'package.json'
    paths-ignore:
      - '**.md'

  # Trigger on Pull Requests targeting main branch when opened or synchronized
  pull_request:
    types: [opened, synchronize, reopened]
    branches:
      - main

  # Trigger on tag creation matching v1.0.0, v2.1.0, etc.
  push:
    tags:
      - 'v*.*.*'

5. Jobs and Steps

  • Job: A set of steps running on a specific host environment (runs-on). Jobs run in parallel by default.
  • Step: An individual task executed sequentially inside a job. Steps share a filesystem and environment state on the runner VM.

YAML

name: Job Dependency Pipeline

on: push

jobs:
  compile:
    runs-on: ubuntu-latest
    steps:
      - name: Step 1 - Build
        run: echo "Compiling assets..."

  test:
    needs: compile # Forces 'test' to wait until 'compile' finishes successfully
    runs-on: ubuntu-latest
    steps:
      - name: Step 1 - Unit Test
        run: echo "Executing unit tests..."

  deploy:
    needs: [compile, test] # Waits for both upstream jobs
    runs-on: ubuntu-latest
    steps:
      - name: Step 1 - Deploy
        run: echo "Deploying to production..."

6. Using Marketplace Actions

Instead of writing raw shell scripts for every task, you can import community and official actions from the GitHub Marketplace using the uses: keyword.

Versioning Actions

  • @v4 (Major version tag – receives non-breaking updates).
  • @v4.1.2 (Exact semantic version).
  • @8f4b7f8... (Full commit SHA – most secure, immutable).

YAML

jobs:
  setup-environment:
    runs-on: ubuntu-latest
    steps:
      # Action 1: Clone repository code
      - name: Checkout Repository
        uses: actions/checkout@v4

      # Action 2: Provision Node.js runtime environment
      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: '20'
          registry-url: 'https://registry.npmjs.org'

      # Step 3: Native shell execution
      - name: Install dependencies
        run: npm ci

7. Environment Variables and Secrets

GitHub Actions handles environment configuration at the workflow, job, or step scope. Sensitive credentials must be stored as Encrypted Secrets in repository/organization settings.

YAML

name: Environment & Secrets Demo

on: push

# Workflow-level environment variables
env:
  GLOBAL_APP_NAME: "MyEnterpriseApp"
  LOG_LEVEL: "debug"

jobs:
  process-payment:
    runs-on: ubuntu-latest
    # Job-level environment variables
    env:
      JOB_ENV: "payment-processor"

    steps:
      - name: Secure API Call
        # Step-level environment variables
        env:
          PAYMENT_API_KEY: ${{ secrets.PAYMENT_GATEWAY_KEY }} # Injecting secret
          DYNAMIC_VAR: "step-specific-value"
        run: |
          echo "Processing payment for $GLOBAL_APP_NAME"
          # Accessing secret safely via environment variable in shell
          python process.py --key "$PAYMENT_API_KEY"

      - name: Set dynamic environment variable for subsequent steps
        run: |
          echo "BUILD_TIMESTAMP=$(date +'%Y-%m-%d_%H-%M-%S')" >> $GITHUB_ENV

      - name: Read dynamic variable
        run: |
          echo "Timestamp was: $BUILD_TIMESTAMP"

8. Expressions and Conditional Execution

Expressions let you evaluate programmatic conditions and access context objects (github, env, runner, steps, secrets). Use if: directives to skip jobs or steps dynamically.

YAML

jobs:
  conditional-job:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Execute on main branch only
        if: github.ref == 'refs/heads/main'
        run: echo "This step runs ONLY on pushes to main."

      - name: Execute step with custom status check functions
        id: test_step
        run: npm test

      # Runs ONLY if the previous step failed
      - name: Report Failure
        if: failure() && steps.test_step.outcome == 'failure'
        run: echo "The test execution step failed!"

      # Runs ALWAYS, regardless of prior step pass/fail state
      - name: Always Cleanup
        if: always()
        run: echo "Cleaning up temporary test artifacts..."

9. Matrix Strategy

A Matrix Strategy generates multiple job runs by defining input variables across OSs, runtimes, or database versions. GitHub Actions expands these configurations into a parallel execution grid.

YAML

jobs:
  matrix-build:
    runs-on: ${{ matrix.os }}
    strategy:
      fail-fast: false # Keep running other matrix jobs even if one fails
      max-parallel: 4 # Limit concurrent runners
      matrix:
        os: [ubuntu-latest, windows-latest, macos-latest]
        node-version: [18, 20]
        # Include specific additional configuration
        include:
          - os: ubuntu-latest
            node-version: 22
            experimental: true
        # Exclude invalid or unwanted combinations
        exclude:
          - os: windows-latest
            node-version: 18

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: node -v

10. Caching Dependencies

To speed up workflow runs, use actions/cache or built-in caching inside setup actions. Caches persist archive files between workflow runs using a unique cache key (typically hashed from lockfiles).

YAML

jobs:
  cache-demo:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      # Method A: Built-in setup action caching (Recommended)
      - uses: actions/setup-python@v5
        with:
          python-version: '3.11'
          cache: 'pip' # Automatically hashes requirements.txt/Pipfile

      # Method B: Manual Cache Configuration via actions/cache
      - name: Cache Custom Directory
        uses: actions/cache@v4
        with:
          path: ~/.custom_cache_dir
          # Primary lookup key
          key: ${{ runner.os }}-custom-${{ hashFiles('**/lockfile.json') }}
          # Fallback lookup keys if primary key misses
          restore-keys: |
            ${{ runner.os }}-custom-

      - name: Install Dependencies
        run: pip install -r requirements.txt

11. Uploading and Downloading Artifacts

Artifacts allow you to persist output files (build binaries, test reports, coverage HTML) beyond the runner’s ephemeral lifecycle and pass data between independent jobs.

YAML

jobs:
  build-job:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: mkdir dist && echo "Compiled App Code" > dist/app.bin

      # Upload artifacts
      - name: Upload Build Binaries
        uses: actions/upload-artifact@v4
        with:
          name: compiled-app-artifact
          path: dist/
          retention-days: 7

  deploy-job:
    needs: build-job # Must wait for build-job to upload
    runs-on: ubuntu-latest
    steps:
      # Download artifacts generated in upstream job
      - name: Download Build Binaries
        uses: actions/download-artifact@v4
        with:
          name: compiled-app-artifact
          path: downloaded-dist/

      - name: Verify Downloaded Assets
        run: cat downloaded-dist/app.bin

12. Manual and Scheduled Workflows

Workflows can run on cron schedules or be triggered manually via the GitHub UI/API with custom user inputs (workflow_dispatch).

YAML

name: Manual & Scheduled Execution

on:
  # Cron trigger: Runs every Monday at 08:00 UTC
  schedule:
    - cron: '0 8 * * 1'

  # Manual trigger with interactive input forms
  workflow_dispatch:
    inputs:
      target_env:
        description: 'Target Deployment Environment'
        type: choice
        required: true
        options:
          - staging
          - production
      perform_cleanup:
        description: 'Run deep database cleanup?'
        type: boolean
        default: false

jobs:
  execute:
    runs-on: ubuntu-latest
    steps:
      - name: Print Trigger Context
        run: |
          echo "Trigger event: ${{ github.event_name }}"
          echo "Selected Environment: ${{ inputs.target_env }}"
          echo "Perform Cleanup: ${{ inputs.perform_cleanup }}"

13. Reusable Workflows and Composite Actions

Composite Action (.github/actions/setup-stack/action.yml)

Bundles multiple run steps into a single reusable step block.

YAML

name: 'Setup Project Stack'
description: 'Standardized setup steps for project'
runs:
  using: 'composite'
  steps:
    - uses: actions/setup-node@v4
      with:
        node-version: '20'
    - run: npm ci
      shell: bash # Shell directive is mandatory for composite actions

Reusable Workflow (.github/workflows/reusable-ci.yml)

Encapsulates complete jobs for consumption across callers.

YAML

name: Reusable CI Core
on:
  workflow_call:
    inputs:
      node-version:
        type: string
        default: '20'
jobs:
  run-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
      - run: npm test

Calling Workflow (.github/workflows/caller.yml)

YAML

jobs:
  invoke-reusable:
    uses: ./.github/workflows/reusable-ci.yml
    with:
      node-version: '22'

14. Docker Integration

GitHub Actions runners come pre-configured with Docker, enabling step containers, containerized jobs, service containers (databases/queues), and image publishing.

YAML

jobs:
  # Integration testing using a Database Service Container
  database-tests:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:15
        env:
          POSTGRES_PASSWORD: mysecretpassword
          POSTGRES_DB: testdb
        ports:
          - 5432:5432
        # Health checks to ensure DB is ready before test steps start
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5

    steps:
      - uses: actions/checkout@v4
      - name: Verify PostgreSQL Connection
        run: |
          PGPASSWORD=mysecretpassword psql -h localhost -U postgres -d testdb -c "SELECT 1;"

  # Build & Publish Docker Container Image
  docker-build-push:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Log in to GitHub Container Registry (GHCR)
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and Push Docker Image
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}/app:latest

15. Cloud Deployments (AWS/Azure/GCP)

To deploy safely to modern cloud infrastructure, never use long-lived access key secrets. Use OpenID Connect (OIDC) to request temporary, short-lived tokens using IAM Role assumption.

YAML

name: Keyless OIDC AWS Deployment

on:
  push:
    branches: [ "main" ]

jobs:
  deploy-aws:
    runs-on: ubuntu-latest
    # Required permission to request the OIDC JWT token from GitHub
    permissions:
      id-token: write
      contents: read

    steps:
      - uses: actions/checkout@v4

      - name: Authenticate with AWS via OIDC
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeploymentRole
          aws-region: us-east-1

      - name: Deploy to S3 Static Bucket
        run: |
          aws s3 sync ./dist s3://my-production-app-bucket --delete

16. Enterprise CI/CD Patterns and Security

Production enterprise workflows require strict security practices: Zero Trust permissions, Pinned Action Hashes, Concurrency Controls, and Protected Environments.

YAML

name: Enterprise Secure Pipeline

on:
  push:
    branches: [ "main" ]

# Prevent race conditions by cancelling in-progress runs on same branch
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

# Hardened Security Rule 1: Set Least-Privilege permissions globally
permissions: {}

jobs:
  secure-build:
    runs-on: ubuntu-latest
    permissions:
      contents: read # Read-only code access
      id-token: write # For OIDC deployment step

    # Attach workflow to protected GitHub Environment (Approval rules & secrets)
    environment:
      name: production
      url: https://my-app.company.com

    steps:
      # Hardened Security Rule 2: Pin Actions to full immutable commit SHAs
      - name: Checkout Code
        uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2

      - name: Setup Node.js
        uses: actions/setup-node@39370e3970a6d050c080011e813206d11393d18e # v4.1.0
        with:
          node-version: '20'

      - name: Run Dependency Vulnerability Audit
        run: npm audit --audit-level=high

      - name: Build Application
        run: npm run build

GitHub Actions Hands-on Practice Projects

1. Hello World Workflow

A minimal workflow to test trigger mechanics, job execution, and basic logging in GitHub Actions.

YAML

name: Hello World

on:
  push:
    branches: [ "main" ]
  workflow_dispatch:

jobs:
  say-hello:
    runs-on: ubuntu-latest
    steps:
      - name: Print Welcome Message
        run: echo "Hello World from GitHub Actions!"
      
      - name: Display Runner Details
        run: |
          echo "Triggered event: ${{ github.event_name }}"
          echo "Running on branch: ${{ github.ref_name }}"
          echo "Executed by: ${{ github.actor }}"

2. Node.js Build Pipeline

Automates dependencies installation, build scripts execution, and unit tests using Node.js with package manager caching.

YAML

name: Node.js CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Run linter
        run: npm run lint --if-present

      - name: Build application
        run: npm run build --if-present

      - name: Execute unit tests
        run: npm test

3. Python CI Pipeline

Runs static analysis, dependency installation, and pytest execution for Python projects.

YAML

name: Python CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'
          cache: 'pip'

      - name: Install dependencies
        run: |
          python -m pip install --upgrade pip
          if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
          pip install pytest flake8

      - name: Lint with flake8
        run: |
          # stop the build if there are Python syntax errors or undefined names
          flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
          # exit-zero treats all errors as warnings.
          flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics

      - name: Run Pytest
        run: pytest

4. Java Maven Pipeline

Sets up OpenJDK, caches local Maven dependencies, builds the project, and runs integration tests.

YAML

name: Java CI with Maven

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'
          cache: maven

      - name: Build with Maven
        run: mvn -B package --file pom.xml

      - name: Run Tests
        run: mvn test

5. Playwright Automation Workflow

Installs system dependencies and browser binaries required to execute Playwright end-to-end tests headless in CI.

YAML

name: Playwright Tests

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]

jobs:
  playwright-tests:
    timeout-minutes: 60
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'

      - name: Install dependencies
        run: npm ci

      - name: Install Playwright Browsers & OS Dependencies
        run: npx playwright install --with-deps

      - name: Run Playwright tests
        run: npx playwright test

      - name: Upload Playwright Report
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: playwright-report
          path: playwright-report/
          retention-days: 30

6. Selenium Pytest Workflow

Executes Selenium browser automation tests using headless Chrome in a Python environment.

YAML

name: Selenium Pytest Pipeline

on:
  push:
    branches: [ "main" ]

jobs:
  selenium-tests:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.10'
          cache: 'pip'

      - name: Install Dependencies
        run: |
          pip install --upgrade pip
          pip install selenium pytest pytest-xdist

      - name: Run Selenium Tests (Headless Chrome)
        run: pytest tests/ui/ --headless

7. Parallel Browser Execution with a Matrix Strategy

Spins up isolated, parallel runners for multiple browser engine combinations simultaneously to accelerate test execution.

YAML

name: Cross-Browser Matrix Execution

on:
  push:
    branches: [ "main" ]

jobs:
  matrix-test:
    runs-on: ubuntu-latest
    strategy:
      fail-fast: false
      matrix:
        browser: [chromium, firefox, webkit]
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install dependencies
        run: npm ci

      - name: Install Matrix Browser (${{ matrix.browser }})
        run: npx playwright install ${{ matrix.browser }} --with-deps

      - name: Run Tests on ${{ matrix.browser }}
        run: npx playwright test --project=${{ matrix.browser }}

8. Scheduled Nightly Test Execution

Uses cron scheduling syntax to trigger automated regression suites at a designated time without manual intervention.

YAML

name: Nightly Regression Suite

on:
  schedule:
    # Runs at 00:00 UTC every day
    - cron: '0 0 * * *'
  workflow_dispatch: # Allows manual trigger if needed

jobs:
  nightly-tests:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 20

      - name: Install Dependencies
        run: npm ci

      - name: Execute Nightly Regression
        run: npm run test:regression

9. Manual Workflow with User Inputs

Presents interactive inputs in the GitHub UI for standard testing parameters like target environment, target browser, and debug flags.

YAML

name: Manual Test Trigger

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Target Deployment Environment'
        required: true
        default: 'staging'
        type: choice
        options:
          - dev
          - qa
          - staging
          - production
      browser:
        description: 'Browser Choice'
        required: true
        default: 'chrome'
        type: choice
        options:
          - chrome
          - firefox
          - safari
      headless:
        description: 'Run in Headless Mode?'
        required: true
        type: boolean
        default: true

jobs:
  run-custom-test:
    runs-on: ubuntu-latest
    steps:
      - name: Print User Parameters
        run: |
          echo "Running tests against: ${{ inputs.environment }}"
          echo "Selected Browser: ${{ inputs.browser }}"
          echo "Headless mode: ${{ inputs.headless }}"

      - name: Checkout code
        uses: actions/checkout@v4

      - name: Run Suite
        run: |
          echo "Executing test CLI commands with flags..."
          # Example CLI invocation:
          # npm test -- --env=${{ inputs.environment }} --browser=${{ inputs.browser }} --headless=${{ inputs.headless }}

10. Upload HTML and Allure Reports

Executes tests, generates report output, and attaches compiled HTML and Allure report assets to the workflow summary using if: always().

YAML

name: Test Suite with Allure Reporting

on:
  push:
    branches: [ "main" ]

jobs:
  test-and-report:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.11'

      - name: Install Dependencies
        run: |
          pip install pytest allure-pytest

      - name: Run Tests & Generate Allure Results
        run: pytest --alluredir=allure-results
        continue-on-error: true

      - name: Install Allure CLI & Generate HTML Report
        run: |
          sudo wget https://github.com/allure-framework/allure2/releases/download/2.24.0/allure-2.24.0.tgz
          sudo tar -zxvf allure-2.24.0.tgz -C /opt/
          sudo ln -s /opt/allure-2.24.0/bin/allure /usr/bin/allure
          allure generate allure-results --clean -o allure-report

      - name: Upload Allure HTML Report Artifact
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: allure-html-report
          path: allure-report/
          retention-days: 14

11. Reusable Workflow for Common Test Execution

Defines a modular, parameterized reusable workflow (workflow_call) and demonstrates how a caller workflow invokes it across repositories or jobs.

Standard Reusable Workflow (.github/workflows/reusable-test.yml)

YAML

name: Shared Test Runner

on:
  workflow_call:
    inputs:
      test_suite:
        required: true
        type: string
      node_version:
        required: false
        type: string
        default: '20'
    secrets:
      API_TOKEN:
        required: true

jobs:
  execute-tests:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node_version }}
      - run: npm ci
      - name: Run Test Suite
        env:
          API_TOKEN: ${{ secrets.API_TOKEN }}
        run: npm run test:${{ inputs.test_suite }}

Caller Workflow (.github/workflows/main-pipeline.yml)

YAML

name: Main Pipeline

on:
  push:
    branches: [ "main" ]

jobs:
  run-smoke-tests:
    uses: ./.github/workflows/reusable-test.yml
    with:
      test_suite: 'smoke'
      node_version: '20'
    secrets:
      API_TOKEN: ${{ secrets.SMOKE_API_TOKEN }}

12. Docker Build and Publish Pipeline

Authenticates to Docker Hub (or GHCR), configures Docker Buildx, and pushes a multi-arch container image.

YAML

name: Docker Build and Publish

on:
  push:
    tags:
      - 'v*.*.*'
    branches:
      - 'main'

jobs:
  docker-build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

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

      - name: Extract Metadata (Tags, Labels)
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ secrets.DOCKERHUB_USERNAME }}/my-app

      - name: Build and Push Docker Image
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}

13. Deploy to AWS EC2

Connects to AWS using OpenID Connect (OIDC) and deploys updated application builds to an EC2 target via SSH.

YAML

name: Deploy to AWS EC2

on:
  push:
    branches: [ "main" ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
    steps:
      - name: Checkout Code
        uses: actions/checkout@v4

      - name: Configure AWS Credentials (OIDC)
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsEC2DeployRole
          aws-region: us-east-1

      - name: Deploy to EC2 via SSH
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ec2-user
          key: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
          script: |
            cd /var/www/myapp
            git pull origin main
            npm install --production
            pm2 restart all

14. Trigger One Workflow from Another

Uses the workflow_run event trigger to execute a downstream automation workflow automatically after an upstream workflow finishes.

Downstream Workflow (.github/workflows/deploy-on-ci-success.yml)

YAML

name: Deployment Triggered by CI Success

on:
  workflow_run:
    workflows: ["Node.js CI"]  # Name of upstream workflow
    types:
      - completed

jobs:
  on-success:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'success' }}
    steps:
      - name: Run Downstream Task
        run: echo "Upstream CI succeeded! Starting deployment process..."
        
  on-failure:
    runs-on: ubuntu-latest
    if: ${{ github.event.workflow_run.conclusion == 'failure' }}
    steps:
      - name: Notify Team of Failure
        run: echo "Upstream CI failed. Aborting downstream triggers."

15. Multi-Environment Deployment (Dev → QA → Staging → Production)

Establishes sequential environment promotion chains using needs conditions, protected environments, and manual gating rules.

YAML

name: Multi-Environment Promotion Pipeline

on:
  push:
    branches: [ "main" ]

jobs:
  deploy-dev:
    name: Deploy to Development
    runs-on: ubuntu-latest
    environment: dev
    steps:
      - uses: actions/checkout@v4
      - name: Run Dev Deployment
        run: echo "Deploying build commit ${{ github.sha }} to DEV environment"

  deploy-qa:
    name: Deploy to QA
    needs: deploy-dev
    runs-on: ubuntu-latest
    environment: qa
    steps:
      - uses: actions/checkout@v4
      - name: Run QA Deployment
        run: echo "Deploying build commit ${{ github.sha }} to QA environment"

  deploy-staging:
    name: Deploy to Staging
    needs: deploy-qa
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - uses: actions/checkout@v4
      - name: Run Staging Deployment
        run: echo "Deploying build commit ${{ github.sha }} to STAGING environment"

  deploy-production:
    name: Deploy to Production
    needs: deploy-staging
    runs-on: ubuntu-latest
    # Requires manual reviewer approval set up under GitHub Environment rules
    environment: production
    steps:
      - uses: actions/checkout@v4
      - name: Run Production Deployment
        run: echo "Deploying build commit ${{ github.sha }} to PRODUCTION environment"

Github Fundamentals Intermediate

1. What is Matrix Strategy?

A matrix strategy lets you run a single job multiple times using variations of inputs (like different OSs, runtime versions, or build flags). GitHub Actions automatically creates a parallel job for every possible combination of matrix variables.

YAML

jobs:
  test:
    runs-on: ${{ matrix.os }}
    strategy:
      matrix:
        os: [ubuntu-latest, windows-latest]
        node-version: [18, 20, 22]
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm test

This example runs 6 parallel jobs ($2 \text{ OSs} \times 3 \text{ Node versions}$).

2. Explain Caching

Caching stores dependencies (such as node_modules, Maven packages, or Docker layers) across workflow runs. Because runner VMs are completely wiped after every job, downloading dependencies repeatedly wastes time and bandwidth.

You can use actions/cache@v4 or built-in caching options inside setup actions (like actions/setup-node).

YAML

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      # Built-in caching for NPM dependencies
      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'npm'
      - run: npm ci

When a cache key matches, the runner downloads the pre-packaged dependencies instead of reinstalling them from the internet.

3. How Do You Upload Artifacts?

Artifacts are files or directories generated during a job (e.g., compiled binaries, test coverage logs, APKs) that you want to save after the runner VM is destroyed.

You use the actions/upload-artifact@v4 action to attach files to the workflow run.

YAML

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm run build
      - name: Save build output
        uses: actions/upload-artifact@v4
        with:
          name: web-dist
          path: dist/

Uploaded artifacts can be downloaded manually from the GitHub UI or programmatically by other jobs.

4. How Do Jobs Communicate?

Because every job executes in a completely isolated virtual machine, they do not share filesystem memory or local variables directly. Jobs communicate in two primary ways:

Method A: Job Outputs (For Small Data / Strings)

Pass scalar values (like commit IDs, version numbers, or status flags) via $GITHUB_OUTPUT.

YAML

jobs:
  generator:
    runs-on: ubuntu-latest
    outputs:
      app_version: ${{ steps.set_version.outputs.version }}
    steps:
      - id: set_version
        run: echo "version=1.2.3" >> $GITHUB_OUTPUT

  receiver:
    needs: generator
    runs-on: ubuntu-latest
    steps:
      - run: echo "The version is ${{ needs.generator.outputs.app_version }}"

Method B: Artifacts (For Files / Directories)

Pass files between jobs using actions/upload-artifact in Job 1 and actions/download-artifact in Job 2.

5. Explain Reusable Workflows

Reusable Workflows allow you to avoid duplicating workflow code across repositories or within the same repository. Instead of copying and pasting pipeline definitions, you create a central workflow file and invoke it from caller workflows.

A reusable workflow must use the workflow_call trigger:

YAML

# .github/workflows/reusable-build.yml (Called Workflow)
name: Reusable Build Component
on:
  workflow_call:
    inputs:
      target-env:
        type: string
        required: true

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Building for ${{ inputs.target-env }}"

Caller workflow usage:

YAML

# .github/workflows/main.yml (Caller Workflow)
jobs:
  run-reusable:
    uses: ./.github/workflows/reusable-build.yml
    with:
      target-env: 'production'

6. Difference Between uses and run

Featurerunuses
PurposeExecutes inline shell commands or scripts.Executes a pre-packaged Action or Reusable Workflow.
SourceRuns directly on the runner shell (Bash, PowerShell, zsh).Fetched from GitHub Marketplace, local files, or public repositories.
Examplerun: npm testuses: actions/checkout@v4

7. What is needs?

By default, jobs in a workflow execute in parallel. The needs keyword defines dependency requirements to force sequential execution or form an execution chain (DAG).

YAML

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - run: npm test

  deploy:
    needs: test # Waits for 'test' job to complete successfully
    runs-on: ubuntu-latest
    steps:
      - run: ./deploy.sh

If test fails, deploy is automatically skipped.

8. How Do You Trigger Workflows Conditionally?

You can run workflows, jobs, or individual steps conditionally using if expressions or trigger filters:

Method A: Step or Job Level if Condition

YAML

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to Prod
        # Runs only if the event is a push to main branch
        if: github.ref == 'refs/heads/main' && github.event_name == 'push'
        run: ./deploy-prod.sh

Method B: Event Path/Branch Filtering (on)

YAML

on:
  push:
    branches:
      - main
    paths:
      - 'src/**' # Triggers only if files in src/ change

9. What are Environments?

Environments describe continuous deployment targets like production, staging, or development. They allow you to attach security controls and configuration variables directly to a deployment target.

Key features of Environments:

  • Required Reviewers: Pause workflow execution until specified team members manually approve.
  • Wait Timers: Delay deployment after a trigger (e.g., wait 15 minutes before pushing).
  • Environment Secrets/Variables: Restrict deployment keys so they are only accessible when running against that specific environment.

YAML

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: production
      url: https://myapp.com
    steps:
      - run: ./deploy.sh

10. What are Concurrency Groups?

Concurrency Groups ensure that only a single job or workflow run within a designated group executes at any given time. If a new run starts while a previous run is in progress, GitHub Actions can automatically cancel the old run or queue the new run.

This prevents deployment race conditions or redundant builds when developers rapidly push multiple commits.

YAML

name: Deploy Pipeline
on: push

# Prevents simultaneous deployments on the same branch
concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true # Cancels any previous run still processing

GitHub Actions Advanced Concept

1. What is OIDC Authentication?

OpenID Connect (OIDC) allows GitHub Actions to authenticate directly with cloud providers (AWS, Azure, GCP) using short-lived JWT tokens rather than long-lived, hardcoded credentials or API keys.

  1. The runner requests an OIDC JSON Web Token (JWT) from GitHub’s OIDC provider.
  2. The runner sends this JWT to the cloud provider (e.g., AWS Security Token Service).
  3. The cloud provider validates the signature, evaluates claims (such as repository name, branch, or environment), and exchanges the JWT for short-lived cloud credentials.

2. How Do You Deploy Securely to AWS?

Use OIDC alongside the official aws-actions/configure-aws-credentials action instead of storing AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY inside repository secrets.

YAML

jobs:
  deploy:
    runs-on: ubuntu-latest
    permissions:
      id-token: write  # Grants permission to fetch the OIDC JWT token
      contents: read
    steps:
      - uses: actions/checkout@v4
      
      - name: Authenticate with AWS via OIDC
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: arn:aws:iam::123456789012:role/GitHubActionsDeployRole
          aws-region: us-east-1

      - name: Deploy AWS Infrastructure
        run: aws s3 sync ./dist s3://my-production-bucket

3. How Do You Optimize Large Workflows?

  • Smart Caching: Cache dependency directories (~/.npm, ~/.m2, target folders) using build-tool-native caching options.
  • Path & Branch Filtering: Use paths and paths-ignore so workflows run only when relevant code changes.
  • Job Dependencies (needs): Fail fast by placing cheap checks (linting, static analysis) before heavy build/test jobs.
  • Matrix Filtering / Cancellation: Set fail-fast: true inside matrix strategies so remaining matrix combinations cancel immediately if one fails.
  • Concurrency Cancellation: Set cancel-in-progress: true inside concurrency blocks to terminate stale builds on new commits.

YAML

on:
  push:
    paths:
      - 'src/**'  # Ignore documentation or root README changes

4. How Do You Reuse Workflows Across Repositories?

Reference a reusable workflow stored in an external repository using the {owner}/{repo}/.github/workflows/{filename}.yml@{ref} syntax. The target repository must have its visibility set to public or shared within an organization.

YAML

# In repo: caller-org/app-repo
jobs:
  call-shared-ci:
    # References shared pipeline from security-team/shared-workflows repo
    uses: security-team/shared-workflows/.github/workflows/ci-template.yml@v2.1
    with:
      environment: 'staging'
    secrets: inherit # Automatically passes caller secrets to called workflow

5. What are Composite Actions?

A Composite Action aggregates multiple step commands or actions into a single reusable action. Unlike reusable workflows (which encompass full jobs), composite actions run as a single step within a job.

They are defined in an action.yml file and require runs.using: 'composite' and an explicit shell: directive on every run step.

YAML

# .github/actions/setup-node-and-cache/action.yml
name: 'Setup Node and Cache'
description: 'Custom setup wrapper for project standard initialization'

inputs:
  node-version:
    default: '20'

runs:
  using: 'composite'
  steps:
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
        cache: 'npm'
    - name: Install dependencies
      shell: bash  # Required in composite actions
      run: npm ci

6. How Do You Secure Secrets?

  • Use Least Privilege: Restrict secret exposure using Environment Secrets gated behind approval environments.
  • Never Print Secrets: Avoid passing secrets directly into shell scripts where set -x or debug flags could print them to standard output.
  • Avoid PR Triggers from Forks: Workflows triggered by pull_request from fork repositories do not receive access to repository secrets by default.
  • Pass Secrets via Environment Variables: Pass secrets to scripts using env blocks rather than raw string replacement inside commands to avoid process listing injection.

YAML

steps:
  - name: Run Secure Script
    env:
      DB_PASSWORD: ${{ secrets.DB_PASSWORD }} # Passed as env var, not inline text
    run: python db_migrate.py

7. What is Least-Privilege Workflow Permission?

By default, GITHUB_TOKEN may inherit read/write permissions depending on organization settings. To enforce least privilege, set global workflow permissions to read-all or contents: read, and grant specific elevated scopes only to the jobs that require them.

YAML

name: Security Standard Pipeline
on: push

# Deny all permissions globally by default
permissions: {}

jobs:
  build_and_test:
    runs-on: ubuntu-latest
    permissions:
      contents: read # Read-only access to code
    steps:
      - uses: actions/checkout@v4
      - run: npm test

  publish_release:
    needs: build_and_test
    runs-on: ubuntu-latest
    permissions:
      contents: write # Granted write access ONLY for release generation
    steps:
      - uses: actions/checkout@v4
      - run: gh release create v1.0.0
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

8. How Do You Handle Rollbacks?

Automate rollbacks using conditional steps (if: failure()) or a dedicated rollback workflow triggered by deployment checks.

YAML

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Deploy Release
        id: deploy_step
        run: ./deploy-app.sh

      - name: Healthcheck Target
        id: healthcheck
        run: ./verify-endpoint.sh

      - name: Trigger Automated Rollback
        if: failure() && steps.deploy_step.outcome == 'success'
        run: ./rollback-to-previous-image.sh

9. How Do You Implement Blue-Green Deployment?

Deploy the new application version to an isolated “Green” environment, perform health checks, and swap live traffic routing (e.g., DNS, Load Balancer, or ingress route) from “Blue” to “Green”.

YAML

jobs:
  blue_green_deploy:
    runs-on: ubuntu-latest
    environment: production
    steps:
      - uses: actions/checkout@v4

      - name: Deploy to Green Environment
        run: ./deploy-green.sh --version ${{ github.sha }}

      - name: Run Integration Tests Against Green
        run: ./test-target.sh --url https://green.internal.myapp.com

      - name: Switch Traffic (Blue -> Green)
        run: ./switch-load-balancer.sh --target green

10. How Do You Debug Failed Workflows?

  • Enable Runner Diagnostic / Step Debug Logging: Set repository secrets ACTIONS_STEP_DEBUG = true and ACTIONS_RUNNER_DEBUG = true to produce verbose log outputs.
  • Re-run Jobs with Debug Logging Enabled: Click Re-run jobs -> check Enable debug logging from the GitHub UI interface.
  • Inspect Artifacts: Save log files, crash dumps, or screenshots using actions/upload-artifact@v4 inside an if: always() step.

YAML

steps: – name: Run Test Suite run: npm test – name: Capture Failure Logs if: failure() uses: actions/upload-artifact@v4 with: name: test-failure-logs path: ./logs/

GitHub Actions Fundamentals for Beginners

1. What is GitHub Actions?

GitHub Actions is an automated CI/CD (Continuous Integration and Continuous Delivery) platform built directly into GitHub. It allows you to automate software workflows directly from your repository—such as building code, running tests, publishing packages, or deploying applications—whenever specific GitHub events occur.

YAML

# Simple example: Running tests whenever code is pushed
name: CI Pipeline
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: npm install
      - run: npm test

2. What is a Workflow?

A Workflow is an automated, configurable process defined in a .yml (or .yaml) file stored inside your repository’s .github/workflows/ directory. A repository can have multiple workflows (e.g., one for unit testing, one for code linting, and one for production deployments).

Workflows are triggered by events (like a push, pull_request, or schedule) and consist of one or more jobs.

YAML

# .github/workflows/greeting.yml
name: Daily Greeting
on:
  schedule:
    - cron: '0 9 * * 1-5' # Runs every weekday at 9 AM UTC

jobs:
  greet:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Good morning, team!"

3. What is a Runner?

A Runner is an application or server that executes the jobs inside a GitHub Actions workflow. When a workflow is triggered, GitHub assigns a runner to listen for available jobs, run the steps, and stream the logs and results back to GitHub.

Runners come pre-installed with standard development tooling (Git, Node.js, Python, Docker, Docker Compose, CLI tools, etc.).

4. Difference Between Job and Step

  • Job: A group of steps that execute on the same runner instance. By default, if a workflow has multiple jobs, they run in parallel unless configured to run sequentially using needs.
  • Step: An individual task within a job. Steps run sequentially on the runner and share the same environment and filesystem. A step can either run a shell command (run) or execute a reusable action (uses).
FeatureJobStep
ExecutionRuns in parallel (default) or sequentiallyAlways runs sequentially inside its parent job
EnvironmentRuns on its own separate virtual machine / runnerShares the virtual machine environment with other steps in the job
Data SharingFilesystem is isolated from other jobsShares local filesystem changes directly with subsequent steps

YAML

jobs:
  build_job: # JOB 1
    runs-on: ubuntu-latest
    steps:
      - name: Step 1 # STEP 1.1
        run: echo "Compiling code..."
      - name: Step 2 # STEP 1.2
        run: echo "Creating build artifact..."

  deploy_job: # JOB 2 (Depends on JOB 1)
    needs: build_job
    runs-on: ubuntu-latest
    steps:
      - name: Step 1 # STEP 2.1
        run: echo "Deploying build..."

5. What is YAML?

YAML (“YAML Ain’t Markup Language”) is a human-readable data format used for configuration files. GitHub Actions uses YAML to structure workflows. It relies strictly on indentation (spaces, never tabs) and key-value pairs to establish hierarchy.

YAML

# Basic YAML structure rules:
string_key: "value"
number_key: 100
boolean_key: true

list_example:
  - item1
  - item2

nested_object:
  parent:
    child: "value"

6. What are GitHub-Hosted Runners?

GitHub-hosted runners are fully managed virtual machines hosted by GitHub. Every time a job runs, GitHub spins up a fresh, ephemeral VM running your choice of operating system (Ubuntu Linux, Windows, or macOS), runs the job, and destroys the VM afterward.

  • Pros: Zero maintenance, completely clean environment per run, automatically updated software packages.
  • Syntax: runs-on: ubuntu-latest, runs-on: windows-latest, or runs-on: macos-latest.

YAML

jobs:
  check-os:
    runs-on: macos-latest
    steps:
      - run: sw_vers # Checks macOS version

7. What are Self-Hosted Runners?

Self-hosted runners are machines (physical servers, local VMs, cloud instances on AWS/Azure, or Docker containers) that you set up and manage yourself, then register with GitHub.

  • Pros: Access to private internal networks/databases, custom hardware requirements (e.g., GPUs for AI/ML training), faster builds through persistent caching.
  • Cons: You are responsible for OS updates, security, and scaling.
  • Syntax: runs-on: self-hosted.

YAML

jobs:
  internal-deploy:
    runs-on: self-hosted
    steps:
      - run: ./deploy-to-private-datacenter.sh

8. What are GitHub Secrets?

GitHub Secrets are encrypted environment variables stored securely in repository, organization, or environment settings. They allow you to store sensitive credentials (e.g., API keys, database passwords, deployment tokens) without hardcoding them into your source code.

GitHub automatically masks secrets in workflow logs (replacing secret values with ***).

YAML

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Login to Docker Hub
        run: docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}

9. What is workflow_dispatch?

workflow_dispatch is an event trigger that allows you to run a workflow manually. Once added to on:, a “Run workflow” button appears in the GitHub Actions tab UI. It can also accept custom input parameters (text, drop-downs, booleans).

YAML

name: Manual Release
on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Target deployment environment'
        required: true
        default: 'staging'
        type: choice
        options:
          - staging
          - production

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - run: echo "Deploying to ${{ inputs.environment }}"

10. What is actions/checkout?

actions/checkout is an official, reusable action (actions/checkout@v4) provided by GitHub.

When a job starts, the runner’s workspace is completely empty. actions/checkout clones your repository’s code into the workspace so that subsequent steps (like linter checks, test runs, or build tools) can access and execute against your project files.

YAML

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      # Without checkout, npm build will fail because package.json is missing
      - name: Download repository code
        uses: actions/checkout@v4

      - name: Build project
        run: npm run build

GitHub Actions Complete Roadmap (Beginner to Advanced)

Step-by-Step Learning Guide with Practical Examples

This roadmap is designed specifically for QA Engineers, SDET, DevOps Beginners, and Developers who want to master GitHub Actions from scratch.

By the end of this guide, you’ll be able to build production-ready CI/CD pipelines for:

  • Selenium
  • Playwright
  • Cypress
  • API Testing
  • Python
  • Java
  • Node.js
  • Docker
  • AWS Deployment

Learning Path

LevelTopicsOutcome
Level 1GitHub FundamentalsUnderstand Git & GitHub
Level 2GitHub Actions BasicsRun first workflow
Level 3Workflow SyntaxLearn YAML
Level 4Events & TriggersControl execution
Level 5Jobs & StepsMulti-job pipelines
Level 6Variables & SecretsSecure pipelines
Level 7Matrix StrategyMultiple OS/Browsers
Level 8ArtifactsUpload Reports
Level 9CachingFaster execution
Level 10Advanced WorkflowsReusable workflows
Level 11DockerRun inside containers
Level 12DeploymentsAWS/Azure/GCP
Level 13Enterprise ConceptsProduction CI/CD

Module 1 — GitHub Fundamentals

Topics

  • What is Git?
  • What is GitHub?
  • Repository
  • Branch
  • Commit
  • Push
  • Pull
  • Merge
  • Pull Request
  • Fork
  • Clone

Example

git init

git add .

git commit -m "Initial Commit"

git push origin main

Module 2 — What is GitHub Actions?

GitHub Actions is GitHub’s built-in automation platform.

It automatically performs tasks whenever an event occurs.

Examples

  • Run tests
  • Build applications
  • Deploy websites
  • Send email
  • Upload reports
  • Publish packages

Module 3 — GitHub Actions Architecture

Understand these components:

Repository

↓

Workflow

↓

Jobs

↓

Steps

↓

Actions

↓

Runner

Workflow

.github/workflows/main.yml

Job

A workflow may contain multiple jobs.

jobs:
  test:

Step

steps:

Each job contains multiple steps.


Runner

GitHub provides runners.

Examples

ubuntu-latest

windows-latest

macos-latest

Action

Reusable automation.

Example

actions/checkout

Module 4 — First Workflow

name: My First Workflow

on: push

jobs:

  hello:

    runs-on: ubuntu-latest

    steps:

      - name: Print Message
        run: echo "Hello GitHub Actions"

Output

Hello GitHub Actions

Module 5 — YAML Basics

Topics

  • Indentation
  • Keys
  • Values
  • Lists
  • Mapping

Example

name: Demo

on:
  push:

jobs:

  build:

    runs-on: ubuntu-latest

    steps:

      - run: echo Hello

Module 6 — Workflow Triggers

Push

on:
  push:

Pull Request

on:
  pull_request:

Manual Trigger

on:
  workflow_dispatch:

Schedule

on:

  schedule:

    - cron: "0 6 * * *"

Runs every day.


Multiple Events

on:

  push:

  pull_request:

  workflow_dispatch:

Module 7 — Jobs

Single Job

jobs:

  test:

    runs-on: ubuntu-latest

Multiple Jobs

jobs:

  build:

  test:

  deploy:

Dependent Jobs

needs:

  build

Module 8 — Steps

steps:

- uses: actions/checkout@v4

- run: npm install

- run: npm test

Module 9 — GitHub Marketplace Actions

Popular Actions

actions/checkout

actions/setup-node

actions/cache

actions/upload-artifact

actions/download-artifact

actions/setup-python

Module 10 — Setup Programming Languages

NodeJS

- uses: actions/setup-node@v4

  with:

    node-version: 22

Python

- uses: actions/setup-python@v5

  with:

    python-version: 3.13

Java

- uses: actions/setup-java@v4

.NET

actions/setup-dotnet

Module 11 — Running Scripts

steps:

- run: ls

- run: pwd

- run: npm install

- run: npm test

Module 12 — Environment Variables

env:

  URL: https://example.com

Use

echo $URL

Windows

echo %URL%

Module 13 — Secrets

Repository

Settings

↓

Secrets and Variables

↓

Actions

Example

${{ secrets.USERNAME }}

${{ secrets.PASSWORD }}

Module 14 — Expressions

${{ github.actor }}

${{ github.repository }}

${{ github.ref }}

${{ github.sha }}

${{ runner.os }}

Module 15 — Conditional Execution

if:

  github.ref == 'refs/heads/main'

Example

- name: Deploy

  if: github.ref == 'refs/heads/main'

Module 16 — Matrix Strategy

Run on multiple operating systems.

strategy:

  matrix:

    os:

      - ubuntu-latest

      - windows-latest

      - macos-latest

Multiple Node versions

matrix:

  node:

    - 18

    - 20

    - 22

Module 17 — Caching

uses:

actions/cache@v4

Cache

  • npm
  • Maven
  • Gradle
  • Pip

Improves build speed.


Module 18 — Upload Artifacts

Example

- uses:

actions/upload-artifact@v4

with:

  name: TestReport

  path: reports/

Download later.


Module 19 — Download Artifacts

actions/download-artifact

Module 20 — Service Containers

Run databases.

MySQL

PostgreSQL

Redis

MongoDB

Module 21 — Docker

Build Docker Image

docker build .

Push Docker Hub

docker push

Module 22 — Reusable Workflows

workflow_call

Used in enterprise projects.


Module 23 — Composite Actions

Create your own custom action.

action.yml

Module 24 — Inputs

workflow_dispatch:

inputs:

Example

Branch Name

Environment

Browser

Module 25 — Outputs

Pass values between jobs.

outputs:

Module 26 — Self Hosted Runner

Instead of GitHub Runner

Your Server

↓

GitHub Runner Installed

↓

Workflow Executes

Module 27 — Deployments

Deploy to

  • AWS EC2
  • Azure
  • GCP
  • Kubernetes
  • Docker
  • IIS

Module 28 — Notifications

Examples

  • Email
  • Slack
  • Microsoft Teams
  • Discord

Module 29 — Playwright CI

Workflow

Checkout

↓

Setup Node

↓

Install Dependencies

↓

Install Browsers

↓

Execute Tests

↓

Upload HTML Report

Module 30 — Selenium Python CI

Checkout

↓

Setup Python

↓

Install Requirements

↓

Run Pytest

↓

Upload Allure Report

Module 31 — API Automation

Run

  • Postman
  • Newman
  • Rest Assured
  • Pytest API

Module 32 — Advanced Concepts

  • Reusable workflows
  • Composite actions
  • Dependency graph
  • Workflow permissions
  • OIDC authentication
  • Concurrency
  • Environments
  • Required reviewers
  • Branch protection
  • Deployment approvals
  • Environment protection rules

Module 33 — Enterprise CI/CD Pipeline

Developer

↓

Push Code

↓

Build

↓

Static Code Analysis

↓

Unit Test

↓

Integration Test

↓

Automation Test

↓

Package

↓

Docker Build

↓

Security Scan

↓

Deploy Staging

↓

Approval

↓

Deploy Production

↓

Notification

Module 34 — Real-World Project Examples

Project 1

Node.js Application CI

  • Install dependencies
  • Run ESLint
  • Run Unit Tests
  • Upload Coverage

Project 2

Python Project

  • Install Python
  • Install Requirements
  • Execute Pytest
  • Generate HTML Report

Project 3

Playwright Automation

  • Install Node
  • Install Browsers
  • Execute Tests
  • Upload HTML Report
  • Upload Allure Report

Project 4

Java Selenium

  • Setup Java
  • Setup Maven
  • Execute TestNG
  • Publish Report

Project 5

Docker Deployment

  • Build Image
  • Push Docker Hub
  • Deploy EC2

Project 6

AWS Deployment

  • Build
  • SCP Files
  • Restart Service

Step-by-Step Guide to Install Git on MacOS

Method 1: Install Git Using Homebrew (Recommended)

Step 1: Open Terminal

Press:

  • Command (⌘) + Space
  • Type Terminal
  • Press Enter

Step 2: Check if Git is Already Installed

Run:

git --version

If Git is installed, you’ll see output like:

git version 2.45.0

If not installed, continue below.


Step 3: Install Homebrew (If Not Installed)

Run this command in Terminal:

/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

Wait for installation to complete.


Step 4: Verify Homebrew Installation

Run:

brew --version

Example output:

Homebrew 4.3.0

Step 5: Install Git Using Homebrew

Run:

brew install git

Homebrew downloads and installs the latest Git version.


Step 6: Verify Git Installation

Run:

git --version

Example:

git version 2.45.1

Step 7: Configure Git Username

Run:

git config --global user.name "Your Name"

Example:

git config --global user.name "Deepesh Yadav"

Step 8: Configure Git Email

Run:

git config --global user.email "your-email@example.com"

Example:

git config --global user.email "deepesh@gmail.com"

Step 9: Verify Git Configuration

Run:

git config --list

Example output:

user.name=Deepesh Yadav
user.email=deepesh@gmail.com