diff --git a/.buildkite/commands/build-and-test.sh b/.buildkite/commands/build-and-test.sh index e8901c0b6..22b2f5b39 100644 --- a/.buildkite/commands/build-and-test.sh +++ b/.buildkite/commands/build-and-test.sh @@ -3,5 +3,9 @@ echo "--- :rubygems: Setting up Gems" install_gems +# Unit tests don't need real credentials +echo "--- :key: Providing Credentials" +cp Simplenote/SPCredentials.template.swift Simplenote/SPCredentials.external-contributors.swift + echo "--- :hammer_and_wrench: Build and Test" bundle exec fastlane test diff --git a/.gitignore b/.gitignore index 23b8512d1..1ba49be18 100644 --- a/.gitignore +++ b/.gitignore @@ -25,11 +25,11 @@ DerivedData .idea/ *.hmap *.xcscmblueprint -Simplenote/DerivedSources/ +Simplenote/DerivedSources/* +!Simplenote/DerivedSources/README.md # Settings Simplenote/config.plist -Simplenote/Credentials/ # Bundler /vendor/ @@ -52,6 +52,8 @@ build/ .configure-files/* !.configure-files/*.enc +Simplenote/SPCredentials.external-contributors.swift + # Swift Package Manager .build diff --git a/Scripts/Build-Phases/copy-secret.sh b/Scripts/Build-Phases/copy-secret.sh index 4d441cf6f..373fd6e50 100755 --- a/Scripts/Build-Phases/copy-secret.sh +++ b/Scripts/Build-Phases/copy-secret.sh @@ -1,4 +1,26 @@ -#!/bin/bash -euo pipefail +#!/usr/bin/env bash + +set -euo pipefail + +# Materialize secrets into the target's DERIVED_FILE_DIR so the decrypted +# credentials never land in the repo checkout. +# +# The compiled file comes from one of two sources, in order: +# +# 1. ${SECRETS_ROOT}, for internal contributors. `bundle exec fastlane run +# configure_apply` decrypts it there, outside the repo; this phase only +# reads it. +# 2. Simplenote/SPCredentials.external-contributors.swift — gitignored, so +# external contributors can keep their own Simperium credentials with +# little-to-no risk of committing them, starting from a copy of the +# committed template. +# +# If neither is present, the build will fail. + +SECRETS_ROOT="${HOME}/.configure/simplenote-macos/secrets" +SECRETS_FILE="${SECRETS_ROOT}/SPCredentials.swift" +TEMPLATE_SECRETS_FILE="${SRCROOT}/Simplenote/SPCredentials.template.swift" +EXTERNAL_SECRETS_FILE="${SRCROOT}/Simplenote/SPCredentials.external-contributors.swift" # To help the Xcode build system optimize the build, we want to ensure each of # the secrets we want to copy is defined as an input file for the run script @@ -20,13 +42,14 @@ function ensure_is_in_input_files_list() { echo "error: Input file list verification needs a path to verify!" exit 1 fi - file_to_find=$1 - if [ $SCRIPT_INPUT_FILE_LIST_COUNT -eq 0 ]; then + if [ "${SCRIPT_INPUT_FILE_LIST_COUNT:-0}" -eq 0 ]; then echo "error: No input file list given (.xcfilelist). Cannot continue." exit 1 fi + file_to_find=$1 + i=0 found=false while [[ $i -lt $SCRIPT_INPUT_FILE_LIST_COUNT && "$found" = false ]] @@ -35,55 +58,49 @@ function ensure_is_in_input_files_list() { file_list_resolved_var_name=SCRIPT_INPUT_FILE_LIST_${i} # The following reads the processed xcfilelist line by line looking for # the given file - while read input_file; do + while read -r input_file; do if [ "$file_to_find" == "$input_file" ]; then found=true break fi done <"${!file_list_resolved_var_name}" - let i=i+1 + (( i=i+1 )) done + if [ "$found" = false ]; then echo "error: Could not find $file_to_find as an input to the build phase. Add $file_to_find to the input files list using the .xcfilelist." exit 1 fi } -SECRETS_ROOT="${HOME}/.configure/simplenote-macos/secrets" -SECRETS_FILE="${SECRETS_ROOT}/SPCredentials.swift" -EXAMPLE_SECRETS_FILE="${SRCROOT}/Simplenote/SPCredentials-demo.swift" +ensure_is_in_input_files_list "$SECRETS_FILE" +ensure_is_in_input_files_list "$EXTERNAL_SECRETS_FILE" -ensure_is_in_input_files_list $SECRETS_FILE -ensure_is_in_input_files_list $EXAMPLE_SECRETS_FILE +# The destination comes from the build phase's `outputPaths`, which Xcode +# exposes as SCRIPT_OUTPUT_FILE_N. Each consumer target writes into its own +# $(DERIVED_FILE_DIR), keeping the decrypted secret out of the checkout. +if [ "${SCRIPT_OUTPUT_FILE_COUNT:-0}" -lt 1 ]; then + echo "error: No output file given. Declare the destination in the build phase's output files list." + exit 1 +fi -SECRETS_DESTINATION_FILE="${SRCROOT}/Simplenote/Credentials/SPCredentials.swift" -mkdir -p $(dirname "$SECRETS_DESTINATION_FILE") +SECRETS_DESTINATION_FILE="${SCRIPT_OUTPUT_FILE_0}" +mkdir -p "$(dirname "$SECRETS_DESTINATION_FILE")" -if cmp --silent -- ${SECRETS_FILE} ${SECRETS_DESTINATION_FILE}; then - echo "☑️ Credentials were not modified. Skipping..." +apply() { + echo "Applying secrets from ${1}" + # `cp -v` names the destination, which differs per consumer target. + cp -v "$1" "$SECRETS_DESTINATION_FILE" exit 0 -fi +} if [ -f "$SECRETS_FILE" ]; then - echo "Applying Production Secrets" - cp -v "$SECRETS_FILE" "${SECRETS_DESTINATION_FILE}" - exit 0 + apply "$SECRETS_FILE" fi -# No secrets file found. Use the example secrets file as a last resort, unless -# building for Release. - -COULD_NOT_FIND_SECRET_MSG="Could not find secrets file at ${SECRETS_DESTINATION_FILE}. This is likely due to the source secrets being missing from ${SECRETS_ROOT}" -INTERNAL_CONTRIBUTOR_MSG="If you are an internal contributor, run \`bundle exec fastlane run configure_apply\` to update your secrets" +if [ -f "$EXTERNAL_SECRETS_FILE" ]; then + apply "$EXTERNAL_SECRETS_FILE" +fi -case $CONFIGURATION in - Release) - echo "error: $COULD_NOT_FIND_SECRET_MSG. Cannot continue Release build. $INTERNAL_CONTRIBUTOR_MSG and try again. External contributors should not need to perform a Release build." - exit 1 - ;; - *) - echo "warning: $COULD_NOT_FIND_SECRET_MSG. Falling back to $EXAMPLE_SECRETS_FILE. In a Release build, this would be an error. $INTERNAL_CONTRIBUTOR_MSG and try again. If you are an external contributor, you can ignore this warning." - echo "Applying Example Secrets" - cp -v "$EXAMPLE_SECRETS_FILE" "$SECRETS_DESTINATION_FILE" - ;; -esac +echo "error: No secrets found! Internal contributors: run \`bundle exec fastlane run configure_apply\`. External contributors: copy '${TEMPLATE_SECRETS_FILE}' to '${EXTERNAL_SECRETS_FILE}', fill in your own Simperium credentials, and build again." +exit 1 diff --git a/Scripts/Build-Phases/copy-secret.xcfilelist b/Scripts/Build-Phases/copy-secret.xcfilelist index 36c78f3c8..fbed4ce90 100644 --- a/Scripts/Build-Phases/copy-secret.xcfilelist +++ b/Scripts/Build-Phases/copy-secret.xcfilelist @@ -1,7 +1,9 @@ -# Inputs for the build phase run script marshalling the secrets for the app, -# currently running from the SimplenoteSecrets aggregate targets +# Inputs for the build phase run script marshalling the secrets for the app. +# Shared between the per-target "Copy Secret" build phases on the Simplenote and +# IntentsExtension targets — each phase writes its own SPCredentials.swift into +# $(DERIVED_FILE_DIR). ${HOME}/.configure/simplenote-macos/secrets/SPCredentials.swift -${SRCROOT}/Simplenote/SPCredentials-demo.swift +${SRCROOT}/Simplenote/SPCredentials.external-contributors.swift # Add the script itself as an input, so the build system will know to run it # if it changes ${SRCROOT}/Scripts/Build-Phases/copy-secret.sh diff --git a/Simplenote.xcodeproj/project.pbxproj b/Simplenote.xcodeproj/project.pbxproj index 30d64403f..65d9204e4 100644 --- a/Simplenote.xcodeproj/project.pbxproj +++ b/Simplenote.xcodeproj/project.pbxproj @@ -6,20 +6,6 @@ objectVersion = 54; objects = { -/* Begin PBXAggregateTarget section */ - B52D0EC5230DCAD7003F799D /* SimplenoteSecrets */ = { - isa = PBXAggregateTarget; - buildConfigurationList = B52D0EC8230DCAD7003F799D /* Build configuration list for PBXAggregateTarget "SimplenoteSecrets" */; - buildPhases = ( - B52D0EC9230DCB15003F799D /* ShellScript */, - ); - dependencies = ( - ); - name = SimplenoteSecrets; - productName = GenerateCredentials; - }; -/* End PBXAggregateTarget section */ - /* Begin PBXBuildFile section */ 3700E97721C1E390004771C9 /* SPTextAttachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3700E97521C1E390004771C9 /* SPTextAttachment.swift */; }; 3712FC831FE1ACAA008544AC /* Storage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3712FC701FE1ACA9008544AC /* Storage.swift */; }; @@ -233,7 +219,7 @@ B5E086362448EA3C00DEF476 /* TagTableCellView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E086342448EA3C00DEF476 /* TagTableCellView.swift */; }; B5E086392448EE9D00DEF476 /* NSTableView+Simplenote.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E086372448EE9D00DEF476 /* NSTableView+Simplenote.swift */; }; B5E0863C2449012700DEF476 /* NSImage+Simplenote.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E0863A2449012700DEF476 /* NSImage+Simplenote.swift */; }; - B5E196C2230F5F5300F5658A /* SPCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E196C0230F5F5300F5658A /* SPCredentials.swift */; }; + B5E196C2230F5F5300F5658A /* SPCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8C27310000000000000A003 /* SPCredentials.swift */; }; B5E8E41224575C990098892B /* ToolbarState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E8E41024575C990098892B /* ToolbarState.swift */; }; B5E96B671BDE732500D707F5 /* AuthViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B5E96B651BDE732500D707F5 /* AuthViewController.m */; }; B5EB3AD22458B9940089858D /* NSNotification+Simplenote.m in Sources */ = {isa = PBXBuildFile; fileRef = B5EB3AD02458B9940089858D /* NSNotification+Simplenote.m */; }; @@ -264,7 +250,7 @@ BA2BF3402C07C75500A7C894 /* FindNoteIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2BF33F2C07C75500A7C894 /* FindNoteIntentHandler.swift */; }; BA2C65CF26FE996A00FA84E1 /* NSButton+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA2C65CA26FE996100FA84E1 /* NSButton+Extensions.swift */; }; BA4C6D18264CAAF800B723A7 /* URLRequest+Simplenote.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA4C6D17264CAAF800B723A7 /* URLRequest+Simplenote.swift */; }; - BA4F223E2C1255A500144EDA /* SPCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = B5E196C0230F5F5300F5658A /* SPCredentials.swift */; }; + BA4F223E2C1255A500144EDA /* SPCredentials.swift in Sources */ = {isa = PBXBuildFile; fileRef = A8C27310000000000000A004 /* SPCredentials.swift */; }; BA54F2462C0E63C700DBCE9D /* AppendNoteIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA54F2452C0E63C700DBCE9D /* AppendNoteIntentHandler.swift */; }; BA54F2482C0E6A6900DBCE9D /* CreateNewNoteIntentHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA54F2472C0E6A6900DBCE9D /* CreateNewNoteIntentHandler.swift */; }; BA553F0927065E20007737E9 /* FontSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = BA553F0727065E20007737E9 /* FontSettings.swift */; }; @@ -340,13 +326,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - B52D0ECE230DCEAC003F799D /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 26F72A7F14032D2900A7935E /* Project object */; - proxyType = 1; - remoteGlobalIDString = B52D0EC5230DCAD7003F799D; - remoteInfo = GenerateCredentials; - }; BAB261692BFFD0AF009A98D7 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 26F72A7F14032D2900A7935E /* Project object */; @@ -679,7 +658,9 @@ B5E086342448EA3C00DEF476 /* TagTableCellView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TagTableCellView.swift; sourceTree = ""; }; B5E086372448EE9D00DEF476 /* NSTableView+Simplenote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTableView+Simplenote.swift"; sourceTree = ""; }; B5E0863A2449012700DEF476 /* NSImage+Simplenote.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSImage+Simplenote.swift"; sourceTree = ""; }; - B5E196C0230F5F5300F5658A /* SPCredentials.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SPCredentials.swift; sourceTree = ""; }; + A8C27310000000000000A003 /* SPCredentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPCredentials.swift; sourceTree = DERIVED_FILE_DIR; }; + A8C27310000000000000A004 /* SPCredentials.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SPCredentials.swift; sourceTree = DERIVED_FILE_DIR; }; + A8C27310000000000000A008 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; B5E8E41024575C990098892B /* ToolbarState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ToolbarState.swift; sourceTree = ""; }; B5E96B641BDE732500D707F5 /* AuthViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AuthViewController.h; sourceTree = ""; }; B5E96B651BDE732500D707F5 /* AuthViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AuthViewController.m; sourceTree = ""; }; @@ -897,7 +878,7 @@ B53BF1A224AC388F00938C34 /* Controllers */, B5CBB05A241971240003C271 /* Converters */, B557A0E825BB0DC700E5313E /* Coordinators */, - B52D0ECA230DCE22003F799D /* Credentials */, + A8C27310000000000000A005 /* DerivedSources */, B51E9FE322E64473004F16B4 /* Extensions */, B574CA71242D539400F8D02F /* Handlers */, 463774DB171F111600E2E333 /* Models */, @@ -1190,12 +1171,30 @@ name = Extensions; sourceTree = ""; }; - B52D0ECA230DCE22003F799D /* Credentials */ = { + A8C27310000000000000A005 /* DerivedSources */ = { + isa = PBXGroup; + children = ( + A8C27310000000000000A006 /* Simplenote */, + A8C27310000000000000A007 /* IntentsExtension */, + A8C27310000000000000A008 /* README.md */, + ); + path = DerivedSources; + sourceTree = ""; + }; + A8C27310000000000000A006 /* Simplenote */ = { + isa = PBXGroup; + children = ( + A8C27310000000000000A003 /* SPCredentials.swift */, + ); + name = Simplenote; + sourceTree = ""; + }; + A8C27310000000000000A007 /* IntentsExtension */ = { isa = PBXGroup; children = ( - B5E196C0230F5F5300F5658A /* SPCredentials.swift */, + A8C27310000000000000A004 /* SPCredentials.swift */, ); - path = Credentials; + name = IntentsExtension; sourceTree = ""; }; B52EE32C25927D5D00347F2B /* Notes */ = { @@ -1697,6 +1696,7 @@ buildConfigurationList = 466FFF2C17CC10A800399652 /* Build configuration list for PBXNativeTarget "Simplenote" */; buildPhases = ( BAAA71F42C07B8BB00244C01 /* Swiftlint */, + A8C27310000000000000A001 /* Copy Secret */, 466FFEA717CC10A800399652 /* Sources */, 466FFEDC17CC10A800399652 /* Frameworks */, 466FFEE517CC10A800399652 /* Resources */, @@ -1706,7 +1706,6 @@ buildRules = ( ); dependencies = ( - B52D0ECF230DCEAC003F799D /* PBXTargetDependency */, BAB2616A2BFFD0AF009A98D7 /* PBXTargetDependency */, ); name = Simplenote; @@ -1743,6 +1742,7 @@ isa = PBXNativeTarget; buildConfigurationList = BAB2616F2BFFD0AF009A98D7 /* Build configuration list for PBXNativeTarget "IntentsExtension" */; buildPhases = ( + A8C27310000000000000A002 /* Copy Secret */, BAB2615E2BFFD0AF009A98D7 /* Sources */, BAB2615F2BFFD0AF009A98D7 /* Frameworks */, BAB261602BFFD0AF009A98D7 /* Resources */, @@ -1775,10 +1775,6 @@ LastSwiftMigration = 0920; ProvisioningStyle = Manual; }; - B52D0EC5230DCAD7003F799D = { - CreatedOnToolsVersion = 11.0; - ProvisioningStyle = Manual; - }; B5CBB068241976230003C271 = { CreatedOnToolsVersion = 11.3.1; ProvisioningStyle = Manual; @@ -1830,7 +1826,6 @@ projectRoot = ""; targets = ( 466FFEA617CC10A800399652 /* Simplenote */, - B52D0EC5230DCAD7003F799D /* SimplenoteSecrets */, B5CBB068241976230003C271 /* SimplenoteTests */, BAB261612BFFD0AF009A98D7 /* IntentsExtension */, ); @@ -1884,9 +1879,28 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - B52D0EC9230DCB15003F799D /* ShellScript */ = { + A8C27310000000000000A001 /* Copy Secret */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${SRCROOT}/Scripts/Build-Phases/copy-secret.xcfilelist", + ); + inputPaths = ( + ); + name = "Copy Secret"; + outputFileListPaths = ( + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/SPCredentials.swift", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "${SRCROOT}/Scripts/Build-Phases/copy-secret.sh\n"; + }; + A8C27310000000000000A002 /* Copy Secret */ = { isa = PBXShellScriptBuildPhase; - alwaysOutOfDate = 1; buildActionMask = 2147483647; files = ( ); @@ -1895,10 +1909,11 @@ ); inputPaths = ( ); + name = "Copy Secret"; outputFileListPaths = ( ); outputPaths = ( - "$(SRCROOT)/Simplenote/Credentials/SPCredentials.swift", + "$(DERIVED_FILE_DIR)/SPCredentials.swift", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -2228,11 +2243,6 @@ /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - B52D0ECF230DCEAC003F799D /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = B52D0EC5230DCAD7003F799D /* SimplenoteSecrets */; - targetProxy = B52D0ECE230DCEAC003F799D /* PBXContainerItemProxy */; - }; BAB2616A2BFFD0AF009A98D7 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = BAB261612BFFD0AF009A98D7 /* IntentsExtension */; @@ -2546,24 +2556,6 @@ }; name = Release; }; - B52D0EC6230DCAD7003F799D /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - DEAD_CODE_STRIPPING = YES; - MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - B52D0EC7230DCAD7003F799D /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - DEAD_CODE_STRIPPING = YES; - MACOSX_DEPLOYMENT_TARGET = "$(RECOMMENDED_MACOSX_DEPLOYMENT_TARGET)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; B5CBB071241976230003C271 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -2759,15 +2751,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - B52D0EC8230DCAD7003F799D /* Build configuration list for PBXAggregateTarget "SimplenoteSecrets" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - B52D0EC6230DCAD7003F799D /* Debug */, - B52D0EC7230DCAD7003F799D /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; B5CBB070241976230003C271 /* Build configuration list for PBXNativeTarget "SimplenoteTests" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Simplenote/DerivedSources/README.md b/Simplenote/DerivedSources/README.md new file mode 100644 index 000000000..662da27a0 --- /dev/null +++ b/Simplenote/DerivedSources/README.md @@ -0,0 +1,10 @@ +# DerivedSources + +The two `SPCredentials.swift` entries here — one per consumer target, under `Simplenote/` and `IntentsExtension/` — are shown in red in Xcode and `Open Quickly` cannot find them. +That is expected: they do not exist in the repository. + +The `Copy Secret` build phase writes each into its own target's `$(DERIVED_FILE_DIR)`, from the decrypted credentials under `~/.configure/simplenote-macos/secrets/`, or, missing those, from `SPCredentials.external-contributors.swift`. +Missing both fails the build. +See `Scripts/Build-Phases/copy-secret.sh`. + +Do not delete the red references. The app will not compile without them! diff --git a/Simplenote/SPCredentials-demo.swift b/Simplenote/SPCredentials.template.swift similarity index 87% rename from Simplenote/SPCredentials-demo.swift rename to Simplenote/SPCredentials.template.swift index a27b459d8..758bca71e 100644 --- a/Simplenote/SPCredentials-demo.swift +++ b/Simplenote/SPCredentials.template.swift @@ -1,4 +1,7 @@ -/// Simplenote API Demo Credentials +/// Simplenote API Credentials Template +/// +/// Copy to `SPCredentials.external-contributors.swift` and fill in your own +/// credentials. That path is gitignored. /// import Foundation diff --git a/readme.md b/readme.md index c4107a669..4a4a256cd 100644 --- a/readme.md +++ b/readme.md @@ -48,18 +48,27 @@ You can also open the project by double clicking on `Simplenote.xcworkspace` fil ## Setup Credentials -Simplenote is powered by the [Simperium Sync'ing protocol](https://www.simperium.com). We distribute **testing credentials** that help us authenticate your application, and verify that the API calls being made are valid. +Simplenote is powered by the [Simperium Sync'ing protocol](https://www.simperium.com), which requires credentials to authenticate the application and verify that the API calls being made are valid. **⚠️ Please note → We're not accepting any new Simperium accounts at this time.** +Credentials live in the `simperium*` properties of the `SPCredentials` type, which is generated at build time from production credentials kept outside the checkout, falling back to user-specified ones. +When it finds neither, the build fails with instructions on how to provide them. -Please copy the **testing Simperium credentials** as follows: +Internal contributors decrypt the production credentials with: ``` -mkdir -p Simplenote/Credentials && cp Simplenote/SPCredentials-demo.swift Simplenote/Credentials/SPCredentials.swift +bundle exec fastlane run configure_apply ``` -This will allow you to compile and run the app on a device or a simulator. +External contributors start from the committed template, whose copy is gitignored: + +``` +cp Simplenote/SPCredentials.template.swift Simplenote/SPCredentials.external-contributors.swift +``` + +Unchanged, the template is enough to compile and run the app and its unit tests. +Replace its `simperium*` values with your own to use a different Simperium app. _Note: Simplenote API features such as sharing and publishing will not work with development builds._