A reference implementation of a continuous integration and deployment workflow using GitHub Actions, automated tests, controlled deployments, semantic version tags, and deployment notifications.
The repository contains a React Pokédex application used to demonstrate the complete delivery lifecycle from pull-request validation to production deployment on Render.
The application is hosted on Render and may require a short startup period after inactivity.
- Continuous integration for pushes and pull requests targeting
main. - Static code analysis with ESLint.
- Component and unit testing with Jest.
- Production builds with Webpack.
- End-to-end browser testing with Playwright.
- Deployment to Render only after successful validation.
- Automatic patch-version tags after deployment.
- Success and failure notifications through Discord.
- Optional deployment skipping through commit-message controls.
- Protected-branch and pull-request workflows.
- Operational health and version endpoints.
- React
- React Router
- Axios
- Express
- PokeAPI
- JavaScript
- Webpack
- Babel
- Jest
- React Testing Library
- Playwright
- ESLint
- GitHub Actions
- Render
- Git version tags
- Discord deployment notifications
Browser
|
| HTTP
v
React application
|
| REST requests
v
PokeAPI
For production, Webpack generates the frontend assets in the dist directory. A small Express server serves those static files and exposes operational endpoints.
Pull request to main
|
v
Install dependencies
|
v
Run ESLint
|
v
Run Jest tests
|
v
Create production build
|
v
Run Playwright E2E tests
|
v
Validation complete
For an eligible push to main, the workflow continues:
Successful validation
|
v
Trigger Render deployment
|
+----------------------+
| |
v v
Create patch version tag Send success notification
If validation, deployment, or version tagging fails, the workflow sends a failure notification containing repository, commit, branch, workflow, and run information.
The GitHub Actions workflow runs when:
- A commit is pushed to
main. - A pull request targeting
mainis opened. - A pull request targeting
mainreceives new commits.
Pull requests execute the validation pipeline but do not deploy the application.
Deployment, version tagging, and success notifications only execute for eligible pushes to main.
A commit containing the following token skips deployment and version tagging:
#skip
The validation stages still run, allowing documentation or maintenance changes to be checked without triggering a new deployment.
Example:
docs: improve project documentation #skip
After a successful production deployment, the pipeline creates a new Git tag using a patch-version increment.
Example:
v1.0.0
v1.0.1
v1.0.2
The workflow uses the repository-provided GITHUB_TOKEN to create and push the tag.
This mechanism creates version tags; it does not currently generate GitHub Release pages or release artifacts.
The workflow sends Discord notifications for:
- Successful production deployments.
- Validation, deployment, or version-tagging failures.
Notifications include contextual information such as:
- Repository.
- Commit SHA.
- Branch.
- Workflow.
- Run number.
The deployment workflow requires:
RENDER_DEPLOY_HOOK
DISCORD_WEBHOOK
RENDER_DEPLOY_HOOK triggers the Render deployment.
DISCORD_WEBHOOK sends success and failure notifications.
Secrets must be configured through GitHub repository settings and must never be committed to source control.
| Method | Endpoint | Purpose |
|---|---|---|
GET |
/health |
Verify that the Express application is running |
GET |
/version |
Return the current application version value |
Example health response:
ok
Playwright starts the production application locally before executing the browser tests.
The current E2E suite verifies that:
- The Pokédex front page opens successfully.
- Pokémon information is displayed.
- A user can navigate from the list to an individual Pokémon page.
- Expected details are displayed after navigation.
- Node.js
- npm
git clone https://github.com/dannydj/fullstackopen-cicd.git
cd fullstackopen-cicdnpm installnpm startThe Webpack development server runs by default at:
http://localhost:8080
npm run buildnpm run start-prodThe Express server runs by default at:
http://localhost:5001
Run the Jest test suite:
npm testRun static code analysis:
npm run eslintRun the Playwright end-to-end suite:
npm run test:e2ePlaywright automatically builds and starts the production application before executing the E2E tests.
fullstackopen-cicd/
├── .github/
│ └── workflows/
│ └── pipeline.yml
├── e2e-tests/
│ └── pokedex.spec.js
├── public/
├── src/
├── app.js
├── package.json
├── playwright.config.js
├── webpack.config.js
└── README.md
- The
/versionendpoint is currently maintained independently from the generated Git tags. - The pipeline creates Git tags but does not create GitHub Releases.
- Deployment verification does not currently include a post-deployment smoke test.
- The application depends on the availability of the external PokeAPI service.
- Discord notifications depend on an externally configured webhook.
- The project is intended as a CI/CD reference and not as a production Pokémon service.
- Synchronize the
/versionendpoint with the generated release tag. - Add a post-deployment health-check or smoke-test job.
- Replace
npm installwith deterministicnpm ciexecution. - Cache npm and Playwright dependencies between workflow runs.
- Generate deployment artifacts and GitHub Releases.
- Pin every third-party GitHub Action to an immutable commit SHA.
- Add dependency and security scanning.
- Use job-specific minimum GitHub Actions permissions.
- Add workflow concurrency controls to prevent overlapping deployments.
The concepts from this repository were also applied to a separate full-stack application:
Full-Stack Phonebook with CI/CD
That project demonstrates a React, Node.js, Express, and MongoDB application with its own validation and deployment pipeline.
This repository was developed as part of the University of Helsinki's Full Stack Open — Part 11: Continuous Integration / Continuous Deployment.
The application uses the course's Pokédex starter project as the system under delivery. The GitHub Actions workflow, automated deployment, version tagging, notifications, and related delivery controls were implemented as part of the CI/CD exercises.
The project retains the ISC license metadata from the original starter project.