From d38fdc45112ea5fb2f1353cf53ec6d987b50a9fd Mon Sep 17 00:00:00 2001 From: Ethan Dickson Date: Wed, 27 May 2026 05:17:30 +0000 Subject: [PATCH] fix: normalize real CRLF in appcast description MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The `#"\r\n"#` raw string literal matches the 4 characters \, r, \, n — not CR+LF. GitHub stores release bodies with CRLF line endings, so the replacement was a no-op and the CRs reached Parsley untouched. Parsley's `parts()` calls `Scanner.scanUpToString("\n")` to grab the H1 title. Foundation's Scanner skips newlines by default (`charactersToBeSkipped` includes \n), so when the input has CRLF the scanner walks past every newline to EOF, leaving the body empty. Only releases whose notes start with `# ` hit the H1 branch, which is why v0.8.1 was the first to publish an empty to releases.coder.com. --- scripts/update-appcast/Sources/main.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/update-appcast/Sources/main.swift b/scripts/update-appcast/Sources/main.swift index d546003f..17a57bc6 100644 --- a/scripts/update-appcast/Sources/main.swift +++ b/scripts/update-appcast/Sources/main.swift @@ -99,7 +99,7 @@ struct UpdateAppcast: AsyncParsableCommand { } if let description, !description.isEmpty { - let description = description.replacingOccurrences(of: #"\r\n"#, with: "\n") + let description = description.replacingOccurrences(of: "\r\n", with: "\n") let descriptionDoc: Document do { descriptionDoc = try Parsley.parse(description)