├── .gitignore ├── backend ├── stuff_to_read.md ├── pundit.md ├── sidekiq_config.md └── alexa_tutorial.md ├── ios ├── danger.png ├── viewmodels │ ├── profile.png │ ├── review.png │ ├── Overview.md │ ├── view-model-motivation.md │ └── view-model-reuse.md ├── stuff_to_read.md ├── Estimation_Playbook_Images │ ├── image1.png │ ├── image2.png │ ├── image3.png │ ├── image4.png │ ├── image5.png │ ├── image6.png │ └── image7.png ├── ios_recommended_tools.md ├── ios_swift_4_transition_checklist ├── ios_code_coverage.md ├── ios_app_submission_checklist.md ├── common_cocoapods.md ├── ios_inspecting_an_ipa_file.md ├── ios_project_setup.md ├── ios_danger.md ├── build_and_install_errors.md ├── cocoapods_best_practices.md ├── cocoapods_processes.md ├── ios_estimation_playbook.md ├── firebase.md ├── rxswift_sherpa.md ├── MVVM_Testing.md └── rxswift_by_example.md ├── android ├── images │ ├── code-style.png │ └── pr-coverage-comment.png ├── tidbits │ ├── README.md │ ├── mock_singleton_in_kotlin.md │ └── complete_code_coverage_for_nullable_var.md ├── stuff_to_read.md ├── architecture_articles.md ├── android_studio_plugins.md ├── android_pr_coverage.md ├── code_style.md ├── third_party_libs.md ├── android_project_creation.md ├── android_cobertura.md └── android_jenkins.md ├── git ├── images │ └── why-rebase │ │ ├── merge-flow.png │ │ └── rebase-flow.png ├── why_rebase.md ├── commit_message_guide.md ├── git_cookbook.md ├── versioning-faq.md └── git_workflow_quick_reference.md ├── webservices ├── images │ └── react-testing │ │ ├── meal-event-1.png │ │ ├── meal-event-2.png │ │ └── meal-event-3.png ├── gotchas │ ├── rails.md │ ├── javascript.md │ └── gems.md ├── miscellaneous_best_practices.md ├── caching.md ├── react_deployment.md ├── setup.md ├── oauth-jwt.md ├── deployment.md ├── css │ └── styling_guidelines.md ├── ruby │ └── service_objects.md ├── mean_stack_glossary.md └── react_and_recompose.md ├── mobile_api_guidance.md ├── development_principles.md ├── readme-template.md ├── README.md └── pull_request_guidelines.md /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | .DS_Store 4 | -------------------------------------------------------------------------------- /backend/stuff_to_read.md: -------------------------------------------------------------------------------- 1 | # Backend Resources 2 | 3 | TODO 4 | -------------------------------------------------------------------------------- /ios/danger.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/ios/danger.png -------------------------------------------------------------------------------- /ios/viewmodels/profile.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/ios/viewmodels/profile.png -------------------------------------------------------------------------------- /ios/viewmodels/review.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/ios/viewmodels/review.png -------------------------------------------------------------------------------- /android/images/code-style.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/android/images/code-style.png -------------------------------------------------------------------------------- /ios/stuff_to_read.md: -------------------------------------------------------------------------------- 1 | # iOS Resources 2 | 3 | [App Store submission checklist](ios_app_submission_checklist.md) 4 | 5 | -------------------------------------------------------------------------------- /git/images/why-rebase/merge-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/git/images/why-rebase/merge-flow.png -------------------------------------------------------------------------------- /git/images/why-rebase/rebase-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/git/images/why-rebase/rebase-flow.png -------------------------------------------------------------------------------- /android/images/pr-coverage-comment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/android/images/pr-coverage-comment.png -------------------------------------------------------------------------------- /ios/Estimation_Playbook_Images/image1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/ios/Estimation_Playbook_Images/image1.png -------------------------------------------------------------------------------- /ios/Estimation_Playbook_Images/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/ios/Estimation_Playbook_Images/image2.png -------------------------------------------------------------------------------- /ios/Estimation_Playbook_Images/image3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/ios/Estimation_Playbook_Images/image3.png -------------------------------------------------------------------------------- /ios/Estimation_Playbook_Images/image4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/ios/Estimation_Playbook_Images/image4.png -------------------------------------------------------------------------------- /ios/Estimation_Playbook_Images/image5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/ios/Estimation_Playbook_Images/image5.png -------------------------------------------------------------------------------- /ios/Estimation_Playbook_Images/image6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/ios/Estimation_Playbook_Images/image6.png -------------------------------------------------------------------------------- /ios/Estimation_Playbook_Images/image7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/ios/Estimation_Playbook_Images/image7.png -------------------------------------------------------------------------------- /webservices/images/react-testing/meal-event-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/webservices/images/react-testing/meal-event-1.png -------------------------------------------------------------------------------- /webservices/images/react-testing/meal-event-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/webservices/images/react-testing/meal-event-2.png -------------------------------------------------------------------------------- /webservices/images/react-testing/meal-event-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IntrepidPursuits/sherpa/HEAD/webservices/images/react-testing/meal-event-3.png -------------------------------------------------------------------------------- /ios/ios_recommended_tools.md: -------------------------------------------------------------------------------- 1 | #iOS Recommended Tools 2 | Useful tools recommended for every iOS developer to use. 3 | 4 | ##Breakpoints 5 | [Xcode User Breakpoints](https://www.natashatherobot.com/xcode-debugging-user-breakpoints/) 6 | [Useful collection of Xcode User breakpoints](https://gist.github.com/gbernady/1fc53d70587b9064f84c) 7 | -------------------------------------------------------------------------------- /webservices/gotchas/rails.md: -------------------------------------------------------------------------------- 1 | ## Gotchas with Rails 2 | 3 | ### I made a change to config or an initializer and it's not reflected in my dev environment! :sob: 4 | 5 | The culprit may be [spring](https://github.com/rails/spring), Rails' application preloader. Sometimes it's bad at its job. Run `spring stop` and see if that fixes the problem. 6 | -------------------------------------------------------------------------------- /android/tidbits/README.md: -------------------------------------------------------------------------------- 1 | # Tidbits 2 | A collection of random (but helpful!) bits of Android/Java/Kotlin knowledge 3 | 4 | # Table of Contents 5 | 1. Kotlin 6 | * [How to get complete code coverage in unit tests for a nullable var](complete_code_coverage_for_nullable_var.md) 7 | * [How to mock singleton objects in Kotlin](mock_singleton_in_kotlin.md) 8 | -------------------------------------------------------------------------------- /webservices/miscellaneous_best_practices.md: -------------------------------------------------------------------------------- 1 | ## Miscellaneous best practices 2 | 3 | * Use destroy dependencies on `has_many` associations 4 | 5 | ```ruby 6 | class BlogPost < ActiveRecord::Base 7 | has_many :comments, dependent: :destroy 8 | end 9 | ``` 10 | 11 | * Add indexes for all attributes that you may query on when creating a table or adding a column 12 | 13 | ```ruby 14 | def change 15 | add_column :blog_posts, :category_name, :string 16 | add_index :blog_posts, :category_name 17 | end 18 | ``` 19 | -------------------------------------------------------------------------------- /android/stuff_to_read.md: -------------------------------------------------------------------------------- 1 | # Android Resources 2 | Good stuff, cheap. 3 | 4 | ## General 5 | * [Android Weekly](http://androidweekly.net/) - subscribe to it, great way to keep current. 6 | * [Dashboards](https://developer.android.com/about/dashboards/index.html) - keep track of Android platform version demographics. 7 | * [Recent Support Library Revisions](https://developer.android.com/topic/libraries/support-library/revisions.html) - stay up to date on the latest Support Library changes. 8 | 9 | ## Design 10 | * [Device Metrics](https://design.google.com/devices/) - Useful list of many devices and their screen metrics. 11 | -------------------------------------------------------------------------------- /git/why_rebase.md: -------------------------------------------------------------------------------- 1 | Atlassian has a couple of good articles covering [the conceptual differences of merging and rebasing](https://www.atlassian.com/git/tutorials/merging-vs-rebasing) and [the pros and cons of each workflow](https://www.atlassian.com/git/articles/git-team-workflows-merge-or-rebase/). 2 | 3 | Why have we at Intrepid have chosen to prefer the rebase workflow? 4 | 5 | We prefer to optimize our history for future developers rather than optimizing for ease of work in the moment and we find that the merge workflow does not allow that. 6 | 7 | This merge history is much harder to understand 8 | 9 | ![messy](images/why-rebase/merge-flow.png) 10 | 11 | than this rebase history 12 | 13 | ![clean](images/why-rebase/rebase-flow.png) 14 | -------------------------------------------------------------------------------- /ios/viewmodels/Overview.md: -------------------------------------------------------------------------------- 1 | The purpose of this document is to capture some of our thinking around the best practices around using view models, and to help alleviate some confusion regarding it's usage. 2 | These examples are meant to provide guidance, not meant to be used as a strict guideline of the only way to do it. 3 | When in doubt, remember that the goal of introducing view models is to separate view logic and model logic. 4 | 5 | 6 | Topics/Proposed Topics: 7 | - [x] [Motivation behind using view models](view-model-motivation.md) 8 | - [x] [View model reuse accross multiple models](view-model-reuse.md) 9 | - [ ] Example of view model tests (Bryan) 10 | - [ ] View models with two way bindings using rx (Ben) 11 | - [ ] View models that handle network calls 12 | - [ ] View models that handle both network calls and persistence 13 | 14 | Archived Topics: 15 | - [ ] Should view models be value types as opposed to reference types? 16 | -------------------------------------------------------------------------------- /android/architecture_articles.md: -------------------------------------------------------------------------------- 1 | ### Articles related to GUI architecture 2 | 3 |
4 | Uncle Bob gives an overview of a clean, layered architecture that emphasizes the dependency-inversion principle.

5 |
6 | Martin Fowler takes us back to 2006 in his discussion of GUI architectures; the segments on MVC, MVP, and the concept of a passive view are particularly relevant.

7 |
8 | Hannes Dorfmann summarizes MVP in his introduction to Mosby, a library for Android that enforces an MVP architecture.

9 |
10 | Fernando Cejas recapitulates the principles of "the clean architecture" from the perspective of an Android developer.

11 |
12 | A pitch for another MVP library for Android.

13 | -------------------------------------------------------------------------------- /ios/ios_swift_4_transition_checklist: -------------------------------------------------------------------------------- 1 | # Swift 4 Transition Checklist 2 | 3 | Provided below is a short checklist of items to complete so your project is ready to make the jump to Swift 4. 4 | 5 | We ask all projects to add the following checklist to the Readme file and complete the necessary items. 6 | 7 | Transitioning Swift Wisdom to Swift 4 will be handled collectively by the iOS team. As a result, there is no need to account for Swift Wisdom related work when completing the checklist. 8 | 9 | ``` 10 | # Swift 4 Transition Checklist 11 | 12 | Is the project going to remain active or under maintenance contract beyond launch of Swift 4 (Sept/Oct 2017) - [ ] Yes - [ ] No 13 | 14 | - [ ] Swift 4 transition story in the backlog 15 | - [ ] Podfile being inventoried by Jenkins 16 | - [ ] Manual Pod audit to identify unmaintained/Intrepid maintained Pods 17 | - [ ] Stories for removing unmaintained/Intrepid Pods, if needed (Not including Swift Wisdom) 18 | - [ ] Stories for updating unmaintained/Intrepid Pods, if needed (Not including Swift Wisdom) 19 | 20 | ``` 21 | -------------------------------------------------------------------------------- /android/android_studio_plugins.md: -------------------------------------------------------------------------------- 1 | # Useful Android Studio Plugins 2 | 3 | [.ignore](https://plugins.jetbrains.com/plugin/7495--ignore) - Helps with ignored files 4 | 5 | [Advanced Java Folding](https://plugins.jetbrains.com/plugin/9320-advanced-java-folding) - Makes Java look more concise, like Kotlin 6 | 7 | [Android ButterKnife Zelezny](https://plugins.jetbrains.com/plugin/7369-android-butterknife-zelezny) - Auto-generate ButterKnife injections from selected XML 8 | 9 | [Android DPI Calculator](https://plugins.jetbrains.com/plugin/7832-android-dpi-calculator) - Calculate pixel sizes in all densities simultaneously 10 | 11 | [Android Parcelable code generator](https://plugins.jetbrains.com/plugin/7332-android-parcelable-code-generator) - Generates Parcelable implementation based on class fields 12 | 13 | [Android Resource Usage Count](https://plugins.jetbrains.com/plugin/9885-android-resource-usage-count) - Display a count in the left gutter for how many times a resource is referenced 14 | 15 | [DTO Generator](https://plugins.jetbrains.com/plugin/7834-dto-generator) - Auto-generate Java model classes from JSON 16 | 17 | [Key Promoter X](https://plugins.jetbrains.com/plugin/9792-key-promoter-x) - Helps you learn Android Studio keyboard shortcuts 18 | 19 | [Snake](https://plugins.jetbrains.com/plugin/7854-snake) - Play Snake inside of Android Studio 20 | -------------------------------------------------------------------------------- /mobile_api_guidance.md: -------------------------------------------------------------------------------- 1 | # Versioning 2 | 3 | Functionality provided by an API inevitably changes over time, and it’s sometimes necessary to make breaking, backwards-incompatible changes. In contrast to web app users, mobile app users must upgrade their software to take advantage of new functionality, and there is a period of overlap and adoption where two versions of a client are in circulation. It is beneficial to think about upgrade strategies early in your API’s development, and there are a few different approaches. 4 | 5 | The most common approach is to prefix URIs with a version, e.g. ‘/v1/method’. This allows clients that are configured to use a particular version of an API to continue using it after a new version of the API is released with a different prefix. Facebook is an example of an API that is versioned this way. 6 | 7 | Another approach is to require all clients to upgrade when a new API is released. The user must be presented with an explicit message that they need to visit the appropriate app store to upgrade their app. This is typically a sacrifice in user experience but can be necessary for applications like multiplayer games. To implement this, an API can either provide a “latestVersion” endpoint, or create an explicit error code that triggers the client to present the upgrade message to the user. An example of this type of API is the game Hearthstone. -------------------------------------------------------------------------------- /android/android_pr_coverage.md: -------------------------------------------------------------------------------- 1 | # Adding Coverage Status Reporting to Pull Requests 2 | 3 | We can use the [GitHub Pull Request Coverage Status Plugin](https://github.com/jenkinsci/github-pr-coverage-status-plugin) to get test coverage measurements posted to GitHub as PR comments. The Skeleton projects and Jenkins templates have been updated with this setup, but these instructions can help legacy projects make use of this as well. 4 | 5 | ![Coverage Report](images/pr-coverage-comment.png) 6 | 7 | 8 | ### Steps 9 | 10 | 1. If not a Skeleton-based project, set up [coverage reporting](android_cobertura.md) 11 | 1. Update `coverage.gradle` so that your jacoco reports output a file called `jacoco.xml`. Previously, it likely was `coverage.xml`. 12 | 1. Make sure to also update your jenkins job to reference the correct file in the shell command where it converts JaCoCo reports to Cobertura format, if necessary 13 | 1. Add the "Record Master Coverage" post-build step to your main project job. 14 | 1. Make sure your PR builder job runs `unitTestCoverage` rather than `testDebugUnitTest`. 15 | 1. Add the "Public coverage to GitHub" post-build step to your PR builder job. 16 | 17 | ### Known issues 18 | 19 | - The PR message will report 0% coverage on master, so you can't actually see the change in coverage. This seems to be due to one of [these](https://github.com/jenkinsci/github-pr-coverage-status-plugin/issues/28) [two](https://github.com/jenkinsci/github-pr-coverage-status-plugin/issues/20) issues in the plugin. 20 | -------------------------------------------------------------------------------- /android/tidbits/mock_singleton_in_kotlin.md: -------------------------------------------------------------------------------- 1 | # How to mock singleton `object`s in Kotlin without using PowerMock 2 | 3 | ### MySingleton.kt - the definition of your Singleton object 4 | ```kotlin 5 | @VisibleForTesting 6 | var mySingletonDelegate: MySingletonIfc? = null 7 | 8 | // The delegate here is the "secret sauce" which allows us to specify an alternative implementation 9 | // (such as for testing), or, if it was not set, then use the default implementation defined below. 10 | object MySingleton: MySingletonIfc by mySingletonDelegate ?: MySingletonImpl 11 | 12 | private object MySingletonImpl : MySingletonIfc { 13 | override fun foo(): String { 14 | // Actual implementation 15 | } 16 | } 17 | 18 | interface MySingletonIfc { 19 | fun foo(): String 20 | } 21 | ``` 22 | 23 | ### BaseTest.kt - ALL unit tests must derive from this, otherwise you may run into initialization issues 24 | ```kotlin 25 | @Mock 26 | protected lateinit var mockMySingleton: MySingletonIfc 27 | 28 | @Before 29 | fun baseSetup() { 30 | // Note that the extra level of delegation is critical here 31 | // Specifying "mySingletonDelegate = mockMySingleton" is not good enough, as the mocked object on its own 32 | // doesn't sufficiently override/initialize the default implementation (for some unknown reason) 33 | mySingletonDelegate = object : MySingletonIfc by mockMySingleton {} 34 | } 35 | ``` 36 | 37 | ### YourTest.kt - To override this mocked singleton in your tests, you can now do the following: 38 | ```kotlin 39 | whenever(mockMySingleton.foo()).thenReturn(“A mocked string response”) 40 | ``` 41 | -------------------------------------------------------------------------------- /development_principles.md: -------------------------------------------------------------------------------- 1 | 2 | # Intrepid Development Principles 3 | 4 | The following core principles represent how Intrepid approaches software development. We use these principles as a lens through which we can evaluate new technologies, tools, and processes. 5 | 6 | ### Team Alignment 7 | 8 | There are many players on a software development team. Project managers, engineers, designers, and stakeholders all make dozens of small decisions each day that lead to a successful product. Each one of these micro-decisions is a trade off. It is important that each team member has a clear understanding of the high level project goals and success criteria as a framework for evaluating these choices. 9 | 10 | ### Plan for Change 11 | 12 | At Intrepid we understand that uncertainty is inevitable in software development. We regard iteration as a necessary and healthy aspect of creating great products. We drive positive change by leveraging our experience and validating ideas with real-world users. 13 | 14 | ### Transparency 15 | 16 | We reduce the impact of this uncertainty by building continuous feedback into our process. Our quality metrics, code review workflow, and agile approach are designed to give stakeholders and team members alike a clear view of progress. It is never too early to communicate risks. 17 | 18 | ### Self Assessment 19 | 20 | Every project has its own unique set of challenges. A healthy team must examine what ceremonies, procedures, and communication styles work well for their project. It is through this self assessment that we can more accurately plan for successful delivery. 21 | 22 | 23 | -------------------------------------------------------------------------------- /android/code_style.md: -------------------------------------------------------------------------------- 1 | # Adding a Shared Code Style to Android Studio 2 | 3 | You'll find the Intrepid code style template in this directory, it's 4 | called "Intrepid.xml". 5 | 6 | 1. Download the code style file. 7 | 1. Import the code style by going to Preferences -> Editor -> Code Style and choosing "Import Scheme..." from the gear menu next to the "Scheme" box. 8 | 1. Select the file you downloaded in step 1. 9 | 10 | You should now see the code style visible in the Scheme dropdown, as shown: 11 | 12 | ![Code style settings](images/code-style.png) 13 | 14 | Our code style is a living document - if you have suggested changes, 15 | please bring them up on the #android Slack channel for discussion and 16 | we'll go from there! 17 | 18 | ### Syncing the code style file 19 | Code style settings can also be checked into git and have the changes 20 | be automatically synced across team members. 21 | 22 | 1. Choose "Copy to Project..." from Preferences -> Editor -> Code Style -> gear menu next to the "Scheme" box. 23 | 1. Select "Project" as the Scheme (this may be automatic) 24 | 1. The code style should now be present in `.idea/codeStyles/Project.xml` and the configuration in `.idea/codeStyles/codeStyleConfig.xml` will indicate to use project settings. 25 | 1. Add those two files to Git and commit them. 26 | 27 | Normally, we put the whole `.idea` 28 | folder under gitignore. However, we can make an exception for the code 29 | style files. You can explitly exempt them from being ignored by doing something like this: 30 | ``` 31 | .idea/* 32 | !.idea/codeStyles/* 33 | ``` 34 | 35 | Or you can force-add them: 36 | ``` 37 | git add -f .idea/codeStyles 38 | ``` 39 | 40 | Once tracked, Git will notice changes to the files in the future. 41 | 42 | That's it! Your coworkers will get the new code style the next time they pull. You can validate it's working by checking that the Scheme is automagically set to "Project". 43 | -------------------------------------------------------------------------------- /ios/ios_code_coverage.md: -------------------------------------------------------------------------------- 1 | # Configure iOS Project To Track Code Coverage 2 | This setup is for both your Pull Request Jenkins projects as well as your main OTA build, as the process is identical for these two configurations. 3 | 4 | # Setup Jenkins 5 | Following either the Pull Request template found [here](http://ci.intrepid.io:8080/view/Templates/job/ios-pull-request-template/) or the OTA template found [here](http://ci.intrepid.io:8080/view/Templates/job/ios-template/), ensuring code coverage is reported for your iOS projects is straight forward. 6 | 7 | ## Using [Scan](https://github.com/fastlane/fastlane/tree/master/scan) To Run Test 8 | You should have a section of code in your 'Execute Shell' Build Phase within your Jenkins project that looks like this: 9 | ``` 10 | scan --configuration "Debug" \ 11 | --skip_build true \ 12 | --code_coverage true \ 13 | --scheme "${XCODE_SCHEME}" \ 14 | --device "${TESTING_DEVICE}" \ 15 | --clean 16 | ``` 17 | To ensure that you are collecting code coverage information, make sure that `--code_coverage` has the value of `true`. 18 | 19 | Additionally, after your scan call, you must make sure that you also call this line after scan: 20 | ``` 21 | ruby ${SCRIPT_DIR}/coverage.rb ${XCODE_SCHEME} 22 | ``` 23 | **NOTE:** You must ensure that this line comes AFTER the scan command. 24 | 25 | Therefore, you need to ensure that this section of code matches: 26 | ``` 27 | scan --configuration "Debug" \ 28 | --skip_build true \ 29 | --code_coverage true \ 30 | --scheme "${XCODE_SCHEME}" \ 31 | --device "${TESTING_DEVICE}" \ 32 | --clean 33 | 34 | ruby ${SCRIPT_DIR}/coverage.rb ${XCODE_SCHEME} 35 | ``` 36 | 37 | ## Using Jenkins Xcode Plugin 38 | If you have yet to transition your Jenkins project over to using the script we have in the templates, please do so and then refer to the above section if you have questions. 39 | 40 | # Help 41 | For any help setting this up, please reference the Jenkins project templates or ask **David Brooks (dbrooks@intrepid.io)** for assistance. 42 | -------------------------------------------------------------------------------- /readme-template.md: -------------------------------------------------------------------------------- 1 | # Project Name 2 | 3 | 10 | [![Build Status](https://ci.intrepid.io/buildStatus/icon?job=iOS/ios-legacy/ios-template)](https://ci.intrepid.io/job/iOS/job/ios-legacy/job/ios-template/) 11 | [![Coverage](http://ci.intrepid.io:9913/jenkins/cobertura/iOS/job/ios-legacy/job/ios-template)](https://ci.intrepid.io/job/iOS/job/ios-legacy/job/ios-template/cobertura/) 12 | 13 | The purpose of this great app is… something something… the intersection of technology and humanity. 14 | ___ 15 | # Table of Contents 16 | 17 | 1. [Building](#building) 18 | 1. [Onboarding](#onboarding) 19 | 2. [Running](#running) 20 | 2. [Testing](#testing) 21 | 3. [Release](#release) 22 | 1. [Quirks](#quirks) 23 | 2. [Known Bugs](#known-bugs) 24 | 4. [Architecture](#architecture) 25 | 1. [Data Flow](#data-flow) 26 | 2. [Core Technology #1](#core-technology-1) 27 | 3. [Core Technology #2](#core-technology-2) 28 | 4. [Third Party Libraries](#third-party-libraries) 29 | 5. [History](#history) 30 | 31 | ___ 32 | 33 | # Building 34 | ## Onboarding 35 | Install dependencies using `pod install` and open the `xcworkspace` project. 36 | This project doesn't require any other special configuration to run. 37 | 38 | ## Running 39 | Run the app in either the simulator or on a device. 40 | ___ 41 | 42 | # Testing 43 | Run unit tests. 44 | Something something code coverage. 45 | 46 | # Release 47 | Build it, sign it, :shipit: 48 | 49 | ## Quirks 50 | This app depends on this obscure library. You’ve probably never heard of it. 51 | 52 | ## Known Bugs 53 | No bugs. **QA Rules** 54 | ___ 55 | 56 | # Architecture 57 | ## Data Flow 58 | ## Core Technology 1 59 | ## Core Technology 2 60 | ## Third Party Libraries 61 | ___ 62 | 63 | # History 64 | App is awaiting approval from client for app store. 65 | 66 | - 8/29/2016: 1.0.1 version uploaded to app store. 67 | -------------------------------------------------------------------------------- /ios/ios_app_submission_checklist.md: -------------------------------------------------------------------------------- 1 | # iOS App Store Submission Checklist 2 | 3 | If you need some quick advice, check out this [App Submission](https://drive.google.com/a/intrepid.io/file/d/0B6c_wNPk_qCbQjBSNzFBMi1sOTQ/view?usp=sharing) video tutorial. The tutorial takes you from creating a new Xcode project to submitting a build to iTunes Connect. Otherwise follow these steps: 4 | 5 | - Sign up for Apple Developer Program account (requires DUNS number for businesses) 6 | - If the app communicates with custom hardware, send hardware to Apple to use while they review the app. 7 | - Gather certificates 8 | - Create an iOS distribution certificate using the Apple Developer Portal 9 | - Create prodution APNS certificates 10 | - Upload APNS certificates to push notification provider (e.g. Urban Airship, Localytics) 11 | - Create an App ID that matches the project’s bundle identifier, with proper entitlements (push, game center, etc.) using the Apple Developer Portal 12 | - Metadata 13 | - App title 14 | - Not the same as springboard title (on phone) 15 | - Good to add keywords here 16 | - Unlimited character count, though titles will be truncated 17 | - App version (must match version number in binary) 18 | - App SKU (really not used for anything; usually “appname_date”) 19 | - App description as it will appear in the app store 20 | - App store category & optional subcategory 21 | - Price (or free) 22 | - Country availability 23 | - What’s new description (only for updates, not first-time submission) 24 | - Localized non-english descriptions if applicable 25 | - Keywords (100 characters) 26 | - Don’t add spaces after commas separating keywords 27 | - Large app icon (1024 x 1024) 28 | - At least one screenshot to appear in the app store for each platform (640x1126 iPhone, 2048x1536 iPad) 29 | - Best to have several, annotated shots 30 | - WatchKit icon & screenshots (if applicable) 31 | - EULA (if different from the default) 32 | - Demo account information for Apple reviewers 33 | - Extra instructions for Apple reviewers (if applicable) -------------------------------------------------------------------------------- /ios/common_cocoapods.md: -------------------------------------------------------------------------------- 1 | # Common CocoaPods: 2 | 3 | The purpose of this document is to provide a list of recommended cocoapods that are commonly used across Intrepid projects. 4 | 5 | ## Networking 6 | - [Alamofire](https://github.com/Alamofire/Alamofire) 7 | 8 | ## Persistence 9 | - [Realm](https://github.com/realm/realm-cocoa) 10 | 11 | ## Keyboard Handling 12 | - [TPKeyboardAvoiding](https://github.com/michaeltyson/TPKeyboardAvoiding) 13 | - [IQKeyboardManager](https://github.com/hackiftekhar/IQKeyboardManager) 14 | 15 | ## Analytics 16 | - [Fabric](https://get.fabric.io/) 17 | - [MixPanel](https://mixpanel.com/) 18 | - [Localytics](https://www.localytics.com/) 19 | 20 | ## Attributed Labels 21 | - [TTTAttributedLabel](https://github.com/TTTAttributedLabel/TTTAttributedLabel) 22 | 23 | ## Loading Spinners 24 | - [SVProgressHUD](https://github.com/SVProgressHUD/SVProgressHUD) 25 | - [CircleProgressView](https://github.com/CardinalNow/iOS-CircleProgressView) 26 | - [PKHUD](https://github.com/pkluz/PKHUD) 27 | - [SwiftSpinner](https://github.com/icanzilb/SwiftSpinner) 28 | 29 | ## Constraints 30 | - [Purelayout](https://github.com/PureLayout/PureLayout) 31 | 32 | ## JSON Serialization/Deserialization 33 | - [Genome](https://github.com/LoganWright/Genome) 34 | - [SwiftyJSON](https://github.com/SwiftyJSON/SwiftyJSON) 35 | 36 | ## Dates 37 | - [AFDateHelper](https://github.com/melvitax/DateHelper) 38 | - [NSDate-Escort](https://github.com/azu/NSDate-Escort) 39 | 40 | ## Image Downloading & Caching 41 | - [Kingfisher](https://github.com/onevcat/Kingfisher) 42 | - [SDWebImage](https://github.com/rs/SDWebImage) 43 | - [AlamofireImage](https://github.com/Alamofire/AlamofireImage) 44 | 45 | ## Keychain 46 | - [KeychainAccess](https://github.com/kishikawakatsumi/KeychainAccess) 47 | 48 | ## Reachability 49 | - [ReachabilitySwift](https://github.com/ashleymills/Reachability.swift) 50 | 51 | ## UI 52 | - [FXBlurView](https://github.com/nicklockwood/FXBlurView) 53 | 54 | ## Reactive Programming 55 | - [RxSwift](https://github.com/ReactiveX/RxSwift) 56 | 57 | ## Permissions Handling 58 | - [PermissionScope](https://github.com/nickoneill/PermissionScope) 59 | -------------------------------------------------------------------------------- /ios/ios_inspecting_an_ipa_file.md: -------------------------------------------------------------------------------- 1 | # Inspecting an .ipa file 2 | 3 | Often it can be useful to know to what is actually being bundled with your application's .ipa file. While this file might appear to be atomic, you are actually able to extract and observe it's contents. Doing so is as simple as right clicking on the .ipa file and opening it with *Archive Utility*, unzipping it as a folder named `Payload`. If *Archive Utility* is not available, it's likely because your OS doesn't realize the .ipa is actually a zip format. Changing the .ipa extension to .zip should be enough to fool the OS into making it unzippable. 4 | 5 | You can also use [ProvisionQL](https://github.com/ealeksandrov/ProvisionQL), a helpful *QuickLook* plugin, to inspect some of the details of the .ipa file and its contents without having to unzip it. 6 | 7 | #### Inspecting an .ipa can be useful for: 8 | * Debugging issues in your app's build process 9 | * Discovering what images/fonts/strings/etc. an app on the AppStore uses 10 | * Discovering what frameworks an app on the AppStore depends on 11 | 12 | ## Determining whether or not an .ipa is provisioned for a given device 13 | 14 | Occasionally, when you need to manually install an .ipa on your test device, you'll run in to the error "A valid provisioning profile for this executable was not found." If you encounter this error, inspect the ipa's embedded profile to verify the device's ID is included as a sanity check. 15 | 16 | 1. Open the `embedded.mobileprovision` file in a text editor (`Payload` > *Application-file* > `embedded.mobileprovision`). This is a binary file with an ascii plist embedded in the middle. Your average text editor will be able to display its contents with a mangled format; however, Atom does a pretty good job at making the plist portion readable. 17 | 2. Look for the array with the key `ProvisionedDevices`. This array includes the IDs for all of the provisioned devices and presumably your device's ID is missing. 18 | 19 | ### If your device's ID is missing: 20 | * You may have an out of date version of the given provisioning profile - verify this by checking its list of devices against the version on the Apple Developer portal 21 | * The wrong profile may have been selected (automatically or manually) - verify this by checking the other values in plist, notably: `application-identifier`, `Name`, `TeamIdentifier`, and `TeamName` 22 | -------------------------------------------------------------------------------- /android/third_party_libs.md: -------------------------------------------------------------------------------- 1 | # Our Favorite Third-Party Libraries 2 | 3 | ### Retrofit 4 | 5 | Clean, intuitive, RESTful HTTP client we use to perform network IO; use with OkHttp. 6 | 7 | Overview:
8 | Source: 9 | 10 | Overview of OkHttp:
11 | Source for OkHttp: 12 | 13 | ### EventBus 14 | 15 | An event bus tailored to Android, greenrobot's EventBus supports communication between distinct application components; generally, the event bus should only be used when an event is broadcast to multiple listeners at once. 16 | 17 | Overview:
18 | Source:
19 | Alternatives: 20 | 21 | ### ButterKnife 22 | 23 | Tool used to refine the process of instantiating views and setting listeners; depends on annotation processing to generate boilerplate code (that you would otherwise write) at compile time. 24 | 25 | Overview:
26 | Source: 27 | 28 | ### Timber 29 | 30 | Simple logging utility; Timber automatically tags log statements, permits use of string format parameters, and makes it easier to adjust logging based on build configuration. 31 | 32 | Source: 33 | 34 | ### Picasso 35 | 36 | Used for downloading and caching images; also supports easy transformation and display of said images. 37 | 38 | Overview:
39 | Source: 40 | 41 | ### Calligraphy 42 | 43 | Implements custom fonts with negligible impact on performance & memory; looks for fonts in assets/ directory. 44 | 45 | Source: 46 | 47 | ### RxJava 48 | 49 | Supports clean implementation of asynchronous and event-based tasks; considerably useful for coordinating execution across multiple threads. 50 | 51 | Source:
52 | RxJava for Android: and 53 | 54 | ### RxPermissions 55 | Allows for permission handling for the new permissions model (M and above) using RxJava and Observables. 56 | 57 | Source:
58 | -------------------------------------------------------------------------------- /git/commit_message_guide.md: -------------------------------------------------------------------------------- 1 | # Writing a good commit message 2 | 3 | The following are a couple of good examples of commit messages 4 | taken from good blog posts. See the posts for more details on "Why". 5 | 6 | ``` 7 | Summarize changes in around 50 characters or less 8 | 9 | More detailed explanatory text, if necessary. Wrap it to about 72 10 | characters or so. In some contexts, the first line is treated as the 11 | subject of the commit and the rest of the text as the body. The 12 | blank line separating the summary from the body is critical (unless 13 | you omit the body entirely); various tools like `log`, `shortlog` 14 | and `rebase` can get confused if you run the two together. 15 | 16 | Explain the problem that this commit is solving. Focus on why you 17 | are making this change as opposed to how (the code explains that). 18 | Are there side effects or other unintuitive consequences of this 19 | change? Here's the place to explain them. 20 | 21 | Further paragraphs come after blank lines. 22 | 23 | - Bullet points are okay, too 24 | 25 | - Typically a hyphen or asterisk is used for the bullet, preceded 26 | by a single space, with blank lines in between, but conventions 27 | vary here 28 | 29 | If you use an issue tracker, put references to them at the bottom, 30 | like this: 31 | 32 | Resolves: #123 33 | See also: #456, #789 34 | ``` 35 | Source: https://chris.beams.io/posts/git-commit/ 36 | 37 | 38 | ``` 39 | Capitalized, short (50 chars or less) summary 40 | 41 | More detailed explanatory text, if necessary. Wrap it to about 72 42 | characters or so. In some contexts, the first line is treated as the 43 | subject of an email and the rest of the text as the body. The blank 44 | line separating the summary from the body is critical (unless you omit 45 | the body entirely); tools like rebase can get confused if you run the 46 | two together. 47 | 48 | Write your commit message in the imperative: "Fix bug" and not "Fixed bug" 49 | or "Fixes bug." This convention matches up with commit messages generated 50 | by commands like git merge and git revert. 51 | 52 | Further paragraphs come after blank lines. 53 | 54 | - Bullet points are okay, too 55 | 56 | - Typically a hyphen or asterisk is used for the bullet, followed by a 57 | single space, with blank lines in between, but conventions vary here 58 | 59 | - Use a hanging indent 60 | ``` 61 | Source: https://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html 62 | -------------------------------------------------------------------------------- /webservices/caching.md: -------------------------------------------------------------------------------- 1 | ## Best Practice on Caching 2 | 3 | `GET` requests that return a resource or set of resources should enable caching via `If-Modified-Since` and `Last-Modified` headers. 4 | 5 | * The client can send an `If-Modified-Since` header. If the resource(s) has not been modified since that time, a 304 response should be returned with no request body. 6 | * These endpoints should always include a `Last-Modified` header that includes the most recent time the resource(s) were modified. 7 | - In the case of a `GET` request that returns a set of resources, this should be the `updated_at` timestamp of the most recently updated resource. 8 | 9 | ### Example implementations 10 | 11 | Call the `stale?` method in your controller action, passing it the relevant resource. From the [documentation](http://apidock.com/rails/ActionController/ConditionalGet/stale%3F): 12 | 13 | > Sets the etag and/or last_modified on the response and checks it against the client request. If the request doesn’t match the options provided, the request is considered stale and should be generated from scratch. Otherwise, it’s fresh and we don’t need to generate anything and a reply of 304 Not Modified is sent. 14 | 15 | #### Single resource 16 | 17 | ```ruby 18 | def show 19 | blog_post = BlogPost.find(params[:id]) 20 | 21 | if stale?(blog_post) 22 | render json: blog_post 23 | end 24 | end 25 | ``` 26 | 27 | #### Set of resources 28 | 29 | ```ruby 30 | def index 31 | blog_posts = BlogPost.order(updated_at: :desc) 32 | 33 | if stale?(blog_posts.first) 34 | render json: blog_posts 35 | end 36 | end 37 | ``` 38 | 39 | ### Other considerations 40 | 41 | #### Child resources 42 | 43 | Consider an endpoint `GET /blog_posts` that returns a list of blog posts and their comments. The client sends an `If-Modified-Since` header of 5 minutes ago. No blog posts have been modified in the last 5 minutes, but a comment has been added to one of them. 44 | 45 | In most such cases, we'll treat this set of resources as though it has been modified, although the parent resources have not been. 46 | 47 | The easiest way to ensure this treatment is to modify the parent record's `updated_at` timestamp when a child resource is added or updated using `touch: true`: 48 | 49 | ```ruby 50 | class Comment < ActiveRecord::Base 51 | belongs_to :blog_post, touch: true 52 | end 53 | 54 | class BlogPost < ActiveRecord::Base 55 | has_many :comments 56 | end 57 | ``` 58 | -------------------------------------------------------------------------------- /android/tidbits/complete_code_coverage_for_nullable_var.md: -------------------------------------------------------------------------------- 1 | # How to get complete code coverage in unit tests for a nullable `var` 2 | 3 | ### The example 4 | If you're writing unit tests for a Kotlin class, you may not see complete code coverage for code like this (even if you're testing `bar()` with both null & non-null values of `foo`): 5 | ```kotlin 6 | class Example { 7 | private var foo: String? = null 8 | 9 | fun bar() { 10 | if(foo != null) { 11 | foo?.size() 12 | } 13 | } 14 | } 15 | ``` 16 | 17 | Because `foo` is a var, the compiler can't guarantee that another thread won't access it and change its value between the time you check `if(foo != null)` and the time you call `foo?.size()`. 18 | This is why you have to use the `?` when calling `foo.size()` - because the compiler won't smart cast the `var` from `String?` to `String` even though you're inside a null-checking if statement. 19 | 20 | Unless you want to write tests that actually capture the value of `foo` changing mid-method, it's much better to write this code like this: 21 | ```kotlin 22 | class Example { 23 | private var foo: String? = null 24 | 25 | fun bar() { 26 | foo?.let { 27 | it.size() 28 | } 29 | } 30 | } 31 | ``` 32 | 33 | In this 2nd example, the compiler automatically creates a constant `val` reference to `foo` that's internal to the `let` block, and can therefore guarantee that `foo` (`it` inside the `let` block) is non-null. 34 | This also eliminates the code coverage issue as the value is only checked for null once. 35 | 36 | In my opinion, this approach is also much cleaner than handling it yourself by manually creating a temporary `val` like this: 37 | ```kotlin 38 | class Example { 39 | private var foo: String? = null 40 | 41 | fun bar() { 42 | val copyOfFoo = foo 43 | if(copyOfFoo != null) { 44 | copyOfFoo.size() 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | ### Background 51 | What was initially baffling about this was that I was using a nullable `var` such as in the example above, and this class only had two methods which both had `synchronized` blocks wrapping all changes to `foo`. 52 | It took me a while to tumble to the fact that the compiler was worried about multi-threaded access, and that this was one instance where the code coverage tool just isn't smart enough to be able to determine that multithreaded access was not a concern. 53 | -------------------------------------------------------------------------------- /webservices/react_deployment.md: -------------------------------------------------------------------------------- 1 | # ReactJS App Deployment 2 | 3 | ## Overview 4 | 5 | We usually deploy front end React apps as wholly separate codebases from whatever we are using as the back end server. This gives us great versioning flexibility as well as the ability to push new React code with zero downtime. 6 | 7 | Using `webpack`, the entire React app can be compiled into a single JavaScript file that contains all the minified/transpiled/etc. React code, and the "bare" HTML file containing the React root DOM element and a links to the JavaScript. The important part is the link-- the Javascript file name (and HTML