From 01f4583166505b1543f9ac80e3acb3cfdc9c9377 Mon Sep 17 00:00:00 2001 From: Arthur Alves Date: Wed, 14 Dec 2022 17:51:05 +0100 Subject: [PATCH 01/14] ref: change 'Bash().capture' method to select either the stdout or stderr stream --- Sources/VariantsCore/Helpers/Bash.swift | 30 ++++++++++++++++++------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/Sources/VariantsCore/Helpers/Bash.swift b/Sources/VariantsCore/Helpers/Bash.swift index 4ddd09fe..726c4142 100644 --- a/Sources/VariantsCore/Helpers/Bash.swift +++ b/Sources/VariantsCore/Helpers/Bash.swift @@ -11,6 +11,11 @@ struct Bash { var command: String var arguments: [String] + enum Stream { + case stdout + case stderr + } + init(_ command: String, arguments: String...) { self.command = command self.arguments = arguments @@ -20,12 +25,12 @@ struct Bash { _ = try capture() } - func capture() throws -> String? { + func capture(stream: Stream = .stdout) throws -> String? { guard var bashCommand = try execute(command: "/bin/bash", arguments: ["-l", "-c", "which \(command)"]) else { throw RuntimeError("\(command) not found") } bashCommand = bashCommand.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines) - if let output = try execute(command: bashCommand, arguments: arguments) { + if let output = try execute(command: bashCommand, arguments: arguments, stream: stream) { // `dropLast()` is required as the output always contains a new line (`\n`) at the end. return String(output.dropLast()) } @@ -34,11 +39,13 @@ struct Bash { // MARK: - Private - private func execute(command: String, arguments: [String] = []) throws -> String? { + private func execute(command: String, arguments: [String] = [], stream: Stream = .stdout) throws -> String? { let process = Process() - let pipe = Pipe() + let stdoutPipe = Pipe() + let stderrPipe = Pipe() process.arguments = arguments - process.standardOutput = pipe + process.standardOutput = stdoutPipe + process.standardError = stderrPipe if #available(OSX 10.13, *) { process.executableURL = URL(fileURLWithPath: command) @@ -48,8 +55,15 @@ struct Bash { process.launch() } - let data = pipe.fileHandleForReading.readDataToEndOfFile() - let output = String(data: data, encoding: .utf8) - return output + switch stream { + case .stdout: + let stdoutData = stdoutPipe.fileHandleForReading.readDataToEndOfFile() + let stdout = String(data: stdoutData, encoding: .utf8) + return stdout + case .stderr: + let stderrData = stderrPipe.fileHandleForReading.readDataToEndOfFile() + let stderr = String(data: stderrData, encoding: .utf8) + return stderr + } } } From db3f2a0c5fe100cbfe09cf9e61582c2e58432f4f Mon Sep 17 00:00:00 2001 From: Arthur Alves Date: Wed, 14 Dec 2022 17:51:56 +0100 Subject: [PATCH 02/14] ref: require python3 to run 'gyb' and alert default to fatalError if python3 can't be found --- .../Factory/iOS/VariantsFileFactory.swift | 11 +++++++++-- utils/gyb | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift b/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift index 75ec6b28..770629ce 100644 --- a/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift +++ b/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift @@ -72,14 +72,21 @@ class VariantsFileFactory { let fileContent = try? variantsGybFile.read(), fileContent == data { - try Bash(gybExecutablePath.absolute().description, + let gybStdErr = try Bash(gybExecutablePath.absolute().description, arguments: "--line-directive", "", "-o", "Variants.swift", variantsGybFile.absolute().description - ).run() + ).capture(stream: .stderr) + if let stdErr = gybStdErr, !stdErr.isEmpty { + if stdErr.contains("env: python3: No such file or directory") { + logger.logFatal(item: "We're unable to find a 'python3' executable. Install 'python3' or ensure it's your executable path and try running this Variants command again.") + } else { + logger.logFatal(item: stdErr as Any) + } + } logger.logInfo("⚙️ ", item: """ '\(variantsGybFile.parent().abbreviate().string)/Variants.swift' has been generated with success diff --git a/utils/gyb b/utils/gyb index dece788e..8206bd8a 100755 --- a/utils/gyb +++ b/utils/gyb @@ -1,3 +1,3 @@ -#!/usr/bin/env python2.7 +#!/usr/bin/env python3 import gyb gyb.main() From 9da879bcaa07ab5d2127ecf5006b239daccd05ac Mon Sep 17 00:00:00 2001 From: Arthur Alves Date: Wed, 14 Dec 2022 18:08:37 +0100 Subject: [PATCH 03/14] chore: adjust log message to print over multiple lines --- Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift | 6 +++++- Tests/VariantsCoreTests/VariantsFileFactoryTests.swift | 2 -- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift b/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift index 770629ce..0e120815 100644 --- a/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift +++ b/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift @@ -82,7 +82,11 @@ class VariantsFileFactory { ).capture(stream: .stderr) if let stdErr = gybStdErr, !stdErr.isEmpty { if stdErr.contains("env: python3: No such file or directory") { - logger.logFatal(item: "We're unable to find a 'python3' executable. Install 'python3' or ensure it's your executable path and try running this Variants command again.") + logger.logFatal(item: + """ + We're unable to find a 'python3' executable. + Install 'python3' or ensure it's your executable path and try running this Variants command again. + """) } else { logger.logFatal(item: stdErr as Any) } diff --git a/Tests/VariantsCoreTests/VariantsFileFactoryTests.swift b/Tests/VariantsCoreTests/VariantsFileFactoryTests.swift index 8c368a0f..704fb37a 100644 --- a/Tests/VariantsCoreTests/VariantsFileFactoryTests.swift +++ b/Tests/VariantsCoreTests/VariantsFileFactoryTests.swift @@ -60,8 +60,6 @@ class VariantsFileFactoryTests: XCTestCase { let variantsFilePath = Bundle(for: type(of: self)).path(forResource: "Resources/ios/Variants", ofType: "swift") XCTAssertNotNil(variantsFilePath) -// guard let variantsFile = variantsFilePath else { return } -// XCTAssertEqual(try String(contentsOfFile: variantsFile), variantsSwiftContent) } func testUtilsDirectory_pathExists() { From c709bbfbacc64fa70f574178b3ff1ff277cdb65f Mon Sep 17 00:00:00 2001 From: Arthur Alves Date: Thu, 15 Dec 2022 15:08:44 +0100 Subject: [PATCH 04/14] ref: better handle GYB error; rely on python2.7 instead of python3; and ensure 'testRender_noSecrets' is corrected --- .../Factory/iOS/VariantsFileFactory.swift | 42 ++++++++++++------- Templates/ios/Variants.swift.template.gyb | 21 +++++----- .../VariantsFileFactoryTests.swift | 21 ++++++++-- utils/gyb | 2 +- 4 files changed, 56 insertions(+), 30 deletions(-) diff --git a/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift b/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift index 0e120815..8a2d46da 100644 --- a/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift +++ b/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift @@ -30,7 +30,6 @@ class VariantsFileFactory { "secrets": secrets, "configurationValues": configurationValues ] as [String: Any] - let environment = Environment(loader: FileSystemLoader(paths: [variantsGybTemplatePath.absolute()])) let rendered = try environment.renderTemplate(name: StaticPath.Template.variantsSwiftGybFileName, context: context) @@ -80,27 +79,40 @@ class VariantsFileFactory { "Variants.swift", variantsGybFile.absolute().description ).capture(stream: .stderr) - if let stdErr = gybStdErr, !stdErr.isEmpty { - if stdErr.contains("env: python3: No such file or directory") { - logger.logFatal(item: - """ - We're unable to find a 'python3' executable. - Install 'python3' or ensure it's your executable path and try running this Variants command again. - """) - } else { - logger.logFatal(item: stdErr as Any) - } - } + let variantsFilePath = "\(variantsGybFile.parent().abbreviate().string)/Variants.swift" + handleGybErrors(message: gybStdErr, variantsFilePath: variantsFilePath) - logger.logInfo("⚙️ ", item: """ - '\(variantsGybFile.parent().abbreviate().string)/Variants.swift' has been generated with success - """, color: .green) + logger.logInfo("⚙️ ", item: "'\(variantsFilePath)' has been generated with success", color: .green) } } else { throw TemplateDoesNotExist(templateNames: [folder.string]) } } + private func handleGybErrors(message: String?, variantsFilePath: String) { + if let stdErr = message, !stdErr.isEmpty { + if stdErr.contains("env: python2.7: No such file or directory") { + logger.logFatal(item: + """ + We're unable to find a 'python2.7' executable. + Install 'python2.7' or ensure it's in your executables path and try running this Variants command again. + Tip: + * Install pyenv (brew install pyenv) + * Install python2.7 (pyenv install python2.7) + * Add "$(pyenv root)/shims" to your PATH + """) + } else if stdErr.contains("for chunk in chunks(encode(os.environ.get(") { + logger.logFatal(item: + """ + We're unable to create 'Variants.Secrets' in '\(variantsFilePath)'. + Ensure that custom config values whose `env: true` are actually environment variables. + """) + } else { + logger.logFatal(item: stdErr as Any) + } + } + } + let logger: Logger } diff --git a/Templates/ios/Variants.swift.template.gyb b/Templates/ios/Variants.swift.template.gyb index c7d01afc..e0c1421f 100644 --- a/Templates/ios/Variants.swift.template.gyb +++ b/Templates/ios/Variants.swift.template.gyb @@ -28,29 +28,28 @@ public struct Variants { {% if configurationValues %} // MARK: - ConfigurationValueKey /// Custom configuration values coming from variants.yml as enum cases - - public enum ConfigurationValueKey: String { {% for confValue in configurationValues %} - case {{ confValue.name }} {% endfor %} + + public enum ConfigurationValueKey: String { + {% for confValue in configurationValues %} + case {{ confValue.name }}{% endfor %} } - + static func configurationValue(for key: ConfigurationValueKey) -> Any? { return Self.configuration[key.rawValue] - } - {% endif %} - + }{% endif %} {% if secrets %} // MARK: - Secrets /// Encrypted secrets coming from variants.yml as environment variables - + public struct Secrets { - + private static let salt: [UInt8] = [ %{ salt = [ord(byte) for byte in os.urandom(64)] }% % for chunk in chunks(salt, 8): ${"".join(["0x%02x, " % byte for byte in chunk])} % end ] - + {% for secret in secrets %} static var {{ secret.name }}: String { let encoded: [UInt8] = [ @@ -62,7 +61,7 @@ public struct Variants { return decode(encoded, cipher: salt) } {% endfor %} - + private static func decode(_ encoded: [UInt8], cipher: [UInt8]) -> String { String(decoding: encoded.enumerated().map { (offset, element) in element ^ cipher[offset % cipher.count] diff --git a/Tests/VariantsCoreTests/VariantsFileFactoryTests.swift b/Tests/VariantsCoreTests/VariantsFileFactoryTests.swift index 704fb37a..b1d4e4d4 100644 --- a/Tests/VariantsCoreTests/VariantsFileFactoryTests.swift +++ b/Tests/VariantsCoreTests/VariantsFileFactoryTests.swift @@ -26,8 +26,19 @@ class VariantsFileFactoryTests: XCTestCase { } return infoDictionary }() + + // MARK: - ConfigurationValueKey + /// Custom configuration values coming from variants.yml as enum cases + public enum ConfigurationValueKey: String { + + case PROPERTY_A + case PROPERTY_B + } + static func configurationValue(for key: ConfigurationValueKey) -> Any? { + return Self.configuration[key.rawValue] + } + } - """ private let defaultVariant = try? iOSVariant( @@ -37,8 +48,10 @@ class VariantsFileFactoryTests: XCTestCase { appIcon: nil, appName: nil, storeDestination: "testFlight", - custom: [CustomProperty(name: "PROPERTY_A", value: "VALUE_A", destination: .project), - CustomProperty(name: "PROPERTY_B", value: "VALUE_B", env: true, destination: .project)], + custom: [ + CustomProperty(name: "PROPERTY_A", value: "VALUE_A", destination: .project), + CustomProperty(name: "PROPERTY_B", value: "VALUE_B", destination: .project) + ], idSuffix: nil, bundleID: nil, variantSigning: nil, @@ -60,6 +73,8 @@ class VariantsFileFactoryTests: XCTestCase { let variantsFilePath = Bundle(for: type(of: self)).path(forResource: "Resources/ios/Variants", ofType: "swift") XCTAssertNotNil(variantsFilePath) + guard let variantsFile = variantsFilePath else { return } + XCTAssertEqual(try String(contentsOfFile: variantsFile), variantsSwiftContent) } func testUtilsDirectory_pathExists() { diff --git a/utils/gyb b/utils/gyb index 8206bd8a..dece788e 100755 --- a/utils/gyb +++ b/utils/gyb @@ -1,3 +1,3 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python2.7 import gyb gyb.main() From 906eec011beaa9356994b30205ba398b5afea28e Mon Sep 17 00:00:00 2001 From: Gabriel Minucci Date: Tue, 10 Dec 2024 11:25:43 +0100 Subject: [PATCH 05/14] chore: improve error handling --- .../Factory/iOS/VariantsFileFactory.swift | 109 +++++++++--------- 1 file changed, 56 insertions(+), 53 deletions(-) diff --git a/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift b/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift index 8a2d46da..ea0f2c84 100644 --- a/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift +++ b/Sources/VariantsCore/Factory/iOS/VariantsFileFactory.swift @@ -52,64 +52,67 @@ class VariantsFileFactory { } private func write(_ data: Data, using folder: Path = Path("/tmp/")) throws { - if folder.isDirectory, folder.exists { - let variantsGybFile = try folder.safeJoin(path: Path(StaticPath.Xcode.variantsGybFileName)) - - // Only proceed to write to file if such doesn't yet exist - // Or does exist and 'isWritable' - guard !variantsGybFile.exists - || variantsGybFile.isWritable else { - throw TemplateDoesNotExist(templateNames: [folder.string]) - } - - // Write to file - try variantsGybFile.write(data) - - if - try UtilsDirectory().path.exists, - let gybExecutablePath = try? UtilsDirectory().path.safeJoin(path: "gyb"), - let fileContent = try? variantsGybFile.read(), - fileContent == data { - - let gybStdErr = try Bash(gybExecutablePath.absolute().description, - arguments: - "--line-directive", - "", - "-o", - "Variants.swift", - variantsGybFile.absolute().description - ).capture(stream: .stderr) - let variantsFilePath = "\(variantsGybFile.parent().abbreviate().string)/Variants.swift" - handleGybErrors(message: gybStdErr, variantsFilePath: variantsFilePath) - - logger.logInfo("⚙️ ", item: "'\(variantsFilePath)' has been generated with success", color: .green) - } - } else { + guard folder.isDirectory, folder.exists else { + throw TemplateDoesNotExist(templateNames: [folder.string]) + } + + let variantsGybFile = try folder.safeJoin(path: Path(StaticPath.Xcode.variantsGybFileName)) + // Only proceed to write to file if such doesn't yet exist + // Or does exist and 'isWritable' + guard !variantsGybFile.exists || variantsGybFile.isWritable else { throw TemplateDoesNotExist(templateNames: [folder.string]) } + + try variantsGybFile.write(data) + guard + try UtilsDirectory().path.exists, + let gybExecutablePath = try? UtilsDirectory().path.safeJoin(path: "gyb"), + let fileContent = try? variantsGybFile.read(), + fileContent == data + else { return } + + let gybStdErr = try Bash(gybExecutablePath.absolute().description, + arguments: + "--line-directive", + "", + "-o", + "Variants.swift", + variantsGybFile.absolute().description + ).capture(stream: .stderr) + let variantsFilePath = "\(variantsGybFile.parent().abbreviate().string)/Variants.swift" + handleGybErrors(message: gybStdErr, variantsFilePath: variantsFilePath) + logger.logInfo("⚙️ ", item: "'\(variantsFilePath)' has been generated with success", color: .green) } private func handleGybErrors(message: String?, variantsFilePath: String) { - if let stdErr = message, !stdErr.isEmpty { - if stdErr.contains("env: python2.7: No such file or directory") { - logger.logFatal(item: - """ - We're unable to find a 'python2.7' executable. - Install 'python2.7' or ensure it's in your executables path and try running this Variants command again. - Tip: - * Install pyenv (brew install pyenv) - * Install python2.7 (pyenv install python2.7) - * Add "$(pyenv root)/shims" to your PATH - """) - } else if stdErr.contains("for chunk in chunks(encode(os.environ.get(") { - logger.logFatal(item: - """ - We're unable to create 'Variants.Secrets' in '\(variantsFilePath)'. - Ensure that custom config values whose `env: true` are actually environment variables. - """) - } else { - logger.logFatal(item: stdErr as Any) - } + guard let message, !message.isEmpty else { return } + + switch message { + case _ where message.contains("env: python2.7: No such file or directory"): + logger.logFatal(item: + """ + We're unable to find a 'python2.7' executable. + Install 'python2.7' or ensure it's in your executables path and try running this Variants command again. + Tip: + * Install pyenv (brew install pyenv) + * Install python2.7 (pyenv install python2.7) + * Add "$(pyenv root)/shims" to your PATH + """) + case _ where message.contains("for chunk in chunks(encode(os.environ.get("): + logger.logFatal(item: + """ + We're unable to create 'Variants.Secrets' in '\(variantsFilePath)'. + Ensure that custom config values whose `env: true` are actually environment variables. + """) + case _ where message.contains("pyenv: python2.7: command not found"): + logger.logFatal(item: + """ + Looks like you have pyenv installed but the current configured version is not correct. + Please, select the latest build of python 2.7 as local version. + For example: `pyenv local 2.7` + """) + default: + logger.logFatal(item: message as Any) } } From 2c68863fd6bdb196fe4f95a490c33b087d4c4678 Mon Sep 17 00:00:00 2001 From: Gabriel Minucci Date: Tue, 10 Dec 2024 11:33:29 +0100 Subject: [PATCH 06/14] chore: update swiftlint workflow --- .github/workflows/swiftlint.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.github/workflows/swiftlint.yml b/.github/workflows/swiftlint.yml index cdfc7871..dcda1107 100644 --- a/.github/workflows/swiftlint.yml +++ b/.github/workflows/swiftlint.yml @@ -3,11 +3,17 @@ name: SwiftLint on: pull_request: types: [ opened, synchronize ] + paths: + - '.github/workflows/swiftlint.yml' + - '.swiftlint.yml' + - '**/*.swift' jobs: SwiftLint: - runs-on: macos-latest + runs-on: ubuntu-latest steps: - - uses: actions/checkout@v1 - - name: Run SwiftLint - run: swiftlint lint --strict --reporter github-actions-logging \ No newline at end of file + - uses: actions/checkout@v3 + - name: GitHub Action for SwiftLint + uses: stanfordbdhg/action-swiftlint@v4 + with: + args: --strict --reporter github-actions-logging \ No newline at end of file From 82bd00824496b7523fa9962d664d9ec0d0ff33c5 Mon Sep 17 00:00:00 2001 From: Gabriel Minucci Date: Tue, 10 Dec 2024 12:57:07 +0100 Subject: [PATCH 07/14] fix: swiftlint warnings --- Package.swift | 11 ++-- .../Custom Types/Project/AndroidProject.swift | 3 +- .../Custom Types/Project/iOSProject.swift | 7 ++- Sources/VariantsCore/Helpers/SpecHelper.swift | 4 +- .../Schemas/iOS/iOSConfiguration.swift | 4 +- .../VariantsCore/Schemas/iOS/iOSSigning.swift | 4 +- .../VariantsCore/Schemas/iOS/iOSTarget.swift | 4 +- .../VariantsCore/Schemas/iOS/iOSVariant.swift | 4 +- .../Mocks/MockXCcodeConfigFactory.swift | 3 +- Tests/VariantsCoreTests/YamlParserTests.swift | 5 +- Tests/VariantsCoreTests/iOSProjectTests.swift | 3 +- Tests/VariantsCoreTests/iOSSigningTests.swift | 4 +- Tests/VariantsTests/InitCommandTests.swift | 9 ++-- Variants.xcodeproj/project.pbxproj | 52 ++++++++++++++++++- .../VariantsTestApp/ViewController.swift | 7 +-- 15 files changed, 88 insertions(+), 36 deletions(-) diff --git a/Package.swift b/Package.swift index 5bf38d9b..7dbf2dfc 100644 --- a/Package.swift +++ b/Package.swift @@ -36,7 +36,9 @@ let package = Package( name: "danger-swift", url: "https://github.com/danger/swift.git", from: "3.5.0" - ) + ), + .package( + url: "https://github.com/SimplyDanny/SwiftLintPlugins") ], targets: [ .target( @@ -46,7 +48,8 @@ let package = Package( "Yams", "XcodeProj", .product(name: "ArgumentParser", package: "swift-argument-parser"), - "Stencil" + "Stencil", + "SwiftLintPlugins" ] ), .target( @@ -57,7 +60,9 @@ let package = Package( ), .testTarget( name: "VariantsTests", - dependencies: ["Variants"] + dependencies: [ + "Variants" + ] ) ] ) diff --git a/Sources/VariantsCore/Custom Types/Project/AndroidProject.swift b/Sources/VariantsCore/Custom Types/Project/AndroidProject.swift index 833553a9..1d3f3173 100644 --- a/Sources/VariantsCore/Custom Types/Project/AndroidProject.swift +++ b/Sources/VariantsCore/Custom Types/Project/AndroidProject.swift @@ -101,7 +101,7 @@ class AndroidProject: Project { try gradleFactory.createScript(with: configuration, variant: defaultVariant) } - // swiftlint:disable function_body_length + // swiftlint:disable:next function_body_length private func setupFastlane(with configuration: AndroidConfiguration, skip: Bool) { if skip { Logger.shared.logInfo("Skipped Fastlane setup", item: "") @@ -183,7 +183,6 @@ class AndroidProject: Project { } } } - // swiftlint:enable function_body_length private func storeFastlaneParams(for variant: AndroidVariant, configuration: AndroidConfiguration) throws { var customProperties: [CustomProperty] = (variant.custom ?? []) + (configuration.custom ?? []) diff --git a/Sources/VariantsCore/Custom Types/Project/iOSProject.swift b/Sources/VariantsCore/Custom Types/Project/iOSProject.swift index e529f7ca..d520251b 100644 --- a/Sources/VariantsCore/Custom Types/Project/iOSProject.swift +++ b/Sources/VariantsCore/Custom Types/Project/iOSProject.swift @@ -5,12 +5,12 @@ // Created by Balazs Toth // +// swiftlint:disable type_name + import Foundation import ArgumentParser import PathKit -// swiftlint:disable type_name - class iOSProject: Project { init( specHelper: SpecHelper, @@ -140,7 +140,7 @@ class iOSProject: Project { } } - // swiftlint:disable function_body_length + // swiftlint:disable:next function_body_length private func setupFastlane(with configuration: iOSConfiguration, skip: Bool) { if skip { Logger.shared.logInfo("Skipped Fastlane setup", item: "") @@ -225,7 +225,6 @@ class iOSProject: Project { } } } - // swiftlint:enable function_body_length private func storeFastlaneParams(_ properties: [CustomProperty]) throws { let fastlaneProperties = properties.filter { $0.destination == .fastlane } diff --git a/Sources/VariantsCore/Helpers/SpecHelper.swift b/Sources/VariantsCore/Helpers/SpecHelper.swift index 80e9b642..dece3aa5 100644 --- a/Sources/VariantsCore/Helpers/SpecHelper.swift +++ b/Sources/VariantsCore/Helpers/SpecHelper.swift @@ -5,11 +5,11 @@ // Created by Arthur Alves // +// swiftlint:disable type_name + import Foundation import PathKit -// swiftlint:disable type_name - enum iOSProjectKey: String, CaseIterable { case project = "PROJECT" case target = "TARGET" diff --git a/Sources/VariantsCore/Schemas/iOS/iOSConfiguration.swift b/Sources/VariantsCore/Schemas/iOS/iOSConfiguration.swift index 99f35a60..0e30ab4e 100644 --- a/Sources/VariantsCore/Schemas/iOS/iOSConfiguration.swift +++ b/Sources/VariantsCore/Schemas/iOS/iOSConfiguration.swift @@ -5,10 +5,10 @@ // Created by Arthur Alves // -import Foundation - // swiftlint:disable type_name +import Foundation + internal extension CodingUserInfoKey { static let bundleID = CodingUserInfoKey(rawValue: "bundle_id")! } diff --git a/Sources/VariantsCore/Schemas/iOS/iOSSigning.swift b/Sources/VariantsCore/Schemas/iOS/iOSSigning.swift index a11d516d..2401d9ab 100644 --- a/Sources/VariantsCore/Schemas/iOS/iOSSigning.swift +++ b/Sources/VariantsCore/Schemas/iOS/iOSSigning.swift @@ -5,10 +5,10 @@ // Created by Arthur Alves // -import Foundation - // swiftlint:disable type_name +import Foundation + struct iOSSigning: Codable { let teamName: String? let teamID: String? diff --git a/Sources/VariantsCore/Schemas/iOS/iOSTarget.swift b/Sources/VariantsCore/Schemas/iOS/iOSTarget.swift index 2e1bd843..e6da19f0 100644 --- a/Sources/VariantsCore/Schemas/iOS/iOSTarget.swift +++ b/Sources/VariantsCore/Schemas/iOS/iOSTarget.swift @@ -5,10 +5,10 @@ // Created by Arthur Alves // -import Foundation - // swiftlint:disable type_name +import Foundation + public typealias NamedTarget = (key: String, value: iOSTarget) public struct iOSTarget: Codable { diff --git a/Sources/VariantsCore/Schemas/iOS/iOSVariant.swift b/Sources/VariantsCore/Schemas/iOS/iOSVariant.swift index 1bf1d1c4..64c9513d 100644 --- a/Sources/VariantsCore/Schemas/iOS/iOSVariant.swift +++ b/Sources/VariantsCore/Schemas/iOS/iOSVariant.swift @@ -5,10 +5,10 @@ // Created by Arthur Alves // -import Foundation - // swiftlint:disable type_name +import Foundation + public struct iOSVariant: Variant { let name: String let versionName: String diff --git a/Tests/VariantsCoreTests/Mocks/MockXCcodeConfigFactory.swift b/Tests/VariantsCoreTests/Mocks/MockXCcodeConfigFactory.swift index 6a12306c..51b498eb 100644 --- a/Tests/VariantsCoreTests/Mocks/MockXCcodeConfigFactory.swift +++ b/Tests/VariantsCoreTests/Mocks/MockXCcodeConfigFactory.swift @@ -5,10 +5,11 @@ // Created by Arthur Alves // +// swiftlint:disable colon + import Foundation import PathKit @testable import VariantsCore -// swiftlint:disable colon class MockXCcodeConfigFactory: XCFactory { var writeContentCache: [(content: String, file: Path, force: Bool)] = [] diff --git a/Tests/VariantsCoreTests/YamlParserTests.swift b/Tests/VariantsCoreTests/YamlParserTests.swift index 09626e74..c97afc08 100644 --- a/Tests/VariantsCoreTests/YamlParserTests.swift +++ b/Tests/VariantsCoreTests/YamlParserTests.swift @@ -74,7 +74,8 @@ class YamlParserTests: XCTestCase { } } } - // swiftlint:disable function_body_length + + // swiftlint:disable:next function_body_length func testExtractConfiguration_valid_iOS() { let parser = YamlParser() do { @@ -167,7 +168,7 @@ class YamlParserTests: XCTestCase { XCTAssertTrue(((error as? DecodingError) == nil)) } } - // swiftlint:enable function_body_length + func testExtractConfiguration_valid_android() { let parser = YamlParser() do { diff --git a/Tests/VariantsCoreTests/iOSProjectTests.swift b/Tests/VariantsCoreTests/iOSProjectTests.swift index 652ec51b..b01f5abd 100644 --- a/Tests/VariantsCoreTests/iOSProjectTests.swift +++ b/Tests/VariantsCoreTests/iOSProjectTests.swift @@ -5,11 +5,12 @@ // Created by Arthur Alves // +// swiftlint:disable type_name + import XCTest import PathKit import ArgumentParser @testable import VariantsCore -// swiftlint:disable type_name class iOSProjectTests: XCTestCase { let specHelperMock = SpecHelperMock( diff --git a/Tests/VariantsCoreTests/iOSSigningTests.swift b/Tests/VariantsCoreTests/iOSSigningTests.swift index 0812aa15..df7e4da1 100644 --- a/Tests/VariantsCoreTests/iOSSigningTests.swift +++ b/Tests/VariantsCoreTests/iOSSigningTests.swift @@ -5,11 +5,11 @@ // Created by Roman Huti // +// swiftlint:disable type_name + import XCTest @testable import VariantsCore -// swiftlint:disable type_name - final class iOSSigningTests: XCTestCase { func testMergeValidSignings() throws { diff --git a/Tests/VariantsTests/InitCommandTests.swift b/Tests/VariantsTests/InitCommandTests.swift index b50a1b60..edf59361 100644 --- a/Tests/VariantsTests/InitCommandTests.swift +++ b/Tests/VariantsTests/InitCommandTests.swift @@ -5,11 +5,11 @@ // Created by Arthur Alves // +// swiftlint:disable line_length + import XCTest import class Foundation.Bundle -// swiftlint:disable line_length - final class InitCommandTests: XCTestCase { func testUsage_help() throws { let arguments = ["init", "--help"] @@ -33,8 +33,9 @@ final class InitCommandTests: XCTestCase { let output = try CLIExecutor.shared.run(with: arguments) XCTAssertEqual(output, expectedOutput) } - - #warning("Test 'testUsage_noExtraArguments' will always fail when running from Xcode.") + + /// Note: + /// Test testUsage_noExtraArguments' will always fail when running from Xcode. func testUsage_noExtraArguments() throws { let arguments = ["init"] diff --git a/Variants.xcodeproj/project.pbxproj b/Variants.xcodeproj/project.pbxproj index d83e7a8b..18a9c27e 100644 --- a/Variants.xcodeproj/project.pbxproj +++ b/Variants.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 52; + objectVersion = 54; objects = { /* Begin PBXAggregateTarget section */ @@ -601,6 +601,7 @@ buildPhases = ( 8E1B9CC9254AC1E700DD0204 /* Headers */, 8E1B9CCA254AC1E700DD0204 /* Sources */, + 2D70A7582D0854F000DF5272 /* ShellScript */, 8E1B9CCB254AC1E700DD0204 /* Frameworks */, 8E1B9CCC254AC1E700DD0204 /* Resources */, ); @@ -643,6 +644,7 @@ buildConfigurationList = OBJ_379 /* Build configuration list for PBXNativeTarget "Variants" */; buildPhases = ( OBJ_382 /* Sources */, + 2D70A7562D08548E00DF5272 /* ShellScript */, OBJ_421 /* Frameworks */, 8E1BA14E254C43A900DD0204 /* Embed Frameworks */, ); @@ -710,6 +712,7 @@ 8E1BA105254C3FD000DD0204 /* XCRemoteSwiftPackageReference "xcodeproj" */, 8E1BA10E254C3FFF00DD0204 /* XCRemoteSwiftPackageReference "swift-argument-parser" */, 8E8A483325514BE00056F79F /* XCRemoteSwiftPackageReference "Stencil" */, + 2D70A7512D08525300DF5272 /* XCRemoteSwiftPackageReference "SwiftLintPlugins" */, ); productRefGroup = OBJ_274 /* Products */; projectDirPath = ""; @@ -750,6 +753,45 @@ }; /* End PBXResourcesBuildPhase section */ +/* Begin PBXShellScriptBuildPhase section */ + 2D70A7562D08548E00DF5272 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "SWIFT_PACKAGE_DIR=\"${BUILD_DIR%Build/*}SourcePackages/artifacts\"\nSWIFTLINT_CMD=$(ls \"$SWIFT_PACKAGE_DIR\"/swiftlintplugins/SwiftLintBinary/SwiftLintBinary.artifactbundle/swiftlint-*/bin/swiftlint | head -n 1)\n\nif test -f \"$SWIFTLINT_CMD\" 2>&1\nthen\n \"$SWIFTLINT_CMD\"\nelse\n echo \"warning: `swiftlint` command not found - See https://github.com/realm/SwiftLint#installation for installation instructions.\"\nfi\n"; + }; + 2D70A7582D0854F000DF5272 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + alwaysOutOfDate = 1; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "SWIFT_PACKAGE_DIR=\"${BUILD_DIR%Build/*}SourcePackages/artifacts\"\nSWIFTLINT_CMD=$(ls \"$SWIFT_PACKAGE_DIR\"/swiftlintplugins/SwiftLintBinary/SwiftLintBinary.artifactbundle/swiftlint-*/bin/swiftlint | head -n 1)\n\nif test -f \"$SWIFTLINT_CMD\" 2>&1\nthen\n \"$SWIFTLINT_CMD\"\nelse\n echo \"warning: `swiftlint` command not found - See https://github.com/realm/SwiftLint#installation for installation instructions.\"\nfi\n"; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 8E1B9CCA254AC1E700DD0204 /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -1481,6 +1523,14 @@ /* End XCConfigurationList section */ /* Begin XCRemoteSwiftPackageReference section */ + 2D70A7512D08525300DF5272 /* XCRemoteSwiftPackageReference "SwiftLintPlugins" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/SimplyDanny/SwiftLintPlugins"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 0.57.1; + }; + }; 8E1BA0F3254C3F3E00DD0204 /* XCRemoteSwiftPackageReference "PathKit" */ = { isa = XCRemoteSwiftPackageReference; repositoryURL = "https://github.com/kylef/PathKit.git"; diff --git a/samples/ios/VariantsTestApp/VariantsTestApp/ViewController.swift b/samples/ios/VariantsTestApp/VariantsTestApp/ViewController.swift index e836985f..4ba95de4 100644 --- a/samples/ios/VariantsTestApp/VariantsTestApp/ViewController.swift +++ b/samples/ios/VariantsTestApp/VariantsTestApp/ViewController.swift @@ -7,9 +7,4 @@ import UIKit -class ViewController: UIViewController { - override func viewDidLoad() { - super.viewDidLoad() - // Do any additional setup after loading the view. - } -} +class ViewController: UIViewController { } From 2e87d695d291bb64a5ec6fe3081684052e627fb2 Mon Sep 17 00:00:00 2001 From: Gabriel Minucci Date: Tue, 10 Dec 2024 13:08:13 +0100 Subject: [PATCH 08/14] chore: update Readme --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 524b8481..f1978d18 100644 --- a/README.md +++ b/README.md @@ -43,6 +43,12 @@ This file is responsible for: ## Installation +### Dependencies + +In order to generate the code from templates, Variants requires Python 2.7. We recommend configuring the python version using a version management tool such as Pyenv. + +For details on how to install and use it check the [Pyenv repo](https://github.com/pyenv/pyenv). + ### On Github Actions CI See [Switching Variants on CI](docs/GITHUB_ACTION.md) for a better understanding and examples. From bdb786fa5ca9385ccf7efefb48e18f4b297d280b Mon Sep 17 00:00:00 2001 From: Gabriel Minucci Date: Tue, 10 Dec 2024 13:16:27 +0100 Subject: [PATCH 09/14] chore: update danger gh action --- .github/workflows/danger-swift.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/danger-swift.yml b/.github/workflows/danger-swift.yml index 748b49c3..55474629 100644 --- a/.github/workflows/danger-swift.yml +++ b/.github/workflows/danger-swift.yml @@ -5,12 +5,15 @@ on: types: [ opened, synchronize, edited ] jobs: - danger-scan: + build: runs-on: ubuntu-latest + name: "Run Danger" steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v3 - name: Danger - uses: danger/swift@3.6.1 + uses: danger/swift@3.15.0 + with: + args: --failOnErrors --no-publish-check env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} + DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} \ No newline at end of file From aed2fb26da57a1067ee792b507f67179a39db2b3 Mon Sep 17 00:00:00 2001 From: Gabriel Minucci Date: Tue, 10 Dec 2024 13:17:56 +0100 Subject: [PATCH 10/14] chore: rename danger build job --- .github/workflows/danger-swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/danger-swift.yml b/.github/workflows/danger-swift.yml index 55474629..4ac81c86 100644 --- a/.github/workflows/danger-swift.yml +++ b/.github/workflows/danger-swift.yml @@ -5,7 +5,7 @@ on: types: [ opened, synchronize, edited ] jobs: - build: + danger-scan: runs-on: ubuntu-latest name: "Run Danger" steps: From b0b5c897e967db5bbef86c6501190e8daf0a4078 Mon Sep 17 00:00:00 2001 From: Gabriel Minucci Date: Tue, 10 Dec 2024 13:26:11 +0100 Subject: [PATCH 11/14] chore: update danger gh action --- .github/workflows/danger-swift.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/danger-swift.yml b/.github/workflows/danger-swift.yml index 4ac81c86..cde5acd8 100644 --- a/.github/workflows/danger-swift.yml +++ b/.github/workflows/danger-swift.yml @@ -7,11 +7,10 @@ on: jobs: danger-scan: runs-on: ubuntu-latest - name: "Run Danger" steps: - uses: actions/checkout@v3 - name: Danger - uses: danger/swift@3.15.0 + uses: danger/swift@3.20.2 with: args: --failOnErrors --no-publish-check env: From 27e446e08dc13a876053c216f8369086fd47642a Mon Sep 17 00:00:00 2001 From: Gabriel Minucci Date: Tue, 10 Dec 2024 15:01:37 +0100 Subject: [PATCH 12/14] chore: remove Danger api token --- .github/workflows/danger-swift.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/danger-swift.yml b/.github/workflows/danger-swift.yml index cde5acd8..25af997e 100644 --- a/.github/workflows/danger-swift.yml +++ b/.github/workflows/danger-swift.yml @@ -14,5 +14,4 @@ jobs: with: args: --failOnErrors --no-publish-check env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - DANGER_GITHUB_API_TOKEN: ${{ secrets.DANGER_GITHUB_API_TOKEN }} \ No newline at end of file + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 590ef1f6d5d2d0dba993fdc7281df5711309fc6b Mon Sep 17 00:00:00 2001 From: Gabriel Minucci Date: Tue, 10 Dec 2024 16:53:39 +0100 Subject: [PATCH 13/14] chore: temporarily disables danger --- .github/workflows/danger-swift.yml | 38 ++++++++++++++++++------------ 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/.github/workflows/danger-swift.yml b/.github/workflows/danger-swift.yml index 25af997e..e3551bac 100644 --- a/.github/workflows/danger-swift.yml +++ b/.github/workflows/danger-swift.yml @@ -1,17 +1,25 @@ -name: "Danger Swift" +# We are disabling Danger temporarily until we get a fix to the error +# +# ERROR: Failed to parse JSON: valueNotFound(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "danger", intValue: nil), CodingKeys(stringValue: "github", intValue: nil), CodingKeys(stringValue: "reviews", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "user", intValue: nil)], debugDescription: "Cannot get keyed decoding container -- found null value instead", underlyingError: nil)) +# ERROR: Dangerfile eval failed at Dangerfile.swift +# +# In short, if a user that is deleted left a comment in a PR, the author becomes null +# which breaks the JSON parsing -on: - pull_request: - types: [ opened, synchronize, edited ] +# name: "Danger Swift" -jobs: - danger-scan: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Danger - uses: danger/swift@3.20.2 - with: - args: --failOnErrors --no-publish-check - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file +# on: +# pull_request: +# types: [ opened, synchronize, edited ] + +# jobs: +# danger-scan: +# runs-on: ubuntu-latest +# steps: +# - uses: actions/checkout@v3 +# - name: Danger +# uses: danger/swift@3.20.2 +# with: +# args: --failOnErrors --no-publish-check +# env: +# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 1f939e8d124cc632c3ae6401682c3a1bd5dcbf24 Mon Sep 17 00:00:00 2001 From: Gabriel Minucci Date: Tue, 10 Dec 2024 16:56:03 +0100 Subject: [PATCH 14/14] fix: re-enable danger --- .github/workflows/danger-swift.yml | 38 ++++++++++++------------------ 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/.github/workflows/danger-swift.yml b/.github/workflows/danger-swift.yml index e3551bac..25af997e 100644 --- a/.github/workflows/danger-swift.yml +++ b/.github/workflows/danger-swift.yml @@ -1,25 +1,17 @@ -# We are disabling Danger temporarily until we get a fix to the error -# -# ERROR: Failed to parse JSON: valueNotFound(Swift.Dictionary, Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "danger", intValue: nil), CodingKeys(stringValue: "github", intValue: nil), CodingKeys(stringValue: "reviews", intValue: nil), _JSONKey(stringValue: "Index 0", intValue: 0), CodingKeys(stringValue: "user", intValue: nil)], debugDescription: "Cannot get keyed decoding container -- found null value instead", underlyingError: nil)) -# ERROR: Dangerfile eval failed at Dangerfile.swift -# -# In short, if a user that is deleted left a comment in a PR, the author becomes null -# which breaks the JSON parsing +name: "Danger Swift" -# name: "Danger Swift" +on: + pull_request: + types: [ opened, synchronize, edited ] -# on: -# pull_request: -# types: [ opened, synchronize, edited ] - -# jobs: -# danger-scan: -# runs-on: ubuntu-latest -# steps: -# - uses: actions/checkout@v3 -# - name: Danger -# uses: danger/swift@3.20.2 -# with: -# args: --failOnErrors --no-publish-check -# env: -# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file +jobs: + danger-scan: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Danger + uses: danger/swift@3.20.2 + with: + args: --failOnErrors --no-publish-check + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file