From 752515e23af33705f01ae6687486794682a0a13f Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Thu, 6 Jun 2024 16:25:46 +0200 Subject: [PATCH 01/43] Adding scripts to detect api changes --- .github/workflows/detect_api_changes.yml | 47 ++++ .../compare_public_interface_definition.swift | 205 ++++++++++++++++++ .../generate_public_interface_definition.sh | 56 +++++ 3 files changed, 308 insertions(+) create mode 100644 .github/workflows/detect_api_changes.yml create mode 100755 Scripts/compare_public_interface_definition.swift create mode 100755 Scripts/generate_public_interface_definition.sh diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml new file mode 100644 index 0000000000..cb8e82ddbd --- /dev/null +++ b/.github/workflows/detect_api_changes.yml @@ -0,0 +1,47 @@ +name: Scan PR + +on: + workflow_dispatch: + pull_request: + types: [opened, synchronize, reopened] + push: + branches: + - develop + +jobs: + + build: + env: + sonarToken: ${{ secrets.SONAR_TOKEN }} + destination: "name=iPhone 15 Pro,OS=17.2" + project: "Adyen.xcodeproj" + params: "-derivedDataPath ./DerivedData -skipPackagePluginValidation" + runs-on: macos-14-xlarge # Apple Silicon Runner + + steps: + - uses: actions/checkout@v4 + - uses: n1hility/cancel-previous-runs@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Validate Versions + run: | + Scripts/validate-3ds2-SDK-version.sh + Scripts/validate-Adyen-SDK-version.sh + + - name: Select latest Xcode + uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: '15.1' + + - name: πŸ› οΈ Install Tools + run: | + brew install sonar-scanner + + - name: πŸ” Detect Changes + run: | + Scripts/generate_public_interface_definition.sh + ./Scripts/compare_public_interface_definition.swift ${{ github.event.pull_request.base.ref }} ${{ github.server_url }}/${{ github.repository }} + env: + params: '${{env.params}}' + scheme: 'AdyenUIHost' diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift new file mode 100755 index 0000000000..7e74762fe2 --- /dev/null +++ b/Scripts/compare_public_interface_definition.swift @@ -0,0 +1,205 @@ +#!/usr/bin/env xcrun swift + +// +// Copyright (c) 2024 Adyen N.V. +// +// This file is open source and available under the MIT license. See the LICENSE file for more info. +// + +import Foundation + +let currentDirectory = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) + +let old = CommandLine.arguments[1] +let new = CommandLine.arguments[2] + +class Element: Codable, Equatable, CustomDebugStringConvertible { + let kind: String + let name: String + let mangledName: String? + let printedName: String + let declKind: String? + + let children: [Element]? + let spiGroupNames: [String]? + + var parent: Element? + + enum CodingKeys: String, CodingKey { + case kind + case name + case printedName + case mangledName + case children + case spiGroupNames = "spi_group_names" + case declKind + } + + var debugDescription: String { + var definition = "" + spiGroupNames?.forEach { + definition += "@_spi(\($0)) " + } + definition += "public " + + if declKind == "Var" { + definition += "var " + } else if declKind == "Func" { + definition += "func " + } else if declKind == "Import" { + definition += "import" + } + + definition += "\(printedName)" + + return definition + } + + public static func == (lhs: Element, rhs: Element) -> Bool { + lhs.mangledName == rhs.mangledName + && lhs.children == rhs.children + && lhs.spiGroupNames == rhs.spiGroupNames + } + + var parentPath: String { + var parent = self.parent + var path = [parent?.name] + while parent != nil { + parent = parent?.parent + path += [parent?.name] + } + + var sanitizedPath = path.compactMap({$0}) + + if sanitizedPath.last == "TopLevel" { + sanitizedPath.removeLast() + } + + return sanitizedPath.reversed().joined(separator: ".") + } +} + +class Definition: Codable, Equatable { + let root: Element + + enum CodingKeys: String, CodingKey { + case root = "ABIRoot" + } + + public static func == (lhs: Definition, rhs: Definition) -> Bool { + lhs.root == rhs.root + } +} + +struct Change { + enum ChangeType { + case addition + case removal + case change + + var icon: String { + switch self { + case .addition: + return "🐣" + case .removal: + return "πŸ’”" + case .change: + return "πŸ”€" + } + } + } + + var changeType: ChangeType + var parentName: String + var changeDescription: String +} + +func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> [Change] { + if lhs == rhs { + return [] + } + + var changes = [Change]() + + if oldFirst, lhs.printedName != rhs.printedName { + changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "\(lhs) ➑️ \(rhs)")] + } + + if oldFirst, lhs.spiGroupNames != rhs.spiGroupNames { + changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "\(lhs) ➑️ \(rhs)")] + } + + if oldFirst, lhs.children == rhs.children { + changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "\(lhs) ➑️ \(rhs)")] + } + + changes += lhs.children?.flatMap { lhsElement in + if let rhsChildForName = rhs.children?.first(where: { ($0.mangledName ?? $0.name) == (lhsElement.mangledName ?? lhsElement.name) }) { + return recursiveCompare(element: lhsElement, to: rhsChildForName, oldFirst: oldFirst) + } else { + if oldFirst { + return [.init(changeType: .removal, parentName: lhsElement.parentPath, changeDescription: "\(lhsElement) was removed")] + } else { + return [.init(changeType: .addition, parentName: lhsElement.parentPath, changeDescription: "\(lhsElement) was added")] + } + } + } ?? [] + + return changes +} + +func setupRelationships(for element: Element, parent: Element?) { + element.children?.forEach { + $0.parent = element + setupRelationships(for: $0, parent: element) + } +} + +func compare() throws -> Bool { + let oldFileUrl = currentDirectory.appending(path: old) + let newFileUrl = currentDirectory.appending(path: new) + + //print("Old:", oldFileUrl) + //print("New:", newFileUrl) + + let decodedOldDefinition = try JSONDecoder().decode( + Definition.self, + from: Data(contentsOf: oldFileUrl) + ) + + let decodedNewDefinition = try JSONDecoder().decode( + Definition.self, + from: Data(contentsOf: newFileUrl) + ) + + if decodedOldDefinition == decodedNewDefinition { + return true + } + + setupRelationships(for: decodedOldDefinition.root, parent: nil) + setupRelationships(for: decodedNewDefinition.root, parent: nil) + + let changes = recursiveCompare(element: decodedOldDefinition.root, to: decodedNewDefinition.root, oldFirst: true) + recursiveCompare(element: decodedNewDefinition.root, to: decodedOldDefinition.root, oldFirst: false) + + var groupedChanges = [String: [Change]]() + + changes.forEach { + groupedChanges[$0.parentName] = (groupedChanges[$0.parentName] ?? []) + [$0] + } + + + groupedChanges.keys.sorted().forEach { key in + print("[\(key)]") + groupedChanges[key]?.forEach { + print("- \($0.changeType.icon) \($0.changeDescription)") + } + } + + return false +} + +do { + print(try compare() ? "βœ… Both files are equal" : "πŸ”€ Changes detected") +} catch { + print(error) +} diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh new file mode 100755 index 0000000000..45f8df63e8 --- /dev/null +++ b/Scripts/generate_public_interface_definition.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +echo "Branch:" $1 +echo "Repo:" $2 + +rm -rf .build +mv Adyen.xcodeproj Adyen.xcode_proj +rm -rf comparison_version + +function cleanup() { + rm -rf .build + rm -rf comparison_version + mv Adyen.xcode_proj Adyen.xcodeproj +} + +trap cleanup EXIT + +echo "β†˜οΈ Checking out comparison version" +mkdir comparison_version +cd comparison_version +# ${{ github.server_url }}/${{ github.repository }} # https://github.com/Adyen/adyen-ios.git +# ${{ github.event.pull_request.base.ref }} # e.g. develop +git clone -b $1 $2 +cd adyen-ios +mv Adyen.xcodeproj Adyen.xcode_proj + +echo "πŸ‘· Building comparison project" +xcodebuild -derivedDataPath .build -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -scheme "AdyenDropIn" -destination "platform=iOS,name=Any iOS Device" -target "x86_64-apple-ios16.4-simulator" -quiet + +echo "πŸ“‹ Generating comparison api_dump" +xcrun swift-api-digester -dump-sdk -module AdyenDropIn -o ../../api_dump_comparison.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" +xcrun swift-api-digester -dump-sdk -module Adyen -o ../../api_dump_comparison.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" + +cd ../.. + +# Building project in `.build` directory +echo "πŸ‘· Building updated project" +xcodebuild -derivedDataPath .build -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -scheme "AdyenDropIn" -destination "platform=iOS,name=Any iOS Device" -target "x86_64-apple-ios16.4-simulator" -quiet + +# Generating api_dump +echo "πŸ“‹ Generating new api_dump" +xcrun swift-api-digester -dump-sdk -module AdyenDropIn -o api_dump.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" +xcrun swift-api-digester -dump-sdk -module Adyen -o api_dump.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" + +echo "πŸ”€ Comparing" + +echo "- diff" +diff api_dump_comparison.json api_dump.json + +echo "- swift-api-digester -diagnose-sdk" +# This command does not take @_spi into account unfortunately (It works well with changing from public to private or add new func/var/objects) +# xcrun swift-api-digester -diagnose-sdk -module Adyen -o api_diff -use-interface-for-module Adyen -abi -BI ./last_release/adyen-ios/.build/Build/Products/Debug-iphonesimulator -I .build/Build/Products/Debug-iphonesimulator -bsdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" +# cat api_diff + +# This command also does not take @_spi into account (Same as swift-api-digester -diagnose-sdk basically but running on the json files) +xcrun swift-api-digester -diagnose-sdk --input-paths api_dump_comparison.json -input-paths api_dump.json From 5787fb85b22f3760312e903e2f5138ff59ef3a26 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Thu, 6 Jun 2024 16:27:33 +0200 Subject: [PATCH 02/43] changing github action --- .github/workflows/detect_api_changes.yml | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index cb8e82ddbd..01f566450e 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -1,4 +1,4 @@ -name: Scan PR +name: Detect public API changes on: workflow_dispatch: @@ -12,10 +12,6 @@ jobs: build: env: - sonarToken: ${{ secrets.SONAR_TOKEN }} - destination: "name=iPhone 15 Pro,OS=17.2" - project: "Adyen.xcodeproj" - params: "-derivedDataPath ./DerivedData -skipPackagePluginValidation" runs-on: macos-14-xlarge # Apple Silicon Runner steps: @@ -23,25 +19,13 @@ jobs: - uses: n1hility/cancel-previous-runs@v3 with: token: ${{ secrets.GITHUB_TOKEN }} - - - name: Validate Versions - run: | - Scripts/validate-3ds2-SDK-version.sh - Scripts/validate-Adyen-SDK-version.sh - name: Select latest Xcode uses: maxim-lobanov/setup-xcode@v1 with: xcode-version: '15.1' - - - name: πŸ› οΈ Install Tools - run: | - brew install sonar-scanner - name: πŸ” Detect Changes run: | Scripts/generate_public_interface_definition.sh ./Scripts/compare_public_interface_definition.swift ${{ github.event.pull_request.base.ref }} ${{ github.server_url }}/${{ github.repository }} - env: - params: '${{env.params}}' - scheme: 'AdyenUIHost' From b3b376554c092edca341e93aaa24464246a6527b Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Thu, 6 Jun 2024 16:34:17 +0200 Subject: [PATCH 03/43] adjusted script --- .github/workflows/detect_api_changes.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index 01f566450e..c6036bd087 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -11,7 +11,6 @@ on: jobs: build: - env: runs-on: macos-14-xlarge # Apple Silicon Runner steps: @@ -27,5 +26,10 @@ jobs: - name: πŸ” Detect Changes run: | + echo "${branch}" + echo "${baseRepo}" Scripts/generate_public_interface_definition.sh - ./Scripts/compare_public_interface_definition.swift ${{ github.event.pull_request.base.ref }} ${{ github.server_url }}/${{ github.repository }} + ./Scripts/compare_public_interface_definition.swift "${branch}" "${baseRepo}" + env: + branch: '${{ github.event.pull_request.base.ref }}' + baseRepo: '${{ github.server_url }}/${{ github.repository }}' From ffebcc23a27a6a82e544b4c32ed10033ea77ff06 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Thu, 6 Jun 2024 16:36:40 +0200 Subject: [PATCH 04/43] More changes --- .github/workflows/detect_api_changes.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index c6036bd087..b9aba44848 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -26,10 +26,10 @@ jobs: - name: πŸ” Detect Changes run: | - echo "${branch}" - echo "${baseRepo}" + echo ${branch} + echo ${baseRepo} Scripts/generate_public_interface_definition.sh - ./Scripts/compare_public_interface_definition.swift "${branch}" "${baseRepo}" + ./Scripts/compare_public_interface_definition.swift ${branch} ${baseRepo} env: branch: '${{ github.event.pull_request.base.ref }}' - baseRepo: '${{ github.server_url }}/${{ github.repository }}' + baseRepo: '${{ github.server_url }}/${{ github.repository }}.git' From 3cadff755e27251ff73428f844daa975a3ebb21a Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Thu, 6 Jun 2024 16:40:39 +0200 Subject: [PATCH 05/43] fixing script --- .github/workflows/detect_api_changes.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index b9aba44848..a576b18ec0 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -26,10 +26,8 @@ jobs: - name: πŸ” Detect Changes run: | - echo ${branch} - echo ${baseRepo} - Scripts/generate_public_interface_definition.sh - ./Scripts/compare_public_interface_definition.swift ${branch} ${baseRepo} + Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} + ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json env: branch: '${{ github.event.pull_request.base.ref }}' baseRepo: '${{ github.server_url }}/${{ github.repository }}.git' From d2cf2115c323c83464cc374a1684fa36143a78fa Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Thu, 6 Jun 2024 16:49:44 +0200 Subject: [PATCH 06/43] small sanitation --- .github/workflows/detect_api_changes.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index a576b18ec0..a313ef9593 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -29,5 +29,5 @@ jobs: Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json env: - branch: '${{ github.event.pull_request.base.ref }}' - baseRepo: '${{ github.server_url }}/${{ github.repository }}.git' + branch: '${{github.event.pull_request.base.ref}}' + baseRepo: '${{github.server_url}}/${{github.repository}}.git' From a8598f156480b986407567c540b389dc2c168c87 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Thu, 6 Jun 2024 16:56:35 +0200 Subject: [PATCH 07/43] Remove diffing --- Scripts/generate_public_interface_definition.sh | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index 45f8df63e8..462acced87 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -42,15 +42,15 @@ echo "πŸ“‹ Generating new api_dump" xcrun swift-api-digester -dump-sdk -module AdyenDropIn -o api_dump.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" xcrun swift-api-digester -dump-sdk -module Adyen -o api_dump.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" -echo "πŸ”€ Comparing" +#echo "πŸ”€ Comparing" -echo "- diff" -diff api_dump_comparison.json api_dump.json +# echo "- diff" +# diff api_dump_comparison.json api_dump.json -echo "- swift-api-digester -diagnose-sdk" +#echo "- swift-api-digester -diagnose-sdk" # This command does not take @_spi into account unfortunately (It works well with changing from public to private or add new func/var/objects) # xcrun swift-api-digester -diagnose-sdk -module Adyen -o api_diff -use-interface-for-module Adyen -abi -BI ./last_release/adyen-ios/.build/Build/Products/Debug-iphonesimulator -I .build/Build/Products/Debug-iphonesimulator -bsdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" # cat api_diff # This command also does not take @_spi into account (Same as swift-api-digester -diagnose-sdk basically but running on the json files) -xcrun swift-api-digester -diagnose-sdk --input-paths api_dump_comparison.json -input-paths api_dump.json +# xcrun swift-api-digester -diagnose-sdk --input-paths api_dump_comparison.json -input-paths api_dump.json From f4f7754b2a011a1aae99fbcd69dc6fee2407b03c Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 11:34:11 +0200 Subject: [PATCH 08/43] adding module name --- .../compare_public_interface_definition.swift | 41 +++++++++++-------- .../generate_public_interface_definition.sh | 12 ++---- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index 7e74762fe2..71fd8568c1 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -19,6 +19,7 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { let mangledName: String? let printedName: String let declKind: String? + let moduleName: String? let children: [Element]? let spiGroupNames: [String]? @@ -33,6 +34,7 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { case children case spiGroupNames = "spi_group_names" case declKind + case moduleName } var debugDescription: String { @@ -47,7 +49,7 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { } else if declKind == "Func" { definition += "func " } else if declKind == "Import" { - definition += "import" + definition += "import " } definition += "\(printedName)" @@ -57,8 +59,8 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { public static func == (lhs: Element, rhs: Element) -> Bool { lhs.mangledName == rhs.mangledName - && lhs.children == rhs.children - && lhs.spiGroupNames == rhs.spiGroupNames + && lhs.children == rhs.children + && lhs.spiGroupNames == rhs.spiGroupNames } var parentPath: String { @@ -69,12 +71,16 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { path += [parent?.name] } - var sanitizedPath = path.compactMap({$0}) + var sanitizedPath = path.compactMap { $0 } if sanitizedPath.last == "TopLevel" { sanitizedPath.removeLast() } + if let moduleName = moduleName { + sanitizedPath += [moduleName] + } + return sanitizedPath.reversed().joined(separator: ".") } } @@ -121,15 +127,7 @@ func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> var changes = [Change]() - if oldFirst, lhs.printedName != rhs.printedName { - changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "\(lhs) ➑️ \(rhs)")] - } - - if oldFirst, lhs.spiGroupNames != rhs.spiGroupNames { - changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "\(lhs) ➑️ \(rhs)")] - } - - if oldFirst, lhs.children == rhs.children { + if oldFirst, (lhs.printedName != rhs.printedName || lhs.spiGroupNames != rhs.spiGroupNames || lhs.children == rhs.children) { changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "\(lhs) ➑️ \(rhs)")] } @@ -159,8 +157,8 @@ func compare() throws -> Bool { let oldFileUrl = currentDirectory.appending(path: old) let newFileUrl = currentDirectory.appending(path: new) - //print("Old:", oldFileUrl) - //print("New:", newFileUrl) + // print("Old:", oldFileUrl) + // print("New:", newFileUrl) let decodedOldDefinition = try JSONDecoder().decode( Definition.self, @@ -179,7 +177,15 @@ func compare() throws -> Bool { setupRelationships(for: decodedOldDefinition.root, parent: nil) setupRelationships(for: decodedNewDefinition.root, parent: nil) - let changes = recursiveCompare(element: decodedOldDefinition.root, to: decodedNewDefinition.root, oldFirst: true) + recursiveCompare(element: decodedNewDefinition.root, to: decodedOldDefinition.root, oldFirst: false) + let changes = recursiveCompare( + element: decodedOldDefinition.root, + to: decodedNewDefinition.root, + oldFirst: true + ) + recursiveCompare( + element: decodedNewDefinition.root, + to: decodedOldDefinition.root, + oldFirst: false + ) var groupedChanges = [String: [Change]]() @@ -187,7 +193,6 @@ func compare() throws -> Bool { groupedChanges[$0.parentName] = (groupedChanges[$0.parentName] ?? []) + [$0] } - groupedChanges.keys.sorted().forEach { key in print("[\(key)]") groupedChanges[key]?.forEach { @@ -199,7 +204,7 @@ func compare() throws -> Bool { } do { - print(try compare() ? "βœ… Both files are equal" : "πŸ”€ Changes detected") + try print(compare() ? "βœ… Both files are equal" : "πŸ”€ Changes detected") } catch { print(error) } diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index 462acced87..60b091aa8a 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -1,7 +1,7 @@ #!/bin/bash -echo "Branch:" $1 -echo "Repo:" $2 +echo "Branch: " $1 +echo "Repo: " $2 rm -rf .build mv Adyen.xcodeproj Adyen.xcode_proj @@ -18,28 +18,24 @@ trap cleanup EXIT echo "β†˜οΈ Checking out comparison version" mkdir comparison_version cd comparison_version -# ${{ github.server_url }}/${{ github.repository }} # https://github.com/Adyen/adyen-ios.git -# ${{ github.event.pull_request.base.ref }} # e.g. develop git clone -b $1 $2 cd adyen-ios mv Adyen.xcodeproj Adyen.xcode_proj echo "πŸ‘· Building comparison project" -xcodebuild -derivedDataPath .build -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -scheme "AdyenDropIn" -destination "platform=iOS,name=Any iOS Device" -target "x86_64-apple-ios16.4-simulator" -quiet +xcodebuild -derivedDataPath .build -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -scheme "Adyen" -destination "platform=iOS,name=Any iOS Device" -target "x86_64-apple-ios16.4-simulator" -quiet echo "πŸ“‹ Generating comparison api_dump" -xcrun swift-api-digester -dump-sdk -module AdyenDropIn -o ../../api_dump_comparison.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" xcrun swift-api-digester -dump-sdk -module Adyen -o ../../api_dump_comparison.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" cd ../.. # Building project in `.build` directory echo "πŸ‘· Building updated project" -xcodebuild -derivedDataPath .build -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -scheme "AdyenDropIn" -destination "platform=iOS,name=Any iOS Device" -target "x86_64-apple-ios16.4-simulator" -quiet +xcodebuild -derivedDataPath .build -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -scheme "Adyen" -destination "platform=iOS,name=Any iOS Device" -target "x86_64-apple-ios16.4-simulator" -quiet # Generating api_dump echo "πŸ“‹ Generating new api_dump" -xcrun swift-api-digester -dump-sdk -module AdyenDropIn -o api_dump.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" xcrun swift-api-digester -dump-sdk -module Adyen -o api_dump.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" #echo "πŸ”€ Comparing" From dcdc099992b83000fc595bbb300bff0cca30e9dd Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 11:43:13 +0200 Subject: [PATCH 09/43] Try comment phase --- .github/workflows/detect_api_changes.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index a313ef9593..26833a77d5 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -31,3 +31,11 @@ jobs: env: branch: '${{github.event.pull_request.base.ref}}' baseRepo: '${{github.server_url}}/${{github.repository}}.git' + + - name: πŸ“ Comment on PR + uses: thollander/actions-comment-pull-request@v2 + with: + message: | + Comparing changes with base branch ${{ github.event.pull_request.base.ref }} + _(execution **${{ github.run_id }}** / attempt **${{ github.run_attempt }}**)_ + comment_tag: api_changes From 3d2cef1ad8cd7b9e7ceea1c1b726684aad6cd79b Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 11:57:28 +0200 Subject: [PATCH 10/43] Playing around --- .github/workflows/detect_api_changes.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index 26833a77d5..e31f475939 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -26,16 +26,19 @@ jobs: - name: πŸ” Detect Changes run: | - Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} - ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json + # Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} + # ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json + echo ${workspace} env: branch: '${{github.event.pull_request.base.ref}}' baseRepo: '${{github.server_url}}/${{github.repository}}.git' + workspace: '${{ github.workspace }}' - name: πŸ“ Comment on PR uses: thollander/actions-comment-pull-request@v2 with: message: | Comparing changes with base branch ${{ github.event.pull_request.base.ref }} + Workspace directory: ${{ github.workspace }} _(execution **${{ github.run_id }}** / attempt **${{ github.run_attempt }}**)_ comment_tag: api_changes From 9a0d19ca37c9992e77b30a66e51b00f19876149a Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 11:59:42 +0200 Subject: [PATCH 11/43] Playing around --- .github/workflows/detect_api_changes.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index e31f475939..d6752425ec 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -37,8 +37,5 @@ jobs: - name: πŸ“ Comment on PR uses: thollander/actions-comment-pull-request@v2 with: - message: | - Comparing changes with base branch ${{ github.event.pull_request.base.ref }} - Workspace directory: ${{ github.workspace }} - _(execution **${{ github.run_id }}** / attempt **${{ github.run_attempt }}**)_ + filePath: "${{ github.workspace }}/Package.swift" comment_tag: api_changes From 2fe25beee384cc4b51ed29c2aebcf64a528be4d0 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 12:02:01 +0200 Subject: [PATCH 12/43] more playing around --- .github/workflows/detect_api_changes.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index d6752425ec..cdb1770d09 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -26,16 +26,14 @@ jobs: - name: πŸ” Detect Changes run: | - # Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} - # ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json - echo ${workspace} + Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} + ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json env: branch: '${{github.event.pull_request.base.ref}}' baseRepo: '${{github.server_url}}/${{github.repository}}.git' - workspace: '${{ github.workspace }}' - name: πŸ“ Comment on PR uses: thollander/actions-comment-pull-request@v2 with: - filePath: "${{ github.workspace }}/Package.swift" + filePath: "${{ github.workspace }}/api_dump.json" comment_tag: api_changes From 8944308e63826a93649e4c0eb2b827cc8fc2b667 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 12:44:05 +0200 Subject: [PATCH 13/43] Fixing commenting --- .github/workflows/detect_api_changes.yml | 2 +- .../compare_public_interface_definition.swift | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index cdb1770d09..16c7fb03fe 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -35,5 +35,5 @@ jobs: - name: πŸ“ Comment on PR uses: thollander/actions-comment-pull-request@v2 with: - filePath: "${{ github.workspace }}/api_dump.json" + filePath: "${{ github.workspace }}/api_comparison.md" comment_tag: api_changes diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index 71fd8568c1..994ad1515d 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -193,13 +193,25 @@ func compare() throws -> Bool { groupedChanges[$0.parentName] = (groupedChanges[$0.parentName] ?? []) + [$0] } + var fileContent: [String] = ["# Public API Changes\n"] + groupedChanges.keys.sorted().forEach { key in - print("[\(key)]") + fileContent += ["## \(key)"] groupedChanges[key]?.forEach { - print("- \($0.changeType.icon) \($0.changeDescription)") + fileContent += ["- \($0.changeType.icon) \($0.changeDescription)"] } } + print(fileContent.joined(separator: "\n")) + + let outputPath = currentDirectory.appendingPathComponent("api_comparison.md") + + do { + try fileContent.joined(separator: "\n").write(to: outputPath, atomically: true, encoding: String.Encoding.utf8) + } catch { + print(error) + } + return false } From 0268bfda0bc01c002696e076346647be5e63cf6b Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 12:52:46 +0200 Subject: [PATCH 14/43] Nicer formatting --- .../compare_public_interface_definition.swift | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index 994ad1515d..368be19fd6 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -128,7 +128,7 @@ func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> var changes = [Change]() if oldFirst, (lhs.printedName != rhs.printedName || lhs.spiGroupNames != rhs.spiGroupNames || lhs.children == rhs.children) { - changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "\(lhs) ➑️ \(rhs)")] + changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "`\(lhs)` ➑️ `\(rhs)`")] } changes += lhs.children?.flatMap { lhsElement in @@ -136,9 +136,9 @@ func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> return recursiveCompare(element: lhsElement, to: rhsChildForName, oldFirst: oldFirst) } else { if oldFirst { - return [.init(changeType: .removal, parentName: lhsElement.parentPath, changeDescription: "\(lhsElement) was removed")] + return [.init(changeType: .removal, parentName: lhsElement.parentPath, changeDescription: "`\(lhsElement)` was removed")] } else { - return [.init(changeType: .addition, parentName: lhsElement.parentPath, changeDescription: "\(lhsElement) was added")] + return [.init(changeType: .addition, parentName: lhsElement.parentPath, changeDescription: "`\(lhsElement)` was added")] } } } ?? [] @@ -153,7 +153,7 @@ func setupRelationships(for element: Element, parent: Element?) { } } -func compare() throws -> Bool { +func compare() throws { let oldFileUrl = currentDirectory.appending(path: old) let newFileUrl = currentDirectory.appending(path: new) @@ -171,7 +171,8 @@ func compare() throws -> Bool { ) if decodedOldDefinition == decodedNewDefinition { - return true + try persistComparison(fileContent: "# Public API Changes\n\nβœ… Nothing detected") + return } setupRelationships(for: decodedOldDefinition.root, parent: nil) @@ -202,21 +203,17 @@ func compare() throws -> Bool { } } - print(fileContent.joined(separator: "\n")) - - let outputPath = currentDirectory.appendingPathComponent("api_comparison.md") + try persistComparison(fileContent: fileContent.joined(separator: "\n")) +} - do { - try fileContent.joined(separator: "\n").write(to: outputPath, atomically: true, encoding: String.Encoding.utf8) - } catch { - print(error) - } - - return false +func persistComparison(fileContent: String) throws { + print(fileContent) + let outputPath = currentDirectory.appendingPathComponent("api_comparison.md") + try fileContent.write(to: outputPath, atomically: true, encoding: String.Encoding.utf8) } do { - try print(compare() ? "βœ… Both files are equal" : "πŸ”€ Changes detected") + try compare() } catch { print(error) } From 65f026b4c440edb9c480e63ecb15cd08213d8d17 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 13:23:51 +0200 Subject: [PATCH 15/43] sorting changes by changeDescription --- Scripts/compare_public_interface_definition.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index 368be19fd6..17f5c3d02d 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -198,7 +198,7 @@ func compare() throws { groupedChanges.keys.sorted().forEach { key in fileContent += ["## \(key)"] - groupedChanges[key]?.forEach { + groupedChanges[key]?.sorted(by: { $0.changeDescription < $1.changeDescription }).forEach { fileContent += ["- \($0.changeType.icon) \($0.changeDescription)"] } } From b497b0e9a26676883951ff4dda720a4715940029 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 13:25:02 +0200 Subject: [PATCH 16/43] removing unused code --- Scripts/compare_public_interface_definition.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index 17f5c3d02d..6fa76c8a91 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -157,9 +157,6 @@ func compare() throws { let oldFileUrl = currentDirectory.appending(path: old) let newFileUrl = currentDirectory.appending(path: new) - // print("Old:", oldFileUrl) - // print("New:", newFileUrl) - let decodedOldDefinition = try JSONDecoder().decode( Definition.self, from: Data(contentsOf: oldFileUrl) From e1873904185dfb9137c1e3b1681457711d51c90d Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 13:55:34 +0200 Subject: [PATCH 17/43] Recreating comment to make sure it's one of the last --- .github/workflows/detect_api_changes.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index 16c7fb03fe..6d26298328 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -37,3 +37,4 @@ jobs: with: filePath: "${{ github.workspace }}/api_comparison.md" comment_tag: api_changes + mode: recreate From 2f2ff62a7d0e8db0a6515c0e56093d0779aa8e4f Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 15:39:28 +0200 Subject: [PATCH 18/43] trying out loops --- .github/workflows/detect_api_changes.yml | 8 ++- .../generate_public_interface_definition.sh | 56 ++++++++++--------- 2 files changed, 37 insertions(+), 27 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index 6d26298328..425fdd6d4a 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -26,8 +26,12 @@ jobs: - name: πŸ” Detect Changes run: | - Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} - ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json + for module in Adyen AdyenDropIn AdyenActions AdyenCard + do + echo Generating API Definition for $module + Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} $module + ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json + done env: branch: '${{github.event.pull_request.base.ref}}' baseRepo: '${{github.server_url}}/${{github.repository}}.git' diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index 60b091aa8a..3cdbc6c4c8 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -1,7 +1,17 @@ #!/bin/bash -echo "Branch: " $1 -echo "Repo: " $2 +BRANCH=$1 +REPO=$2 +TARGET="x86_64-apple-ios17.4-simulator" +SDK="`xcrun --sdk iphonesimulator --show-sdk-path`" +MODULE=$3 #"Adyen" +COMPARISON_VERSION_DIR_NAME="comparison_version_$BRANCH" + +echo "Branch: " $BRANCH +echo "Repo: " $REPO +echo "Module: " $MODULE +echo "Target: " $TARGET +echo "Dir: " $COMPARISON_VERSION_DIR_NAME rm -rf .build mv Adyen.xcodeproj Adyen.xcode_proj @@ -9,44 +19,40 @@ rm -rf comparison_version function cleanup() { rm -rf .build - rm -rf comparison_version + # rm -rf $COMPARISON_VERSION_DIR_NAME mv Adyen.xcode_proj Adyen.xcodeproj } trap cleanup EXIT echo "β†˜οΈ Checking out comparison version" -mkdir comparison_version -cd comparison_version -git clone -b $1 $2 -cd adyen-ios -mv Adyen.xcodeproj Adyen.xcode_proj + +# If the directory already exists we just navigate into it and run the commands +if [ ! -d "$COMPARISON_VERSION_DIR_NAME" ]; +then + mkdir $COMPARISON_VERSION_DIR_NAME + cd $COMPARISON_VERSION_DIR_NAME + git clone -b $BRANCH $REPO + cd adyen-ios + mv Adyen.xcodeproj Adyen.xcode_proj +else + cd $COMPARISON_VERSION_DIR_NAME + cd adyen-ios + mv Adyen.xcodeproj Adyen.xcode_proj +fi echo "πŸ‘· Building comparison project" -xcodebuild -derivedDataPath .build -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -scheme "Adyen" -destination "platform=iOS,name=Any iOS Device" -target "x86_64-apple-ios16.4-simulator" -quiet +xcodebuild -derivedDataPath .build -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet echo "πŸ“‹ Generating comparison api_dump" -xcrun swift-api-digester -dump-sdk -module Adyen -o ../../api_dump_comparison.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" +xcrun swift-api-digester -dump-sdk -module $MODULE -o ../../api_dump_comparison.json -I .build/Build/Products/Debug-iphonesimulator -sdk $SDK -target $TARGET cd ../.. # Building project in `.build` directory echo "πŸ‘· Building updated project" -xcodebuild -derivedDataPath .build -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -scheme "Adyen" -destination "platform=iOS,name=Any iOS Device" -target "x86_64-apple-ios16.4-simulator" -quiet +xcodebuild -derivedDataPath .build -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet # Generating api_dump echo "πŸ“‹ Generating new api_dump" -xcrun swift-api-digester -dump-sdk -module Adyen -o api_dump.json -I .build/Build/Products/Debug-iphonesimulator -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" - -#echo "πŸ”€ Comparing" - -# echo "- diff" -# diff api_dump_comparison.json api_dump.json - -#echo "- swift-api-digester -diagnose-sdk" -# This command does not take @_spi into account unfortunately (It works well with changing from public to private or add new func/var/objects) -# xcrun swift-api-digester -diagnose-sdk -module Adyen -o api_diff -use-interface-for-module Adyen -abi -BI ./last_release/adyen-ios/.build/Build/Products/Debug-iphonesimulator -I .build/Build/Products/Debug-iphonesimulator -bsdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -sdk "`xcrun --sdk iphonesimulator --show-sdk-path`" -target "arm64-apple-ios17.2-simulator" -# cat api_diff - -# This command also does not take @_spi into account (Same as swift-api-digester -diagnose-sdk basically but running on the json files) -# xcrun swift-api-digester -diagnose-sdk --input-paths api_dump_comparison.json -input-paths api_dump.json +xcrun swift-api-digester -dump-sdk -module $MODULE -o api_dump.json -I .build/Build/Products/Debug-iphonesimulator -sdk $SDK -target $TARGET From 8a321d48bf8a71eb2f2f7d5e9cac1a2b19192b22 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 7 Jun 2024 15:53:54 +0200 Subject: [PATCH 19/43] adding complete check --- .github/workflows/detect_api_changes.yml | 4 ++-- .../compare_public_interface_definition.swift | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index 425fdd6d4a..72eb8903d1 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -26,11 +26,11 @@ jobs: - name: πŸ” Detect Changes run: | - for module in Adyen AdyenDropIn AdyenActions AdyenCard + for module in Adyen AdyenDropIn AdyenActions AdyenCard AdyenEncryption AdyenComponents AdyenSession AdyenWeChatPay AdyenCashAppPay AdyenTwint AdyenDelegatedAuthentication do echo Generating API Definition for $module Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} $module - ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json + ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json $module done env: branch: '${{github.event.pull_request.base.ref}}' diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index 6fa76c8a91..c389424c55 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -12,6 +12,7 @@ let currentDirectory = URL(fileURLWithPath: FileManager.default.currentDirectory let old = CommandLine.arguments[1] let new = CommandLine.arguments[2] +let moduleName = CommandLine.arguments[3] class Element: Codable, Equatable, CustomDebugStringConvertible { let kind: String @@ -168,7 +169,7 @@ func compare() throws { ) if decodedOldDefinition == decodedNewDefinition { - try persistComparison(fileContent: "# Public API Changes\n\nβœ… Nothing detected") + try persistComparison(fileContent: "# Public API Changes to `\(moduleName)`\n\nβœ… Nothing detected") return } @@ -191,7 +192,7 @@ func compare() throws { groupedChanges[$0.parentName] = (groupedChanges[$0.parentName] ?? []) + [$0] } - var fileContent: [String] = ["# Public API Changes\n"] + var fileContent: [String] = ["# Public API Changes to `\(moduleName)`\n"] groupedChanges.keys.sorted().forEach { key in fileContent += ["## \(key)"] @@ -206,7 +207,17 @@ func compare() throws { func persistComparison(fileContent: String) throws { print(fileContent) let outputPath = currentDirectory.appendingPathComponent("api_comparison.md") - try fileContent.write(to: outputPath, atomically: true, encoding: String.Encoding.utf8) + + guard let data = (fileContent + "\n\n").data(using: String.Encoding.utf8) else { return } + + if FileManager.default.fileExists(atPath: outputPath.path) { + let fileHandle = try FileHandle(forWritingTo: outputPath) + fileHandle.seekToEndOfFile() + fileHandle.write(data) + fileHandle.closeFile() + } else { + try data.write(to: outputPath, options: .atomicWrite) + } } do { From 9b3659c70f995b5127d6ffcdb848d4fc30b4f3de Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 11:00:42 +0200 Subject: [PATCH 20/43] formatting --- .github/workflows/detect_api_changes.yml | 3 ++- Scripts/compare_public_interface_definition.swift | 8 ++++---- Scripts/generate_public_interface_definition.sh | 4 ++++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index 72eb8903d1..525b3f5f41 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -26,7 +26,7 @@ jobs: - name: πŸ” Detect Changes run: | - for module in Adyen AdyenDropIn AdyenActions AdyenCard AdyenEncryption AdyenComponents AdyenSession AdyenWeChatPay AdyenCashAppPay AdyenTwint AdyenDelegatedAuthentication + for module in $modules do echo Generating API Definition for $module Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} $module @@ -35,6 +35,7 @@ jobs: env: branch: '${{github.event.pull_request.base.ref}}' baseRepo: '${{github.server_url}}/${{github.repository}}.git' + modules: "Adyen AdyenDropIn" # AdyenActions AdyenCard AdyenEncryption AdyenComponents AdyenSession AdyenWeChatPay AdyenCashAppPay AdyenTwint AdyenDelegatedAuthentication" - name: πŸ“ Comment on PR uses: thollander/actions-comment-pull-request@v2 diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index c389424c55..bd347abe0b 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -192,10 +192,10 @@ func compare() throws { groupedChanges[$0.parentName] = (groupedChanges[$0.parentName] ?? []) + [$0] } - var fileContent: [String] = ["# Public API Changes to `\(moduleName)`\n"] + var fileContent: [String] = ["## `\(moduleName)`\n"] groupedChanges.keys.sorted().forEach { key in - fileContent += ["## \(key)"] + fileContent += ["### \(key)"] groupedChanges[key]?.sorted(by: { $0.changeDescription < $1.changeDescription }).forEach { fileContent += ["- \($0.changeType.icon) \($0.changeDescription)"] } @@ -208,14 +208,14 @@ func persistComparison(fileContent: String) throws { print(fileContent) let outputPath = currentDirectory.appendingPathComponent("api_comparison.md") - guard let data = (fileContent + "\n\n").data(using: String.Encoding.utf8) else { return } - if FileManager.default.fileExists(atPath: outputPath.path) { + guard let data = (fileContent + "\n\n").data(using: String.Encoding.utf8) else { return } let fileHandle = try FileHandle(forWritingTo: outputPath) fileHandle.seekToEndOfFile() fileHandle.write(data) fileHandle.closeFile() } else { + guard let data = ("# Public API Changes\n" + fileContent + "\n\n").data(using: String.Encoding.utf8) else { return } try data.write(to: outputPath, options: .atomicWrite) } } diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index 3cdbc6c4c8..ce61ed9791 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -25,6 +25,10 @@ function cleanup() { trap cleanup EXIT +echo "πŸ—‚οΈ Changed files" + +git diff --name-only $BRANCH + echo "β†˜οΈ Checking out comparison version" # If the directory already exists we just navigate into it and run the commands From 43c0de68d4365cae2e0f56f583ac15137bb52f46 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 11:12:21 +0200 Subject: [PATCH 21/43] Fixed formatting --- Adyen/Core/AdyenContext/AdyenContext.swift | 21 +++++++++++++++++++ .../compare_public_interface_definition.swift | 2 +- .../generate_public_interface_definition.sh | 6 ++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/Adyen/Core/AdyenContext/AdyenContext.swift b/Adyen/Core/AdyenContext/AdyenContext.swift index 7864e2c255..4fe2407498 100644 --- a/Adyen/Core/AdyenContext/AdyenContext.swift +++ b/Adyen/Core/AdyenContext/AdyenContext.swift @@ -10,6 +10,27 @@ import Foundation /// A class that defines the behavior of the components in a payment flow. public final class AdyenContext: PaymentAware { + // TODO: Remove after testing! + public struct PublicStruct { + + private var privateVar: String + internal var internalVar: String + @_spi(AdyenInternal) public var spiVar: String + public var publicVar: String + + public init( + privateVar: String, + internalVar: String, + spiVar: String, + publicVar: String + ) { + self.privateVar = privateVar + self.internalVar = internalVar + self.spiVar = spiVar + self.publicVar = publicVar + } + } + // MARK: - Properties /// The API context used to retrieve internal resources. diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index bd347abe0b..4506088520 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -169,7 +169,7 @@ func compare() throws { ) if decodedOldDefinition == decodedNewDefinition { - try persistComparison(fileContent: "# Public API Changes to `\(moduleName)`\n\nβœ… Nothing detected") + try persistComparison(fileContent: "## `\(moduleName)`\nβœ… Nothing detected") return } diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index ce61ed9791..690c696fe3 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -27,8 +27,14 @@ trap cleanup EXIT echo "πŸ—‚οΈ Changed files" +git fetch --all git diff --name-only $BRANCH +# TODO: Compile a list of changed modules from the git diff +# TODO: Generate a Package.swift target that contains all modules +# TODO: Build each (updated + comparison) project once +# TODO: Generate an sdk dump from every module that had changes + echo "β†˜οΈ Checking out comparison version" # If the directory already exists we just navigate into it and run the commands From ca200393c63c2a0ed82c157c02799de220ed93ae Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 11:26:46 +0200 Subject: [PATCH 22/43] fixing git diff --- Scripts/compare_public_interface_definition.swift | 6 ------ Scripts/generate_public_interface_definition.sh | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index 4506088520..0b53da5eab 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -20,7 +20,6 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { let mangledName: String? let printedName: String let declKind: String? - let moduleName: String? let children: [Element]? let spiGroupNames: [String]? @@ -35,7 +34,6 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { case children case spiGroupNames = "spi_group_names" case declKind - case moduleName } var debugDescription: String { @@ -78,10 +76,6 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { sanitizedPath.removeLast() } - if let moduleName = moduleName { - sanitizedPath += [moduleName] - } - return sanitizedPath.reversed().joined(separator: ".") } } diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index 690c696fe3..d3a06b97cc 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -27,7 +27,7 @@ trap cleanup EXIT echo "πŸ—‚οΈ Changed files" -git fetch --all +git fetch origin $BRANCH git diff --name-only $BRANCH # TODO: Compile a list of changed modules from the git diff From 09b6eacc84cbcc895e5fcd9f6751451e416c459b Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 11:33:37 +0200 Subject: [PATCH 23/43] trying something different --- Scripts/generate_public_interface_definition.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index d3a06b97cc..ac5e62f1a8 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -27,8 +27,7 @@ trap cleanup EXIT echo "πŸ—‚οΈ Changed files" -git fetch origin $BRANCH -git diff --name-only $BRANCH +git diff --name-only $(git rev-parse "$BRANCH") # TODO: Compile a list of changed modules from the git diff # TODO: Generate a Package.swift target that contains all modules From a006d7de1cbc85fd873823501f7b1213be9dae6a Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 11:36:09 +0200 Subject: [PATCH 24/43] trying something else --- Scripts/generate_public_interface_definition.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index ac5e62f1a8..b53ed64483 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -27,7 +27,9 @@ trap cleanup EXIT echo "πŸ—‚οΈ Changed files" -git diff --name-only $(git rev-parse "$BRANCH") +TARGET_COMMIT_HASH=$(git rev-parse "$BRANCH") +CHANGED_FILEPATHS=$(git diff --name-only "$TARGET_COMMIT_HASH") +echo CHANGED_FILEPATHS # TODO: Compile a list of changed modules from the git diff # TODO: Generate a Package.swift target that contains all modules From e2f76d00b438a4c0d7aa639bc78d05453fae5865 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 11:39:59 +0200 Subject: [PATCH 25/43] maybe this time --- Scripts/generate_public_interface_definition.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index b53ed64483..a6b5893275 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -27,9 +27,9 @@ trap cleanup EXIT echo "πŸ—‚οΈ Changed files" -TARGET_COMMIT_HASH=$(git rev-parse "$BRANCH") +TARGET_COMMIT_HASH=$(git rev-parse origin/$BRANCH) CHANGED_FILEPATHS=$(git diff --name-only "$TARGET_COMMIT_HASH") -echo CHANGED_FILEPATHS +echo $CHANGED_FILEPATHS # TODO: Compile a list of changed modules from the git diff # TODO: Generate a Package.swift target that contains all modules From 4b620baba852c52124d5838a1236a63548510d09 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 13:17:05 +0200 Subject: [PATCH 26/43] whatever --- .../generate_public_interface_definition.sh | 24 +++++++++++-------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index a6b5893275..4d5fb6db47 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -14,7 +14,6 @@ echo "Target: " $TARGET echo "Dir: " $COMPARISON_VERSION_DIR_NAME rm -rf .build -mv Adyen.xcodeproj Adyen.xcode_proj rm -rf comparison_version function cleanup() { @@ -26,16 +25,20 @@ function cleanup() { trap cleanup EXIT echo "πŸ—‚οΈ Changed files" - -TARGET_COMMIT_HASH=$(git rev-parse origin/$BRANCH) -CHANGED_FILEPATHS=$(git diff --name-only "$TARGET_COMMIT_HASH") -echo $CHANGED_FILEPATHS +# TODO: Do this check before pulling the repo to prevent pulling when there are no changes +COMMIT_HASH=$(git rev-parse origin/$BRANCH) +CHANGED_FILEPATHS=$(git diff --name-only $COMMIT_HASH) +for FILE_PATH in $CHANGED_FILEPATHS; do + echo $FILE_PATH +done # TODO: Compile a list of changed modules from the git diff # TODO: Generate a Package.swift target that contains all modules # TODO: Build each (updated + comparison) project once # TODO: Generate an sdk dump from every module that had changes +mv Adyen.xcodeproj Adyen.xcode_proj + echo "β†˜οΈ Checking out comparison version" # If the directory already exists we just navigate into it and run the commands @@ -44,18 +47,19 @@ then mkdir $COMPARISON_VERSION_DIR_NAME cd $COMPARISON_VERSION_DIR_NAME git clone -b $BRANCH $REPO - cd adyen-ios - mv Adyen.xcodeproj Adyen.xcode_proj else cd $COMPARISON_VERSION_DIR_NAME - cd adyen-ios - mv Adyen.xcodeproj Adyen.xcode_proj fi +exit + +cd adyen-ios +mv Adyen.xcodeproj Adyen.xcode_proj + echo "πŸ‘· Building comparison project" xcodebuild -derivedDataPath .build -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet -echo "πŸ“‹ Generating comparison api_dump" +echo "πŸ“‹ Generating comparison api_dump"s xcrun swift-api-digester -dump-sdk -module $MODULE -o ../../api_dump_comparison.json -I .build/Build/Products/Debug-iphonesimulator -sdk $SDK -target $TARGET cd ../.. From 654e5b94fb0c0ad170dab48fe5e1f44a43362a01 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 14:37:48 +0200 Subject: [PATCH 27/43] maybe this works --- .../generate_public_interface_definition.sh | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index 4d5fb6db47..ede47ebe0d 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -24,14 +24,6 @@ function cleanup() { trap cleanup EXIT -echo "πŸ—‚οΈ Changed files" -# TODO: Do this check before pulling the repo to prevent pulling when there are no changes -COMMIT_HASH=$(git rev-parse origin/$BRANCH) -CHANGED_FILEPATHS=$(git diff --name-only $COMMIT_HASH) -for FILE_PATH in $CHANGED_FILEPATHS; do - echo $FILE_PATH -done - # TODO: Compile a list of changed modules from the git diff # TODO: Generate a Package.swift target that contains all modules # TODO: Build each (updated + comparison) project once @@ -47,10 +39,19 @@ then mkdir $COMPARISON_VERSION_DIR_NAME cd $COMPARISON_VERSION_DIR_NAME git clone -b $BRANCH $REPO + COMMIT_HASH=$(git rev-parse origin/$BRANCH) else cd $COMPARISON_VERSION_DIR_NAME + COMMIT_HASH=$(git rev-parse origin/$BRANCH) fi +echo "πŸ—‚οΈ Changed files" + +CHANGED_FILEPATHS=$(git diff --name-only $COMMIT_HASH) +for FILE_PATH in $CHANGED_FILEPATHS; do + echo $FILE_PATH +done + exit cd adyen-ios @@ -59,7 +60,7 @@ mv Adyen.xcodeproj Adyen.xcode_proj echo "πŸ‘· Building comparison project" xcodebuild -derivedDataPath .build -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet -echo "πŸ“‹ Generating comparison api_dump"s +echo "πŸ“‹ Generating comparison api_dump" xcrun swift-api-digester -dump-sdk -module $MODULE -o ../../api_dump_comparison.json -I .build/Build/Products/Debug-iphonesimulator -sdk $SDK -target $TARGET cd ../.. From 2deb1866b760bbcf285a32631142ef660b2b1494 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 17:46:03 +0200 Subject: [PATCH 28/43] Improving comparison --- .../compare_public_interface_definition.swift | 58 ++++++++++---- .../generate_public_interface_definition.sh | 76 ++++++++++--------- 2 files changed, 86 insertions(+), 48 deletions(-) diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index 0b53da5eab..86d8d952c7 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -14,6 +14,14 @@ let old = CommandLine.arguments[1] let new = CommandLine.arguments[2] let moduleName = CommandLine.arguments[3] +struct Conformance: Codable, Equatable { + var printedName: String + + enum CodingKeys: String, CodingKey { + case printedName + } +} + class Element: Codable, Equatable, CustomDebugStringConvertible { let kind: String let name: String @@ -24,6 +32,9 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { let children: [Element]? let spiGroupNames: [String]? + let declAttributes: [String]? + let conformances: [Conformance]? + var parent: Element? enum CodingKeys: String, CodingKey { @@ -34,6 +45,8 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { case children case spiGroupNames = "spi_group_names" case declKind + case declAttributes + case conformances } var debugDescription: String { @@ -43,16 +56,24 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { } definition += "public " - if declKind == "Var" { - definition += "var " - } else if declKind == "Func" { - definition += "func " - } else if declKind == "Import" { - definition += "import " + if declAttributes?.contains("Final") == true { + definition += "final " + } + + if let declKind { + if declKind == "Constructor" { + definition += "func " + } else { + definition += "\(declKind.lowercased()) " + } } definition += "\(printedName)" + if let conformanceNames = conformances?.map({ $0.printedName }), !conformanceNames.isEmpty { + definition += " : \(conformanceNames.joined(separator: ", "))" + } + return definition } @@ -101,9 +122,9 @@ struct Change { var icon: String { switch self { case .addition: - return "🐣" + return "❇️" case .removal: - return "πŸ’”" + return "πŸ˜Άβ€πŸŒ«οΈ" case .change: return "πŸ”€" } @@ -122,10 +143,21 @@ func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> var changes = [Change]() - if oldFirst, (lhs.printedName != rhs.printedName || lhs.spiGroupNames != rhs.spiGroupNames || lhs.children == rhs.children) { + // TODO: Add check if accessor changed (e.g. changed from get/set to get only...) + + if oldFirst, ( + lhs.printedName != rhs.printedName || + lhs.spiGroupNames != rhs.spiGroupNames || + lhs.conformances != rhs.conformances || + lhs.declAttributes != rhs.declAttributes + ) { changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "`\(lhs)` ➑️ `\(rhs)`")] } + if lhs.children == rhs.children { + return changes + } + changes += lhs.children?.flatMap { lhsElement in if let rhsChildForName = rhs.children?.first(where: { ($0.mangledName ?? $0.name) == (lhsElement.mangledName ?? lhsElement.name) }) { return recursiveCompare(element: lhsElement, to: rhsChildForName, oldFirst: oldFirst) @@ -163,7 +195,7 @@ func compare() throws { ) if decodedOldDefinition == decodedNewDefinition { - try persistComparison(fileContent: "## `\(moduleName)`\nβœ… Nothing detected") + try persistComparison(fileContent: "## 🫧 `\(moduleName)`\n- No changes detected") return } @@ -186,12 +218,12 @@ func compare() throws { groupedChanges[$0.parentName] = (groupedChanges[$0.parentName] ?? []) + [$0] } - var fileContent: [String] = ["## `\(moduleName)`\n"] + var fileContent = ["## πŸ‘€ `\(moduleName)`\n"] groupedChanges.keys.sorted().forEach { key in - fileContent += ["### \(key)"] + fileContent += ["### \(key)"] groupedChanges[key]?.sorted(by: { $0.changeDescription < $1.changeDescription }).forEach { - fileContent += ["- \($0.changeType.icon) \($0.changeDescription)"] + fileContent += ["- \($0.changeType.icon) \($0.changeDescription)"] } } diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index ede47ebe0d..cc045f13f8 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -4,15 +4,22 @@ BRANCH=$1 REPO=$2 TARGET="x86_64-apple-ios17.4-simulator" SDK="`xcrun --sdk iphonesimulator --show-sdk-path`" -MODULE=$3 #"Adyen" +MODULE_NAMES=("Adyen" "AdyenDropIn" "AdyenActions" "AdyenCard" "AdyenEncryption" "AdyenComponents" "AdyenSession" "AdyenWeChatPay" "AdyenCashAppPay" "AdyenTwint" "AdyenDelegatedAuthentication") COMPARISON_VERSION_DIR_NAME="comparison_version_$BRANCH" +DERIVED_DATA_PATH=".build" +SDK_DUMP_INPUT_PATH="$DERIVED_DATA_PATH/Build/Products/Debug-iphonesimulator" echo "Branch: " $BRANCH echo "Repo: " $REPO -echo "Module: " $MODULE echo "Target: " $TARGET echo "Dir: " $COMPARISON_VERSION_DIR_NAME +echo "Modules:" +for MODULE in ${MODULE_NAMES[@]} +do + echo "-" $MODULE +done + rm -rf .build rm -rf comparison_version @@ -22,53 +29,52 @@ function cleanup() { mv Adyen.xcode_proj Adyen.xcodeproj } +function setupComparisonRepo() { + rm -rf $COMPARISON_VERSION_DIR_NAME + mkdir $COMPARISON_VERSION_DIR_NAME + cd $COMPARISON_VERSION_DIR_NAME + git clone -b $BRANCH $REPO + + cd adyen-ios + mv Adyen.xcodeproj Adyen.xcode_proj +} + trap cleanup EXIT # TODO: Compile a list of changed modules from the git diff # TODO: Generate a Package.swift target that contains all modules # TODO: Build each (updated + comparison) project once -# TODO: Generate an sdk dump from every module that had changes +# TODO: Only generate + compare an sdk dump from any module that had changes mv Adyen.xcodeproj Adyen.xcode_proj echo "β†˜οΈ Checking out comparison version" -# If the directory already exists we just navigate into it and run the commands -if [ ! -d "$COMPARISON_VERSION_DIR_NAME" ]; -then - mkdir $COMPARISON_VERSION_DIR_NAME - cd $COMPARISON_VERSION_DIR_NAME - git clone -b $BRANCH $REPO - COMMIT_HASH=$(git rev-parse origin/$BRANCH) -else - cd $COMPARISON_VERSION_DIR_NAME - COMMIT_HASH=$(git rev-parse origin/$BRANCH) -fi - -echo "πŸ—‚οΈ Changed files" - -CHANGED_FILEPATHS=$(git diff --name-only $COMMIT_HASH) -for FILE_PATH in $CHANGED_FILEPATHS; do - echo $FILE_PATH -done +setupComparisonRepo # We're now in the comparison repository directory -exit +for MODULE in ${MODULE_NAMES[@]} +do -cd adyen-ios -mv Adyen.xcodeproj Adyen.xcode_proj +echo "πŸ‘· [$MODULE] Building comparison project" +xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet -echo "πŸ‘· Building comparison project" -xcodebuild -derivedDataPath .build -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet - -echo "πŸ“‹ Generating comparison api_dump" -xcrun swift-api-digester -dump-sdk -module $MODULE -o ../../api_dump_comparison.json -I .build/Build/Products/Debug-iphonesimulator -sdk $SDK -target $TARGET +echo "πŸ“‹ [$MODULE] Generating comparison api_dump" +xcrun swift-api-digester -dump-sdk -module $MODULE -o ../../api_dump_comparison.json -I $SDK_DUMP_INPUT_PATH -sdk $SDK -target $TARGET cd ../.. -# Building project in `.build` directory -echo "πŸ‘· Building updated project" -xcodebuild -derivedDataPath .build -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet +echo "πŸ‘· [$MODULE] Building updated project" +xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet + +echo "πŸ“‹ [$MODULE] Generating new api_dump" +xcrun swift-api-digester -dump-sdk -module $MODULE -o api_dump.json -I $SDK_DUMP_INPUT_PATH -sdk $SDK -target $TARGET + +echo "πŸ•΅οΈ [$MODULE] Diffing" +./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json $MODULE -# Generating api_dump -echo "πŸ“‹ Generating new api_dump" -xcrun swift-api-digester -dump-sdk -module $MODULE -o api_dump.json -I .build/Build/Products/Debug-iphonesimulator -sdk $SDK -target $TARGET +# Reset and move into comparison dir again for the next iteration +rm api_dump.json +rm api_dump_comparison.json +cd $COMPARISON_VERSION_DIR_NAME/adyen-ios + +done From 6f16208cd2b0acaa593c31cd2b47844c7ffc2532 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 17:46:20 +0200 Subject: [PATCH 29/43] Updating workflow --- .github/workflows/detect_api_changes.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index 525b3f5f41..88511675b5 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -26,16 +26,10 @@ jobs: - name: πŸ” Detect Changes run: | - for module in $modules - do - echo Generating API Definition for $module - Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} $module - ./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json $module - done + Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} env: branch: '${{github.event.pull_request.base.ref}}' baseRepo: '${{github.server_url}}/${{github.repository}}.git' - modules: "Adyen AdyenDropIn" # AdyenActions AdyenCard AdyenEncryption AdyenComponents AdyenSession AdyenWeChatPay AdyenCashAppPay AdyenTwint AdyenDelegatedAuthentication" - name: πŸ“ Comment on PR uses: thollander/actions-comment-pull-request@v2 From b1f847c9934803866385ab8931c11a57f4811ad9 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Mon, 10 Jun 2024 18:08:16 +0200 Subject: [PATCH 30/43] Removed testing code --- Adyen/Core/AdyenContext/AdyenContext.swift | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/Adyen/Core/AdyenContext/AdyenContext.swift b/Adyen/Core/AdyenContext/AdyenContext.swift index 4fe2407498..7864e2c255 100644 --- a/Adyen/Core/AdyenContext/AdyenContext.swift +++ b/Adyen/Core/AdyenContext/AdyenContext.swift @@ -10,27 +10,6 @@ import Foundation /// A class that defines the behavior of the components in a payment flow. public final class AdyenContext: PaymentAware { - // TODO: Remove after testing! - public struct PublicStruct { - - private var privateVar: String - internal var internalVar: String - @_spi(AdyenInternal) public var spiVar: String - public var publicVar: String - - public init( - privateVar: String, - internalVar: String, - spiVar: String, - publicVar: String - ) { - self.privateVar = privateVar - self.internalVar = internalVar - self.spiVar = spiVar - self.publicVar = publicVar - } - } - // MARK: - Properties /// The API context used to retrieve internal resources. From 1606cfa130355458a76332e48f960d8b88217130 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Wed, 12 Jun 2024 10:21:40 +0200 Subject: [PATCH 31/43] Trigger action --- Scripts/compare_public_interface_definition.swift | 1 - 1 file changed, 1 deletion(-) diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index 86d8d952c7..a09860ae69 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -31,7 +31,6 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { let children: [Element]? let spiGroupNames: [String]? - let declAttributes: [String]? let conformances: [Conformance]? From da662b1d28a218c6f694058a87ae5625bc38b236 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Wed, 12 Jun 2024 10:48:53 +0200 Subject: [PATCH 32/43] fixing --- Scripts/compare_public_interface_definition.swift | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index a09860ae69..0c917c9ade 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -76,6 +76,10 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { return definition } + var isSpiInternal: Bool { + !(spiGroupNames ?? []).isEmpty + } + public static func == (lhs: Element, rhs: Element) -> Bool { lhs.mangledName == rhs.mangledName && lhs.children == rhs.children @@ -121,7 +125,7 @@ struct Change { var icon: String { switch self { case .addition: - return "❇️" + return "❇️ " case .removal: return "πŸ˜Άβ€πŸŒ«οΈ" case .change: @@ -140,6 +144,11 @@ func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> return [] } + if lhs.isSpiInternal && rhs.isSpiInternal { + // If both elements are spi internal we can ignore them as they are not in the public interface + return [] + } + var changes = [Change]() // TODO: Add check if accessor changed (e.g. changed from get/set to get only...) From 308aeeab179af8c957ca80ce333790105c6e4934 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Wed, 12 Jun 2024 11:32:52 +0200 Subject: [PATCH 33/43] Removing spi internal additions/removals from log --- Scripts/compare_public_interface_definition.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index 0c917c9ade..a997795352 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -159,6 +159,7 @@ func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> lhs.conformances != rhs.conformances || lhs.declAttributes != rhs.declAttributes ) { + // TODO: Show what exactly changed (name, spi, conformance, declAttributes, ...) as a bullet list maybe (add a `changeList` property to `Change`) changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "`\(lhs)` ➑️ `\(rhs)`")] } @@ -170,6 +171,8 @@ func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> if let rhsChildForName = rhs.children?.first(where: { ($0.mangledName ?? $0.name) == (lhsElement.mangledName ?? lhsElement.name) }) { return recursiveCompare(element: lhsElement, to: rhsChildForName, oldFirst: oldFirst) } else { + if lhsElement.isSpiInternal { return [] } + if oldFirst { return [.init(changeType: .removal, parentName: lhsElement.parentPath, changeDescription: "`\(lhsElement)` was removed")] } else { From c62c607917caf76ade22753adfd3ef8f2e649a9f Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Thu, 13 Jun 2024 11:37:37 +0200 Subject: [PATCH 34/43] extracting find function to Element extension --- Scripts/compare_public_interface_definition.swift | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift index a997795352..f1285de693 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/compare_public_interface_definition.swift @@ -104,6 +104,12 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { } } +extension [Element] { + func firstElementMatchingName(of otherElement: Element) -> Element? { + first(where: { ($0.mangledName ?? $0.name) == (otherElement.mangledName ?? otherElement.name) }) + } +} + class Definition: Codable, Equatable { let root: Element @@ -168,7 +174,7 @@ func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> } changes += lhs.children?.flatMap { lhsElement in - if let rhsChildForName = rhs.children?.first(where: { ($0.mangledName ?? $0.name) == (lhsElement.mangledName ?? lhsElement.name) }) { + if let rhsChildForName = rhs.children?.firstElementMatchingName(of: lhsElement) { return recursiveCompare(element: lhsElement, to: rhsChildForName, oldFirst: oldFirst) } else { if lhsElement.isSpiInternal { return [] } From 9fd987f40a945b098e6c9c59a4ad932b986df888 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Thu, 13 Jun 2024 16:45:06 +0200 Subject: [PATCH 35/43] Adding documentation --- Scripts/generate_public_interface_definition.sh | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh index cc045f13f8..6c5dce5b14 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/generate_public_interface_definition.sh @@ -25,7 +25,7 @@ rm -rf comparison_version function cleanup() { rm -rf .build - # rm -rf $COMPARISON_VERSION_DIR_NAME + rm -rf $COMPARISON_VERSION_DIR_NAME mv Adyen.xcode_proj Adyen.xcodeproj } @@ -36,26 +36,24 @@ function setupComparisonRepo() { git clone -b $BRANCH $REPO cd adyen-ios - mv Adyen.xcodeproj Adyen.xcode_proj + mv Adyen.xcodeproj Adyen.xcode_proj # We have to obscure the project file so `xcodebuild` uses the Package.swift to build the module } trap cleanup EXIT # TODO: Compile a list of changed modules from the git diff -# TODO: Generate a Package.swift target that contains all modules -# TODO: Build each (updated + comparison) project once -# TODO: Only generate + compare an sdk dump from any module that had changes +# TODO: Generate a Package.swift library that contains all targets/modules so we don't have to do multiple slow `xcodebuild` mv Adyen.xcodeproj Adyen.xcode_proj echo "β†˜οΈ Checking out comparison version" - setupComparisonRepo # We're now in the comparison repository directory +echo "πŸ‘· Building & Diffing" for MODULE in ${MODULE_NAMES[@]} do -echo "πŸ‘· [$MODULE] Building comparison project" +echo "πŸ› οΈ [$MODULE] Building comparison project" xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet echo "πŸ“‹ [$MODULE] Generating comparison api_dump" @@ -63,7 +61,7 @@ xcrun swift-api-digester -dump-sdk -module $MODULE -o ../../api_dump_comparison. cd ../.. -echo "πŸ‘· [$MODULE] Building updated project" +echo "πŸ› οΈ [$MODULE] Building updated project" xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet echo "πŸ“‹ [$MODULE] Generating new api_dump" From afe29a7f37125e41ac45d2238a3995f3fa77e362 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Thu, 13 Jun 2024 16:48:15 +0200 Subject: [PATCH 36/43] Remove scripts folder from spell check --- spell-check-excluded-files-list | 1 + 1 file changed, 1 insertion(+) diff --git a/spell-check-excluded-files-list b/spell-check-excluded-files-list index beca5b153a..1f3946dbaa 100644 --- a/spell-check-excluded-files-list +++ b/spell-check-excluded-files-list @@ -5,3 +5,4 @@ Demo/Common/IntegrationExamples/DemoAddressLookupProvider.swift Demo/Common/IntegrationExamples/MapkitAddressLookupProvider.swift Tests/* UITests/* +Scripts/* From a7929b50a873fd761e96b8733173701ac9fb607e Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 14 Jun 2024 15:05:31 +0200 Subject: [PATCH 37/43] Optimizing speed --- .github/workflows/detect_api_changes.yml | 2 +- .../compare.sh} | 20 +++--- .../diff.swift} | 17 +++-- .../update_package_file.swift | 64 +++++++++++++++++++ 4 files changed, 83 insertions(+), 20 deletions(-) rename Scripts/{generate_public_interface_definition.sh => detect_public_api_changes/compare.sh} (78%) rename Scripts/{compare_public_interface_definition.swift => detect_public_api_changes/diff.swift} (95%) create mode 100755 Scripts/detect_public_api_changes/update_package_file.swift diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index 88511675b5..fd83b6f28a 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -26,7 +26,7 @@ jobs: - name: πŸ” Detect Changes run: | - Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} + Scripts/detect_public_api_changes/compare.sh ${branch} ${baseRepo} env: branch: '${{github.event.pull_request.base.ref}}' baseRepo: '${{github.server_url}}/${{github.repository}}.git' diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/detect_public_api_changes/compare.sh similarity index 78% rename from Scripts/generate_public_interface_definition.sh rename to Scripts/detect_public_api_changes/compare.sh index 6c5dce5b14..2b40dc95ef 100755 --- a/Scripts/generate_public_interface_definition.sh +++ b/Scripts/detect_public_api_changes/compare.sh @@ -36,43 +36,43 @@ function setupComparisonRepo() { git clone -b $BRANCH $REPO cd adyen-ios + ../../Scripts/detect_public_api_changes/update_package_file.swift Package.swift "AdyenAllTargets" mv Adyen.xcodeproj Adyen.xcode_proj # We have to obscure the project file so `xcodebuild` uses the Package.swift to build the module } trap cleanup EXIT -# TODO: Compile a list of changed modules from the git diff -# TODO: Generate a Package.swift library that contains all targets/modules so we don't have to do multiple slow `xcodebuild` - mv Adyen.xcodeproj Adyen.xcode_proj +./Scripts/detect_public_api_changes/update_package_file.swift Package.swift "AdyenAllTargets" echo "β†˜οΈ Checking out comparison version" setupComparisonRepo # We're now in the comparison repository directory +echo "πŸ› οΈ Building 'AdyenAllTargets' comparison project" +xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme "AdyenAllTargets" -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet +cd ../.. +echo "πŸ› οΈ Building 'AdyenAllTargets' updated project" +xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme "AdyenAllTargets" -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet + echo "πŸ‘· Building & Diffing" for MODULE in ${MODULE_NAMES[@]} do -echo "πŸ› οΈ [$MODULE] Building comparison project" -xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet +cd $COMPARISON_VERSION_DIR_NAME/adyen-ios echo "πŸ“‹ [$MODULE] Generating comparison api_dump" xcrun swift-api-digester -dump-sdk -module $MODULE -o ../../api_dump_comparison.json -I $SDK_DUMP_INPUT_PATH -sdk $SDK -target $TARGET cd ../.. -echo "πŸ› οΈ [$MODULE] Building updated project" -xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet - echo "πŸ“‹ [$MODULE] Generating new api_dump" xcrun swift-api-digester -dump-sdk -module $MODULE -o api_dump.json -I $SDK_DUMP_INPUT_PATH -sdk $SDK -target $TARGET echo "πŸ•΅οΈ [$MODULE] Diffing" -./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json $MODULE +./diff.swift api_dump.json api_dump_comparison.json $MODULE # Reset and move into comparison dir again for the next iteration rm api_dump.json rm api_dump_comparison.json -cd $COMPARISON_VERSION_DIR_NAME/adyen-ios done diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/detect_public_api_changes/diff.swift similarity index 95% rename from Scripts/compare_public_interface_definition.swift rename to Scripts/detect_public_api_changes/diff.swift index f1285de693..7b6591fb86 100755 --- a/Scripts/compare_public_interface_definition.swift +++ b/Scripts/detect_public_api_changes/diff.swift @@ -62,14 +62,14 @@ class Element: Codable, Equatable, CustomDebugStringConvertible { if let declKind { if declKind == "Constructor" { definition += "func " - } else { + } else { definition += "\(declKind.lowercased()) " } } definition += "\(printedName)" - if let conformanceNames = conformances?.map({ $0.printedName }), !conformanceNames.isEmpty { + if let conformanceNames = conformances?.map(\.printedName), !conformanceNames.isEmpty { definition += " : \(conformanceNames.joined(separator: ", "))" } @@ -150,7 +150,7 @@ func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> return [] } - if lhs.isSpiInternal && rhs.isSpiInternal { + if lhs.isSpiInternal, rhs.isSpiInternal { // If both elements are spi internal we can ignore them as they are not in the public interface return [] } @@ -159,12 +159,11 @@ func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> // TODO: Add check if accessor changed (e.g. changed from get/set to get only...) - if oldFirst, ( - lhs.printedName != rhs.printedName || - lhs.spiGroupNames != rhs.spiGroupNames || - lhs.conformances != rhs.conformances || - lhs.declAttributes != rhs.declAttributes - ) { + if oldFirst, + lhs.printedName != rhs.printedName || + lhs.spiGroupNames != rhs.spiGroupNames || + lhs.conformances != rhs.conformances || + lhs.declAttributes != rhs.declAttributes { // TODO: Show what exactly changed (name, spi, conformance, declAttributes, ...) as a bullet list maybe (add a `changeList` property to `Change`) changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "`\(lhs)` ➑️ `\(rhs)`")] } diff --git a/Scripts/detect_public_api_changes/update_package_file.swift b/Scripts/detect_public_api_changes/update_package_file.swift new file mode 100755 index 0000000000..8e25a8f86e --- /dev/null +++ b/Scripts/detect_public_api_changes/update_package_file.swift @@ -0,0 +1,64 @@ +#!/usr/bin/env xcrun swift + +import Foundation + +///Parse Package.swift file and add a new library to the list of products that contains all targets + +// MARK: - Convenience Methods + +func availableTargets(from packageContent: String) -> [String] { + let scanner = Scanner(string: packageContent) + _ = scanner.scanUpTo("targets: [", into: nil) + + var availableTargets = Set() + + while scanner.scanUpTo(".target(", into: nil) { + let nameStartTag = "name: \"" + let nameEndTag = "\"" + + scanner.scanUpTo(nameStartTag, into: nil) + scanner.scanString(nameStartTag, into: nil) + + var targetName: NSString? + scanner.scanUpTo(nameEndTag, into: &targetName) + if let targetName = targetName as? String { + availableTargets.insert(targetName) + } + } + + return availableTargets.sorted() +} + +func consolidatedLibraryEntry(_ name: String, from availableTargets: [String]) -> String { +""" + + .library( + name: "\(name)", + targets: [\(availableTargets.map { "\"\($0)\"" }.joined(separator: ", "))] + ), +""" +} + +func updatedContent(with consolidatedEntry: String) -> String { + // Update the Package.swift content + var updatedContent = packageContent + if let productsRange = packageContent.range(of: "products: [", options: .caseInsensitive) { + updatedContent.insert(contentsOf: consolidatedEntry, at: productsRange.upperBound) + } else { + print("Products section not found") + } + return updatedContent +} + +// MARK: - Main + +let packagePath = CommandLine.arguments[1] // Path to the Package.swift file +let consolidatedLibraryName = CommandLine.arguments[2] // Name of the library containing all targets + +let packageContent = try String(contentsOfFile: packagePath) +let targets = availableTargets(from: packageContent) +let consolidatedEntry = consolidatedLibraryEntry(consolidatedLibraryName, from: targets) +let updatedPackageContent = updatedContent(with: consolidatedEntry) + +// Write the updated content back to the file +try updatedPackageContent.write(toFile: packagePath, atomically: true, encoding: .utf8) From 2522192b02742b9797d64a7234d6dcf5f05ca328 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 14 Jun 2024 15:12:00 +0200 Subject: [PATCH 38/43] Removed unused code --- .../compare_public_interface_definition.swift | 270 ------------------ .../generate_public_interface_definition.sh | 78 ----- 2 files changed, 348 deletions(-) delete mode 100755 Scripts/compare_public_interface_definition.swift delete mode 100755 Scripts/generate_public_interface_definition.sh diff --git a/Scripts/compare_public_interface_definition.swift b/Scripts/compare_public_interface_definition.swift deleted file mode 100755 index f1285de693..0000000000 --- a/Scripts/compare_public_interface_definition.swift +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/env xcrun swift - -// -// Copyright (c) 2024 Adyen N.V. -// -// This file is open source and available under the MIT license. See the LICENSE file for more info. -// - -import Foundation - -let currentDirectory = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) - -let old = CommandLine.arguments[1] -let new = CommandLine.arguments[2] -let moduleName = CommandLine.arguments[3] - -struct Conformance: Codable, Equatable { - var printedName: String - - enum CodingKeys: String, CodingKey { - case printedName - } -} - -class Element: Codable, Equatable, CustomDebugStringConvertible { - let kind: String - let name: String - let mangledName: String? - let printedName: String - let declKind: String? - - let children: [Element]? - let spiGroupNames: [String]? - let declAttributes: [String]? - let conformances: [Conformance]? - - var parent: Element? - - enum CodingKeys: String, CodingKey { - case kind - case name - case printedName - case mangledName - case children - case spiGroupNames = "spi_group_names" - case declKind - case declAttributes - case conformances - } - - var debugDescription: String { - var definition = "" - spiGroupNames?.forEach { - definition += "@_spi(\($0)) " - } - definition += "public " - - if declAttributes?.contains("Final") == true { - definition += "final " - } - - if let declKind { - if declKind == "Constructor" { - definition += "func " - } else { - definition += "\(declKind.lowercased()) " - } - } - - definition += "\(printedName)" - - if let conformanceNames = conformances?.map({ $0.printedName }), !conformanceNames.isEmpty { - definition += " : \(conformanceNames.joined(separator: ", "))" - } - - return definition - } - - var isSpiInternal: Bool { - !(spiGroupNames ?? []).isEmpty - } - - public static func == (lhs: Element, rhs: Element) -> Bool { - lhs.mangledName == rhs.mangledName - && lhs.children == rhs.children - && lhs.spiGroupNames == rhs.spiGroupNames - } - - var parentPath: String { - var parent = self.parent - var path = [parent?.name] - while parent != nil { - parent = parent?.parent - path += [parent?.name] - } - - var sanitizedPath = path.compactMap { $0 } - - if sanitizedPath.last == "TopLevel" { - sanitizedPath.removeLast() - } - - return sanitizedPath.reversed().joined(separator: ".") - } -} - -extension [Element] { - func firstElementMatchingName(of otherElement: Element) -> Element? { - first(where: { ($0.mangledName ?? $0.name) == (otherElement.mangledName ?? otherElement.name) }) - } -} - -class Definition: Codable, Equatable { - let root: Element - - enum CodingKeys: String, CodingKey { - case root = "ABIRoot" - } - - public static func == (lhs: Definition, rhs: Definition) -> Bool { - lhs.root == rhs.root - } -} - -struct Change { - enum ChangeType { - case addition - case removal - case change - - var icon: String { - switch self { - case .addition: - return "❇️ " - case .removal: - return "πŸ˜Άβ€πŸŒ«οΈ" - case .change: - return "πŸ”€" - } - } - } - - var changeType: ChangeType - var parentName: String - var changeDescription: String -} - -func recursiveCompare(element lhs: Element, to rhs: Element, oldFirst: Bool) -> [Change] { - if lhs == rhs { - return [] - } - - if lhs.isSpiInternal && rhs.isSpiInternal { - // If both elements are spi internal we can ignore them as they are not in the public interface - return [] - } - - var changes = [Change]() - - // TODO: Add check if accessor changed (e.g. changed from get/set to get only...) - - if oldFirst, ( - lhs.printedName != rhs.printedName || - lhs.spiGroupNames != rhs.spiGroupNames || - lhs.conformances != rhs.conformances || - lhs.declAttributes != rhs.declAttributes - ) { - // TODO: Show what exactly changed (name, spi, conformance, declAttributes, ...) as a bullet list maybe (add a `changeList` property to `Change`) - changes += [.init(changeType: .change, parentName: lhs.parentPath, changeDescription: "`\(lhs)` ➑️ `\(rhs)`")] - } - - if lhs.children == rhs.children { - return changes - } - - changes += lhs.children?.flatMap { lhsElement in - if let rhsChildForName = rhs.children?.firstElementMatchingName(of: lhsElement) { - return recursiveCompare(element: lhsElement, to: rhsChildForName, oldFirst: oldFirst) - } else { - if lhsElement.isSpiInternal { return [] } - - if oldFirst { - return [.init(changeType: .removal, parentName: lhsElement.parentPath, changeDescription: "`\(lhsElement)` was removed")] - } else { - return [.init(changeType: .addition, parentName: lhsElement.parentPath, changeDescription: "`\(lhsElement)` was added")] - } - } - } ?? [] - - return changes -} - -func setupRelationships(for element: Element, parent: Element?) { - element.children?.forEach { - $0.parent = element - setupRelationships(for: $0, parent: element) - } -} - -func compare() throws { - let oldFileUrl = currentDirectory.appending(path: old) - let newFileUrl = currentDirectory.appending(path: new) - - let decodedOldDefinition = try JSONDecoder().decode( - Definition.self, - from: Data(contentsOf: oldFileUrl) - ) - - let decodedNewDefinition = try JSONDecoder().decode( - Definition.self, - from: Data(contentsOf: newFileUrl) - ) - - if decodedOldDefinition == decodedNewDefinition { - try persistComparison(fileContent: "## 🫧 `\(moduleName)`\n- No changes detected") - return - } - - setupRelationships(for: decodedOldDefinition.root, parent: nil) - setupRelationships(for: decodedNewDefinition.root, parent: nil) - - let changes = recursiveCompare( - element: decodedOldDefinition.root, - to: decodedNewDefinition.root, - oldFirst: true - ) + recursiveCompare( - element: decodedNewDefinition.root, - to: decodedOldDefinition.root, - oldFirst: false - ) - - var groupedChanges = [String: [Change]]() - - changes.forEach { - groupedChanges[$0.parentName] = (groupedChanges[$0.parentName] ?? []) + [$0] - } - - var fileContent = ["## πŸ‘€ `\(moduleName)`\n"] - - groupedChanges.keys.sorted().forEach { key in - fileContent += ["### \(key)"] - groupedChanges[key]?.sorted(by: { $0.changeDescription < $1.changeDescription }).forEach { - fileContent += ["- \($0.changeType.icon) \($0.changeDescription)"] - } - } - - try persistComparison(fileContent: fileContent.joined(separator: "\n")) -} - -func persistComparison(fileContent: String) throws { - print(fileContent) - let outputPath = currentDirectory.appendingPathComponent("api_comparison.md") - - if FileManager.default.fileExists(atPath: outputPath.path) { - guard let data = (fileContent + "\n\n").data(using: String.Encoding.utf8) else { return } - let fileHandle = try FileHandle(forWritingTo: outputPath) - fileHandle.seekToEndOfFile() - fileHandle.write(data) - fileHandle.closeFile() - } else { - guard let data = ("# Public API Changes\n" + fileContent + "\n\n").data(using: String.Encoding.utf8) else { return } - try data.write(to: outputPath, options: .atomicWrite) - } -} - -do { - try compare() -} catch { - print(error) -} diff --git a/Scripts/generate_public_interface_definition.sh b/Scripts/generate_public_interface_definition.sh deleted file mode 100755 index 6c5dce5b14..0000000000 --- a/Scripts/generate_public_interface_definition.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash - -BRANCH=$1 -REPO=$2 -TARGET="x86_64-apple-ios17.4-simulator" -SDK="`xcrun --sdk iphonesimulator --show-sdk-path`" -MODULE_NAMES=("Adyen" "AdyenDropIn" "AdyenActions" "AdyenCard" "AdyenEncryption" "AdyenComponents" "AdyenSession" "AdyenWeChatPay" "AdyenCashAppPay" "AdyenTwint" "AdyenDelegatedAuthentication") -COMPARISON_VERSION_DIR_NAME="comparison_version_$BRANCH" -DERIVED_DATA_PATH=".build" -SDK_DUMP_INPUT_PATH="$DERIVED_DATA_PATH/Build/Products/Debug-iphonesimulator" - -echo "Branch: " $BRANCH -echo "Repo: " $REPO -echo "Target: " $TARGET -echo "Dir: " $COMPARISON_VERSION_DIR_NAME - -echo "Modules:" -for MODULE in ${MODULE_NAMES[@]} -do - echo "-" $MODULE -done - -rm -rf .build -rm -rf comparison_version - -function cleanup() { - rm -rf .build - rm -rf $COMPARISON_VERSION_DIR_NAME - mv Adyen.xcode_proj Adyen.xcodeproj -} - -function setupComparisonRepo() { - rm -rf $COMPARISON_VERSION_DIR_NAME - mkdir $COMPARISON_VERSION_DIR_NAME - cd $COMPARISON_VERSION_DIR_NAME - git clone -b $BRANCH $REPO - - cd adyen-ios - mv Adyen.xcodeproj Adyen.xcode_proj # We have to obscure the project file so `xcodebuild` uses the Package.swift to build the module -} - -trap cleanup EXIT - -# TODO: Compile a list of changed modules from the git diff -# TODO: Generate a Package.swift library that contains all targets/modules so we don't have to do multiple slow `xcodebuild` - -mv Adyen.xcodeproj Adyen.xcode_proj - -echo "β†˜οΈ Checking out comparison version" -setupComparisonRepo # We're now in the comparison repository directory - -echo "πŸ‘· Building & Diffing" -for MODULE in ${MODULE_NAMES[@]} -do - -echo "πŸ› οΈ [$MODULE] Building comparison project" -xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet - -echo "πŸ“‹ [$MODULE] Generating comparison api_dump" -xcrun swift-api-digester -dump-sdk -module $MODULE -o ../../api_dump_comparison.json -I $SDK_DUMP_INPUT_PATH -sdk $SDK -target $TARGET - -cd ../.. - -echo "πŸ› οΈ [$MODULE] Building updated project" -xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme $MODULE -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet - -echo "πŸ“‹ [$MODULE] Generating new api_dump" -xcrun swift-api-digester -dump-sdk -module $MODULE -o api_dump.json -I $SDK_DUMP_INPUT_PATH -sdk $SDK -target $TARGET - -echo "πŸ•΅οΈ [$MODULE] Diffing" -./Scripts/compare_public_interface_definition.swift api_dump_comparison.json api_dump.json $MODULE - -# Reset and move into comparison dir again for the next iteration -rm api_dump.json -rm api_dump_comparison.json -cd $COMPARISON_VERSION_DIR_NAME/adyen-ios - -done From 1dc1692ca50d3979b3ebfd9c23f04746d68af242 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 14 Jun 2024 15:17:39 +0200 Subject: [PATCH 39/43] Only running the script on PRs and manually --- .github/workflows/detect_api_changes.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index fd83b6f28a..78f8dd7b25 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -4,9 +4,6 @@ on: workflow_dispatch: pull_request: types: [opened, synchronize, reopened] - push: - branches: - - develop jobs: From 911d6f9a344347c18f6d0a08a4140a2c900b5a1c Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 14 Jun 2024 15:18:45 +0200 Subject: [PATCH 40/43] Remove manual run of script --- .github/workflows/detect_api_changes.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index 78f8dd7b25..02b64203b8 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -1,7 +1,6 @@ name: Detect public API changes on: - workflow_dispatch: pull_request: types: [opened, synchronize, reopened] From e7f8c5744bb27f0e51d1bf0aac013a01b0f1e3bf Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Fri, 14 Jun 2024 16:30:34 +0200 Subject: [PATCH 41/43] Do not add "no changes detected" to output --- Scripts/detect_public_api_changes/diff.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Scripts/detect_public_api_changes/diff.swift b/Scripts/detect_public_api_changes/diff.swift index 7b6591fb86..44d02a7ef9 100755 --- a/Scripts/detect_public_api_changes/diff.swift +++ b/Scripts/detect_public_api_changes/diff.swift @@ -211,7 +211,7 @@ func compare() throws { ) if decodedOldDefinition == decodedNewDefinition { - try persistComparison(fileContent: "## 🫧 `\(moduleName)`\n- No changes detected") + // try persistComparison(fileContent: "## 🫧 `\(moduleName)`\n- No changes detected") return } From 5d09aff51ab1dba09d9ea1868e6da2a3a165b01d Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Sat, 15 Jun 2024 13:48:17 +0200 Subject: [PATCH 42/43] Simplifying generation --- Scripts/detect_public_api_changes/compare.sh | 161 +++++++++++++----- Scripts/detect_public_api_changes/diff.swift | 4 +- .../package_file_helper.swift | 70 ++++++++ .../update_package_file.swift | 64 ------- 4 files changed, 193 insertions(+), 106 deletions(-) create mode 100755 Scripts/detect_public_api_changes/package_file_helper.swift delete mode 100755 Scripts/detect_public_api_changes/update_package_file.swift diff --git a/Scripts/detect_public_api_changes/compare.sh b/Scripts/detect_public_api_changes/compare.sh index 2b40dc95ef..55806092e8 100755 --- a/Scripts/detect_public_api_changes/compare.sh +++ b/Scripts/detect_public_api_changes/compare.sh @@ -1,78 +1,157 @@ #!/bin/bash +# ------------------------------------------------------------------- +# Setup & Info +# ------------------------------------------------------------------- + BRANCH=$1 REPO=$2 TARGET="x86_64-apple-ios17.4-simulator" SDK="`xcrun --sdk iphonesimulator --show-sdk-path`" -MODULE_NAMES=("Adyen" "AdyenDropIn" "AdyenActions" "AdyenCard" "AdyenEncryption" "AdyenComponents" "AdyenSession" "AdyenWeChatPay" "AdyenCashAppPay" "AdyenTwint" "AdyenDelegatedAuthentication") COMPARISON_VERSION_DIR_NAME="comparison_version_$BRANCH" DERIVED_DATA_PATH=".build" SDK_DUMP_INPUT_PATH="$DERIVED_DATA_PATH/Build/Products/Debug-iphonesimulator" +ALL_TARGETS_LIBRARY_NAME="AdyenAllTargets" +MODULE_NAMES=($(./Scripts/detect_public_api_changes/package_file_helper.swift Package.swift -print-available-targets)) -echo "Branch: " $BRANCH -echo "Repo: " $REPO -echo "Target: " $TARGET -echo "Dir: " $COMPARISON_VERSION_DIR_NAME +# ------------------------------------------------------------------- +# Convenience Functions +# ------------------------------------------------------------------- -echo "Modules:" -for MODULE in ${MODULE_NAMES[@]} -do - echo "-" $MODULE -done +# Echos the entered information for validation +function printRunInfo() { -rm -rf .build -rm -rf comparison_version + echo "Branch: " $BRANCH + echo "Repo: " $REPO + echo "Target: " $TARGET + echo "Dir: " $COMPARISON_VERSION_DIR_NAME -function cleanup() { - rm -rf .build - rm -rf $COMPARISON_VERSION_DIR_NAME - mv Adyen.xcode_proj Adyen.xcodeproj + echo "Modules:" + for MODULE in ${MODULE_NAMES[@]}; do + echo "-" $MODULE + done } +# Clones the comparison project into a custom directory function setupComparisonRepo() { + rm -rf $COMPARISON_VERSION_DIR_NAME mkdir $COMPARISON_VERSION_DIR_NAME cd $COMPARISON_VERSION_DIR_NAME git clone -b $BRANCH $REPO + cd .. +} + +# Builds the project and temporarily modifies +# some files to optimize the process +# +# $1 - The path to the current project dir +# +# Examples +# +# buildProject . # If we're in the current project dir +# buildProject ../.. # If we're in the comparison project dir +function buildProject() { + + # Removing derived data if available + rm -rf .build + + # We have to obscure the project file so `xcodebuild` uses the Package.swift to build the module + mv Adyen.xcodeproj Adyen.xcode_proj + + # Copying the Package.swift so we can revert the change done by the next step + cp Package.swift Package.sw_ift + + # Modify the Package.swift file to generate a product/library that contains all targets + # so we only have to build it once and can use it to diff all modules + $1/Scripts/detect_public_api_changes/package_file_helper.swift Package.swift -add-consolidated-library $ALL_TARGETS_LIBRARY_NAME + + xcodebuild -scheme $ALL_TARGETS_LIBRARY_NAME \ + -sdk $SDK \ + -derivedDataPath $DERIVED_DATA_PATH \ + -destination "platform=iOS,name=Any iOS Device" \ + -target $TARGET \ + -quiet \ + -skipPackagePluginValidation - cd adyen-ios - ../../Scripts/detect_public_api_changes/update_package_file.swift Package.swift "AdyenAllTargets" - mv Adyen.xcodeproj Adyen.xcode_proj # We have to obscure the project file so `xcodebuild` uses the Package.swift to build the module + # Reverting the tmp changes + rm Package.swift + mv Adyen.xcode_proj Adyen.xcodeproj + mv Package.sw_ift Package.swift } -trap cleanup EXIT +# Generates an sdk-dump in form of a json file +# +# $1 - The module to generate the dump for +# $2 - The output path for the generated json file +# +# Examples +# +# generateSdkDump "AdyenDropIn" "api_dump.json" +# +function generateSdkDump() { + + xcrun swift-api-digester -dump-sdk \ + -module $1 \ + -o $2 \ + -I $SDK_DUMP_INPUT_PATH \ + -sdk $SDK \ + -target $TARGET +} -mv Adyen.xcodeproj Adyen.xcode_proj -./Scripts/detect_public_api_changes/update_package_file.swift Package.swift "AdyenAllTargets" +# Compares both versions of the provided module +# and writes the result into a .md file (Handled by the diff.swift script) +# +# $1 - The module to compare +# +# Examples +# +# diffModuleVersions "AdyenDropIn" +# +function diffModuleVersions() { -echo "β†˜οΈ Checking out comparison version" -setupComparisonRepo # We're now in the comparison repository directory + echo "πŸ“‹ [$1] Generating current sdk dump" + generateSdkDump $1 "api_dump.json" -echo "πŸ› οΈ Building 'AdyenAllTargets' comparison project" -xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme "AdyenAllTargets" -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet -cd ../.. -echo "πŸ› οΈ Building 'AdyenAllTargets' updated project" -xcodebuild -derivedDataPath $DERIVED_DATA_PATH -sdk $SDK -scheme "AdyenAllTargets" -destination "platform=iOS,name=Any iOS Device" -target $TARGET -quiet + cd $COMPARISON_VERSION_DIR_NAME/adyen-ios -echo "πŸ‘· Building & Diffing" -for MODULE in ${MODULE_NAMES[@]} -do + echo "πŸ“‹ [$1] Generating comparison sdk dump" + generateSdkDump $1 "../../api_dump_comparison.json" + cd ../.. + + ./Scripts/detect_public_api_changes/diff.swift "api_dump.json" "api_dump_comparison.json" $1 + + # Cleaning up afterwards + rm api_dump.json + rm api_dump_comparison.json +} + +# ------------------------------------------------------------------- +# Main Execution +# ------------------------------------------------------------------- + +printRunInfo + +echo "β†˜οΈ Setting up comparison project" +setupComparisonRepo + +# Move into the comparison project cd $COMPARISON_VERSION_DIR_NAME/adyen-ios -echo "πŸ“‹ [$MODULE] Generating comparison api_dump" -xcrun swift-api-digester -dump-sdk -module $MODULE -o ../../api_dump_comparison.json -I $SDK_DUMP_INPUT_PATH -sdk $SDK -target $TARGET +echo "πŸ› οΈ Building '$ALL_TARGETS_LIBRARY_NAME' comparison project" +buildProject ../.. +# Move back to the current project dir cd ../.. -echo "πŸ“‹ [$MODULE] Generating new api_dump" -xcrun swift-api-digester -dump-sdk -module $MODULE -o api_dump.json -I $SDK_DUMP_INPUT_PATH -sdk $SDK -target $TARGET +echo "πŸ› οΈ Building '$ALL_TARGETS_LIBRARY_NAME' current project" +buildProject . + +echo "πŸ‘· Diffing all Modules" -echo "πŸ•΅οΈ [$MODULE] Diffing" -./diff.swift api_dump.json api_dump_comparison.json $MODULE +for MODULE in ${MODULE_NAMES[@]}; do -# Reset and move into comparison dir again for the next iteration -rm api_dump.json -rm api_dump_comparison.json +diffModuleVersions $MODULE done diff --git a/Scripts/detect_public_api_changes/diff.swift b/Scripts/detect_public_api_changes/diff.swift index 44d02a7ef9..1ca0979d59 100755 --- a/Scripts/detect_public_api_changes/diff.swift +++ b/Scripts/detect_public_api_changes/diff.swift @@ -10,6 +10,8 @@ import Foundation let currentDirectory = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) +// TODO: Pass all modules at once so we can write the file out all at once +// (This also allows us to indicate in the title whether or not there were any changes) let old = CommandLine.arguments[1] let new = CommandLine.arguments[2] let moduleName = CommandLine.arguments[3] @@ -211,7 +213,7 @@ func compare() throws { ) if decodedOldDefinition == decodedNewDefinition { - // try persistComparison(fileContent: "## 🫧 `\(moduleName)`\n- No changes detected") + try persistComparison(fileContent: "## 🫧 `\(moduleName)` - No changes detected") return } diff --git a/Scripts/detect_public_api_changes/package_file_helper.swift b/Scripts/detect_public_api_changes/package_file_helper.swift new file mode 100755 index 0000000000..4b344a0c47 --- /dev/null +++ b/Scripts/detect_public_api_changes/package_file_helper.swift @@ -0,0 +1,70 @@ +#!/usr/bin/env xcrun swift + +import Foundation + +// MARK: - Convenience Methods + +/// Extracts all targets in the targets section +/// +/// Returns: All available target names +func availableTargets(from packageContent: String) -> [String] { + let scanner = Scanner(string: packageContent) + _ = scanner.scanUpToString("targets: [") + + var availableTargets = Set() + + while scanner.scanUpToString(".target(") != nil { + let nameStartTag = "name: \"" + let nameEndTag = "\"" + + _ = scanner.scanUpToString(nameStartTag) + _ = scanner.scanString(nameStartTag) + + if let targetName = scanner.scanUpToString(nameEndTag) { + availableTargets.insert(targetName) + } + } + + return availableTargets.sorted() +} + +/// Generates a library entry from the name and available target names to be inserted into the `Package.swift` file +func consolidatedLibraryEntry(_ name: String, from availableTargets: [String]) -> String { +""" + + .library( + name: "\(name)", + targets: [\(availableTargets.map { "\"\($0)\"" }.joined(separator: ", "))] + ), +""" +} + +/// Generates the updated content for the `Package.swift` adding the consolidated library entry (containing all targets) in the products section +func updatedContent(with consolidatedEntry: String) -> String { + // Update the Package.swift content + var updatedContent = packageContent + if let productsRange = packageContent.range(of: "products: [", options: .caseInsensitive) { + updatedContent.insert(contentsOf: consolidatedEntry, at: productsRange.upperBound) + } else { + print("Products section not found") + } + return updatedContent +} + +// MARK: - Main + +let packagePath = CommandLine.arguments[1] // Path to the Package.swift file +let packageContent = try String(contentsOfFile: packagePath) +let targets = availableTargets(from: packageContent) + +if CommandLine.arguments[2] == "-add-consolidated-library" { + // Inserts a new library into the targets section containing all targets from the target section + let consolidatedLibraryName = CommandLine.arguments[3] // Name of the library containing all targets + let consolidatedEntry = consolidatedLibraryEntry(consolidatedLibraryName, from: targets) + let updatedPackageContent = updatedContent(with: consolidatedEntry) + // Write the updated content back to the file + try updatedPackageContent.write(toFile: packagePath, atomically: true, encoding: .utf8) +} else if CommandLine.arguments[2] == "-print-available-targets" { + // Prints the targets to the console so it can be consumed by the "compare.sh" script and transformed in to an array + print(targets.joined(separator: " ")) +} diff --git a/Scripts/detect_public_api_changes/update_package_file.swift b/Scripts/detect_public_api_changes/update_package_file.swift deleted file mode 100755 index 8e25a8f86e..0000000000 --- a/Scripts/detect_public_api_changes/update_package_file.swift +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env xcrun swift - -import Foundation - -///Parse Package.swift file and add a new library to the list of products that contains all targets - -// MARK: - Convenience Methods - -func availableTargets(from packageContent: String) -> [String] { - let scanner = Scanner(string: packageContent) - _ = scanner.scanUpTo("targets: [", into: nil) - - var availableTargets = Set() - - while scanner.scanUpTo(".target(", into: nil) { - let nameStartTag = "name: \"" - let nameEndTag = "\"" - - scanner.scanUpTo(nameStartTag, into: nil) - scanner.scanString(nameStartTag, into: nil) - - var targetName: NSString? - scanner.scanUpTo(nameEndTag, into: &targetName) - if let targetName = targetName as? String { - availableTargets.insert(targetName) - } - } - - return availableTargets.sorted() -} - -func consolidatedLibraryEntry(_ name: String, from availableTargets: [String]) -> String { -""" - - .library( - name: "\(name)", - targets: [\(availableTargets.map { "\"\($0)\"" }.joined(separator: ", "))] - ), -""" -} - -func updatedContent(with consolidatedEntry: String) -> String { - // Update the Package.swift content - var updatedContent = packageContent - if let productsRange = packageContent.range(of: "products: [", options: .caseInsensitive) { - updatedContent.insert(contentsOf: consolidatedEntry, at: productsRange.upperBound) - } else { - print("Products section not found") - } - return updatedContent -} - -// MARK: - Main - -let packagePath = CommandLine.arguments[1] // Path to the Package.swift file -let consolidatedLibraryName = CommandLine.arguments[2] // Name of the library containing all targets - -let packageContent = try String(contentsOfFile: packagePath) -let targets = availableTargets(from: packageContent) -let consolidatedEntry = consolidatedLibraryEntry(consolidatedLibraryName, from: targets) -let updatedPackageContent = updatedContent(with: consolidatedEntry) - -// Write the updated content back to the file -try updatedPackageContent.write(toFile: packagePath, atomically: true, encoding: .utf8) From a3233861df96e8ff3e80709c8198698636f13149 Mon Sep 17 00:00:00 2001 From: Alex Guretzki Date: Wed, 19 Jun 2024 14:40:00 +0200 Subject: [PATCH 43/43] fixing github workflow --- .github/workflows/detect_api_changes.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/detect_api_changes.yml b/.github/workflows/detect_api_changes.yml index 29a5ee1c6b..02b64203b8 100644 --- a/.github/workflows/detect_api_changes.yml +++ b/.github/workflows/detect_api_changes.yml @@ -22,7 +22,7 @@ jobs: - name: πŸ” Detect Changes run: | - Scripts/generate_public_interface_definition.sh ${branch} ${baseRepo} + Scripts/detect_public_api_changes/compare.sh ${branch} ${baseRepo} env: branch: '${{github.event.pull_request.base.ref}}' baseRepo: '${{github.server_url}}/${{github.repository}}.git'