CI/CD with Vue, Firebase Hosting and Github Actions

Alpercation
Oct 26, 2020 · 7 min read
Image for post
Image for post
Photo by Richy Great on Unsplash

Even if you’re the only developer in a project, you still have to make sure you automate your deployment process and follow certain steps in order to prevent bugs sneak into production code. Writing tests is the first step of it. But then, running those tests everytime you make a change in the code is a time consuming process where you can benefit from some automation. This is where Github Actions come into play: How about creating a workflow in Github Actions which will run the tests for you when you make a pull request and won’t allow merging to master and deploying to production if the tests fail? That would really help with avoiding unintentional deployment of buggy code. Another important point is not forgetting to deploy your code into production when a pull request is merged to master. The Github workflow that we are going to create will also handle that by automatically deploying to Firebase Hosting when a pull request is completed.

Let’s see how it’s done step by step:

Creating a Vue Project

If you have an older version, you can update by npm update -g @vue/cli or if you never had installed before you can install it globally by npm install -g @vue/cli.

Next, let’s create a brand new vue project called “vue_ci_cd” with the command vue create vue_ci_cd_example.

Not all settings are relevant for the purpose of this tutorial, but make sure the following settings are handled as follows:

  • Please pick a preset: Manually select features
  • Pick a unit testing solution: Jest
  • Pick an E2E testing solution: Cypress (Chrome only)

It will then install all the necessary dependencies for the app. If everything goes well, you should be able to run the app with this command cd vue_ci_cd_example && npm run serve .

Pushing the Vue project to a Github repository

Initializing Firebase Hosting for the project

Make sure you are in the project folder, and then do firebase init. The settings will be as follows:

  • Which Firebase CLI features do you want to set up for this folder?: make sure at least Hosting is selected
  • What do you want to use as your public directory? dist
  • Configure as a single-page app (rewrite all urls to /index.html)? y
  • Set up automatic builds and deploys with GitHub? y

At this stage, it will connect to your Github to be able to get the repository information.

  • For which GitHub repository would you like to set up a GitHub workflow? your_github_account_name/repository_name (for me, this was: alperkay/vue_ci_cd_example)
  • Set up the workflow to run a build script before every deploy? y
  • What script should be run before every deploy? (npm ci && npm run build): enter
  • Set up automatic deployment to your site’s live channel when a PR is merged? y
  • What is the name of the GitHub branch associated with your site’s live channel? (master) enter

This will create a Firebase project with hosting enabled, it will connect the Firebase project to the repository in Github and also will create a .github/workflows folder in your project’s root with 2 files firebase-hosting-merge.yml and firebase-hosting-pull-request.yml . First workflow will run in every merge to master, whereas the second one will run only when a pull request is created. What these 2 workflows will do is basically build the application and deploy it to Firebase Hosting. The first one will deploy to your production / live environment , while the second one will deploy to a separate url where you can preview/QA the result of your code before merging the pull request. This is already a great achievement, because we don't need to deal with deployment everytime we make changes to our code. Pushing or merging to master branch will be enough. And the rest will be taken care of by Firebase and Github.

Adjusting the Github workflows for our needs

Let’s create a new branch and replace the “firebase-hosting-pull-request.yml” file with the following one:

firebase-hosting-pull-request.yml

# This file was auto-generated by the Firebase CLI
# <https://github.com/firebase/firebase-tools>
name: Deploy to Firebase Hosting on PR
"on": pull_request
jobs:
unit_test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm ci && npm run test:unit
e2e_test:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Cypress run
uses: cypress-io/github-action@v2
with:
start: npm run serve
wait-on: <http://localhost:8080/>
config_file: cypress.json
spec: "tests/e2e/**/*"
env:
CYPRESS_baseUrl: <http://localhost:8080/>
build_and_preview:
needs: [unit_test, e2e_test]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- run: npm ci && npm run build
- uses: FirebaseExtended/action-hosting-deploy@v0
with:
repoToken: "${{ secrets.GITHUB_TOKEN }}"
firebaseServiceAccount: #REFERENCE TO FIREBASE SERVICE ACCOUNT SECRET GOES HERE. YOU CAN KEEP THE ONE YOU ALREADY HAVE IN THE ORIGINAL VERSION OF THE FILE
projectId: #YOUR PROJECTID GOES HERE. YOU CAN KEEP THE ONE YOU CAN KEEP THE ONE YOU ALREADY HAVE IN THE ORIGINAL VERSION OF THE FILE
env:
FIREBASE_CLI_PREVIEWS: hostingchannels

So, we added the unit_test and e2e_test jobs to the pull-request workflow, which will run unit and e2e tests first and then build and deploy to a preview/QA environment. This is a very important step to make sure we don't push code with failing tests.

Now, if you push these changes and create a pull request in Github, you ‘ll see in the repo’s Actions tab that “Deploy to Firebase Hosting on PR” job is running.

If the job succeeds, then you’ll see that your app will be deployed to a preview page in Firebase Hosting. To make it more clear, this step does not deploy to your production page but to a separate url, so that you can actually check visually/qa if the app is working properly.

Image for post
Image for post
“deploy to firebase hosting on pr” action completed

Of course, this doesn’t prevent merging bad code to your master branch. If you want to prevent (which I think you should) merging pull requests with failing unit or e2e tests to master, you should add a Branch protection rule. For that, go to the Settings tab in your Github repository. Select Branches from the left-side menu. And under Branch protection rules header, select Add rule. We should put down the name of the branch that we want to protect to Branch name pattern text field and select the necessary status checks as follows:

Image for post
Image for post

Now, let’s create a new branch and change the sample unit test (/tests/unit/example.spec.ts) so that it fails intentionally. When you push this code and create a pull request to merge to master, you’ll see 2 things:

  • First, as expected, our workflows will run and unit_test step will fail and therefore build&preview step will never run
  • Since unit tests fail, Github will not allow you to complete the pull request, merge to master and deploy into production

Let’s go back to the code and fix the unit test so that it can pass. When we push this fix, the test jobs will run again and succeed this time, which will allow the next job (build_and_preview) to run and also succeed. At this point, it will give you a url (similar to what you see in the below screenshot) where you can QA the pull request.

Image for post
Image for post

And now when you check your pull request in Github, you’ll see that Github now allows it to be merged since Branch Protection Rules that we set have passed successfully. When you complete the pull request, the other workflow named “Deploy to Firebase Hosting on merge” will run and hopefully it will deploy your app/webpage to production.

Now, isn’t this cool?

In a few easy steps, we were able to build a basic CI/CD pipeline. As long as you write tests and those tests succeed, every code you merge to master will be deployed to your production environment. I’m sure this basic pipeline can be improved in many ways and I’d love to hear what you guys do more to make your deployments automated and bug-free.

Vue.js Developers

Helping web professionals up their skill and knowledge of…

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store