Skip to content

Commit

Permalink
Better swift release message (#273)
Browse files Browse the repository at this point in the history
  • Loading branch information
MahdiBM authored Dec 14, 2024
1 parent 2dc4291 commit 2068605
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 13 deletions.
3 changes: 1 addition & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@
"yaml.maxItemsComputed": 1000000,
"yaml.format.enable": true,
"editor.rulers": [120],
"editor.minimap.enabled": false,
"editor.wordWrapColumn": 100,
"editor.wordWrapColumn": 120,
"githubPullRequests.pullBranch": "never",
"errorLens.statusBarColorsEnabled": true,
"errorLens.statusBarIconsEnabled": true,
Expand Down
43 changes: 43 additions & 0 deletions Sources/Penny/Services/CachesService/CachesStorage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,27 @@ struct CachesStorage: Sendable, Codable {
var swiftReleasesData: SwiftReleasesChecker.Storage?
var autoFaqsResponseRateLimiter: DefaultAutoFaqsService.ResponseRateLimiter?

init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.reactionCacheData = container.decodeIfPresentWithLogging(
ReactionCache.Storage.self,
forKey: .reactionCacheData
)
self.evolutionCheckerData = container.decodeIfPresentWithLogging(
EvolutionChecker.Storage.self,
forKey: .evolutionCheckerData
)
self.soCheckerData = container.decodeIfPresentWithLogging(SOChecker.Storage.self, forKey: .soCheckerData)
self.swiftReleasesData = container.decodeIfPresentWithLogging(
SwiftReleasesChecker.Storage.self,
forKey: .swiftReleasesData
)
self.autoFaqsResponseRateLimiter = container.decodeIfPresentWithLogging(
DefaultAutoFaqsService.ResponseRateLimiter.self,
forKey: .autoFaqsResponseRateLimiter
)
}

init() {}

static func makeFromCachedData(context: Context) async -> CachesStorage {
Expand Down Expand Up @@ -75,3 +96,25 @@ struct CachesStorage: Sendable, Codable {
)
}
}

extension KeyedDecodingContainer {
fileprivate func decodeIfPresentWithLogging<T>(
_ type: T.Type,
forKey key: KeyedDecodingContainer<K>.Key
) -> T? where T: Decodable {
do {
let value = try self.decodeIfPresent(type, forKey: key)
return value
} catch {
Logger(label: "CachesStorage").warning(
"Failed to decode a cached value",
metadata: [
"error": .string(String(reflecting: error)),
"key": .string(String(describing: key)),
"type": .string(Swift._typeName(type)),
]
)
return nil
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@ import Foundation
struct DefaultSwiftReleasesService: SwiftReleasesService {
let httpClient: HTTPClient
let logger = Logger(label: "DefaultSwiftReleasesService")
let decoder = JSONDecoder()
let decoder: JSONDecoder = {
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
return decoder
}()

func listReleases() async throws -> [SwiftOrgRelease] {
let url = "https://www.swift.org/api/v1/install/releases.json"
Expand Down
23 changes: 19 additions & 4 deletions Sources/Penny/SwiftReleasesChecker.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,18 @@ actor SwiftReleasesChecker: Service {
self.storage.currentReleases = releases

for release in newReleases {
let image =
"https://opengraph.githubassets.com/\(UUID().uuidString)/swiftlang/swift/releases/tag/\(release.tag)"
/// swiftlang's GitHub logo aka the Swift logo
let image = "https://avatars.githubusercontent.com/u/42816656"
await discordService.sendMessage(
channelId: Constants.Channels.news.id,
payload: .init(embeds: [
.init(
title: "Swift \(release.stableName) Release".unicodesPrefix(256),
description: """
\((release.xcodeRelease == true) ? "Available on \(release.xcode)" : "Doesn't come with a dedicated Xcode release")
""",
url: "https://github.com/swiftlang/swift/releases/tag/\(release.tag)",
color: .cyan,
color: .orange,
image: .init(url: .exact(image))
)
])
Expand All @@ -75,9 +78,11 @@ actor SwiftReleasesChecker: Service {
}
}

struct SwiftOrgRelease: Codable, Hashable {
struct SwiftOrgRelease: Codable {
let name: String
let tag: String
let xcode: String
let xcodeRelease: Bool?

var stableName: String {
let components = self.name.split(
Expand All @@ -91,3 +96,13 @@ struct SwiftOrgRelease: Codable, Hashable {
}
}
}

extension SwiftOrgRelease: Hashable {
static func == (lhs: SwiftOrgRelease, rhs: SwiftOrgRelease) -> Bool {
lhs.tag == rhs.tag
}

func hash(into hasher: inout Hasher) {
hasher.combine(self.tag)
}
}
15 changes: 10 additions & 5 deletions Tests/PennyTests/Fake/TestData.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,6 @@ import Foundation

enum TestData {

private static let decoder = JSONDecoder()

private static func resource(named name: String) -> Data {
let fileManager = FileManager.default
let currentDirectory = fileManager.currentDirectoryPath
Expand All @@ -27,9 +25,15 @@ enum TestData {
return data
}

private static func resource<D: Decodable>(named name: String, as: D.Type = D.self) -> D {
private static func resource<D: Decodable>(
named name: String,
keyDecodingStrategy: JSONDecoder.KeyDecodingStrategy = .useDefaultKeys,
as: D.Type = D.self
) -> D {
let data = resource(named: name)
return try! JSONDecoder().decode(D.self, from: data)
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = keyDecodingStrategy
return try! decoder.decode(D.self, from: data)
}

static let vaporGuild = resource(
Expand All @@ -54,6 +58,7 @@ enum TestData {
).items
static let swiftReleases = TestData.resource(
named: "swiftReleases.json",
keyDecodingStrategy: .convertFromSnakeCase,
as: [SwiftOrgRelease].self
)
static let swiftReleasesUpdated = TestData.resource(
Expand All @@ -76,7 +81,7 @@ enum TestData {

static func decodedFor(gatewayEventKey key: String) -> Gateway.Event {
let data = gatewayEvents[key]!
let decoded = try! decoder.decode(Gateway.Event.self, from: data)
let decoded = try! JSONDecoder().decode(Gateway.Event.self, from: data)
return decoded
}

Expand Down
4 changes: 3 additions & 1 deletion Tests/PennyTests/Tests/GatewayProcessingTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,9 @@ extension SerializationNamespace.GatewayProcessingTests {
let _message = await responseStorage.awaitResponse(at: endpoint).value
let message = try #require(_message as? Payloads.CreateMessage, "\(_message)")

#expect(message.embeds?.first?.title == "Swift 6.0.1 Release")
let embed = try #require(message.embeds?.first)
#expect(embed.title == "Swift 6.0.1 Release")
#expect(embed.description == "Doesn't come with a dedicated Xcode release")

/// No more messages should be sent
let _newMessage = await responseStorage.awaitResponse(
Expand Down

0 comments on commit 2068605

Please sign in to comment.