Testing is half of a pipeline; shipping is the other half. In this lesson you will deploy a site to GitHub Pages, publish a Playwright report, push a Docker image to GitHub Container Registry and build a staging-to-production pipeline with smoke tests and approvals.
đ What You’ll Learn: CI vs CD, deploying to GitHub Pages, publishing a Playwright HTML report, building and pushing Docker images to ghcr.io on tags, a staged pipeline with environments, smoke tests and required reviewers, OIDC for cloud credentials, and rolling back.
đ From CI to CD
So far your workflows test code (Continuous Integration). Continuous Delivery/Deployment (CD) goes further: after the tests pass, the pipeline ships the result, a website, a Docker image, a package or a test report, automatically and the same way every time.
A typical pipeline:
push to main âââļ build âââļ test âââļ deploy to staging âââļ smoke tests âââļ (approval) âââļ deploy to production
This lesson shows three common deployment targets and the safety features around them. It builds on workflow syntax and secrets and environments.
đ Example 1: Deploy a Static Site to GitHub Pages
# .github/workflows/pages.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:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: npm
- run: npm ci
- run: npm run build # creates ./dist
- uses: actions/upload-pages-artifact@v3
with:
path: ./dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4
In Settings, Pages, set Source to GitHub Actions. More in GitHub Pages.
Bonus for testers: publish the Playwright HTML report
Replace the build steps with your test run and upload playwright-report/ as the Pages artifact. The team then opens the latest report at a stable URL instead of downloading artifacts.
- run: npx playwright install --with-deps
- run: npx playwright test
continue-on-error: true # publish the report even when tests fail
- uses: actions/upload-pages-artifact@v3
with:
path: ./playwright-report
â ī¸ Common mistake: A Pages site from a public repository is public. Do not publish reports that contain sensitive data, screenshots of internal systems or traces with tokens.
đŗ Example 2: Build and Push a Docker Image to GitHub Container Registry
# .github/workflows/docker.yml
name: Docker image
on:
push:
tags: [ 'v*' ] # release when a version tag is pushed
permissions:
contents: read
packages: write
jobs:
image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: |
ghcr.io/acme/test-runner:${{ github.ref_name }}
ghcr.io/acme/test-runner:latest
Tagging a release (git tags) with git tag -a v1.2.0 -m "Release 1.2.0" and git push origin v1.2.0 triggers the build. Image names on ghcr.io must be lowercase. Running tests in containers is covered in Playwright with Docker and Kubernetes.
đĨī¸ Example 3: Staging and Production with Approvals
# .github/workflows/deploy.yml
name: Deploy
on:
push:
branches: [ main ]
concurrency:
group: deploy-${{ github.ref }}
cancel-in-progress: false # never cancel a deployment halfway
jobs:
test:
uses: ./.github/workflows/playwright-tests.yml # reusable test workflow
with:
base-url: https://qa.example.com
secrets: inherit
deploy-staging:
needs: test
runs-on: ubuntu-latest
environment:
name: staging
url: https://staging.example.com
steps:
- uses: actions/checkout@v4
- run: ./scripts/deploy.sh staging
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
smoke-staging:
needs: deploy-staging
runs-on: ubuntu-latest
environment: staging
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: lts/*
cache: npm
- run: npm ci && npx playwright install --with-deps chromium
- run: npx playwright test --grep @smoke --project=chromium
env:
BASE_URL: https://staging.example.com
deploy-production:
needs: smoke-staging
runs-on: ubuntu-latest
environment:
name: production # configured with required reviewers
url: https://www.example.com
steps:
- uses: actions/checkout@v4
- run: ./scripts/deploy.sh production
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
What makes this safe:
| Feature | Protection |
|---|---|
needs chain | Production only after tests, staging deployment and smoke tests pass |
Environment production with required reviewers | A person approves the production job |
| Environment deployment branches | Only main can deploy to production |
| Environment secrets | Staging and production use different credentials |
concurrency without cancel | Deployments run one at a time and are never cut off |
| Reusable workflow for tests | One test definition for every pipeline |
The deploy script depends on your hosting (cloud CLI, SSH, Kubernetes, a hosting provider’s action). For cloud providers, prefer OpenID Connect (OIDC): permissions: id-token: write plus the provider’s official login action, so no long-lived cloud keys are stored as secrets.
âŠī¸ Rolling Back
- Redeploy the previous version: re-run the deployment workflow for an earlier tag or commit (keep
workflow_dispatchwith areforversioninput). - Or revert the bad commit on
mainwithgit revertand let the pipeline deploy again (undo changes).
đ Assignment
- Deploy a simple static HTML page from a repository to GitHub Pages with the Pages workflow.
- Publish a Playwright HTML report to Pages from a practice (public, non-sensitive) project.
- Create
stagingandproductionenvironments; add yourself as required reviewer for production and restrict it tomain. - Build the staging â smoke test â production chain with
echodeploy steps and approve the production job. - Push a
v0.1.0tag and build a Docker image to ghcr.io (any small Dockerfile).
â FAQ
đ¤ How do I deploy with GitHub Actions?
Add a workflow that runs after tests (needs), uses an environment for the target, and runs the deployment step (a Pages action, a Docker push, a cloud CLI or a script) with secrets or OIDC credentials.
đ¤ How do I add manual approval before production deployment?
Create a production environment with required reviewers and reference it with environment: production in the deploy job.
đ¤ How do I publish a Playwright report with GitHub Actions?
Upload playwright-report/ with actions/upload-pages-artifact and deploy with actions/deploy-pages, or upload it as a normal artifact.
đ¤ How do I push a Docker image to GitHub Container Registry?
Log in with docker/login-action to ghcr.io using GITHUB_TOKEN with packages: write permission, then build and push with docker/build-push-action.
đ¤ What is OIDC in GitHub Actions?
OpenID Connect lets workflows get short-lived cloud credentials directly from the cloud provider, so you do not store long-lived keys as secrets.
đ¯ Next Steps
- đī¸ GitHub Actions Hands-on Practice Projects
- đ GitHub Pages: Host a Website for Free
- đ Git and GitHub Tutorial: full course
đŦ Learn Git and GitHub step by step: watch the series on YouTube!
Subscribe to SqaToolsByDY • Practice on sqatools.in
2 thoughts on “Deploy with GitHub Actions: GitHub Pages, Docker Images and Staged Releases”