Continuously Integrate and Deploy an Angular Application to Firebase Hosting with GitHub Actions

Deploy ANgular Application to Firebase Hosting using Github Workflow CI CD Pipeline

Today we are going to learn how to implement a CI/CD pipeline to deploy an Angular application in Firebase hosting whenever we push the updated code to our GitHub repository. We are going to use GitHub Actions for this. GitHub Actions is a CI/CD tool that allows users to automate their project workflow. You can define certain actions to run when code is pushed to a branch, a new tag is uploaded, or even when a directory has changed. Before starting this tutorial, hope you have the following prerequisites.
  • Firebase project
  • Angular application
  • GitHub repository for the Angular application
If you need help to setup Firebase with your Angular project, you can refer to this tutorial: https://www.bezkoder.com/integrate-firebase-angular-15/

Setup Firebase on your Angular project and deploy it from your local computer to Firebase Hosting

  1. Check whether the Firebase tools is installed or simply run: npm install -g firebase-tools
  2. Check whether you’re logged in to Firebase or run the command: firebase login
  3. Set up hosting config by running the command: firebase init
  4. Build your project by running the command: ng build
  5. Deploy your project on Firebase hosting by running: firebase deploy
When you run the "firebase init" command, you will be asked to setup hosting with GitHub. Let's enter "No" for that for this tutorial. This "firebase init" command will create some files in the project root and the file named "firebase.json" is important for this tutorial. The main thing to note here is the public folder (hosting.public) in the firebase.json file should be equal to the build destination (architect.build.options.outputPath) in the angular.json file.

Setup Firebase Continuous Integration Token on Your GitHub Repo

  1. Get a Firebase token to be used in a CI/CD server by running: firebase login:ci
  2. Copy and save the retrieved Firebase token
  3. Go to the "Settings" tab in your GitHub repository
  4. Go to the "Actions" section under the "Secrets and variables" section in the repository settings
  5. Add a new secret to save your Firebase token in your GitHub repository
Github repository action secrets for firebase hosting CI CD

Add Production Build Command into Your Package.json File

Hope you know that we have two different environments for an Angular project by default. We can add more environments if we wish to. Normally when we run  "ng build", it builds the project in the development environment. But if you need to build in the production environment, you can use the following command: ng build --configuration production.

You can add the following line into the scripts object in your package.json file to make that command shorter (ng build:prod).

"build:prod": "ng build --configuration production"

Setup a CI/CD Workflow with GitHub Actions

  1. To create your first workflow click on "Set up a workflow yourself" in the "Actions" section of your GitHub repository.
  2. Then use the following code there and commit the changes to your repository main branch. Then it will be saved in the ".github/workflows/main.yml" file in your repository.

Please mention the correct node version you used to develop and build the project locally in the above YAML file. Otherwise, it may give some errors when it runs the GitHub workflow.

Now you can see your GitHub CI/CD workflow in the "Actions" tab in your repository. Try pushing some changes to your main branch and see the Actions tab and your Firebase hosting. Works... pretty awesome right?

Secure and Hide Your Angular Environment Variables in Your Repository with GitHub Workflow Actions.

You have setup your GitHub Action but wait... Your Angular environment variables are there in your repository, right? Normally, I used environment.ts to store the Firebase project configuration. Since this file contains secrets and keys it cannot be pushed to the remote repository. You have to hide them even if it's a private repo because this private repo can have many developers but your Firebase production project is not accessible to all of them right? If they have access to your production server, please just consider the security of your project more ;)

Anyway... now we are going to hide our environment variables from our GitHub repository but later we learn how to use those secret Angular environment configs while it runs the CI/CD GitHub workflow.
  1. Add the following file paths to your .gitignore file, commit it, and push.
    • /src/environments/environment.ts
    • /src/environments/environment.prod.ts
  2. If you have already pushed these env files to your GitHub repo, please delete them from your repo.
  3. As we did for the Firebase token, you can store the content in the environment.prod.ts as a GitHub Actions Secret. Btw, this is a lazy way ;)
Github repository action secrets for Angular Environment Variables

Github repository action secrets for Firebase Hosting and Angular Environment Variables

Let's see how to use these secret environment configs when it runs the GitHub CI/CD workflow.
  1. Create a new JavaScript file in the project root directory to include steps to create the environment.ts file and the environment.prod.ts file with configurations we saved in GitHub Actions Secrets. I named this file as "angular-env-file-creator.js".
  2. Put the following code in the server.js file. Then commit it and push it to the main branch.

  3. Now, you have to update the ".github/workflows/main.yml" file in your repository to tell the GitHub Actions to run this server.js before building the Angular project. The following image shows the updated YAML file.
Github Actions workflow to host Angular app on firebase hosting with Env Configs

Now you can test your GitHub workflow CI/CD pipeline again by pushing some changes to your main branch. To debug, add log messages to angular-env-file-creator.js. Remember that the GitHub secrets won’t be printed as log messages for security reasons.

The workflow executions got failed sometimes when it's unable to create the "src/environments" folder using our JS script. We create that folder in the JS script because that folder won't be there in our GitHub repository after we put the environment.ts file path and the environment.prod.ts file path in the ".gitignore" file. A small hack is there to fix this. I just put an empty text file inside the "src/environments" folder to keep that folder in the GitHub repo.

Happy Hacking ;p See you in another article!