Environnements et intégration continue : NuxtJS & Firebase (Partie 3)

Bien le bonjour !

Justement je pensais à vous en me disant : mais je ne vais quand même pas les laisser avec le gâteau prêt à être mangé sans ajouter les fruits et la crème. Il est midi, j’ai faim.

Vous l’aurez compris, si vous êtes là c’est que vous avez suivi (et je vous en remercie) au moins mon tutoriel vous expliquant comment installer une application SSR Nuxt sous Firebase. Et si vous avez été attentifs j’ai, lors de ce tutoriel, supprimé le répertoire .git afin de nous débarrasser de la trace des versions de fichiers.

Je vais maintenant vous proposer de remettre en place la gestion des sources ainsi que de l’intégration continue sous Gitlab et ce avec deux environnements : développement et production.

Si vous n’êtes pas encore familiarisés, je vous redirige vers cet article qui explique de manière simple et concise l’intérêt de mettre en place plusieurs environnements, leurs rôles et leurs spécificités.

Cela étant dit, allons-y !

 

Pré-requis

Ce tutoriel est la continuité du dernier. Je me baserai donc sur l’application obtenue à la fin de la partie 2.

Vous allez avoir besoin de Git.

Il vous faudra un compte Gitlab. Bien évidemment il est possible d’utiliser le CI/CD de votre choix mais il vous faudra adapter les instructions que je fournirai au système pour lequel vous opterez.

Il vous faudra avoir créé deux projets Firebase et récupérer leur ID pour les écrire dans le fichier .firebaserc. L’un sera dédié au developpement, l’autre à la production.

 

Création du projet Gitlab

Juste créer un projet Gitlab portant le nom de votre application.

 

Initialisation

Je vous invite de vous rendre à la racine du projet nuxt-on-firebase/ et à lancer la commande suivante qui initialisera le traçage git :

git init

Sous VS Code vous devriez voir apparaitre la surbrillance verte propre à la detection de modifications dans le projet.

Vous êtes à présent sous la branche principale master.

Décidément pour le moment c’est pas la folie. On y vient on y vient.

Maintenant on va envoyer tout ce beau monde sous votre projet gitlab :

## Association au répertoire distant
git remote add origin <lien de votre projet gitlab>
## Ajout de tout le répertoire local
git add .
## Création du commit
git commit -m "Commit initial, le SSR est en place"
## Et du coup on envoie tout sur le répertoire distant
git push -u origin master

Et si vous allez sur votre projet, pouf il y a vos sources.

 

Récupération du token firebase

Vous avez du remarquer que pour déployer une application sous Firehost il nous faut l’associer à un projet sous la console. Souvenez vous :) Pour cela nous nous connections à Firebase via un firebase login qui nous ouvrait un onglet de navigateur avec une interface bien pratique. Une fois la partie interface passée, hop on était loggués.

La question se pose maintenant : comment faire pour de l’intégration continue ?

Une fois le déploiement lancé dans le pipeline, l’ouverture d’une page web est impossible. Firebase a pensé à tout, nous allons utiliser un token de connexion généré ainsi :

firebase login:ci

Cette commande va vous donner un token de connexion que vous irez appliquer dans gitlab dans les variables d’environnement du repository.

Settings > CI/CD > Variables.

 

Le Fichier .gitlab-ci.yml

Pour commencer je vous invite à regarde un peu la documentation de Gitlab si vous n’êtes pas familiés de ce type de fichier.

Maintenant on va écrire le script de déploiement. Le fichier Yaml par défaut lu par gitlab lors d’un commit est le fichier .gitlab-ci.yml.

Créons le à la racine :

touch .gitlab-ci.yml

 

Et voici ce que l’on trouvera dedans :

image: andreysenov/firebase-tools

stages:
  - build
  - deploy

build:
  environment: test
  stage: build
  script:
    - npm run setup
    - npm run build
  except:
    - master

deploy-dev:
  environment: test
  stage: deploy
  only: 
    - master
  script:
    - npm run setup
    - firebase use develop --token $FIREBASE_TOKEN
    - firebase deploy -m "Deploying to test environment" --token $FIREBASE_TOKEN

deploy-prod:
  environment: production
  stage: deploy
  only: 
    - tags
  script:
    - npm run setup
    - firebase use production --token $FIREBASE_TOKEN
    - firebase deploy -m "Deploying to production environment" --token $FIREBASE_TOKEN

Nous utilisons déjà une image firebase afin d’avoir les commandes Firebase et Node de base.

  • Nous avons donc un job build qui s’éxécutera à chaque fois que vous pusherez quelque chose sur le repository Gitlab tant qu’il ne s’agit pas de la branche master.

  • Le job deploy-dev s’éxécutera lorsque vous mergerez vos travaux sur la branche master. Cela déclenchera donc un déploiement en environnement de développement.

  • Enfin, le job deploy-prod s’éxécutera au tag de la branche master. Cela vous permettra de gérer vos releases de production efficacement.

Dans chacun des scripts je dis à firebase d’utiliser l’ID du projet Firebase indiqué pour le développement ou la production. Ainsi il vous suffira de créer un autre projet Firebase via la Firebase Console et de modifier le fichier .firebaserc avec les ID des projets vous servant d’environnement de dev ou de prod. De cette manière, il est possible d’ajouter une multitude d’environnements.

L’authentification firebase s’effectue via l’option --token à laquelle on attribue la variable d’environnement Gitlab $FIREBASE_TOKEN mise en place plus haut.

Allez, on commit tout ça :

## Ici on est sous le master
git checkout -b continuous-integration
git add .gitlab-ci.yml
git commit -m "ajout du fichier de déploiement"
git push --set-upstream origin continuous-integration

Il ne nous reste plus qu’à merge cette branche dans le master depuis gitlab.

Suite à cela, Gitlab lance un déploiement du master. Vous pouvez alors tagger le master. Le déploiement se fera sous le projet firebase lié à l’environnement de production.

Tout va bien dans le meilleur des mondes ! Vous avez mis en place de l’intégration continue ! Bravo.

Maintenant d’autres petites questions vont se poser.

 

Gestion des environnements

Ne vous rejouissez pas trop vite, Nuxt a tout de même ses petites manignances derrière notre dos.

Reprenons, nous sommes d’accord que si vous souhaitez une application tournant en dev et une en production il va vous falloir deux projets Firebase.

Il est à noter qu’il est tout de même possible sous Firebase d’avoir plusieurs applications sous un même projet. Elle partageront les ressources et auront chacunes leurs statistiques propres. Ce cas peut vous interesser mais ce n’est pas celui que je choisis ici car si on souhaite par la suite avoir une base de données Firestore par environnement, on aura besoin de deux projets distincts.

Bref qui dit deux projets dit deux configurations d’API différentes. Il nous faut donc tester si nous sommes en developpement ou en production.

Toi, au fond je t’ai entendu avec ton : "Nan mais il suffit d’utiliser NODE_ENV et voilà"

Eh non… Nuxt est, comme je vous le disais, un petit malin. La commande nuxt build lancée lors de notre npm run build écrase automatiquement NODE_ENV par “production”.

Donc il faut ruser. Et là je retrouve mon nuxtichou d’amour avec la propriété env dans le fichier nuxt.config.js.

Tout simplement on va définir des variables d’environnement au build que l’on pourra par la suite réutiliser à notre guise.

Il va donc nous falloir créer une propriété indiquant l’environnement courant qui nous servira pour gérer des comportements différents de l’application en fonction de son environnement d’éxécution. Nous allons également créer les variables nécessaires à la configuration de l’API Firebase.

Et pour les récupérer on attribue donc la fameuse propriété env dans le fichier nuxt.config.js :

env: {
    app_env: process.env.APP_ENV,
    FIREBASE_API_KEY: process.env.FIREBASE_API_KEY,
    FIREBASE_DATABASE_NAME: process.env.FIREBASE_DATABASE_NAME,
    FIREBASE_PROJECT_ID: process.env.FIREBASE_PROJECT_ID,
    FIREBASE_SENDER_ID: process.env.FIREBASE_SENDER_ID
},

La question qui se pose maintenant c’est comment récupérer tout cela au build dépendament de l’environnement sachant que l’on doit considérer le démarrage en local ?

Je répondrai par : Dotenv + Gitlab !

Dotenv

Afin de gérer des variables d’environnement en local nous allons utiliser dotenv et plus spécifiquement le module fait pour Nuxt. Il s’agit d’un module permettant de charger les variables d’environnement du fichier .env directement dans l’application. Cette attribution s’effectue au build de Nuxt.

## Ici nous sommes sous /src dans notre application. 
## En effet on souhaite installer cette dépendance pour l'application Nuxt uniquement.
npm install @nuxtjs/dotenv

Il nous faudra ensuite aller dans le fichier nuxt.config.js et y rajouter le module dotenv :

buildModules: [
    '@nuxtjs/dotenv'
  ],

Parlons maintenant de ce fameux fichier .env. Avant de créer le fichier, bien s’assurer qu’il est présent dans votre .gitignore. On n’en veut pas dans la gestion de sources.

## Sous src toujours
touch .env

Dans le fichier vous y mettrez vos variables d’environnement comme suis:

APP_ENV=develop
FIREBASE_API_KEY=votre_api_key_Firebase
FIREBASE_DATABASE_NAME=votre_database_name_Firebase
FIREBASE_PROJECT_ID=votre_project_id_Firebase
FIREBASE_SENDER_ID=votre_sender_id_Firebase

J’ai jamais autant écrit Firebase de ma vie. Firebase.

Bien pour le local c’est bon. Vos variables d’environnment sont attribuées. Le fichier .env n’est pas tracé et donc il faut trouver un autre moyen de les attribuer lorsque l’on déploie l’application.

Gitlab

Ce qu’il y a de bien avec le Gitlab CI c’est que l’on peut lui spécifier dans ses jobs des constantes utilisables au moment du build de l’application. Donc ce code FIREBASE_API_KEY: process.env.FIREBASE_API_KEY (voir plus haut) fonctionnera autant en local qu’au déploiement en dev ou prod.

Donc déjà il faut ajouter les variables sous Settings > CI/CD > Variables.

On ajoute donc ces 8 variables :

  • FIREBASE_API_KEY_DEV
  • FIREBASE_DATABASE_NAME_DEV
  • FIREBASE_PROJECT_ID_DEV
  • FIREBASE_SENDER_ID_DEV
  • FIREBASE_API_KEY_PROD
  • FIREBASE_DATABASE_NAME_PROD
  • FIREBASE_PROJECT_ID_PROD
  • FIREBASE_SENDER_ID_PROD

Je vous laisse attribuer les bonnes valeurs avec celles de vos projets Firebase.

Vous pouvez modifier votre fichier .gitlab-ci.yml qui ressemblera à ceci :

image: andreysenov/firebase-tools

stages:
  - build
  - deploy

build:
  environment: test
  stage: build
  script:
    - npm run setup
    - npm run build:dev
  except:
    - master

deploy-dev:
  environment: test
  stage: deploy
  only: 
    - master
  variables:
    APP_ENV: $APP_ENV_DEV
    FIREBASE_API_KEY: $FIREBASE_API_KEY_DEV
    FIREBASE_DATABASE_NAME: $FIREBASE_DATABASE_NAME_DEV
    FIREBASE_PROJECT_ID: $FIREBASE_PROJECT_ID_DEV
    FIREBASE_SENDER_ID: $FIREBASE_SENDER_ID_DEV
  script:
    - npm run setup
    - firebase use develop --token $FIREBASE_TOKEN
    - firebase deploy -m "Deploying to test environment" --token $FIREBASE_TOKEN

deploy-prod:
  environment: production
  stage: deploy
  only: 
    - tags
  variables: 
    APP_ENV: $APP_ENV_PROD
    FIREBASE_API_KEY: $FIREBASE_API_KEY_PROD
    FIREBASE_DATABASE_NAME: $FIREBASE_DATABASE_NAME_PROD
    FIREBASE_PROJECT_ID: $FIREBASE_PROJECT_ID_PROD
    FIREBASE_SENDER_ID: $FIREBASE_SENDER_ID_PROD
  script:
    - npm run setup
    - firebase use production --token $FIREBASE_TOKEN
    - firebase deploy -m "Deploying to production environment" --token $FIREBASE_TOKEN

On notera bien les propriétés variables qui ont été rajoutées avec les clefs précédemment configurées sous Gitlab.

Pour le déploiement, tout est en place.

 

Le plugin d’initialisation Firebase

Cet article commence à être vraiment long. C’est le dernier chapitre (promis).

Maintenant que vous disposez de vos projets firebase de dev et de prod et de vos variables d’environnement spécifiques on peut mettre en place ce qu’il faut pour pouvoir utiliser firebase au sein de l’application.

Dans le répertoire plugins de Nuxt, on va créer un fichier nommé fireapp.js

cd src/plugins && touch fireapp.js

## On va avoir besoin du package firebase
## Ne pas oublier de retourner sous src
cd .. && npm install firebase

Dans ce fichier, on trouvera donc :

import firebase from 'firebase'

if(!firebase.apps.length) {

    //On utilise nos fameuses variables d'environnement
    const config = {
        apiKey: process.env.FIREBASE_API_KEY,
        authDomain: `${process.env.FIREBASE_PROJECT_ID}.firebaseapp.com`,
        databaseURL: `https://${process.env.FIREBASE_DATABASE_NAME}.firebaseio.com`,
        projectId: process.env.FIREBASE_PROJECT_ID,
        storageBucket: `${process.env.FIREBASE_PROJECT_ID}.appspot.com`,
        messagingSenderId: process.env.FIREBASE_SENDER_ID
    }
    //Initialisation de firebase
    firebase.initializeApp(config)
}

// On stocke les instances
const firebaseApp = firebase.app()
const fireDb = firebase.firestore()

//Et on les rends disponible à qui en aura besoin dans l'application
export { firebaseApp }
export { fireDb }

N’oubliez pas d’ajouter le fichier aux plugins Nuxt dans le fichier nuxt.config.js.

 

Conclusion

Et voilà !

Nous avons mis en place de l’intégration continue pour notre application ainsi que la disponilité de l’API Firebase (application et base de données en temps réel) pour deux environnements d’éxécution.

Si jamais vous avez besoin d’idées pour la gestion utilisateur FireAuth ou la mise en place d’une base de données Firebase (avec son ORM Firestorm), cela me fera plaisir de vous présenter différentes solutions relatives à ces sujets. N’hésitez donc pas à revenir vers moi.

Je vous remercie d’avoir suivi ce tutoriel et vous dis à très bientot.

Happy coding !

Bien à vous,

Pophip.

Rémi Perreira

Consultant en développement