Έργο 14 — CI/CD με GitHub Actions · Επίπεδο αρχάριος → ενδιάμεσο · Εκτιμώμενη διάρκεια: 1 ώρα 30 έως 2 ώρες
Λαμβάνετε έναν στατικό μίνι-ιστότοπο ήδη συνδεδεμένο με δύο λειτουργικά workflows GitHub Actions. Κλωνοποιείτε, ωθείτε, ο ιστότοπός σας είναι στο διαδίκτυο. Αλλάζετε ένα χρώμα στο
config.json, ωθείτε ξανά, η δημόσια σελίδα ενημερώνεται μόνη της. Τελειώνετε επισκευάζοντας τρία ελαττωματικά workflows που απεικονίζουν τα κλασικά σφάλματα του CI/CD.
Μόλις προσληφθήκατε ως junior σε μια διαδικτυακή εταιρεία. Η πρώτη σας εργασία: ένας μίνι-ιστότοπος «portfolio» προς δωρεάν φιλοξενία. Η εντολή του προϊσταμένου:
«Θέλω να μπορώ να αλλάξω το χρώμα του ιστότοπου τροποποιώντας ένα μόνο αρχείο, να κάνω
git push, και αυτό να ενημερώνεται μόνο του. Κανένα FTP, κανένας διακομιστής προς διαχείριση.»
Ο senior της ομάδας έχει ήδη γράψει τα δύο workflows GitHub Actions και το σενάριο κατασκευής. Η δουλειά σας:
git clone + push + ενεργοποίηση του Pages).config.json με τα στοιχεία σας και τα χρώματά σας.push → Pages λειτουργεί αλλάζοντας το χρώμα τουλάχιστον δύο φορές.Αυτό το έργο δεν είναι εργαστήριο όπου γράφετε YAML από το μηδέν. Είναι εργαστήριο όπου αναλαμβάνετε μια αλυσίδα CI/CD ήδη στη θέση της, όπως σε μια πραγματική ομάδα: δεν επανεφεύρετε τα workflows, τα κατανοείτε, εξατομικεύετε, αποσφαλματώνετε.
Αυτό το έγγραφο είναι αυτάρκες. Κανένα εξωτερικό μάθημα προς άνοιγμα για να το ολοκληρώσετε.
Το GitHub Actions είναι μια μηχανή εκτέλεσης ενσωματωμένη στο GitHub. Σε κάθε γεγονός (push, pull_request, χρονοδιακόπτης, χειροκίνητο κουμπί), εκκινεί workflows περιγραφόμενα σε YAML, σε runners (δωρεάν VM Ubuntu / Windows / macOS για δημόσια αποθετήρια).
name: Mon premier workflow # εμφανίζεται στο UI
on: # ΠΟΤΕ να εκτελεστεί
push:
branches: [main]
jobs: # ΤΙ να γίνει (>= 1 job)
construire: # ελεύθερο όνομα του job
runs-on: ubuntu-latest # ΠΟΥ να εκτελεστεί (εικόνα της VM)
steps: # τα βήματα του job
- uses: actions/checkout@v4 # βήμα "επαναχρησιμοποιήσιμη ενέργεια"
- run: echo "Bonjour" # βήμα "εντολή κελύφους"Δύο τύποι βημάτων:
uses: καλεί μια δημοσιευμένη ενέργεια (actions/checkout@v4, actions/setup-python@v5, κ.λπ.).run: εκτελεί μια εντολή κελύφους στον runner.on: | Ενεργοποιείται όταν… |
|---|---|
push: { branches: [main] } | Ωθούμε μια δέσμευση στο main |
pull_request: { branches: [main] } | Κάποιος ανοίγει / ενημερώνει μια PR προς main |
schedule: [{ cron: "0 6 * * *" }] | Κάθε μέρα στις 06:00 UTC |
workflow_dispatch: | Χειροκίνητο κουμπί στην καρτέλα Actions |
Το ίδιο workflow μπορεί να έχει πολλούς ενεργοποιητές ταυτόχρονα — αυτή είναι η περίπτωση του deployer-pages.yml (push + χειροκίνητο).
Το GitHub Pages είναι στατική φιλοξενία που προσφέρεται με κάθε δημόσιο αποθετήριο. Δημοσιεύουμε HTML/CSS/JS μέσω μίας από τις ακόλουθες μεθόδους:
gh-pages (παλιά μέθοδος)./docs του main (άλλη μέθοδος).Το δημόσιο URL είναι https://<utilisateur>.github.io/<nom-du-depot>/ — προσβάσιμο από οποιονδήποτε περιηγητή.
Για δημοσίευση από Actions, το deployer-pages.yml αλυσιδώνει τρεις επίσημες ενέργειες:
Κεφαλαιώδης περιορισμός: το job που δημοσιεύει χρειάζεται ιδιαίτερα δικαιώματα, αλλιώς λαμβάνουμε Resource not accessible by integration. Το παρεχόμενο workflow τα δηλώνει ήδη:
permissions:
contents: read
pages: write
id-token: writeΑυτή είναι επίσης η βλάβη 1 της αποστολής 3 — κρατήστε την.
Σε κάθε εκτέλεση, το GitHub Actions εκθέτει χρήσιμες μεταβλητές περιβάλλοντος:
| Μεταβλητή | Περιεχόμενο |
|---|---|
GITHUB_SHA | Το SHA της δέσμευσης που ενεργοποίησε το run |
GITHUB_REF_NAME | Το όνομα του κλάδου (main, feature-x, κ.λπ.) |
GITHUB_RUN_NUMBER | Ένας μετρητής που αυξάνεται σε κάθε run |
Σε αυτό το έργο, το outils/build.py διαβάζει αυτές τις τρεις μεταβλητές για να τις εμφανίσει στη δημοσιευμένη σελίδα. Οπτική απόδειξη ότι η ανάπτυξη προέρχεται όντως από Actions και όχι από τοπικό python build.py.
Αναμενόμενος τελικός βρόχος — πρέπει να τον αναπαραγάγετε τουλάχιστον 2 φορές:
site/config.json στο VS Code.couleur_fond (π.χ. #0f172a → #7c3aed).git add site/config.json && git commit -m "changement de fond" && git push.https://<vous>.github.io/<depot>/ → το φόντο είναι βιολετί.projet14-github-actions-pages-tp/
├── 00-ENONCE.md <- αυτό το έγγραφο
├── 02-CORRECTION.md <- λεπτομερείς λύσεις (να διαβαστούν ΜΕΤΑ τη δοκιμή)
├── README.md
│
├── site/ <- Ο ΙΣΤΟΤΟΠΟΣ (πηγή)
│ ├── config.json <- ΕΣΕΙΣ ΤΡΟΠΟΠΟΙΕΙΤΕ : χρώματα, τίτλος, συγγραφέας
│ └── src/
│ ├── index.html.template <- πρότυπο HTML (δείκτες {{...}})
│ └── css/
│ └── style.css.template <- πρότυπο CSS (δείκτες {{...}})
│
├── outils/
│ └── build.py <- ΠΑΡΕΧΕΤΑΙ — να μην τροποποιηθεί
│
├── .github/ <- ΗΔΗ ΛΕΙΤΟΥΡΓΙΚΑ WORKFLOWS
│ └── workflows/
│ ├── deployer-pages.yml <- κατασκευή + δημοσίευση στο Pages
│ └── verifier-config.yml <- επικύρωση του config.json σε PR
│
├── casses/ <- 3 ελαττωματικά workflows (Αποστολή 3)
│ ├── casse-1-permissions-manquantes.yml
│ ├── casse-2-declencheur-errone.yml
│ └── casse-3-chemin-artefact.yml
│
└── .gitignore <- αγνοεί το dist/Σημαντικό σημείο: τα δύο workflows είναι ήδη στο .github/workflows/. Δεν έχετε τίποτα να γράψετε για το μέρος της ανάπτυξης — μόνο να κατανοήσετε τι συμβαίνει και να εξατομικεύσετε το config.json.
outils/build.py — είναι το συμβόλαιο μεταξύ του config.json και του τελικού HTML/CSS.dist/: εμφανίζεται στο .gitignore και ανακατασκευάζεται σε κάθε run.git --version).python --version — για τοπική δοκιμή του build.py).projet14-github-actions-pages-tp/ στον δίσκο σας.projet14-actions-pages..gitignore (ήδη παρέχονται).Από τη ρίζα του έργου:
python .\outils\build.pyΠρέπει να δείτε:
OK dist/index.html genere
OK dist/css/style.css genere
--- Substitutions appliquees ---
{{TITRE}} -> Mon premier site pilote par GitHub Actions
{{COULEUR_FOND}} -> #0f172a
...Ανοίξτε το dist/index.html σε έναν περιηγητή: βλέπετε τον ιστότοπο με το προεπιλεγμένο σκοτεινό φόντο. Αν λειτουργεί τοπικά, θα λειτουργήσει στο Actions.
git init
git branch -M main
git add .
git commit -m "point de depart projet14"
git remote add origin https://github.com/<votre-utilisateur>/projet14-actions-pages.git
git push -u origin mainΚαρτέλα Actions του αποθετηρίου σας → εμφανίζεται ένα run με τίτλο Deployer sur GitHub Pages. Περιμένετε να γίνει πράσινο (~40 δευτερόλεπτα μετά το push).
Στο τέλος του job deployer, ένα μήνυμα ανακοινώνει:
Your site is live at https://<vous>.github.io/projet14-actions-pages/Κάντε κλικ → βλέπετε τον δημοσιευμένο ιστότοπό σας.
config.json (20 βαθμοί)Ανοίξτε το site/config.json και τροποποιήστε τουλάχιστον:
titre — βάλτε το όνομά σας ή αυτό ενός φανταστικού έργου.auteur — το όνομά σας.couleur_fond — στη μορφή #RRGGBB (π.χ. #7c3aed, #dc2626, #0891b2).Επαληθεύστε με python .\outils\build.py ότι το build περνά ακόμη. Λάθος μορφή (rouge, #ff, RGB(255,0,0)) εντοπίζεται από το build.py και θα μπλοκάρει το workflow.
Περιορισμός: μην σπάσετε το JSON. Ένα κόμμα παραπάνω, μια αγκύλη που λείπει → κόκκινο workflow στο GitHub.
Αυτό είναι η καρδιά του έργου. Πρέπει να δείξετε ότι ο κύκλος CI/CD λειτουργεί, ενεργοποιώντας τον τουλάχιστον δύο φορές:
site/config.json (αλλάξτε π.χ. το couleur_fond σε #dc2626 — κόκκινο).git add site/config.json && git commit -m "fond en rouge" && git push.https://<vous>.github.io/<votre-depot>/ → το φόντο είναι κόκκινο.#16a34a, μπλε #0891b2, βιολετί #7c3aed, της επιλογής σας).Απόδειξη προς παροχή στην έκθεση:
git log --oneline).Κρίσιμο σημείο: στη δημόσια σελίδα, ένα πλακίδιο εμφανίζει Commit SHA : <7 χαρακτήρες>. Αυτό το SHA αντιστοιχεί στην τελευταία δέσμευση στο main. Είναι η οπτική απόδειξη ότι η σελίδα προέρχεται όντως από Actions.
Ο φάκελος casses/ περιέχει τρία ελαττωματικά workflows, καθένα απεικονίζει ένα κλασικό σφάλμα. Για καθένα:
.github/workflows/ (δίπλα στα επίσημα workflows)..github/workflows/ (όχι στο casses/ — το πρωτότυπο μένει ελαττωματικό).| Αρχείο | Αναμενόμενο σύμπτωμα |
|---|---|
casse-1-permissions-manquantes.yml | Το job deployer αποτυγχάνει με Resource not accessible by integration |
casse-2-declencheur-errone.yml | Κανένα run δεν ενεργοποιείται: το workflow αγνοείται σιωπηλά |
casse-3-chemin-artefact.yml | Το job construire αποτυγχάνει με Error: Path does not exist: ./public |
Σημαντική συμβουλή: μπορείτε να εκκινήσετε κάθε workflow χειροκίνητα μέσω Run workflow στην καρτέλα Actions, χωρίς να κάνετε πραγματική δέσμευση σε κάθε δοκιμή. Τα ελαττωματικά workflows έχουν όλα workflow_dispatch: ή μπορείτε να το προσθέσετε προσωρινά.
Απόδειξη προς παροχή για κάθε βλάβη: στιγμιότυπο του κόκκινου run πριν, diff της διόρθωσης, στιγμιότυπο του πράσινου run μετά.
Κατ' επιλογή, ένα μόνο αρκεί:
a) Προσθέστε ένα σήμα κατάστασης σε ένα README.md στη ρίζα του αποθετηρίου GitHub σας (όχι αυτό του εργαστηρίου):
Εμφανίζει passing (πράσινο) ή failing (κόκκινο) ζωντανά.
b) Δημιουργήστε μια PR δοκιμής με ηθελημένα άκυρο config.json (π.χ. "couleur_fond": "rouge"). Το workflow Verifier la configuration πρέπει να αποτύχει και να μπλοκάρει τη συγχώνευση. Παρέχετε το στιγμιότυπο του μπλοκαρίσματος.
c) Δημιουργήστε ένα τρίτο χειροκίνητο workflow (workflow_dispatch:) που στέλνει ειδοποίηση curl σε webhook (URL παρεχόμενο μέσω Settings → Secrets, ποτέ σε καθαρό κείμενο στο YAML).
Ένα RAPPORT.md στη ρίζα του αποθετηρίου σας, που περιέχει:
https://<vous>.github.io/<depot>/).on: push χωρίς να διευκρινίζει branches: — πότε ενεργοποιείται; Είναι πρόβλημα;id-token: write είναι απαραίτητο για δημοσίευση στο GitHub Pages; Σε τι χρησιμεύει το διακριτικό OIDC;git push στο main ταυτόχρονα; Το μπλοκ concurrency τι αλλάζει στη συμπεριφορά;API_KEY στο Settings → Secrets. Ο κώδικας του workflow μπορεί να το διαβάσει μέσω ${{ secrets.API_KEY }}. Μπορεί να εκτυπωθεί στα ημερολόγια; Γιατί το GitHub καλύπτει ορισμένες τιμές;deployer-pages.yml και verifier-config.yml. Το δεύτερο είναι άχρηστο αφού το πρώτο κάνει την ίδια κατασκευή; Αιτιολογήστε γιατί είναι συμπληρωματικά.build.py σας δημιουργούσε ένα αρχείο historique.log; Πού θα έπρεπε να το αποθηκεύσετε;| Στοιχείο | Βαθμοί |
|---|---|
Αποστολή 1 — εξατομικευμένο config.json και τοπικό build OK | 20 |
| Αποστολή 2 — Απόδειξη του κύκλου push → Pages (2 χρώματα + στιγμιότυπα + SHA) | 30 |
| Αποστολή 3 — 3 βλάβες διαγνωσμένες και επισκευασμένες | 30 |
| Ποιότητα της έκθεσης (δομή, στιγμιότυπα, εξηγήσεις) | 20 |
| Μπόνους — Αποστολή 4 | +10 |
| Σύνολο | 100 (+10) |
Ποινές:
.github/workflows/ (άρα αγνοείται από το GitHub).dist/ (πρέπει να μείνει στο .gitignore).outils/build.py.# Σκελετός αναφοράς ενός workflow
name: Description humaine
on: # ΠΟΤΕ
push:
branches: [main]
pull_request:
branches: [main]
workflow_dispatch: # χειροκίνητο κουμπί
permissions: # ΜΟΝΟ ό,τι είναι απαραίτητο
contents: read
pages: write
concurrency: # να μην στοιβάζονται τα runs
group: pages
cancel-in-progress: false
jobs:
mon-job:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Une commande
run: python outils/build.pyΟι 5 χειρονομίες που σώζουν στη διάγνωση:
Re-run failed jobs: επανεκκινεί μόνο τα αποτυχημένα βήματα, πιο γρήγορα.workflow_dispatch: πρόσθεσέ το στα workflows σου για να τα επανεκκινείς χειροκίνητα χωρίς κενή δέσμευση.echo "::debug::mon message": εκτυπώνει μήνυμα αποσφαλμάτωσης στα ημερολόγια.site/config.jsonΑυτό είναι το μόνο αρχείο που πρέπει να τροποποιείτε σε κανονικές συνθήκες.
{
"titre": "Mon premier site pilote par GitHub Actions",
"sous_titre": "Change une couleur, fais un push, et regarde GitHub Pages se mettre a jour tout seul.",
"couleur_fond": "#0f172a",
"couleur_texte": "#f1f5f9",
"couleur_accent": "#38bdf8",
"auteur": "Etudiant du cours AOA-DEVOPS-101",
"version": "1.0.0"
}Περιορισμοί του αρχείου:
couleur_fond, couleur_texte, couleur_accent) πρέπει να τηρούν τη μορφή #RRGGBB — αλλιώς το build.py απορρίπτει.site/src/index.html.templateΠρότυπο HTML του οποίου κάθε {{MARQUEUR}} αντικαθίσταται από το build.py. Η σελίδα θα εμφανίζει:
config.json).config.json).GITHUB_* του runner).Το πλήρες αρχείο παρέχεται στο site/src/index.html.template.
site/src/css/style.css.templateΠρότυπο CSS που χρησιμοποιεί {{COULEUR_FOND}}, {{COULEUR_TEXTE}} και {{COULEUR_ACCENT}} σε ένα μπλοκ :root.
Απόσπασμα:
:root {
--fond: {{COULEUR_FOND}};
--texte: {{COULEUR_TEXTE}};
--accent: {{COULEUR_ACCENT}};
}
body {
background: var(--fond);
color: var(--texte);
}.github/workflows/deployer-pages.ymlname: Deployer sur GitHub Pages
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false
jobs:
construire:
name: Construire le site
runs-on: ubuntu-latest
steps:
- name: Recuperer le code
uses: actions/checkout@v4
- name: Installer Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Generer dist/ a partir de config.json
run: python outils/build.py
- name: Preparer le dossier a publier
uses: actions/upload-pages-artifact@v3
with:
path: dist
deployer:
name: Publier sur GitHub Pages
needs: construire
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.publication.outputs.page_url }}
steps:
- name: Publier l'artefact
id: publication
uses: actions/deploy-pages@v4Ανάγνωση γραμμή προς γραμμή: βλ. 02-CORRECTION.md → Αποστολή 2.
.github/workflows/verifier-config.ymlname: Verifier la configuration
on:
pull_request:
branches: [main]
push:
branches-ignore: [main]
jobs:
linter:
name: Valider config.json
runs-on: ubuntu-latest
steps:
- name: Recuperer le code
uses: actions/checkout@v4
- name: Installer Python 3.12
uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Construire en dry-run
run: python outils/build.py
- name: Verifier que dist/ est bien genere
run: |
test -f dist/index.html
test -f dist/css/style.css
echo "OK - site construit sans erreur"Το outils/build.py κάνει τέσσερα πράγματα:
site/config.json.#RRGGBB (regex).{{MARQUEUR}} στα δύο πρότυπα και γράφει το αποτέλεσμα στο dist/.Στο GitHub Actions, οι μεταβλητές GITHUB_SHA, GITHUB_REF_NAME, GITHUB_RUN_NUMBER είναι αυτόματα διαθέσιμες. Τοπικά, δεν υπάρχουν → το σενάριο εμφανίζει local-* στη θέση τους. Έτσι διακρίνουμε μια σελίδα πραγματικά αναπτυγμένη από Actions από μια σελίδα κατασκευασμένη τοπικά.
casses/casse-1-permissions-manquantes.ymlΤο workflow τρέχει αλλά το job deployer αποτυγχάνει με:
Error: Resource not accessible by integrationΕρώτηση να θέσετε στον εαυτό σας: ποια ολόκληρη ενότητα λείπει, στην κορυφή του αρχείου, δίπλα στο on:;
casses/casse-2-declencheur-errone.ymlΈνα push στο main δεν ενεργοποιεί ποτέ αυτό το workflow. Κανένα run δεν εμφανίζεται. Κανένα σφάλμα.
Ερώτηση να θέσετε στον εαυτό σας: διαβάστε το κλειδί κάτω από το on:. Το GitHub περιμένει push, αλλά τι βλέπουμε γραμμένο;
casses/casse-3-chemin-artefact.ymlΤο build.py επιτυγχάνει και εμφανίζει OK dist/index.html genere. Αλλά το upload-pages-artifact αποτυγχάνει με:
Error: Path does not exist: ./publicΕρώτηση να θέσετε στον εαυτό σας: πού γράφει το build.py τον ιστότοπο (κοιτάξτε τον κώδικα Python); Ποιο path: πρέπει λοιπόν να βάλετε στο workflow;
Μάθημα δημιουργημένο από τον Dr. Haythem REHOUMA — Ανάπτυξη και ανάπτυξη λύσεων δεδομένων