├── .gitignore ├── Continuous-Deployment-Setup-Electron.md ├── Continuous-Deployment-Setup-Hex.md ├── Continuous-Deployment-Setup-NPM.md ├── Continuous-Deployment-Setup-React-Native.md ├── README.md └── config.example.yml /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | -------------------------------------------------------------------------------- /Continuous-Deployment-Setup-Electron.md: -------------------------------------------------------------------------------- 1 | 🚧 🚧 🚧 GUIDE UNDER CONSTRUCTION 🚧 🚧 🚧 2 | 3 | This is the first draft of this document and it currently leans pretty heavily on a existing setup for `reactotron`. Eventually all the information needed should be available within this guide. 4 | 5 | # Electron app setup 6 | 7 | When setting up an Electron app there are a lot of moving parts and things to consider. To ease the setup process this guide will walk you though some basic setup steps from basic building, setting up an auto updater and using Circle CI for CI/CD 8 | 9 | ## Building 10 | 11 | Electron apps are made up of two somewhat separate parts. The first part is the binary that the operating system actually runs. This will need to be compiled specifically for each platform you want to target. We will call this the `Binary`. The second part is the actual implementation of whatever you want the app to do. This can be written in any webbased technology (`react`, `angular`, `vue`, `jQuery`, etc). This guide will be assuming it will be built in `react` and bundled with `webpack` (https://webpack.js.org/) although these play a minor part in this guide so feel free to switch them out and adapt this guide to whatever technology you like. We will call this secondar part the `App`. 12 | 13 | ### Building the `App` 14 | 15 | The way that electron works is it just uses Chrome to render a website but provides certain APIs to allow for access to certain system APIs (like access to the filesystem). As such the `App` is basically just a website hosted in its own application that a user can run. Typically when working with `webpack` for the web your end result is a javascript file that is your entry point. Much like web that will be our goal for our Electron app too. 16 | 17 | The first step to getting a working build is to get your javascript bundle built. I won't go into details around `webpack` configuration as that is a topic covered in all corners of the web ad nauseam. A good exmaple you can follow (which is actually Electron focused) is https://github.com/electron-react-boilerplate/electron-react-boilerplate. 18 | 19 | I would recommend having all the source files for `App` in some sort of `src` or `app` directory. The bundle that gets output is configurable so you can have that setup in whatever way you would like. 20 | 21 | ### Building the `Binary` 22 | 23 | Once you have a basic bundle for you application being built you will need to be able to package up binaries for all platforms you would like to target. For this I recommend using `electron-builder` (https://www.electron.build/) but you can do this with a few other methods. The first thing that you will need to setup is a entry html file. This file is the webpage that is actually rendered by Electron. This file should be located alongside your `App` code. Its job will be to do any setup needed in the browser and to also add the `App` bundle as a script tag. There is nothing particularly special about this html file. I would recommend using the one from the `electron-react-boilerplate` as a starting point for this html file. The next thing you will need is a bit of javascript to wire up some things for your application. These things include the menu, loading the actual html file and wiring up any events you might want to watch for on the applications window. I recommend calling this `main.js` or `main.dev.js`. This should typically be located alongside your `App` code. The main file included in `electron-react-boilerplate` is a really good, clean example of a main file. Once you have both of these things you will need to configure `webpack` to build the javascript file and generate a bundle. This is the final bundle you will need to generate for the app. 24 | 25 | Now that you have a lot of bundled javascript code you need to setup `electron-builder`. You will start by adding a `build` object to your `package.json`. Within this `build` object you can include a bunch of configuration for how the application will be bundled for each platform. I will cover some of the more common ones here but you can find a lot of other options here: https://www.electron.build/configuration/configuration. 26 | 27 | - `productName` - A string containing the name of the application 28 | - `appId` - A string that is app ID. This is needed for when you are creating the signing certificate for macOS 29 | - `files` - An array of files to include in the compiled application 30 | - `directories` 31 | - `buildResources` - The name of the folder containing resources (like an app icon) 32 | - `output` - Where to put the binaries 33 | - `publish` - Configuration for where to publish artifacts if you have `electron-builder` handle the release process (this guide does not but is technically an option). 34 | 35 | An example configuration from `reactotron`: 36 | 37 | ```json 38 | "build": { 39 | "productName": "Reactotron", 40 | "appId": "com.reactotron.app", 41 | "files": [ 42 | "src/dist/", 43 | "src/app.html", 44 | "src/main.prod.js", 45 | "src/main.prod.js.map", 46 | "package.json" 47 | ], 48 | "directories": { 49 | "buildResources": "resources", 50 | "output": "release" 51 | }, 52 | "publish": { 53 | "provider": "github", 54 | "owner": "infinitered", 55 | "repo": "reactotron", 56 | "private": false 57 | } 58 | } 59 | ``` 60 | 61 | The files must include the output of the `App` build, the html file for entry (named `app.html`), the output of the `main` build and the `package.json`. 62 | 63 | With all that configuration setup you should be ready to try and run your first build. Here are some helpful scripts to get you started: 64 | 65 | ```json 66 | "scripts": { 67 | "build": "concurrently \"yarn build-main\" \"yarn build-renderer\"", 68 | "build-main": "cross-env NODE_ENV=production webpack --config ./configs/webpack.config.main.prod.babel.js --colors", 69 | "build-renderer": "cross-env NODE_ENV=production webpack --config ./configs/webpack.config.renderer.prod.babel.js --colors", 70 | "package": "yarn build && electron-builder build", 71 | "package-all": "yarn build && electron-builder build -mwl", 72 | } 73 | ``` 74 | 75 | The `build` commands simply run webpack to build the bundles. The `package` command will take it a setup further and generate a binary for the operating system you are on. Sometimes that isn't enough and you will want to build for all the operating systems. That is where `package-all` comes in which includes a `-mwl` argument. `m` - macOS, `w` - Windows, `l` - Linux. 76 | 77 | ## CI Setup 78 | 79 | Now that we can build and create binaries we need to make it automated since no one wants to be responsible for manually building the application. This guide uses CircleCI as the CI service and makes the assumption that you know basic CircleCI configuration. Lets start with some code and break it down. Here is the CircleCI config for `reactotron`: 80 | 81 | ```yml 82 | # Javascript Node CircleCI 2.0 configuration file 83 | # 84 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details 85 | # 86 | 87 | defaults: &defaults 88 | macos: 89 | xcode: "10.1.0" 90 | working_directory: ~/repo 91 | 92 | version: 2 93 | jobs: 94 | build_and_test: 95 | <<: *defaults 96 | steps: 97 | - checkout 98 | - restore_cache: 99 | name: Restore node modules 100 | keys: 101 | - v1-dependencies-{{ checksum "package.json" }} 102 | # fallback to using the latest cache if no exact match is found 103 | - v1-dependencies- 104 | - run: 105 | name: Install dependencies 106 | command: yarn install 107 | - save_cache: 108 | name: Save node modules 109 | paths: 110 | - node_modules 111 | key: v1-dependencies-{{ checksum "package.json" }} 112 | - run: 113 | name: Build Apps 114 | command: yarn build 115 | 116 | releaseVersion: 117 | <<: *defaults 118 | steps: 119 | - checkout 120 | - restore_cache: 121 | name: Restore node modules 122 | keys: 123 | - v1-dependencies-{{ checksum "package.json" }} 124 | # fallback to using the latest cache if no exact match is found 125 | - v1-dependencies- 126 | - run: 127 | name: Install dependencies 128 | command: yarn install 129 | - save_cache: 130 | name: Save node modules 131 | paths: 132 | - node_modules 133 | key: v1-dependencies-{{ checksum "package.json" }} 134 | - run: 135 | name: Install Wine & RPM 136 | command: brew install wine && brew install rpm 137 | - run: 138 | name: Decode Certificates 139 | command: base64 -D -o Certificates.p12 <<< $ReactotronCerts 140 | - run: 141 | name: Install Gems 142 | command: bundle install 143 | - run: 144 | name: Install Cert 145 | command: bundle exec fastlane setup 146 | - run: 147 | name: Run Release 148 | command: yarn ci:publish 149 | 150 | workflows: 151 | version: 2 152 | test_and_release: 153 | jobs: 154 | - build_and_test: 155 | filters: 156 | branches: 157 | ignore: master 158 | - releaseVersion: 159 | context: ReactotronCerts 160 | filters: 161 | branches: 162 | only: master 163 | ``` 164 | 165 | There are only two jobs setup right now because I was having difficulty with getting the macOS build servers to use the caching mechinism provided by CircleCI. The first job is setup to only build the `App` to ensure that ic can. This job is used by all branches other then master and PRs. The second job is where the real magic happens. 166 | 167 | Here is the breakdown of the steps: 168 | - Restore node modules 169 | - We restore any cached `node_modules` (I am not convinced at this moment that this is actually working) 170 | - Install dependencies 171 | - Install all `node_modules` 172 | - Save node modules 173 | - Save the `node_modules` cache (again, not sure this works right now) 174 | - Install Wine & RPM 175 | - These are preqs for building Windows binaries 176 | - Decode Certificates 177 | - This is pulling in the certificates used to sign the macOS build. Most documentation suggests using `fastlane match` to manage the certificates but in this case I was not wanting to do that so I found a great article showing how to handle certificates without having to have a repo hosting the certificates. (https://medium.com/@m4rr/circleci-2-0-and-the-ios-code-signing-df434d0086e2) 178 | - Install Gems 179 | - Reactotron is setup with a few ruby gems. Lets install em. 180 | - Install Cert 181 | - This runs a fastlane lane that just installs the cert into the build servers keychain. You can find the script below. 182 | - Run Release 183 | - This runs the `semantic-release` which handles building the entire electron app and publishes it to GitHub. 184 | 185 | #### Fastlane Script 186 | ```ruby 187 | setup_circle_ci 188 | import_certificate( 189 | keychain_name: ENV["MATCH_KEYCHAIN_NAME"], 190 | keychain_password: ENV["MATCH_KEYCHAIN_PASSWORD"], 191 | certificate_path: 'Certificates.p12', 192 | certificate_password: ENV["CERTIFICATE_PASSWORD"] || "default", 193 | log_output: true 194 | ) 195 | ``` 196 | -------------------------------------------------------------------------------- /Continuous-Deployment-Setup-Hex.md: -------------------------------------------------------------------------------- 1 | ## CircleCI CD Setup - Hex 2 | 3 | TODO: Add instructions. 4 | -------------------------------------------------------------------------------- /Continuous-Deployment-Setup-NPM.md: -------------------------------------------------------------------------------- 1 | # CircleCI CD Setup - NPM 2 | 3 | This document shows the steps necessary to set up automatic continuous integration testing and automatic NPM deployment upon successfully merging a pull request. 4 | 5 | ## First Things First 6 | 7 | 1. Write tests 8 | - If the project already has tests, great. If not, write some. 9 | - They better pass! Tests are important because you don't want to be deploying broken code. 10 | - See [this](https://github.com/infinitered/ignite-webview/blob/master/test.js) for an example of a very simple testing setup 11 | 12 | ## CircleCI Setup 13 | 14 | 1. [Log into CircleCI](https://circleci.com/vcs-authorize/) with your Github account 15 | 2. Choose `infinitered` from the dropdown in the top left 16 | 3. Navigate to `Add Projects` on the left 17 | 4. Search for your repo 18 | 5. Choose `Set Up Project` 19 | - If you see `Contact Repo Admin`, you will need to be given admin permissions on CircleCI. See [Jamon](https://github.com/jamonholmgren) about this. 20 | 6. Set Up Project 21 | - Select `Linux` for the operating system and `Node` for the language 22 | 7. Copy the basic config.yml to `.circleci/config.yml`, commit your code changes and push to github `master` 23 | 8. Choose `Start building` to initiate the first CI build 24 | 9. Enable builds from forked pull requests. Go to project settings > Advanced Settings, then toggle on `Build forked pull requests` 25 | 26 | ## Configure Code for CircleCI 27 | 28 | 1. Create a folder in the project root named `.circleci`. 29 | 2. Create a file inside that folder named `config.yml` 30 | 3. Use the below template in that file. For simple Node projects, you likely won't have to change it. 31 | 4. If needed, see [configuration docs](https://circleci.com/docs) for additional configuration options. 32 | 33 | ```yaml 34 | defaults: &defaults 35 | docker: 36 | # Choose the version of Node you want here 37 | - image: cimg/node:14.19.1 38 | working_directory: ~/repo 39 | 40 | version: 2.1 41 | jobs: 42 | setup: 43 | <<: *defaults 44 | steps: 45 | - checkout 46 | - run: 47 | name: Install dependencies 48 | command: | 49 | yarn install 50 | 51 | tests: 52 | <<: *defaults 53 | steps: 54 | - checkout 55 | - run: 56 | name: Run tests 57 | command: yarn ci:test 58 | 59 | publish: 60 | <<: *defaults 61 | steps: 62 | - checkout 63 | - run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 64 | # Run semantic-release after all the above is set. 65 | - run: 66 | name: Publish to NPM 67 | command: yarn ci:publish # this will be added to your package.json scripts 68 | 69 | workflows: 70 | version: 2.1 71 | test_and_release: 72 | jobs: 73 | - setup 74 | - tests: 75 | requires: 76 | - setup 77 | - publish: 78 | requires: 79 | - tests 80 | filters: 81 | branches: 82 | only: master 83 | ``` 84 | 85 | If your project requires global NPM packages (for example, `npm i -g react-native`) or `npm link`, add those steps to the `tests` block. This is more common when testing CLI packages. 86 | 87 | ```yml 88 | - run: 89 | name: Change Permissions 90 | command: sudo chown -R $(whoami) /usr/local 91 | - run: 92 | name: Install React Native CLI 93 | command: npm i -g react-native-cli 94 | - run: 95 | name: Link Ignite CLI 96 | command: npm link 97 | - run: 98 | name: Run tests 99 | command: yarn ci:test # this command will be added to/found in your package.json scripts 100 | ``` 101 | 102 | 5. Make sure the test script is added to your `package.json` 103 | 104 | ```json 105 | { 106 | ... 107 | "scripts": { 108 | ... 109 | "ci:test": "" <<-- if you don't already have this one 110 | }, 111 | ... 112 | } 113 | ``` 114 | 115 | ## Add Semantic Release 116 | 117 | 1. Install semantic-release and git plugin as dev dependencies 118 | - `yarn add --dev semantic-release @semantic-release/git` 119 | 2. Add a `publish` job to the `jobs:` section of your `.circleci/config.yml`, like so: 120 | 121 | ```yml 122 | defaults: ... 123 | 124 | version: 2.1 125 | jobs: 126 | setup: ... 127 | 128 | tests: ... 129 | 130 | publish: 131 | <<: *defaults 132 | steps: 133 | - checkout 134 | - run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 135 | - restore_cache: 136 | name: Restore node modules 137 | keys: 138 | - v1-dependencies-{{ checksum "package.json" }} 139 | # fallback to using the latest cache if no exact match is found 140 | - v1-dependencies- 141 | # Run semantic-release after all the above is set. 142 | - run: 143 | name: Publish to NPM 144 | command: yarn ci:publish # this will be added to your package.json scripts 145 | 146 | 147 | workflows: 148 | version: 2.1 149 | test_and_release: 150 | jobs: 151 | - setup 152 | - tests: 153 | requires: 154 | - setup 155 | - publish: 156 | requires: 157 | - tests 158 | filters: 159 | branches: 160 | only: master 161 | ``` 162 | 163 | 3. Add publish scripts to your `package.json`: 164 | 165 | ```json 166 | { 167 | ... 168 | "scripts": { 169 | ... 170 | "ci:test": "", 171 | "ci:publish": "semantic-release" 172 | }, 173 | ... 174 | } 175 | ``` 176 | 177 | 4. Add release configuration to your `package.json`: 178 | 179 | ```json 180 | { 181 | ... 182 | "release": { 183 | "plugins": [ 184 | "@semantic-release/commit-analyzer", 185 | "@semantic-release/release-notes-generator", 186 | "@semantic-release/npm", 187 | "@semantic-release/github", 188 | [ 189 | "@semantic-release/git", 190 | { 191 | "assets": "package.json", 192 | "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" 193 | } 194 | ] 195 | ] 196 | } 197 | ... 198 | } 199 | ``` 200 | 201 | 5. Add `NPM_TOKEN` and `GITHUB_TOKEN` entries to env vars on CircleCI ([https://app.circleci.com/settings/project/github/infinitered/YOURPROJECT/environment-variables](https://app.circleci.com/settings/project/github/infinitered/YOURPROJECT/environment-variables)). You should be able to find these in our team 1password under `CircleCI CI/CD Semantic Release Tokens`. 202 | - If you need to make a new `NPM_TOKEN`, go here: [https://www.npmjs.com/settings/YOURUSER/tokens/new](https://www.npmjs.com/settings/YOURUSER/tokens/new) -- use the *Automation* type 203 | - If you need to make a new `GITHUB_TOKEN`, go to https://github.com/settings/tokens/new and create a new one with `repo` access. More info about [semantic-release authentication here](https://github.com/semantic-release/semantic-release/blob/6a8eede96f9e61f22ddbf885db7947798b1bf55c/docs/usage/ci-configuration.md#authentication). 204 | 6. Add the `Circle CI` Github team (Including the `infinitered-circleci` user) to your repo (https://github.com/infinitered/YOURPROJECT/settings/collaboration) 205 | 7. Check git tags `git tag --merged master`. Ensure that what shows up there matches what you expect to see. 206 | - Sometimes this doesn't match what Github shows. So, you need to do a manual release and be sure to tag it in git with `git tag -a v1.4.0 -m "my version 1.4.0"`. Then push the tag up to github with `git push --tags`. Talk to Carlin or Jamon about this if you're confused. 207 | - If you haven't created any tags yet, there will be no output. If you publish without any tags, it will default to `1.0.0` which is probably not what you want. 208 | 209 | ## Manual Release 210 | 211 | 1. If you haven't published a manual release yet, go ahead and do so now. `yarn publish` will do the job. 212 | 2. Create a Github release (and tag). https://github.com/infinitered/YOUR_REPO/releases (Draft a new release) 213 | 3. Pull down the tag with `git fetch --tags`, and then re-run `git tag --merged master` to ensure the tag is up on Github 214 | 215 | ## Test Automatic Release 216 | 217 | 1. Create a new empty commit with `git commit --allow-empty -m "fix(ci): Testing CI release"` 218 | 2. Push it to `master` (or do a pullrequest and merge it in) 219 | 3. CircleCI should deploy a new version to NPM 220 | - NOTE: If CircleCI does the wrong thing and a version goes up to NPM that you don't want, just run `npm unpublish YOURPROJECT@1.4.1` or whatever version. If you are able to do this within 15 minutes NPM will remove the version. Beyond 15 minutes all you can do is use `npm deprecate` and deploy a new version. 221 | 222 | ## Commit message format 223 | 224 | Format your commit messages like so to get the desired version bump: 225 | 226 | | Format | Version bump | Example | 227 | |--------|--------------|---------| 228 | | `fix/refactor(feature): Message` | Patch-level, e.g. `1.0.3` to `1.0.4` | `fix(wkwebview): Fixed issue #12 - crash when navigating` | 229 | | `feat(feature): Message` | Minor/Feature-level, e.g. `1.0.3` to `1.1.0` | `feat(android): Added file upload` | 230 | | `fix/feat/perf(feature):` (and in body) `BREAKING CHANGE: Message` | Major/Breaking-level, e.g. `1.0.3` to `2.0.0` | `fix(ios): \nBREAKING CHANGE: Removed UIWebView` | 231 | 232 | Each release will include a changelog: 233 | 234 | ![image](https://user-images.githubusercontent.com/1479215/48959809-cb13df00-ef1c-11e8-9281-579df168c0e7.png) 235 | 236 | Semantic Release will also comment on any issues that are fixed in a particular release. 237 | 238 | TIP: If you set up your repo to only allow `Squash & Merge` on pull request, you will get a chance to edit the commit message and release notes and cut a new release. 239 | 240 | ![image](https://user-images.githubusercontent.com/1479215/48959734-31e4c880-ef1c-11e8-96db-4e854a8edc1d.png) 241 | 242 | ## Notes 243 | 244 | 1. You can't have your `master` branch "protected". [Go here to see if it is.](https://github.com/infinitered/ignite/settings/branches) 245 | 2. If you run into problems where it doesn't seem to think there are any changes to push, it generally means something is messed up with your Github tags. Delete any errant tags and do a manual deploy. 246 | 3. You may need to [add the following ENV variables](https://discuss.circleci.com/t/trying-to-push-change-back-to-github-please-tell-me-who-you-are/18185/3) to CircleCI if you are getting an error like this: 247 | 248 | ``` 249 | *** Please tell me who you are. 250 | 251 | Run 252 | 253 | git config --global user.email "you@example.com" 254 | git config --global user.name “Your Name” 255 | 256 | to set your account’s default identity. 257 | ``` 258 | 259 | ENV vars to set: `EMAIL`, `GIT_AUTHOR_NAME`, `GIT_COMMITTER_NAME` 260 | 261 | ## Questions? Issues? 262 | 263 | Open an issue in this repo and tag @carlinisaacson and @jamonholmgren. 264 | 265 | If you have a fix for one of these instructions, just edit this file on Github (:pencil: top right) and commit it directly to `master`, no pull request needed. 266 | -------------------------------------------------------------------------------- /Continuous-Deployment-Setup-React-Native.md: -------------------------------------------------------------------------------- 1 | # CircleCI CD Setup - React Native 2 | 3 | This document shows the steps necessary to set up CircleCI automatic continuous integration testing and automatic Fastlane beta builds upon successfully merging a pull request. 4 | 5 | Note: there is some experimental information about using Github Actions at [the end of the document](#Github-Actions-Setup). 6 | 7 | ## First Things First 8 | 9 | 1. Write tests 10 | 11 | - If the project already has tests, great. If not, write some. 12 | - They better pass! Tests are important because you don't want to be deploying broken code. 13 | - See [this](https://github.com/infinitered/ChainReactApp2019) for an example of how we typically setup tests for a React Native app. 14 | 15 | # CircleCI Setup 16 | 17 | 1. [Log into CircleCI](https://circleci.com/vcs-authorize/) with your Github account 18 | 2. Choose `infinitered` from the dropdown in the top left 19 | 3. Navigate to `Add Projects` on the left 20 | 4. Search for your repo 21 | 5. Choose `Set Up Project` 22 | 23 | - If you see `Contact Repo Admin`, you will need to be given admin permissions on CircleCI. See [Jamon](https://github.com/jamonholmgren) about this. 24 | 25 | 6. Set Up Project 26 | 27 | - Select `macOS` for the operating system and `Other` for the language 28 | 29 | 7. Copy the basic config.yml to `.circleci/config.yml`, commit your code changes and push to github `master` 30 | 8. Choose `Start building` to initiate the first CI build. This build will fail. That's ok. We will update the config in the next step. 31 | 9. Enable builds from forked pull requests. Go to project settings > Advanced Settings, then toggle on `Build forked pull requests` 32 | 10. If this project is open-source, you'll want to make sure the open-source setting is enabled to allow for macOS builds. Go to project settings > Advanced Settings, then toggle `Free and Open Source`. 33 | 34 | ## Continuous Integration 35 | 36 | 1. Create a folder in the project root named `.circleci`. 37 | 2. Create a file inside that folder named `config.yml` 38 | 3. Use the below template in that file. 39 | 4. If needed, see [configuration docs](https://circleci.com/docs/2.0/config-intro/#section=configuration) for additional configuration options. 40 | _(Here is a complete [config.yml](https://github.com/infinitered/open-source/blob/master/config.example.yml) with CI and CD steps completed)_ 41 | 42 | ```yaml 43 | defaults: &defaults 44 | docker: 45 | # Choose the version of Node you want here 46 | - image: circleci/node:10.11 47 | working_directory: ~/repo 48 | 49 | version: 2 50 | jobs: 51 | setup: 52 | <<: *defaults 53 | steps: 54 | - checkout 55 | - restore_cache: 56 | keys: 57 | - v1-dependencies-node-{{ checksum "package.json" }} 58 | # fallback to using the latest cache if no exact match is found 59 | - v1-dependencies-node- 60 | - run: 61 | name: Install dependencies 62 | command: yarn install 63 | - save_cache: 64 | name: Save node modules 65 | paths: 66 | - node_modules 67 | key: v1-dependencies-node-{{ checksum "package.json" }} 68 | 69 | tests: 70 | <<: *defaults 71 | steps: 72 | - checkout 73 | - restore_cache: 74 | keys: 75 | - v1-dependencies-node-{{ checksum "package.json" }} 76 | # fallback to using the latest cache if no exact match is found 77 | - v1-dependencies-node- 78 | - run: 79 | name: Run tests 80 | command: yarn ci:test # this command will be added to/found in your package.json scripts 81 | 82 | workflows: 83 | version: 2 84 | test_and_release: 85 | jobs: 86 | - setup 87 | - tests: 88 | requires: 89 | - setup 90 | ``` 91 | 92 | 5. Make sure the test script is added to your `package.json` 93 | 94 | ```json 95 | { 96 | ... 97 | "scripts": { 98 | ... 99 | "ci:test": "" <<-- if you don't already have this one 100 | }, 101 | ... 102 | } 103 | ``` 104 | 105 | ## iOS Continuous Deployment 106 | 107 | ### Add Fastlane 108 | 109 | 1. Before you can add continuous deployment, you'll need to setup Fastlane and Match to sign and deploy your app. You can follow these blog posts 110 | to get setup! 111 | 112 | - [Releasing on iOS with Fastlane](https://shift.infinite.red/simple-react-native-ios-releases-4c28bb53a97b) 113 | 114 | Make sure you get to the point of being able to run: 115 | 116 | ``` 117 | fastlane ios beta 118 | ``` 119 | 120 | 2. In your Fastfile, add: 121 | 122 | ```Ruby 123 | before_all do 124 | setup_circle_ci 125 | end 126 | ``` 127 | 128 | 3. In your `beta` lane, make sure you have included a command that bumps the build number prior to building, and then commits the build number after building. Example: 129 | 130 | ```Ruby 131 | PROJECT = "YourProject" 132 | XCODE_PROJECT = "#{PROJECT}.xcodeproj" 133 | 134 | lane :beta do 135 | 136 | increment_build_number(xcodeproj: "./#{XCODE_PROJECT}") 137 | 138 | match(type: "appstore") 139 | build_ios_app( 140 | scheme: PROJECT, 141 | workspace: "./YourProject.xcworkspace", 142 | xcargs: "-UseNewBuildSystem=NO -allowProvisioningUpdates", 143 | export_method: "app-store" 144 | ) 145 | 146 | # Ship it! 147 | upload_to_testflight( 148 | skip_waiting_for_build_processing: true 149 | ) 150 | 151 | commit_version_bump( 152 | xcodeproj: "./#{XCODE_PROJECT}", 153 | ignore: /tvOS/, 154 | force: true, 155 | message: "[skip ci] Version bump" 156 | ) 157 | end 158 | ``` 159 | 160 | If you prefer, you can also do these steps as separate fastlane commands, just make sure to include a `- run:` entry for each one in `config.yml`. 161 | 162 | ### Setting up CircleCI to Run Fastlane 163 | 164 | Check out [this blog](https://medium.com/@odedre/circle-ci-v2-react-native-project-build-release-setup-ce4ef31209d0) for lots of helpful tips. 165 | 166 | 1. Make sure CircleCI has all the credentials to run your fastlane scripts: 167 | 168 | 1. Go into the Settings screen for your project on CircleCI 169 | 2. Under "Build Settings", click on "Environment Variables" (https://circleci.com/gh/infinitered/YOURPROJECT/edit#env-vars) 170 | 3. Click "Add Variable" 171 | 4. Set `FASTLANE_USER` to the email address of your your Apple App Store Connect / Dev Portal user. For Infinite Red projects, this is probably: `admin@infinite.red` 172 | 5. Do this for all of the variables listed [here](https://github.com/fastlane/docs/blob/950c6f42231d86b5187d2cfdcab2a6c81d0f61dc/docs/best-practices/continuous-integration.md#environment-variables-to-set) 173 | 174 | **Note**: If your dev portal user does not have 2-Factor Auth turned on (`admin@infinite.red` does not), you DO NOT need to set `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD`. Including this variabe when your account does need it will result in errors during TestFlight upload. 175 | 176 | You can find more info from the [Fastlane Docs](https://github.com/fastlane/docs/blob/950c6f42231d86b5187d2cfdcab2a6c81d0f61dc/docs/best-practices/continuous-integration.md), and from the [CircleCI codesigning docs](https://circleci.com/docs/2.0/ios-codesigning/) 177 | 178 | 1. Add `GITHUB_TOKEN` to env vars on CircleCI (https://circleci.com/gh/infinitered/YOURPROJECT/edit#env-vars). You should be able to find these in our team 1password under `CircleCI CI/CD Semantic Release Tokens`. 179 | 180 | - If you need to make a new `GITHUB_TOKEN`, go to https://github.com/settings/tokens/new and create a new one with `repo` access. 181 | 182 | 2. Add the `Circle CI` Github team (Including the `infinitered-circleci` user) to your repo (https://github.com/infinitered/YOURPROJECT/settings/collaboration) with write access. 183 | 184 | 3. Add the `Circle CI` Github team as a read-only collaborator to the private match certificates repo. 185 | 186 | 4. Log in to GitHub/CircleCI as the CI user (`ci@infinite.red`, the credentials are in 1Password). Then in CircleCI, go to Project Settings > Checkout SSH keys (https://circleci.com/gh/infinitered/YOURPROJECT/edit#checkout) and add a new user key. This will allow CircleCI to clone the certs repo in order to sign your app. 187 | 188 | 5. Go to Project Settings > Checkout SSH Keys and add a new deploy key. You will copy the fingerprint and paste into the `config.yml` example below in the `add_ssh_keys` section (there should be `"`s around it) 189 | 190 | 6. Add a script to your `package.json` called `ci:setup`. This will run any necessary shell commands to prepare your project for building. For example, creating private files like `.env`. If you don't any additional setup, you can leave this command as "", or remove the `ci:setup` step from the `config.yml` example below. 191 | 192 | ```json 193 | { 194 | ... 195 | "scripts": { 196 | ... 197 | "ci:setup": "touch .env && echo \"ENV_VAR=\"$ENV_VAR >> .env", 198 | }, 199 | ... 200 | } 201 | ``` 202 | 203 | Note: `react-native-dotenv` throws errors if there is not a `.env` present with the variables it expects. However, if you don't want to put secret values in this script (you shouldn't), then you can add them directly to CircleCI under Project Settings > Environment Variables. Then you can reference them in this script as `$ENV_VAR`. 204 | 205 | 7. Add `mac` configuration and `deploy_ios` job to your CircleCI `config.yml`: 206 | 207 | NOTE: The macOS boxes currently come with Node 11.0, with no apparent way to change the version. This shouldn't be a huge problem. One known issue is with `upath`, which is a deep dependency of react-native. If you encounter errors related to `upath` requiring a lower version of Node, just make sure it is at `1.1.0`, and not `1.0.4` in your `yarn.lock`. See https://github.com/airbnb/enzyme/issues/1637#issuecomment-397327562. 208 | 209 | ```yaml 210 | defaults: ... 211 | 212 | mac: &mac 213 | macos: 214 | xcode: "10.1.0" 215 | working_directory: ~/repo 216 | environment: 217 | FL_OUTPUT_DIR: output 218 | shell: /bin/bash --login -o pipefail 219 | 220 | version: 2 221 | jobs: 222 | setup: ... 223 | 224 | tests: ... 225 | 226 | deploy_ios: 227 | <<: *mac 228 | steps: 229 | - checkout 230 | - add_ssh_keys: 231 | fingerprints: — “SSH_FINGERPRINT_HERE” 232 | - run: 233 | name: Git configuration 234 | command: git config user.email "ci@infinite.red" && git config user.name "CircleCI" 235 | - run: 236 | name: Set upstream branch 237 | command: git branch --set-upstream-to origin ${CIRCLE_BRANCH} 238 | # Node modules 239 | - restore_cache: 240 | name: Restore node modules 241 | keys: 242 | - v1-dependencies-mac-{{ checksum "package.json" }} 243 | # fallback to using the latest cache if no exact match is found 244 | - v1-dependencies-mac- 245 | - run: 246 | name: Install dependencies 247 | command: NOYARNPOSTINSTALL=1 yarn install 248 | - save_cache: 249 | name: Save node modules 250 | paths: 251 | - node_modules 252 | key: v1-dependencies-mac-{{ checksum "package.json" }} 253 | 254 | # Cocoapods 255 | - run: 256 | name: Fetch CocoaPods Specs 257 | command: | 258 | curl https://cocoapods-specs.circleci.com/fetch-cocoapods-repo-from-s3.sh | bash -s cf 259 | - run: 260 | working_directory: ios 261 | name: Install CocoaPods 262 | command: pod install --verbose 263 | 264 | # Gems 265 | - restore_cache: 266 | name: Restore gems 267 | key: bundle-v1-{{ checksum "ios/Gemfile.lock" }}-{{ arch }} 268 | - run: 269 | name: Bundle Install 270 | command: bundle install 271 | working_directory: ios 272 | - save_cache: 273 | key: bundle-v1-{{ checksum "ios/Gemfile.lock" }}-{{ arch }} 274 | paths: 275 | - vendor/bundle 276 | 277 | # Misc setup 278 | - run: 279 | name: Misc setup 280 | command: yarn ci:setup 281 | 282 | # Git grooming 283 | - run: 284 | name: Pull latest git 285 | command: git stash && git pull && git stash pop 286 | 287 | # Run Fastlane 288 | - run: 289 | working_directory: ios 290 | name: Fastlane 291 | command: bundle exec fastlane ios beta 292 | 293 | # Git cleanup 294 | - run: 295 | name: Pull latest git 296 | command: git stash && git pull && git stash pop 297 | - run: 298 | name: Push version bump commit 299 | command: git push 300 | - store_artifacts: 301 | path: output 302 | 303 | workflows: 304 | version: 2 305 | test_and_release: 306 | jobs: 307 | - setup 308 | - tests: 309 | requires: 310 | - setup 311 | - deploy_ios: 312 | filters: 313 | branches: 314 | only: master 315 | ``` 316 | 317 | ## Troubleshooting tips 318 | 319 | - If you need to debug failed builds, you can use the "Rebuild with SSH" option in CircleCI. See https://circleci.com/docs/2.0/ssh-access-jobs/ for more info. 320 | 321 | - Tip: make sure you are logged in to Github/CircleCI as yourself (not the CI user) when you hit the button to rebuild with SSH. 322 | 323 | - If you get a vague error saying `File main.jsbundle does not exist`, that means there was an error while building the app and you can view the more detailed message by inspecting the log files with the following command (while in SSH mode). Increase the number of lines from 50 as needed. 324 | 325 | ``` 326 | tail -50 ios/output/buildlogs/gym/YourProject-YourProject.log 327 | ``` 328 | 329 | # Github Actions Setup 330 | 331 | Here is some experimental information for Github Actions CI. Please add to it as you learn more about Github Actions! 332 | 333 | ## Github Actions YML File 334 | 335 | ```yml 336 | name: RN App CI 337 | on: [push] 338 | jobs: 339 | build: 340 | runs-on: macos-latest 341 | env: 342 | CI: true 343 | NODE_ENV: development 344 | steps: 345 | - uses: actions/checkout@v1 346 | - name: Cache my-app node modules 347 | uses: actions/cache@v1 348 | with: 349 | path: my-app/node_modules 350 | key: ${{ runner.OS }}-build-${{ hashFiles('**/my-app/yarn.lock') }} 351 | restore-keys: | 352 | ${{ runner.OS }}-build-${{ env.cache-name }}- 353 | ${{ runner.OS }}-build- 354 | ${{ runner.OS }}- 355 | - name: Install dependencies 356 | run: | 357 | yarn install 358 | - name: Run unit tests 359 | run: | 360 | yarn test:unit 361 | - name: Install cocoapods 362 | run: | 363 | cd my-app/ios 364 | pod install --repo-update 365 | - name: Run e2e tests 366 | run: | 367 | cd my-app 368 | yarn test:e2e:build --configuration="ios.sim.debug" 369 | yarn test:e2e --configuration="ios.sim.debug" 370 | ``` 371 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Infinite Red Open Source Dashboard 2 | 3 | Hey there! Welcome! 4 | 5 | This repo contains markdown files with info and guides for [Infinite Red](https://infinite.red)'s open source libraries and tooling. 6 | 7 | We're glad you're here and feel free to poke around. If you notice an issue, feel free to submit a PR. You can easily edit Markdown files right in Github by clicking the little :pencil: icon on the top right. 8 | 9 | ## Infinite Red Websites 10 | 11 | [![infinite.red](https://img.shields.io/website-up-down-green-red/https/infinite.red.svg?label=infinite.red)](https://infinite.red) 12 | 13 | ## Infinite Red Open Source Projects 14 | 15 | This list is currently being fleshed out. There are several missing projects and the status / CI / CD is not fully validated. We'll be working on this as we have time. 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 232 | 233 | 234 | 235 |
NameStatusCICDBuildVersion
Ignite CLIActive 36 | 37 | CircleCI 38 | 39 | version
Ignite BowserMaintenance 49 | 50 | CircleCI 51 | 52 | version
ReactotronActive 62 | 63 | CircleCI 64 | 65 | version
Reactotron Core ClientActive 75 | 76 | CircleCI 77 | 78 | version
Reactotron Core ServerActive 88 | 89 | CircleCI 90 | 91 | version
Reactotron React NativeActive 101 | 102 | CircleCI 103 | 104 | version
Reactotron React JSActive 114 | 115 | CircleCI 116 | 117 | version
Reactotron MSTActive 127 | 128 | CircleCI 129 | 130 | version
Reactotron ApisauceActive 140 | 141 | CircleCI 142 | 143 | version
Reactotron ReduxActive 154 | 155 | CircleCI 156 | 157 | version
Reactotron Redux SagaActive 167 | 168 | CircleCI 169 | 170 | version
GluegunActive 180 | 181 | CircleCI 182 | 183 | version
SolidarityActiveversion
Solidarity React NativeActive 202 | 203 | CircleCI 204 | 205 | version
apisauceMaintenance 215 | 216 | CircleCI 217 | 218 | version
RamdasauceMaintenance 228 | 229 | CircleCI 230 | 231 | version
236 | 237 | Legend: ✅ = Setup, ❌ = Not setup, 🚧 = Currently under construction, ❓ = Unknown status, ❎ = Not applicable 238 | 239 | ## Guide to squash commits 240 | 241 | *Guide to squash messages for auto deployment* 242 | 243 | Each of these keywords must be followed by a colon. They can also be followed by a parenthetical which will add that parenthetical word in *bold* in front of the message in the changelog. E.g. `fix: Updated gluegun` or `fix(deps): Updated gluegun` are both valid. 244 | 245 | #### Skip CI: `[skip ci]` 246 | 247 | This will not run the deployment script. I usually put it in the _body_ of the commit message, not the title (first line). 248 | 249 | I use this a lot to "group" multiple fixes in one release. So I might merge 3 PRs, have the first 2 have `[skip ci]`, and the third I let the CI run, so it gathers up all 3 changes into one changelog and releases once. 250 | 251 | #### Non-release changes 252 | 253 | **Code base maintenance: `chore: Message` 254 | **Documentation:** `docs: Message` 255 | 256 | These will not add to the changelog nor (by itself) trigger a release. However, be aware that if there are previous `[skip ci]` changes, you _will_ trigger a release with _all_ of the unreleased `fix` or `feat` changes. This is sometimes useful if you merge a ton of PRs with `[skip ci]` and want to trigger a release: just do an empty commit like so: 257 | 258 | ``` 259 | git commit --allow-empty -m "chore(ci): Trigger release" 260 | ``` 261 | 262 | ... and push directly to master. 263 | 264 | #### Patch-level release: `fix: Message` 265 | 266 | This will add to the "Bugfixes" section of the changelog and trigger a release (unless `[skip ci]`). 267 | 268 | #### Minor version release: `feat: Message` 269 | 270 | This will add to the "Features" section of the changelog and trigger a release (unless `[skip ci]`). 271 | 272 | #### Major version release: 273 | 274 | In your commit message _body_ (not title), whether it's `fix` or `feat`, include the following: 275 | 276 | ``` 277 | BREAKING CHANGE: Describe the breaking change here 278 | ``` 279 | 280 | So an example: 281 | 282 | ![breaking change example](https://user-images.githubusercontent.com/1479215/57470446-b19def80-723d-11e9-85e4-400bf65bf32a.png) 283 | 284 | #### Gotchas 285 | 286 | 1. Don't trigger more than one release at a time. One or both will fail. 287 | 2. Do _not_ put `BREAKING CHANGES:`, it doesn't work. :sadpanda: Only `BREAKING CHANGE:` (with the colon). And it _must_ be in the commit message body, not the title. 288 | 3. I've never released a major version without some sort of hiccup. Maybe next time? 289 | 290 | ## Infinite Red Guides 291 | 292 | - [Continuous Deployment Setup - NPM](./Continuous-Deployment-Setup-NPM.md) 293 | - [Continuous Deployment Setup - React Native](./Continuous-Deployment-Setup-React-Native.md) 294 | - [Continuous Deployment Setup - Hex](./Continuous-Deployment-Setup-Hex.md) 295 | -------------------------------------------------------------------------------- /config.example.yml: -------------------------------------------------------------------------------- 1 | # Javascript Node CircleCI 2.0 configuration file 2 | # 3 | # Check https://circleci.com/docs/2.0/language-javascript/ for more details 4 | # 5 | 6 | defaults: &defaults 7 | docker: 8 | # Choose the version of Node you want here 9 | - image: circleci/node:10.11 10 | working_directory: ~/repo 11 | 12 | version: 2 13 | jobs: 14 | setup: 15 | <<: *defaults 16 | steps: 17 | - checkout 18 | - restore_cache: 19 | name: Restore node modules 20 | keys: 21 | - v1-dependencies-{{ checksum "package.json" }} 22 | # fallback to using the latest cache if no exact match is found 23 | - v1-dependencies- 24 | - run: 25 | name: Install dependencies 26 | command: | 27 | yarn install 28 | - save_cache: 29 | name: Save node modules 30 | paths: 31 | - node_modules 32 | key: v1-dependencies-{{ checksum "package.json" }} 33 | 34 | 35 | tests: 36 | <<: *defaults 37 | steps: 38 | - checkout 39 | - restore_cache: 40 | name: Restore node modules 41 | keys: 42 | - v1-dependencies-{{ checksum "package.json" }} 43 | # fallback to using the latest cache if no exact match is found 44 | - v1-dependencies- 45 | - run: 46 | name: Install React Native CLI and Ignite CLI 47 | command: | 48 | sudo npm i -g ignite-cli react-native-cli 49 | - run: 50 | name: Run tests 51 | command: yarn ci:test # this command will be added to/found in your package.json scripts 52 | 53 | publish: 54 | <<: *defaults 55 | steps: 56 | - checkout 57 | - run: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> ~/.npmrc 58 | - restore_cache: 59 | name: Restore node modules 60 | keys: 61 | - v1-dependencies-{{ checksum "package.json" }} 62 | # fallback to using the latest cache if no exact match is found 63 | - v1-dependencies- 64 | # Run semantic-release after all the above is set. 65 | - run: 66 | name: Publish to NPM 67 | command: yarn ci:publish # this will be added to your package.json scripts 68 | 69 | workflows: 70 | version: 2 71 | test_and_release: 72 | jobs: 73 | - setup 74 | - tests: 75 | requires: 76 | - setup 77 | - publish: 78 | requires: 79 | - tests 80 | filters: 81 | branches: 82 | only: master --------------------------------------------------------------------------------