Deploy Apps And Functions To Firebase From A Mono Repo With GitHub Actions

How to deploy applications and functions from a mono repo with GitHub Actions to Firebase Hosting and Functions

Mar 23, 2020

#devops #github #webdev #yaml

Photo by 张 嘴 on Unsplash

I share one trick a day until the end of the COVID-19 quarantine in Switzerland, April 19th 2020. Twenty-seven days left until hopefully better days.


I am a big fan of a blog post published by Julien Renaux a couple of months ago in which he displays how to deploy an application using GitHub Actions to Firebase Hosting.

The article is super comprehensive and I even already have published a following post about it once before 🤣. Nevertheless I think that this challenge is the perfect excuse to publish again another follow-up 😉.


Mono Repo

Our open source project DeckDeckGo contains many Progressive Web Apps and Cloud Functions, for which, obviously, I did set up GitHub actions as Julien displayed.

In this blog post I share the enhancement I had to implement in order to make the integration supports a mono repo.


To Firebase Hosting

Let’s say that one of your application is available in a sub-folder of our repo called docs . Basically, everything you have to do in addition to the original post is to prefix all steps of the Action with your sub-directory, respectively with docs .

Concretely, if for example we would like to trigger the action when a merge happens in the master branch, but, only if a modifications impacts our specific app, we specify a path to the Action on listener.

Listen to push to master for the all repo:

on: push: branches: - master

Listen to push to master only if sub-folder is affected:

on: push: branches: - master paths: - "docs/**"

Because the Git checkout of our pipeline happens on the root level of our repo, when it goes to installing dependencies or running a build, we do have to observe our sub-folder too. For such purpose, GitHub Action provides a handy option working-directory for the npm steps.

Run npm in the root folder:

- name: Install Dependencies run: npm ci

Run npm in a sub-directory:

- name: Install Dependencies run: npm ci working-directory: ./docs

Likewise, when it goes to artifacts, we also have to prefix the path to our bundle.

Archiving without sub-folder:

- name: Archive Artifact uses: actions/upload-artifact@master with: name: www path: www

Archiving with sub-folder:

- name: Archive Artifact uses: actions/upload-artifact@master with: name: docs path: docs/www

Finally, the Firebase Action does also provide an option to specify a project path.

Deploy to Firebase from root:

- name: Deploy to Firebase uses: w9jds/firebase-action@master with: args: deploy --only hosting env: FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}

Deploy to Firebase for a sub-directory:

- name: Deploy to Firebase uses: w9jds/firebase-action@master with: args: deploy --only hosting env: FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }} PROJECT_ID: "default" PROJECT_PATH: "./docs"

All in all, here’s the action to deploy our application for a sub-folder of our
mono repo to Firebase Hosting:

name: CI - Docs on: push: branches: - master paths: - "docs/**" jobs: build: name: Build runs-on: ubuntu-latest steps: - name: Checkout Repo uses: actions/checkout@master - name: Install Dependencies run: npm ci working-directory: ./docs - name: Build run: npm run build working-directory: ./docs - name: Archive Artifact uses: actions/upload-artifact@master with: name: docs path: docs/www deploy: name: Deploy needs: build runs-on: ubuntu-latest steps: - name: Checkout Repo uses: actions/checkout@master - name: Download Artifact uses: actions/download-artifact@master with: name: docs path: docs/www - name: Deploy to Firebase uses: w9jds/firebase-action@master with: args: deploy --only hosting env: FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }} PROJECT_ID: "default" PROJECT_PATH: "./docs"

To Firebase Cloud

In DeckDeckGo we are also taking advantages of the amazing Cloud Functions features of Firebase.

The process is basically the same as previously with that difference that you don’t have to build or even bundle anything because these steps are contained in the deployment process it self. Therefore checking out the repo, installing the dependencies and deploying is going to do the trick.

Note that again, as we have a mono repo, the following example happens in a sub-directory called cloud which contains the functions.

name: CI - Cloud on: push: branches: - master paths: - "cloud/**" jobs: deploy: name: Deploy runs-on: ubuntu-latest steps: - name: Checkout Repo uses: actions/checkout@master - name: Install Dependencies run: npm ci working-directory: ./cloud/functions - name: Deploy to Firebase uses: w9jds/firebase-action@master with: args: deploy --only functions env: FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }} PROJECT_ID: "default" PROJECT_PATH: "./cloud"

Summary

GitHub actions are awesome! Seriously, few lines, few configuration, supports mono repo, really a perfect solution for a project like ours.

That being said, notably if you are and want to use them in your company, you might be interested by another blog post published by Julien which describes some possible risks linked to versioning and dependencies.

You are also most welcomed to have a look to our open source Actions in our repo or even better, if you notice anything which can be improved in DeckDeckGo, don’t hesitate to open an issue or even better, send us a Pull Request 😃.

Stay home, stay safe!

David