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
39 changes: 32 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,18 +1,43 @@
name: CI
name: CI — NexaCloud API

on:
push:
branches: [ "main" ]
branches: [main]
pull_request:
branches: [ "main" ]
branches: [main]

jobs:
build:
test:
runs-on: ubuntu-latest

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

- name: Example step
run: echo "Add your build/test steps here!"
- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Installer les dépendances
run: pip install -r ressources/requirements.txt

- name: Lancement du test
run: pytest ressources/ -v
lint:
runs-on: ubuntu-latest

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

- name: Setup Python
uses: actions/setup-python@v5
with:
python-version: "3.11"

- name: Installer flake8
run: pip install flake8

- name: "Lint avec flake8"
run: flake8 ressources/ --config ressources/.flake8
62 changes: 62 additions & 0 deletions .github/workflows/cicd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
name: CI/CD — NexaCloud API

on:
push:
branches: [main]
pull_request:
branches: [main]

jobs:
# ── Job 1 : Qualité ────────────────────────────────────────────────
qualite:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v4

- uses: actions/setup-python@v5
with:
python-version: "3.11"

- run: pip install -r ressources/requirements.txt

- name: Lint
run: flake8 ressources/ --config ressources/.flake8

- name: Tests
run: pytest ressources/ -v --cov=ressources

# ── Job 2 : Staging ───────────────────────────────────────────────
staging:
runs-on: ubuntu-latest
needs: qualite # attend que le job qualite réussisse
environment: staging
if: github.ref_name == 'main' # uniquement sur la branche main

steps:
- uses: actions/checkout@v4

- name: "Run Azure webapp deploy action using publish profile credentials"
uses: azure/webapps-deploy@v3
with:
app-name: "DevAppAdrien"
publish-profile: ${{ secrets.azureWebAppPublishProfile }}
package: ressources/

# ── Job 3 : Production ────────────────────────────────────────────
production:

runs-on: ubuntu-latest
needs: staging
environment: production
if: github.ref_name == 'main'

steps:
- uses: actions/checkout@v4

- name: "Run Azure webapp deploy action using publish profile credentials"
uses: azure/webapps-deploy@v3
with:
app-name: "DevAppAdrien"
publish-profile: ${{ secrets.azureWebAppPublishProfile }}
package: ressources/
44 changes: 25 additions & 19 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,26 +1,32 @@
name: Run Azure Login with OIDC
name: Deploy

on:
workflow_dispatch:

permissions:
id-token: write
contents: read
workflow_dispatch:

jobs:
build-and-deploy:
deploy-staging:
runs-on: ubuntu-latest
environment: staging

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

- name: Déployer en staging
run: |
echo "✅ Déploiement en staging réussi"
echo "URL : https://staging.nexacloud.example.com"

deploy-production:
runs-on: ubuntu-latest
environment: production
needs: deploy-staging # attend que staging soit terminé ET approuvé

steps:
- name: Azure login
uses: azure/login@v3
with:
client-id: ${{ secrets.AZURE_CLIENT_ID }}
tenant-id: ${{ secrets.AZURE_TENANT_ID }}
subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- name: Checkout
uses: actions/checkout@v4

- name: Azure CLI script
uses: azure/cli@v2
with:
azcliversion: latest
inlineScript: |
az account show
- name: Déployer en production
run: |
echo "🚀 Déploiement en production réussi"
echo "URL : https://nexacloud.example.com"
30 changes: 30 additions & 0 deletions .github/workflows/hello.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
name: Hello NexaCloud

on:
push:
branches: [main]
workflow_dispatch: # permet de déclencher manuellement depuis l'interface GitHub

jobs:
salutation:
runs-on: ubuntu-latest

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

- name: Informations sur l'environnement
run: |
echo "Repo : ${{ github.repository }}"
echo "Branche : ${{ github.ref_name }}"
echo "Commit : ${{ github.sha }}"
echo "Acteur : ${{ github.actor }}"

- name: Get date
run: echo "DATE=$(date +'%Y-%m-%d')" >> $GITHUB_ENV

- name: Use date
run: echo ${{ env.DATE }}

- name: Lister les fichiers du repo
run: ls -la
19 changes: 19 additions & 0 deletions .github/workflows/secrets.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: Demo Secrets

on:
workflow_dispatch:

jobs:
demo:
runs-on: ubuntu-latest

env:
API_KEY: ${{ secrets.API_KEY }}

steps:
- name: Vérifier que le secret est défini
run: if [ -z "$API_KEY" ]; then
echo " Le secret API_KEY n'est pas défini"
exit 1
fi
echo "✅ Le secret API_KEY est défini ( caractères)"
30 changes: 30 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -198,10 +198,19 @@ Ouvrez le fichier `.github/workflows/ci.yml` déjà présent dans ce repo.
Répondez aux questions suivantes **sans modifier le fichier** :

1. Sur quelle(s) branche(s) ce workflow se déclenche-t-il ?
# sur la branch main

2. Combien de jobs contient-il ?

# un job
3. Sur quel système d'exploitation tourne-t-il ?

# Ubuntu
4. Quelle action installe Python ?

# requirements.txt
5. Quelle commande lance les tests ?
# runs on

Vérifiez vos réponses en allant dans l'onglet **Actions** de votre repo GitHub après votre premier push.

Expand Down Expand Up @@ -534,9 +543,30 @@ C'est l'exercice le plus important de l'étape.

1. **Introduisez une erreur de style** dans `ressources/app.py` : ajoutez une ligne avec des espaces superflus en fin de ligne ou une ligne trop longue (> 100 caractères). Commitez et pushez.
2. **Observez** : quel job échoue ? Que dit le message d'erreur dans les logs ?

Run flake8 ressources/ --config ressources/.flake8
ressources/app.py:18:101: E501 line too long (123 > 100 characters)
Error: Process completed with exit code 1.

3. **Corrigez** l'erreur, pushez à nouveau.
4. **Introduisez une erreur dans un test** : modifiez `test_app.py` pour qu'un assert soit faux (ex : `assert data["info"] == 999`). Commitez et pushez.
5. **Observez** : cette fois quel job échoue ?

client = <FlaskClient <Flask 'app'>>

def test_index_status(client):
"""La route / retourne 200 avec le statut ok."""
response = client.get("/")
assert response.status_code == 200
data = response.get_json()
> assert data["info"] == 999
E KeyError: 'info'

ressources/test_app.py:21: KeyError
=========================== short test summary info ============================
FAILED ressources/test_app.py::test_index_status - KeyError: 'info'
========================= 1 failed, 4 passed in 0.13s ==========================

6. **Corrigez** et vérifiez que la CI repasse au vert.

> 💡 Le but n'est pas de ne jamais casser la CI — c'est de savoir lire les logs et corriger rapidement. Cette compétence s'acquiert en cassant volontairement.
Expand Down
28 changes: 28 additions & 0 deletions azure.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Dans votre terminal (Azure CLI doit être installé)

RESOURCE_GROUP="asigurRG"
APP_NAME="DevAppAdrien" # nom unique obligatoire
LOCATION="francecentral"

# Créer le resource group
az group create --name "$RESOURCE_GROUP" --location "$LOCATION"

# Créer le plan App Service (B1 — nécessaire pour Always On et la stabilité)
az appservice plan create \
--name "pythonappdev" \
--resource-group "$RESOURCE_GROUP" \
--sku B1 \
--is-linux

# Créer l'App Service Python
az webapp create \
--name "$APP_NAME" \
--resource-group "$RESOURCE_GROUP" \
--plan "plan-nexacloud" \
--runtime "PYTHON:3.11"

# Récupérer le publish profile (à coller dans les secrets GitHub)
az webapp deployment list-publishing-profiles \
--name "$APP_NAME" \
--resource-group "$RESOURCE_GROUP" \
--xml
2 changes: 2 additions & 0 deletions notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Mon TP Github Actions
Mon TP Github Actions
90 changes: 48 additions & 42 deletions ressources/app.py
Original file line number Diff line number Diff line change
@@ -1,42 +1,48 @@
"""
app.py — API NexaCloud
Mini API Flask utilisée comme cible du pipeline CI/CD dans le TP GitHub Actions.
"""

from flask import Flask, jsonify

app = Flask(__name__)

# Simule un résumé de logs issu du TP Bash / PowerShell
LOG_SUMMARY = {
"info": 142,
"warning": 28,
"error": 12,
"critical": 3,
}


@app.route("/")
def index():
return jsonify({"status": "ok", "service": "NexaCloud API", "version": "1.1.0"})


@app.route("/health")
def health():
return jsonify({"status": "healthy"})


@app.route("/logs/summary")
def logs_summary():
return jsonify(LOG_SUMMARY)


@app.route("/logs/critical")
def logs_critical():
seuil = LOG_SUMMARY["critical"]
alerte = seuil > 0
return jsonify({"critical_count": seuil, "alerte": alerte})


if __name__ == "__main__":
app.run(debug=True, port=5001)
"""
app.py — API NexaCloud
Mini API Flask utilisée comme cible du pipeline CI/CD dans le TP GitHub Actions.
"""

from flask import Flask, jsonify

app = Flask(__name__)

# Simule un résumé de logs issu du TP Bash / PowerShell
LOG_SUMMARY = {
"info": 142,
"warning": 28,
"error": 12,
"critical": 3,
}


@app.route("/")
def index():
return jsonify({"status": "ok", "service": "NexaCloud API", "version": "1.1.0"})


@app.route("/health")
def health():
return jsonify({"status": "healthy"})


@app.route("/logs/summary")
def logs_summary():
return jsonify(LOG_SUMMARY)


@app.route("/logs/critical")
def logs_critical():
seuil = LOG_SUMMARY["critical"]
alerte = seuil > 0
return jsonify({"critical_count": seuil, "alerte": alerte})


@app.route("/logs/stats")
def logs_stats():
total = sum(LOG_SUMMARY.values())
return jsonify({"total": total, "breakdown": LOG_SUMMARY})


if __name__ == "__main__":
app.run(debug=True, port=5001)
Loading
Loading