From a4ef329d959c73e6a9ba3e9448a8c416339d1416 Mon Sep 17 00:00:00 2001 From: Emil Karimov Date: Wed, 4 Feb 2026 23:25:05 +0300 Subject: [PATCH] Add extended HTTP methods and release tagging --- .github/workflows/swift.yml | 47 +++++++++++++++++++ API.md | 4 ++ API_RU.md | 4 ++ CHANGELOG.md | 6 ++- README.md | 2 +- README_RU.md | 3 +- Sources/EKNetwork/NetworkManager.swift | 4 ++ .../AdditionalCoverageTests.swift | 5 +- .../ExtendedCoverageTests.swift | 7 ++- Tests/EKNetworkTests/ExtendedTestSuite.swift | 20 ++++++++ .../EKNetworkTests/NetworkManagerTests.swift | 4 ++ 11 files changed, 99 insertions(+), 7 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 407ab26..e2577e1 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -191,3 +191,50 @@ jobs: echo "- Total lines: ${{ steps.calc.outputs.total }}" >> $GITHUB_STEP_SUMMARY echo "- Covered lines: ${{ steps.calc.outputs.covered }}" >> $GITHUB_STEP_SUMMARY echo "- Coverage: ${{ steps.calc.outputs.coverage }}%" >> $GITHUB_STEP_SUMMARY + + release: + name: Tag and Release + runs-on: ubuntu-latest + needs: test + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + permissions: + contents: write + + steps: + - name: Checkout code + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Read version + id: version + run: | + VERSION=$(sed -n 's/.*EKNetworkVersionString = "\(.*\)".*/\1/p' Sources/EKNetwork/Version.swift) + if [ -z "$VERSION" ]; then + echo "❌ Failed to read version from Version.swift" + exit 1 + fi + echo "version=$VERSION" >> "$GITHUB_OUTPUT" + echo "tag=v$VERSION" >> "$GITHUB_OUTPUT" + + - name: Create tag + id: tag + run: | + TAG="${{ steps.version.outputs.tag }}" + if git rev-parse "$TAG" >/dev/null 2>&1; then + echo "exists=true" >> "$GITHUB_OUTPUT" + echo "Tag $TAG already exists, skipping tag creation." + exit 0 + fi + git config user.name "github-actions[bot]" + git config user.email "github-actions[bot]@users.noreply.github.com" + git tag -a "$TAG" -m "Release $TAG" + git push origin "$TAG" + echo "exists=false" >> "$GITHUB_OUTPUT" + + - name: Create GitHub release + if: steps.tag.outputs.exists == 'false' + uses: softprops/action-gh-release@v2 + with: + tag_name: ${{ steps.version.outputs.tag }} + generate_release_notes: true diff --git a/API.md b/API.md index 5edf228..ac5fee3 100644 --- a/API.md +++ b/API.md @@ -207,6 +207,10 @@ public enum HTTPMethod: String { case put = "PUT" case delete = "DELETE" case patch = "PATCH" + case head = "HEAD" + case options = "OPTIONS" + case trace = "TRACE" + case connect = "CONNECT" } ``` diff --git a/API_RU.md b/API_RU.md index 27c2a3a..1cb74ca 100644 --- a/API_RU.md +++ b/API_RU.md @@ -204,6 +204,10 @@ public enum HTTPMethod: String { case put = "PUT" case delete = "DELETE" case patch = "PATCH" + case head = "HEAD" + case options = "OPTIONS" + case trace = "TRACE" + case connect = "CONNECT" } ``` diff --git a/CHANGELOG.md b/CHANGELOG.md index a68fd55..688a73b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -_Nothing yet._ +### Added +- Expanded supported HTTP methods to include `HEAD`, `OPTIONS`, `TRACE`, and `CONNECT` alongside the existing verbs. + +### Changed +- CI now tags and creates a GitHub release automatically after successful tests on `main`. ## [1.4.2] - 2026-02-03 diff --git a/README.md b/README.md index 80bdeed..293b68e 100644 --- a/README.md +++ b/README.md @@ -675,7 +675,7 @@ func testSignIn() async throws { EKNetwork has comprehensive test coverage (115 tests, 99.42% code coverage) and provides protocols for easy testing: -- ✅ All HTTP methods (GET, POST, PUT, DELETE, PATCH) +- ✅ All HTTP methods (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, TRACE, CONNECT) - ✅ Query parameters - ✅ Various body types (JSON, Form URL Encoded, Multipart, Raw Data) - ✅ Retry policy diff --git a/README_RU.md b/README_RU.md index 739e69d..f8226fa 100644 --- a/README_RU.md +++ b/README_RU.md @@ -638,7 +638,7 @@ func testSignIn() async throws { EKNetwork имеет полное тестовое покрытие (21 тест) и предоставляет протоколы для легкого тестирования: -- ✅ Все HTTP методы (GET, POST, PUT, DELETE, PATCH) +- ✅ Все HTTP методы (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS, TRACE, CONNECT) - ✅ Query параметры - ✅ Различные типы body (JSON, Form URL Encoded, Multipart, Raw Data) - ✅ Retry policy @@ -755,4 +755,3 @@ EKNetwork доступен под лицензией MIT. См. [LICENSE](LICENS [⭐ Поставьте звезду, если проект полезен для вас!](#) - diff --git a/Sources/EKNetwork/NetworkManager.swift b/Sources/EKNetwork/NetworkManager.swift index b6fa119..e3ca73f 100644 --- a/Sources/EKNetwork/NetworkManager.swift +++ b/Sources/EKNetwork/NetworkManager.swift @@ -118,6 +118,10 @@ public enum HTTPMethod: String { case put = "PUT" case delete = "DELETE" case patch = "PATCH" + case head = "HEAD" + case options = "OPTIONS" + case trace = "TRACE" + case connect = "CONNECT" } diff --git a/Tests/EKNetworkTests/AdditionalCoverageTests.swift b/Tests/EKNetworkTests/AdditionalCoverageTests.swift index a16d1e7..e6ddc7b 100644 --- a/Tests/EKNetworkTests/AdditionalCoverageTests.swift +++ b/Tests/EKNetworkTests/AdditionalCoverageTests.swift @@ -306,6 +306,10 @@ func testHTTPMethodRawValues() async throws { #expect(HTTPMethod.put.rawValue == "PUT") #expect(HTTPMethod.delete.rawValue == "DELETE") #expect(HTTPMethod.patch.rawValue == "PATCH") + #expect(HTTPMethod.head.rawValue == "HEAD") + #expect(HTTPMethod.options.rawValue == "OPTIONS") + #expect(HTTPMethod.trace.rawValue == "TRACE") + #expect(HTTPMethod.connect.rawValue == "CONNECT") } // MARK: - Edge Cases Tests @@ -986,4 +990,3 @@ func testRetryPolicyShouldRetryClosure() async throws { #expect(retryBox.get() == true) RetryProtocol.attempt?.deallocate() } - diff --git a/Tests/EKNetworkTests/ExtendedCoverageTests.swift b/Tests/EKNetworkTests/ExtendedCoverageTests.swift index b120030..1899c0c 100644 --- a/Tests/EKNetworkTests/ExtendedCoverageTests.swift +++ b/Tests/EKNetworkTests/ExtendedCoverageTests.swift @@ -225,7 +225,11 @@ func testHTTPMethodRawValuesValidation() async throws { (.post, "POST"), (.put, "PUT"), (.delete, "DELETE"), - (.patch, "PATCH") + (.patch, "PATCH"), + (.head, "HEAD"), + (.options, "OPTIONS"), + (.trace, "TRACE"), + (.connect, "CONNECT") ] for (method, expected) in methods { @@ -330,4 +334,3 @@ func testRequestWithAllOptionalParameters() async throws { let response = try await manager.send(FullRequest(), accessToken: nil) #expect(response.value == "full") } - diff --git a/Tests/EKNetworkTests/ExtendedTestSuite.swift b/Tests/EKNetworkTests/ExtendedTestSuite.swift index 7a55332..76c8cc2 100644 --- a/Tests/EKNetworkTests/ExtendedTestSuite.swift +++ b/Tests/EKNetworkTests/ExtendedTestSuite.swift @@ -44,6 +44,26 @@ func testHTTPMethodPatch() { #expect(HTTPMethod.patch.rawValue == "PATCH") } +@Test("HTTPMethod head raw value") +func testHTTPMethodHead() { + #expect(HTTPMethod.head.rawValue == "HEAD") +} + +@Test("HTTPMethod options raw value") +func testHTTPMethodOptions() { + #expect(HTTPMethod.options.rawValue == "OPTIONS") +} + +@Test("HTTPMethod trace raw value") +func testHTTPMethodTrace() { + #expect(HTTPMethod.trace.rawValue == "TRACE") +} + +@Test("HTTPMethod connect raw value") +func testHTTPMethodConnect() { + #expect(HTTPMethod.connect.rawValue == "CONNECT") +} + // MARK: - NetworkError @Test("NetworkError invalidURL case") diff --git a/Tests/EKNetworkTests/NetworkManagerTests.swift b/Tests/EKNetworkTests/NetworkManagerTests.swift index 02c50ca..1e0df5c 100644 --- a/Tests/EKNetworkTests/NetworkManagerTests.swift +++ b/Tests/EKNetworkTests/NetworkManagerTests.swift @@ -891,6 +891,10 @@ func testHTTPMethods() async throws { try await testMethod(.put, expectedMethod: "PUT") try await testMethod(.delete, expectedMethod: "DELETE") try await testMethod(.patch, expectedMethod: "PATCH") + try await testMethod(.head, expectedMethod: "HEAD") + try await testMethod(.options, expectedMethod: "OPTIONS") + try await testMethod(.trace, expectedMethod: "TRACE") + try await testMethod(.connect, expectedMethod: "CONNECT") } @MainActor