Πρότυπα ροών εργασίας


Αυτό το έγγραφο εξηγεί πώς να ρυθμίσεις ροές εργασίας Συνεχούς Ενσωμάτωσης (Continuous Integration, CI) για μια γλωσσική διαδρομή του Exercism χρησιμοποιώντας το GitHub Actions (GHA). Παρέχει βέλτιστες πρακτικές και παραδείγματα που μπορείς να χρησιμοποιήσεις για να φτιάξεις τις δικές σου γρήγορες, αξιόπιστες και στιβαρές ροές εργασίας CI. Οι ροές εργασίας GHA σε αυτόν τον φάκελο μπορούν να προσαρμοστούν ώστε να δουλέψουν με οποιοδήποτε CI, επειδή η βασική δομή παραμένει ίδια.

Θα:

  • περιγράψει την ιδανική ροή εργασίας CI
  • συζητήσει ζητήματα και συστάσεις
  • σου δώσει μερικά πρότυπα για χρήση
  • σου αφήσει έναν οδηγό για τη μετάβαση από το Travis

Παράδειγμα υλοποίησης αυτών των αρχείων ροής εργασίας μπορείς να βρεις στο exercism/javascript.

ΒΟΗΘΕΙΑ: αυτό μοιάζει με πάρα πολλή δουλειά 😓

Το υπόλοιπο έγγραφο είναι σχεδιασμένο για να εξηγήσει πώς λειτουργούν οι ροές εργασίας. Αν βιάζεσαι και θέλεις απλώς να περάσεις από το Travis ή το Circle στο GHA χωρίς να βελτιστοποιήσεις τα script για τα PR, ρίξε μια ματιά στον οδηγό των ~10 λεπτών μας για τη μετάβαση από το Travis.

Ενέργειες CI της διαδρομής

Οι προτεινόμενες ενέργειες για τον έλεγχο της ακεραιότητας του περιεχομένου του αποθετηρίου σου είναι οι εξής:

  1. έλεγχος με configlet για να ελέγξεις το config.json
  2. έλεγχος για stubs
  3. έλεγχος για τεκμηρίωση (η v3 απαιτεί νέα αρχεία· αυτό μπορεί να μετακινηθεί στο configlet)
  4. lint των ασκήσεων χρησιμοποιώντας μια διαμόρφωση "maintainers"
  5. δοκιμή των ασκήσεων χρησιμοποιώντας τα αρχεία example/exemplar (μπορεί να περιλαμβάνει βήμα build)

Μπορεί επίσης να υπάρχουν ενέργειες ειδικές για τη διαδρομή. Για παράδειγμα:

  1. έλεγχος της ακεραιότητας των ρυθμίσεων των ασκήσεων
  2. έλεγχος της μορφοποίησης των αρχείων των ασκήσεων

Και ίσως να θέλεις περισσότερους ελέγχους ποιότητας ζωής, όπως:

  1. επιβεβαίωσε ότι υπάρχει το CONTRIBUTING
  2. επιβεβαίωσε ότι υπάρχει ένα λογικό lockfile για τις εξαρτήσεις
  3. επιβεβαίωσε ότι οι σύνδεσμοι μέσα στα αρχεία markdown είναι έγκυροι
  4. ...

Συστάσεις

Συχνότητα εκτέλεσης των ελέγχων

Για κάθε ενέργεια, σκέψου πόσο συχνά πρέπει να εκτελείται.

  • Ο έλεγχος με configlet είναι τόσο σημαντικός (επειδή μια διαδρομή μπορεί να σπάσει αν σπάσει το config.json) που μάλλον πρέπει να εκτελείται πάντα, αλλά χρειάζεται να εκτελεστεί μόνο μία φορά ανά commit.
  • Ο έλεγχος ύπαρξης ή ακεραιότητας των αρχείων χρειάζεται να εκτελεστεί μόνο μία φορά ανά commit.
  • Αν μια διαδρομή πρόκειται να εκτελείται σε πολλαπλές εκδόσεις runtime ή μεταγλωττιστή, το build και το test των ασκήσεων πρέπει να γίνεται για κάθε υποστηριζόμενη έκδοση
  • Τα PR μάλλον χρειάζεται να εκτελούν ενέργειες μόνο σε αρχεία που προστέθηκαν ή άλλαξαν, αλλά επειδή ένα αρχείο μπορεί να επηρεάσει μια άσκηση, είναι ασφαλέστερο να εκτελούνται οι ενέργειες για την άσκηση, αν αλλάξει ένα από τα αρχεία της.

Μπορεί να είναι πολύ χρήσιμο να κάνεις τις ενέργειες που πρέπει να εκτελούνται διαθέσιμες και τοπικά. Αυτό σημαίνει ότι τα script που κάνουν την πραγματική δουλειά μπορούν να εκτελεστούν και χειροκίνητα. Για να το πετύχεις αυτό, μην ενσωματώνεις την ενέργεια μέσα στα αρχεία ροής εργασίας, αλλά δημιούργησε ένα ξεχωριστό script. Για παράδειγμα, ο έλεγχος για stubs μπορεί να γίνει εξ ολοκλήρου με bash μέσα στο αρχείο ροής εργασίας, αλλά η σύσταση εδώ είναι να δημιουργήσεις αντ' αυτού ένα νέο εκτελέσιμο script, το scripts/ci-check.

"Μα η εντολή είναι πολύ σύντομη, π.χ. eslint . --ext ts --ext tsx".

Όταν αυτή η εντολή χρειαστεί να ενημερωθεί, πρέπει τώρα να ενημερωθεί σε όλα τα σημεία στην τεκμηρίωση, στα αρχεία ροής εργασίας και στα μυαλά των maintainers. Η εξαγωγή της σε ένα script λύνει όλα αυτά. Η ανάγνωση ενός αρχείου ροής εργασίας μπορεί επίσης να είναι πολύ τρομακτική.

Έλεγχοι σε PR όπου αλλάζουν ασκήσεις

Τα script scripts/pr και scripts/pr-check (δες τα πρότυπα) εκτελούνται με πολλαπλά ορίσματα, ένα για κάθε αρχείο που άλλαξε ή προστέθηκε σε αυτό το PR. Για παράδειγμα, αν το two-fer έχει ενημερωθεί, μια κλήση μπορεί να μοιάζει κάπως έτσι:

scripts/pr exercises/two-fer/README.md exercises/two-fer/.meta/example.ext

Συνιστάται να εκτελείς τυχόν ενέργειες για την άσκηση που άλλαξε και όχι για το αρχείο που άλλαξε. Αυτό συμβαίνει επειδή η αλλαγή ενός αρχείου πιθανότατα προκαλεί αλλαγές σε ολόκληρη την άσκηση (σκέψου: διαμόρφωση, πακέτα).

Δεν είσαι έτοιμος; / Πολύπλοκο;

Πριν εφαρμόσεις αυτή τη βελτιστοποίηση, μπορείς να την αγνοήσεις με ασφάλεια! Ο οδηγός μετάβασης υπονοεί να την προσθέσεις σε μεταγενέστερο στάδιο. Αν αγνοήσεις τα ορίσματα εισόδου, όλοι οι έλεγχοι θα εκτελεστούν σε όλες τις ασκήσεις. Αυτό είναι απολύτως εντάξει. Απλώς θα πάρει περισσότερο χρόνο.

Έλεγχοι ακεραιότητας

Αν η διαδρομή έχει ένα μόνο αρχείο εξαρτήσεων "top-level" ή/και άλλα αρχεία διαμόρφωσης, πρόσθεσε ένα βήμα ακεραιότητας (που υπάρχει δίπλα σε ένα scripts/sync ή bin/sync, το οποίο θα αντέγραφε όλα τα αρχεία διαμόρφωσης σε όλες τις ασκήσεις), το οποίο διασφαλίζει ότι τα αρχεία top-level/base είναι ίδια με αυτό που αντιγράφηκε στους καταλόγους των ασκήσεων. Τώρα οι εξαρτήσεις μπορούν να ενημερωθούν, να συγχρονιστούν σε όλο το αποθετήριο, και μπορούμε να διασφαλίσουμε ότι όλες οι ασκήσεις έχουν την ίδια διαμόρφωση.

Ένας συνηθισμένος τρόπος για να το πετύχεις είναι να χρησιμοποιήσεις ένα checksum. Το Ubuntu (και διάφορες άλλες διανομές Linux) έρχεται με ένα εργαλείο που λέγεται sha1sum, αλλά χρησιμοποιώντας οποιαδήποτε μέθοδο για να κατακερματίσεις ή να ανάγεις το αρχείο διαμόρφωσης (md5, sha1, crc32) σε μια τιμή checksum, θα δούλευε:

$ sha1sum README.md
cd58091c5043bf21f00d39ff1740d8b2976deeff *README.md

Έλεγχοι ασφαλείας

Αν η διαδρομή χρησιμοποιεί επιπλέον ροές εργασίας που απαιτούν πρόσβαση στο token του GitHub ή σε άλλα secrets, είναι βέλτιστη πρακτική να κλειδώσεις όλες τις ενέργειες που χρησιμοποιούνται στη ροή εργασίας σε ένα συγκεκριμένο commit. Δες τον οδηγό ενίσχυσης ασφαλείας του GitHub για λεπτομέρειες.

Για παράδειγμα:

- uses: julia-actions/setup-julia@v1
+ uses: julia-actions/setup-julia@d26d1111976eae5f00db04f0515ab744ec9cd79e # 1.3.1

Αν τα εργαλεία έχουν lockfiles για τη διαχείριση εξαρτήσεων, σκέψου να το κάνεις commit στο αποθετήριο και να χρησιμοποιήσεις ένα "frozen lockfile" μέσα στα αρχεία ροής εργασίας. Για παράδειγμα: npm ci, yarn install --frozen-lockfile και bundle install --frozen. Αυτό διασφαλίζει ότι το lockfile είναι ενημερωμένο όταν αλλάζεις εξαρτήσεις και αποτρέπει την είσοδο κακόβουλων πακέτων.

Πρότυπα

Σε αυτόν τον κατάλογο υπάρχουν τουλάχιστον τα ακόλουθα πρότυπα:

  • configlet.yml: Αυτή η ροή εργασίας θα φέρει το τελευταίο binary του configlet και θα κάνει lint σε αυτό το αποθετήριο. Εκτελείται σε κάθε commit. Για PR, εκτελείται στο πραγματικό commit και σε ένα δέντρο "after merge".
  • ci.yml: Αυτή η ροή εργασίας εκτελείται μόνο στον κύριο κλάδο, μία φορά σε κάθε commit.
    1. Εκτέλεσε μια εντολή "pre-check" (έλεγχος για stubs, lint, docs, κ.λπ.) για όλες τις ασκήσεις
    2. Εκτέλεσε μια εντολή "ci" (build και test) για πολλαπλές εκδόσεις, για όλες τις ασκήσεις
  • pr.ci.yml: Αυτή η ροή εργασίας εκτελείται μόνο σε PR, μία φορά σε κάθε commit.
    1. Εκτέλεσε μια εντολή "pre-check" (έλεγχος για stubs, lint, docs, κ.λπ.) για τα αρχεία που άλλαξαν
    2. Εκτέλεσε μια εντολή "ci" (build και test) για πολλαπλές εκδόσεις, για τις ασκήσεις που άλλαξαν

Οι ροές εργασίας που δεν αφορούν PR μπορούν επίσης να ενεργοποιηθούν μέσω του workflow_dispatch.

Κάθε αρχείο αναφέρει στην κορυφή ποια "scripts" πρέπει να είναι διαθέσιμα. Αν θέλεις αυτά να είναι binaries, αντικατέστησε το scripts/xxx με bin/xxx. Κάποια εργαλεία θα απαιτήσουν τα binaries να βρίσκονται μέσα σε έναν φάκελο bin.

  • scripts/ci: ένα script που θα πρέπει να κάνει build και test σε όλες τις ασκήσεις, χρησιμοποιώντας τις λύσεις-παραδείγματα σε αντιπαραβολή με τα tests
  • scripts/ci-check: ένα script που θα πρέπει να κάνει lint σε όλες τις ασκήσεις και, προαιρετικά, να ελέγχει για stubs, ακεραιότητα διαμόρφωσης και άλλα
  • scripts/pr: ίδιο με το scripts/ci, αλλά θα πρέπει να εκτελείται μόνο για ασκήσεις που προκύπτουν από τα paths που δίνονται ως είσοδος
  • scripts/pr-check: ίδιο με το scripts/ci-check, αλλά θα πρέπει να εκτελείται μόνο για αρχεία ή ασκήσεις που προκύπτουν από τα paths που δίνονται ως είσοδος

Αντιμετώπιση προβλημάτων

Αν αντιμετωπίσεις οποιοδήποτε πρόβλημα ή θέλεις κάποιος να ελέγξει τις ροές εργασίας σου, κάνε ping στην ομάδα @exercism/github-actions.

Άλλαξες ένα αρχείο top-level που θα έπρεπε να προκαλέσει εκτέλεση CI σε όλες τις ασκήσεις

Τη στιγμή που γράφεται αυτό, το pr.ci.yml επιτρέπει μόνο δοκιμές βάσει "επέκτασης". Ιδανικά, αυτό θα ενημερωθεί ώστε να ενεργοποιείται πάντα όταν αλλάζουν συγκεκριμένα αρχεία (για παράδειγμα το binary για την εκτέλεση των tests). Ωστόσο, αυτές οι αλλαγές είναι συχνά σπάνιες και γίνονται από maintainers, οπότε το γεγονός ότι το ci.yml εκτελείται στο main, πάντα, για τα πάντα, είναι μάλλον αρκετά ασφαλές.

Δημιούργησες ένα αρχείο scripts/xxx στα Windows και τώρα δε δουλεύει στο {άλλο λειτουργικό σύστημα}

Από προεπιλογή, τα αρχεία που δημιουργούνται στα Windows δεν έχουν ενσωματωμένα μεταδεδομένα στο git-index σχετικά με το αν είναι εκτελέσιμα, επειδή το μοντέλο δικαιωμάτων στα Windows είναι διαφορετικό. Το Git, από προεπιλογή, θα χρησιμοποιήσει τα μεταδεδομένα του git-index για να καθορίσει αν το αρχείο πρέπει να είναι εκτελέσιμο σε συστήματα βασισμένα σε POSIX, και έτσι θα κάνει το αρχείο scripts/xxx ΜΗ εκτελέσιμο.

git update-index --chmod=+x scripts/xxx
git commit -m "Make scripts/xxx executable"