Pourquoi CI/CD pour React avec GitHub Actions ?
Le développement continu (CI) et la livraison continue (CD) sont des pratiques essentielles dans les équipes de développement modernes, y compris celles travaillant sur des projets React. Ces pratiques automatisent le processus de construction, de test et de déploiement du code, permettant aux développeurs de livrer plus rapidement et avec une meilleure qualité.
Un cas d'usage concret est la mise à jour automatique d'une application web sur un serveur de production après chaque modification du code. Grâce au CI/CD, cette tâche peut être effectuée en quelques minutes, réduisant ainsi le temps entre les modifications et leur disponibilité aux utilisateurs.
Prerequis
Pour suivre ce tutoriel, vous aurez besoin des éléments suivants :
- Un compte GitHub
- Node.js (version recommandée : 14.x ou supérieure)
- npm (Node Package Manager) (version recommandée : 6.x ou supérieure)
- Git (version recommandée : 2.35.0 ou supérieure)
Concepts fondamentaux
Pipeline de CI/CD
Un pipeline est une séquence d'étapes automatisées qui permettent de construire, tester et déployer le code source. Voici un schema mental clair :
Code Source -> Dépôt (GitHub) -> Vérification des Tests -> Construction -> Déploiement
Workflow GitHub Actions
Un workflow est une séquence d'étapes définies dans un fichier YAML et exécutée par GitHub Actions. Chaque étape peut être personnalisée pour effectuer diverses tâches.
Voici un exemple de workflow simple :
## .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Build project
run: npm run build
- name: Deploy to server
run: scp -r dist user@example.com:/path/to/server
Déploiement sur un serveur distant
Pour déployer votre application React sur un serveur distant, vous pouvez utiliser des commandes SSH et SCP (Secure Copy Protocol). Voici un exemple de workflow qui déploie l'application sur un serveur :
## .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Build project
run: npm run build
- name: Deploy to server
run: |
scp -r dist user@example.com:/path/to/server
Mise en pratique : projet fil rouge
Projet : Gestionnaire de tâches
Nous allons créer un simple gestionnaire de tâches React avec les fonctionnalités suivantes :
- Ajouter une nouvelle tâche
- Marquer une tâche comme terminée
- Supprimer une tâche
Étape 1 : Initialisation du projet
npx create-react-app task-manager
cd task-manager
Étape 2 : Création des composants
Créons les composants TaskList, AddTask, et TaskItem dans le fichier src/App.js.
// src/App.js
import React, { useState } from 'react';
import './App.css';
function App() {
const [tasks, setTasks] = useState([]);
const [newTask, setNewTask] = useState('');
const handleAddTask = () => {
if (newTask.trim() !== '') {
setTasks([...tasks, { text: newTask, completed: false }]);
setNewTask('');
}
};
const handleToggleComplete = (index) => {
const updatedTasks = [...tasks];
updatedTasks[index].completed = !updatedTasks[index].completed;
setTasks(updatedTasks);
};
const handleDeleteTask = (index) => {
const updatedTasks = tasks.filter((_, i) => i !== index);
setTasks(updatedTasks);
};
return (
<div className="App">
<h1>Task Manager</h1>
<input
type="text"
value={newTask}
onChange={(e) => setNewTask(e.target.value)}
placeholder="Add a new task..."
/>
<button onClick={handleAddTask}>Add Task</button>
<ul>
{tasks.map((task, index) => (
<li key={index}>
<span
style=textDecoration: task.completed ? 'line-through' : 'none'
onClick={() => handleToggleComplete(index)}
>
{task.text}
</span>
<button onClick={() => handleDeleteTask(index)}>Delete</button>
</li>
))}
</ul>
</div>
);
}
export default App;
Étape 3 : Configuration du workflow GitHub Actions
Créez un fichier .github/workflows/ci-cd.yml avec le contenu suivant :
## .github/workflows/ci-cd.yml
name: CI/CD Pipeline
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Run tests
run: npm test
deploy:
needs: build
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v2
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: '14'
- name: Install dependencies
run: npm install
- name: Build project
run: npm run build
- name: Deploy to server
run: |
scp -r dist user@example.com:/path/to/server
Étape 4 : Déploiement sur un serveur distant
Assurez-vous que vous avez configuré les droits SSH pour accéder au serveur distant. Vous pouvez utiliser l'outil ssh-keygen pour générer une paire de clés SSH et l'ajouter à votre compte GitHub.
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
Ajoutez la clé publique (~/.ssh/id_rsa.pub) à vos paramètres d'accès SSH sur GitHub.
Erreurs frequentes et debugging
Erreur 1 : npm install échoue avec un message d'erreur
npm ERR! code ERESOLVE
npm ERR! ERESOLVE unable to resolve dependency tree
Cause : Les dépendances du projet ne sont pas correctement spécifiées.
Correction :
## Corriger les dépendances dans package.json
npm install --save react react-dom
Erreur 2 : npm test échoue avec un message d'erreur
FAIL: No tests found.
Cause : Aucun fichier de test n'est trouvé.
Correction :
Créez un fichier src/App.test.js pour tester les composants du gestionnaire de tâches.
// src/App.test.js
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import App from './App';
test('renders app with task list', () => {
const { getByText, getByPlaceholderText, getByRole } = render(<App />);
const inputElement = getByPlaceholderText(/add a new task/i);
fireEvent.change(inputElement, { target: { value: 'New Task' } });
const buttonElement = getByRole('button', { name: /add task/i });
fireEvent.click(buttonElement);
expect(getByText(/new task/i)).toBeInTheDocument();
});
Erreur 3 : scp échoue avec un message d'erreur
Permission denied (publickey).
Cause : Les droits SSH pour accéder au serveur distant ne sont pas correctement configurés.
Correction :
Assurez-vous que vous avez ajouté la clé publique à vos paramètres d'accès SSH sur GitHub et que les permissions sur le serveur distant sont correctes. Vous pouvez utiliser l'outil ssh-copy-id pour copier la clé publique sur le serveur.
ssh-copy-id user@example.com
Pour aller plus loin
1. Utilisation de Docker pour le déploiement
Vous pouvez utiliser Docker pour empaqueter votre application React et la déployer sur un serveur distant.
2. Configuration de l'authentification SSH via secrets GitHub Actions
Vous pouvez configurer les variables d'environnement dans GitHub Actions pour éviter d'exposer vos informations d'identification SSH dans le code source.
Documentation Secrets GitHub Actions
3. Utilisation de CircleCI pour un pipeline plus avancé
CircleCI est une alternative populaire à GitHub Actions, offrant des fonctionnalités plus avancées et des capacités de configuration plus flexibles.
Défi pratique : Ajout d'un système de notifications
Ajoutez un système de notifications pour informer les utilisateurs lorsque une nouvelle tâche est ajoutée ou supprimée. Vous pouvez utiliser des bibliothèques comme react-toastify pour afficher des notifications en temps réel.
npm install react-toastify
Utilisez ensuite react-toastify dans votre composant App.js pour afficher les notifications.
// src/App.js
import React, { useState } from 'react';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
function App() {
// Code existant...
const handleAddTask = () => {
if (newTask.trim() !== '') {
setTasks([...tasks, { text: newTask, completed: false }]);
setNewTask('');
toast.success('New task added!');
}
};
const handleDeleteTask = (index) => {
const updatedTasks = tasks.filter((_, i) => i !== index);
setTasks(updatedTasks);
toast.error('Task deleted!');
};
return (
<div className="App">
{/* Code existant... */}
<ToastContainer />
</div>
);
}
export default App;
Ce tutoriel vous a permis de comprendre les concepts fondamentaux du CI/CD avec GitHub Actions et d'appliquer ces pratiques à un projet React réaliste. Vous pouvez maintenant automatiser le processus de construction, de test et de déploiement de vos projets React, ce qui permettra de livrer plus rapidement et avec une meilleure qualité.