How to Set Up a Gitlab CI/CD pipeline to deploy a Next.js App to Firebase


A definitive guide to setting up GitLab CI/CD pipeline for deploying a Next.js App to Firebase Hosting
Posted On: Saturday, 11-May-2024
How to Set Up a Gitlab CI/CD pipeline to deploy a Next.js App to FirebaseHow to Set Up a Gitlab CI/CD pipeline to deploy a Next.js App to Firebase


Congratulations 🎉 on launching your new blog. Now that you have a basic blog set up using Next.js, let's automate our deployment process to enhance efficiency. Next.js Apps are commonly deployed to Vercel or Netlify. But, lets explore some alternatives. In this article, we will see how we can set up a CI/CD pipeline for our Next.js app using Gitlab Pipelines and deploy to Firebase App Hosting. This would apply to any other CI/CD pipelines such as Github Actions or Azure DevOps, as the trick remains the same.




Prerequisites

If you do not have a Firebase project setup then I got you covered in next tutorial about how to setup Next.js apps on firebase. Once you have a Firebase project setup, you will need to create a Service Account to authenticate the CI/CD pipeline.

Previously, CI/CD pipelines used to authenticate Firebase using FIREBASE_TOKEN, however this has been deprecated and replaced with GOOGLE_APPLICATION_CREDENTIALS environment variable.

You might see this warning message when you run firebase deploy command if you are using FIREBASE_TOKEN.


🔴🟡🟢
⚠️Warning-Message
$ firebase deploy --token $FIREBASE_TOKEN
⚠  Authenticating with `--token` is deprecated and will be removed in a future major version of `firebase-tools`.
Instead, use a service account key with `GOOGLE_APPLICATION_CREDENTIALS`: https://cloud.google.com/docs/authentication/getting-started

In this article we will use using the latest recommended way to setup authentication for our GitLab pipelines.



Setting up Firebase Service Account

Let's start by creating a Service Account in Firebase, if you haven't already. Go to your Firebase project and click on Settings > Project Settings > Service accounts.

Firebase service Account PageFirebase service Account Page

You should see your service account as firebase-adminsdk-xxxxxx@domain-com.iam.gserviceaccount.com.

  1. Click on Generate new private key and download the JSON file and save it in a secured location.
  2. Rename the private key file to firebase-adminsdk-private-key.json for convenience.
  3. You can skip the above two steps if you already have the private key JSON file.
Firebase generate new private KeyFirebase generate new private Key


Use GCP cloud Google Credentials to authenticate Gitlab Pipeline runners

Now we need to use the private key JSON file to authenticate our Gitlab Pipeline runners. To do that, we have to set the contents of the JSON file as a secret in Gitlab.

  1. Go to your Gitlab project and click on Settings > CI/CD > Variables.
  2. Click on Expand.
  3. Click on Add Variable and add the following details
Gitlab Set CI/CD Environment VariableGitlab Set CI/CD Environment Variable
  1. Keep the variable Type as Variable
  2. Set the Visibility flag as Visible.
  3. Set the Key name as GOOGLE_APP_CRED
  4. Set the Value as the contents of the JSON file as shown below:
    Gitlab Set GOOGLE_APPLICATION_CREDENTIAL CI/CD Environment VariableGitlab Set GOOGLE_APPLICATION_CREDENTIAL CI/CD Environment Variable
  5. Click on Add Variable button.


Setting up Gitlab CI/CD Pipeline file

Once the environment variables are set, we can now setup the Gitlab CI/CD Pipeline file. Add the below contents to the .gitlab-ci.yml file in the root of your project.


🔴🟡🟢
.gitlab-ci.yml
image: node:20.12.2-buster # Use the latest LTS release of Node.js

stages: # List of stages for jobs, and their order of execution. Lets keep it simple for now
  - build-n-deploy

before_script:
  - npm i -g firebase-tools
  - firebase experiments:enable webframeworks # Enable the webframeworks experiment
  - echo $GOOGLE_APP_CRED > "$HOME/gccred.json"
  - export GOOGLE_APPLICATION_CREDENTIALS="$HOME/gccred.json"

after_script:
  - rm -rf $HOME/gccred.json

deploy-job: # This job runs in the deploy stage.
  stage: build-n-deploy
  environment: production
  script:
    - echo "Building My Awesome Blog"
    - npm install
    - echo "Deploying to Firebase"
    - firebase deploy
  only:
    refs:
      - main



Points to note in the above file
  1. image : This is the docker image we will be using to build our project on. We are using latest Node.js LTS version here.
  2. before_script : This is where the magic happens
    1. npm i -g firebase-tools: This installs the firebase-tools globally.
    2. firebase experiments:enable webframeworks : This enables the webframeworks experimental feature. This is essential as of now because NextJS deployment in Firebase is still in experimental stage and we have to enable this settings globally before deploying. Else, you will get the following error:
    1. echo $GOOGLE_APP_CRED > "$HOME/gccred.json" :
      This creates a file called gccred.json in the home directory.
    2. export GOOGLE_APPLICATION_CREDENTIALS="$HOME/gccred.json" :
      This exports the GOOGLE_APPLICATION_CREDENTIALS environment variable with our firebase-adminsdk credentials.
  3. deploy-job : This is the stage where we build and deploy the project to Firebase.
  4. after_script : Although, the Gitlab pipeline runners gets purged after each run, but for security reasons and peace-of-mind we remove the gccred.json file from HOME directory.

Conclusion

With the above setup we are now ready to deploy our NextJS project to Firebase. The pipeline will automatically get triggered when you push any changes to main branch and will build & deploy the project to Firebase.



🛠️ Troubleshooting - HTTP Error: 403, Caller is missing permission


You might encounter the following error while deploying to Firebase:

This is because the the firebase-adminsdk service account invokes a default compute service account to deploy firebase functions which are Google Cloud Functions under the hood, and this account does not have the roles/iam.serviceAccountUser role. To fix this issue, you can grant the roles/iam.serviceAccountUser role to the default compute service account by doing the following steps:

  1. Open the Cloud Console and navigate to the IAM & Admin page.
  2. Click on the Service Accounts tab.
  3. Click on actions button on 460700000000-compute@developer.gserviceaccount.com account row.
  4. Click on "Manage Permission".
    GCP IAM Service AccountsGCP IAM Service Accounts
  5. Edit principal of "firebase-adminsdk" service account
    GCP Compute Service Edit PrincipalGCP Compute Service Edit Principal
  6. In the Assign Role section Click on Add Role
    GCP Service Account - Add RoleGCP Service Account - Add Role
  7. Next search and select "Service Account User"
    GCP Service Account - Service Account UserGCP Service Account - Service Account User
  8. Click on the Save button.
    GCP Service Account - Service Account UserGCP Service Account - Service Account User

A Voila!🪄 Thats it! you won't see "HTTP Error: 403, Caller is missing permission" error when you trigger GitLab your newly created CI/CD pipeline.

AN
Abhilash Nayak
Last Updated on: 12-05-2024

/> Devy.in© 2024Made from scratch with ❤️ & 🍵