|
1 | 1 | import { existsSync } from "node:fs"; |
2 | | -import { cp, link, mkdir, readdir, readFile, symlink, unlink, writeFile } from "node:fs/promises"; |
| 2 | +import { cp, link, mkdir, readdir, readFile, readlink, rm, symlink, unlink, writeFile } from "node:fs/promises"; |
3 | 3 | import { join, resolve } from "node:path"; |
4 | 4 | import { SHARED_DIR } from "../constants"; |
5 | 5 | import type { Profile } from "../types"; |
@@ -104,6 +104,21 @@ export class GitHubRunnerProvider implements RunnerProvider { |
104 | 104 | return runners; |
105 | 105 | } |
106 | 106 |
|
| 107 | + async currentVersion(id: string): Promise<string | null> { |
| 108 | + const runnerDir = join(this.profile.directory, id); |
| 109 | + return this.detectVersion(runnerDir); |
| 110 | + } |
| 111 | + |
| 112 | + async update(ids: string[]): Promise<void> { |
| 113 | + const sharedPath = await this.ensureDownloaded(); |
| 114 | + |
| 115 | + for (const id of ids) { |
| 116 | + const runnerDir = join(this.profile.directory, id); |
| 117 | + await this.removeRunnerBinaries(runnerDir); |
| 118 | + await this.setupRunnerDir(sharedPath, runnerDir); |
| 119 | + } |
| 120 | + } |
| 121 | + |
107 | 122 | private async getRunnerStatus(runnerDir: string, id: string): Promise<RunnerInfo> { |
108 | 123 | const name = await this.readRunnerName(runnerDir); |
109 | 124 | const pid = await this.readPidFile(runnerDir); |
@@ -240,6 +255,31 @@ export class GitHubRunnerProvider implements RunnerProvider { |
240 | 255 | } |
241 | 256 | } |
242 | 257 |
|
| 258 | + private async detectVersion(runnerDir: string): Promise<string | null> { |
| 259 | + try { |
| 260 | + const target = await readlink(join(runnerDir, "externals")); |
| 261 | + const match = target.match(/github\/([^/]+)/); |
| 262 | + return match?.[1] ?? null; |
| 263 | + } catch { |
| 264 | + return null; |
| 265 | + } |
| 266 | + } |
| 267 | + |
| 268 | + private async removeRunnerBinaries(runnerDir: string) { |
| 269 | + for (const dir of HARDLINK_DIRS) { |
| 270 | + await rm(join(runnerDir, dir), { force: true, recursive: true }); |
| 271 | + } |
| 272 | + for (const dir of SYMLINK_DIRS) { |
| 273 | + await rm(join(runnerDir, dir), { force: true }); |
| 274 | + } |
| 275 | + for (const pattern of ["*.sh", "*.sh.template"]) { |
| 276 | + const files = await Array.fromAsync(new Bun.Glob(pattern).scan(runnerDir)); |
| 277 | + for (const file of files) { |
| 278 | + await rm(join(runnerDir, file), { force: true }); |
| 279 | + } |
| 280 | + } |
| 281 | + } |
| 282 | + |
243 | 283 | private stripBom(content: string) { |
244 | 284 | return content.replace(/^\uFEFF/, ""); |
245 | 285 | } |
|
0 commit comments