diff --git a/.a8c-secrets/Secrets.swift.age b/.a8c-secrets/Secrets.swift.age new file mode 100644 index 000000000000..fe8fcccc2686 Binary files /dev/null and b/.a8c-secrets/Secrets.swift.age differ diff --git a/.a8c-secrets/keys.pub b/.a8c-secrets/keys.pub new file mode 100644 index 000000000000..af1dfa3e9cfc --- /dev/null +++ b/.a8c-secrets/keys.pub @@ -0,0 +1,4 @@ +# dev +age1srcq3hl92ym9jk3ezj5prwhche3w8szc0cssy8t7afrkjmtkxu2qkjsdfn +# ci +age1a7xcr6qzwnzgcxq95sq33p58xdzsmful8w7mp2zktvuy5434yuss9rmv8f diff --git a/.a8c-secrets/repo-id b/.a8c-secrets/repo-id new file mode 100644 index 000000000000..b60ad318d574 --- /dev/null +++ b/.a8c-secrets/repo-id @@ -0,0 +1 @@ +wordpress-ios@github.com@wordpress-mobile diff --git a/.buildkite/commands/build-and-upload-testflight.sh b/.buildkite/commands/build-and-upload-testflight.sh index d8d6ee04a81b..45541bcc17a0 100755 --- a/.buildkite/commands/build-and-upload-testflight.sh +++ b/.buildkite/commands/build-and-upload-testflight.sh @@ -7,8 +7,7 @@ APP="${1:?Usage: build-and-upload-testflight.sh }" "$(dirname "${BASH_SOURCE[0]}")/shared-set-up.sh" "$(dirname "${BASH_SOURCE[0]}")/shared-set-up-distribution.sh" -echo "--- :closed_lock_with_key: Installing Secrets" -bundle exec fastlane run configure_apply +source "$(dirname "${BASH_SOURCE[0]}")/install-a8c-secrets.sh" echo "--- :testflight: Building and uploading ${APP} to TestFlight" bundle exec fastlane build_and_upload_app_for_testflight app:"${APP}" diff --git a/.buildkite/commands/build-for-testing.sh b/.buildkite/commands/build-for-testing.sh index 80fd7fae1e68..dcd4e3db2045 100755 --- a/.buildkite/commands/build-for-testing.sh +++ b/.buildkite/commands/build-for-testing.sh @@ -16,8 +16,7 @@ fi "$(dirname "${BASH_SOURCE[0]}")/shared-set-up.sh" -echo "--- :closed_lock_with_key: Installing Secrets" -bundle exec fastlane run configure_apply +source "$(dirname "${BASH_SOURCE[0]}")/install-a8c-secrets.sh" echo "--- :hammer_and_wrench: Building" bundle exec fastlane "build_${APP}_for_testing" diff --git a/.buildkite/commands/complete-code-freeze.sh b/.buildkite/commands/complete-code-freeze.sh index 9297d9e4d298..dccabcf320fa 100755 --- a/.buildkite/commands/complete-code-freeze.sh +++ b/.buildkite/commands/complete-code-freeze.sh @@ -14,8 +14,5 @@ source use-bot-for-git "$(dirname "${BASH_SOURCE[0]}")/shared-set-up.sh" -echo '--- :closed_lock_with_key: Access secrets' -bundle exec fastlane run configure_apply - echo '--- :shipit: Complete code freeze' bundle exec fastlane complete_code_freeze skip_confirm:true diff --git a/.buildkite/commands/finalize-hotfix.sh b/.buildkite/commands/finalize-hotfix.sh index cb3be53d1d66..942410578b73 100755 --- a/.buildkite/commands/finalize-hotfix.sh +++ b/.buildkite/commands/finalize-hotfix.sh @@ -15,8 +15,5 @@ source use-bot-for-git echo '--- :ruby: Setup Ruby tools' install_gems -echo '--- :closed_lock_with_key: Access secrets' -bundle exec fastlane run configure_apply - echo '--- :shipit: Finalize hotfix' bundle exec fastlane finalize_hotfix_release skip_confirm:true diff --git a/.buildkite/commands/finalize-release.sh b/.buildkite/commands/finalize-release.sh index bbba37e01b8d..18ff3a002112 100755 --- a/.buildkite/commands/finalize-release.sh +++ b/.buildkite/commands/finalize-release.sh @@ -15,8 +15,5 @@ source use-bot-for-git echo '--- :ruby: Setup Ruby tools' install_gems -echo '--- :closed_lock_with_key: Access secrets' -bundle exec fastlane run configure_apply - echo '--- :shipit: Finalize release' bundle exec fastlane finalize_release skip_confirm:true diff --git a/.buildkite/commands/gather-testflight-candidates.sh b/.buildkite/commands/gather-testflight-candidates.sh index c7c2052b62c6..a8bd5eb696ab 100755 --- a/.buildkite/commands/gather-testflight-candidates.sh +++ b/.buildkite/commands/gather-testflight-candidates.sh @@ -1,13 +1,10 @@ #!/bin/bash -eu # Lists the nightly builds, opens the "choose a build" block step, and posts the -# candidate list to Slack. No build — just gems + secrets. +# candidate list to Slack. No build — just gems. echo "--- :rubygems: Setting up Gems" install_gems -echo "--- :closed_lock_with_key: Installing Secrets" -bundle exec fastlane run configure_apply - echo "--- :testflight: Gathering candidates and opening the block step" bundle exec fastlane gather_testflight_candidates diff --git a/.buildkite/commands/install-a8c-secrets.sh b/.buildkite/commands/install-a8c-secrets.sh new file mode 100755 index 000000000000..45c6e4aac7ec --- /dev/null +++ b/.buildkite/commands/install-a8c-secrets.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash + +# The `Decrypt Secrets` and `Generate Credentials` build phases resolve +# `a8c-secrets` off PATH, so the export below has to survive in the caller's shell. +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + echo "This script must be sourced, not executed, because it exports PATH." >&2 + exit 1 +fi + +set -euo pipefail + +echo "--- :closed_lock_with_key: Installing a8c-secrets" + +# `install_a8c-secrets_binary` comes from the a8c-ci-toolkit plugin. It pins the +# a8c-secrets version and checks the download against a checksum vendored there. +install_dir="$HOME/.local/bin" +install_a8c-secrets_binary --install-dir "$install_dir" +export PATH="$install_dir:$PATH" diff --git a/.buildkite/commands/promote-build-to-public.sh b/.buildkite/commands/promote-build-to-public.sh index d7d510d10196..2fcea9d166d4 100755 --- a/.buildkite/commands/promote-build-to-public.sh +++ b/.buildkite/commands/promote-build-to-public.sh @@ -1,6 +1,6 @@ #!/bin/bash -eu -# Promotes the build chosen in the preceding block step to public beta. No build — just gems + secrets. +# Promotes the build chosen in the preceding block step to public beta. No build — just gems. # `build_to_promote` must stay in sync with PROMOTION_META_DATA_KEY in fastlane/lanes/promote.rb, # which is the key the gather lane writes the block-step select field under. @@ -14,8 +14,5 @@ fi echo "--- :rubygems: Setting up Gems" install_gems -echo "--- :closed_lock_with_key: Installing Secrets" -bundle exec fastlane run configure_apply - echo "--- :rocket: Promoting ${BUILD_CODE} to public beta" bundle exec fastlane promote_build build_code:"${BUILD_CODE}" diff --git a/.buildkite/commands/promote-nightly.sh b/.buildkite/commands/promote-nightly.sh index 76e15e7aa168..28c0586251f4 100755 --- a/.buildkite/commands/promote-nightly.sh +++ b/.buildkite/commands/promote-nightly.sh @@ -1,13 +1,10 @@ #!/bin/bash -eu -# Promotes the last build of the day to the nightly group. No build — just gems + secrets. +# Promotes the last build of the day to the nightly group. No build — just gems. echo "--- :rubygems: Setting up Gems" install_gems -echo "--- :closed_lock_with_key: Installing Secrets" -bundle exec fastlane run configure_apply - echo "--- :new_moon: Promoting last build of the day to nightly beta" # The lane refuses to run anywhere but trunk. bundle exec fastlane promote_nightly_build diff --git a/.buildkite/commands/prototype-build-jetpack.sh b/.buildkite/commands/prototype-build-jetpack.sh index 8e91a0bdbfe8..4dcba08ca011 100644 --- a/.buildkite/commands/prototype-build-jetpack.sh +++ b/.buildkite/commands/prototype-build-jetpack.sh @@ -7,8 +7,7 @@ fi "$(dirname "${BASH_SOURCE[0]}")/shared-set-up.sh" "$(dirname "${BASH_SOURCE[0]}")/shared-set-up-distribution.sh" -echo "--- :closed_lock_with_key: Installing Secrets" -bundle exec fastlane run configure_apply +source "$(dirname "${BASH_SOURCE[0]}")/install-a8c-secrets.sh" echo "--- :hammer_and_wrench: Building" bundle exec fastlane build_and_upload_jetpack_prototype_build diff --git a/.buildkite/commands/prototype-build-wordpress.sh b/.buildkite/commands/prototype-build-wordpress.sh index 1798ddb780b8..1300cb3f7e65 100644 --- a/.buildkite/commands/prototype-build-wordpress.sh +++ b/.buildkite/commands/prototype-build-wordpress.sh @@ -7,8 +7,7 @@ fi "$(dirname "${BASH_SOURCE[0]}")/shared-set-up.sh" "$(dirname "${BASH_SOURCE[0]}")/shared-set-up-distribution.sh" -echo "--- :closed_lock_with_key: Installing Secrets" -bundle exec fastlane run configure_apply +source "$(dirname "${BASH_SOURCE[0]}")/install-a8c-secrets.sh" echo "--- :hammer_and_wrench: Building" bundle exec fastlane build_and_upload_wordpress_prototype_build diff --git a/.buildkite/commands/release-build-jetpack.sh b/.buildkite/commands/release-build-jetpack.sh index 0c8b3ad9f3e0..6dcd2b55cd20 100755 --- a/.buildkite/commands/release-build-jetpack.sh +++ b/.buildkite/commands/release-build-jetpack.sh @@ -3,8 +3,7 @@ "$(dirname "${BASH_SOURCE[0]}")/shared-set-up.sh" "$(dirname "${BASH_SOURCE[0]}")/shared-set-up-distribution.sh" -echo "--- :closed_lock_with_key: Installing Secrets" -bundle exec fastlane run configure_apply +source "$(dirname "${BASH_SOURCE[0]}")/install-a8c-secrets.sh" echo "--- :hammer_and_wrench: Building" bundle exec fastlane build_and_upload_jetpack_for_app_store diff --git a/.buildkite/commands/release-build-wordpress.sh b/.buildkite/commands/release-build-wordpress.sh index 86326de30ba7..0ec8137dd8a2 100755 --- a/.buildkite/commands/release-build-wordpress.sh +++ b/.buildkite/commands/release-build-wordpress.sh @@ -3,8 +3,7 @@ "$(dirname "${BASH_SOURCE[0]}")/shared-set-up.sh" "$(dirname "${BASH_SOURCE[0]}")/shared-set-up-distribution.sh" -echo "--- :closed_lock_with_key: Installing Secrets" -bundle exec fastlane run configure_apply +source "$(dirname "${BASH_SOURCE[0]}")/install-a8c-secrets.sh" echo "--- :hammer_and_wrench: Building" bundle exec fastlane build_and_upload_app_store_connect \ diff --git a/.buildkite/release-pipelines/code-freeze.yml b/.buildkite/release-pipelines/code-freeze.yml index e03a83cfbe41..43a93eb80064 100644 --- a/.buildkite/release-pipelines/code-freeze.yml +++ b/.buildkite/release-pipelines/code-freeze.yml @@ -18,9 +18,6 @@ steps: echo '--- :ruby: Setup Ruby tools' install_gems - echo '--- :closed_lock_with_key: Access secrets' - bundle exec fastlane run configure_apply - echo '--- :shipit: Run code freeze' bundle exec fastlane code_freeze version:"${RELEASE_VERSION}" skip_confirm:true retry: diff --git a/.buildkite/release-pipelines/new-beta-release.yml b/.buildkite/release-pipelines/new-beta-release.yml index 4835caaf293e..db065dbce699 100644 --- a/.buildkite/release-pipelines/new-beta-release.yml +++ b/.buildkite/release-pipelines/new-beta-release.yml @@ -19,9 +19,6 @@ steps: echo '--- :ruby: Setup Ruby tools' install_gems - echo '--- :closed_lock_with_key: Access secrets' - bundle exec fastlane run configure_apply - echo '--- :shipit: Deploy new beta' bundle exec fastlane new_beta_release skip_confirm:true retry: diff --git a/.buildkite/release-pipelines/new-hotfix.yml b/.buildkite/release-pipelines/new-hotfix.yml index ec8deef72852..d4a48fae2dc0 100644 --- a/.buildkite/release-pipelines/new-hotfix.yml +++ b/.buildkite/release-pipelines/new-hotfix.yml @@ -19,9 +19,6 @@ steps: echo '--- :ruby: Setup Ruby tools' install_gems - echo '--- :closed_lock_with_key: Access secrets' - bundle exec fastlane run configure_apply - echo '--- :shipit: Start new hotfix' bundle exec fastlane new_hotfix_release skip_confirm:true version:"$VERSION" retry: diff --git a/.buildkite/release-pipelines/publish-release.yml b/.buildkite/release-pipelines/publish-release.yml index 024c3f616f90..f25dfffbfeee 100644 --- a/.buildkite/release-pipelines/publish-release.yml +++ b/.buildkite/release-pipelines/publish-release.yml @@ -19,9 +19,6 @@ steps: echo '--- :ruby: Setup Ruby tools' install_gems - echo '--- :closed_lock_with_key: Access secrets' - bundle exec fastlane run configure_apply - echo '--- :package: Publish Release' bundle exec fastlane publish_release skip_confirm:true retry: diff --git a/.buildkite/release-pipelines/update-app-store-strings.yml b/.buildkite/release-pipelines/update-app-store-strings.yml index 83dc1a1bd6b5..1edfa69d0cb8 100644 --- a/.buildkite/release-pipelines/update-app-store-strings.yml +++ b/.buildkite/release-pipelines/update-app-store-strings.yml @@ -18,9 +18,6 @@ steps: echo '--- :ruby: Setup Ruby tools' install_gems - echo '--- :closed_lock_with_key: Access secrets' - bundle exec fastlane run configure_apply - echo '--- :shipit: Update relaese notes and other App Store metadata' bundle exec fastlane update_appstore_strings skip_confirm:true retry: diff --git a/.buildkite/shared-pipeline-vars b/.buildkite/shared-pipeline-vars index ef632b72f9df..01b4e25703c9 100755 --- a/.buildkite/shared-pipeline-vars +++ b/.buildkite/shared-pipeline-vars @@ -5,7 +5,7 @@ # The ~> modifier is not currently used, but we check for it just in case XCODE_VERSION=$(sed -E 's/^~> ?//' .xcode-version) -CI_TOOLKIT_PLUGIN_VERSION="6.1.1" +CI_TOOLKIT_PLUGIN_VERSION="6.2.0" TEST_COLLECTOR_PLUGIN_VERSION="1.11.0" export IMAGE_ID="xcode-$XCODE_VERSION" diff --git a/.configure b/.configure deleted file mode 100644 index b7892ab8149c..000000000000 --- a/.configure +++ /dev/null @@ -1,13 +0,0 @@ -{ - "project_name": "WordPress-iOS", - "branch": "trunk", - "pinned_hash": "6baf4e086398ddf8141d7132e557703a715fafd2", - "files_to_copy": [ - { - "file": "iOS/WPiOS/Secrets.swift", - "destination": "~/.configure/wordpress-ios/secrets/Secrets.swift", - "encrypt": true - } - ], - "file_dependencies": [] -} diff --git a/.configure-files/Secrets.swift.enc b/.configure-files/Secrets.swift.enc deleted file mode 100644 index 500132fd96da..000000000000 Binary files a/.configure-files/Secrets.swift.enc and /dev/null differ diff --git a/.gitattributes b/.gitattributes index 648ab329c02f..3b002f08fa65 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,4 @@ RELEASE-NOTES.txt merge=union *.strings diff=localizablestrings -.configure-files/*.enc binary +.a8c-secrets/*.age binary diff --git a/.gitignore b/.gitignore index 12c9beff70d0..de1564ba1a58 100644 --- a/.gitignore +++ b/.gitignore @@ -85,10 +85,12 @@ Scripts/fastlane/ # CI Artifacts Location Artifacts -# All encrypted secrets should be stored under .configure-files -# Everything without a .enc extension is ignored -.configure-files/* -!.configure-files/*.enc +# a8c-secrets decrypts into ~/.a8c-secrets//, outside the checkout. +# In-repo, track only the repo id, the public keys, and the encrypted *.age blobs. +.a8c-secrets/* +!.a8c-secrets/repo-id +!.a8c-secrets/keys.pub +!.a8c-secrets/*.age # A file external contributors can have locally to provide their own credentials. # This file is created during the `rake init:oss` task, based on the Secrets-example.swift file. diff --git a/CODEOWNERS b/CODEOWNERS index c29db1d94519..220249b7e6e5 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -24,4 +24,4 @@ Dangerfile* @wordpress-mobile/apps-infra-tooling .xcode-version @wordpress-mobile/apps-infra-tooling # Secrets -.configure-files/ @wordpress-mobile/apps-infra-tooling +.a8c-secrets/ @wordpress-mobile/apps-infra-tooling diff --git a/Rakefile b/Rakefile index 5c03a487e2d9..7d317e9cbb5c 100644 --- a/Rakefile +++ b/Rakefile @@ -17,7 +17,7 @@ desc 'Install required dependencies' task dependencies: %w[dependencies:check dependencies:gutenberg_xcframeworks] namespace :dependencies do - task check: %w[ruby:check bundler:check bundle:check credentials:apply] + task check: %w[ruby:check bundler:check bundle:check] namespace :ruby do task :check do @@ -75,25 +75,6 @@ namespace :dependencies do CLOBBER << '.bundle' end - namespace :credentials do - task :apply do - next unless Dir.exist?(File.join(Dir.home, '.mobile-secrets/.git')) || ENV.key?('CONFIGURE_ENCRYPTION_KEY') - - # The string is indented all the way to the left to avoid padding when printed in the terminal - command = %( -FASTLANE_SKIP_UPDATE_CHECK=1 \ -FASTLANE_HIDE_CHANGELOG=1 \ -FASTLANE_HIDE_PLUGINS_TABLE=1 \ -FASTLANE_ENV_PRINTER=1 \ -FASTLANE_SKIP_ACTION_SUMMARY=1 \ -FASTLANE_HIDE_TIMESTAMP=1 \ -bundle exec fastlane run configure_apply force:true - ) - - sh(command) - end - end - desc 'Download and extract Gutenberg xcframeworks' task :gutenberg_xcframeworks do sh("#{PROJECT_DIR}/Scripts/download-gutenberg-xcframeworks.sh") @@ -200,7 +181,6 @@ namespace :init do dependencies install:tools:check_developer credentials:setup - gpg_key:setup ] end @@ -330,7 +310,6 @@ namespace :install do developer_tools = { 'convert' => 'imagemagick', 'gs' => 'ghostscript', 'sentry-cli' => 'getsentry/tools/sentry-cli', - 'gpg' => 'gpg', 'git-crypt' => 'git-crypt' } # Check for tool, install if not installed @@ -426,99 +405,6 @@ namespace :credentials do end end -namespace :gpg_key do - # automate the process of creatong a GPG key - task setup: %w[gpg_key:check gpg_key:prompt gpg_key:finish] - - # confirm that GPG tools is installed - task :check do - puts 'Checking system for GPG Tools' - if command?('gpg') - puts 'GPG Tools found' - else - Rake::Task['gpg_key:install'].invoke - end - end - - # install GPG Tools - task :install do - puts 'GPG Tools not found. Installing GPG Tools' - sh 'brew install gpg' - end - - # Ask developer if they need to create a new key. - # If yes, begin process of creating key, if no move on - task :prompt do - next unless create_gpg_key? - - if create_default_key? - display_default_config_helpers - Rake::Task['gpg_key:generate_default'].invoke - else - Rake::Task['gpg_key:generate_custom'].invoke - end - end - - # Generate new GPG key - task :generate_custom do - puts '' - puts 'Begin Generating Custom GPG Keys' - puts '=====================================================================================' - - sh 'gpg --full-generate-key', verbose: false - end - - # Generate new default GPG key - task :generate_default do - puts '' - puts 'Begin Generating Default GPG Keys' - puts '=====================================================================================' - - sh 'gpg --generate-key', verbose: false - end - - # prompt developer to send GPG key to Platform - task :finish do - puts '=====================================================================================' - puts 'Key Generation Complete!' - puts 'Please send your GPG public key to Platform 9-3/4' - puts 'You can contact them in the Slack channel #platform9' - puts '=====================================================================================' - end - - # ask user if they want to create a key, loop till given a valid answer - def create_gpg_key? - puts '=====================================================================================' - puts 'To access production credentials for the WordPress app you will need to a GPG Key' - puts 'Do you need to generate a new GPG Key?' - puts "Press 'Y' to create a new key. Press 'N' to skip" - - display_prompt_response? - end - - # ask user if they want to create a key, loop till given a valid answer - def create_default_key? - puts '=====================================================================================' - puts 'You can choose to setup with a default or custom key pair setup' - puts 'Default setup - Type: RSA to RSA, RSA length: 2048, Valid for: does not expire' - puts 'Would you like to continue with the default setup?' - puts '=====================================================================================' - puts "Press 'Y' for Yes. Press 'N' for custom configuration" - - display_prompt_response? - end - - # display prompt for developer to aid in setting up default key - def display_default_config_helpers - puts '' - puts '' - puts '=====================================================================================' - puts 'You will need to enter the following info to create your key' - puts 'Please enter your real name, email address, and a password for your key when prompted' - puts '=====================================================================================' - end -end - # prompt for a Y or N response, continue asking if other character # return true for Y and false for N def display_prompt_response? diff --git a/Scripts/BuildPhases/DecryptSecrets.sh b/Scripts/BuildPhases/DecryptSecrets.sh new file mode 100755 index 000000000000..63113f3d206b --- /dev/null +++ b/Scripts/BuildPhases/DecryptSecrets.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +set -euo pipefail + +# Runs from the `Decrypt Secrets` aggregate target so it happens once per build: +# `a8c-secrets decrypt` is not safe to run concurrently, and the ten targets that +# consume the secrets build in parallel. + +# Build phases don't inherit the shell's PATH, so point at a8c-secrets' default +# install location. +export PATH="$HOME/.local/bin:$PATH" + +# External contributors build with their own credentials and never install the tool. +if ! command -v a8c-secrets > /dev/null 2>&1; then + echo "warning: a8c-secrets not installed; skipping secrets decryption." + exit 0 +fi + +a8c-secrets decrypt --non-interactive diff --git a/Scripts/BuildPhases/GenerateCredentials.sh b/Scripts/BuildPhases/GenerateCredentials.sh index 8afb065ffdd8..8b1e640ad273 100755 --- a/Scripts/BuildPhases/GenerateCredentials.sh +++ b/Scripts/BuildPhases/GenerateCredentials.sh @@ -2,8 +2,14 @@ set -euo pipefail -# The Secrets File Sources -SECRETS_ROOT="${HOME}/.configure/wordpress-ios/secrets" +# The committed .age blob is the versioned source of the decrypted secrets file. +# Where a8c-secrets puts the plaintext is the tool's business, so ask it rather +# than spelling out its layout here. +# +# Reach the repo root by trimming SRCROOT's last component rather than appending +# `/..`: the input file list this path is matched against is the one Xcode +# resolved, and Xcode collapses `..` when it writes it. +ENCRYPTED_SECRETS_FILE="${SRCROOT%/*}/.a8c-secrets/Secrets.swift.age" # 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 @@ -49,8 +55,7 @@ function ensure_is_in_input_files_list() { fi } -SECRETS_FILE="${SECRETS_ROOT}/Secrets.swift" -ensure_is_in_input_files_list $SECRETS_FILE +ensure_is_in_input_files_list $ENCRYPTED_SECRETS_FILE LOCAL_SECRETS_FILE="${SRCROOT}/Credentials/Secrets.swift" EXAMPLE_SECRETS_FILE="${SRCROOT}/Credentials/Secrets-example.swift" @@ -60,10 +65,11 @@ ensure_is_in_input_files_list $EXAMPLE_SECRETS_FILE SECRETS_DESTINATION_FILE="${SCRIPT_OUTPUT_FILE_0}" mkdir -p "$(dirname "$SECRETS_DESTINATION_FILE")" +# `a8c-secrets which` exits non-zero when the file has not been decrypted yet. # WordPress, Jetpack, and Reader use all the same secrets at this time. -if [ -f "$SECRETS_FILE" ]; then +if command -v a8c-secrets > /dev/null 2>&1 && SECRETS_FILE=$(a8c-secrets which Secrets.swift 2>/dev/null); then echo "Applying Production Secrets" - cp -v "$SECRETS_FILE" "${SECRETS_DESTINATION_FILE}" + cp "$SECRETS_FILE" "$SECRETS_DESTINATION_FILE" exit 0 fi @@ -78,15 +84,15 @@ if [ -f "$LOCAL_SECRETS_FILE" ]; then echo "warning: Using local Secrets from $LOCAL_SECRETS_FILE. If you are an external contributor, this is expected and you can ignore this warning. If you are an internal contributor, make sure to use our shared credentials instead." echo "Applying Local Secrets" - cp -v "$LOCAL_SECRETS_FILE" "${SECRETS_DESTINATION_FILE}" + cp "$LOCAL_SECRETS_FILE" "$SECRETS_DESTINATION_FILE" exit 0 fi # None of the above secrets was 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 and try again" +COULD_NOT_FIND_SECRET_MSG="Could not find secrets file at ${SECRETS_DESTINATION_FILE}. This is likely due to the secrets not having been decrypted" +INTERNAL_CONTRIBUTOR_MSG="If you are an internal contributor, run \`a8c-secrets decrypt\` to update your secrets and try again (see https://github.com/Automattic/a8c-secrets for setup)" EXTERNAL_CONTRIBUTOR_MSG="If you are an external contributor, run \`bundle exec rake init:oss\` to set up and use your own credentials" case $CONFIGURATION in @@ -100,6 +106,6 @@ case $CONFIGURATION in *) 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. $EXTERNAL_CONTRIBUTOR_MSG." echo "Applying Example Secrets" - cp -v "$EXAMPLE_SECRETS_FILE" "${SECRETS_DESTINATION_FILE}" + cp "$EXAMPLE_SECRETS_FILE" "$SECRETS_DESTINATION_FILE" ;; esac diff --git a/Scripts/BuildPhases/GenerateCredentials.xcfilelist b/Scripts/BuildPhases/GenerateCredentials.xcfilelist index 2d99cf0ff613..3556dff3b751 100644 --- a/Scripts/BuildPhases/GenerateCredentials.xcfilelist +++ b/Scripts/BuildPhases/GenerateCredentials.xcfilelist @@ -1,6 +1,10 @@ # Lists of input files for the script that populates the app's secrets with the # correct values for the current scheme and build configuration. -${HOME}/.configure/wordpress-ios/secrets/Secrets.swift + +# The committed .age is the versioned source of the decrypted secrets file the +# phase actually reads (via `a8c-secrets which`), so tracking it re-runs the +# phase after a pull that rotates the secret. +${SRCROOT}/../.a8c-secrets/Secrets.swift.age # Local Secrets file that external contributors can use to specify their own # ClientID and Secrets. This file is created by the Rakefile when external diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 5964c2e9431d..917402529ba6 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -7,6 +7,17 @@ objects = { /* Begin PBXAggregateTarget section */ + 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */ = { + isa = PBXAggregateTarget; + buildConfigurationList = D53494F78D616808DCB4A45E /* Build configuration list for PBXAggregateTarget "Decrypt Secrets" */; + buildPhases = ( + 038B974054F8161836A4FE44 /* Decrypt Secrets */, + ); + dependencies = ( + ); + name = "Decrypt Secrets"; + productName = "Decrypt Secrets"; + }; FFA8E22A1F94E3DE0002170F /* SwiftLint */ = { isa = PBXAggregateTarget; buildConfigurationList = FFA8E22F1F94E3DE0002170F /* Build configuration list for PBXAggregateTarget "SwiftLint" */; @@ -214,6 +225,13 @@ remoteGlobalIDString = 0107E0B128F97D5000DE87DB; remoteInfo = JetpackStatsWidgets; }; + 0622080DC83F4B988D9A7732 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0A4FB5FE91E0FB8978A881A4; + remoteInfo = "Decrypt Secrets"; + }; 0C3313C42E0439A9000C3760 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; @@ -228,6 +246,13 @@ remoteGlobalIDString = 0CED016F2D95B897003015CF; remoteInfo = Keystone; }; + 1D5A9F915AFDD37ADAE5B6B3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0A4FB5FE91E0FB8978A881A4; + remoteInfo = "Decrypt Secrets"; + }; 3FCFFAFD2994A949002840C9 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; @@ -249,6 +274,13 @@ remoteGlobalIDString = 1D6058900D05DD3D006BFB54; remoteInfo = WordPress; }; + 67B2B1BD1B72EDCD56E09378 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0A4FB5FE91E0FB8978A881A4; + remoteInfo = "Decrypt Secrets"; + }; 7358E6BD210BD318002323EB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; @@ -263,6 +295,13 @@ remoteGlobalIDString = 74576671202B558C00F42E40; remoteInfo = WordPressDraftActionExtension; }; + 769D3F36016EAF96E0A6942F /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0A4FB5FE91E0FB8978A881A4; + remoteInfo = "Decrypt Secrets"; + }; 8096212628E5411400940A5D /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; @@ -291,6 +330,48 @@ remoteGlobalIDString = 932225A61C7CE50300443B02; remoteInfo = WordPressShare; }; + AC3931C50F6374EE6BE0878B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0A4FB5FE91E0FB8978A881A4; + remoteInfo = "Decrypt Secrets"; + }; + B6AD221EACD79608CD4592DA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0A4FB5FE91E0FB8978A881A4; + remoteInfo = "Decrypt Secrets"; + }; + B6C4FB8D0B592DC550A800C3 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0A4FB5FE91E0FB8978A881A4; + remoteInfo = "Decrypt Secrets"; + }; + B904E75B46BF37ED7B5187FD /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0A4FB5FE91E0FB8978A881A4; + remoteInfo = "Decrypt Secrets"; + }; + D1DAAEDC31CAA402FE8A1DD8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0A4FB5FE91E0FB8978A881A4; + remoteInfo = "Decrypt Secrets"; + }; + D59FA597D783ED86B07C8D4B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0A4FB5FE91E0FB8978A881A4; + remoteInfo = "Decrypt Secrets"; + }; E16AB93E14D978520047A2E5 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */; @@ -1569,6 +1650,7 @@ buildRules = ( ); dependencies = ( + FD201323F47B01659717FF80 /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( 0C3E79892DB164B3000C7072 /* JetpackStatsWidgets */, @@ -1643,6 +1725,7 @@ ); dependencies = ( 0C5A8A7B2D9B22F100C25301 /* PBXTargetDependency */, + 6DB3D57911FC0C06F3D132CD /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( 0C5A3FAB2D9B1EF400C25301 /* Reader */, @@ -1703,6 +1786,7 @@ 932225B01C7CE50300443B02 /* PBXTargetDependency */, 7457667B202B558C00F42E40 /* PBXTargetDependency */, 7358E6BE210BD318002323EB /* PBXTargetDependency */, + 3828A866957B1D2DD25E64C4 /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( 0C3C98902DA04EF9009F3BFB /* WordPress */, @@ -1755,6 +1839,7 @@ buildRules = ( ); dependencies = ( + 65CC6335ECE100E214DE55FE /* PBXTargetDependency */, ); name = WordPressNotificationServiceExtension; packageProductDependencies = ( @@ -1777,6 +1862,7 @@ buildRules = ( ); dependencies = ( + 27FB1E0DB05514EA97FBA227 /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( 0C1CB0CD2D95C63C00494A8C /* Sources */, @@ -1802,6 +1888,7 @@ buildRules = ( ); dependencies = ( + 0502FF518F1263A191852804 /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( 0C1CB0CD2D95C63C00494A8C /* Sources */, @@ -1827,6 +1914,7 @@ buildRules = ( ); dependencies = ( + D4295A73403A34F65E19CC82 /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( 0C1CB0CD2D95C63C00494A8C /* Sources */, @@ -1852,6 +1940,7 @@ buildRules = ( ); dependencies = ( + CF65101CD8CB91DC81A54D2C /* PBXTargetDependency */, ); name = JetpackNotificationServiceExtension; packageProductDependencies = ( @@ -1874,6 +1963,7 @@ buildRules = ( ); dependencies = ( + 8852AC3D54E4A0AD8F746230 /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( 0C1CB0CD2D95C63C00494A8C /* Sources */, @@ -1933,6 +2023,7 @@ 8096212728E5411400940A5D /* PBXTargetDependency */, 8096219028E55F8600940A5D /* PBXTargetDependency */, 80F6D05F28EE88FC00953C1A /* PBXTargetDependency */, + 48675A72EB62C7BDFF515517 /* PBXTargetDependency */, ); fileSystemSynchronizedGroups = ( 0C3C988F2DA04EEF009F3BFB /* Jetpack */, @@ -2110,6 +2201,7 @@ 0C3313B62E0439A8000C3760 /* Miniature */, 0C3313C22E0439A9000C3760 /* MiniatureTests */, 4A8280FC2E5FE9B60037E180 /* WordPressKitTests */, + 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */, ); }; /* End PBXProject section */ @@ -2261,6 +2353,25 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 038B974054F8161836A4FE44 /* Decrypt Secrets */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "Decrypt Secrets"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${SRCROOT}/../Scripts/BuildPhases/DecryptSecrets.sh\"\n"; + }; 09607CE7281C9CA6002D2E5A /* [Lint] Check AppLocalizedString usage */ = { isa = PBXShellScriptBuildPhase; alwaysOutOfDate = 1; @@ -2738,6 +2849,12 @@ target = 0107E0B128F97D5000DE87DB /* JetpackStatsWidgets */; targetProxy = 0107E0EC28F97E6100DE87DB /* PBXContainerItemProxy */; }; + 0502FF518F1263A191852804 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Decrypt Secrets"; + target = 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */; + targetProxy = D1DAAEDC31CAA402FE8A1DD8 /* PBXContainerItemProxy */; + }; 0C3313C52E0439A9000C3760 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 0C3313B62E0439A8000C3760 /* Miniature */; @@ -2748,6 +2865,18 @@ target = 0CED016F2D95B897003015CF /* Keystone */; targetProxy = 0C5A8A7A2D9B22F100C25301 /* PBXContainerItemProxy */; }; + 27FB1E0DB05514EA97FBA227 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Decrypt Secrets"; + target = 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */; + targetProxy = B904E75B46BF37ED7B5187FD /* PBXContainerItemProxy */; + }; + 3828A866957B1D2DD25E64C4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Decrypt Secrets"; + target = 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */; + targetProxy = AC3931C50F6374EE6BE0878B /* PBXContainerItemProxy */; + }; 3FCFFAFE2994A949002840C9 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = FFA8E22A1F94E3DE0002170F /* SwiftLint */; @@ -2758,11 +2887,29 @@ target = FFA8E22A1F94E3DE0002170F /* SwiftLint */; targetProxy = 3FCFFAFF2994AB25002840C9 /* PBXContainerItemProxy */; }; + 48675A72EB62C7BDFF515517 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Decrypt Secrets"; + target = 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */; + targetProxy = 1D5A9F915AFDD37ADAE5B6B3 /* PBXContainerItemProxy */; + }; 4A8281022E5FE9B60037E180 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 1D6058900D05DD3D006BFB54 /* WordPress */; targetProxy = 4A8281012E5FE9B60037E180 /* PBXContainerItemProxy */; }; + 65CC6335ECE100E214DE55FE /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Decrypt Secrets"; + target = 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */; + targetProxy = D59FA597D783ED86B07C8D4B /* PBXContainerItemProxy */; + }; + 6DB3D57911FC0C06F3D132CD /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Decrypt Secrets"; + target = 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */; + targetProxy = 0622080DC83F4B988D9A7732 /* PBXContainerItemProxy */; + }; 7358E6BE210BD318002323EB /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 7358E6B7210BD318002323EB /* WordPressNotificationServiceExtension */; @@ -2788,16 +2935,40 @@ target = 80F6D01F28EE866A00953C1A /* JetpackNotificationServiceExtension */; targetProxy = 80F6D05E28EE88FC00953C1A /* PBXContainerItemProxy */; }; + 8852AC3D54E4A0AD8F746230 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Decrypt Secrets"; + target = 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */; + targetProxy = 769D3F36016EAF96E0A6942F /* PBXContainerItemProxy */; + }; 932225B01C7CE50300443B02 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 932225A61C7CE50300443B02 /* WordPressShareExtension */; targetProxy = 932225AF1C7CE50300443B02 /* PBXContainerItemProxy */; }; + CF65101CD8CB91DC81A54D2C /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Decrypt Secrets"; + target = 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */; + targetProxy = B6C4FB8D0B592DC550A800C3 /* PBXContainerItemProxy */; + }; + D4295A73403A34F65E19CC82 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Decrypt Secrets"; + target = 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */; + targetProxy = 67B2B1BD1B72EDCD56E09378 /* PBXContainerItemProxy */; + }; E16AB93F14D978520047A2E5 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 1D6058900D05DD3D006BFB54 /* WordPress */; targetProxy = E16AB93E14D978520047A2E5 /* PBXContainerItemProxy */; }; + FD201323F47B01659717FF80 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = "Decrypt Secrets"; + target = 0A4FB5FE91E0FB8978A881A4 /* Decrypt Secrets */; + targetProxy = B6AD221EACD79608CD4592DA /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -3773,6 +3944,32 @@ }; name = Release; }; + 3F004C7A3022F6B50020B519 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + PRODUCT_NAME = "Decrypt Secrets"; + }; + name = Debug; + }; + 3F004C7B3022F6B50020B519 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + PRODUCT_NAME = "Decrypt Secrets"; + }; + name = Release; + }; + 3F004C7C3022F6B50020B519 /* Release-Alpha */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "Decrypt Secrets"; + }; + name = "Release-Alpha"; + }; 4A8281032E5FE9B60037E180 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = F14B5F70208E648200439554 /* WordPress.debug.xcconfig */; @@ -5345,6 +5542,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + D53494F78D616808DCB4A45E /* Build configuration list for PBXAggregateTarget "Decrypt Secrets" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 3F004C7A3022F6B50020B519 /* Debug */, + 3F004C7B3022F6B50020B519 /* Release */, + 3F004C7C3022F6B50020B519 /* Release-Alpha */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; E16AB93D14D978240047A2E5 /* Build configuration list for PBXNativeTarget "WordPressTest" */ = { isa = XCConfigurationList; buildConfigurations = (