Skip to content

Fix url

Fix url #11

Workflow file for this run

name: Frontend CI/CD Workflow
on:
workflow_dispatch:
push:
branches:
- main
paths:
- 'frontend/**'
jobs:
start-time-capture:
runs-on: ubuntu-24.04
outputs:
workflow_start_time: ${{ steps.start.outputs.start_time_unix }}
steps:
- name: Capture Workflow Start Time
id: start
run: echo "start_time_unix=$(date +%s)" >> $GITHUB_OUTPUT
prepare-cache:
runs-on: ubuntu-24.04
needs: start-time-capture
outputs:
cache-hit: ${{ steps.npm-cache-restore.outputs.cache-hit }}
steps:
- uses: actions/checkout@v5
- name: Setup Node.js 18
uses: actions/setup-node@v4
with:
node-version: 18
# Restore Cache Attempt
- name: Restore npm Cache
id: npm-cache-restore
uses: actions/cache/restore@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('frontend/package-lock.json') }}
# Install Dependencies (Only runs on a cache miss)
- name: Install Dependencies (Cache Miss Only)
if: steps.npm-cache-restore.outputs.cache-hit != 'true'
run: npm ci
working-directory: ./frontend
- name: Save npm Cache
if: steps.npm-cache-restore.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('frontend/package-lock.json') }}
- name: Slack Notify
if: failure()
uses: ./.github/actions/slack-notify
with:
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
job-status: ${{ job.status }}
last: 'no'
start-time: ${{ needs.start-time-capture.outputs.workflow_start_time }}
scan-secrets:
name: Gitleaks Scan
runs-on: ubuntu-24.04
needs: [prepare-cache, start-time-capture]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: gitleaks/gitleaks-action@v2
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Slack Notify
if: failure()
uses: ./.github/actions/slack-notify
with:
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
job-status: ${{ job.status }}
last: 'no'
start-time: ${{ needs.start-time-capture.outputs.workflow_start_time }}
build-and-test:
name: Build and Run Unit Tests
runs-on: ubuntu-24.04
needs: [scan-secrets, start-time-capture]
steps:
- name: Checkout Code
uses: actions/checkout@v5
- name: Setup Node.js 18
uses: actions/setup-node@v4
with:
node-version: 18
- name: Restore npm Cache
uses: actions/cache/restore@v4
with:
path: ~/.npm
key: ${{ runner.os }}-node-${{ hashFiles('frontend/package-lock.json') }}
# (will hit cache from prepare-cache job if available)
- name: Install Dependencies
run: npm ci
working-directory: ./frontend
- name: Build
run: npm run build
working-directory: ./frontend
- name: Run Unit Tests
# Assumes 'test' script is defined in package.json
run: npm test
working-directory: ./frontend
- name: Slack Notify
if: failure()
uses: ./.github/actions/slack-notify
with:
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
job-status: ${{ job.status }}
last: 'no'
start-time: ${{ needs.start-time-capture.outputs.workflow_start_time }}
semgrep:
name: semgrep SAST scan
runs-on: ubuntu-24.04
needs: [build-and-test, start-time-capture]
container:
image: semgrep/semgrep
if: (github.actor != 'dependabot[bot]')
steps:
- uses: actions/checkout@v4
- run: semgrep ci --subdir frontend/
env:
SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }}
- name: Slack Notify
if: failure()
uses: ./.github/actions/slack-notify
with:
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
job-status: ${{ job.status }}
last: 'no'
start-time: ${{ needs.start-time-capture.outputs.workflow_start_time }}
trivy_for_code_dependencies:
runs-on: ubuntu-24.04
name: Trivy for Code dependencies
needs: [semgrep, start-time-capture]
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Trivy vulnerability scanner on dependencies
uses: aquasecurity/trivy-action@master
continue-on-error: true
with:
scan-type: 'fs'
scan-ref: './frontend'
severity: 'HIGH,CRITICAL'
exit-code: '1'
format: 'table'
- name: Slack Notify
if: failure()
uses: ./.github/actions/slack-notify
with:
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
job-status: ${{ job.status }}
last: 'no'
start-time: ${{ needs.start-time-capture.outputs.workflow_start_time }}
image-build-scan-sbom-push-update-repo:
name: Build, Scan, then SBOM, push and update repo
runs-on: ubuntu-24.04
needs: [trivy_for_code_dependencies, start-time-capture]
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub (for push)
uses: docker/login-action@v3
with:
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set Image Tag
id: vars
run: echo "TAG=$(echo ${GITHUB_SHA} | cut -c1-7)" >> $GITHUB_ENV
- name: Build Image
uses: docker/build-push-action@v6
with:
context: ./frontend
load: true
tags: localbuild/frontend:${{ env.TAG }}
upload-artifact: false
- name: Run Trivy vulnerability scanner for the entire image artifact
uses: aquasecurity/trivy-action@master
continue-on-error: true
with:
image-ref: localbuild/frontend:${{ env.TAG }}
severity: 'HIGH,CRITICAL'
exit-code: '1'
format: 'table'
- name: Generate SBOM with Syft
uses: anchore/sbom-action@v0
if: always()
with:
image: localbuild/frontend:${{ env.TAG }} # Scan the local image
output-file: 'sbom.spdx.json' # Save the SBOM file
upload-artifact: false
- name: Upload SBOM Artifact
uses: actions/upload-artifact@v4
if: always()
with:
name: frontend-sbom
path: sbom.spdx.json
- name: Push Final Image to Registry (Only if all security checks passed)
if: success()
run: |
docker tag localbuild/frontend:${{ env.TAG }} mostafaibrahim24/empl-frontend:${{ env.TAG }}
docker push mostafaibrahim24/empl-frontend:${{ env.TAG }}
- name: Update GitOps manifest with new image tag
if: success()
run: |
git clone https://x-access-token:${GITOPS_TOKEN}@github.com/${GITOPS_REPO}.git
cd manifests-gitops
sed -i "s#mostafaibrahim24/empl-frontend:.*#mostafaibrahim24/empl-frontend:${TAG}#" deployments/frontend-deploy.yaml
git config user.name "ci-bot"
git config user.email "ci@bot.com"
git commit -am "[GH-ACTIONS] Update frontend image"
git push origin main
env:
GITOPS_TOKEN: ${{ secrets.GITOPS_TOKEN }}
GITOPS_REPO: mostafaibrahim24/manifests-gitops
- name: Slack Notify
if: always()
uses: ./.github/actions/slack-notify
with:
slack-webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
job-status: ${{ job.status }}
last: 'yes'
start-time: ${{ needs.start-time-capture.outputs.workflow_start_time }}