{"id":30083757,"url":"https://github.com/flyjeray/react-ci-cd-practice","last_synced_at":"2026-04-10T13:32:16.900Z","repository":{"id":305495241,"uuid":"1023029785","full_name":"flyjeray/react-ci-cd-practice","owner":"flyjeray","description":"CI/CD practice - Jest, Linters, Artifacts, Cache, Composite Actions, GH Pages, Slack updates, concurrency","archived":false,"fork":false,"pushed_at":"2026-01-30T15:09:07.000Z","size":525,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-01-31T08:07:27.490Z","etag":null,"topics":["cicd","eslint","github-actions","github-pages","husky","jest","prettier","react","slack"],"latest_commit_sha":null,"homepage":"https://flyjeray.github.io/react-ci-cd-practice/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/flyjeray.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-07-20T11:29:02.000Z","updated_at":"2026-01-30T15:09:12.000Z","dependencies_parsed_at":"2025-07-20T23:29:18.664Z","dependency_job_id":"37a981de-69f8-436e-9c60-90dd60bd49f4","html_url":"https://github.com/flyjeray/react-ci-cd-practice","commit_stats":null,"previous_names":["flyjeray/react-ci-cd-testing-practice","flyjeray/react-ci-cd-practice"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/flyjeray/react-ci-cd-practice","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flyjeray%2Freact-ci-cd-practice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flyjeray%2Freact-ci-cd-practice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flyjeray%2Freact-ci-cd-practice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flyjeray%2Freact-ci-cd-practice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/flyjeray","download_url":"https://codeload.github.com/flyjeray/react-ci-cd-practice/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/flyjeray%2Freact-ci-cd-practice/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31645284,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-10T07:40:12.752Z","status":"ssl_error","status_checked_at":"2026-04-10T07:40:11.664Z","response_time":98,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cicd","eslint","github-actions","github-pages","husky","jest","prettier","react","slack"],"created_at":"2025-08-08T23:01:10.197Z","updated_at":"2026-04-10T13:32:16.885Z","avatar_url":"https://github.com/flyjeray.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# React CI/CD Practice\n\nA practice project implementing continuous integration and deployment pipelines with GitHub Actions.\n\n\u003e **Note:** This project was created as a learning exercise to explore CI/CD concepts with GitHub Actions. It demonstrates workflows, custom actions, and deployment strategies suitable for a small React application.\n\n## 📋 Table of Contents\n\n- [Overview](#overview)\n- [CI/CD Architecture](#cicd-architecture)\n- [Pull Request Workflow](#pull-request-workflow)\n- [Deployment Pipeline](#deployment-pipeline)\n- [Reusable Workflows \u0026 Custom Actions](#reusable-workflows--custom-actions)\n\n## Overview\n\nThis is a React TypeScript application built to practice and demonstrate modern CI/CD patterns using GitHub Actions. The project showcases automated testing, code quality checks, parallel job execution, artifact sharing, and continuous deployment to GitHub Pages.\n\n**Key Features:**\n\n- Automated pull request validation with parallel checks\n- Continuous deployment to GitHub Pages on merge\n- Build artifact sharing across workflow jobs\n- Reusable workflow components for notifications\n- Custom composite action for Node.js setup\n- Slack integration for build status notifications\n\n## CI/CD Architecture\n\nThe project implements a complete CI/CD pipeline split across three workflows, each serving a specific purpose:\n\n```\n.github/\n├── actions/\n│   └── setup-node/              # Custom composite action\n│       └── action.yaml          # Node.js setup with caching\n└── workflows/\n    ├── main.yml                 # Pull request validation\n    ├── deploy.yaml              # Production deployment\n    └── reusable-slack-notify.yml # Shared notification workflow\n```\n\n### Pipeline Overview\n\nThe CI/CD strategy separates concerns between validation (PR checks) and deployment (production releases), ensuring code quality before any changes reach production.\n\n**Pull Request Flow:**\n\n```\nPR Created/Updated\n    ↓\nBuild React App\n    ↓\n┌────────────┬──────────────┬──────────────┐\n│  Lint      │  Type Check  │  Test        │ (Parallel)\n│  (ESLint)  │  (TypeScript)│  (Jest)      │\n└────────────┴──────────────┴──────────────┘\n    ↓\nSlack Notification (Success/Failure)\n```\n\n**Deployment Flow:**\n\n```\nPush to Main Branch\n    ↓\nBuild Production Bundle\n    ↓\nDeploy to GitHub Pages\n    ↓\nSlack Notification (Success/Failure)\n```\n\n## Pull Request Workflow\n\n**File:** `.github/workflows/main.yml`\n\n**Trigger:** Every pull request targeting the `main` branch\n\nThe pull request workflow runs comprehensive quality checks before allowing code to be merged. It's designed to fail fast and provide quick feedback to developers.\n\n### Workflow Features\n\n**Concurrency Control:**\n\n```yaml\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n```\n\nWhen a new commit is pushed to a PR, any in-progress workflow runs for that PR are automatically cancelled. This saves compute resources and provides faster feedback on the latest code.\n\n**Job Execution Strategy:**\n\n1. **Build job** runs first and creates a production build\n2. Build artifacts are uploaded for reuse\n3. **Lint, Type Check, and Test jobs** run in parallel (no dependencies between them)\n4. Each parallel job downloads the build artifact\n5. **Notification job** runs after all checks complete\n\n### Job Details\n\n#### Build\n\nCompiles the React application and uploads the build output for subsequent jobs.\n\n```yaml\n- uses: ./.github/actions/setup-node # Custom action\n  with:\n    node-version: 18\n- run: npm run build\n- uses: actions/upload-artifact@v4\n  with:\n    name: react-build\n    path: ./build\n```\n\nBy building once and sharing the artifact, the workflow avoids redundant build steps in each validation job.\n\n#### Lint \u0026 Formatting\n\nValidates code quality and consistent formatting:\n\n- **ESLint:** Checks for code quality issues and potential bugs\n- **Prettier:** Ensures consistent code formatting across the codebase\n\n```bash\nnpm run lint         # ESLint validation\nnpm run style-check  # Prettier formatting check\n```\n\n#### Type Checking\n\nRuns TypeScript compiler in type-check mode without emitting files:\n\n```bash\nnpm run typecheck  # tsc --noEmit\n```\n\nThis catches type errors that could lead to runtime bugs.\n\n#### Jest Testing\n\nExecutes the full test suite with coverage reporting:\n\n```bash\nnpm test  # jest --coverage\n```\n\nTests ensure components behave correctly and prevent regressions.\n\n#### Slack Notification\n\nSends a summary notification to Slack after all checks complete, whether they succeed or fail. Uses the reusable notification workflow (see below).\n\n## Deployment Pipeline\n\n**File:** `.github/workflows/deploy.yaml`\n\n**Trigger:** Every push to the `main` branch\n\nThe deployment workflow handles production releases, building and deploying the application to GitHub Pages.\n\n### Build and Deploy Job\n\n1. **Checkout code** from the main branch\n2. **Setup Node.js** with dependency caching\n3. **Build production bundle** with optimizations\n4. **Deploy to GitHub Pages** using the `peaceiris/actions-gh-pages@v4` action\n\n```yaml\n- name: Deploy to GitHub Pages\n  uses: peaceiris/actions-gh-pages@v4\n  with:\n    github_token: ${{ secrets.GITHUB_TOKEN }}\n    publish_dir: ./build\n```\n\nThe action automatically:\n\n- Creates or updates the `gh-pages` branch\n- Pushes the build directory contents\n- Configures GitHub Pages if not already set up\n\n### Deployment URL\n\nThe application is automatically deployed to: https://flyjeray.github.io/react-ci-cd-practice\n\n## Reusable Workflows \u0026 Custom Actions\n\n### Reusable Slack Notification Workflow\n\n**File:** `.github/workflows/reusable-slack-notify.yml`\n\nA workflow designed to be called by other workflows.\n\n**Usage example:**\n\n```yaml\njobs:\n  notify:\n    uses: ./.github/workflows/reusable-slack-notify.yml\n    with:\n      status: ${{ (contains(needs.*.result, 'failure') \u0026\u0026 'failure') || 'success' }}\n      title: \"Pull Request ${{ (contains(needs.*.result, 'failure') \u0026\u0026 'Failed') || 'Passed' }}\"\n      message: \"PR #${{ github.event.pull_request.number }} checks have finished.\"\n    secrets:\n      SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}\n```\n\n**Inputs:**\n\n- `status`: Determines notification color (success = green, failure = red)\n- `title`: Bold header text in Slack message\n- `message`: Body text with details and links\n\n**Implementation:**\n\nUses the `rtCamp/action-slack-notify@v2` action with conditional formatting based on status. Messages include:\n\n- GitHub icon and branding\n- Clickable links to workflow runs\n- Color-coded status indicators\n- Context about what triggered the notification\n\n### Custom Composite Action: `setup-node`\n\n**File:** `.github/actions/setup-node/action.yaml`\n\nA composite action that encapsulates the common Node.js setup pattern used across all workflows.\n\n**What it does:**\n\n1. **Installs Node.js** using the specified version\n2. **Restores npm cache** using a hash of `package-lock.json`\n3. **Installs dependencies** with `npm ci --prefer-offline`\n\n**Benefits:**\n\n- **DRY principle:** Setup logic defined once, used everywhere\n- **Consistent caching:** Same cache strategy across all workflows\n- **Maintainability:** Changes to setup process only need to be made in one place\n- **Performance:** Dependency caching significantly speeds up workflow runs\n\n**Usage:**\n\n```yaml\n- uses: ./.github/actions/setup-node\n  with:\n    node-version: 18\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflyjeray%2Freact-ci-cd-practice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fflyjeray%2Freact-ci-cd-practice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fflyjeray%2Freact-ci-cd-practice/lists"}