Learn
🤖 AI Hub 📰 News 📖 Dictionary 🧰 Resources
Grow
💼 Jobs 🚀 Community 🏆 Challenges
Explore by Stage
🌑 Zero 📚 Learn 🔧 Practice 🏗 Build 🚀 Launch 💰 Earn
Account
Login Sign Up
🏗️HTML 🎨CSS ⚡JavaScript 🐙Git & GitHub ⚛️React Soon 📘TypeScript Soon 🐍Python 🗄️Database & SQL Soon 🌐Web Development Soon ☁️Cloud & DevOps Soon 🤖AI & ML Soon 📄Resume Prep Soon 🎤Interview Prep Soon 💼Freelancing Soon 🚀SaaS & Side Projects Soon 🤖Automation Soon
Advanced 🕑 12 min read 👁 4 views 📅 Oct 22, 2026

GitHub Actions: Automating Checks for Your Project

Write your first GitHub Actions workflow that checks every HTML page on each push and pull request, read the logs, and deploy your site to GitHub Pages automatically.

The Guard at the College Gate

At the main gate of most colleges there is a security guard who checks every visitor’s ID card. Nobody has to call the principal each time a student walks in. The rule is set once, and the guard applies it to every person, every day, without getting tired or forgetting.

GitHub Actions is a guard for your repository. You write the rule once, for example “every HTML page must be valid and have a title”, and GitHub checks it automatically every time someone pushes code or opens a pull request. Asha, Ravi and Imran no longer need to test the Utsav fest site by hand: if something is wrong, GitHub shows a red cross before the mistake reaches the live site.

What Is CI?

CI stands for Continuous Integration. “Integration” means joining everyone’s work together; “continuous” means doing it often, in small pieces. CI is the habit of checking every change automatically as soon as it is pushed. Its partner, CD (Continuous Delivery or Deployment), publishes the checked work automatically. GitHub Actions can do both.

Even a small student team needs this, because people forget. If Ravi pushes a broken page at midnight, a CI check tells him within minutes which line is wrong.

The Parts of a Workflow

A workflow is a YAML file inside the folder .github/workflows/ of your repository. The folder name must be exactly this, starting with a dot. A file can have any name ending in .yml or .yaml.

college-fest-site/
├── .github/
│   └── workflows/
│       └── check.yml      <- your workflow file
├── index.html
├── schedule.html
├── register.html
└── README.md

Inside a workflow, the words fit together like this:

Workflow  (one YAML file in .github/workflows/)
  │
  ├── on: the EVENT that starts it (push, pull_request, ...)
  │
  └── jobs:
        └── a JOB  (runs on a RUNNER, a fresh virtual computer)
              ├── step 1: uses: an action someone already wrote
              ├── step 2: run: your own terminal command
              └── step 3: run: another command
WordMeaningAt the college gate
EventWhat starts the workflow, such as a push or a pull requestA visitor arrives
JobA group of steps that run together on one machineThe ID check
RunnerThe virtual computer GitHub starts for the job, for example ubuntu-latest (Linux)The guard on duty
StepOne task in the job: an action or a commandLook at the card, compare the photo
ActionA ready-made, reusable step, used with uses:A card scanner bought from a company

Each job gets a fresh, empty runner, so the first step almost always downloads your code.

YAML in One Minute

YAML is a simple format for settings. key: value sets a value, indentation with spaces shows what belongs inside what, and a line starting with - is an item in a list. Tabs are not allowed, and wrong indentation is the most common reason a workflow breaks.

Your First Workflow: check.yml

Asha creates .github/workflows/check.yml with this content:

name: Check HTML

on:
  push:
    branches: [main]
  pull_request:

jobs:
  html-check:
    runs-on: ubuntu-latest

    steps:
      - name: Get the code
        uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: lts/*

      - name: Validate every HTML page
        run: npx --yes html-validate "*.html"

      - name: Make sure every page has a title
        run: |
          for page in *.html; do
            if ! grep -qi "<title>" "$page"; then
              echo "$page has no <title> tag"
              exit 1
            fi
          done
          echo "All pages have a title."

Here is every line explained:

LineWhat it does
name: Check HTMLThe name shown in the Actions tab and next to commits.
on:Starts the list of events that run this workflow.
push: with branches: [main]Run when someone pushes to main.
pull_request:Run when a pull request is opened, or new commits are pushed to it.
jobs:Starts the list of jobs.
html-check:The job’s ID. You choose it: small letters and hyphens.
runs-on: ubuntu-latestRun on GitHub’s newest standard Linux runner. Windows and macOS runners also exist.
steps:Starts the list of steps, run from top to bottom.
- name: Get the codeA new step with a readable name for the logs.
uses: actions/checkout@v4The official checkout action copies your repository onto the runner. @v4 is its major version.
uses: actions/setup-node@v4Installs Node.js, which gives us the npx command.
with: and node-version: lts/*Settings for that action: use the current long-term support version of Node.js.
run: npx --yes html-validate "*.html"Runs a command: npx downloads the free html-validate tool, which checks every .html file in the top folder. --yes skips the “install it?” question.
run: |The | means “several lines of commands follow”.
The for loopA small shell script: for each page, grep looks for <title>. If one is missing, it prints the page name and runs exit 1.

The key rule: a step fails when its command ends with a non-zero exit code (like exit 1), and then the job stops and is marked as failed.

uses or run?

uses: runs an action written by someone else, named as owner/repository@version. Actions from the actions/ owner are made by GitHub. run: runs your own command in the runner’s terminal, as you would type it in Git Bash. Only use actions you trust, because they run with access to your code.

Add the workflow to the repository

# From the top folder of college-fest-site
mkdir -p .github/workflows
code .github/workflows/check.yml      # or create the file in the VS Code Explorer

# After pasting the workflow and saving:
git add .github/workflows/check.yml
git commit -m "Add HTML check workflow"
git push
Windows users: these commands work in Git Bash. You can also create the folders and the file in the VS Code Explorer.

Reading the Actions Tab and the Logs

Open the repository on GitHub and click the Actions tab. Each push creates a new run of the workflow. Click a run, then the job html-check, then a step to open its log, the text the runner printed. A yellow dot means the run is still working.

A week later, Imran adds the registration page and opens a pull request. The check fails. In the log he sees something like:

Run npx --yes html-validate "*.html"

/home/runner/work/college-fest-site/college-fest-site/register.html
  14:6  error  <img> is missing required "alt" attribute  wcag/h37

✖ 1 problem (1 error, 0 warnings)

More information:
  https://html-validate.org/rules/wcag/h37.html
Error: Process completed with exit code 1.

The log names the file, the line and column (14:6) and the rule:

<!-- register.html, line 14: the check fails here -->
<img src="images/utsav-logo.png">

He adds the missing alt text, commits and pushes again to the same branch:

<!-- Fixed: every image needs alt text for screen readers -->
<img src="images/utsav-logo.png" alt="Utsav 2026 fest logo">

The workflow runs again by itself and passes.

Green tick, red cross

GitHub shows a green tick for success or a red cross for failure next to each commit and in the pull request, where the list of checks has a Details link to the log. Owners can also add a branch protection rule or ruleset (under Settings) so that a pull request cannot be merged until the checks pass: the guard does not open the gate without a valid ID.

Real-Life Example: Deploying the Fest Site with Actions

In the GitHub Pages Deploy lesson, the team published the site from a branch. Pages can also be published by a workflow, which is useful when you want checks or build steps first.

Part 1, on GitHub: open Settings, then Pages. Under Build and deployment, set Source to GitHub Actions.

Part 2, the workflow: she adds .github/workflows/deploy.yml:

name: Deploy site to GitHub Pages

on:
  push:
    branches: [main]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: pages
  cancel-in-progress: false

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}

    steps:
      - name: Get the code
        uses: actions/checkout@v4

      - name: Set up Pages
        uses: actions/configure-pages@v5

      - name: Upload the site files
        uses: actions/upload-pages-artifact@v3
        with:
          path: .

      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v4
PartWhat it does
workflow_dispatch:Adds a Run workflow button in the Actions tab, so you can deploy by hand.
permissions:What the workflow may do: read the code, write to Pages, and get a short-lived token that proves the deployment comes from this repository.
concurrency:Only one deployment runs at a time. A newer one waits instead of clashing.
environment:Records the deployment and shows the site link on the run page.
actions/configure-pagesReads your Pages settings and prepares the deployment.
actions/upload-pages-artifact with path: .Packs the files to publish (here, the top folder) into an artifact, a bundle of files stored with the run.
actions/deploy-pagesPublishes that artifact. Its id: deployment lets environment read the page address.

After the next push to main, the run shows the link to https://asha-utsav-demo.github.io/college-fest-site/. The versions after @ change over time, so check each action’s page for the newest major version.

Try these changes:

  1. Remove branches: [main] from check.yml so the check runs on pushes to every branch.
  2. Add one more step to check.yml with run: test -f index.html, which fails if the home page is ever deleted.
  3. Add workflow_dispatch: to check.yml and run it by hand from the Actions tab.

Secrets: Never Hard-Code Keys

Some workflows need a password or API key, for example to send a message to the team when the site is deployed. Never write a key in any file in your repository: others can copy it, and it stays in the Git history even after you delete it. Instead, open Settings, then Secrets and variables, then Actions, and add a repository secret. The workflow reads it like this:

      - name: Send launch message
        run: ./scripts/notify.sh
        env:
          NOTIFY_TOKEN: ${{ secrets.NOTIFY_TOKEN }}

GitHub hides secret values in the logs, and does not give secrets to workflows started by pull requests from forks.

Is It Free?

For public repositories, GitHub Actions on GitHub’s standard runners is free. For private repositories, each account gets a monthly amount of free minutes and storage, and the amount depends on your plan. Check the current numbers in GitHub’s billing documentation.

Common Mistakes

  • Wrong folder name. .github/workflow/ (missing “s”) or github/workflows/ (missing dot) is ignored silently. Fix: the path must be .github/workflows/.
  • Bad indentation. A step two spaces off breaks the file. Fix: use spaces only and line up items under their parent.
  • Forgetting the checkout step. The runner starts empty, so later steps find no files. Fix: start with uses: actions/checkout@v4.
  • A check that never fails. If your script prints an error but does not exit 1, the step stays green. Fix: always end a failed check with a non-zero exit code.
  • Pasting keys into YAML. Fix: delete the key, create a new one with the service, and store it as a secret.

Practice Task: Let the Guard Catch a Mistake

  1. Add check.yml from this lesson to your college-fest-site repository and push it. Check that the run on main is green.
  2. On a new branch gallery, add the page below. It has a deliberate mistake.
  3. Push the branch and open a pull request. Watch the check fail and read the log.
  4. Fix the mistake, push again, and watch the pull request turn green.
<!-- gallery.html: add this page, then push it on a branch -->
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Utsav Gallery</title>
</head>
<body>
  <h1>Photos from Utsav 2025</h1>
  <img src="https://picsum.photos/400/250">
</body>
</html>
Show one possible answer (try it yourself first!)
# 1. Create the workflow file (paste check.yml from the lesson) and push it
mkdir -p .github/workflows
#    (create .github/workflows/check.yml and save)
git add .github/workflows/check.yml
git commit -m "Add HTML check workflow"
git push

# 2. Open the Actions tab on GitHub: the run on main should be green

# 3. Add the gallery page on a new branch
git switch -c gallery
#    (create gallery.html with the starter code)
git add gallery.html
git commit -m "Add gallery page"
git push -u origin gallery

# 4. Open a pull request. The "Check HTML" check fails with:
#    <img> is missing required "alt" attribute

# 5. Fix the image line in gallery.html:
#    <img src="https://picsum.photos/400/250" alt="Students dancing on the main stage">
git commit -am "Add alt text to gallery image"
git push
#    The check runs again on the pull request and turns green.

Key Takeaways

  • CI checks every change automatically. GitHub Actions runs it for you.
  • A workflow lives in .github/workflows/; it has events (on:), jobs, a runner (runs-on:) and steps.
  • uses: runs a ready-made action; run: runs your own command. A non-zero exit code fails the step.
  • Read results in the Actions tab and as green ticks or red crosses on commits and pull requests.
  • GitHub Pages can be deployed with actions/upload-pages-artifact and actions/deploy-pages after setting the Pages source to GitHub Actions.
  • Keep keys in secrets, never in files.

❓ Frequently Asked Questions

No. The workflows run on GitHub's own runners. You only add a YAML file in .github/workflows/ and push it.
Usually the file is in the wrong folder or the YAML has an error. Check that the path is exactly .github/workflows/ and look at the Actions tab for an error message about the file.
uses runs a ready-made action from another repository, such as actions/checkout. run runs a terminal command that you write yourself.
Public repositories can use GitHub's standard runners for free. Private repositories get a limited amount of free minutes each month, which depends on the account plan.
Only if you give them to it as secrets. Store keys under Settings, Secrets and variables, Actions, and read them with the secrets context. Never write them in a file.
Was this lesson helpful?

🎯 Finished this lesson?

🔗 Related Tutorials
🤖 Got a Doubt? Ask AI
Get instant answers in Hindi or English
🤖
Z2T Bot
Online
Ask me anything about this tutorial — I'm here! 👋