What We’re Doing
What we’re trying to do with this tutorial is to automate our code commits being tested and automatically deployed with CircleCI.
Why Though?
“Boils down to saving time.”
Sometimes developers don’t run unit tests and double check their code to make sure things are working correctly.
Requirements
- NodeJS —
10.16.3
- GitHub Account
- CircleCI Account Linked With GitHub
Create React App
Let’s get started! We’re going to start by doing the basic the create-react-app
:
npx create-react-app c;
Initial Jest Test
Once the app is scaffolded out, let’s try a simple test.
yarn run test --watchAll=false; # npm run test--watchAll=false;# Expected Output
# yarn run v1.16.0
# $ react-scripts test --watchAll=false
# PASS src/App.test.js
# ✓ renders without crashing (25ms)
#
# Test Suites: 1 passed, 1 total
# Tests: 1 passed, 1 total
# Snapshots: 0 total
# Time: 1.046s
# Ran all test suites.
# ✨ Done in 1.83s.
NOTE: for npm
this might not exit the watch
, so we need to add the following modification to our package.json
to add another test with the watchAll=false
File: ./package.json
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"test-nowatch": "react-scripts test --watchAll=false",
"eject": "react-scripts eject"
},
GitHub Repository Setup
Next we’re going to setup a new repository on GitHub and configure our local folder with that new create-react-app
we just made.
̶N̶e̶x̶t̶ ̶w̶e̶’̶r̶e̶ ̶g̶o̶i̶n̶g̶ ̶t̶o̶ ̶r̶e̶m̶o̶v̶e̶ ̶t̶h̶e̶ ̶o̶r̶i̶g̶i̶n̶a̶l̶ ̶.̶g̶i̶t
̶ ̶f̶o̶l̶d̶e̶r̶ ̶f̶r̶o̶m̶ ̶o̶u̶r̶ ̶p̶r̶o̶j̶e̶c̶t̶,̶ ̶s̶o̶ ̶t̶h̶a̶t̶ ̶w̶e̶ ̶c̶a̶n̶ ̶l̶i̶n̶k̶ ̶i̶t̶ ̶w̶i̶t̶h̶ ̶o̶u̶r̶ ̶n̶e̶w̶ ̶G̶i̶t̶H̶u̶b̶ ̶r̶e̶p̶o̶s̶i̶t̶o̶r̶y̶ ̶t̶h̶a̶t̶ ̶w̶e̶ ̶j̶u̶s̶t̶ ̶s̶e̶t̶ ̶u̶p̶.̶
̶r̶m̶ ̶-̶r̶f̶ ̶.̶g̶i̶t̶
̶N̶e̶x̶t̶ ̶w̶e̶ ̶n̶e̶e̶d̶ ̶t̶o̶ ̶r̶e̶-̶e̶s̶t̶a̶b̶l̶i̶s̶h̶ ̶g̶i̶t̶
̶f̶o̶r̶ ̶t̶h̶e̶ ̶p̶r̶o̶j̶e̶c̶t̶.̶
̶g̶i̶t̶ ̶i̶n̶i̶t̶;̶
UPDATE: Another Developer on Reddit pointed out that you do not need to do this ☝. Thanks oplav
🙏.
Link the folder to the repository:
git remote add origin https://github.com/{youraccount}/deploy-react-firebase-circleci.git;
Lastly, add, commit, and push our code:
git add .;
git commit -m "INIT: initial commit.";
git push origin master;
CircleCI Setup & Config
To setup CircleCI, we need to sign up and connect our GitHub account.
Sign Up
Add Project
Go to Add Project
on the left sidebar.
Set Up Project
Make sure to setup you new deploy-creact-firebase-circleci
Configure Project
Select Linux
and select Node
. Copy to your clipboard the config.yml
file and then click Start Building.
Building
Right away it will start building, but because there is no config.yml
file yet, it’ll give an error.
Next to the name of your project will be a Cog Icon, click it to be brought to the Project Settings.
Pull Requests
We’re to set up CircleCI to only build on Pull Requests (PRs) and our main branch master
. This is to make we save on our Free account offered from CircleCI.
In Project Settings, click Advanced Settings, and then select On
for Only build pull requests.
Configuring Our First Test
Now that we have everything setup, we can no create our first config.yml
file in our repository.
First, create a new folder call .circleci
and place it in a file called config.yml
. We’ll use this node circleci configuration as a base and but make some changes.
File: /.circleci/config.yml
Create a new a branch react-test
so that we can create a new PR, commit, and push our changes.
git checkout -b react-test;
git add .;
git commit -m "FEAT: Initial CircleCI config.yml";
git push origin react-test;
Create A Pull Request On GitHub
This is so that we can initiate the process for a build on CircleCI.
As soon as you create a Pull Request, it will automatically run the test and show a pass like we did before at the beginning with yarn run test
or npm run test-nowatch
.
If you click on Details
right of ci/circleci: build
, you can see the tests that were successfully performed on CircleCI.
Now if want to add more tests, we can, so that it acts as a last minute check before we try to merge things.
Firebase Setup
Next thing we want to do is deploy our code directly to Firebase.
I’m already going to assume that the Firebase project has been setup on Firebase.com but not within out project.
Initial React Build
Before we continue setting up things with react, we’ll do an initial build that we’ll be using later. Run the following:
yarn run build; # npm run build;
Firebase Project Login
If you haven’t done so already, you’ll need to add firebase-tools
to the project.
yarn add firebase-tools --dev; # npm install firebase-tools --dev;
Login and select your existing project.
./node_modules/firebase-tools/lib/bin/firebase.js init;
Select Hosting
:
◯ Database: Deploy Firebase Realtime Database Rules
◯ Firestore: Deploy rules and create indexes for Firestore
◯ Functions: Configure and deploy Cloud Functions
❯◉ Hosting: Configure and deploy Firebase Hosting sites
◯ Storage: Deploy Cloud Storage security rules
Select Use Existing Project
:
❯ Use an existing project
Create a new project
Add Firebase to an existing Google Cloud Platform project
Don't set up a default project
Select your project:
❯ your-project-1234abc (your-firebase-project-1234abc)
Press Enter
:
? What do you want to use as your public directory?
Press y
and then Enter
:
? Configure as a single-page app (rewrite all urls to /index.html)? (y/N) y
Press n
and then Enter
:
? File public/index.html already exists. Overwrite? (y/N) n
In your repository you’ll see two new files:
.firebaserc
firebase.json
I’m going to add .firebaserc
to .gitignore
so that this repository is not bound to one firebase project, if needed.
File: .gitignore
...
# misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.localnpm-debug.log*
yarn-debug.log*
yarn-error.log*
.firebaserc
And we’ll create a copy file called .firebaserc.example
File: .firebaserc.example
{
"projects": {
"default": "[YOUR-PROJECT-ID]"
}
}
We’re going to use this as a template later to fill it in on the fly with CircleCI.
Lastly, we’re going to modify our firebase.json
file to point to the build
folder we created, so that Firebase knows to public this directory instead of the uncompressed public
folder.
File: firebase.json
{
"hosting": {
"public": "build",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
CircleCI Workflows
This next step, we’re going to modify the configm.yml
, add a build process, add the ability to generate a .firebaserc
file and add a deploy process, where deploy only happens on the master
branch.
NOTE: Pay attention to your yaml
spaces or tabs. They really do matter.
File: /.circleci/config.yml
Remember to git add, commit, and push the code.
Generate Firebase Login CI Token
The tests should pass and now we just need to account for $FIREBASE_PROJECT_ID
and $FIREBASE_TOKEN
in CircleCI.
Before we can do that we need to generate a continuous integration token from Firebase, by running:
./node_modules/firebase-tools/lib/bin/firebase.js login:ci
You’ll be redirect to log into your account and then a token should be generated:
# Expected OutputWaiting for authentication...✔ Success! Use this token to login on a CI server:1234abc56789nmadjdasddasdjkhsakdhsadsa312hadjhsakdashdasdExample: firebase deploy --token "$FIREBASE_TOKEN"
CircleCI Environment Variables
After retrieving all the keys you need, go back CircleCI and go to the Project Settings and click on Environment Variables.
We’re going to click Add Variable and enter the appropriate keys.
Merge The Pull Requests
Now we’ll go back to the Pull Request and merge the successfully passed code.
The code will now be tested once more on master
and if everything is good, it will deploy the code to the Firebase hosting automatically.
Visiting Our Firebase React Project
Now when you visit the deployment linkhttps://{your-project-id}.firebaseapp.com
you should see the code successfully deployed.
What Else You Can Do
We’re successfully automated testing and deployment of our React app on Firebase Hosting, but there is definitely more that we can do.
What some developers have done is adjust some of the settings for GitHub to prevent other developers from merging code to master unless they have passed all their tests.
Additional you could split up your app and add a NodeJS backend which would have its own testing and deployment process.
If you got value from this, and/or if you think this can be improved, please let me know in the comments.
Please share it on twitter 🐦 or other social media platforms. Thanks again for reading. 🙏
Follow me on twitter: @codingwithmanny and instagram at @codingwithmanny.