From 5c402b32e1eb67f388c64da89c182f528e4ce1a7 Mon Sep 17 00:00:00 2001 From: Richard Piazza Date: Sat, 21 Mar 2026 13:47:02 -0500 Subject: [PATCH 1/4] Updated PR workflow --- .github/workflows/pull_request.yml | 80 ++++++++++++++++++++++++++++++ .github/workflows/swift.yml | 33 ------------ 2 files changed, 80 insertions(+), 33 deletions(-) create mode 100644 .github/workflows/pull_request.yml delete mode 100644 .github/workflows/swift.yml diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml new file mode 100644 index 0000000..a8ddc17 --- /dev/null +++ b/.github/workflows/pull_request.yml @@ -0,0 +1,80 @@ +SCHEME: "TranslationCatalog" + +jobs: + Lint: + runs-on: macos-26 + steps: + - name: Checkout + uses: actions/checkout@v6 + - name: Lint + run: swiftformat --lint . --reporter github-actions-log + + Swift: + strategy: + fail-fast: false + matrix: + os: [ + macos-26, + ubuntu-latest, + ] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout + uses: actions/checkout@v6 + - name: Cache + uses: actions/cache@v5 + with: + path: | + .build + ~/Library/Developer/Xcode/DerivedData/ModuleCache.noindex + ~/Library/Caches/org.swift.swiftpm + ~/Library/org.swift.swiftpm + key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.swift', '**/Package.resolved') }} + restore-keys: | + ${{ runner.os }}-spm- + - name: Package Resolution + run: swift package resolve + - name: Build + run: swift build + - name: Test + run: swift test + + Xcode: + strategy: + fail-fast: false + matrix: + platform: [ + "macOS", + "iOS", + "tvOS", + "watchOS", + "visionOS", + "macOS,variant=Mac Catalyst", + ] + runs-on: macos-26 + steps: + - name: Checkout + uses: actions/checkout@v6 + - name: Cache + uses: actions/cache@v5 + with: + path: | + .build + ~/Library/Developer/Xcode/DerivedData/ModuleCache.noindex + ~/Library/Caches/org.swift.swiftpm + ~/Library/org.swift.swiftpm + key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.swift', '**/Package.resolved') }} + restore-keys: | + ${{ runner.os }}-spm- + - name: Package Resolution + run: set -o pipefail && xcodebuild -resolvePackageDependencies | xcbeautify + - name: Build + env: + DESTINATION: "generic/platform=${{ matrix.platform }}" + shell: + run: | + xcodebuild \ + -scheme "$SCHEME" \ + -destination "$DESTINATION" \ + build \ + | xcbeautify diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml deleted file mode 100644 index de257f1..0000000 --- a/.github/workflows/swift.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: Swift - -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - workflow_dispatch: - -jobs: - SwiftActions: - strategy: - fail-fast: false - matrix: - os: [macos-15, ubuntu-latest] - - runs-on: ${{ matrix.os }} - - steps: - - name: Checkout Source - uses: actions/checkout@v4 - - - name: Setup Toolchain - if: ${{ runner.os == 'Linux' }} - shell: bash - run: sudo apt-get install sqlite3 libsqlite3-dev - - - name: Swift Build - uses: SwiftActions/SwiftBuild@main - - - name: Swift Test - uses: SwiftActions/SwiftTest@main - \ No newline at end of file From 436cb54d9dee851cb5c13be0eeabdd821b462b49 Mon Sep 17 00:00:00 2001 From: Richard Piazza Date: Sat, 21 Mar 2026 13:47:19 -0500 Subject: [PATCH 2/4] Apply SwiftFormat --- .swiftformat | 2 ++ .../TranslationCatalogIO/Internal/Resource.swift | 2 +- .../TranslationCatalogIO/Internal/StringsXml.swift | 4 ++-- .../Extensions/FileManager+localizer.swift | 3 +-- .../ExpressionEncoderTests.swift | 8 ++++---- .../FilesystemEncodingTests.swift | 10 +++++----- .../KeyHierarchy2Tests.swift | 12 ++++++------ .../KeyHierarchyTests.swift | 14 +++++++------- Tests/TranslationCatalogTests/NodeSortTests.swift | 2 +- 9 files changed, 29 insertions(+), 28 deletions(-) diff --git a/.swiftformat b/.swiftformat index 66a20d4..17d120d 100644 --- a/.swiftformat +++ b/.swiftformat @@ -11,5 +11,7 @@ --disable blankLinesAtStartOfScope --disable hoistPatternLet --disable redundantType +--disable swiftTestingTestCaseNames --disable unusedArguments --disable wrapArguments +--disable wrapPropertyBodies diff --git a/Sources/TranslationCatalogIO/Internal/Resource.swift b/Sources/TranslationCatalogIO/Internal/Resource.swift index 0be5baa..544aa12 100644 --- a/Sources/TranslationCatalogIO/Internal/Resource.swift +++ b/Sources/TranslationCatalogIO/Internal/Resource.swift @@ -21,7 +21,7 @@ struct Resource: Codable, DynamicNodeDecoding, DynamicNodeEncoding { .element } } - + static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { switch key { case CodingKeys.name, CodingKeys.formatted: diff --git a/Sources/TranslationCatalogIO/Internal/StringsXml.swift b/Sources/TranslationCatalogIO/Internal/StringsXml.swift index 779f050..851a37e 100644 --- a/Sources/TranslationCatalogIO/Internal/StringsXml.swift +++ b/Sources/TranslationCatalogIO/Internal/StringsXml.swift @@ -12,7 +12,7 @@ struct StringsXml: Codable, DynamicNodeDecoding, DynamicNodeEncoding { static func nodeDecoding(for key: CodingKey) -> XMLDecoder.NodeDecoding { .element } - + static func nodeEncoding(for key: any CodingKey) -> XMLEncoder.NodeEncoding { .element } @@ -25,7 +25,7 @@ struct StringsXml: Codable, DynamicNodeDecoding, DynamicNodeEncoding { static func make(with data: Data) throws -> StringsXml { try XMLDecoder().decode(StringsXml.self, from: data) } - + func encoded() throws -> Data { let encoder = XMLEncoder() encoder.outputFormatting = [.sortedKeys] diff --git a/Sources/localizer/Extensions/FileManager+localizer.swift b/Sources/localizer/Extensions/FileManager+localizer.swift index b164776..e85522a 100644 --- a/Sources/localizer/Extensions/FileManager+localizer.swift +++ b/Sources/localizer/Extensions/FileManager+localizer.swift @@ -11,8 +11,7 @@ extension FileManager { // Relative Path? let directory = URL(fileURLWithPath: currentDirectoryPath, isDirectory: true) - let relativeURL = directory.appendingPathComponent(filename) - return relativeURL + return directory.appendingPathComponent(filename) } @available(*, deprecated) diff --git a/Tests/TranslationCatalogTests/ExpressionEncoderTests.swift b/Tests/TranslationCatalogTests/ExpressionEncoderTests.swift index b399369..6c50c72 100644 --- a/Tests/TranslationCatalogTests/ExpressionEncoderTests.swift +++ b/Tests/TranslationCatalogTests/ExpressionEncoderTests.swift @@ -3,7 +3,7 @@ import TranslationCatalog import XCTest final class ExpressionEncoderTests: XCTestCase { - + private let locale: Locale = Locale(identifier: "en_US") private let expressions: [TranslationCatalog.Expression] = [ Expression( @@ -25,7 +25,7 @@ final class ExpressionEncoderTests: XCTestCase { languageCode: .english ), ] - + func testAndroidXMLEncoding() throws { let data = try ExpressionEncoder.encodeValues( for: expressions, @@ -43,7 +43,7 @@ final class ExpressionEncoderTests: XCTestCase { """) } - + func testAppleStringsEncoding() throws { let data = try ExpressionEncoder.encodeValues( for: expressions, @@ -58,7 +58,7 @@ final class ExpressionEncoderTests: XCTestCase { "EXP_03" = "Hello %@, welcome to %@!"; """) } - + func testJSONEncoding() throws { let data = try ExpressionEncoder.encodeValues( for: expressions, diff --git a/Tests/TranslationCatalogTests/FilesystemEncodingTests.swift b/Tests/TranslationCatalogTests/FilesystemEncodingTests.swift index d0270df..06a02ef 100644 --- a/Tests/TranslationCatalogTests/FilesystemEncodingTests.swift +++ b/Tests/TranslationCatalogTests/FilesystemEncodingTests.swift @@ -5,13 +5,13 @@ import XCTest class FilesystemEncodingTests: XCTestCase { func testProjectDocumentEncoding() throws { - let document = ProjectDocument( - id: UUID(uuidString: "24D67823-F859-40A1-88C2-A56F1170905B")!, + let document = try ProjectDocument( + id: XCTUnwrap(UUID(uuidString: "24D67823-F859-40A1-88C2-A56F1170905B")), name: "Example", expressionIds: [ - UUID(uuidString: "7F9D2FF1-31C1-47A1-94EE-E23BB0A7AD2B")!, - UUID(uuidString: "592E488D-4E3C-490B-8725-C45FF7DEC872")!, - UUID(uuidString: "FB7C761C-9026-49C2-BBC7-9B7B897CAA6D")!, + XCTUnwrap(UUID(uuidString: "7F9D2FF1-31C1-47A1-94EE-E23BB0A7AD2B")), + XCTUnwrap(UUID(uuidString: "592E488D-4E3C-490B-8725-C45FF7DEC872")), + XCTUnwrap(UUID(uuidString: "FB7C761C-9026-49C2-BBC7-9B7B897CAA6D")), ] ) diff --git a/Tests/TranslationCatalogTests/KeyHierarchy2Tests.swift b/Tests/TranslationCatalogTests/KeyHierarchy2Tests.swift index a3e5dd0..4de1e80 100644 --- a/Tests/TranslationCatalogTests/KeyHierarchy2Tests.swift +++ b/Tests/TranslationCatalogTests/KeyHierarchy2Tests.swift @@ -51,7 +51,7 @@ final class KeyHierarchy2Tests: XCTestCase { hierarchy = try KeyHierarchy.make(with: keys) } - func testHierarchyGeneration() throws { + func testHierarchyGeneration() { XCTAssertTrue(hierarchy.contents.isEmpty) XCTAssertEqual(hierarchy.nodes.count, 1) XCTAssertEqual(hierarchy.nodes.map(\.id), [ @@ -63,7 +63,7 @@ final class KeyHierarchy2Tests: XCTestCase { XCTAssertTrue(hierarchy.containsPhantoms) } - func testNodeAtPath() throws { + func testNodeAtPath() { var node = hierarchy.node(at: [["UNKNOWN"]]) XCTAssertNil(node) node = hierarchy.node(at: [["PAYMENT"], ["METHOD"], ["EXPIRATION"]]) @@ -72,12 +72,12 @@ final class KeyHierarchy2Tests: XCTestCase { XCTAssertNotNil(node) } - func testRemoveNodeAtPath() throws { + func testRemoveNodeAtPath() { let node = hierarchy.removeNode(at: [["PAYMENT"], ["METHOD"], ["CONFIRM"]]) XCTAssertNotNil(node) } - func testOrphanNodes() throws { + func testOrphanNodes() { let nodes = hierarchy.orphanNodes() XCTAssertEqual(nodes.count, 8) XCTAssertEqual(nodes, [ @@ -92,7 +92,7 @@ final class KeyHierarchy2Tests: XCTestCase { ]) } - func testPhantomNodes() throws { + func testPhantomNodes() { let nodes = hierarchy.phantomNodes() XCTAssertEqual(nodes.count, 2) XCTAssertEqual(nodes, [ @@ -101,7 +101,7 @@ final class KeyHierarchy2Tests: XCTestCase { ]) } - func testLocalizedStringConvertible() throws { + func testLocalizedStringConvertible() { let syntax = hierarchy.syntaxTree() XCTAssertEqual(syntax, """ import LocaleSupport diff --git a/Tests/TranslationCatalogTests/KeyHierarchyTests.swift b/Tests/TranslationCatalogTests/KeyHierarchyTests.swift index e125196..4321030 100644 --- a/Tests/TranslationCatalogTests/KeyHierarchyTests.swift +++ b/Tests/TranslationCatalogTests/KeyHierarchyTests.swift @@ -47,7 +47,7 @@ final class KeyHierarchyTests: XCTestCase { hierarchy = try KeyHierarchy.make(with: keys) } - func testHierarchyGeneration() throws { + func testHierarchyGeneration() { XCTAssertEqual(hierarchy.contents.count, 1) XCTAssertEqual(Array(hierarchy.contents.keys), [ ["GREETING"], @@ -65,7 +65,7 @@ final class KeyHierarchyTests: XCTestCase { XCTAssertTrue(hierarchy.containsPhantoms) } - func testNodeAtPath() throws { + func testNodeAtPath() { var node = hierarchy.node(at: [["UNKNOWN"]]) XCTAssertNil(node) node = hierarchy.node(at: [["HIDDEN"]]) @@ -74,12 +74,12 @@ final class KeyHierarchyTests: XCTestCase { XCTAssertNotNil(node) } - func testRemoveNodeAtPath() throws { + func testRemoveNodeAtPath() { let node = hierarchy.removeNode(at: [["PLATFORM"], ["APPLE"]]) XCTAssertNotNil(node) } - func testOrphanNodes() throws { + func testOrphanNodes() { let nodes = hierarchy.orphanNodes() XCTAssertEqual(nodes.count, 4) XCTAssertEqual(nodes, [ @@ -90,7 +90,7 @@ final class KeyHierarchyTests: XCTestCase { ]) } - func testPhantomNodes() throws { + func testPhantomNodes() { let nodes = hierarchy.phantomNodes() XCTAssertEqual(nodes.count, 1) XCTAssertEqual(nodes, [ @@ -98,7 +98,7 @@ final class KeyHierarchyTests: XCTestCase { ]) } - func testLocalizedStringConvertible() throws { + func testLocalizedStringConvertible() { let syntax = hierarchy.syntaxTree() XCTAssertEqual(syntax, """ import LocaleSupport @@ -214,7 +214,7 @@ final class KeyHierarchyTests: XCTestCase { key: "ZULU_ZONE", defaultValue: "zone" ) - var test = hierarchy! + var test = try XCTUnwrap(hierarchy) try test.processKey(key, path: [["ZULU"], ["ZONE"]]) let syntax = try test .compressed(mergePhantoms: false) diff --git a/Tests/TranslationCatalogTests/NodeSortTests.swift b/Tests/TranslationCatalogTests/NodeSortTests.swift index c2b1939..ca8d849 100644 --- a/Tests/TranslationCatalogTests/NodeSortTests.swift +++ b/Tests/TranslationCatalogTests/NodeSortTests.swift @@ -7,7 +7,7 @@ final class NodeSortTests: XCTestCase { let comparator = NodePathSortComparator() - func testSorting() throws { + func testSorting() { let nodes: [Node] = [ [["Account"], ["New"]], [["Account"], ["Add"]], From 483a756b5f7f37cceffb8333eab30e541da8b29a Mon Sep 17 00:00:00 2001 From: Richard Piazza Date: Sat, 21 Mar 2026 13:49:25 -0500 Subject: [PATCH 3/4] Fixed Workflow Syntax --- .github/workflows/pull_request.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index a8ddc17..79933ae 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -1,4 +1,12 @@ -SCHEME: "TranslationCatalog" +name: Pull Request + +on: + pull_request: + branches: [ main ] + workflow_dispatch: + +env: + SCHEME: "TranslationCatalog" jobs: Lint: From 03416dd5efb3ca9934f872f51fb8b3b85c4ae8c0 Mon Sep 17 00:00:00 2001 From: Richard Piazza Date: Sat, 21 Mar 2026 13:50:06 -0500 Subject: [PATCH 4/4] Missing shell reference --- .github/workflows/pull_request.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index 79933ae..459782b 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -79,7 +79,7 @@ jobs: - name: Build env: DESTINATION: "generic/platform=${{ matrix.platform }}" - shell: + shell: bash run: | xcodebuild \ -scheme "$SCHEME" \