diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 4e7a9b2cbc..0000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,507 +0,0 @@ -# .circleci/config.yml - -version: 2.1 - -orbs: - aws-cli: circleci/aws-cli@3.1.4 - - # Using inline orb for now - getting-started-smoke-test: - orbs: - macos: circleci/macos@2 - node: circleci/node@5.0.2 - ruby: circleci/ruby@1.6.0 - aws-cli: circleci/aws-cli@3.1.1 - - commands: - send-metric-on-fail: - description: Send failure datapoint to cloudwatch - steps: - - run: - name: Send failure datapoint to cloudwatch - command: | - payload="{\"jobName\": \"${CIRCLE_JOB}\", \"projectRepoName\": \"${CIRCLE_PROJECT_REPONAME}\"}" - echo $payload - aws lambda invoke --function-name CircleCIWorkflowFailureHandler --payload "$payload" --cli-binary-format raw-in-base64-out response.json - when: on_fail - run-with-retry: - description: Run command with retry - parameters: - label: - description: Display name - type: string - command: - description: Command to run - type: string - retry-count: - description: Number of retry - type: integer - default: 3 - sleep: - description: Wait duration until next retry - type: integer - default: 5 - no_output_timeout: - description: Elapsed time the command can run without output - type: string - default: 10m - steps: - - run: - name: << parameters.label >> - command: | - retry() { - MAX_RETRY=<< parameters.retry-count >> - n=0 - until [ $n -ge $MAX_RETRY ] - do - << parameters.command >> && break - n=$[$n+1] - sleep << parameters.sleep >> - done - if [ $n -ge $MAX_RETRY ]; then - echo "failed: ${@}" >&2 - exit 1 - fi - } - retry - no_output_timeout: << parameters.no_output_timeout >> - jobs: - ios: - parameters: - xcode-version: - type: string - default: 13.3.0 - simulator-device: - type: string - default: iPhone 13 - simulator-os-version: - type: string - default: "15.4" - working_directory: ~/ios-canaries/canaries/example - macos: - xcode: <> - environment: - FL_OUTPUT_DIR: output - # Add steps to the job - # See: https://circleci.com/docs/2.0/configuration-reference/#steps - steps: - - checkout: - path: ~/ios-canaries - - aws-cli/setup: - role-session-name: ${CIRCLE_WORKFLOW_JOB_ID} - role-arn: ${AWS_ROLE_ARN} - session-duration: '2000' - - node/install - - run: npm install -g @aws-amplify/cli - - run: amplify init --quickstart --frontend ios - - macos/preboot-simulator: - device: <> - version: <> - - ruby/install-deps - - run-with-retry: - label: Run pod install - command: pod install - no_output_timeout: 20m - - run-with-retry: - label: Run tests - command: bundle exec fastlane scan - - send-metric-on-fail - -defaults: &defaults - macos: - xcode: '13.3.0' - working_directory: ~/amplify-swift - environment: - BUNDLE_PATH: vendor/bundle - -references: - repo_cache_key: &repo_cache_key v2-repo-{{ .Branch }}-{{ .Revision }} - - restore_repo: &restore_repo - restore_cache: - keys: - - *repo_cache_key - - v2-repo-{{ .Branch }} - - v2-repo - - pods_cache_key: &pods_cache_key v3-dependency-pods-{{ checksum "~/amplify-swift/Podfile" }} - - pods_backup_cache_key: &pods_backup_cache_key v3-dependency-pods - - restore_pods: &restore_pods - restore_cache: - keys: - - *pods_cache_key - - *pods_backup_cache_key - - plugin_pods_cache_key: &plugin_pods_cache_key - -commands: - pre_start_simulator: - description: >- - pre start simulator, build may fail if simulator is not started - steps: - - run: - name: Pre-start simulator - command: bash ~/amplify-swift/CircleciScripts/pre_start_simulator.sh - - restore_gems: - steps: - - restore_cache: - keys: - - v2-gems-{{ checksum "~/amplify-swift/Gemfile.lock" }} - - v2-gems- - - check_bundle: - steps: - - run: - name: Check bundle - command: bundle check --path $BUNDLE_PATH || bundle install --path $BUNDLE_PATH - - make_artifacts_directory: - steps: - - run: - name: Make artifacts directory - command: mkdir -p "artifacts" - - save_plugin_pods: - parameters: - prefix: - type: string - steps: - - save_cache: - key: v1-<< parameters.prefix >>-dependency-pods-{{ checksum "Podfile" }} - paths: - - ./Pods - - restore_plugin_pods: - parameters: - prefix: - type: string - steps: - - restore_cache: - keys: - - v1-<< parameters.prefix >>-dependency-pods-{{ checksum "Podfile" }} - - v1-<< parameters.prefix >>-dependency-pods - - upload_artifacts: - steps: - - store_artifacts: - path: artifacts - - -jobs: - checkout_code: - <<: *defaults - steps: - - *restore_repo - - checkout - - save_cache: - key: *repo_cache_key - paths: - - ~/amplify-swift - - install_gems: - <<: *defaults - steps: - - *restore_repo - - restore_gems - - run: - name: Bundle install - command: bundle check --path $BUNDLE_PATH || bundle install --path $BUNDLE_PATH - environment: - BUNDLE_JOBS: 4 - BUNDLE_RETRY: 3 - - save_cache: - key: v2-gems-{{ checksum "~/amplify-swift/Gemfile.lock" }} - paths: - - vendor/bundle - - build_test_amplify: - <<: *defaults - steps: - - *restore_repo - - pre_start_simulator - - run: pod install - - restore_gems - - check_bundle - - make_artifacts_directory - - run: - name: Build amplify - command: xcodebuild build-for-testing -workspace Amplify.xcworkspace -scheme Amplify -sdk iphonesimulator -destination "${destination}" | tee "artifacts/build-Amplify.log" | xcpretty - - run: - name: Test amplify - command: xcodebuild test -workspace Amplify.xcworkspace -scheme Amplify -sdk iphonesimulator -destination "${destination}" | tee "artifacts/test-Amplify.log" | xcpretty --simple --color --report junit - - run: - name: Upload coverage report to Codecov - command: bash ~/amplify-swift/build-support/codecov.sh -F 'Amplify' -J '^Amplify$' - - store_test_results: - path: build/reports - - upload_artifacts - - build_amplify_spm: - <<: *defaults - working_directory: ~/amplify-swift/.swiftpm/xcode - steps: - - *restore_repo - - pre_start_simulator - - restore_gems - - check_bundle - - make_artifacts_directory - - run: - name: Build amplify for SPM - command: xcodebuild build-for-testing -workspace package.xcworkspace -scheme Amplify-Package -sdk iphonesimulator -destination "${destination}" | tee "artifacts/build-Ampify-for-SPM.log" | xcpretty - - build_test_aws_plugins_core: - <<: *defaults - steps: - - *restore_repo - - pre_start_simulator - - run: pod install - - restore_gems - - check_bundle - - make_artifacts_directory - - run: - name: Build AWS plugins core - command: xcodebuild build-for-testing -workspace Amplify.xcworkspace -scheme AWSPluginsCore -sdk iphonesimulator -destination "${destination}" | tee "artifacts/build-AWSPluginsCore.log" | xcpretty - - run: - name: Test AWS plugins core - command: xcodebuild test -workspace Amplify.xcworkspace -scheme AWSPluginsCore -sdk iphonesimulator -destination "${destination}" | tee "artifacts/test-AWSPluginsCore.log" | xcpretty --simple --color --report junit - - run: - name: Upload coverage report to Codecov - command: bash ~/amplify-swift/build-support/codecov.sh -F 'AWSPluginsCore' -J '^AWSPluginsCore$' - - store_test_results: - path: build/reports - - upload_artifacts - - plugin_unit_test: - <<: *defaults - parameters: - path: - type: string - workspace: - type: string - scheme: - type: string - working_directory: ~/amplify-swift/AmplifyPlugins/<< parameters.path >> - description: << parameters.path >> unit test - steps: - - *restore_repo - - restore_plugin_pods: - prefix: << parameters.path >> - - pre_start_simulator - - run: pod install - - save_plugin_pods: - prefix: << parameters.path >> - - restore_gems - - check_bundle - - make_artifacts_directory - - run: - name: Build << parameters.path >> - command: xcodebuild build-for-testing -workspace << parameters.workspace >>.xcworkspace -scheme << parameters.scheme >> -sdk iphonesimulator -destination "${destination}" | tee "artifacts/build-<< parameters.scheme >>.log" | xcpretty - - run: - name: Test << parameters.path >> - command: xcodebuild test -workspace << parameters.workspace >>.xcworkspace -scheme << parameters.scheme >> -sdk iphonesimulator -destination "${destination}" | tee "artifacts/test-<< parameters.scheme >>.log" | xcpretty --simple --color --report junit - - run: - name: Upload << parameters.path >> coverage report to Codecov - command: bash ~/amplify-swift/build-support/codecov.sh -F << parameters.path >>_plugin_unit_test -J '^<< parameters.scheme >>$' - - store_test_results: - path: build/reports - - upload_artifacts - - deploy: - <<: *defaults - parameters: - lane: - type: string - default: 'unstable' - description: deploy pods to trunk - steps: - - add_ssh_keys: - fingerprints: - - '7a:f2:7f:a6:62:1a:9e:0f:f1:03:8c:fc:86:93:77:6e' - - *restore_repo - - restore_gems - - check_bundle - - aws-cli/setup: - role-arn: $AWS_OIDC_ROLE_ARN - role-session-name: "${CIRCLE_WORKFLOW_JOB_ID}.release" - session-duration: '900' - - run: - name: Release pods - command: bundle exec fastlane << parameters.lane >> - no_output_timeout: 60m - - fortify_scan: - <<: *defaults - steps: - - *restore_repo - - run: - name: Make source directory - command: | - mkdir source - cp -r Amplify source - cp -r AmplifyPlugins source - - aws-cli/setup: - role-arn: 'arn:aws:iam::971028514469:role/CircleCiOIDC' - role-session-name: 'aws-s3-session' - - run: - name: Download License - command: | - aws s3 cp s3://amplify-swift-fortify-prod/fortify.license fortify.license - - run: - name: Download Installer - command: | - aws s3 cp s3://amplify-swift-fortify-prod/Fortify_SCA_and_Apps_22.1.1_Mac.tar.gz Fortify_SCA_and_Apps_22.1.1_Mac.tar.gz - tar -xvf Fortify_SCA_and_Apps_22.1.1_Mac.tar.gz - unzip Fortify_SCA_and_Apps_22.1.1_osx_x64.app.zip - - run: - name: Download Scripts - command: | - aws s3 cp s3://amplify-swift-fortify-prod/amplify_swift_fortify_scan.sh fortify_scan.sh - - run: - name: Run Installer - command: | - Fortify_SCA_and_Apps_22.1.1_osx_x64.app/Contents/MacOS/installbuilder.sh --mode unattended --installdir Fortify --InstallSamples 0 --fortify_license_path fortify.license --MigrateSCA 0 - export PATH=~/amplify-swift/Fortify/bin:$PATH - echo "export PATH=~/amplify-swift/Fortify/bin:\$PATH" >> "$BASH_ENV" - fortifyupdate -acceptKey - sourceanalyzer -version - - run: - name: Run Scan - command: | - sh ./fortify_scan.sh source - -deploy_requires: &deploy_requires - requires: - - build_test_amplify - - build_amplify_spm - - build_test_aws_plugins_core - - unit_test_analytics - - unit_test_api - - unit_test_auth - - unit_test_core_ml - - unit_test_datastore - - unit_test_geo - - unit_test_predictions - - unit_test_storage - - fortify_scan - -workflows: - build_test_deploy: - when: - not: - equal: [ scheduled_pipeline, << pipeline.trigger_source >> ] - jobs: - - checkout_code - - install_gems: - requires: - - checkout_code - - fortify_scan: - context: - - amplify-swift-aws-s3-download - requires: - - install_gems - - build_test_amplify: - requires: - - fortify_scan - - build_test_aws_plugins_core: - requires: - - fortify_scan - - build_amplify_spm: - requires: - - fortify_scan - - plugin_unit_test: - name: unit_test_analytics - path: Analytics - workspace: AnalyticsCategoryPlugin - scheme: AWSPinpointAnalyticsPlugin - requires: - - fortify_scan - - plugin_unit_test: - name: unit_test_api - path: API - workspace: APICategoryPlugin - scheme: AWSAPICategoryPlugin - requires: - - fortify_scan - - plugin_unit_test: - name: unit_test_auth - path: Auth - workspace: AWSCognitoAuthPlugin - scheme: AWSCognitoAuthPlugin - requires: - - fortify_scan - - plugin_unit_test: - name: unit_test_datastore - path: DataStore - workspace: DataStoreCategoryPlugin - scheme: AWSDataStoreCategoryPlugin - requires: - - fortify_scan - - plugin_unit_test: - name: unit_test_geo - path: Geo - workspace: GeoCategoryPlugin - scheme: AWSLocationGeoPlugin - requires: - - fortify_scan - - plugin_unit_test: - name: unit_test_core_ml - path: Predictions - workspace: PredictionsCategoryPlugin - scheme: CoreMLPredictionsPlugin - requires: - - fortify_scan - - plugin_unit_test: - name: unit_test_predictions - path: Predictions - workspace: PredictionsCategoryPlugin - scheme: AWSPredictionsPlugin - requires: - - fortify_scan - - plugin_unit_test: - name: unit_test_storage - path: Storage - workspace: StoragePlugin - scheme: AWSS3StoragePlugin - requires: - - fortify_scan - - deploy: - name: deploy unstable - context: amplify-swift-aws-oidc - <<: *deploy_requires - filters: - branches: - only: - - v1 - - deploy: - name: deploy stable - lane: release - context: amplify-swift-aws-oidc - <<: *deploy_requires - filters: - branches: - only: - - release-v1 - - # Scheduled smoke test workflow - # Jobs are pulled from the getting-started-smoke-test inline orb defined below - canaries: - when: - and: - - equal: [ scheduled_pipeline, << pipeline.trigger_source >> ] - - equal: [ "Canaries", << pipeline.schedule.name >> ] - jobs: - - getting-started-smoke-test/ios: - context: - - cloudwatch-monitoring - xcode-version: "13.3.0" - simulator-os-version: "15.4" - simulator-device: "iPhone 13" - - getting-started-smoke-test/ios: - context: - - cloudwatch-monitoring - xcode-version: "12.5.1" - simulator-os-version: "14.5" - simulator-device: "iPhone 12" diff --git a/.github/workflows/build_test_amplify.yml b/.github/workflows/build_test_amplify.yml new file mode 100644 index 0000000000..cf12025540 --- /dev/null +++ b/.github/workflows/build_test_amplify.yml @@ -0,0 +1,34 @@ +name: Build Test Amplify +on: + workflow_call: + workflow_dispatch: + push: + branches-ignore: + - v1 + - release-v1 + +permissions: + contents: read + +jobs: + build-test-amplify: + runs-on: macos-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + - name: Build Test Amplify + uses: ./.github/composite_actions/run_xcodebuild_test + with: + project_path: . + workspace: Amplify.xcworkspace + scheme: Amplify + + build-amplify-spm: + runs-on: macos-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + - name: Build Amplify for SPM + run: xcodebuild build-for-testing -scheme Amplify-Package -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 13,OS=latest' | xcpretty diff --git a/.github/workflows/deploy_package.yml b/.github/workflows/deploy_package.yml new file mode 100644 index 0000000000..a7d85e6e74 --- /dev/null +++ b/.github/workflows/deploy_package.yml @@ -0,0 +1,78 @@ +name: Deploy Package +on: + workflow_call: + inputs: + type: + description: 'The type of deployment. Valid values are unstable (default) and release' + default: 'unstable' + required: false + type: string + +permissions: + id-token: write + contents: write + +jobs: + build-and-test-amplify: + name: Build and Test Amplify + uses: ./.github/workflows/build_test_amplify.yml + + unit-tests: + name: Run Plugins Unit Tests + uses: ./.github/workflows/unit_test.yml + + fortify: + name: Run Fortify Scan + uses: ./.github/workflows/fortify_scan.yml + secrets: inherit + + release: + name: Release new ${{ inputs.type }} version + environment: Release + needs: [build-and-test-amplify, unit-tests, fortify] + runs-on: macos-latest + steps: + - name: Configure AWS credentials + uses: aws-actions/configure-aws-credentials@5fd3084fc36e372ff1fff382a39b10d03659f355 #v2 + with: + role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} + role-session-name: ${{ format('{0}.release', github.run_id) }} + aws-region: ${{ secrets.AWS_REGION }} + role-duration-seconds: 900 + + - id: retrieve-token + name: Retrieve Deploy Token + env: + DEPLOY_SECRET_ARN: ${{ secrets.DEPLOY_SECRET_ARN }} + run: | + PAT=$(aws secretsmanager get-secret-value \ + --secret-id "$DEPLOY_SECRET_ARN" \ + | jq -r ".SecretString | fromjson | .Credential") + echo "token=$PAT" >> $GITHUB_OUTPUT + + - name: Checkout repo + uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v3.3.0 + with: + fetch-depth: 10 + token: ${{steps.retrieve-token.outputs.token}} + + - name: Restore Gems Cache + uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + with: + path: vendor/bundle + key: v2-gems-${{ hashFiles('**/Gemfile.lock') }} + + - name: Install Bundle + env: + BUNDLE_PATH: vendor/bundle + run: | + bundle config set --local path $BUNDLE_PATH + bundle check || bundle install + + - name: Release Pods + env: + COCOAPODS_SECRET_ARN: ${{ secrets.COCOAPODS_SECRET_ARN }} + WORKING_DIRECTORY: ${{ github.workspace }} + GITHUB_EMAIL: aws-amplify-ops@amazon.com + GITHUB_USER: aws-amplify-ops + run: bundle exec fastlane ${{ inputs.type }} diff --git a/.github/workflows/deploy_release.yml b/.github/workflows/deploy_release.yml new file mode 100644 index 0000000000..01a68524e5 --- /dev/null +++ b/.github/workflows/deploy_release.yml @@ -0,0 +1,16 @@ +name: Build, Test and Release | Stable version +on: + push: + branches: + release-v1 + +permissions: + id-token: write + contents: write + +jobs: + release-stable: + uses: ./.github/workflows/deploy_package.yml + with: + type: release + secrets: inherit diff --git a/.github/workflows/deploy_unstable.yml b/.github/workflows/deploy_unstable.yml new file mode 100644 index 0000000000..ebbde132ed --- /dev/null +++ b/.github/workflows/deploy_unstable.yml @@ -0,0 +1,16 @@ +name: Build, Test and Release | Unstable version +on: + push: + branches: + v1 + +permissions: + id-token: write + contents: write + +jobs: + release-unstable: + uses: ./.github/workflows/deploy_package.yml + with: + type: unstable + secrets: inherit \ No newline at end of file diff --git a/.github/workflows/fortify_scan.yml b/.github/workflows/fortify_scan.yml new file mode 100644 index 0000000000..c4824b385a --- /dev/null +++ b/.github/workflows/fortify_scan.yml @@ -0,0 +1,56 @@ +name: Fortify Scan +on: + workflow_dispatch: + workflow_call: + push: + branches-ignore: + - v1 + - release-v1 + +permissions: + id-token: write + contents: read + +jobs: + fortify-scan: + runs-on: macos-latest + environment: Fortify + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + + - name: Make source directory + run: | + mkdir source + cp -r Amplify source + cp -r AmplifyPlugins source + - name: Configure AWS credentials for fetching fortify resources + uses: aws-actions/configure-aws-credentials@05b148adc31e091bafbaf404f745055d4d3bc9d2 # Pin to 1.6.1 + with: + role-to-assume: ${{ secrets.AWS_ROLE_TO_ASSUME }} + aws-region: ${{ secrets.AWS_REGION }} + role-session-name: GHAFortifySession + role-duration-seconds: 900 + + - name: Download License + run: | + aws s3 cp s3://${{ secrets.AWS_S3_FORTIFY_BUCKET }}${{ vars.LICENSE_PATH }} fortify.license + - name: Download Installer + run: | + aws s3 cp s3://${{ secrets.AWS_S3_FORTIFY_BUCKET }}${{ vars.INSTALLER_PATH }} Fortify_SCA_and_Apps_22.1.1_Mac.tar.gz + tar -xvf Fortify_SCA_and_Apps_22.1.1_Mac.tar.gz + unzip Fortify_SCA_and_Apps_22.1.1_osx_x64.app.zip + - name: Download Scripts + run: | + aws s3 cp s3://${{ secrets.AWS_S3_FORTIFY_BUCKET }}${{ vars.SCRIPTS_PATH }} fortify_scan.sh + - name: Run Installer + run: | + Fortify_SCA_and_Apps_22.1.1_osx_x64.app/Contents/MacOS/installbuilder.sh --mode unattended --installdir ~/amplify-swift/Fortify --InstallSamples 0 --fortify_license_path fortify.license --MigrateSCA 0 + export PATH=~/amplify-swift/Fortify/bin:$PATH + fortifyupdate -acceptKey + sourceanalyzer -version + - name: Run Scan + run: | + export PATH=~/amplify-swift/Fortify/bin:$PATH + sh ./fortify_scan.sh source \ No newline at end of file diff --git a/.github/workflows/integ_test.yml b/.github/workflows/integ_test.yml index c3811ae997..88eca776de 100644 --- a/.github/workflows/integ_test.yml +++ b/.github/workflows/integ_test.yml @@ -1,5 +1,6 @@ name: Integration Tests on: + workflow_call: push: branches: [v1] diff --git a/.github/workflows/release_kickoff.yml b/.github/workflows/release_kickoff.yml index d5161e9241..31b55f4cb7 100644 --- a/.github/workflows/release_kickoff.yml +++ b/.github/workflows/release_kickoff.yml @@ -1,4 +1,4 @@ -# Creates a PR to push main to release branch to kick-off the CircleCI release workflow +# Creates a PR to push main to release branch to kick-off the release workflow name: Release Amplify iOS V1+ on: diff --git a/.github/workflows/unit_test.yml b/.github/workflows/unit_test.yml new file mode 100644 index 0000000000..725e5cd230 --- /dev/null +++ b/.github/workflows/unit_test.yml @@ -0,0 +1,124 @@ +name: Unit Tests +on: + workflow_call: + workflow_dispatch: + push: + branches-ignore: + - v1 + - release-v1 + +permissions: + contents: read + +jobs: + unit-test-aws-plugins-core: + runs-on: macos-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + + - name: Unit Test AWSPluginsCore + uses: ./.github/composite_actions/run_xcodebuild_test + with: + project_path: . + workspace: Amplify.xcworkspace + scheme: AWSPluginsCore + + unit-test-analytics: + runs-on: macos-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + + - name: Unit Test Analytics + uses: ./.github/composite_actions/run_xcodebuild_test + with: + project_path: ./AmplifyPlugins/Analytics/ + workspace: AnalyticsCategoryPlugin.xcworkspace + scheme: AWSPinpointAnalyticsPlugin + + unit-test-api: + runs-on: macos-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + + - name: Unit Test API + uses: ./.github/composite_actions/run_xcodebuild_test + with: + project_path: ./AmplifyPlugins/API/ + workspace: APICategoryPlugin.xcworkspace + scheme: AWSAPICategoryPlugin + + unit-test-auth: + runs-on: macos-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + + - name: Unit Test Auth + uses: ./.github/composite_actions/run_xcodebuild_test + with: + project_path: ./AmplifyPlugins/Auth/ + workspace: AWSCognitoAuthPlugin.xcworkspace + scheme: AWSCognitoAuthPlugin + + unit-test-datastore: + runs-on: macos-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + + - name: Unit Test DataStore + uses: ./.github/composite_actions/run_xcodebuild_test + with: + project_path: ./AmplifyPlugins/DataStore/ + workspace: DataStoreCategoryPlugin.xcworkspace + scheme: AWSDataStoreCategoryPlugin + + unit-test-geo: + runs-on: macos-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + + - name: Unit Test Geo + uses: ./.github/composite_actions/run_xcodebuild_test + with: + project_path: ./AmplifyPlugins/Geo/ + workspace: GeoCategoryPlugin.xcworkspace + scheme: AWSLocationGeoPlugin + + unit-test-predictions: + runs-on: macos-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + + - name: Unit Test Predictions + uses: ./.github/composite_actions/run_xcodebuild_test + with: + project_path: ./AmplifyPlugins/Predictions/ + workspace: PredictionsCategoryPlugin.xcworkspace + scheme: CoreMLPredictionsPlugin + + unit-test-storage: + runs-on: macos-latest + steps: + - uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b + with: + persist-credentials: false + + - name: Unit Test Auth + uses: ./.github/composite_actions/run_xcodebuild_test + with: + project_path: ./AmplifyPlugins/Storage/ + workspace: StoragePlugin.xcworkspace + scheme: AWSS3StoragePlugin diff --git a/Amplify/Categories/DataStore/Model/Internal/Model+Codable.swift b/Amplify/Categories/DataStore/Model/Internal/Model+Codable.swift index 1fd055d95b..a91253a2ec 100644 --- a/Amplify/Categories/DataStore/Model/Internal/Model+Codable.swift +++ b/Amplify/Categories/DataStore/Model/Internal/Model+Codable.swift @@ -71,13 +71,17 @@ extension Model where Self: Codable { /// application making any change to these `public` types should be backward compatible, otherwise it will be a /// breaking change. public func toJSON(encoder: JSONEncoder? = nil) throws -> String { - let resolvedEncoder: JSONEncoder + var resolvedEncoder: JSONEncoder if let encoder = encoder { resolvedEncoder = encoder } else { resolvedEncoder = JSONEncoder(dateEncodingStrategy: ModelDateFormatting.encodingStrategy) } + if isKnownUniquelyReferenced(&resolvedEncoder) { + resolvedEncoder.outputFormatting = .sortedKeys + } + let data = try resolvedEncoder.encode(self) guard let json = String(data: data, encoding: .utf8) else { throw DataStoreError.decodingError( diff --git a/Amplify/Categories/DataStore/Model/Internal/Schema/ModelValueConverter.swift b/Amplify/Categories/DataStore/Model/Internal/Schema/ModelValueConverter.swift index e2ad3fb0f6..de961101ec 100644 --- a/Amplify/Categories/DataStore/Model/Internal/Schema/ModelValueConverter.swift +++ b/Amplify/Categories/DataStore/Model/Internal/Schema/ModelValueConverter.swift @@ -44,7 +44,9 @@ extension ModelValueConverter { } static var jsonEncoder: JSONEncoder { - JSONEncoder(dateEncodingStrategy: ModelDateFormatting.encodingStrategy) + let encoder = JSONEncoder(dateEncodingStrategy: ModelDateFormatting.encodingStrategy) + encoder.outputFormatting = .sortedKeys + return encoder } /// - Warning: Although this has `public` access, it is intended for internal & codegen use and should not be used diff --git a/AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Sync/MutationSync/OutgoingMutationQueue/OutgoingMutationQueue.swift b/AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Sync/MutationSync/OutgoingMutationQueue/OutgoingMutationQueue.swift index 5436dd5647..e9305d164a 100644 --- a/AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Sync/MutationSync/OutgoingMutationQueue/OutgoingMutationQueue.swift +++ b/AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Sync/MutationSync/OutgoingMutationQueue/OutgoingMutationQueue.swift @@ -285,7 +285,8 @@ final class OutgoingMutationQueue: OutgoingMutationQueueBehavior { api: api, storageAdapter: storageAdapter, graphQLResponseError: graphQLResponseError, - apiError: apiError + apiError: apiError, + reconciliationQueue: reconciliationQueue ) { [weak self] result in guard let self = self else { return diff --git a/AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Sync/MutationSync/OutgoingMutationQueue/ProcessMutationErrorFromCloudOperation.swift b/AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Sync/MutationSync/OutgoingMutationQueue/ProcessMutationErrorFromCloudOperation.swift index e651ff2d23..35e2bbc41f 100644 --- a/AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Sync/MutationSync/OutgoingMutationQueue/ProcessMutationErrorFromCloudOperation.swift +++ b/AmplifyPlugins/DataStore/AWSDataStoreCategoryPlugin/Sync/MutationSync/OutgoingMutationQueue/ProcessMutationErrorFromCloudOperation.swift @@ -29,6 +29,7 @@ class ProcessMutationErrorFromCloudOperation: AsynchronousOperation { private let completion: (Result) -> Void private var mutationOperation: AtomicValue>?> private weak var api: APICategoryGraphQLBehavior? + private weak var reconciliationQueue: IncomingEventReconciliationQueue? init(dataStoreConfiguration: DataStoreConfiguration, mutationEvent: MutationEvent, @@ -36,6 +37,7 @@ class ProcessMutationErrorFromCloudOperation: AsynchronousOperation { storageAdapter: StorageEngineAdapter, graphQLResponseError: GraphQLResponseError>? = nil, apiError: APIError? = nil, + reconciliationQueue: IncomingEventReconciliationQueue? = nil, completion: @escaping (Result) -> Void) { self.dataStoreConfiguration = dataStoreConfiguration self.mutationEvent = mutationEvent @@ -43,6 +45,7 @@ class ProcessMutationErrorFromCloudOperation: AsynchronousOperation { self.storageAdapter = storageAdapter self.graphQLResponseError = graphQLResponseError self.apiError = apiError + self.reconciliationQueue = reconciliationQueue self.completion = completion self.mutationOperation = AtomicValue(initialValue: nil) @@ -316,9 +319,24 @@ class ProcessMutationErrorFromCloudOperation: AsynchronousOperation { dataStoreConfiguration.errorHandler(error) } - if case .success(let response) = cloudResult, - case .failure(let error) = response { - dataStoreConfiguration.errorHandler(error) + if case let .success(graphQLResponse) = cloudResult { + if case .failure(let error) = graphQLResponse { + dataStoreConfiguration.errorHandler(error) + } else if case let .success(graphQLResult) = graphQLResponse { + guard let reconciliationQueue = reconciliationQueue else { + let dataStoreError = DataStoreError.configuration( + "reconciliationQueue is unexpectedly nil", + """ + The reference to reconciliationQueue has been released while an ongoing mutation was being processed. + \(AmplifyErrorMessages.reportBugToAWS()) + """ + ) + finish(result: .failure(dataStoreError)) + return + } + + reconciliationQueue.offer([graphQLResult], modelName: mutationEvent.modelName) + } } finish(result: .success(nil)) diff --git a/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Models/SQLModelValueConverterTests.swift b/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Models/SQLModelValueConverterTests.swift index b4aba9e6d6..619265b00e 100644 --- a/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Models/SQLModelValueConverterTests.swift +++ b/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Models/SQLModelValueConverterTests.swift @@ -52,7 +52,7 @@ class SQLModelValueConverterTests: BaseDataStoreTests { /// - bool must be `Int` (1 or 0) /// - the remaining types should not change func testModelWithEveryTypeConversionToBindings() { - let nonModelJSON = "{\"someString\":\"string\",\"someEnum\":\"foo\"}" + let nonModelJSON = "{\"someEnum\":\"foo\",\"someString\":\"string\"}" let example = exampleModel // convert model to SQLite Bindings diff --git a/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Sync/MutationQueue/ProcessMutationErrorFromCloudOperationTests.swift b/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Sync/MutationQueue/ProcessMutationErrorFromCloudOperationTests.swift index c04f275c63..6733402a35 100644 --- a/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Sync/MutationQueue/ProcessMutationErrorFromCloudOperationTests.swift +++ b/AmplifyPlugins/DataStore/AWSDataStoreCategoryPluginTests/Sync/MutationQueue/ProcessMutationErrorFromCloudOperationTests.swift @@ -25,6 +25,7 @@ class ProcessMutationErrorFromCloudOperationTests: XCTestCase { var storageAdapter: StorageEngineAdapter! var localPost = Post(title: "localTitle", content: "localContent", createdAt: .now()) let queue = OperationQueue() + let reconciliationQueue = MockReconciliationQueue() override func setUp() { tryOrFail { @@ -585,6 +586,7 @@ class ProcessMutationErrorFromCloudOperationTests: XCTestCase { api: mockAPIPlugin, storageAdapter: storageAdapter, graphQLResponseError: graphQLResponseError, + reconciliationQueue: reconciliationQueue, completion: completion) queue.addOperation(operation) @@ -662,6 +664,7 @@ class ProcessMutationErrorFromCloudOperationTests: XCTestCase { api: mockAPIPlugin, storageAdapter: storageAdapter, graphQLResponseError: graphQLResponseError, + reconciliationQueue: reconciliationQueue, completion: completion) queue.addOperation(operation) @@ -956,6 +959,7 @@ class ProcessMutationErrorFromCloudOperationTests: XCTestCase { api: mockAPIPlugin, storageAdapter: storageAdapter, graphQLResponseError: graphQLResponseError, + reconciliationQueue: reconciliationQueue, completion: completion) queue.addOperation(operation) @@ -1035,6 +1039,7 @@ class ProcessMutationErrorFromCloudOperationTests: XCTestCase { api: mockAPIPlugin, storageAdapter: storageAdapter, graphQLResponseError: graphQLResponseError, + reconciliationQueue: reconciliationQueue, completion: completion) queue.addOperation(operation) diff --git a/AmplifyPlugins/DataStore/Podfile.lock b/AmplifyPlugins/DataStore/Podfile.lock index 3df8d9c31e..fb2df83a09 100644 --- a/AmplifyPlugins/DataStore/Podfile.lock +++ b/AmplifyPlugins/DataStore/Podfile.lock @@ -23,21 +23,21 @@ PODS: - AWSMobileClient (~> 2.33.0) - AWSPluginsCore (= 1.30.4) - CwlPreconditionTesting (~> 2.0) - - AppSyncRealTimeClient (3.1.0): - - Starscream (~> 4.0.4) - - AWSAuthCore (2.33.0): - - AWSCore (= 2.33.0) - - AWSCognitoIdentityProvider (2.33.0): - - AWSCognitoIdentityProviderASF (= 2.33.0) - - AWSCore (= 2.33.0) - - AWSCognitoIdentityProviderASF (2.33.0): - - AWSCore (= 2.33.0) - - AWSCore (2.33.0) - - AWSMobileClient (2.33.0): - - AWSAuthCore (= 2.33.0) - - AWSCognitoIdentityProvider (= 2.33.0) - - AWSCognitoIdentityProviderASF (= 2.33.0) - - AWSCore (= 2.33.0) + - AppSyncRealTimeClient (3.1.2): + - Starscream (= 4.0.4) + - AWSAuthCore (2.33.5): + - AWSCore (= 2.33.5) + - AWSCognitoIdentityProvider (2.33.5): + - AWSCognitoIdentityProviderASF (= 2.33.5) + - AWSCore (= 2.33.5) + - AWSCognitoIdentityProviderASF (2.33.5): + - AWSCore (= 2.33.5) + - AWSCore (2.33.5) + - AWSMobileClient (2.33.5): + - AWSAuthCore (= 2.33.5) + - AWSCognitoIdentityProvider (= 2.33.5) + - AWSCognitoIdentityProviderASF (= 2.33.5) + - AWSCore (= 2.33.5) - AWSPluginsCore (1.30.4): - Amplify (= 1.30.4) - AWSCore (~> 2.33.0) @@ -109,12 +109,12 @@ SPEC CHECKSUMS: Amplify: 4e41668c8801667e174ab50c12bc3099c71a257f AmplifyPlugins: 1335f0919aa07329df58685a020f2311c75a5176 AmplifyTestCommon: fef1ca37417681cc246d0860cd18e4c6723fbbf7 - AppSyncRealTimeClient: 49901c6f21e541bec09281854c5695a6c1309bf7 - AWSAuthCore: 544324f7c595cba78440027039c4429e6ce588fa - AWSCognitoIdentityProvider: f7364fdae1109e6f326c19e98f5ed5b5d413d929 - AWSCognitoIdentityProviderASF: 2023303dc28588dfe95a4152e588bcea5e1f57ec - AWSCore: ff962198e35c750cb1d59cd459c51f1990e3ec68 - AWSMobileClient: 9fab7504e6403dda5988471aa82cfd33ef8a8b78 + AppSyncRealTimeClient: 36ff2f65f330bce7f1d0d2157a4ae5d255483dac + AWSAuthCore: f80d57f22ad0c781082658de8f941393ea21b955 + AWSCognitoIdentityProvider: 5eeb67304ea7ac853836d685f2b50c08d3194155 + AWSCognitoIdentityProviderASF: aaa2eb46b9775090081b33fb5134090ba253e889 + AWSCore: 6d8aa46c210e37f15c10509437a9c8570f7290bd + AWSMobileClient: 07c4cf156a1b3715cdf15493cdf11aade97d2369 AWSPluginsCore: f2188458c27e6cb09597c67876f80611d14275d7 CwlCatchException: 86760545af2a490a23e964d76d7c77442dbce79b CwlCatchExceptionSupport: a004322095d7101b945442c86adc7cec0650f676 @@ -128,4 +128,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 0bab7193bebdf470839514f327440893b0d26090 -COCOAPODS: 1.11.3 +COCOAPODS: 1.14.3 diff --git a/AmplifyPlugins/Predictions/AWSPredictionsPluginIntegrationTests/IdentifyBasicIntegrationTests.swift b/AmplifyPlugins/Predictions/AWSPredictionsPluginIntegrationTests/IdentifyBasicIntegrationTests.swift index 78a4153ffe..149f79ec31 100644 --- a/AmplifyPlugins/Predictions/AWSPredictionsPluginIntegrationTests/IdentifyBasicIntegrationTests.swift +++ b/AmplifyPlugins/Predictions/AWSPredictionsPluginIntegrationTests/IdentifyBasicIntegrationTests.swift @@ -215,7 +215,6 @@ class IdentifyBasicIntegrationTests: AWSPredictionsPluginTestBase { XCTAssertFalse(data.tables.isEmpty) XCTAssertEqual(data.tables.count, 1) XCTAssertFalse(data.keyValues.isEmpty) - XCTAssertEqual(data.keyValues.count, 4) completeInvoked.fulfill() case .failure(let error): XCTFail("Failed with \(error)") diff --git a/AmplifyTests/CoreTests/Model+CodableTests.swift b/AmplifyTests/CoreTests/Model+CodableTests.swift index 5096ddca87..b933d2552f 100644 --- a/AmplifyTests/CoreTests/Model+CodableTests.swift +++ b/AmplifyTests/CoreTests/Model+CodableTests.swift @@ -11,11 +11,11 @@ import AmplifyTestCommon class ModelCodableTests: XCTestCase { let postJSONWithFractionalSeconds = """ - {"id":"post-1","title":"title","content":"content","comments":[],"createdAt":"1970-01-12T13:46:40.123Z"} + {"comments":[],"content":"content","createdAt":"1970-01-12T13:46:40.123Z","id":"post-1","title":"title"} """ let postJSONWithoutFractionalSeconds = """ - {"id":"post-1","title":"title","content":"content","comments":[],"createdAt":"1970-01-12T13:46:40Z"} + {"comments":[],"content":"content","createdAt":"1970-01-12T13:46:40Z","id":"post-1","title":"title"} """ override func setUp() { diff --git a/Podfile.lock b/Podfile.lock index 223e5332b5..189768ff7f 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -1,5 +1,5 @@ PODS: - - AWSCore (2.33.0) + - AWSCore (2.33.5) - CwlCatchException (2.1.1): - CwlCatchExceptionSupport (~> 2.1.1) - CwlCatchExceptionSupport (2.1.1) @@ -40,7 +40,7 @@ CHECKOUT OPTIONS: :tag: 2.1.0 SPEC CHECKSUMS: - AWSCore: ff962198e35c750cb1d59cd459c51f1990e3ec68 + AWSCore: 6d8aa46c210e37f15c10509437a9c8570f7290bd CwlCatchException: 86760545af2a490a23e964d76d7c77442dbce79b CwlCatchExceptionSupport: a004322095d7101b945442c86adc7cec0650f676 CwlMachBadInstructionHandler: aa1fe9f2d08b29507c150d099434b2890247e7f8 @@ -51,4 +51,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 5e20e56b8ef40444b018a3736b7b726ff9772f00 -COCOAPODS: 1.12.0 +COCOAPODS: 1.14.3 diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 8212e0f772..6bc2b70efa 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -145,7 +145,7 @@ platform :ios do version = options[:version].to_s changelog = options[:changelog] tag = "#{version}" - plugin_root = File.expand_path("#{ENV['CIRCLE_WORKING_DIRECTORY']}/AmplifyPlugins") + plugin_root = File.expand_path("#{ENV['WORKING_DIRECTORY']}/AmplifyPlugins") sh('bundle', 'exec', 'swift', 'package', 'update')