Files
letro-ios/Tools/Sources/Commands/BumpCalendarVersion.swift
Doug ea4f1ba9f3 Automatically open a PR to bump the calver (#4167)
* Update our tools package to Swift 6.1

Also improves the package layout with subdirectories 📁

* Update GenerateSDKMocks to be an Async command.

* Add a tool to bump the project CalVer every month.

* Add a workflow to automatically bump the calendar version.

Note: This only does year & month, the patch is handled by the release script.
2025-06-03 17:52:16 +01:00

55 lines
2.5 KiB
Swift

import ArgumentParser
import CommandLineTools
import Foundation
struct BumpCalendarVersion: ParsableCommand {
static let configuration = CommandConfiguration(abstract: "A tool that bumps the CalVer every month (if needed), setting the patch back to 0.",
discussion: "The tool assumes the release will be published in 6-days so bumps early.")
func run() throws {
try updateProjectYAML()
try Zsh.run(command: "xcodegen")
}
/// Updates the project YAML with the new version.
private func updateProjectYAML() throws {
let yamlURL = URL.projectDirectory.appendingPathComponent("project.yml")
let yamlString = try String(contentsOf: yamlURL)
// Use regex instead of Yams to preserve any whitespace, comments etc in the file.
let marketingVersionRegex = /MARKETING_VERSION:\s*([^\s]+)/
var updatedYAMLString = ""
yamlString.enumerateLines { line, _ in
let processedLine = if let match = line.firstMatch(of: marketingVersionRegex),
let newVersion = try? generateNewVersion(from: String(match.1)) {
line.replacingOccurrences(of: match.1, with: newVersion)
} else {
line
}
updatedYAMLString.append(processedLine + "\n")
}
try updatedYAMLString.write(to: yamlURL, atomically: true, encoding: .utf8)
}
/// Returns the new version string if a change is necessary.
///
/// **Note:** This tool does *not* handle patch bumps, those are done automatically in the release script.
private func generateNewVersion(from currentVersion: String) throws -> String? {
let releaseDate = Date.now.addingTimeInterval(6 * 24 * 60 * 60) // Always assume we're building the RC.
let releaseYear = Calendar.current.component(.year, from: releaseDate) % 1000 // We use the short year.
let releaseMonth = Calendar.current.component(.month, from: releaseDate)
let versionComponents = currentVersion.split(separator: ".").compactMap { Int($0) }
guard versionComponents.count == 3 else { fatalError("Unexpected version format: \(currentVersion)") }
if versionComponents[0] != releaseYear || versionComponents[1] != releaseMonth {
return "\(releaseYear).\(String(format: "%02d", releaseMonth)).0"
} else {
return nil
}
}
}