- Generate a private & public SSH key for the CI server.
- Paste the private key into circle CI.
- Grab the key fingerprint from circle CI for later.
- Paste the public key into ~/.ssh/authorized_keys/ on the host.
- Create a .circleci folder in the root of your project with a config.yml file underneath.
- Adjust the following circle CI config as necessary. The file:
- loads a node environment
- allows the fingerprint supplied to connect
- restores cached node_modules and yarn cache
- runs yarn install
- saves caches
- adds expo-cli – currently does not cache, so will play with that further
- builds the project (into web-build/ subfolder)
- uploads the project via scp to the remote server
version: 2
jobs:
build:
working_directory: ~/web
docker:
- image: circleci/node:8
steps:
- add_ssh_keys:
fingerprints:
- "<the ssh fingerprint from above>"
- checkout
- restore_cache:
key: yarn-v1-{{ checksum "yarn.lock" }}-{{ arch }}
- restore_cache:
key: node-v1-{{ checksum "package.json" }}-{{ arch }}
- run: yarn install
- save_cache:
key: yarn-v1-{{ checksum "yarn.lock" }}-{{ arch }}
paths:
- ~/.cache/yarn
- save_cache:
key: node-v1-{{ checksum "package.json" }}-{{ arch }}
paths:
- node_modules
- run: yarn global add expo-cli
- run: CI=false && yarn web-build && CI=true
- run: scp -o StrictHostKeyChecking=no -r ./web-build/* user@host-server-ip-address:/var/www/path/to/app/
As the project wears on, I’ll add some unit testing and end to end testing to this pipeline.
Footnote: Deploying expo build:web to a subfolder
I had a hell of a time finding the right incantation to get this working. There’s different advice everywhere.
The solutions are not:
- homepage field in package.json
- Anything in app.json
- Any command line flags/switches in expo build
The solution is to customize expo’s webpack file, to specify that there is an output subdirectory.
- Run
expo customize:web
and choose to export webpack.config.js - Specify the public path required. e.g. my webpack.config.js now looks like:
const createExpoWebpackConfigAsync = require("@expo/webpack-config");
module.exports = async function(env, argv) {
const config = await createExpoWebpackConfigAsync(env, argv);
// Customize the config before returning it.
config.output.publicPath = "/app/";
return config;
};
- Note the addition of config.output.publicPath