Merge pull request #101 from kkebo/add-ci

This commit is contained in:
Kenta Kubo 2025-04-09 08:57:46 +09:00 committed by GitHub
commit d92b2d1999
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 157 additions and 37 deletions

21
.github/workflows/ci.yml vendored Normal file
View file

@ -0,0 +1,21 @@
name: ci
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
jobs:
lint:
runs-on: ubuntu-latest
container: swift:6.1
steps:
- uses: actions/checkout@v4
- run: swift format lint -rsp .
yamllint:
runs-on: ubuntu-latest
container: alpine:3.21
steps:
- uses: actions/checkout@v4
- run: apk update && apk add yamllint
- run: yamllint --version
- run: yamllint --strict --config-file .yamllint.yml .

79
.swift-format Normal file
View file

@ -0,0 +1,79 @@
{
"fileScopedDeclarationPrivacy" : {
"accessLevel" : "private"
},
"indentConditionalCompilationBlocks" : true,
"indentSwitchCaseLabels" : false,
"indentation" : {
"spaces" : 4
},
"lineBreakAroundMultilineExpressionChainComponents" : true,
"lineBreakBeforeControlFlowKeywords" : false,
"lineBreakBeforeEachArgument" : true,
"lineBreakBeforeEachGenericRequirement" : true,
"lineBreakBetweenDeclarationAttributes" : false,
"lineLength" : 120,
"maximumBlankLines" : 1,
"multiElementCollectionTrailingCommas" : true,
"noAssignmentInExpressions" : {
"allowedFunctions" : [
"XCTAssertNoThrow"
]
},
"prioritizeKeepingFunctionOutputTogether" : true,
"reflowMultilineStringLiterals" : {
"never" : {
}
},
"respectsExistingLineBreaks" : true,
"rules" : {
"AllPublicDeclarationsHaveDocumentation" : false,
"AlwaysUseLiteralForEmptyCollectionInit" : true,
"AlwaysUseLowerCamelCase" : true,
"AmbiguousTrailingClosureOverload" : true,
"AvoidRetroactiveConformances" : false,
"BeginDocumentationCommentWithOneLineSummary" : true,
"DoNotUseSemicolons" : true,
"DontRepeatTypeInStaticProperties" : true,
"FileScopedDeclarationPrivacy" : true,
"FullyIndirectEnum" : true,
"GroupNumericLiterals" : true,
"IdentifiersMustBeASCII" : true,
"NeverForceUnwrap" : false,
"NeverUseForceTry" : true,
"NeverUseImplicitlyUnwrappedOptionals" : true,
"NoAccessLevelOnExtensionDeclaration" : true,
"NoAssignmentInExpressions" : true,
"NoBlockComments" : true,
"NoCasesWithOnlyFallthrough" : true,
"NoEmptyLinesOpeningClosingBraces" : true,
"NoEmptyTrailingClosureParentheses" : true,
"NoLabelsInCasePatterns" : true,
"NoLeadingUnderscores" : true,
"NoParensAroundConditions" : true,
"NoPlaygroundLiterals" : true,
"NoVoidReturnOnFunctionSignature" : true,
"OmitExplicitReturns" : true,
"OneCasePerLine" : true,
"OneVariableDeclarationPerLine" : true,
"OnlyOneTrailingClosureArgument" : true,
"OrderedImports" : true,
"ReplaceForEachWithForLoop" : true,
"ReturnVoidInsteadOfEmptyTuple" : true,
"TypeNamesShouldBeCapitalized" : true,
"UseEarlyExits" : true,
"UseExplicitNilCheckInConditions" : true,
"UseLetInEveryBoundCaseVariable" : true,
"UseShorthandTypeNames" : true,
"UseSingleLinePropertyGetter" : true,
"UseSynthesizedInitializer" : true,
"UseTripleSlashForDocumentationComments" : true,
"UseWhereClausesInForLoops" : true,
"ValidateDocumentationComments" : true
},
"spacesAroundRangeFormationOperators" : false,
"spacesBeforeEndOfLineComments" : 2,
"tabWidth" : 4,
"version" : 1
}

7
.yamllint.yml Normal file
View file

@ -0,0 +1,7 @@
extends: default
rules:
line-length: false
document-start: false
truthy:
check-keys: false

View file

@ -5,8 +5,8 @@
// Created by Kenta Kubo on 7/1/20.
//
import os.log
import SwiftUI
import os.log
let logger = Logger()

View file

@ -13,14 +13,14 @@ extension NEOnDemandRuleInterfaceType: @retroactive CustomStringConvertible {
case .any:
return "Any"
#if os(macOS)
case .ethernet:
return "Ethernet"
case .ethernet:
return "Ethernet"
#endif
case .wiFi:
return "Wi-Fi"
#if os(iOS)
case .cellular:
return "Cellular"
case .cellular:
return "Cellular"
#endif
default:
return "Unknown"

View file

@ -126,7 +126,7 @@ enum Presets {
configuration: .dnsOverTLS(
DoTConfiguration(
servers: [
"116.202.176.26",
"116.202.176.26"
],
serverName: "dot.libredns.gr"
)
@ -137,7 +137,7 @@ enum Presets {
configuration: .dnsOverHTTPS(
DoHConfiguration(
servers: [
"116.202.176.26",
"116.202.176.26"
],
serverURL: URL(string: "https://doh.libredns.gr/dns-query")
)
@ -148,7 +148,7 @@ enum Presets {
configuration: .dnsOverHTTPS(
DoHConfiguration(
servers: [
"116.202.176.26",
"116.202.176.26"
],
serverURL: URL(string: "https://doh.libredns.gr/ads")
)

View file

@ -48,9 +48,9 @@ enum Configuration {
func toDNSSettings() -> NEDNSSettings {
switch self {
case let .dnsOverTLS(configuration):
case .dnsOverTLS(let configuration):
return configuration.toDNSSettings()
case let .dnsOverHTTPS(configuration):
case .dnsOverHTTPS(let configuration):
return configuration.toDNSSettings()
}
}
@ -87,10 +87,10 @@ extension Configuration: Codable {
var container = encoder.container(keyedBy: Self.CodingKeys.self)
switch self {
case let .dnsOverTLS(configuration):
case .dnsOverTLS(let configuration):
try container.encode(Self.Base.dnsOverTLS, forKey: .base)
try container.encode(configuration, forKey: .dotConfiguration)
case let .dnsOverHTTPS(configuration):
case .dnsOverHTTPS(let configuration):
try container.encode(Self.Base.dnsOverHTTPS, forKey: .base)
try container.encode(configuration, forKey: .dohConfiguration)
}
@ -200,10 +200,11 @@ extension Resolver: Codable {
self.id = try container.decode(UUID.self, forKey: .id)
self.name = try container.decode(String.self, forKey: .name)
self.configuration = try container.decode(Configuration.self, forKey: .configuration)
self.onDemandRules = try container.decodeIfPresent(
[OnDemandRule].self,
forKey: .onDemandRules
) ?? []
self.onDemandRules =
try container.decodeIfPresent(
[OnDemandRule].self,
forKey: .onDemandRules
) ?? []
}
}
@ -218,7 +219,7 @@ extension Resolvers {
extension Resolvers: @retroactive RawRepresentable {
public init?(rawValue: String) {
guard let data = rawValue.data(using: .utf8),
let result = try? JSONDecoder().decode(Self.self, from: data)
let result = try? JSONDecoder().decode(Self.self, from: data)
else {
return nil
}
@ -227,7 +228,7 @@ extension Resolvers: @retroactive RawRepresentable {
public var rawValue: String {
guard let data = try? JSONEncoder().encode(self),
let result = String(data: data, encoding: .utf8)
let result = String(data: data, encoding: .utf8)
else {
return "[]"
}

View file

@ -90,8 +90,10 @@ struct ContentView {
manager.onDemandRules = server.onDemandRules.toNEOnDemandRules()
manager.saveToPreferences { saveError in
if let saveError = saveError as NSError? {
guard saveError.domain != "NEConfigurationErrorDomain"
|| saveError.code != 9 else {
guard
saveError.domain != "NEConfigurationErrorDomain"
|| saveError.code != 9
else {
// Nothing was changed
return
}
@ -187,8 +189,9 @@ extension ContentView: View {
// FIXME: This is a workaround for self.$severs[i].
// That cannot save settings as soon as it is modified.
guard let id = self.usedID,
let uuid = UUID(uuidString: id),
let server = self.servers.find(by: uuid) else {
let uuid = UUID(uuidString: id),
let server = self.servers.find(by: uuid)
else {
return
}
self.saveSettings(of: server)
@ -263,8 +266,9 @@ extension ContentView: View {
// FIXME: This is a workaround for self.$severs[i].
// That cannot save settings as soon as it is modified.
guard let id = self.usedID,
let uuid = UUID(uuidString: id),
let server = self.servers.find(by: uuid) else {
let uuid = UUID(uuidString: id),
let server = self.servers.find(by: uuid)
else {
return
}
self.saveSettings(of: server)

View file

@ -11,7 +11,7 @@ struct RestorationView {
@Environment(\.dismiss) private var dismiss
@State private var selection = Set<Resolver>()
@State private var keyword = ""
let onAdd: (Set<Resolver>) -> ()
let onAdd: (Set<Resolver>) -> Void
private var servers: Resolvers {
guard !self.keyword.isEmpty else { return Presets.servers }

View file

@ -36,7 +36,9 @@ extension RuleView: View {
} header: {
Text("Interface Type Match")
} footer: {
Text("If the current primary network interface is of this type and all of the other conditions in the rule match, then the rule matches.")
Text(
"If the current primary network interface is of this type and all of the other conditions in the rule match, then the rule matches."
)
}
if self.rule.interfaceType.ssidIsUsed {
@ -65,7 +67,9 @@ extension RuleView: View {
Text("SSID Match")
}
} footer: {
Text("If the Service Set Identifier (SSID) of the current primary connected network matches one of the strings in this array and all of the other conditions in the rule match, then the rule matches.")
Text(
"If the Service Set Identifier (SSID) of the current primary connected network matches one of the strings in this array and all of the other conditions in the rule match, then the rule matches."
)
}
}
@ -92,7 +96,9 @@ extension RuleView: View {
Text("DNS Search Domain Match")
}
} footer: {
Text("If the current default search domain is equal to one of the strings in this array and all of the other conditions in the rule match, then the rule matches.")
Text(
"If the current default search domain is equal to one of the strings in this array and all of the other conditions in the rule match, then the rule matches."
)
}
Section {
@ -118,7 +124,9 @@ extension RuleView: View {
Text("DNS Server Address Match")
}
} footer: {
Text("If each of the current default DNS servers is equal to one of the strings in this array and all of the other conditions in the rule match, then the rule matches.")
Text(
"If each of the current default DNS servers is equal to one of the strings in this array and all of the other conditions in the rule match, then the rule matches."
)
}
Section {
@ -132,7 +140,9 @@ extension RuleView: View {
} header: {
Text("Probe URL Match")
} footer: {
Text("If a request sent to this URL results in a HTTP 200 OK response and all of the other conditions in the rule match, then the rule matches. If you don't want to use this rule, leave it empty.")
Text(
"If a request sent to this URL results in a HTTP 200 OK response and all of the other conditions in the rule match, then the rule matches. If you don't want to use this rule, leave it empty."
)
}
}
.navigationTitle(self.rule.name)

View file

@ -6,10 +6,10 @@
//
import XCTest
@testable import DNSecure
class DNSecureTests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
@ -29,5 +29,4 @@ class DNSecureTests: XCTestCase {
// Put the code you want to measure the time of here.
}
}
}

View file

@ -8,7 +8,6 @@
import XCTest
class DNSecureUITests: XCTestCase {
override func setUpWithError() throws {
// Put setup code here. This method is called before the invocation of each test method in the class.

View file

@ -4,8 +4,8 @@
// This file is automatically generated.
// Do not edit it by hand because the contents will be replaced.
import PackageDescription
import AppleProductTypes
import PackageDescription
let package = Package(
name: "DNSecure",
@ -24,13 +24,13 @@ let package = Package(
accentColor: .asset("AccentColor"),
supportedDeviceFamilies: [
.pad,
.phone
.phone,
],
supportedInterfaceOrientations: [
.portrait,
.landscapeRight,
.landscapeLeft,
.portraitUpsideDown(.when(deviceFamilies: [.pad]))
.portraitUpsideDown(.when(deviceFamilies: [.pad])),
],
appCategory: .utilities
)
@ -46,6 +46,6 @@ let package = Package(
"DNSecure"
],
path: "DNSecureTests"
)
),
]
)