Déploiement CI/CD d'un site web statique vers un bucket AWS S3 via Github Actions

Déploiement CI/CD d'un site web statique vers un bucket AWS S3 via Github Actions

par Rebeca Murillo • 18 novembre 2023


Version vidéo de cet article


Introduction

Bienvenue dans ce tutoriel où nous plongerons dans le processus de mise en place de l’intégration continue et du déploiement continu (CI/CD) pour déployer un site web statique dans un bucket Amazon S3 directement depuis notre dépôt GitHub. Nous passerons en revue le processus de configuration des actions GitHub dans notre projet, la configuration de notre compte AWS et nous assurerons que notre site web fonctionne correctement après chaque déploiement.

Cette configuration peut prende un peu de temps à mettre en place, mais elle vous fera gagner du temps par la suite ! Notre site web sera automatiquement mis à jour en un seul clic, simplement en exécutant le workflow Github sur notre branche principale.

Ce tutoriel se divise en trois étapes :

  1. Flux de travail workflow GitHub Actions
  2. Configuration du rôle AWS pour se connecter aux actions GitHub
  3. Configuration des secrets des actions GitHub et exécution du flux de travail

Prérequis

Pour suivre ce tutoriel, vous devrez préalablement configurer :

Grâce à ce guide, vous acquerrez une compréhension approfondie de la construction, de la vérification de la qualité et du déploiement de notre site web statique, et enfin de la vérification du site de production. Commençons cette excitante aventure d’automatisation du déploiement de notre site web !

Flux de travail Workflow GitHub Actions

Pour démarrer le processus, nous allons configurer les actions GitHub dans le projet.

  • Ajouter un fichier sous .github/workflows/build-deploy.yml dans le répertoire de notre projet.
  • Copier le contenu suivant, à adapter selon vos besoins.
name: Build and deploy to S3 bucket

on: workflow_dispatch

permissions:
  id-token: write
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4
      - name: Set up Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 18
      - name: Install Dependencies
        run: npm install
      - name: Build and Output to Dist
        run: npm run build
      - name: Upload Build Artifacts
        uses: actions/upload-artifact@v3
        with:
          name: build-artifacts
          path: dist

  quality:
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4
      - name: Download Build Artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-artifacts
          path: dist
      - name: Set up Python
        uses: actions/setup-python@v4
        with:
          python-version: "3.10"
      - name: Run localhost server
        run: |
          cd dist ; ls -la ;
          python -m http.server 8080 &
      - name: Wait for Local Server to Start
        run: sleep 3
      - name: Check homepage status in localhost
        run: |
          URLs=("http://localhost:8080/" "http://localhost:8080/en/" "http://localhost:8080/es/" "http://localhost:8080/fr/")
          for url in "${URLs[@]}"; do
              response_code=$(curl -w "%{http_code}" -I "$url" -o /dev/null)
              echo -e "e HTTP Status Code for $url: $response_code"
              echo "HTTP Status Code for $url: $response_code"
                
              if [ "$response_code" -ne 200 ]; then
                  echo -e "::error::Error: Unexpected status code for $url"
                  exit 1
              fi
          done

  aws_deploy:
    runs-on: ubuntu-latest
    needs: [build, quality]
    steps:
      - name: Download Build Artifacts
        uses: actions/download-artifact@v3
        with:
          name: build-artifacts
          path: dist
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
          aws-region: ${{ secrets.AWS_REGION }}
      - name: Empty S3 Bucket
        run: aws s3 rm s3://${{ secrets.AWS_S3_BUCKET }} --recursive
      - name: Upload to S3 bucket
        run: |
          ls -la dist/
          aws s3 cp dist/. s3://${{ secrets.AWS_S3_BUCKET }} --recursive
      - name: Clean CloudFront Cache
        run: aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*"

  healthcheck:
    runs-on: ubuntu-latest
    needs: aws_deploy
    steps:
      - name: Checkout Repository
        uses: actions/checkout@v4
      - name: Check homepage status @ https://mywebsite
        run: |
          URLs=("https://rebeca.murillo.link/" "https://rebeca.murillo.link/en/" "https://rebeca.murillo.link/es/" "https://rebeca.murillo.link/fr/")
          for url in "${URLs[@]}"; do
              response_code=$(curl -w "%{http_code}" -I "$url" -o /dev/null)
              echo -e "e HTTP Status Code for $url: $response_code"
              echo "HTTP Status Code for $url: $response_code"
              
              if [ "$response_code" -ne 200 ]; then
                  echo -e "::error::Error: Unexpected status code for $url"
                  exit 1
              fi
          done

Le flux de travail peut être déclenché manuellement ou vous pouvez le personnaliser pour qu’il s’exécute en fonction de conditions telles qu’une poussée de code sur la branche principale. Consultez la documentation Github Actions Events that trigger workflows pour en savoir plus.

Le flux de travail est divisé en quatre tâches différentes :

  1. Tâche de construction de code source
  2. Vérification de la qualité en local
  3. Déploiement dans le bucket S3
  4. Vérification du site de production

Examinons en détail chaque tâche.

Notez que les permissions sont obligatoires pour que aws-actions/configure-aws-credentials puisse s’authentifier !

permissions:
 id-token: write
 contents: read

1. Tâche de construction

La première étape consiste à construire la source du site web statique, en suivant la configuration et le framework de votre site web. Dans ce tutoriel, le projet est construit avec le framework Astro, nous exécutons donc un script pour installer les dépendances Node.js et ensuite construire le code source.

  • Configuration de l’environnement avec Node.js et installation des dépendances avec la commande npm install, avec Github Actions setup Node
  • Construction des sources finales du site web statique avec la commande npm run build, par défaut le framework Astro enregistre les sources construites dans le dossier dist/.
  • Le contenu du dossier de destination de la construction du code source est enregistré et transféré aux tâches suivantes du flux de travail. Nous utilisons pour cela l’action actions/upload-artifact de Github Actions.

Les tâches suivantes utiliseront l’action actions/download-artifact de Github Actions pour récupérer le contenu du dossier dist/.

2. Vérification de la qualité en local

À cette étape, vous pouvez ajouter la commande de test de votre projet, si vous en avez une. Par exemple npm run tests

La deuxième tâche consiste à effectuer une vérification de la qualité du code généré. Pour notre exemple de site web statique, la vérification de la qualité consiste à héberger le site en local et à appeler la page d’accueil par exemple.

  • Les fichiers sources du dossier dist/ de notre première tâche sont utilisés, récupérés avec l’action actions/download-artifact de Github Actions.
  • Exécution d’un serveur local avec le contenu du site web statique grâce à l’action Python setup Github Actions.
  • Vérification du bon fonctionnement de certaines pages du site web. Si l’une des pages ne répond pas correctement (code de statut 200), l’instruction exit 1 est déclenchée, ce qui provoque l’échec du flux de travail GitHub. Cela empêchera le déploiement du code source dans notre bucket S3.

3. Déploiement dans le bucket S3

Après avoir vérifié que le code source généré fonctionne correctement, la troisième tâche consiste à déployer le code source dans le bucket AWS S3.

  • Les fichiers sources du dossier dist/ de notre première tâche sont utilisés, récupérés avec l’action actions/download-artifact de Github Actions.
  • L’action AWS configure-aws-credentials permet la connexion au bucket AWS S3 via un rôle AWS. La configuration de ce rôle est expliquée dans le chapitre suivant.
  • Le bucket AWS hébergeant le site web statique est mis à jour en supprimant d’abord l’ancien contenu, puis en téléchargeant les nouveaux fichiers sources.
  • Enfin, le cache CloudFront est nettoyé, car il peut ne pas refléter immédiatement les modifications du site web.

4. Vérification du site de production

La dernière tâche répète la vérification de la qualité de la deuxième tâche, mais cette fois-ci sur l’URL finale du site. J’ai configuré cette tâche pour vérifier quatre pages, la page d’accueil dans trois langues différentes, afin de s’assurer que le site est opérationnel après le déploiement.

Dans la section suivante, nous examinerons les configurations AWS nécessaires pour cette configuration CI/CD.

Configuration du rôle AWS pour se connecter à Github Actions

Nous allons maintenant configurer notre compte AWS pour le connecter à GitHub Actions. Pour cela, nous devons créer un rôle dans AWS. Ce rôle sera utilisé pour configurer les informations d’identification dans le flux de travail GitHub Actions.

Consultez la documentation AWS pour plus de détails sur ce processus : Use IAM roles to connect GitHub Actions to actions in AWS

1. Créer un fournisseur OIDC pour GitHub

Pour commencer, nous devons créer un fournisseur d’identité pour GitHub.

  • Dans la console AWS, accédez à Identity and Access Management (IAM), sous Access Management > Identity Providers.
  • Cliquez sur “Ajouter un nouveau fournisseur” :
    • Type de fournisseur : “Fournisseur Open ID Connect”
    • URL du fournisseur : token.actions.githubusercontent.com
    • Audience : sts.amazonaws.com

Une fois notre fournisseur d’identité établi, nous pouvons passer à la création du rôle.

2. Créer le rôle AWS

  • Dans la console AWS, accédez à Identity and Access Management (IAM), sous Access Management > “Rôles”.
  • Cliquez sur “Créer un nouveau rôle” :
    • Type d’entité : Identité Web.
    • Sélectionnez le fournisseur d’identité que nous avons créé à l’étape précédente. L’audience sera celle par défaut.
    • L’organisation GitHub est essentiellement votre compte GitHub où le projet est hébergé.
    • Le nom de votre dépôt GitHub.
    • La branche de votre dépôt GitHub qui sera autorisée à exécuter le flux de travail GitHub Actions.
  • Dans l’étape des stratégies d’autorisations, configurez les règles en fonction des actions qui seront exécutées par le flux de travail GitHub Actions. Pour ce tutoriel, les autorisations requises sont :
    • Gestion du bucket AWS S3 : pour supprimer et télécharger du contenu dans le bucket.
    • Gestion de CloudFront AWS : pour réinitialiser le cache CDN.
  • Enregistrez le nouveau rôle.

Dans la politique de confiance, vous pouvez vérifier des informations importantes concernant les autorisations de votre dépôt GitHub et la branche concernée. Vous pouvez adapter cela à votre cas d’utilisation. Après avoir créé le rôle, ouvrez-le pour copier l’ARN (Amazon Resource Name), qui sera nécessaire à l’étape suivante pour configurer les secrets dans GitHub.

Configuration des secrets GitHub Actions et exécution du flux de travail

Dans votre projet GitHub, configurez les secrets requis pour le flux de travail.

  1. Accédez aux paramètres de votre projet GitHub,
  2. Puis à “Secrets et variables” sous “Actions”,
  3. Enfin, créez un secret pour chaque variable avec “Créer un nouveau secret de dépôt”. Dans ce tutoriel, les secrets utilisés dans le flux de travail comprennent :
    • AWS_ROLE_ARN : l’ARN du rôle AWS créé à l’étape précédente.
    • AWS_REGION : la région AWS pour le bucket.
    • AWS_S3_BUCKET : le nom du bucket AWS S3.
    • AWS_CLOUDFRONT_DISTRIBUTION_ID : l’ID de distribution AWS CloudFront.

Avec toutes ces configurations en place, votre compte AWS est maintenant configuré et prêt à être connecté à GitHub Actions.

Pour exécuter le flux de travail, accédez à l’onglet “Actions” dans le dépôt GitHub, sélectionnez le flux de travail et exécutez-le à partir de la branche correspondante.

Une fois le flux de travail lancé, vous pouvez suivre sa progression. Il exécutera séquentiellement les quatre tâches que nous avons décrites précédemment : construction, vérification de la qualité en local, déploiement dans le bucket S3 et vérification du site de production.

Notez que choisir la mauvaise branche entraînera des erreurs dans le flux de travail. La branche doit être autorisée dans les stratégies de rôle AWS.

J’espère que ce tutoriel vous donne une compréhension claire de la façon dont le rôle AWS et GitHub Actions fonctionnent ensemble pour assurer des déploiements sécurisés et contrôlés de votre site web. Le processus est maintenant entièrement automatisé et les autorisations sont configurées pour empêcher les déploiements non autorisés, garantissant ainsi que votre site web reste sécurisé et à jour en un seul clic !