Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/ci/swift-test-skips.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Tests CI leaves out of `swift test` (.github/workflows/ci.yml), one per line:
# <regular expression for Target.TestCase/test> <reason>
# Only for tests that depend on the runner rather than the code (real-time timing, devices).

AnyPS5SharePlayTests.SharePlayOpusTests/testAViewerSayingHelloHearsStereoOpus Real-time WebRTC audio: the jitter buffer and packet rate it measures go past its limits on a shared runner.
79 changes: 79 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
name: CI

on:
pull_request:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read

concurrency:
group: ci-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}

jobs:
test:
name: swift test
# Liquid Glass (glassEffect) needs the macOS 26 SDK.
runs-on: macos-26
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
# The newest Xcode on the runner (its SDK has Liquid Glass; the launcher must also build with Xcode 26's Swift 6.3).
- name: Select the newest Xcode
run: |
ls -d /Applications/Xcode*.app
xcode=$(ls -d /Applications/Xcode_*.app | grep -iv beta | sort -V | tail -1)
sudo xcode-select -s "$xcode"
swift --version
- uses: actions/cache@v6
with:
path: .build
key: spm-debug-${{ runner.os }}-${{ hashFiles('Package.resolved') }}-${{ github.sha }}
restore-keys: spm-debug-${{ runner.os }}-${{ hashFiles('Package.resolved') }}-
- name: swift test (without the runner-dependent tests in .github/ci/swift-test-skips.txt)
run: |
skips=()
while read -r pattern _; do skips+=(--skip "$pattern"); done < <(grep -Ev '^(#|[[:space:]]*$)' .github/ci/swift-test-skips.txt)
echo "swift test ${skips[*]}"
swift test "${skips[@]}"

release:
name: swift build -c release
runs-on: macos-26
timeout-minutes: 45
steps:
- uses: actions/checkout@v7
with:
persist-credentials: false
# The newest Xcode on the runner (its SDK has Liquid Glass; the launcher must also build with Xcode 26's Swift 6.3).
- name: Select the newest Xcode
run: |
ls -d /Applications/Xcode*.app
xcode=$(ls -d /Applications/Xcode_*.app | grep -iv beta | sort -V | tail -1)
sudo xcode-select -s "$xcode"
swift --version
- uses: actions/cache@v6
with:
path: .build
key: spm-release-${{ runner.os }}-${{ hashFiles('Package.resolved') }}-${{ github.sha }}
restore-keys: spm-release-${{ runner.os }}-${{ hashFiles('Package.resolved') }}-
- run: swift build -c release

ci-ok:
name: ci-ok
if: always()
needs: [test, release]
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- env:
NEEDS: ${{ toJSON(needs) }}
run: |
echo "$NEEDS" | jq -r 'to_entries[] | "\(.key): \(.value.result)"'
bad=$(echo "$NEEDS" | jq -r '[to_entries[] | select(.value.result != "success" and .value.result != "skipped") | .key] | join(", ")')
if [ -n "$bad" ]; then echo "::error::Not passed: $bad"; exit 1; fi
2 changes: 1 addition & 1 deletion Sources/AnyPS5/AppModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1417,7 +1417,7 @@ final class AppModel: ObservableObject {
if !waiting { prepareTimer?.invalidate(); prepareTimer = nil; return }
guard prepareTimer == nil else { return }
prepareTimer = Timer.scheduledTimer(withTimeInterval: 30, repeats: true) { [weak self] _ in
MainActor.assumeIsolated { self?.stepPrepare() }
MainActor.assumeIsolated { _ = self?.stepPrepare() }
}
}

Expand Down
4 changes: 2 additions & 2 deletions Sources/AnyPS5/SocialPreviews.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ enum SocialPreviews {
let person = { (id: String, name: String) in TogetherPerson(userId: id, handle: name.lowercased(), displayName: name, avatar: nil) }
let names = ["Mira", "Kenji", "Sol", "Ines", "Theo", "Noor", "Lena", "Felix"]
let top = names.enumerated().map { index, name in TogetherLeaderboard.Entry(rank: index + 1, user: person("p\(index)", name), value: 9_400 - index * 870) }
let me = TogetherLeaderboard.Entry(rank: 41, user: person("u1", "Robin"), value: 1_830)
let around = [TogetherLeaderboard.Entry(rank: 40, user: person("x1", "Lin"), value: 1_905), me, TogetherLeaderboard.Entry(rank: 42, user: person("x2", "Ada"), value: 1_790)]
let robin = TogetherLeaderboard.Entry(rank: 41, user: person("u1", "Robin"), value: 1_830)
let around = [TogetherLeaderboard.Entry(rank: 40, user: person("x1", "Lin"), value: 1_905), robin, TogetherLeaderboard.Entry(rank: 42, user: person("x2", "Ada"), value: 1_790)]
render("leaderboard-game") { model in
model.previewLeaderboard(TogetherLeaderboard(board: "points", scope: .global, game: nil, entries: Array(top.prefix(4)), me: .init(rank: 41, value: 1_830, listed: true), around: around, total: 312),
game: found.first, index: 6)
Expand Down
2 changes: 1 addition & 1 deletion Sources/AnyPS5Core/Profiles/LauncherProfiles.swift
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ public final class ProfileStore: @unchecked Sendable {
let used = Set(book.profiles.map(\.avatar.color))
let color = (0 ..< LauncherProfile.paletteSize).first { !used.contains($0) } ?? book.profiles.count % LauncherProfile.paletteSize
let first = book.profiles.isEmpty
let made = id.flatMap { candidate in profile(candidate) == nil ? candidate : nil }
let made = id.flatMap { candidate in self.profile(candidate) == nil ? candidate : nil }
?? (first && book.legacyOwner == nil ? LauncherProfile.legacyID : UUID().uuidString.lowercased())
let profile = LauncherProfile(id: made, name: name, avatar: .init(color: color), mode: mode, account: account)
book.profiles.append(profile)
Expand Down
7 changes: 6 additions & 1 deletion Tests/AnyPS5CoreTests/IssueDraftTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,12 @@ final class IssueDraftTests: XCTestCase {
// tools/macos/launcher/Tests/AnyPS5CoreTests → the repository root.
let root = URL(fileURLWithPath: #filePath).deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent()
.deletingLastPathComponent().deletingLastPathComponent().deletingLastPathComponent()
let template = try String(contentsOf: root.appendingPathComponent(".github/ISSUE_TEMPLATE/crash.yml"), encoding: .utf8)
let file = root.appendingPathComponent(".github/ISSUE_TEMPLATE/crash.yml")
// The issue forms are AnyPS5-ARM's; the standalone AnyLauncher repository has none to check.
guard FileManager.default.fileExists(atPath: file.path) else {
throw XCTSkip("no .github/ISSUE_TEMPLATE/crash.yml: run this in AnyPS5-ARM's tools/macos/launcher")
}
let template = try String(contentsOf: file, encoding: .utf8)
for field in IssueDraft.crash(report()).fields {
XCTAssertTrue(template.contains("id: \(field.id)\n"), "crash.yml has no field \(field.id)")
}
Expand Down
Loading