Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
96 changes: 96 additions & 0 deletions .github/workflows/backend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
name: Backend — Build, Test & Deploy (VM + Ansible)

on:
push:
paths:
- "apps/backend/**"
workflow_dispatch:

permissions:
contents: read
actions: read
checks: write
pull-requests: write

env:
RG: project2-teaf
OPS_VM: teaf3tier-vm-ops
APP_DIR: apps/backend

jobs:
build-test-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Set up JDK 17
uses: actions/setup-java@v4
with:
distribution: temurin
java-version: 17
cache: maven

- name: Build & test (Maven)
run: mvn -B clean test package
working-directory: ${{ env.APP_DIR }}

- name: Publish test results
uses: dorny/test-reporter@v1
if: always()
with:
name: Backend Tests
path: ${{ env.APP_DIR }}/target/surefire-reports/*.xml
reporter: java-junit

# تسجيل دخول Azure بـ OIDC (مفضل) أو JSON creds
- name: Azure Login (OIDC)
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}

# ادفع الـ jar إلى /opt/artifacts/backend على vm-ops وشغّل ansible هناك
- name: Deploy to vm-ops via Run-Command
run: |
set -e
# ارفع الـ jar كأرتيفاكت مؤقت على الـ VM عبر git pull
az vm run-command invoke \
-g "${{ env.RG }}" -n "${{ env.OPS_VM }}" \
--command-id RunShellScript \
--scripts '
set -e
mkdir -p ~/project
if [ ! -d ~/project/devops-project2-ih-teaf ]; then
git clone https://github.com/teafalahmadi/devops-project2-ih-teaf.git ~/project/devops-project2-ih-teaf
else
cd ~/project/devops-project2-ih-teaf && git pull --rebase
fi
'
# انسخي jar الناتج إلى vm-ops
JAR_PATH=$(ls ${{ env.APP_DIR }}/target/*.jar | head -n1)
az vm run-command invoke \
-g "${{ env.RG }}" -n "${{ env.OPS_VM }}" \
--command-id RunShellScript \
--scripts "
set -e
sudo mkdir -p /opt/artifacts/backend
cat > /opt/artifacts/backend/app.jar.base64 <<'EOF'
$(base64 -w0 $JAR_PATH)
EOF
base64 -d /opt/artifacts/backend/app.jar.base64 | sudo tee /opt/artifacts/backend/app.jar >/dev/null
sudo rm -f /opt/artifacts/backend/app.jar.base64
"
# شغّل ansible على vm-ops لينشر التحديث على vm-backend
az vm run-command invoke \
-g "${{ env.RG }}" -n "${{ env.OPS_VM }}" \
--command-id RunShellScript \
--scripts '
set -e
source ~/ansible-venv/bin/activate || true
cd ~/project/devops-project2-ih-teaf
ansible-playbook -i config/ansible/inventories/prod/hosts.ini config/ansible/site-backend.yml
'

# فحص صحة عبر Application G
37 changes: 37 additions & 0 deletions .github/workflows/frontend.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# .github/workflows/frontend.yml
name: Frontend — Build & Upload

on:
workflow_dispatch:
push:
paths:
- 'apps/frontend/**'
- '.github/workflows/frontend.yml'

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: apps/frontend

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 18
cache: npm

- name: Install deps
run: npm ci

- name: Build (Vite)
run: npm run build

- name: Upload dist artifa
112 changes: 112 additions & 0 deletions .github/workflows/infra.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
name: Infra — Terraform Plan (and optional Apply)

on:
workflow_dispatch:
pull_request:
branches: [ main ]
push:
branches: [ main ]
paths: [ "infra/terraform/**" ]

permissions:
contents: read

jobs:
plan:
name: Terraform Plan
runs-on: ubuntu-latest
permissions:
id-token: write # مطلوب لـ OIDC
contents: read
defaults:
run:
working-directory: infra/terraform

steps:
- name: Checkout
uses: actions/checkout@v4

# تسجيل دخول Azure عبر OIDC (بدون ARM_* Secrets)
- name: Azure Login (OIDC)
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id:${{ secrets.AZURE_SUBSCRIPTION_ID }}

# (اختياري) طباعة الحساب النشط للتأكد
- name: az account show
run: az account show -o table

- name: Setup Terraform
uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.9.6
terraform_wrapper: false

- name: Terraform init
run: terraform init -input=false -reconfigure -upgrade

- name: Terraform fmt (auto-fix & check)
run: |
terraform fmt -recursive
terraform fmt -check

- name: Terraform validate
run: terraform validate

- name: Terraform plan
id: plan
run: terraform plan -no-color -out=tfplan.binary
env:
# متغيرات Terraform (حساسة/غير حساسة)
TF_VAR_admin_ssh_pubkey: ${{ vars.TF_VAR_admin_ssh_pubkey }}
TF_VAR_sql_admin_password: ${{ secrets.TF_VAR_sql_admin_password }}
# لضمان اختيار الاشتراك/التيننت مع مزود azurerm v4
TF_VAR_subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
TF_VAR_tenant_id: ${{ secrets.AZURE_TENANT_ID }}

- name: Upload plan
uses: actions/upload-artifact@v4
with:
name: tfplan
path: infra/terraform/tfplan.binary

# (اختياري) تطبيق — فعّليه إذا تبغين Apply تلقائيًا بعد الدمج/التشغيل اليدوي
apply:
if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref == 'refs/heads/main')
needs: plan
runs-on: ubuntu-latest
environment: prod
permissions:
id-token: write
contents: read
defaults:
run:
working-directory: infra/terraform
steps:
- uses: actions/checkout@v4

- name: Azure Login (OIDC)
uses: azure/login@v2
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id:${{ secrets.AZURE_SUBSCRIPTION_ID }}

- uses: hashicorp/setup-terraform@v3
with:
terraform_version: 1.9.6
terraform_wrapper: false

- name: Terraform init
run: terraform init -input=false -reconfigure -upgrade

# الأبسط: أعدي الحساب مباشرة (بدون استرجاع tfplan.binary)
- name: Terraform apply
run: terraform apply -auto-approve -input=false
env:
TF_VAR_admin_ssh_pubkey: ${{ vars.TF_VAR_admin_ssh_pubkey }}
TF_VAR_sql_admin_password: ${{ secrets.TF_VAR_sql_admin_password }}
TF_VAR_subscription_id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
TF_VAR_tenant_id: ${{ secrets.AZURE_TENANT_ID }}
51 changes: 51 additions & 0 deletions .github/workflows/sonar-infra.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
name: Sonar — Infra (Terraform) analysis

on:
workflow_dispatch:
pull_request:
paths:
- 'infra/**'
- '.github/workflows/sonar-infra.yml'

jobs:
sonar-terraform:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: Install tflint
run: curl -sL https://raw.githubusercontent.com/terraform-linters/tflint/master/install_linux.sh | bash

- name: Run tflint
working-directory: infra/terraform
run: tflint --init && tflint
continue-on-error: true

- name: Install tfsec
run: curl -sSL https://raw.githubusercontent.com/aquasecurity/tfsec/master/scripts/install_linux.sh | bash

- name: Run tfsec (SARIF & soft-fail)
working-directory: infra/terraform
run: tfsec --format sarif --out tfsec.sarif || true

- name: Upload tfsec SARIF
uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: infra/terraform/tfsec.sarif

# SonarCloud (أسهل—ما يحتاج SONAR_HOST_URL)
- name: SonarCloud Scan (Terraform)
uses: SonarSource/sonarcloud-github-action@v2
env:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
with:
projectBaseDir: infra/terraform
args: >
-Dsonar.projectKey=${{ secrets.SONAR_PROJECT_KEY }}
-Dsonar.organization=${{ secrets.SONAR_ORGANIZATION }}
-Dsonar.sources=.
-Dsonar.exclusions=**/.terraform/**,**/*.tfstate*,**/dist/**,**/target/**
50 changes: 27 additions & 23 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
# Environment files
# Terraform
*.tfstate
*.tfstate.*
.terraform/
*.tfvars
override.tf
override.tf.json

# Azure credentials / secrets
azure-credentials.json
*.credentials.json
*.env
.env
.env.local
.env.*.local

# IDE
.vscode/
.idea/
*.iml
# SSH keys
id_*.pub
id_*
teafp2
teafp2.pub
*.pem
*.key

# OS
# OS / Editor files
.DS_Store
Thumbs.db

# Logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Temporary files
*.tmp
*.temp
.vscode/
.idea/
*.swp

**/**/.terraform/
**/**/.terraform.lock.hcl
**/**/*.tfstate
**/**/target/

infra/terraform/tfplan
infra/terraform/tfplan.binary
infra/terraform/.terraform/
infra/terraform/*.tfstate*
24 changes: 24 additions & 0 deletions backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM maven:3.9.9-eclipse-temurin-21 AS build
WORKDIR /app

# Leverage build cache for dependencies
COPY pom.xml .
RUN mvn -q -e -B -DskipTests dependency:go-offline

# Copy sources and build
COPY src ./src
RUN mvn -q -e -B -DskipTests clean package

# Runtime image
FROM eclipse-temurin:21-jre
WORKDIR /app

# Set default Spring profile (overridable at runtime)
ENV SPRING_PROFILES_ACTIVE=docker

# Copy the built jar
COPY --from=build /app/target/*.jar /app/app.jar

EXPOSE 8080

ENTRYPOINT ["java","-jar","/app/app.jar"]
13 changes: 13 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
FROM node:20-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 5173

CMD [ "npm", "run", "dev"]
Loading