Frontend Pipeline Stages
Each pipeline consists of two jobs (lint and build-and-deploy) running on an ubuntu-latest runner. Stages are executed sequentially with environment-specific configurations for the Acharya ERP frontend, a React-based application.
Below is an explanation of key terms from the CI/CD pipeline for the frontend of the Acharya ERP system, a React-based application. The pipeline ensures the React app is linted, built, tested, secured, and deployed reliably to a development environment using AWS S3 and CloudFront. Relevant YAML snippets from the workflow are included for each stage.
Terms Explained
1. Checkout Code
Retrieves the source code from the repository.
- Tool: Uses
actions/checkout@v4to clone thedevbranch of the Acharya ERP repository. - Why It’s Needed: Provides the React codebase for linting, building, and testing.
- YAML Snippet:
- name: Checkout code
uses: actions/checkout@v42. Set up Node.js
Configures the Node.js environment for the React app.
- Tool: Uses
actions/setup-node@v4to install Node.js (version 18). - Why It’s Needed: Enables npm commands for dependency management, linting, building, and testing.
- YAML Snippet:
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18.x'
cache: 'npm'3. Cache npm Dependencies
Speeds up builds by caching dependencies.
- Tool: Uses
actions/cache@v4to cachenode_modulesbased onpackage-lock.json. - Why It’s Needed: Reduces build time for the Acharya ERP frontend.
- YAML Snippet:
- name: Cache npm dependencies
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-4. Install Dependencies
Installs the necessary npm packages for the React app.
- Tool: Uses
npm cifor a clean and consistent installation of dependencies. - Why It’s Needed: Ensures all required libraries are available for linting, building, and testing.
- YAML Snippet:
- name: Install dependencies
run: npm ci5. Run ESLint
Analyzes the React app’s source code for coding issues and security vulnerabilities.
- Tool: ESLint checks JavaScript code for errors or insecure patterns via
npm run lint -- --quiet --format json. - Why It’s Needed: Improves code quality and security for the Acharya ERP app.
- YAML Snippet:
- name: Run ESLint
run: |
LINT_ERRORS=$(npm run lint -- --quiet --format json | jq '.[] | select(.errorCount > 0)')
if [ -n "$LINT_ERRORS" ]; then
echo "❌ ESLint found errors"
exit 1
else
echo "✅ ESLint passed with no errors"
fi6. Build Application
Compiles the React app’s source code (JavaScript, CSS, HTML) into a deployable package.
- Tool: Uses
npm run buildto generate static assets, with environment variables likeREACT_APP_API_URL. - Why It’s Needed: Creates the production-ready assets for the Acharya ERP frontend.
- YAML Snippet:
- name: Build application
run: npm run build
env:
REACT_APP_API_URL: ${{ secrets.REACT_APP_API_URL_DEV }}7. Run Unit Tests with Jest
Runs automated tests to validate individual components (e.g., React components, functions).
- Tool: Uses
npm test -- --coveragewith Jest for unit tests and coverage reports. - Why It’s Needed: Ensures functionality and reliability of the Acharya ERP app.
- YAML Snippet:
- name: Run tests
run: npm test -- --coverage
continue-on-error: false8. Publish Test Results
Displays test results in GitHub for visibility.
- Tool: Uses
dorny/test-reporter@v1to publish Jest JUnit reports (coverage/junit.xml). - Why It’s Needed: Provides feedback on test outcomes for developers.
- YAML Snippet:
- name: Publish Test Results
uses: dorny/test-reporter@v1
if: always()
with:
name: Jest Tests (Dev)
path: coverage/junit.xml
reporter: jest-junit
fail-on-error: false
continue-on-error: true9. Upload Test Artifacts
Stores test and coverage reports for later analysis.
- Tool: Uses
actions/upload-artifact@v4to uploadjunit.xmland other reports (30-day retention). - Why It’s Needed: Allows developers to review test details for the Acharya ERP app.
- YAML Snippet:
- name: Upload Test Results as Artifacts
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-dev
path: coverage/junit.xml
retention-days: 3010. Upload Coverage to Codecov
Tracks coverage metrics over time.
- Tool: Uses
codecov/codecov-action@v4to uploadlcov.infoto Codecov. - Why It’s Needed: Monitors coverage trends to ensure test quality.
- YAML Snippet:
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v4
if: always()
with:
file: ./coverage/lcov.info
flags: unittests
name: codecov-umbrella-dev11. Check Code Coverage
Ensures the code coverage meets a minimum threshold (80%).
- Tool: Parses
coverage/coverage-summary.jsonto verify line coverage percentage. - Why It’s Needed: Enforces high test coverage to reduce bugs in the Acharya ERP system.
- YAML Snippet:
- name: Check Code Coverage
run: |
if [ ! -f ./coverage/coverage-summary.json ]; then
echo "❌ Coverage summary file not found"
exit 1
fi
COVERAGE=$(node -p "require('./coverage/coverage-summary.json').total.lines.pct")
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
echo "❌ Code coverage is $COVERAGE%, below the 80% threshold"
exit 1
else
echo "✅ Code coverage is $COVERAGE%, meets the 80% threshold"
fi12. SCA (Software Composition Analysis)
Scans third-party dependencies (e.g., React libraries, npm packages) for vulnerabilities or outdated versions.
- Tool: Dependabot automatically creates pull requests for updating JavaScript dependencies, configured via
.github/dependabot.yml. - Why It’s Needed: Ensures dependency security for the Acharya ERP frontend.
- YAML Snippet: Not part of the main workflow; configured in
.github/dependabot.yml.
13. Log in to Docker Hub
Authenticates with Docker Hub to enable image pushing.
- Tool: Uses
docker/login-action@v3with credentials stored in GitHub secrets. - Why It’s Needed: Allows the pipeline to publish Docker images for the Acharya ERP app.
- YAML Snippet:
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME_DEV }}
password: ${{ secrets.DOCKER_PASSWORD_DEV }}14. Build Docker Image
Packages the React app into a portable Docker image.
- Tool: Uses
docker buildto create an image tagged asfrontend:dev-<sha>andfrontend:dev-latest. - Why It’s Needed: Ensures consistent environments for testing and deployment.
- YAML Snippet:
- name: Build Docker Image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-${{ github.sha }} .
docker tag ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-${{ github.sha }} ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-latest15. Scan Docker Image with Trivy
Checks the Docker image for vulnerabilities in dependencies or configuration.
- Tool: Uses
aquasecurity/trivy-action@masterto scan and output results in SARIF format (trivy-results.sarif). - Why It’s Needed: Ensures container security before deployment.
- YAML Snippet:
- name: Scan Docker Image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
exit-code: '1'
severity: 'CRITICAL'16. Upload Trivy Scan Results
Displays Docker image vulnerabilities in GitHub.
- Tool: Uses
github/codeql-action/upload-sarif@v3to uploadtrivy-results.sarif. - Why It’s Needed: Provides visibility into container security issues.
- YAML Snippet:
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v3
if: always() && github.actor != 'dependabot[bot]'
with:
sarif_file: 'trivy-results.sarif'17. Push Docker Image to Docker Hub
Publishes the Docker image to a registry.
- Tool: Uses
docker pushto uploadfrontend:dev-<sha>andfrontend:dev-latestto Docker Hub. - Why It’s Needed: Makes the image available for deployment or sharing in the Acharya ERP pipeline.
- YAML Snippet:
- name: Push Docker Image to Docker Hub
run: |
docker push ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-${{ github.sha }}
docker push ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-latest18. Smoke Test
Verifies core functionality of the React app within the Docker image (e.g., app loads, key components render).
- Tool: Runs the Docker image and checks for an HTTP 200 status on the homepage endpoint using
curl. - Why It’s Needed: Ensures the Acharya ERP frontend is stable for deployment.
- YAML Snippet:
- name: Smoke Test
run: |
echo "Starting smoke test (Dev)..."
docker stop smokerun-dev 2>/dev/null || true
docker rm smokerun-dev 2>/dev/null || true
docker run -d --name smokerun-dev -p 8080:80 \
${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-${{ github.sha }}
echo "Waiting for application to start..."
for i in {1..6}; do
if curl -f -s http://localhost:8080 > /dev/null 2>&1; then
echo "✅ Application started successfully!"
break
fi
if [ $i -eq 6 ]; then
echo "❌ Application failed to start within 30 seconds"
docker logs smokerun-dev
docker rm -f smokerun-dev
exit 1
fi
echo "Waiting... (attempt $i/6)"
sleep 5
done
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080)
if [ "$HTTP_STATUS" -eq 200 ]; then
echo "✅ HTTP status check passed (200 OK)"
else
echo "❌ HTTP status check failed (returned $HTTP_STATUS)"
docker rm -f smokerun-dev
exit 1
fi
docker rm -f smokerun-dev
echo "✅ Smoke test completed successfully!"19. Configure AWS Credentials
Authenticates with AWS for S3 and CloudFront access.
- Tool: Uses
aws-actions/configure-aws-credentials@v4with dev-specific credentials. - Why It’s Needed: Enables deployment to AWS services.
- YAML Snippet:
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_DEV }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_DEV }}
aws-region: ${{ secrets.AWS_REGION_DEV }}20. Deploy to S3
Deploys the React app’s static assets to an S3 bucket.
- Tool: Uses
aws s3 syncto upload thebuild/directory to an S3 bucket. - Why It’s Needed: Delivers the Acharya ERP frontend to users in the development environment.
- YAML Snippet:
- name: Deploy to S3
run: aws s3 sync ./build/ s3://${{ secrets.S3_BUCKET_DEV }} --delete21. Invalidate CloudFront Cache
Refreshes the CloudFront cache to serve the latest assets.
- Tool: Uses
aws cloudfront create-invalidationto invalidate cache paths (/*). - Why It’s Needed: Ensures users access the latest version of the Acharya ERP frontend.
- YAML Snippet:
- name: Invalidate CloudFront Cache
run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID_DEV }} --paths "/*"22. Notify Slack
Sends pipeline status notifications to a Slack channel.
- Tool: Uses
slackapi/slack-github-action@v1to send a message to thedev-notificationschannel with pipeline status, commit, and run details. - Why It’s Needed: Keeps the team informed about pipeline outcomes for the Acharya ERP system.
- YAML Snippet:
- name: Notify Slack
if: always()
uses: slackapi/slack-github-action@v1
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: 'dev-notifications'
text: |
*Acharya ERP Frontend (Dev) Pipeline*
Status: ${{ job.status }}
Commit: ${{ github.sha }}
Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}YAML Workflow (Dev)
.github/workflows/frontend-dev.yml
name: Acharya ERP Frontend CI/CD (Dev)
on:
push:
branches:
- dev
permissions:
contents: read
actions: read
checks: write
pull-requests: write
security-events: write
statuses: write
jobs:
lint:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18.x'
cache: 'npm'
- name: Cache npm dependencies
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
- name: Run ESLint
run: |
LINT_ERRORS=$(npm run lint -- --quiet --format json | jq '.[] | select(.errorCount > 0)')
if [ -n "$LINT_ERRORS" ]; then
echo "❌ ESLint found errors"
exit 1
else
echo "✅ ESLint passed with no errors"
fi
build-and-deploy:
runs-on: ubuntu-latest
needs: lint
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '18.x'
cache: 'npm'
- name: Cache npm dependencies
uses: actions/cache@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
${{ runner.os }}-node-
- name: Install dependencies
run: npm ci
- name: Build application
run: npm run build
env:
REACT_APP_API_URL: ${{ secrets.REACT_APP_API_URL_DEV }}
- name: Run tests
run: npm test -- --coverage
continue-on-error: false
- name: Publish Test Results
uses: dorny/test-reporter@v1
if: always()
with:
name: Jest Tests (Dev)
path: coverage/junit.xml
reporter: jest-junit
fail-on-error: false
continue-on-error: true
- name: Upload Test Results as Artifacts
uses: actions/upload-artifact@v4
if: always()
with:
name: test-results-dev
path: coverage/junit.xml
retention-days: 30
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v4
if: always()
with:
file: ./coverage/lcov.info
flags: unittests
name: codecov-umbrella-dev
- name: Check Code Coverage
run: |
if [ ! -f ./coverage/coverage-summary.json ]; then
echo "❌ Coverage summary file not found"
exit 1
fi
COVERAGE=$(node -p "require('./coverage/coverage-summary.json').total.lines.pct")
if (( $(echo "$COVERAGE < 80" | bc -l) )); then
echo "❌ Code coverage is $COVERAGE%, below the 80% threshold"
exit 1
else
echo "✅ Code coverage is $COVERAGE%, meets the 80% threshold"
fi
- name: Log in to Docker Hub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME_DEV }}
password: ${{ secrets.DOCKER_PASSWORD_DEV }}
- name: Build Docker Image
run: |
docker build -t ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-${{ github.sha }} .
docker tag ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-${{ github.sha }} ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-latest
- name: Scan Docker Image with Trivy
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
exit-code: '1'
severity: 'CRITICAL'
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v3
if: always() && github.actor != 'dependabot[bot]'
with:
sarif_file: 'trivy-results.sarif'
- name: Push Docker Image to Docker Hub
run: |
docker push ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-${{ github.sha }}
docker push ${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-latest
- name: Smoke Test
run: |
echo "Starting smoke test (Dev)..."
docker stop smokerun-dev 2>/dev/null || true
docker rm smokerun-dev 2>/dev/null || true
docker run -d --name smokerun-dev -p 8080:80 \
${{ secrets.DOCKER_USERNAME_DEV }}/frontend:dev-${{ github.sha }}
echo "Waiting for application to start..."
for i in {1..6}; do
if curl -f -s http://localhost:8080 > /dev/null 2>&1; then
echo "✅ Application started successfully!"
break
fi
if [ $i -eq 6 ]; then
echo "❌ Application failed to start within 30 seconds"
docker logs smokerun-dev
docker rm -f smokerun-dev
exit 1
fi
echo "Waiting... (attempt $i/6)"
sleep 5
done
HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080)
if [ "$HTTP_STATUS" -eq 200 ]; then
echo "✅ HTTP status check passed (200 OK)"
else
echo "❌ HTTP status check failed (returned $HTTP_STATUS)"
docker rm -f smokerun-dev
exit 1
fi
docker rm -f smokerun-dev
echo "✅ Smoke test completed successfully!"
- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v4
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_DEV }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_DEV }}
aws-region: ${{ secrets.AWS_REGION_DEV }}
- name: Deploy to S3
run: aws s3 sync ./build/ s3://${{ secrets.S3_BUCKET_DEV }} --delete
- name: Invalidate CloudFront Cache
run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID_DEV }} --paths "/*"
- name: Notify Slack
if: always()
uses: slackapi/slack-github-action@v katon
with:
slack-bot-token: ${{ secrets.SLACK_BOT_TOKEN }}
channel-id: 'dev-notifications'
text: |
*Acharya ERP Frontend (Dev) Pipeline*
Status: ${{ job.status }}
Commit: ${{ github.sha }}
Run: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}