Intro

Dans l’épisode précédent, nous avons codé l’intégralité de notre CDN. Nous l’avons ensuite lancé en local avec un object storage Minio pour s’assurer de son bon fonctionnement.

Aujourd’hui c’est le grand jour, nous allons quitter le monde du local et envoyer notre application dans les nuages ☁️.

Notre application est développée en Rust et je souhaite la déployer sur du cloud français.

Le choix de l’hébergeur est dans le titre de l’article, nous allons utiliser Clever Cloud !

Clever Cloud fourni du Platform as a Service (PaaS) basé en Europe.

Leur solution est simple : vous fournissez le code et ils se chargent de le faire tourner sur leurs infras tout en garantissant la scalabilité, la disponibilité et la sécurité de façon transparente et automatisée pour les clients.

Reprenons notre application Rust, cela veut dire pour faire simple que nous avons seulement à fournir le code source et qu’ils se chargent de la compilation et du déploiement. Plus d’infra à gérer, je push juste mon code.

Mais tout d’abord, commençons par préparer la CI de notre projet.

Mise en place de la CI à l’aide de Gitlab CI

L’intégration continue (CI) est une pratique de développement logiciel consistant à automatiser l’intégration des modifications de code, permettant ainsi une détection rapide des erreurs et une livraison plus fiable des applications.

Dans notre cas, le projet est hébergé sur Gitlab, nous allons donc implémenter la CI à l’aide de Gitlab CI.

Gitlab détecte automatique le fichier .gitlab-ci.yml dans le projet. Si celui-ci est présent, la CI sera automatiquement exécutée.

Pour cet article, notre pipeline de CI contiendra les actions suivantes :

  • Exécution du linter pour vérifier la qualité du code
  • Exécution des tests pour s’assurer que les commits n’introduisent pas de régressions (dans un monde idéal, dans la réalité, cela dépend de la qualité des tests et de la couverture du projet.)

Voici à quoi ressemble le fichier .gitlab-ci.yml de notre projet :

image: rust:1.76-buster
stages:
  - test

test:
  stage: test
  rules:
    - if: $CI_COMMIT_TAG == null
  script:
    - cargo test

lint:
  stage: test
  rules:
    - if: $CI_COMMIT_TAG == null
  before_script:
    - rustup component add clippy
  script:
    - cargo clippy

Avec cette configuration, le linting et les tests seront exécutés à chaque commit push sur le projet.

Création de l’application sur Clever Cloud

Installation de la CLI

Pour créer notre application sur Clever Cloud, nous allons utiliser la CLI fournie. Pour cela, nous allons suivre la documentation disponible ici : https://developers.clever-cloud.com/doc/cli/getting_started/.

❯ npm install -g clever-tools

Authentification et récupération des secrets

La CLI nécessite d’être authentifiée pour exécuter des actions. Pour cela, nous utilisons la commande clever login.

❯ clever login
Opening https://console.clever-cloud.com/cli-oauth?cli_version=3.4.0&cli_token=xxxxx in your browser to log you in…
Login successful as User <yourmail@provider.xyz>

Cette commande va ouvrir votre navigateur par défaut avec la mire de connexion.

clever login

Et une fois connecté, nous pouvons récupérer des secrets, mettez-les de côté, nous allons en avoir besoin d’ici peu !

clever secrets

Création de l’application

Tout est prêt maintenant pour créer notre application via la CLI.

Nous allons utiliser la commande clever create :

clever create --type rust gimme-demo --region par

💡 le paramètre --region est optionnel, il prendra par comme valeur par défaut

Si tout se passe bien, vous devez obtenir le résultat suivant :

Application created successfully!
ID: <your app id>
Name: gimme-demo

Vous devez également voir l’application créée depuis la console Clever https://console.clever-cloud.com :

clever created

Avant de push le code du projet, nous allons créer l’addon Cellar étant donné que nous avons besoin d’un object storage.

Cette fois c’est la commande clever addon create que nous allons utiliser :

clever addon create cellar-addon --plan S gimme-store --link gimme-demo

💡 le paramètre --link permet de lier l’addon à notre application

Si tout se passe bien, vous devez obtenir le résultat suivant :

Add-on created and linked to application gimme-demo successfully!
ID: addon_<id>
Real ID: cellar_<id>
Name: gimme-store

Encore une fois, l’addon doit également être visible depuis la console.

Création des variables d’environnements

Dernière étape avant de procéder au déploiement, nous allons devoir créer quelques variables d’environnements sur notre application gimme-demo.

Les variables d’environnements s’ajoutent via la commande clever env set.

Et voici la création de nos variables :

➜  ~ clever env set BUCKET gimme
Your environment variable has been successfully saved
➜  ~ clever env set REGION us-west-1
Your environment variable has been successfully saved
➜  ~ clever env set ENDPOINT cellar-c2.services.clever-cloud.com
Your environment variable has been successfully saved
➜  ~ clever env set ACCESS_KEY <access_key>
Your environment variable has been successfully saved
➜  ~ clever env set SECRET_KEY <secret_key>
Your environment variable has been successfully saved

Nous pouvons vérifier la présence des variables à l’aide la commande clever env :

➜  ~ clever env
# Manually set env variables
ACCESS_KEY="<access_key>"
BUCKET="gimme"
CC_CACHE_DEPENDENCIES="true"
ENDPOINT="cellar-c2.services.clever-cloud.com"
REGION="us-west-1"
SECRET_KEY="secret_key"
# Addon gimme-store
CELLAR_ADDON_HOST="cellar-c2.services.clever-cloud.com"
CELLAR_ADDON_KEY_ID="<access_key>"
CELLAR_ADDON_KEY_SECRET="secret_key"

💡 La valeur de la clé REGION importe peu car l’addon Cellar ne l’utilise pas.

Tout est prêt pour le déploiement.

Déploiement

Sûrement l’étape la plus simple de notre aventure, car elle se résume à une simple commande :

clever deploy

Tout ayant été paramétré durant les étapes précédentes, on donne notre code source Rust et on laisse Clever bosser !

➜  gimme-article git:(master) clever deploy
Remote application is app_id=app_<app_id>, alias=gimme-demo, name=gimme-demo
Remote application belongs to user_<user_id>
App is brand new, no commits on remote yet
New local commit to push is 9a6a98f57e02d153591ab6f643ef8540ac278c3b (from refs/heads/master)
Pushing source code to Clever Cloud…
Your source code has been pushed to Clever Cloud.
Waiting for deployment to start…
Deployment started (deployment_xxxxx)
Waiting for application logs…

Comme mentionné pendant l’intro, l’application est bien déployée en partant des sources. Une première étape consiste à compiler le code Rust pour produire le binaire. Binaire déployé sur notre application une fois prêt.

💡 Clever possède un système de cache sur la compilation qui permet de gagner du temps sur les compilations suivantes. Mes compilations suivantes de l’application ont été bien plus rapides.

Si tout a bien fonctionné, vous devez voir votre application en ligne depuis la console.

2024-03-06T21:52:28.743Z: Done uploading dependencies cache archive
2024-03-06T21:52:28.745Z: Creating build cache archive
2024-03-06T21:52:37.442Z: build cache archive successfully created
2024-03-06T21:52:40.641Z: Begin
2024-03-06T21:52:40.643Z: Starting the application…
2024-03-06T21:52:42.861Z: Application start successful
2024-03-06T21:52:42.861Z: No cron to setup
2024-03-06T21:52:43.407Z: Successfully deployed in 8 minutes and 49 seconds

clever end

La CI c’est bien, la CD c’est encore mieux !

Étant donné que Clever fourni une image docker de sa CLI, la partie déploiement continu va être très simple.

Tout d’abord nous allons configurer quelques variables accessibles par nos pipelines depuis l’interface du projet Gitlab.

Pour cela, nous allons nous rendre dans la partie Settings > CI/CD > Variables du projet.

Les variables à créer sont les suivantes :

  • APP_ID : l’identifiant de l’application Clever
  • CLEVER_TOKEN : token fourni au moment du login via la CLI
  • CLEVER_SECRET : secret fourni au moment du login via la CLI

L’identifiant de l’application se trouve en haut à droite sur la vue d’ensemble de l’application :

clever appid

Et voici les variables créées dans Gitlab :

gitlab cd variables

Une fois ces variables configurées, nous pouvons mettre à jour le fichier .gitlab-ci.yml avec un nouveau job.

Ce job aura la charge de déployer l’application sur Clever lorsqu’un commit arrive sur la branche principale du projet.

Voici le fichier à jour :

image: rust:1.76-buster

stages:
  - test
  - deploy

test:
  stage: test
  rules:
    - if: $CI_COMMIT_TAG == null
  script:
    - cargo test

lint:
  stage: test
  rules:
    - if: $CI_COMMIT_TAG == null
  before_script:
    - rustup component add clippy
  script:
    - cargo clippy

deploy:
  stage: deploy
  image: 
    name: clevercloud/clever-tools:latest
    entrypoint: ["/bin/sh", "-c"]
  rules:
    - if: $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH
  script:
    - clever link $APP_ID
    - clever deploy

Notre déploiement est maintenant automatisé 🎉.

Une petite démonstration pour finir ?

💡 Partons du principe que nous avons déjà upload un package comme montré dans l’article précédent.

Comme la dernière fois, nous allons utiliser la librairie de web-components développée par mes collègues de MGDIS (lien vers le storybook du projet).

Créons une page qui utilise les mg-components via notre CDN comme ceci :

<!DOCTYPE html>
<html>

<head>
  <meta charset='utf-8'>
  <meta http-equiv='X-UA-Compatible' content='IE=edge'>
  <title>CDN Demo</title>
  <meta name='viewport' content='width=device-width, initial-scale=1'>
  <link rel="stylesheet"
    href="https://myapp.cleverapps.io/gimme/mg-components@5.24.0/mg-components/mg-components.css" />
  <script type="module"
    src="https://myapp.cleverapps.io/gimme/mg-components@5.24.0/mg-components/mg-components.esm.js"></script>
  <link rel="stylesheet" href="/assets/app.css">
  <script src="/assets/app.js" defer></script>
</head>

<body>
  <mg-form identifier="demo-form">
    <mg-input-checkbox identifier="mgic-demo" label="Checkbox"></mg-input-checkbox>
    <mg-input-date required=" true" identifier="mgid-demo" label="Date"></mg-input-date>
    <mg-input-numeric identifier="mgin-demo" label="Numeric"></mg-input-numeric>
    <mg-input-password identifier="mgip-demo" label="Password"></mg-input-password>
    <mg-input-text identifier="mg-input-text" label="Text"></mg-input-text>
    <mg-input-textarea identifier="mg-input-textarea" label="Text area"></mg-input-textarea>
    <div slot="actions" class="mg-group-elements mg-group-elements--align-right">
      <mg-button id="can-submit">Submit</mg-button>
      <mg-button id="errors" variant="secondary" type="button">Display errors</mg-button>
    </div>
  </mg-form>
</body>

</html>

Dans cet exemple, nous chargeons deux fichiers depuis notre CDN déployé :

Et voici le rendu de notre page de démonstration :

cdn demo result

Conclusion

Notre voyage au cœur du CDN est désormais terminé.

Au fil de cette série d’articles, nous avons pu aborder différents sujets qui jalonnent le cycle de vie de la création d’une application.

Un CDN fait maison et déployé sur du cloud français, est-ce qu’on ne tiendrait pas un concept de CDN souverain ? 😁

Ce format épisodique était une nouveauté pour moi et j’espère que vous avez pu y découvrir des choses.

Sur ce, je vous dis à la prochaine avec un nouveau sujet !