Same article in Medium: https://medium.com/@thundermiracle/deploy-static-sites-to-netlify-by-circle-ci-ab51a0b59b73
Back in the 90s’ of the web, about all sites were static. But as web users grow, we want to display rich contents. Then comes up the new architecture — [Front → Server → DB]
like LAMP (Linux, Apache, MySQL, PHP). WordPress is the one of the most famous. But time flies, static sites are back! Why?
Why Static Sites
-
Speed. No doubt that static sites are extremely fast.
-
Security. No intermediary means low threat of code injection. No plugins means low worry of catching up the latest version to protect your dynamic site.
-
Low Price. FREE rocking hosting services like Github-Pages or Netlify vs $xx/mon server only for blog or company website. You choose.
-
Easy to migrate. My LAMP site (not WordPress) was DDoS attacked, and that VPS server was stopped automatically before I could login. I requested the provider to let me login and backup the latest data from DB, but was rejected. They said ‘you have only two choices: clean reinstall the server and change the IP or get out of here.’ I moved out. Yes, without the latest DB. Besides, migration cost me much time. But if it was a static site with lambda…
No need Circle-CI, Netlify is enough
Yes. You’re right. You can CD your website to Netlify with only or even without a netlify.toml.
But tests are very important for me, I’d like to test my website before publish them. So, a CI tool is necessary.
Why Circle-CI
I’m not sure whether Circle-CI is the best. But it’s Docker supported just like Gitlab-CI does. So it’s easier for me to understand rather ran Travis-CI. And it’s possible CI Github private repositories too.
Where to build
There are two ways to deploy your site.
- test in Circle-CI, use webhook to kick the Netlify, Netlify build & deploy.
- test & build in Circle-CI, push the built files to Netlify by netlify-cli.
Because of the cache function in circle-ci, test & build in circle-ci is much faster. Besides, if you can migrate to another hosting service with changing last step only.
So I choose method №2.
Let’s begin
Environment
As I’m using gatsbyjs, docz, storybook, next.js to create my websites. I’d like to compile them in node server.
executors:
node:
docker:
- image: circleci/node:8
Cache
npm with package-lock.json is fast
. yarn with yarn.lock is faster
. yarn with yarn.lock and cache rocks
. As package.json doesn’t change often, cache is great in this use case.
Let’s define some variants for cache.
aliases:
restore_cache: &restore_cache
restore_cache:
name: Restore Npm Package Cache
keys:
- yarn-cache-netlify-{{ checksum "yarn.lock" }}
install_node_modules: &install_node_modules
run:
name: Install dependencies
command: yarn
save_cache: &save_cache
save_cache:
name: Save NPM package cache
key: yarn-cache-netlify-{{ checksum "yarn.lock" }}
paths:
- ./node_modules
Jobs
As I mentioned before, I’d like to split the steps to test → build → deploy
for the speed as well as flexibility.
test
test:
executor: node
steps:
- checkout
# Restore cache at second time
- <<: *restore_cache
# Install for first time
- <<: *install_node_modules
# Cache the ./node_modules before test.
- <<: *save_cache
- run:
name: Test
command: yarn test
You may have already noticed, we’re using executor instead of docker:xxx.
build
build:
executor: node
steps:
- checkout
- <<: *restore_cache
- <<: *install_node_modules
- run:
name: Build
command: yarn build
- persist_to_workspace:
root: ./
paths:
- public
deploy
Install netlify-cli and the deploy.
deploy:
executor: node
steps:
- checkout
# Attach the pesisted built files.
- attach_workspace:
at: ./
- <<: *restore_cache
- <<: *install_node_modules
- run:
name: Install netlify-cli
command: sudo npm install -g --silent netlify-cli
- run:
name: Deploy to Netlify
command: netlify deploy --dir=./public -p
As you can see, I can migrate to another host easily by just replacing this part.
Put jobs together
Use workflow the put them together.
workflows:
version: 2
build_and_deploy:
jobs:
- test
- build:
requires:
- test
- deploy:
requires:
- build
filters:
branches:
only: master
That’s all about the configuration yaml, not hard right?
The whole yaml sample file is here
https://github.com/thundermiracle/gatsby-simple-blog/blob/master/deploy/netlify/.circleci/config.yml
But the settings are not finished yet. We’re almost there. What’s left?
netlify deploy — dir=./public -p
Yes. We haven’t told netlify-cli where to deploy.
We need NETLIFY_AUTH_TOKEN
to target our account, and need NETLIFY_SITE_ID
to link our website in the account.
Netlify.com
Generate NETLIFY_AUTH_TOKEN
In your [User Settings] → [Applications] → [Personal access tokens]
.
Link: https://app.netlify.com/user/applications#personal-access-tokens
Click [New access token]
. Save your token somewhere because it’s showed only once and we’ll use it in circle-ci.
Generate NETLIFY_SITE_ID
Two ways to do it.
- Install netlify-cli in your local machine. Run netlify init and follow the instructions.
npm install -g netlify-cli
cd your-project-folder
netlify init
netlify-cli will generate .netlify/config.json
for you. You can set this NETLIFY_SITE_ID
in Circle-ci and delete the folder. Or just remain it and skip the NETLIFY_SITE_ID
setting step.
- In Netlify’s admin panel,
[Sites]
menu, click[New site from Git]
, follow the instructions.
Link: https://app.netlify.com/start
Then you can find your ID here: [Site settings] → [Site information]
API ID is your NETLIFY_SITE_ID
.
Circle-CI
Add project
[Add Projects] → [Set Up Project] → [Start Building]
PS: No need to copy the config.yml as we created it manually just now.
Set environment viriants
[Project Settings] → [Environment Variables] → [Add Variable]
Add your NETLIFY_AUTH_TOKEN
and NETLIFY_SITE_ID
.
Last
Push your source code to Git and Happy Static Site!