diff --git a/.github/workflows/validate-pull-request.yml b/.github/workflows/validate-pull-request.yml new file mode 100644 index 0000000..a49a23b --- /dev/null +++ b/.github/workflows/validate-pull-request.yml @@ -0,0 +1,30 @@ +name: MPSDK Pull Request Validator + +on: + pull_request: + branches: + - main + push: + branches: + - main + +jobs: + validate: + runs-on: macos-latest + + steps: + - name: Checkout Repository + uses: actions/checkout@v3 + + - name: Setup Ruby + uses: ruby/setup-ruby@v1 + with: + bundler-cache: true # runs 'bundle install' and caches installed gems automatically + + - name: Run Pull Request Validator + run: | + # Make sure the script is executable + chmod +x Scripts/git/pull-request-validator.rb + + # Run the validation script + ruby Scripts/git/pull-request-validator.rb diff --git a/.ruby-version b/.ruby-version new file mode 100644 index 0000000..acf9bf0 --- /dev/null +++ b/.ruby-version @@ -0,0 +1 @@ +3.2.2 \ No newline at end of file diff --git a/Gemfile b/Gemfile new file mode 100644 index 0000000..ff364f1 --- /dev/null +++ b/Gemfile @@ -0,0 +1,5 @@ +source 'https://rubygems.org' + +gem 'erb' +gem 'fileutils' +gem 'open3' \ No newline at end of file diff --git a/Gemfile.lock b/Gemfile.lock new file mode 100644 index 0000000..27524c2 --- /dev/null +++ b/Gemfile.lock @@ -0,0 +1,21 @@ +GEM + remote: https://rubygems.org/ + specs: + cgi (0.4.1) + erb (4.0.4) + cgi (>= 0.3.3) + fileutils (1.7.2) + open3 (0.2.1) + +PLATFORMS + arm64-darwin-22 + arm64-darwin-23 + ruby + +DEPENDENCIES + erb + fileutils + open3 + +BUNDLED WITH + 2.5.5 diff --git a/MockReaderUI.podspec b/MockReaderUI.podspec index 87dc73f..dd93d55 100644 --- a/MockReaderUI.podspec +++ b/MockReaderUI.podspec @@ -1,20 +1,18 @@ -require './podspec_constants' - Pod::Spec.new do |s| s.name = 'MockReaderUI' - s.version = SquareMobilePaymentsSDK::VERSION - s.license = SquareMobilePaymentsSDK::LICENSE - s.homepage = SquareMobilePaymentsSDK::HOMEPAGE_URL - s.authors = SquareMobilePaymentsSDK::AUTHORS + s.version = '2.0.0-beta1' + s.license = {:type=>"Square Developer License", :text=>"Copyright (c) 2020-present, Square, Inc. All rights reserved.\n\nYour use of this software is subject to the Square Developer Terms of\nService (https://squareup.com/legal/developers). This copyright notice shall\nbe included in all copies or substantial portions of the software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"} + s.homepage = 'https://github.com/square/mobile-payments-sdk-ios' + s.authors = 'Square' s.summary = 'Enables developers to build use mock readers for testing the MobilePaymentsSDK' - s.ios.deployment_target = SquareMobilePaymentsSDK::IOS_DEPLOYMENT_TARGET + s.ios.deployment_target = '15.0' - s.source ={ :git => "https://github.com/square/mobile-payments-sdk-ios.git" , :tag => SquareMobilePaymentsSDK::VERSION } + s.source ={ :git => "https://github.com/square/mobile-payments-sdk-ios.git" , :tag => "2.0.0-beta1" } s.vendored_frameworks = 'MockReaderUI.xcframework' s.prepare_command = <<-CMD - unzip XCFrameworks/MockReaderUI_#{SquareMobilePaymentsSDK::COMMIT_SHA}.zip + unzip XCFrameworks/MockReaderUI_6432c60c8568.zip CMD -end \ No newline at end of file +end diff --git a/Package.swift b/Package.swift index 07b3aa7..4d9cd6b 100644 --- a/Package.swift +++ b/Package.swift @@ -19,4 +19,4 @@ let package = Package( path: "XCFrameworks/MockReaderUI_6432c60c8568.zip" ), ] -) \ No newline at end of file +) diff --git a/README.md b/README.md index f307a4d..f3762a2 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,11 @@ Install with [CocoaPods](http://cocoapods.org/) by adding the following to your ``` use_frameworks! -pod "SquareMobilePaymentsSDK", "~> 2.0.0.beta1" +pod "SquareMobilePaymentsSDK", "~> 2.0.0-beta1" # Optionally include MockReaderUI if you wish to simulate a physical reader when one is not present. # This feature is only available when provided a sandbox application ID. -pod "MockReaderUI", "~> 2.0.0.beta1", configurations: ['Debug'] +pod "MockReaderUI", "~> 2.0.0-beta1", configurations: ['Debug'] ``` _Note that MockReaderUI framework **requires** the `SquareMobilePaymentsSDK` framework to also be present in your `Podfile`._ @@ -49,7 +49,7 @@ fi Make sure this build phase is after any `[CP] Embed Pods Frameworks` or `Embed Frameworks` Build Phase. -> [!WARNING] +> [!WARNING] > Please note that the `MockReaderUI` product should only be used in debug configurations and is not to be included in the release version of your application. ### 3. Start integrating the SDK diff --git a/Scripts/git/pull-request-validator.rb b/Scripts/git/pull-request-validator.rb new file mode 100644 index 0000000..abe6b8e --- /dev/null +++ b/Scripts/git/pull-request-validator.rb @@ -0,0 +1,10 @@ +require_relative '../sdk_validator' + +# Validate Podspecs, SPM, and Templated Files +unless Validator.validate_podspecs && Validator.validate_spm_package && Validator.validate_template_files + puts "❌ Pull Request Validation Failed" + exit 1 +else + puts "✅ Pull Request Validation Passed" + exit 0 +end diff --git a/podspec_constants.rb b/Scripts/sdk_constants.rb similarity index 99% rename from podspec_constants.rb rename to Scripts/sdk_constants.rb index ef11c79..9bdea81 100644 --- a/podspec_constants.rb +++ b/Scripts/sdk_constants.rb @@ -23,4 +23,4 @@ module SquareMobilePaymentsSDK HOMEPAGE_URL = 'https://github.com/square/mobile-payments-sdk-ios' AUTHORS = 'Square' IOS_DEPLOYMENT_TARGET = '15.0' -end \ No newline at end of file +end diff --git a/Scripts/sdk_utilities.rb b/Scripts/sdk_utilities.rb new file mode 100644 index 0000000..23e4141 --- /dev/null +++ b/Scripts/sdk_utilities.rb @@ -0,0 +1,45 @@ +require 'erb' +require 'fileutils' +require 'open3' + +class TemplateBuilder + def initialize(version, commit_sha, license, homepage_url, authors, ios_deployment_target) + @version = version + @commit_sha = commit_sha + @license = license + @homepage_url = homepage_url + @authors = authors + @ios_deployment_target = ios_deployment_target + end + + def build_and_write(template_path, file_name, output_dir) + template = File.read(template_path) + renderer = ERB.new(template) + result = renderer.result(binding) + File.open("#{output_dir}#{file_name}", 'w+') do |file| + file.write(result) + end + end +end + +class CommandExecutor + def self.execute(command) + stdout, stderr, _status = Open3.capture3(command) + [stdout, stderr] + end +end + +class FileComparator + def self.compare(file1_path, file2_path) + unless File.exist?(file1_path) && File.exist?(file2_path) + puts "File at #{file1_path} or at #{file2_path} does not exist." + return false + end + + unless FileUtils.identical?(file1_path, file2_path) + return false + end + + return true + end +end diff --git a/Scripts/sdk_validator.rb b/Scripts/sdk_validator.rb new file mode 100644 index 0000000..c120c72 --- /dev/null +++ b/Scripts/sdk_validator.rb @@ -0,0 +1,97 @@ +require_relative 'sdk_utilities' +require_relative 'sdk_constants' +require 'fileutils' + +class Validator + def self.validate_podspecs + puts "Validating Podspecs..." + + # Runs pod spec lint validation + command = "pod spec lint" + stdout, stderr = CommandExecutor.execute(command) + stdout.scan(/^(\w+)/).flatten + + # Validates output + unless stdout.include?("All the specs passed validation.") + puts "❌ Podspecs could not be validated" + puts stdout + return false + end + + puts "✅ All podspecs have passed validation" + return true + end + + def self.validate_spm_package + puts "Validating SPM Package..." + + # Resolves all packages in Package.swift + command = "swift package resolve" + _stdout, stderr = CommandExecutor.execute(command) + stderr.scan(/^(\w+)/).flatten + + # Validates output of resolve does not have errors. + unless stderr.nil? || stderr.empty? + puts "❌ SPM Package could not be validated" + puts stderr + return false + end + + packages_to_validate = [ + 'SquareMobilePaymentsSDK', + 'MockReaderUI' + ] + + # Validates SPM was able to resolve and extract the xcframeworks + for package in packages_to_validate do + unless File.directory?("./.build/artifacts/mobile-payments-sdk-ios/#{package}/#{package}.xcframework") + puts "❌ SPM was unable to resolve #{package}" + FileUtils.rm_rf('.build') + return false + end + end + + FileUtils.rm_rf('.build') + + puts "✅ SPM package has passed validation" + return true + end + + def self.validate_template_files + # Creates a temporary directory to write to in the CI + FileUtils.mkdir_p('tmp') + + # Creates Template Builder + template_builder = TemplateBuilder.new( + SquareMobilePaymentsSDK::VERSION, + SquareMobilePaymentsSDK::COMMIT_SHA, + SquareMobilePaymentsSDK::LICENSE, + SquareMobilePaymentsSDK::HOMEPAGE_URL, + SquareMobilePaymentsSDK::AUTHORS, + SquareMobilePaymentsSDK::IOS_DEPLOYMENT_TARGET + ) + + files_to_test = [ + 'README.md', + 'SquareMobilePaymentsSDK.podspec', + 'MockReaderUI.podspec', + 'Package.swift' + ] + + # Validates the files found in the root of the repo match the output of the templated form of the file + for file in files_to_test do + template_builder.build_and_write("./Scripts/templates/#{file}.erb", file, './tmp/') + unless FileComparator.compare("./#{file}", "./tmp/#{file}") + puts "Output of #{file}.erb rendering does not match #{file}." + puts "Please ensure you are modifying the erb template and not the output file" + FileUtils.rm_rf('tmp') + return false + end + end + + FileUtils.rm_rf('tmp') + + puts "✅ Template files have passed validation" + return true + end +end diff --git a/Scripts/templates/MockReaderUI.podspec.erb b/Scripts/templates/MockReaderUI.podspec.erb new file mode 100644 index 0000000..fb389c1 --- /dev/null +++ b/Scripts/templates/MockReaderUI.podspec.erb @@ -0,0 +1,18 @@ +Pod::Spec.new do |s| + s.name = 'MockReaderUI' + s.version = '<%= @version %>' + s.license = <%= @license %> + s.homepage = '<%= @homepage_url %>' + s.authors = '<%= @authors %>' + s.summary = 'Enables developers to build use mock readers for testing the MobilePaymentsSDK' + + s.ios.deployment_target = '<%= @ios_deployment_target %>' + + s.source ={ :git => "https://github.com/square/mobile-payments-sdk-ios.git" , :tag => "<%= @version %>" } + + s.vendored_frameworks = 'MockReaderUI.xcframework' + s.prepare_command = <<-CMD + unzip XCFrameworks/MockReaderUI_<%= @commit_sha %>.zip + CMD + +end diff --git a/Scripts/templates/Package.swift.erb b/Scripts/templates/Package.swift.erb new file mode 100644 index 0000000..35ee0e4 --- /dev/null +++ b/Scripts/templates/Package.swift.erb @@ -0,0 +1,22 @@ +// swift-tools-version:5.3 + +import PackageDescription + +let package = Package( + name: "SquareMobilePaymentsSDK", + products: [ + .library(name: "SquareMobilePaymentsSDK", targets: ["SquareMobilePaymentsSDK"]), + .library(name: "MockReaderUI", targets: ["MockReaderUI"]), + ], + dependencies: [], + targets: [ + .binaryTarget( + name: "SquareMobilePaymentsSDK", + path: "XCFrameworks/SquareMobilePaymentsSDK_<%= @commit_sha %>.zip" + ), + .binaryTarget( + name: "MockReaderUI", + path: "XCFrameworks/MockReaderUI_<%= @commit_sha %>.zip" + ), + ] +) diff --git a/Scripts/templates/README.md.erb b/Scripts/templates/README.md.erb new file mode 100644 index 0000000..0e50096 --- /dev/null +++ b/Scripts/templates/README.md.erb @@ -0,0 +1,65 @@ +[![CocoaPods](https://img.shields.io/cocoapods/v/SquareMobilePaymentsSDK)](https://github.com/CocoaPods/CocoaPods) +[![Swift Package Manager compatible](https://img.shields.io/badge/Swift%20Package%20Manager-compatible-4BC51D.svg?style=flat)](https://github.com/apple/swift-package-manager) + +# Square Mobile Payments SDK + +Build remarkable in-person experiences using Square's Mobile Payments SDK product, now in beta. Use the Mobile Payments SDK to accept in-person payments using Square hardware. The Mobile Payments SDK has the advantage of being an API-driven framework that allows for full customization and uses the latest [v2/payments](https://developer.squareup.com/explorer/square/payments-api/list-payments) API. + +Learn what you can do with the Mobile Payments SDK [here](https://developer.squareup.com/docs/mobile-payments-sdk). + +## Installation + +### 1. Add frameworks using SPM or CocoaPods + +#### Option A. Swift Package Manager + +Install with [Swift Package Manager](https://www.swift.org/documentation/package-manager/) by following these steps: + +1. Select `File > Add Package Dependencies...`. +2. Enter the repository URL: `https://github.com/square/mobile-payments-sdk-ios`. +3. Select the `Exact Version` dependency rule and specify the version as `<%= @version %>`. +4. Ensure the `SquareMobilePaymentsSDK` product is added to your target. + +Optionally, you can also add the `MockReaderUI` product to your target to simulate a physical reader when one is not present in a sandbox environment. + +#### Option B. CocoaPods + +Install with [CocoaPods](http://cocoapods.org/) by adding the following to your `Podfile`: + +``` +use_frameworks! + +pod "SquareMobilePaymentsSDK", "~> <%= @version %>" + +# Optionally include MockReaderUI if you wish to simulate a physical reader when one is not present. +# This feature is only available when provided a sandbox application ID. +pod "MockReaderUI", "~> <%= @version %>", configurations: ['Debug'] +``` +_Note that MockReaderUI framework **requires** the `SquareMobilePaymentsSDK` framework to also be present in your `Podfile`._ + +### 2. Add build phase to setup the framework + +On your application targets’ `Build Phases` settings tab, click the + icon and choose `New Run Script Phase`. Create a Run Script in which you specify your shell (ex: /bin/sh), and add the following contents to the script area below the shell: +``` +SETUP_SCRIPT=${BUILT_PRODUCTS_DIR}/${FRAMEWORKS_FOLDER_PATH}"/SquareMobilePaymentsSDK.framework/setup" +if [ -f "$SETUP_SCRIPT" ]; then + "$SETUP_SCRIPT" +fi +``` + +Make sure this build phase is after any `[CP] Embed Pods Frameworks` or `Embed Frameworks` Build Phase. + +> [!WARNING] +> Please note that the `MockReaderUI` product should only be used in debug configurations and is not to be included in the release version of your application. + +### 3. Start integrating the SDK + +Follow the [Build on iOS guide](https://developer.squareup.com/docs/mobile-payments-sdk/ios#3-initialize-the-mobile-payments-sdk) to learn how to integrate the Mobile Payments SDK in your app. + +## Documentation +* [Mobile Payments SDK Overview](https://developer.squareup.com/docs/mobile-payments-sdk) +* iOS Tech Reference + * [Mobile Payments SDK Framework](https://developer.squareup.com/docs/sdk/mobile-payments/ios) + +If you need more assistance, contact [Developer and App Marketplace Support](https://squareup.com/help/us/en/contact?panel=BF53A9C8EF68) or ask for help in the [Developer Forums](https://developer.squareup.com/forums/). + diff --git a/Scripts/templates/SquareMobilePaymentsSDK.podspec.erb b/Scripts/templates/SquareMobilePaymentsSDK.podspec.erb new file mode 100644 index 0000000..a516a9a --- /dev/null +++ b/Scripts/templates/SquareMobilePaymentsSDK.podspec.erb @@ -0,0 +1,18 @@ +Pod::Spec.new do |s| + s.name = 'SquareMobilePaymentsSDK' + s.version = '<%= @version %>' + s.license = <%= @license %> + s.homepage = '<%= @homepage_url %>' + s.authors = '<%= @authors %>' + s.summary = 'Enables developers to build secure in-person payment solutions' + + s.ios.deployment_target = '<%= @ios_deployment_target %>' + + s.source ={ :git => "https://github.com/square/mobile-payments-sdk-ios.git", :tag => "<%= @version %>" } + + s.vendored_frameworks = 'SquareMobilePaymentsSDK.xcframework' + s.prepare_command = <<-CMD + unzip XCFrameworks/SquareMobilePaymentsSDK_<%= @commit_sha %>.zip + CMD + +end diff --git a/Scripts/update-sdk-version.rb b/Scripts/update-sdk-version.rb new file mode 100644 index 0000000..587dd3c --- /dev/null +++ b/Scripts/update-sdk-version.rb @@ -0,0 +1,27 @@ +require_relative 'sdk_utilities' +require_relative 'sdk_constants' + +template_builder = TemplateBuilder.new( + SquareMobilePaymentsSDK::VERSION, + SquareMobilePaymentsSDK::COMMIT_SHA, + SquareMobilePaymentsSDK::LICENSE, + SquareMobilePaymentsSDK::HOMEPAGE_URL, + SquareMobilePaymentsSDK::AUTHORS, + SquareMobilePaymentsSDK::IOS_DEPLOYMENT_TARGET +) + +# Generate README +template_builder.build_and_write('./Scripts/templates/README.md.erb', 'README.md', './') +puts "✅ Updated README" + +# Generate SquareMobilePaymentsSDK Podsepc +template_builder.build_and_write('./Scripts/templates/SquareMobilePaymentsSDK.podspec.erb', 'SquareMobilePaymentsSDK.podspec', './') +puts "✅ Updated SquareMobilePaymentsSDK.podspec" + +# Generate MockReaderUI Podspec +template_builder.build_and_write('./Scripts/templates/MockReaderUI.podspec.erb', 'MockReaderUI.podspec', './') +puts "✅ Updated MockReaderUI.podspec" + +# Generate Package.swift +template_builder.build_and_write('./Scripts/templates/Package.swift.erb', 'Package.swift', './') +puts "✅ Updated Package.swift" diff --git a/SquareMobilePaymentsSDK.podspec b/SquareMobilePaymentsSDK.podspec index 934e6a7..f240241 100644 --- a/SquareMobilePaymentsSDK.podspec +++ b/SquareMobilePaymentsSDK.podspec @@ -1,20 +1,18 @@ -require './podspec_constants' - Pod::Spec.new do |s| s.name = 'SquareMobilePaymentsSDK' - s.version = SquareMobilePaymentsSDK::VERSION - s.license = SquareMobilePaymentsSDK::LICENSE - s.homepage = SquareMobilePaymentsSDK::HOMEPAGE_URL - s.authors = SquareMobilePaymentsSDK::AUTHORS + s.version = '2.0.0-beta1' + s.license = {:type=>"Square Developer License", :text=>"Copyright (c) 2020-present, Square, Inc. All rights reserved.\n\nYour use of this software is subject to the Square Developer Terms of\nService (https://squareup.com/legal/developers). This copyright notice shall\nbe included in all copies or substantial portions of the software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n"} + s.homepage = 'https://github.com/square/mobile-payments-sdk-ios' + s.authors = 'Square' s.summary = 'Enables developers to build secure in-person payment solutions' - s.ios.deployment_target = SquareMobilePaymentsSDK::IOS_DEPLOYMENT_TARGET + s.ios.deployment_target = '15.0' - s.source ={ :git => "https://github.com/square/mobile-payments-sdk-ios.git", :tag => SquareMobilePaymentsSDK::VERSION } + s.source ={ :git => "https://github.com/square/mobile-payments-sdk-ios.git", :tag => "2.0.0-beta1" } s.vendored_frameworks = 'SquareMobilePaymentsSDK.xcframework' s.prepare_command = <<-CMD - unzip XCFrameworks/SquareMobilePaymentsSDK_#{SquareMobilePaymentsSDK::COMMIT_SHA}.zip + unzip XCFrameworks/SquareMobilePaymentsSDK_6432c60c8568.zip CMD -end \ No newline at end of file +end