diff --git a/.swiftlint.yml b/.swiftlint.yml index eef552d..5a6fa21 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -3,3 +3,13 @@ disabled_rules: - trailing_comma - opening_brace + +# Service types nest their request/response payload structs one level deeper. +nesting: + type_level: 2 + +# ForgejoClient intentionally aggregates every authentication flow in one type. +file_length: + warning: 600 +type_body_length: + warning: 300 diff --git a/README.md b/README.md index 6c3e339..bfd07d3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A native Swift library for the [Forgejo](https://forgejo.org) API. ForgejoKit pr ## Features -- Authentication via username/password (with optional OTP) or API tokens +- Authentication via username/password (with optional OTP), API tokens, or OAuth2 bearer tokens - Repositories: search, list, create, fork, star, file contents, commits, branches, tags, releases - Issues: create, edit, list, comment, manage labels and milestones - Pull requests: create, edit, merge, review, diff @@ -35,6 +35,9 @@ import ForgejoKit // Authenticate with a token let client = ForgejoClient(serverURL: "https://codeberg.org", username: "user", token: "your-token") +// Or authenticate with an OAuth2 access token (sent as `Authorization: Bearer`) +let client = ForgejoClient(serverURL: "https://codeberg.org", username: "user", bearerToken: "oauth2-access-token") + // Or log in with username/password to create an API token let result = try await ForgejoClient.login(serverURL: "https://codeberg.org", username: "user", password: "pass") let client = result.client diff --git a/Sources/ForgejoKit/Services/PullRequestService.swift b/Sources/ForgejoKit/Services/PullRequestService.swift index a7f7242..afb267d 100644 --- a/Sources/ForgejoKit/Services/PullRequestService.swift +++ b/Sources/ForgejoKit/Services/PullRequestService.swift @@ -37,7 +37,6 @@ public final class PullRequestService: Sendable { let mergeTitleField: String? let mergeMessageField: String? - // swiftlint:disable:next nesting enum CodingKeys: String, CodingKey { case method = "Do" case deleteBranchAfterMerge = "delete_branch_after_merge" @@ -58,7 +57,6 @@ public final class PullRequestService: Sendable { let oldPosition: Int? let newPosition: Int? - // swiftlint:disable:next nesting enum CodingKeys: String, CodingKey { case body case path @@ -156,7 +154,6 @@ public final class PullRequestService: Sendable { _ = try await client.performRequestNoContent(url: url, method: "DELETE", body: jsonData, validateStatus: true) } - // swiftlint:disable:next function_parameter_count public func mergePullRequest( owner: String, repo: String, index: Int, method: String, title: String? = nil, message: String? = nil, diff --git a/Sources/ForgejoKit/Services/RepositoryService.swift b/Sources/ForgejoKit/Services/RepositoryService.swift index 12e6818..efac25d 100644 --- a/Sources/ForgejoKit/Services/RepositoryService.swift +++ b/Sources/ForgejoKit/Services/RepositoryService.swift @@ -1,7 +1,5 @@ import Foundation -// swiftlint:disable file_length - private struct CreateRepositoryPayload: Codable { let name: String let description: String? diff --git a/Sources/ForgejoKit/Services/WorkflowService.swift b/Sources/ForgejoKit/Services/WorkflowService.swift index 515e5ed..cbd3003 100644 --- a/Sources/ForgejoKit/Services/WorkflowService.swift +++ b/Sources/ForgejoKit/Services/WorkflowService.swift @@ -116,7 +116,7 @@ public final class WorkflowService: Sendable { // for any run whose tasks are stored with the (1-based) attempt number. // The matching GET endpoint 307-redirects to the latest-attempt URL — // resolve that first, then POST to the resolved attempt-suffixed URL. - let postURL = (try? await client.discoverRedirectLocation(url: baseURL)) ?? baseURL + let postURL = await (try? client.discoverRedirectLocation(url: baseURL)) ?? baseURL let body = try client.encodeRequestBody(ViewRequestBody(logCursors: logCursors)) return try await client.performRequest( url: postURL, method: "POST", body: body, diff --git a/Tests/.swiftlint.yml b/Tests/.swiftlint.yml new file mode 100644 index 0000000..ac97014 --- /dev/null +++ b/Tests/.swiftlint.yml @@ -0,0 +1,18 @@ +# Test fixtures embed large, verbatim JSON payloads and exhaustive decoding +# cases, so length limits are relaxed here. Quality/safety rules stay enabled. +disabled_rules: + - trailing_comma + - opening_brace + +file_length: + warning: 1500 + error: 2000 +type_body_length: + warning: 1300 + error: 1500 +function_body_length: + warning: 60 + error: 100 +line_length: + warning: 600 + error: 700 diff --git a/Tests/ForgejoKitTests/AdminServiceTests.swift b/Tests/ForgejoKitTests/AdminServiceTests.swift index 35dd144..5620e62 100644 --- a/Tests/ForgejoKitTests/AdminServiceTests.swift +++ b/Tests/ForgejoKitTests/AdminServiceTests.swift @@ -1,9 +1,8 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct AdminServiceTests { - @Test func createUserPayloadEncodesCorrectKeys() throws { let json = """ { @@ -19,7 +18,7 @@ struct AdminServiceTests { } """ let data = Data(json.utf8) - let dict = try JSONSerialization.jsonObject(with: data) as! [String: Any] + let dict = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any]) #expect(dict["username"] as? String == "testbot") #expect(dict["login_name"] as? String == "testbot") #expect(dict["must_change_password"] as? Bool == false) diff --git a/Tests/ForgejoKitTests/BearerCredentialTests.swift b/Tests/ForgejoKitTests/BearerCredentialTests.swift index 722190b..a612a12 100644 --- a/Tests/ForgejoKitTests/BearerCredentialTests.swift +++ b/Tests/ForgejoKitTests/BearerCredentialTests.swift @@ -1,6 +1,6 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct BearerCredentialTests { @Test func bearerCredentialUsesBearerScheme() { diff --git a/Tests/ForgejoKitTests/DateDecodingTests.swift b/Tests/ForgejoKitTests/DateDecodingTests.swift index d067c30..8798900 100644 --- a/Tests/ForgejoKitTests/DateDecodingTests.swift +++ b/Tests/ForgejoKitTests/DateDecodingTests.swift @@ -1,13 +1,12 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct DateDecodingTests { - private func decoder() -> JSONDecoder { - let d = JSONDecoder() - d.dateDecodingStrategy = forgejoDateDecodingStrategy - return d + let jsonDecoder = JSONDecoder() + jsonDecoder.dateDecodingStrategy = forgejoDateDecodingStrategy + return jsonDecoder } private struct DateWrapper: Codable { @@ -74,9 +73,9 @@ struct DateDecodingTests { let jsonWithout = #"{"date":"2024-03-10T08:00:00Z"}"# let jsonWith = #"{"date":"2024-03-10T08:00:00.000Z"}"# - let d = decoder() - let resultWithout = try d.decode(DateWrapper.self, from: Data(jsonWithout.utf8)) - let resultWith = try d.decode(DateWrapper.self, from: Data(jsonWith.utf8)) + let jsonDecoder = decoder() + let resultWithout = try jsonDecoder.decode(DateWrapper.self, from: Data(jsonWithout.utf8)) + let resultWith = try jsonDecoder.decode(DateWrapper.self, from: Data(jsonWith.utf8)) #expect(resultWithout.date == resultWith.date) } diff --git a/Tests/ForgejoKitTests/DiffParserTests.swift b/Tests/ForgejoKitTests/DiffParserTests.swift index 1aad492..5e896e2 100644 --- a/Tests/ForgejoKitTests/DiffParserTests.swift +++ b/Tests/ForgejoKitTests/DiffParserTests.swift @@ -1,9 +1,8 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct DiffParserTests { - // MARK: - Empty and minimal input @Test func parseEmptyString() { @@ -305,13 +304,13 @@ struct DiffParserTests { #expect(result.files[0].newName == "hello.py") #expect(result.files[0].oldName == "/dev/null") - #expect(result.files[0].hunks[0].lines.filter { $0.type == .addition }.count == 2) + #expect(result.files[0].hunks[0].lines.count(where: { $0.type == .addition }) == 2) #expect(result.files[1].newName == "README.md") #expect(result.files[1].oldName == "README.md") let readmeHunk = result.files[1].hunks[0] - #expect(readmeHunk.lines.filter { $0.type == .context }.count == 1) - #expect(readmeHunk.lines.filter { $0.type == .addition }.count == 2) + #expect(readmeHunk.lines.count(where: { $0.type == .context }) == 1) + #expect(readmeHunk.lines.count(where: { $0.type == .addition }) == 2) } // MARK: - No newline at end of file sentinel diff --git a/Tests/ForgejoKitTests/ErrorMappingTests.swift b/Tests/ForgejoKitTests/ErrorMappingTests.swift index 31e593a..f96c3ad 100644 --- a/Tests/ForgejoKitTests/ErrorMappingTests.swift +++ b/Tests/ForgejoKitTests/ErrorMappingTests.swift @@ -1,8 +1,7 @@ -import Testing @testable import ForgejoKit +import Testing struct ErrorMappingTests { - @Test func classifiesHTTPStatusCodes() { #expect(HTTPErrorCategory(statusCode: 401) == .authentication) #expect(HTTPErrorCategory(statusCode: 403) == .permissionDenied) diff --git a/Tests/ForgejoKitTests/FileContentTests.swift b/Tests/ForgejoKitTests/FileContentTests.swift index 7585087..317d846 100644 --- a/Tests/ForgejoKitTests/FileContentTests.swift +++ b/Tests/ForgejoKitTests/FileContentTests.swift @@ -1,9 +1,8 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct FileContentTests { - private func makeFileContent(content: String?, encoding: String?) -> FileContent { FileContent( name: "test.txt", @@ -16,7 +15,7 @@ struct FileContentTests { downloadUrl: nil, type: "file", content: content, - encoding: encoding + encoding: encoding, ) } diff --git a/Tests/ForgejoKitTests/ModelDecodingTests.swift b/Tests/ForgejoKitTests/ModelDecodingTests.swift index a06062a..8724804 100644 --- a/Tests/ForgejoKitTests/ModelDecodingTests.swift +++ b/Tests/ForgejoKitTests/ModelDecodingTests.swift @@ -1,13 +1,12 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct ModelDecodingTests { - private func decoder() -> JSONDecoder { - let d = JSONDecoder() - d.dateDecodingStrategy = forgejoDateDecodingStrategy - return d + let jsonDecoder = JSONDecoder() + jsonDecoder.dateDecodingStrategy = forgejoDateDecodingStrategy + return jsonDecoder } // MARK: - User @@ -400,14 +399,14 @@ struct ModelDecodingTests { "updated_at": "2024-03-02T09:00:00Z" } """ - let pr = try decoder().decode(PullRequest.self, from: Data(json.utf8)) - #expect(pr.number == 42) - #expect(pr.title == "Add feature X") - #expect(pr.head.ref == "feature-x") - #expect(pr.base.ref == "main") - #expect(pr.mergeable == true) - #expect(pr.merged == false) - #expect(pr.draft == false) + let pullRequest = try decoder().decode(PullRequest.self, from: Data(json.utf8)) + #expect(pullRequest.number == 42) + #expect(pullRequest.title == "Add feature X") + #expect(pullRequest.head.ref == "feature-x") + #expect(pullRequest.base.ref == "main") + #expect(pullRequest.mergeable == true) + #expect(pullRequest.merged == false) + #expect(pullRequest.draft == false) } @Test func decodesPullRequestWithFullMetadata() throws { @@ -447,18 +446,18 @@ struct ModelDecodingTests { "updated_at": "2024-03-02T09:00:00Z" } """ - let pr = try decoder().decode(PullRequest.self, from: Data(json.utf8)) - #expect(pr.number == 46) - #expect(pr.labels.count == 2) - #expect(pr.labels[0].name == "enhancement") - #expect(pr.milestone?.id == 3) - #expect(pr.milestone?.title == "v1.0") - #expect(pr.milestone?.dueOn != nil) - #expect(pr.assignees?.count == 2) - #expect(pr.assignees?[0].login == "assignee1") - #expect(pr.assignees?[0].fullName == "Assignee One") - #expect(pr.requestedReviewers?.count == 1) - #expect(pr.requestedReviewers?[0].login == "reviewer1") + let pullRequest = try decoder().decode(PullRequest.self, from: Data(json.utf8)) + #expect(pullRequest.number == 46) + #expect(pullRequest.labels.count == 2) + #expect(pullRequest.labels[0].name == "enhancement") + #expect(pullRequest.milestone?.id == 3) + #expect(pullRequest.milestone?.title == "v1.0") + #expect(pullRequest.milestone?.dueOn != nil) + #expect(pullRequest.assignees?.count == 2) + #expect(pullRequest.assignees?[0].login == "assignee1") + #expect(pullRequest.assignees?[0].fullName == "Assignee One") + #expect(pullRequest.requestedReviewers?.count == 1) + #expect(pullRequest.requestedReviewers?[0].login == "reviewer1") } @Test func decodesPullRequestWithRequestedReviewers() throws { @@ -484,11 +483,11 @@ struct ModelDecodingTests { ] } """ - let pr = try decoder().decode(PullRequest.self, from: Data(json.utf8)) - #expect(pr.number == 44) - #expect(pr.requestedReviewers?.count == 2) - #expect(pr.requestedReviewers?[0].login == "reviewer1") - #expect(pr.requestedReviewers?[1].fullName == "Reviewer Two") + let pullRequest = try decoder().decode(PullRequest.self, from: Data(json.utf8)) + #expect(pullRequest.number == 44) + #expect(pullRequest.requestedReviewers?.count == 2) + #expect(pullRequest.requestedReviewers?[0].login == "reviewer1") + #expect(pullRequest.requestedReviewers?[1].fullName == "Reviewer Two") } @Test func decodesPullRequestWithoutRequestedReviewers() throws { @@ -507,9 +506,9 @@ struct ModelDecodingTests { "updated_at": "2024-03-02T09:00:00Z" } """ - let pr = try decoder().decode(PullRequest.self, from: Data(json.utf8)) - #expect(pr.number == 45) - #expect(pr.requestedReviewers == nil) + let pullRequest = try decoder().decode(PullRequest.self, from: Data(json.utf8)) + #expect(pullRequest.number == 45) + #expect(pullRequest.requestedReviewers == nil) } @Test func decodesMergedPullRequest() throws { @@ -531,10 +530,10 @@ struct ModelDecodingTests { "updated_at": "2024-04-01T12:00:00Z" } """ - let pr = try decoder().decode(PullRequest.self, from: Data(json.utf8)) - #expect(pr.merged == true) - #expect(pr.mergedBy?.login == "maintainer") - #expect(pr.mergedAt != nil) + let pullRequest = try decoder().decode(PullRequest.self, from: Data(json.utf8)) + #expect(pullRequest.merged == true) + #expect(pullRequest.mergedBy?.login == "maintainer") + #expect(pullRequest.mergedAt != nil) } // MARK: - PullRequestReview @@ -607,10 +606,10 @@ struct ModelDecodingTests { body: "Fix this", path: "file.swift", oldPosition: 5, - newPosition: 7 + newPosition: 7, ) let data = try JSONEncoder().encode(comment) - let dict = try JSONSerialization.jsonObject(with: data) as! [String: Any] + let dict = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any]) #expect(dict["body"] as? String == "Fix this") #expect(dict["path"] as? String == "file.swift") #expect(dict["old_position"] as? Int == 5) @@ -622,10 +621,10 @@ struct ModelDecodingTests { body: "Note", path: "readme.md", oldPosition: nil, - newPosition: nil + newPosition: nil, ) let data = try JSONEncoder().encode(comment) - let dict = try JSONSerialization.jsonObject(with: data) as! [String: Any] + let dict = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any]) #expect(dict["old_position"] == nil) #expect(dict["new_position"] == nil) } diff --git a/Tests/ForgejoKitTests/NormalizeServerURLTests.swift b/Tests/ForgejoKitTests/NormalizeServerURLTests.swift index f201229..8f2c33b 100644 --- a/Tests/ForgejoKitTests/NormalizeServerURLTests.swift +++ b/Tests/ForgejoKitTests/NormalizeServerURLTests.swift @@ -1,9 +1,8 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct NormalizeServerURLTests { - @Test func stripsTrailingSlash() { let result = ForgejoClient.normalizeServerURL("https://forgejo.example.com/") #expect(result == "https://forgejo.example.com") diff --git a/Tests/ForgejoKitTests/NotificationTests.swift b/Tests/ForgejoKitTests/NotificationTests.swift index 73afbda..a3af03c 100644 --- a/Tests/ForgejoKitTests/NotificationTests.swift +++ b/Tests/ForgejoKitTests/NotificationTests.swift @@ -1,13 +1,12 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct NotificationTests { - private func decoder() -> JSONDecoder { - let d = JSONDecoder() - d.dateDecodingStrategy = forgejoDateDecodingStrategy - return d + let jsonDecoder = JSONDecoder() + jsonDecoder.dateDecodingStrategy = forgejoDateDecodingStrategy + return jsonDecoder } // MARK: - Subject number extraction diff --git a/Tests/ForgejoKitTests/RepositoryServiceURLTests.swift b/Tests/ForgejoKitTests/RepositoryServiceURLTests.swift index 4640683..ad0ca84 100644 --- a/Tests/ForgejoKitTests/RepositoryServiceURLTests.swift +++ b/Tests/ForgejoKitTests/RepositoryServiceURLTests.swift @@ -1,9 +1,8 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct RepositoryServiceURLTests { - /// Creates a client with dummy credentials for URL construction tests. private func makeClient() -> ForgejoClient { ForgejoClient(serverURL: "https://forgejo.example.com", username: "user", password: "pass") @@ -120,7 +119,7 @@ struct RepositoryServiceURLTests { "auto_init": true, ] let data = try JSONSerialization.data(withJSONObject: payload) - let dict = try JSONSerialization.jsonObject(with: data) as! [String: Any] + let dict = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any]) #expect(dict["name"] as? String == "test-repo") #expect(dict["auto_init"] as? Bool == true) #expect(dict["private"] as? Bool == false) @@ -133,7 +132,7 @@ struct RepositoryServiceURLTests { "new_branch": "feature-branch", ] let data = try JSONSerialization.data(withJSONObject: payload) - let dict = try JSONSerialization.jsonObject(with: data) as! [String: Any] + let dict = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any]) #expect(dict["content"] as? String == "base64content") #expect(dict["message"] as? String == "Add file") #expect(dict["new_branch"] as? String == "feature-branch") diff --git a/Tests/ForgejoKitTests/URLSessionManagerTests.swift b/Tests/ForgejoKitTests/URLSessionManagerTests.swift index 8e6bc82..9106d53 100644 --- a/Tests/ForgejoKitTests/URLSessionManagerTests.swift +++ b/Tests/ForgejoKitTests/URLSessionManagerTests.swift @@ -1,9 +1,8 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct URLSessionManagerTests { - // MARK: - trustedHost scoping @Test func selfSignedWithoutTrustedHostAcceptsAny() { @@ -62,49 +61,48 @@ struct URLSessionManagerTests { } struct ForgejoClientHostMatchTests { - // MARK: - Auth header host matching - @Test func authenticatedRequestIncludesAuthForMatchingHost() { + @Test func authenticatedRequestIncludesAuthForMatchingHost() throws { let client = ForgejoClient( serverURL: "https://forgejo.example.com", username: "user", - password: "pass" + password: "pass", ) - let url = URL(string: "https://forgejo.example.com/api/v1/user")! + let url = try #require(URL(string: "https://forgejo.example.com/api/v1/user")) let request = client.authenticatedRequest(url: url) #expect(request.value(forHTTPHeaderField: "Authorization") != nil) } - @Test func authenticatedRequestOmitsAuthForDifferentHost() { + @Test func authenticatedRequestOmitsAuthForDifferentHost() throws { let client = ForgejoClient( serverURL: "https://forgejo.example.com", username: "user", - password: "pass" + password: "pass", ) - let url = URL(string: "https://evil.example.com/api/v1/user")! + let url = try #require(URL(string: "https://evil.example.com/api/v1/user")) let request = client.authenticatedRequest(url: url) #expect(request.value(forHTTPHeaderField: "Authorization") == nil) } - @Test func authenticatedRequestMatchesCaseInsensitiveHost() { + @Test func authenticatedRequestMatchesCaseInsensitiveHost() throws { let client = ForgejoClient( serverURL: "https://Forgejo.Example.COM", username: "user", - password: "pass" + password: "pass", ) - let url = URL(string: "https://forgejo.example.com/api/v1/repos")! + let url = try #require(URL(string: "https://forgejo.example.com/api/v1/repos")) let request = client.authenticatedRequest(url: url) #expect(request.value(forHTTPHeaderField: "Authorization") != nil) } - @Test func authenticatedRequestSetsMethodAndBody() { + @Test func authenticatedRequestSetsMethodAndBody() throws { let client = ForgejoClient( serverURL: "https://forgejo.example.com", username: "user", - password: "pass" + password: "pass", ) - let url = URL(string: "https://forgejo.example.com/api/v1/repos")! + let url = try #require(URL(string: "https://forgejo.example.com/api/v1/repos")) let body = Data("{\"name\":\"test\"}".utf8) let request = client.authenticatedRequest(url: url, method: "POST", body: body) #expect(request.httpMethod == "POST") @@ -116,7 +114,7 @@ struct ForgejoClientHostMatchTests { let client = ForgejoClient( serverURL: "https://forgejo.example.com", username: "user", - password: "pass" + password: "pass", ) let url = try client.makeURL(path: "/api/v1/user") #expect(url.absoluteString == "https://forgejo.example.com/api/v1/user") @@ -126,11 +124,11 @@ struct ForgejoClientHostMatchTests { let client = ForgejoClient( serverURL: "https://forgejo.example.com", username: "user", - password: "pass" + password: "pass", ) let url = try client.makeURL(path: "/api/v1/repos/search", queryItems: [ URLQueryItem(name: "q", value: "test"), - URLQueryItem(name: "page", value: "2") + URLQueryItem(name: "page", value: "2"), ]) #expect(url.absoluteString.contains("q=test")) #expect(url.absoluteString.contains("page=2")) @@ -142,7 +140,7 @@ struct ForgejoClientHostMatchTests { serverURL: "https://my-forgejo.local:3000", username: "user", password: "pass", - allowSelfSignedCertificates: true + allowSelfSignedCertificates: true, ) // The session should be created with self-signed support #expect(client.serverURL == "https://my-forgejo.local:3000") diff --git a/Tests/ForgejoKitTests/UserServiceTests.swift b/Tests/ForgejoKitTests/UserServiceTests.swift index cc04f7a..74c340a 100644 --- a/Tests/ForgejoKitTests/UserServiceTests.swift +++ b/Tests/ForgejoKitTests/UserServiceTests.swift @@ -1,16 +1,15 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct UserServiceTests { - @Test func createTokenPayloadEncodesCorrectKeys() throws { let payload: [String: Any] = [ "name": "integration-test-token", "scopes": ["read:user", "write:user"], ] let data = try JSONSerialization.data(withJSONObject: payload) - let dict = try JSONSerialization.jsonObject(with: data) as! [String: Any] + let dict = try #require(JSONSerialization.jsonObject(with: data) as? [String: Any]) #expect(dict["name"] as? String == "integration-test-token") #expect((dict["scopes"] as? [String])?.count == 2) } diff --git a/Tests/ForgejoKitTests/WorkflowServiceURLTests.swift b/Tests/ForgejoKitTests/WorkflowServiceURLTests.swift index e77ab20..5b3c859 100644 --- a/Tests/ForgejoKitTests/WorkflowServiceURLTests.swift +++ b/Tests/ForgejoKitTests/WorkflowServiceURLTests.swift @@ -1,9 +1,8 @@ +@testable import ForgejoKit import Foundation import Testing -@testable import ForgejoKit struct WorkflowServiceURLTests { - private func makeClient() -> ForgejoClient { ForgejoClient(serverURL: "https://forgejo.example.com", username: "user", password: "pass") } diff --git a/justfile b/justfile index d793164..682cad5 100644 --- a/justfile +++ b/justfile @@ -8,10 +8,10 @@ test: swift test 2>&1 | xcbeautify lint: - swiftlint lint Sources + swiftlint lint Sources Tests format: - swiftformat Sources + swiftformat Sources Tests # Tag and push a new release: just release 1.0.0 release version: