name: Build & Deploy on: push: branches: [ main, develop ] pull_request: branches: [ main, develop ] env: REGISTRY: ghcr.io IMAGE_NAME_BACKEND: job-info-backend IMAGE_NAME_FRONTEND: job-info-frontend jobs: test: name: Test & Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Setup Bun uses: oven-sh/setup-bun@v1 - name: Install Frontend Dependencies run: | cd frontend npm ci - name: Lint Frontend run: | cd frontend npm run lint --if-present - name: Type Check Frontend run: | cd frontend npm run type-check --if-present - name: Build Frontend run: | cd frontend npm run build - name: Test Frontend run: | cd frontend npm test --if-present - name: Install Backend Dependencies run: | cd Mode3Test bun install - name: Test Backend run: | cd Mode3Test bun test --if-present build: name: Build Docker Images needs: test runs-on: ubuntu-latest permissions: contents: read packages: write steps: - uses: actions/checkout@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Log in to Container Registry uses: docker/login-action@v2 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Extract metadata for Backend id: meta-backend uses: docker/metadata-action@v4 with: images: ${{ env.REGISTRY }}/${{ github.repository }}/${{ env.IMAGE_NAME_BACKEND }} tags: | type=ref,event=branch type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha - name: Build and Push Backend uses: docker/build-push-action@v4 with: context: . file: ./Dockerfile.backend push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta-backend.outputs.tags }} labels: ${{ steps.meta-backend.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max - name: Extract metadata for Frontend id: meta-frontend uses: docker/metadata-action@v4 with: images: ${{ env.REGISTRY }}/${{ github.repository }}/${{ env.IMAGE_NAME_FRONTEND }} tags: | type=ref,event=branch type=semver,pattern={{version}} type=semver,pattern={{major}}.{{minor}} type=sha - name: Build and Push Frontend uses: docker/build-push-action@v4 with: context: . file: ./Dockerfile.frontend push: ${{ github.event_name != 'pull_request' }} tags: ${{ steps.meta-frontend.outputs.tags }} labels: ${{ steps.meta-frontend.outputs.labels }} cache-from: type=gha cache-to: type=gha,mode=max deploy: name: Deploy to Kubernetes needs: build runs-on: ubuntu-latest if: github.event_name == 'push' && github.ref == 'refs/heads/main' steps: - uses: actions/checkout@v3 - name: Set up kubectl uses: azure/setup-kubectl@v3 with: version: 'latest' - name: Configure kubectl run: | mkdir -p $HOME/.kube echo "${{ secrets.KUBE_CONFIG }}" | base64 -d > $HOME/.kube/config chmod 600 $HOME/.kube/config - name: Create namespace run: kubectl create namespace job-info --dry-run=client -o yaml | kubectl apply -f - - name: Apply Kubernetes configs run: | kubectl apply -f k8s-config.yaml kubectl apply -f k8s-backend-deployment.yaml kubectl apply -f k8s-frontend-deployment.yaml - name: Update image versions run: | kubectl set image deployment/job-info-backend \ backend=${{ env.REGISTRY }}/${{ github.repository }}/${{ env.IMAGE_NAME_BACKEND }}:${{ github.sha }} \ -n job-info kubectl set image deployment/job-info-frontend \ frontend=${{ env.REGISTRY }}/${{ github.repository }}/${{ env.IMAGE_NAME_FRONTEND }}:${{ github.sha }} \ -n job-info - name: Wait for rollout run: | kubectl rollout status deployment/job-info-backend -n job-info --timeout=5m kubectl rollout status deployment/job-info-frontend -n job-info --timeout=5m - name: Verify deployment run: | kubectl get pods -n job-info kubectl get svc -n job-info kubectl get ingress -n job-info security-scan: name: Security Scan runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Run Trivy vulnerability scanner uses: aquasecurity/trivy-action@master with: scan-type: 'fs' scan-ref: '.' format: 'sarif' output: 'trivy-results.sarif' - name: Upload Trivy results to GitHub Security tab uses: github/codeql-action/upload-sarif@v2 with: sarif_file: 'trivy-results.sarif' - name: Run npm audit run: | cd frontend npm audit --audit-level=moderate - name: Check for secrets uses: trufflesecurity/trufflehog@main with: path: ./ base: ${{ github.event.repository.default_branch }} head: HEAD