Skip to content

Commit 83c127e

Browse files
committed
ci: add test, fmt, lint workflows
1 parent b338777 commit 83c127e

22 files changed

+238
-134
lines changed

.github/workflows/ci.yml

+54
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: ci
2+
3+
on:
4+
pull_request:
5+
paths-ignore:
6+
- "README.md"
7+
push:
8+
branches:
9+
- main
10+
paths-ignore:
11+
- "README.md"
12+
13+
14+
permissions:
15+
contents: read
16+
17+
jobs:
18+
test:
19+
name: test
20+
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest'}}
21+
steps:
22+
- name: Checkout
23+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
24+
with:
25+
fetch-depth: 1
26+
- name: Switch XCode Version
27+
uses: maxim-lobanov/setup-xcode@v1
28+
with:
29+
xcode-version: '16.0.0'
30+
- run: |
31+
make test
32+
format:
33+
name: fmt
34+
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest'}}
35+
steps:
36+
- name: Checkout
37+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
38+
with:
39+
fetch-depth: 1
40+
- run: |
41+
make fmt
42+
lint:
43+
name: lint
44+
runs-on: ${{ github.repository_owner == 'coder' && 'depot-macos-latest' || 'macos-latest'}}
45+
steps:
46+
- name: Checkout
47+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
48+
with:
49+
fetch-depth: 1
50+
- name: Install Swiftlint
51+
run: |
52+
brew install swiftlint
53+
- run: |
54+
make lint

Coder Desktop/.swiftlint.yml

+3
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
disabled_rules:
22
- todo
33
- trailing_comma
4+
- blanket_disable_command # Used by Protobuf
5+
- opening_brace # Handled by SwiftFormat
46
type_name:
57
allowed_symbols: "_"
68
identifier_name:
79
allowed_symbols: "_"
10+
min_length: 1

Coder Desktop/Coder Desktop.xcodeproj/project.pbxproj

+2
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@
721721
CURRENT_PROJECT_VERSION = 1;
722722
DEVELOPMENT_TEAM = 4399GN35BJ;
723723
GENERATE_INFOPLIST_FILE = YES;
724+
MACOSX_DEPLOYMENT_TARGET = 14.6;
724725
MARKETING_VERSION = 1.0;
725726
PRODUCT_BUNDLE_IDENTIFIER = "com.coder.Coder-DesktopUITests";
726727
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -737,6 +738,7 @@
737738
CURRENT_PROJECT_VERSION = 1;
738739
DEVELOPMENT_TEAM = 4399GN35BJ;
739740
GENERATE_INFOPLIST_FILE = YES;
741+
MACOSX_DEPLOYMENT_TARGET = 14.6;
740742
MARKETING_VERSION = 1.0;
741743
PRODUCT_BUNDLE_IDENTIFIER = "com.coder.Coder-DesktopUITests";
742744
PRODUCT_NAME = "$(TARGET_NAME)";

Coder Desktop/Coder Desktop.xctestplan

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
}
2626
},
2727
{
28+
"enabled" : false,
2829
"parallelizable" : true,
2930
"target" : {
3031
"containerPath" : "container:Coder Desktop.xcodeproj",

Coder Desktop/Coder Desktop/Theme.swift

+1
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ enum Theme {
88

99
static let rectCornerRadius: CGFloat = 4
1010
}
11+
1112
static let defaultVisibleAgents = 5
1213
}

Coder Desktop/Coder Desktop/Views/Agents.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ struct Agents<VPN: VPNService, S: Session>: View {
66
@State private var viewAll = false
77
private let defaultVisibleRows = 5
88

9-
internal let inspection = Inspection<Self>()
9+
let inspection = Inspection<Self>()
1010

1111
var body: some View {
1212
Group {

Coder Desktop/Coder Desktop/Views/LoginForm.swift

+6-5
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ struct LoginForm<C: Client, S: Session>: View {
1111
@State private var loading: Bool = false
1212
@FocusState private var focusedField: LoginField?
1313

14-
internal let inspection = Inspection<Self>()
14+
let inspection = Inspection<Self>()
1515

1616
var body: some View {
1717
VStack {
@@ -58,7 +58,8 @@ struct LoginForm<C: Client, S: Session>: View {
5858
.onReceive(inspection.notice) { self.inspection.visit(self, $0) } // ViewInspector
5959
}
6060

61-
internal func submit() async {
61+
func submit() async {
62+
loginError = nil
6263
guard sessionToken != "" else {
6364
return
6465
}
@@ -67,7 +68,7 @@ struct LoginForm<C: Client, S: Session>: View {
6768
return
6869
}
6970
loading = true
70-
defer { loading = false}
71+
defer { loading = false }
7172
let client = C(url: url, token: sessionToken)
7273
do throws(ClientError) {
7374
_ = try await client.user("me")
@@ -134,8 +135,8 @@ struct LoginForm<C: Client, S: Session>: View {
134135
Button("Sign In") {
135136
Task { await submit() }
136137
}
137-
.buttonStyle(.borderedProminent)
138-
.keyboardShortcut(.defaultAction)
138+
.buttonStyle(.borderedProminent)
139+
.keyboardShortcut(.defaultAction)
139140
}.padding(.top, 5)
140141
}
141142
}

Coder Desktop/Coder Desktop/Views/Util.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Combine
22

33
// This is required for inspecting stateful views
4-
internal final class Inspection<V> {
4+
final class Inspection<V> {
55
let notice = PassthroughSubject<UInt, Never>()
66
var callbacks = [UInt: (V) -> Void]()
77

Coder Desktop/Coder Desktop/Views/VPNMenu.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ struct VPNMenu<VPN: VPNService, S: Session>: View {
44
@EnvironmentObject var vpn: VPN
55
@EnvironmentObject var session: S
66

7-
internal let inspection = Inspection<Self>()
7+
let inspection = Inspection<Self>()
88

99
var body: some View {
1010
// Main stack

Coder Desktop/Coder Desktop/Views/VPNState.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import SwiftUI
33
struct VPNState<VPN: VPNService>: View {
44
@EnvironmentObject var vpn: VPN
55

6-
internal let inspection = Inspection<Self>()
6+
let inspection = Inspection<Self>()
77

88
var body: some View {
99
Group {

Coder Desktop/Coder DesktopTests/AgentsTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@testable import Coder_Desktop
2+
import SwiftUI
23
import Testing
34
import ViewInspector
4-
import SwiftUI
55

66
@Suite(.timeLimit(.minutes(1)))
77
struct AgentsTests {
@@ -47,7 +47,7 @@ struct AgentsTests {
4747

4848
let forEach = try view.inspect().find(ViewType.ForEach.self)
4949
#expect(forEach.count == Theme.defaultVisibleAgents)
50-
#expect(throws: Never.self) { try view.inspect().find(link: "a1.coder")}
50+
#expect(throws: Never.self) { try view.inspect().find(link: "a1.coder") }
5151
}
5252

5353
@Test

Coder Desktop/Coder DesktopTests/LoginFormTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@testable import Coder_Desktop
2-
import ViewInspector
3-
import Testing
42
import SwiftUI
3+
import Testing
4+
import ViewInspector
55

66
@Suite(.timeLimit(.minutes(1)))
77
struct LoginTests {

Coder Desktop/Coder DesktopTests/VPNMenuTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@testable import Coder_Desktop
2+
import SwiftUI
23
import Testing
34
import ViewInspector
4-
import SwiftUI
55

66
@Suite(.timeLimit(.minutes(1)))
77
struct VPNMenuTests {

Coder Desktop/Coder DesktopTests/VPNStateTests.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
@testable import Coder_Desktop
2-
import ViewInspector
3-
import Testing
42
import SwiftUI
3+
import Testing
4+
import ViewInspector
55

66
@Suite(.timeLimit(.minutes(1)))
77
struct VPNStateTests {

Coder Desktop/Coder DesktopUITests/Coder_DesktopUITests.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ final class Coder_DesktopUITests: XCTestCase {
77
// In UI tests it is usually best to stop immediately when a failure occurs.
88
continueAfterFailure = false
99

10-
// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
10+
// In UI tests it’s important to set the initial state - such as
11+
// interface orientation - required for your tests before they run. The setUp method is a good place to do this.
1112
}
1213

1314
override func tearDownWithError() throws {

Coder Desktop/Coder DesktopUITests/Coder_DesktopUITestsLaunchTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import XCTest
22

33
final class Coder_DesktopUITestsLaunchTests: XCTestCase {
4-
override class var runsForEachTargetApplicationUIConfiguration: Bool {
4+
override static var runsForEachTargetApplicationUIConfiguration: Bool {
55
true
66
}
77

Coder Desktop/Proto/Receiver.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import Foundation
2-
import SwiftProtobuf
32
import os
3+
import SwiftProtobuf
44

55
/// An actor that reads data from a `DispatchIO` channel, and deserializes it into VPN protocol messages.
66
actor Receiver<RecvMsg: Message> {
@@ -19,7 +19,7 @@ actor Receiver<RecvMsg: Message> {
1919
private func readLen() async throws -> UInt32 {
2020
let lenD: Data = try await withCheckedThrowingContinuation { continuation in
2121
var lenData = Data()
22-
dispatch.read(offset: 0, length: 4, queue: queue) {done, data, error in
22+
dispatch.read(offset: 0, length: 4, queue: queue) { done, data, error in
2323
guard error == 0 else {
2424
let errStrPtr = strerror(error)
2525
let errStr = String(validatingUTF8: errStrPtr!)!
@@ -39,7 +39,7 @@ actor Receiver<RecvMsg: Message> {
3939
private func readMsg(_ length: UInt32) async throws -> RecvMsg {
4040
let msgData: Data = try await withCheckedThrowingContinuation { continuation in
4141
var msgData = Data()
42-
dispatch.read(offset: 0, length: Int(length), queue: queue) {done, data, error in
42+
dispatch.read(offset: 0, length: Int(length), queue: queue) { done, data, error in
4343
guard error == 0 else {
4444
let errStrPtr = strerror(error)
4545
let errStr = String(validatingUTF8: errStrPtr!)!

0 commit comments

Comments
 (0)