Contact salesFree trial
Blog

Créez votre première action GitHub : Guide étape par étape

GitHubCI/CDDevOpsl'automatisationPrésentationSymfonyCon
Partager

Transcription de la vidéo

Nous avons utilisé ChatGPT pour améliorer la grammaire et la syntaxe de la transcription.

Très bien, bienvenue à tous. Je m'appelle Paul, je travaille pour Platform.sh et nous sommes fiers d'être l'hôte de SymfonyCon. Je suis donc ici aujourd'hui pour parler des actions GitHub. Dans mes présentations, j'aime donner une série d'avertissements. Pour ceux qui écoutent, j'ai une animation d'une lumière rouge qui clignote pour vous avertir, et dans ce cas, je vais commencer ma présentation par quelques avertissements.

Tout d'abord, je ne suis en aucun cas un expert en actions GitHub. Cependant, au cours des 18 derniers mois, j'ai été responsable de la construction et de la maintenance d'une large collection d'actions et de flux de travail personnalisés pour aider à automatiser une grande partie des responsabilités de mon équipe. Au cours de cette période, j'ai rencontré de nombreux domaines de frustration et de confusion sur la plateforme, et c'est en quelque sorte ce qui a motivé cette présentation. Mon but, ou mon espoir, est que je puisse vous aider à naviguer dans ces zones de confusion et à vous lancer dans l'automatisation au sein de GitHub.

Le prochain avertissement que je vous donnerai est que je m'attends à ce que vous interagissiez avec moi. Je vais poser beaucoup de questions pendant la présentation et j'ai besoin que vous y répondiez. Le dernier avertissement est que je vais parler très vite parce qu'il s'agit en fait d'un atelier de trois heures que j'essaie de condenser en 35 minutes.

Cela étant dit, voici ce que je souhaite aborder au cours de ces 35 minutes : Je veux parler de la plateforme d'actions et de ce qu'elle est. Je vais ensuite passer en revue les différents composants et éléments de GitHub Actions que vous allez utiliser pour construire votre automatisation. Je vais ensuite parler de l'un de ces éléments, le flux de travail, et nous allons approfondir le flux de travail et parler des éléments et des parties du flux de travail qui sont nécessaires et que vous allez utiliser. Puis, ensemble, nous allons construire notre premier flux de travail - c'est donc un indice que c'est là que j'ai besoin que vous interagissiez avec moi. Ensuite, nous passerons aux actions et à la construction d'actions personnalisées, en parlant des pièces et des parties qui se trouvent à l'intérieur d'une action personnalisée et des choses qui sont nécessaires pour que vous puissiez construire une action personnalisée.

Je dois me déplacer vers la droite - pardon, continuer à me déplacer vers la droite, je dois aller jusqu'à la droite. D'accord, c'est mieux ? D'accord, désolé, j'aime marcher, alors je ne savais pas que je devais rester ici. Ensuite, en cours de route - oh, désolé - nous allons construire notre première action personnalisée ensemble, et la voir utilisée. Au fur et à mesure, je vous donnerai d'autres avertissements, des mises en garde, et des trucs à éviter. Enfin, j'espère qu'avec suffisamment de temps, je vous montrerai comment toutes ces choses se combinent pour construire une véritable automatisation dans la vie réelle.

Tout d'abord, qu'est-ce que GitHub Actions ? GitHub Actions est un service de GitHub. Il s'agit d'une plateforme d'intégration et de livraison continues qui vous permet d'automatiser les choses autour de votre base de code, qu'il s'agisse de la construction, du déploiement ou des tests. C'est ce qui vous donne la possibilité d'automatiser, et ce n'est pas seulement lié au code. Il peut également s'agir de la gestion de projets. Ainsi, tout ce que vous devez faire lorsque quelque chose arrive à votre base de code, nous pouvons utiliser cette plateforme afin d'automatiser les choses.

Quels sont donc les éléments que vous allez utiliser ? Eh bien, vous allez travailler avec ce que l'on appelle des flux de travail. Nous avons des événements, des runners, des jobs, des étapes et des actions GitHub (mais avec un "a" minuscule). Si vous m'écoutez, j'ai un monsieur qui me dit : "Attendez, quoi ?" Oui, les actions GitHub avec un "A" majuscule font référence à la plateforme - l'ensemble de la plateforme d'automatisation. Si vous voyez des actions GitHub avec un 'a' minuscule, cela fait référence à un élément d'automatisation modulaire et autonome que vous pouvez utiliser dans votre automatisation. Parfois, on parle d'actions personnalisées - regardez ça - et parfois simplement d'actions. Mais sachez que cela arrive. En fait, toute la plateforme - c'est malheureux la façon dont GitHub a décidé de nommer certaines choses - ils utilisent souvent un mot, et selon l'endroit où le mot est utilisé, il aura une signification différente. Si l'anglais n'est pas votre langue maternelle, c'est particulièrement difficile. On peut citer le cas de "status" par rapport à "checks" par rapport à "status checks", et ce sont trois choses différentes, pas nécessairement liées.

Donc, si vous vous trouvez dans une situation où ce que vous voyez - dois-je me déplacer à nouveau ? Je suis désolé - si ce que vous voyez ne correspond pas à ce que vous lisez dans la documentation, vous avez peut-être rencontré l'une de ces situations similaires. Très bien, nous avons donc des flux de travail, des exécutants, des tâches, des étapes et des actions. Comment ces éléments s'intègrent-ils les uns aux autres ? Eh bien, nous configurons notre automatisation dans un fichier de flux de travail - c'est là que nous définissons toute l'automatisation que nous voulons voir se produire. Ces flux de travail, ces éléments d'automatisation, vont être déclenchés par un événement - quelque chose qui se produit dans notre base de code - qui déclenche alors une série de tâches. Les jobs sont l'endroit où nous définissons un ensemble d'étapes, et ces étapes sont celles qui exécutent notre logique métier, qu'elles appellent d'autres commandes ou scripts shell, ou qu'elles appellent l'une des actions que j'ai mentionnées plus tôt.

J'aimerais maintenant me pencher sur chacun de ces composants, les définir et les expliquer un peu plus en détail. Donc, le flux de travail - j'ai mentionné que le flux de travail lui-même est l'automatisation. Nous le configurons dans ce que l'on appelle un fichier de flux de travail. Un fichier de flux de travail doit être un fichier YAML - sonnom n'a pas d'importance, il doit juste être un fichier YAML - mais il doit être contenu dans un répertoire .github/workflows à la racine de votre référentiel. Maintenant, votre référentiel lui-même peut avoir plusieurs flux de travail. Vous pouvez avoir un flux de travail déclenché sur le même - vous pouvez avoir une tonne de flux de travail déclenchés sur le même événement ; ils peuvent chacun être déclenchés sur des événements différents ; un flux de travail peut être déclenché par plusieurs événements ; quelle que soit votre situation particulière - il doit juste être YAML et il doit être dans ce répertoire.

Un événement est donc une activité qui se produit dans votre base de code, qu'il s'agisse d'un push, d'une pull request, que quelqu'un ait étiqueté quelque chose - peu importe, c'est juste quelque chose qui se produit. Maintenant, vous avez tout un tas - je vais le feuilleter rapidement - vous avez tout un tas d'événements, et je les ai ici. Vous pouvez voir ici, sur le côté droit, une tonne d'événements qui vous permettent de contrôler avec précision le moment où vous voulez que ces flux de travail soient déclenchés. Je tiens à préciser que dans la documentation, le mot "événement" est parfois remplacé par "déclencheur de flux de travail". Donc, si vous voyez un déclencheur de flux de travail, c'est la même chose - cela signifie exactement la même chose qu'un événement.

Une unité d'exécution est simplement une instance de serveur virtuel - c'est l'endroit où l'automatisation sera exécutée lorsque le flux de travail est déclenché. Vous pouvez utiliser les runners publics fournis par GitHub, ou si vous avez un cas d'utilisation très particulier, vous pouvez également mettre en place votre propre runner auto-hébergé. Si vous optez pour les runners publics, vous avez le choix entre macOS, Windows et Ubuntu dans différentes versions. Une chose à laquelle il faut faire attention, c'est que les programmes d'exécution publics sont publics, ce qui signifie que lorsque vous voulez exécuter votre flux de travail, il peut ne pas se produire immédiatement parce que vous pouvez être placé dans une file d'attente en attendant qu'un programme d'exécution public devienne disponible. Il faut donc en être conscient.

Un job est simplement une collection d'étapes - c'est là que nous allons définir toute notre logique métier et l'automatisation que nous voulons voir se produire. Elles seront exécutées dans ce runner - dans le même runner - donc vous n'aurez pas une étape exécutée sur un runner et la suivante sur un runner différent - elles seront toujours exécutées sur ce même runner. Nous indiquons à la plateforme GitHub Actions l'exécutant sur lequel nous voulons nous exécuter via la propriété runs-on du travail. Ainsi, nous disons, nous avons ce travail, je veux qu'il s'exécute sur macOS 10.12. Par défaut, les tâches à l'intérieur de votre flux de travail vont s'exécuter en parallèle - elles vont toutes s'exécuter exactement en même temps. Si nécessaire, nous pouvons définir des dépendances entre ces travaux, mais il est important de se rappeler - par défaut, jusqu'à ce que vous configuriez cette dépendance - qu'ils vont tous démarrer exactement au même moment. Techniquement, un flux de travail peut comporter un nombre illimité de tâches. Il y a un astérisque à côté de "illimité" parce qu'il y a des limites à la durée d'exécution d'un travail et au nombre de travaux que vous pouvez exécuter en parallèle, donc avec ces limitations, vous ne pouvez pas vraiment avoir un nombre illimité.

Une étape est simplement un script shell ou un appel à une action que l'on souhaite exécuter. Elles sont exécutées dans l'ordre - elles ne sont pas exécutées en parallèle - mais elles sont exécutées une à la fois et dépendent les unes des autres. Ainsi, par défaut, si une étape précédente échoue, toutes les autres étapes de ce travail échoueront. Encore une fois, si nécessaire, nous pouvons modifier ce comportement par défaut, mais c'est ainsi qu'il fonctionne par défaut. Et encore une fois, toutes ces étapes - et c'est important - toutes les étapes s'exécutent dans le même runner. Il n'est pas question d'exécuter l'étape 1 sur Ubuntu et l'étape 2 ailleurs - cela ne se produira pas. Nous pouvons configurer des tâches pour qu'elles s'exécutent sur plusieurs versions de runners, mais par défaut, ces étapes vont toutes s'exécuter sur le même runner.

Comme je l'ai mentionné précédemment, une action est simplement un élément d'automatisation autonome, comme un bloc de Lego, que nous pouvons ensuite combiner avec d'autres actions pour construire des tâches d'automatisation complexes. Donc, en creusant dans la configuration de ce fichier de flux de travail, il y a certaines choses que vous devez avoir pour construire cette automatisation. Vous devez avoir un événement. Ainsi, à l'intérieur de ce fichier de flux de travail, nous devons définir au moins un événement pour indiquer à la plateforme quand nous voulons ou comment nous voulons que ce flux de travail soit déclenché. À l'intérieur de cet événement, nous devons définir au moins un travail, et ce travail doit comporter au moins une étape. Les étapes elles-mêmes doivent exécuter une commande shell ou utiliser une action.

Nous allons donc créer notre premier flux de travail. Si vous ne voyez pas le script, dites-le-moi et j'essaierai d'agrandir un peu la police. Quelle est l'une des choses que nous devons avoir ? Un événement. D'accord, je vais utiliser le mot-clé on. Maintenant, je vais donner un coup de chapeau à JetBrains pour avoir créé une merveilleuse collection d'IDEs. J'ai un plugin pour m'aider à construire des flux de travail, donc vous pouvez voir que dès que je commence ce mot-clé, il est automatiquement pré-rempli, et maintenant j'ai une tonne d'événements différents que je peux utiliser. Pour celui d'aujourd'hui, je vais utiliser le workflow_dispatch. Le workflow_dispatch me permet d'exécuter un workflow manuellement, de sorte que je puisse le déclencher moi-même quand j'en ai besoin, au lieu d'avoir à essayer de recréer un événement existant. Quelle est l'autre chose que nous devons avoir ? Nous devons avoir un exécutant. Mais où définissons-nous l'exécutant ? Qu'est-ce que c'est ? Je crois que je l'ai entendu - les emplois. D'accord, je vais donc faire des emplois, et je dois créer un emploi. Je vais donc dire que celui-ci s'appelle " dire bonjour ", et puis qu'est-ce qu'on dit - on a besoin d'un coureur ? Je vais donc dire run-on, dans ce cas, je vais dire ubuntu-latest. Ensuite, de quoi ai-je besoin à l'intérieur du job ? Des étapes. Je vais donc définir quelques étapes, et dans ce cas, je vais dire run : echo "hello there"- pas"Jello there", pourquoi pas "hello there" ? Oui, c'est ça. Voilà, c'est fait.

Maintenant, pour exécuter vos actions - oups, ce n'est pas le bon onglet. Essayons celui-ci - nous y voilà - qui n'est pas non plus le bon. Et voilà ! Pour exécuter ces actions, vous allez les exécuter dans l'onglet actions de votre référentiel. Si vous avez votre ordinateur et que vous voulez le voir, le dépôt lui-même est épinglé ici en haut de mon profil. Mon profil se trouve sur github.com/gillo-mon nom de famille. J'ai un nom de famille inhabituel. À l'intérieur de ce référentiel, j'ai un onglet Actions, et c'est là que toutes mes actions - ici à gauche - vont être définies. Nous venons d'en créer une appelée "premier". Maintenant, je ne vais pas l'exécuter parce que je ne veux pas attendre qu'un runner public se mette en place, mais je vais vous montrer son exécution. Par défaut, vous verrez le nom du flux de travail du fichier à l'intérieur - il énumérera ensuite tous les travaux - il y a donc ce travail " say hello ". Puis, à l'intérieur de celui-ci, au fur et à mesure que nous creusons, il énumère les étapes en cours d'exécution - nous venons d'en exécuter une, qui consistait à dire " bonjour ". Pas d'applaudissements - oui ! Nous avons réussi ! Nous avons créé notre premier flux de travail - fantastique.

Approfondissons un peu, car j'ai utilisé des éléments dont je n'ai pas encore parlé. L'un d'entre eux est l'identifiant du travail. Chaque travail doit avoir un identifiant. Dans l'exemple que nous venons de faire, je l'ai appelé "saycore hello". C'est parce qu'il doit être composé de caractères alphanumériques, de tirets ou de traits de soulignement. Ils doivent être uniques dans le flux de travail. Nous pouvons donc avoir autant de travaux que nous le souhaitons, mais ils doivent tous avoir un identifiant unique et commencer par une lettre ou un trait de soulignement. Une fois encore, à l'intérieur de ces étapes, il s'agit simplement d'un tableau de tâches - chacune d'entre elles devant être exécutée. Il est important de se rappeler que chaque étape va s'exécuter à l'intérieur de son propre processus. Ainsi, tout comme si vous deviez créer un sous-processus dans une commande shell, il sera dans son propre processus ou démarrera une nouvelle session - ils s'exécuteront chacun dans leur propre processus. Mais ils ont tous accès - parce qu'ils s'exécutent sur le même runner - ils ont tous accès au même système de fichiers. Ainsi, si une étape précédente écrit dans un fichier, une étape ultérieure y aura accès parce qu'elle a accès au système de fichiers.

Chaque étape individuelle doit alors inclure la propriété uses, qui dit, "Hey, GitHub Actions, je veux utiliser une action existante - je veux que vous la récupériez et l'exécutiez," ou, comme nous l'avons fait, nous avons utilisé la propriété run, qui dit, "Hey, je veux exécuter cette commande shell," ou "je veux exécuter ce script shell." Très bien, examinons notre deuxième flux de travail. Revenez ici - et ce devrait être - oups, revenez - je suis sur le mauvais - et voilà. Dans ce cas, j'ai mon événement, donc sur workflow_dispatch, j'ai le même travail exact, "say hello", mais remarquez que je lui ai donné un nom. L'un des éléments que vous pouvez utiliser à l'intérieur de vos flux de travail est de donner un nom au flux de travail, afin qu'il ait une belle étiquette dans l'onglet des actions. Vous pouvez donner à chaque tâche une propriété de nom, ce qui vous permet d'avoir un joli nom de tâche au lieu d'un simple ID - vous pouvez même donner des noms à vos étapes. Mais dans ce cas, je lance un "bonjour" - je dis ensuite "Hé, utilise une action". Je vous montre cette action parce que, par défaut, contrairement à GitLab, GitHub Actions n'extrait pas votre dépôt dans le runner lorsque vous le démarrez. Si vous avez besoin d'accéder au code de votre dépôt, vous devez utiliser l'action checkout pour dire, "Check out my repository into this file system". Donc, dans ce cas, j'ai en fait extrait ce référentiel dans le système de fichiers, ce qui me permet, dans la troisième étape, d'extraire cette liste de fichiers - et puis dans la quatrième étape, je suis juste en train de courir - "Je suis l'étape quatre". Jetons donc un coup d'œil à celle-ci. Revenez ici - revenez - je vais revenir à mes actions. Maintenant, remarquez à gauche - c'est là - " Bienvenue à la fête ", deuxième à gauche - cliquez dessus. Si je m'y plonge, je remarque que le travail n'est plus l'ID du travail, mais cette belle étiquette. Et maintenant, à l'intérieur, j'ai mes quatre étapes, la troisième ayant cette belle étiquette plus lisible par l'homme. Vous êtes un public difficile - pas d'applaudissements pour chacune de ces étapes - Wow, d'accord. Voilà, c'est ce que je cherchais.

Très bien, vous vous demandez peut-être : "Très bien, Paul, nous en sommes à la moitié de cette présentation, et jusqu'à présent, vous en avez passé la moitié à parler de flux de travail. Je pensais qu'il s'agissait d'actions, pourquoi ?" Quelqu'un se pose la question ? Oui, d'accord, même si nous construisons une action au début, vous ne pouvez pas utiliser une action directement - vous ne pouvez utiliser une action que par le biais d'un flux de travail. Donc, si vous ne savez pas comment fonctionnent les flux de travail, vous ne pouvez pas utiliser les actions. Deuxièmement, une action - une action composite, dont nous parlerons des différents types dans un instant - fonctionne presque de la même manière qu'un flux de travail avec l'événement workflow_dispatch. Ils sont très similaires - ils partagent beaucoup de choses, comme les entrées. Ainsi, lorsque vous travaillez, lorsque vous construisez votre logique métier, l'une des idées derrière une action est qu'elle est réutilisable, n'est-ce pas ? Vous pouvez l'utiliser dans plusieurs instances. Il y a donc de fortes chances que vous ayez besoin d'ingérer ou d'accepter des informations dans cette action, et c'est à cela que servent les entrées. Mais workflow_dispatch peutaussi les utiliser, donc nous pouvons utiliser les inputs dans un workflow_dispatch ou à l'intérieur de notre action, et nous pouvons définir tous les inputs que nous voulons. Et tout comme pour les jobs, ils doivent avoir des ID uniques, et encore une fois, être alphanumériques.

À l'intérieur d'une action, il y a quelques différences. L'une d'entre elles est que vous devez inclure une description pour chaque entrée à l'intérieur d'une action. workflow_dispatch, vous pouvez les inclure, mais vous n'êtes pas obligé de le faire - mais dans une action, c'est obligatoire. Un autre élément que vous pouvez utiliser est la propriété required, qui indique si l'entrée est nécessaire pour que le flux de travail ou les actions s'exécutent. Enfin, vous pouvez définir des valeurs par défaut, de sorte que s'ils ne fournissent pas cette valeur ou s'ils ne fournissent pas de valeur pour cette entrée particulière, vous pouvez définir une valeur par défaut connue. Vous accédez à ce qui est entré par le biais de ce que l'on appelle un "contexte", dont je vais parler plus loin. Examinons une entrée. Revenons en arrière - nous y sommes. Remarquez que j'ai activé : workflow_dispatch. J'ai maintenant une propriété inputs. Dans la propriété inputs, j'ai donné un nom à l'une de ces entrées, j'ai configuré la description et j'ai dit que c'était vrai. J'ai mentionné plus tôt que nous allions accéder à cette entrée par l'intermédiaire d'un contexte - c'est ce qu'est ce petit morceau ici. Il dit : "Hé, retournez aux entrées - prenez maintenant la valeur de l'ID de l'entrée - le nom." Vous comprenez ? Très bien, voyons cela en action.

Revenons à la troisième entrée. Dans ce cas, je vais l'exécuter. J'ai mentionné plus tôt que vous pouviez exécuter des flux de travail par le biais de workflow_dispatch - c'est ainsi que ce petit bouton à droite apparaît. Et remarquez - qu'est-ce que ça dit ? "Quel est votre nom ?" Il y a cette entrée, et si j'essaie de l'exécuter - qu'est-ce que c'est - merci, merci - alors si j'essaie de l'exécuter, qu'est-ce qui se passe ? Échec, oui, il dit : "Non, c'est nécessaire." Alors, je dirai : "Jérôme, bonjour, Jérôme, wouahou !" Je vais donc exécuter ce flux de travail - avec un peu de chance, il y a un coureur public assez rapidement. Allez, les exécutants publics - je saurai que c'est un exécutant public qui l'exécute parce que la petite coche se transformera en point - hé, c'est parti ! Je peux maintenant aller dans la liste de mon travail - il est en cours d'exécution ou en attente - là, il demande - allez, finissez, finissez - hé ! Très bien, c'est fait, nous y voilà, merci, merci à tous.

D'accord, donc, les contextes sont la façon dont vos actions, vos flux de travail reçoivent des informations de la plateforme d'actions, que ce soit à propos des exécutants, du travail, du flux de travail lui-même, des événements qui se produisent - c'est la façon dont cette information est exposée à votre base de code. Vous disposez de 12 types de contextes, que je vais vous présenter ici. Ici, à droite, vous pouvez voir que nous avons 12 types différents. Encore une fois, les coureurs, les étapes, les entrées, les besoins, la matrice, les secrets, les variables, etc. Il convient toutefois de noter que tous les contextes ne sont pas disponibles dans toutes les situations. C'est pourquoi vous pouvez utiliser ce que l'on appelle une "matrice". Si vous n'utilisez pas de matrice, c'est que le contexte de la matrice n'est pas disponible. Il faut donc se rendre compte que tous les contextes ne sont pas disponibles à tout moment. Pour accéder à un contexte, si vous utilisez quelque chose qui n'est pas une action personnalisée basée sur JavaScript utilisant la boîte à outils GitHub, vous accéderez à ces contextes avec le signe dollar - comment les appelez-vous, les parenthèses fantaisie - les parenthèses fantaisie, je ne sais pas comment elles s'appellent en fait, peu importe comment elles s'appellent - le nom du contexte, le nom de la propriété que vous voulez. Ensuite, les propriétés elles-mêmes peuvent être les valeurs de chaîne que vous recherchez, ou elles peuvent être d'autres objets, et vous pouvez creuser encore et encore jusqu'à ce que vous atteigniez le contexte dont vous avez besoin, comme l'accès à un contexte d'étapes où j'accède à un ID spécifique d'une étape, puis je cible ses sorties, dont nous allons parler - les sorties dans une seconde - je cible son contexte de sorties pour obtenir la valeur contenue dans l'ID de l'URL ciblée.

Si vous utilisez JavaScript, vous disposez d'une jolie petite boîte à outils qui expose ces différents contextes par le biais de méthodes. Maintenant, il y a un petit avertissement, et c'est un avertissement important - s'il vous plaît, si vous ne vous souvenez de rien d'autre de cette présentation, souvenez-vous de ceci - les contextes qui viennent de l'entrée fournie par l'utilisateur ne sont pas pré-escapés - ils ne sont pas préparés pour que vous puissiez les utiliser à l'intérieur de commandes shell ou de votre code directement. D'accord ? Cela signifie qu'ils sont mûrs pour l'injection de code. Par exemple, si j'essayais de définir une variable shell égale à un titre de demande - un titre de demande d'extraction - les titres de demande d'extraction proviennent des utilisateurs - ce qui se passerait, c'est qu'ils créeraient un titre de demande d'extraction appelé a" ;, alors quand je définirais title="a" ;, que se passerait-il ? C'est une commande shell complète, n'est-ce pas ? Ce point-virgule dit : " C'est la fin d'une commande, voici la suivante. " Je finirais par exécuter cette commande. Sachez donc que ces commandes ne sont pas prêtes à être utilisées directement.

D'accord, donc les sorties - si vous avez accepté des données d'entrée, que vous avez effectué un traitement sur ces informations, vous pouvez avoir besoin de sortir des informations. En outre, si vous construisez un flux de travail complexe, à un moment donné, l'une de ces étapes va probablement faire quelque chose à laquelle vous voulez qu'une autre étape puisse accéder. Les sorties sont donc simplement des données ou des informations que vous souhaitez envoyer d'une action vers le flux de travail appelant, ou d'une étape vers l'étape suivante. Il s'agit donc d'informations que nous pouvons réutiliser ultérieurement. Pour définir une sortie - encore une fois, à partir de tout ce qui n'utilise pas la boîte à outils JavaScript - vous faites un écho de l'ID égal à la valeur, puis vous l'envoyez à la variable environnementale de sortie de GitHub. Ou, si vous utilisez la boîte à outils JavaScript, vous disposez d'une méthode setOutput qui vous permet de définir ces valeurs. Ensuite, comme nous l'avons vu plus tôt, pour utiliser ces valeurs, vous allez accéder à un certain contexte - les étapes - très probablement les étapes - l'ID de l'étape qui sort l'objet d'ici, et ensuite l'ID que nous avons peut-être défini.

Voulez-vous voir cela en action ? Voilà, c'est parti ! Très bien, je devrais être - j'allais dire, vous devriez être très réveillé maintenant. Très bien, nous avons donc un autre flux de travail ici - oh, je vais faire défiler la page vers le haut parce que j'ai agrandi un peu la police de caractères. Remarquez qu'à la troisième étape - la deuxième, excusez-moi - la deuxième étape, je prends l'horodatage actuel de la date - je vais ensuite le définir en tant qu'ID de currentTime, l'envoyer à la sortie, et à la troisième étape, je peux accéder à cette valeur que j'ai définie via le contexte des étapes - je remonte pour obtenir l'heure, je saisis currentTime pour l'envoyer à la sortie. Je vais vous montrer cela en action. Retournez ici, revenez à mon onglet d'actions - ai-je entendu un bâillement ? Je ne suis pas si ennuyeux, n'est-ce pas ? Bon sang, vous êtes durs à la tâche. Voyons voir - c'est le troisième - j'ai oublié lequel - oh, le voilà. Alors, creusez ici - c'est mon travail de "dire charge", et aussi de prendre le temps. Ici, vous pouvez voir que j'ai réglé l'heure, je l'ai envoyé en écho à la sortie. Permettez-moi de saisir mon pointeur ici. J'ai donc défini currentTime= la date, puis, à la quatrième étape, je l'envoie à la sortie via ce contexte. Voilà, c'est ce que je cherchais.

Très bien, nous sommes maintenant prêts. Nous disposons de tous les outils et de toutes les connaissances nécessaires. Nous sommes prêts à construire des actions personnalisées - oh, mais pas des actions avec un "A" majuscule - nous devons construire des actions avec un "a" minuscule, ne l'oubliez pas. Il existe donc trois types d'actions que vous pouvez créer. Nous avons accès à une action de type Docker, à une action JavaScript et à une action composite. La différence est que Docker vous permet d'être très précis dans l'environnement dans lequel votre logique d'entreprise s'exécute. Ainsi, si vous avez des exigences très strictes, vous devrez probablement utiliser votre propre image Docker plutôt que l'un des runners publics. Une action composite basée sur JavaScript est intéressante car elle permet de séparer le code de l'action - la logique métier - du service d'action lui-même, et d'être plus à même - plus à même - plus à même - plus à même - plus à même - je me suis embrouillé - plus à même - plus à même - plus à même - je me suis embrouillé - de simuler l'environnement et de tester ce code en dehors de la plateforme GitHub Actions, et elle s'exécute généralement un peu plus rapidement qu'une action personnalisée basée sur Docker. Le problème d'une action personnalisée basée sur JavaScript est que vous ne pouvez pas utiliser ou réutiliser l'action publique de quelqu'un d'autre à moins qu'il n'ait également exposé cette action sous la forme d'un package JavaScript. C'est pour cela que la troisième action est disponible - la troisième est appelée composite, et c'est ce qui vous permet d'utiliser les actions d'autres personnes à l'intérieur de votre propre action, ce qui vous permet à nouveau d'utiliser cette modularité plus Lego-block pour assembler les choses en quelque chose de plus complexe.

Les actions elles-mêmes doivent être stockées dans un référentiel, ou si vous voulez les stocker dans un référentiel existant, elles doivent être dans leur propre répertoire. Il y a des éléments et des parties d'actions que vous devez avoir - excusez-moi - et le premier est qu'ils doivent tous avoir un fichier de métadonnées. Ce fichier de métadonnées doit être un fichier YAML, nommé action.yml, et doit être stocké à la racine du référentiel du répertoire dans lequel votre action est stockée. Il doit contenir au moins trois propriétés - quatre techniquement. Il doit avoir un nom, une description et la propriété runs avec la sous-propriété runs-using. Il doit avoir toutes ces propriétés. Et c'est ce runs-using qui indique à la plateforme d'actions quel type nous allons utiliser - donc runs-using : docker, runs-using : composite. Selon le type d'action que vous choisissez, d'autres propriétés sont requises à l'intérieur de la propriété runs. De plus, c'est dans le fichier de métadonnées que nous définissons les entrées et les sorties.

Ainsi, un exemple d'action - et il s'agit d'un fichier d'action complet - est le suivant : J'ai ma propriété name, "Greets user", j'ai la description : Greet user to the GitHub Actions platform, puis j'ai la propriété runs avec une sous-propriété using, et j'utilise node:20 pour désigner une action personnalisée basée sur JavaScript. Et parce que je fais une action personnalisée basée sur JavaScript, je dois alors avoir la propriété main et la diriger vers mon bootstrap ou mon fichier de démarrage pour ma logique d'entreprise à l'intérieur de ce paquet JavaScript

Les trois différents types d'actions composites ou les trois différents types d'actions entraînent quelques avertissements. Lorsque vous utilisez la propriété runs-using pour Docker et composite, vous utilisez les mots "Docker" et "composite", mais pour JavaScript, vous n'utilisez pas le mot "JavaScript" - vous utilisez la version de node que vous voulez utiliser. À l'heure actuelle, seules les versions 16 et 20 sont valables pour Node à l'intérieur d'une action personnalisée - la version 16 est obsolète depuis le 24 octobre. Il n'y a pas encore de sous-remplacement, donc la seule version à laquelle vous avez vraiment accès est la 20. Je crois que Node 22 va être publié au printemps prochain, et il est fort probable qu'ils ajouteront alors Node 22 en tant qu'option à ce moment-là. L'autre défi avec une action personnalisée basée sur JavaScript est que vous devez livrer l'intégralité du répertoire node_modules, ou toutes vos dépendances JavaScript, dans ce dépôt afin de les utiliser, ou utiliser quelque chose comme le NCC de Vercel pour regrouper toutes vos dépendances dans un seul fichier JavaScript.

L'avertissement avec l'action personnalisée basée sur le composite est que parce que vous utilisez ces runners, les binaires et les programmes à l'intérieur des runners peuvent ne pas être la version dont vous avez besoin, de sorte que vous pouvez vous retrouver à devoir mettre à jour les versions avant que vous puissiez utiliser une commande shell. À ce moment-là, si vous passez la majeure partie de votre action personnalisée - cette action composite - à mettre à jour les dépendances, c'est peut-être à ce moment-là qu'il faut passer à une action basée sur Docker. Alors, vous êtes prêt à construire une action personnalisée ? C'est ce que j'aime entendre.

D'accord, alors qu'est-ce que je dois avoir - oh, oh, c'est bon - d'accord, pour une action, qu'est-ce qu'on doit avoir pour construire l'action ? Fichier de métadonnées - de quoi avons-nous besoin ? Un nom - d'accord, j'ai mon nom. Quoi d'autre ? Une description - quoi d'autre ? Exécution - utilisation. Très bien, j'ai donc composite. Dans ce cas, composite va utiliser d'autres actions, donc il va y avoir un besoin d'étapes. Dans ce cas - j'ai oublié de le mentionner - je construis cette action ici, dans le répertoire .github/actions, et elle a son propre répertoire. Il n'est pas nécessaire que ce soit " actions " - je viens de le faire - cela m'a semblé logique - j'allais tous les stocker dans un endroit similaire, mais mon fichier de métadonnées est à la racine.

Alors, que dois-je faire pour pouvoir utiliser le référentiel que nous avons vu plus tôt ? Oh, je dois le vérifier, d'accord - oups, j'ai sauté une étape - oh, j'ai sauté tout le chemin - je suis désolé, j'ai sauté mes étapes. Donc, nous n'allons pas - nous allons faire cela dans le flux de travail, désolé. Nous essayons donc de recréer cette action dans le flux de travail que nous avons fait plus tôt. Ce que je veux faire, c'est la même chose - je veux dire " bonjour " à quelqu'un, donc je vais avoir une entrée. Cette fois, je vais l'appeler who_to_greet, et configurer la description. Nous pouvons ignorer l'acte de type uniquement - chaque type à l'intérieur d'une action est une chaîne de caractères. Dans les flux de travail, vous avez plusieurs types, donc dans ce cas, je l'ai juste réutilisé. Maintenant, dans mon étape, je lui ai donné un nom, je lui ai donné un ID - dans ce cas, j'ai dit que je voulais utiliser l'interpréteur de commandes bash au lieu d'un autre type d'interpréteur de commandes, et ensuite je vais exécuter : echo "Hello" ${{ inputs.who_to_greet }}.

Pouvons-nous exécuter cette action directement ? Non, qu'est-ce qu'il nous faut ? Un flux de travail - d'accord. À l'intérieur du flux de travail, que devons-nous avoir ? Un événement. D'accord, il y a mon événement - quoi d'autre ? Des emplois. Donc, il y a mon travail et quoi d'autre ? Des étapes. Maintenant, parce que j'ai stocké cette action dans le référentiel lui-même, j'ai besoin d'extraire le référentiel et d'être capable d'utiliser cette action. Je peux alors dire "Très bien, je veux utiliser l'action qui est stockée dans ce référentiel", mais cette action que nous venons de créer a une... a quoi ? Une entrée. Je vais donc utiliser le mot-clé with, puis je vais utiliser ce même ID d'entrée et lui donner une valeur. Parce que je veux exécuter ceci comme une distribution, je vais probablement avoir besoin de fournir une entrée, donc je vais aussi inclure une entrée sur le flux de travail lui-même. Ainsi, le flux de travail va s'exécuter, il va avoir une entrée, je vais alors prendre ce qui est entré et l'envoyer à l'action que nous venons de créer.

Êtes-vous prêt à voir cela en action ? Oui, c'est ça. D'accord, retournons à l'onglet des actions et disons " V, une action " en appuyant sur " run ". Remarquez qu'il y a qui nous devons saluer - encore une fois, je dirai " SymfonyCon 2023 ", mais je vais mettre quelques points d'exclamation de plus ici - non, juste là - oh, allez jusqu'au bout - pourquoi ne me laisse-t-il pas le sélectionner ? Voilà - nous dirons " Super excité " - nous lancerons ce flux de travail - allez, les coureurs publics - parce que je sais que je suis proche de l'heure - allez, allez, allez - nous y voilà - cliquez dessus. Maintenant, c'est notre flux de travail - nous creusons dans le flux de travail - nous pouvons voir qu'il a vérifié notre référentiel - il a ensuite exécuté notre utilisateur d'accueil - et si je l'exécute, je devrais l'avoir - nous y voilà ! Et voilà !

Très bien, alors qu'avons-nous couvert ? Nous avons parlé de la plateforme d'actions, n'est-ce pas ? Nous avons parlé des différents composants de la plateforme d'actions que nous pouvons utiliser. Nous avons parlé du fichier de flux de travail et de la manière dont nous définissons le fichier de flux de travail et les éléments qui sont nécessaires. Nous avons ensuite construit notre premier flux de travail ensemble. Nous avons parlé des actions personnalisées et des éléments nécessaires. Nous avons ensuite construit cette action avec ce flux de travail et nous avons parlé de quelques avertissements, n'est-ce pas ? Mais, les bonjours sont toujours un peu, hum, pas tout à fait aussi utiles, n'est-ce pas ? Alors, mettons tout ensemble. Mettons tout cela ensemble dans un exemple du monde réel. Et l'objectif - dans ce cas particulier, c'était un objectif réel - c'est que nous avions besoin, pour chaque demande d'extraction, de pouvoir exécuter un test de régression visuel. Tout le monde est familier avec les tests de régression visuels, où vous prenez une capture d'écran de votre site de production et une capture d'écran d'un autre site, puis vous les comparez et voyez s'il y a des régressions dans cet aspect visuel, n'est-ce pas ? C'est bien, oui ? D'accord, jetons un coup d'œil à cette action - oups, faites défiler - est-ce que c'est l'action ? Non, ce n'est pas l'action. Ah, voilà l'action - désolé, ce n'est pas la bonne.

Très bien, alors quelles sont les deux choses minimum dont j'ai besoin pour un test de régression visuel ? Deux - j'ai besoin d'une capture d'écran - j'ai besoin de l'URL de production - un site de production - et d'un site de test. Ici, j'ai mon nom et ma description - nous devons les avoir. J'ai des entrées - l'une est l'URL de test, alors donnez-moi une URL que vous voulez tester avec de nouveaux éléments. L'URL de référence est le site de production. Permettez-moi de faire défiler pour que vous puissiez voir ceci - j'ai les runs-using : composite et run-steps. La première est que je veux probablement m'assurer que l'URL - la chaîne qui m'a été donnée - ressemble à une URL, et je veux probablement m'assurer que le site répond. Donc, dans ce cas, je vais utiliser une action - la voilà - j'ai une action, et je vais lui envoyer l'URL de test, et tout ce que fait cette action, c'est dire, "Est-ce que cela ressemble à une URL ? Laissez-moi appeler le site et m'assurer qu'il répond". Je fais donc cela une fois avec l'URL de test, puis une fois avec l'URL de référence.

Je vais ensuite utiliser un paquetage appelé Backstop, qui est un outil de régression visuelle, et je l'installe. Dans une minute, je vais devoir modifier la configuration de Backstop pour lui donner ces nouvelles URL. Pour ce faire, j'ai besoin d'utiliser jq, une requête JSON à l'intérieur du shell, mais la version fournie avec le runner public était la 1.6, et j'ai besoin de la 1.7. Je peux donc utiliser une autre action à l'intérieur de mon action pour mettre à jour jq à l'intérieur du runner. Je mets ensuite à jour la configuration de Backstop pour inclure mes nouvelles URLs, puis je lance la référence de Backstop qui va prendre ces captures d'écran. Ensuite, je peux descendre et exécuter le test.

Que fait généralement un test en cas d'échec ? Il échoue, il y en a un, mais quoi d'autre ? Il crée un rapport, n'est-ce pas ? Il y a donc deux choses : Premièrement, il échoue - et j'ai dit plus tôt que les étapes sont toujours dépendantes les unes des autres - si l'une échoue, toutes les autres échouent. Je ne veux pas que cela se produise. Donc, dans ce cas, remarquez que j'ai mis continue-on-error : true - donccela dit, "Ne pas échouer si l'une de ces étapes échoue." Je supprime le message et je le capture - le voici - test_results=$? Ensuite, je descends et - oups, ce n'est pas à l'écran - laissez-moi descendre un peu plus bas - je définis la sortie du test lui-même dans une autre variable environnementale que je peux ensuite utiliser plus bas.

J'ai dit tout à l'heure que chaque étape était dépendante - dans ce cas, remarquez que vous avez aussi des conditions pour les étapes. Je peux dire : "N'exécutez cette étape que si cette variable d'environnement est réglée sur false." Ainsi, si le test a échoué plus tôt, je vais maintenant utiliser une autre action pour stocker le rapport et l'attacher au flux de travail d'appel, de sorte que quelqu'un qui utilise ceci dans une demande d'extraction puisse voir cet échec et réellement utiliser ou voir ce test de régression visuel. Enfin, en cas d'échec, je vais sortir avec une valeur non nulle, ce qui fait échouer l'étape dans le flux de travail d'appel, et nous ferons échouer le reste des étapes de ce travail.

Pour le voir, basculez ici - voici le flux de travail joint qui va avec. Donc maintenant je vais dire, on pull request target to main - donc s'il y a une pull request contre main, je vais l'exécuter sur la dernière version d'Ubuntu. Je vais ensuite - oh, j'ai presque oublié - l'une des grandes choses à propos de Platform et Upsun est que nous avons ces intégrations avec GitHub, et l'une des choses qu'il fait est que lorsque vous créez une demande d'extraction, il va en fait cloner votre environnement de production. Il superpose ensuite le code PR dans cet environnement et le met en ligne. Avec l'intégration, il contactera GitHub et dira : " Hey, j'ai réussi à terminer ceci - voici votre nouvelle URL d'environnement PR éphémère ". C'est ce que fait cette première action : elle dit : " Avez-vous reçu un succès, GitHub ? Oh, vous l'avez fait ? D'accord, maintenant donnez-moi cette URL ", et elle envoie une sortie appelée target_url. La deuxième étape consiste donc à exécuter l'action que je viens de vous montrer, en envoyant l'URL que nous avons obtenue grâce à la première action. Ensuite, j'ai stocké - parce que votre URL de production ne change généralement pas - j'ai stocké cela en tant que variable de dépôt dans GitHub, en la transmettant.

Pour le voir en action, permettez-moi de revenir en arrière parce que je sais que je n'ai pas beaucoup de temps. Où est ma demande d'extraction - non, c'est le contexte - la voici - voici ma demande d'extraction. Vous pouvez voir en bas, il y a cette intégration - elle a réussi - elle a rendu mon URL. J'ai d'autres tests en cours, puis le flux de travail pour la demande de téléchargement - le test de régression visuel a été exécuté, mais vous pouvez voir qu'il a échoué. Si je clique sur les détails, je vois - c'est là - que le test de régression visuelle a échoué. Ensuite, si je regarde dans le résumé - si je fais défiler - si cela me permet de faire défiler tout en bas - il y a ce rapport de test de régression visuelle stocké. Je peux maintenant jeter un coup d'œil à ce rapport et voir que j'ai eu deux réussites, deux échecs - oh bonté divine, oui, ce n'était vraiment pas bon. Oh, on dirait que la taille de la police a changé ou quelque chose comme ça - oh oui. Et maintenant je sais dans ma pull request, "Hey, quelque chose ne va pas - je dois aller vérifier ce qui s'est passé".

Merci à tous. Très bien, je pense que je n'ai plus de temps - il m'en reste peut-être deux, trois - je ne sais pas s'il me reste du temps ou non - je n'ai pas vu l'heure qu'il était. Voici mes coordonnées. Je suis assez facile à trouver - il n'y a pas beaucoup de Gilzow dans le monde. Mais le meilleur moyen de me trouver, c'est linktr.ee/gilzow : on ytrouve tous mes comptes de médias sociaux, tous, des profils partout, et je suis presque toujours "gilzow" dans tout ce que je fais. N'hésitez donc pas à me contacter - je serai également au stand le reste de la journée - et à me réjouir - j'adore parler de ces choses, et je serais heureux de répondre à toutes vos questions, maintenant ou plus tard.

Votre meilleur travail
est à l'horizon

Essai gratuit
Discord
© 2025 Platform.sh. All rights reserved.