Intro
During the time I've been learning to program - because I don't know if I can say I've studied computer science as a whole-, I've done many little projects and other more ambitious - all just for learning purposes-, and as the time passes, I started building some criteria ๐ง about what's else, what spice can I add to those projects to enrich them in technologies. There is always the term "overkill" lurking around, but when it's just for learning purposes and you can set terms and goals ... just do it.
For those who haven't hopped in the CI/CD train, here I bring you a comprehensive set of steps you can take to connect your beautiful, dusty and forgotten, Todo App
, that's been wandering for many months in your /projects
directory.
I'll try to make this as short as possible, but it will be divided into 2 posts. This first post will be about continuous delivery and the second, I'm still not sure if it is continuous delivery or continuous deployment, BUT the technical terminology is the homework, I'm just here to show you the door, you're the one who crosses it and determines what is made of. Off we go โผ๏ธ.
End result ๐
- Basic app ๐ถ๐ฝ
- Github repository with two branches:
master
andcircleci
- A CircleCI account
- A
.yml
file that serves as configuration for CircleCI. It will trigger your test suite every you push content to theorigin/circleci
you were working on.
Continuous Integration (CI) ๐ค
As Microsoft describes it, continuous integration is:
... the process of automating the build and testing of code every time a team member commits changes to version control. - microsoft docs
In simple words, for me, CI means that every time we make git push
, it triggers a set of tasks, previously configured, that culminate with our app to go through multiple tests and/or builds. All this to validate the integrity of the code that you push
to your remote repositories, either to Github, Gitlab, Bitbucket or other remote version control system of your preference, so at this point we are able to say: Ok, the build that originated with the changes on this last commit went through the testing suite without breaking, maybe this is ready for **production*
First Step 1๏ธโฃ
Actually, I'm not starting from the first stem, but you do it on your computers. I'm creating a new app with yarn create react-app
and connecting it to a Github repository. From this point, I'll assume you've all done that.
Second step: Protect master branch in Github 2๏ธโฃ
On the main page of our Github repository, let's go settings
and then branches
.
Then we click in Add Rule
, in Branch name pattern
we write master. Then click in Require status checks to pass before merging
, Require branch to be up to date before merging
, finally let's click in Include administrators
. The last click ensures that everyone has to respect the checks you set to the branch you are protecting, which includes administrators. If we do not check it, we will still be able to merge our feature branch with master.
As you can see, the options panel displays is a message that says Sorry, we couldn't find any status checks ...
. This message appears because our repository doesn't know about the possible checks that we will create in the CircleCI config file.
Let add this file immediately ๐๐ฝโโ๏ธ.
Third step: CircleCIย 3๏ธโฃ
To be able to have continuous integration in our project we'll use the services that CircleCI's free tier delivers me - which by the way is more than enough for our small projects. We can find the website in this link. We register with Github and we'll have access yo all our repositories in the dashboard.
The file we are creating has a .yml
extension -YAML Ain't Markup Language-, which gives us the possibility of setting the steps, for a good configuration file, in a human legible way ๐๐ฝ.
- Go to
ADD PROJECTS
- To the right of your project, it will say
Set Up Project
. Click here - Choose
Node
- Scroll down the page and we will see a configuration file template. Copy it
- In our local repository, create and checkout to a new branch with the name of the feature you are adding to it, in this case, we will create one named
circleci
-->git checkout -b circleci
- Create a directory named
.circleci
. - Inside that directory create a file named
config.yml
- Paste the configuration file template copied before๐๐ฝ
Our configuration file should look like this.
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/node:7.10
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/mongo:3.4.4
working_directory: ~/repo
steps:
- checkout
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "package.json" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run: yarn install
- save_cache:
paths:
- node_modules
key: v1-dependencies-{{ checksum "package.json" }}
# run tests!
- run: yarn test
Forth Step: Do The First Pushย 4๏ธโฃ
- Let's stage our changes to the circleci directory with
git add .circleci/
- Commit the changes
- We Push them to our remote with
git push -u origin circleci
. This will generate a new remote branch with the same name as the local one - origin/circleci - Go to our Github repository
- We will find a green button that says
Create pull request
. If it doesn't appear, we create the pull request ourself๐๐ฝ Notice that the
Merge pull request button
is disabled. This is because we protected master with thecircleci: build
check. Thus, meanwhile the check is not approved, we won't be able to merge ๐ก.
Let's debug! The build failed and we need to check why ๐คท๐ฝโโ๏ธ.
In the same Github page, next to the build that fails, the one with the โ, we see a hyperlink
Details
, click it. That takes us to our CircleCI account, specifically to the 'Job' that failed. There it clearly says that we need a Node version that is>=8.10
. There it is! Let's fix it ๐ท๐ฝโโ๏ธ.
Go to the
config.yml
file in our local repository and on line 5 change the version of your node image.
# image: circleci/node:7.10 <-- Change this
- image: circleci/node:lts # For this.
- We save the file, stage our changes and push them to Github with
git add. && git commit -m 'fix(ci): change to node:lts' && git push
- Head to our Github repository and in the Pull request tab we can see there is a "(1)", that's our old pull request, it's still alive ๐ป. For it to disappear we have to explicitly close it or merge it, if not, it will be there, receiving every other commit you push to the branch we are trying to merge with, in this case
origin/circleci
- Now the build check passes ๐๐ฝ
- Finally, click
Merge
and then we can delete the branch from your Github - then we can do the same in our local repository.
And voilร we just made our first step in the looong way of continuous integration ๐. In the next post we'll use Netlify as a hosting for this app and I'll implement Continuous Delivery with a new configuration file and some Netlify spices, so the deploy process is automatized, plus a way to make the build
process faster using the cache
commands that CircleCI has available for us.
๐พ Here is my Twitter account, sometimes I post about web development
I hope it's useful, Chao!
Bonus: Github Flow
The way I manage my version control system is known as Github Flow, and it goes like this.
- Everything in
master
is deployable - To work on something new, create a descriptively named branch off of
master
(ie:new-circleci
) - Commit to that branch locally and regularly push your work to the same-named branch on the server
- When you need feedback or help, or you think the branch is ready for merging, open a pull request
- After someone else has reviewed and signed off on the feature, you can merge it into master
- Once it is merged and pushed to
master
, you can and should deploy immediately
Keywords
- Continuous Development
- Continuous Delivery
- Github Flow
Top comments (1)
Helpful article but I'm sure most of us could really do without the animated GIFs (other than the screen captures)