From 95c8c3dc30d0e06c4250c198559d5aac67106c1e Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Tue, 15 Aug 2023 10:35:33 -0500 Subject: [PATCH 1/2] Tidepool Sync --- Loop | 2 +- LoopKit | 2 +- Scripts/sync.swift | 137 ++++++++++++++++++++------------------------- 3 files changed, 64 insertions(+), 77 deletions(-) diff --git a/Loop b/Loop index 7b234dba04..cbf0590def 160000 --- a/Loop +++ b/Loop @@ -1 +1 @@ -Subproject commit 7b234dba046ac6ef554bf3cb115e501d53a14347 +Subproject commit cbf0590def84137ee82128c2f1e39234103cee97 diff --git a/LoopKit b/LoopKit index 675655b833..9877adcc0e 160000 --- a/LoopKit +++ b/LoopKit @@ -1 +1 @@ -Subproject commit 675655b833bcd5aef2391c47562b57a213bfffb4 +Subproject commit 9877adcc0e40144b36693bee009d480d86ac2b5b diff --git a/Scripts/sync.swift b/Scripts/sync.swift index af3f97e1ed..ffe1927aba 100755 --- a/Scripts/sync.swift +++ b/Scripts/sync.swift @@ -6,21 +6,57 @@ import Foundation import Cocoa import AsyncSwiftGit // @bdewey -import OctoKit // /Users/pete/dev/octokit.swift +import OctoKit // nerdishbynature/octokit.swift == main + +let createPRs = false + +guard CommandLine.arguments.count == 3 else { + print("usage: sync.swift ") + exit(1) +} +let pullRequestName = CommandLine.arguments[1] // example: "LOOP-4688 DIY Sync" +let syncBranch = CommandLine.arguments[2] // example: "ps/LOOP-4688/diy-sync" + +enum EnvError: Error { + case missing(String) +} + +func getEnv(_ name: String) throws -> String { + guard let value = ProcessInfo.processInfo.environment[name] else { + throw EnvError.missing(name) + } + return value +} + +let ghUsername = try getEnv("GH_USERNAME") +let ghToken = try getEnv("GH_TOKEN") +let ghCommitterName = try getEnv("GH_COMMITTER_NAME") +let ghCommitterEmail = try getEnv("GH_COMMITTER_EMAIL") struct Project { let project: String let branch: String + let subdir: String - init(_ project: String, _ branch: String) { + init(_ project: String, _ branch: String, _ subdir: String = "") { self.project = project self.branch = branch + self.subdir = subdir + } + + var path: String { + if subdir.isEmpty { + return project + } else { + return subdir + "/" + project + } } } let projects = [ Project("Loop", "dev"), Project("LoopKit", "dev"), + Project("TidepoolService", "dev"), Project("CGMBLEKit", "dev"), Project("dexcom-share-client-swift", "dev"), Project("RileyLinkKit", "dev"), @@ -32,49 +68,31 @@ let projects = [ Project("NightscoutRemoteCGM", "dev"), Project("LoopSupport", "dev"), Project("G7SensorKit", "main"), - Project("TidepoolService", "dev"), - Project("TidepoolKit", "dev"), Project("OmniKit", "main"), - Project("MinimedKit", "main") + Project("MinimedKit", "main"), + Project("LibreTransmitter", "main") ] let fm = FileManager.default let loopkit = URL(string: "https://github.com/LoopKit")! let tidepool = URL(string: "https://github.com/tidepool-org")! -let syncBranch = "tidepool-sync" let incomingRemote = "tidepool" -enum EnvError: Error { - case missing(String) -} - -func getEnv(_ name: String) throws -> String { - guard let value = ProcessInfo.processInfo.environment[name] else { - throw EnvError.missing(name) - } - return value -} - -let ghUsername = try getEnv("GH_USERNAME") -let ghToken = try getEnv("GH_TOKEN") -let ghCommitterName = try getEnv("GH_COMMITTER_NAME") -let ghCommitterEmail = try getEnv("GH_COMMITTER_EMAIL") - let octokit = Octokit(TokenConfiguration(ghToken)) let credentials = Credentials.plaintext(username: ghUsername, password: ghToken) let signature = try! Signature(name: ghCommitterName, email: ghCommitterEmail) for project in projects { - let dest = URL(string: fm.currentDirectoryPath)!.appendingPathComponent(project.project) + let dest = URL(string: fm.currentDirectoryPath)!.appendingPathComponent(project.path) let repository: AsyncSwiftGit.Repository - if !fm.fileExists(atPath: project.project) { + if !fm.fileExists(atPath: dest.path) { print("Cloning \(project.project)") let url = loopkit.appendingPathComponent(project.project) repository = try await Repository.clone(from: url, to: dest) print("Cloned \(project.project)") } else { - print("Already Exists: \(project.project)") + print("Already Exists: \(project.path)") repository = try Repository(openAt: dest) } @@ -110,55 +128,24 @@ for project in projects { print("Pushing \(refspec) to \(project.project)") try await repository.push(remoteName: "origin", refspecs: [refspec], credentials: credentials) - // Make sure a PR exists, or create it - let prs = try await octokit.listPullRequests(owner: "LoopKit", repo: project.project, base: project.branch, head:"LoopKit:tidepool-sync") - let pr: PullRequest - if prs.count == 0 { - pr = try await octokit.createPullRequest(owner: "LoopKit", repo: project.project, title: "Tidepool Sync", head: "LoopKit:" + syncBranch, base: project.branch, body: "") - print("PR = \(pr)") - } else { - pr = prs.first! - } - if let url = pr.htmlURL { - if NSWorkspace.shared.open(url) { - print("default browser was successfully opened") - - } - } + if createPRs { + // Make sure a PR exists, or create it + + let prs = try await octokit.pullRequests(owner: "LoopKit", repository: project.project, base: project.branch, head:"LoopKit:" + syncBranch) + let pr: PullRequest + if prs.count == 0 { + pr = try await octokit.createPullRequest(owner: "LoopKit", repo: project.project, title: pullRequestName, head: "LoopKit:" + syncBranch, base: project.branch, body: "") + print("PR = \(pr)") + } else { + pr = prs.first! + } + if let url = pr.htmlURL { + if NSWorkspace.shared.open(url) { + print("default browser was successfully opened") + } + } + } else { + print("Skipping PR creation") + } } -extension Octokit { - func createPullRequest(owner: String, - repo: String, - title: String, - head: String, - headRepo: String? = nil, - base: String, - body: String? = nil, - maintainerCanModify: Bool? = nil, - draft: Bool? = nil) async throws -> PullRequest - { - return try await withCheckedThrowingContinuation { continuation in - octokit.createPullRequest(owner: owner, repo: repo, title: title, head: head, headRepo: headRepo, base: base, body: body, maintainerCanModify: maintainerCanModify, draft: draft) - { response in - continuation.resume(with: response) - } - } - } - - func listPullRequests(owner: String, - repo: String, - base: String? = nil, - head: String? = nil, - state: Openness = .open, - sort: SortType = .created, - direction: SortDirection = .desc) async throws -> [PullRequest] - { - return try await withCheckedThrowingContinuation { continuation in - octokit.pullRequests(owner: owner, repository: repo, base: base, head: head, state: state, sort: sort, direction: direction) - { response in - continuation.resume(with: response) - } - } - } -} From 590a5563a1325c34f1c20ec42845b32e31c2264c Mon Sep 17 00:00:00 2001 From: Pete Schwamb Date: Wed, 16 Aug 2023 09:37:51 -0500 Subject: [PATCH 2/2] Make sure diffs exist, merge in LoopKit updates --- LoopKit | 2 +- Scripts/sync.swift | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/LoopKit b/LoopKit index 738d1a14ed..0f6f72f9f1 160000 --- a/LoopKit +++ b/LoopKit @@ -1 +1 @@ -Subproject commit 738d1a14edb34eadb3f47706de2ba06516dd2037 +Subproject commit 0f6f72f9f10bfa80d8296fa5646b1d02a823b6a7 diff --git a/Scripts/sync.swift b/Scripts/sync.swift index ffe1927aba..b4ecd1837e 100755 --- a/Scripts/sync.swift +++ b/Scripts/sync.swift @@ -113,11 +113,10 @@ for project in projects { // Merge changes from tidepool to diy try await repository.merge(revisionSpecification: "\(incomingRemote)/\(project.branch)", signature: signature) - let (ahead, behind) = try repository.commitsAheadBehind(other: "origin/\(project.branch)") - print("Ahead = \(ahead)") - print("Behind = \(behind)") + let originTree = try repository.lookupTree(for: "origin/\(project.branch)") + let diff = try repository.diff(originTree, repository.headTree) - guard ahead > 0 else { + guard diff.count > 0 else { print("No incoming changes; skipping PR creation.") try await repository.checkout(revspec: project.branch) continue