1 import { readFileSync, writeFileSync } from "node:fs";
2 import { resolve } from "node:path";
3
4 const repoRoot = resolve(import.meta.dirname, "..");
5 const cliCargoTomlPath = resolve(repoRoot, "crates/cli/Cargo.toml");
6 const sdkNpmPackageJsonPath = resolve(repoRoot, "sdk/npm/smbcloud-auth/package.json");
7 const authGemVersionPath = resolve(repoRoot, "sdk/gems/auth/lib/auth/version.rb");
8 const authGemCargoTomlPath = resolve(repoRoot, "sdk/gems/auth/ext/auth/Cargo.toml");
9 const modelGemVersionPath = resolve(repoRoot, "sdk/gems/model/lib/model/version.rb");
10 const modelGemCargoTomlPath = resolve(repoRoot, "sdk/gems/model/ext/model/Cargo.toml");
11
12 function readText(path) {
13 return readFileSync(path, "utf8");
14 }
15
16 function writeText(path, content) {
17 writeFileSync(path, content, "utf8");
18 }
19
20 function readCargoPackageVersion(path) {
21 const match = readText(path).match(/^version\s*=\s*"([^"]+)"/m);
22
23 if (!match) {
24 throw new Error(`Unable to find version in ${path}`);
25 }
26
27 return match[1];
28 }
29
30 function replaceOrThrow(content, pattern, replacement, description) {
31 if (!pattern.test(content)) {
32 throw new Error(`Unable to update ${description}`);
33 }
34
35 return content.replace(pattern, replacement);
36 }
37
38 function updateFile(path, updater) {
39 const current = readText(path);
40 const next = updater(current);
41
42 if (next !== current) {
43 writeText(path, next);
44 return true;
45 }
46
47 return false;
48 }
49
50 const releaseVersion = readCargoPackageVersion(cliCargoTomlPath);
51 const [major = "0", minor = "0"] = releaseVersion.split(".");
52 const rubySdkRequirement = `${major}.${minor}`;
53 const updatedPaths = [];
54
55 if (
56 updateFile(sdkNpmPackageJsonPath, (content) => {
57 const parsed = JSON.parse(content);
58 parsed.version = releaseVersion;
59 return `${JSON.stringify(parsed, null, 2)}\n`;
60 })
61 ) {
62 updatedPaths.push(sdkNpmPackageJsonPath);
63 }
64
65 if (
66 updateFile(authGemVersionPath, (content) =>
67 replaceOrThrow(
68 content,
69 /VERSION\s*=\s*'[^']+'/,
70 `VERSION = '${releaseVersion}'`,
71 `${authGemVersionPath} VERSION constant`,
72 ),
73 )
74 ) {
75 updatedPaths.push(authGemVersionPath);
76 }
77
78 if (
79 updateFile(authGemCargoTomlPath, (content) => {
80 let next = replaceOrThrow(
81 content,
82 /^version\s*=\s*"[^"]+"/m,
83 `version = "${releaseVersion}"`,
84 `${authGemCargoTomlPath} package version`,
85 );
86
87 for (const crateName of [
88 "smbcloud-auth-sdk",
89 "smbcloud-model",
90 "smbcloud-network",
91 ]) {
92 next = replaceOrThrow(
93 next,
94 new RegExp(`(${crateName}\\s*=\\s*\\{\\s*version\\s*=\\s*")([^"]+)("\\s*\\})`),
95 `$1${rubySdkRequirement}$3`,
96 `${authGemCargoTomlPath} dependency ${crateName}`,
97 );
98 }
99
100 return next;
101 })
102 ) {
103 updatedPaths.push(authGemCargoTomlPath);
104 }
105
106 if (
107 updateFile(modelGemVersionPath, (content) =>
108 replaceOrThrow(
109 content,
110 /VERSION\s*=\s*'[^']+'/,
111 `VERSION = '${releaseVersion}'`,
112 `${modelGemVersionPath} VERSION constant`,
113 ),
114 )
115 ) {
116 updatedPaths.push(modelGemVersionPath);
117 }
118
119 if (
120 updateFile(modelGemCargoTomlPath, (content) =>
121 replaceOrThrow(
122 content,
123 /^version\s*=\s*"[^"]+"/m,
124 `version = "${releaseVersion}"`,
125 `${modelGemCargoTomlPath} package version`,
126 ),
127 )
128 ) {
129 updatedPaths.push(modelGemCargoTomlPath);
130 }
131
132 console.log(`Release version: ${releaseVersion}`);
133
134 if (updatedPaths.length === 0) {
135 console.log("Release metadata already in sync.");
136 } else {
137 console.log("Updated release metadata files:");
138 for (const path of updatedPaths) {
139 console.log(`- ${path}`);
140 }
141 }
142
143 console.log(`Ruby SDK dependency requirement: ${rubySdkRequirement}`);