Continuously deploy a Jekyll generated static site to Firebase with Gitlab in under 6 minutes.
Tags: devops, git, firebase, ruby
Published: 2020-03-22 19:02:00

There comes a time when a software developer either wants acknowledgement, build an online presence or just show how cool he/she/it is. Myself? I just wanted to give back to the newcomers who seek knowledge, as I once did, and I still do, every time I open a browser or a book.  

To solve that I decided to create a [blog][catalin-vasile], and there I found Jekyll, a fantastic tool to develop fast, reliable websites. It generates pure HTML, but it can also be integrated with 3rd party tools like Disqus (comment section). Writing content for Jekyll is straight forward: write some markdown, build and check your site, and you’re ready to push.  

Making the site pretty with CSS is out of the scope of this post and will only focus on getting it deployed to Firebase. I will open-source ‘my design’ if there’s enough interest, but just so you know, I am really bad with everything about front-end.  

## Prerequisites:
<ul style="list-style: circle inside none">
    <li><a class="has-text-danger" href="https://code.visualstudio.com/download" _target="blank">Visual Studio Code (or any 
        other editor)</a></li>
    <li><a class="has-text-danger" href="https://git-scm.com/doc" _target="blank">Git and Bash Knowledge</a></li>
    <li><a class="has-text-danger" href="https://jekyllrb.com/" _target="blank">Jekyll</a></li>
    <li><a class="has-text-danger" href="https://firebase.google.com/" _target="blank">Firebase hosting</a></li>
    <li><a class="has-text-danger" href="https://about.gitlab.com/" _target="blank">Git on Gitlab</a></li>
    <li><a class="has-text-danger" href="https://www.npmjs.com/get-npm" _target="blank">Node.js and npm</a></li>
    <li><a class="has-text-danger" href="https://www.docker.com/" _target="blank">Docker (optional)</a></li>
</ul>
The services above are free to use, this very blog uses the same infrastructure. The only difference is that this blog is running on a paid domain name.  

I chose Firebase as a hosting provider because it provides free SSL and CDN on Google’s servers. Gitlab for versioning because it comes with a pipeline included and its free tier is more than enough. Jekyll because I don’t know anything about JavaScript and Gatsby.   
<hr>
## Jekyll
Installing Jekyll and creating your first website is as simple as following their guide [here][jekyll]. But if you already have Ruby installed on your machine, even better, just run this one-liner:  
```
sudo gem install jekyll bundler && jekyll new my-blog && cd my-blog
```
To quickly test that everything went well run:  

```
bundle exec jekyll serve
```
And access your newly generated website at `http://127.0.0.1:4000/`, this is what you're supposed to see in the browser:   
![jekyll-landing-page][jekyll-landing]
Great! Now that you generated your first static website, we can move on to the next part: Taking it to ‘production’ and making it accessible from the public internet.  
<hr>
## Firebase Hosting
So let’s create a Firebase account, for that follow Google’s page [here][firebase] and sign up unless you already have a Google account, then you only have to log in.  
Continue by creating your first project on the Firebase Console and while waiting for that to be set up, install Node.js and npm as described [here][npm].  
![firebase-project-setup][firebase-project]
Why the need for npm? To deploy to Firebase Hosting we are going to use *firebase-tools cli*. Therefore once *node* and *npm* are installed run `npm install -g firebase-tools` within your terminal to install that as well.  
After it’s done, you need to give the tool access to your account, so switch to your terminal, change directory to your website’s root and run `firebase init`. Select *‘Hosting’*, and then select your project. You will now have two new files in your project: `firebase.json` and `.firebaserc.`  
By default, the *firebase tool* expects the folder it deploys to be called **public** whereas Jekyll (by default) builds to **_site**. To change that we need to open up `firebase.json` in Visual Studio Code or any other text editor of your choice, paste in the following and save it:  
```
{
    "hosting": {
      "public": "_site",
      "ignore": [
        "firebase.json",
        "**/.*"
      ]
    }
}
```
You've reached so far, but guess what? Now you can deploy your generated Jekyll website to Firebase Hosting. All you have to do is run `firebase deploy --verbose` in your terminal.  

The URL to access your newly deployed website on the internet can be found on the project's overview within the *Firebase Dashboard*. On the left side of the screen, there’s a *Hosting* menu item which will lead to your project's registered domains. If you can't find it, just type in your browser `http://<your-project-name>.web.app` which should take you to your newly deployed website.  
Now let's deploy every time we create and commit a new post or any other change you push to your Gitlab repository. If you didn't create a Gitlab account yet, you can do it [here][gitlab].  
<hr>
## Gitlab
Before pushing your generated website to any repository in Gitlab, we need 2 last things: 
A `$FIREBASE_TOKEN` which grants our CI/CD pipeline access to run the deployment and a file that describes the actions happening on the pipeline.  
To get the token run `firebase login:ci` at the root of your generated website in your terminal. A successful message would look like:  
```
✔  Success! Use this token to login on a CI server:

1/as4Gqp8rm31xNecDRcD939xpk7g4h2R6fycEwFTqPaw

Example: firebase deploy --token "$FIREBASE_TOKEN"
```
We'll set the token as a variable inside the Gitlab repository as seen here:  
![gitlab-environment-variable][gitlab-env-var]
For the last part, we will use the `$FIREBASE_TOKEN` in our `.gitlab-ci.yml`. For that, we need to create the `.gitlab-ci.yml` file at the root of the generated website folder, and paste the following content to it:  
```
variables:
  PROJECT_NAME: <your-project-name>
  JEKYLL_ENV: production
stages:
  - deploy

cache:
  paths:
  - vendor/
  
production:
  stage: deploy
  only:
    - master
  image: catalinvasile/firebase-tools:latest
  script:
    - bundle install --path vendor
    - JEKYLL_ENV=${JEKYLL_ENV} bundle exec jekyll build 
    - firebase use ${PROJECT_NAME} --token $FIREBASE_TOKEN
    - firebase deploy --only hosting -m "Pipe $CI_PIPELINE_ID Build $CI_BUILD_ID" --token $FIREBASE_TOKEN
```
And that's it! All you have left to do is `git push` your website to a Gitlab repository. From now on, every time you will write a new post for your website or add any change to your repository, it will trigger a deployment. The changes will be reflected as soon as the pipeline finishes running.  
I know that some of the mentioned snippets aren't self-explanatory, but to keep things short enough, without getting into too many details, I left them out on purpose, waiting to be discovered.  
Well done 👏! I hope you enjoyed this, as much as I did writing it!

[catalin-vasile]: https://catalinvasile.dev
[firebase]: https://firebase.google.com/
[npm]: https://www.npmjs.com/get-npm
[visual studio code]: https://code.visualstudio.com/download
[jekyll]: https://jekyllrb.com/docs/
[gitlab]: https://gitlab.com/
[firebase-project]: https://catalinvasile.dev/assets/images/firebase-create-project.png "firebase-project-setup"
[jekyll-landing]: https://catalinvasile.dev/assets/images/jekyll-landing-page.png "jekyll-landing-page"
[gitlab-env-var]: https://catalinvasile.dev/assets/images/gitlab-environment-variable.png "gitlab-environment"