release/v0.7.4
claude/smbcloud-github-app-k9641p
development
feature/apps
feature/build-release
feature/ci-docs
feature/ci-ruby-gems
feature/cicd
feature/completion
feature/dist-nuget
feature/fix-ci-sdk-pypi-rubygem
feature/fix-clippy-on-stable-channel
feature/fix-deployment-script
feature/github-email
feature/gresiq-v1
feature/project-new-structure
feature/rsync-deploy
feature/ruby-runner
feature/sdk-npm
feature/sdk-workflows
feature/smbcloud-cli-release-npm
feature/smbcloud-deploy
feature/wasm
main
release/v0.7.4
| 1 | import { existsSync, readFileSync, readdirSync } from "node:fs"; |
| 2 | import { resolve } from "node:path"; |
| 3 | |
| 4 | const repoRoot = resolve(import.meta.dirname, ".."); |
| 5 | const expectedVersion = readFileSync(resolve(repoRoot, "crates/cli/Cargo.toml"), "utf8") |
| 6 | .match(/^version\s*=\s*"([^"]+)"/m)?.[1]; |
| 7 | |
| 8 | if (!expectedVersion) { |
| 9 | throw new Error("Unable to determine the release version from crates/cli/Cargo.toml"); |
| 10 | } |
| 11 | |
| 12 | const mismatches = []; |
| 13 | |
| 14 | function read(path) { |
| 15 | return readFileSync(resolve(repoRoot, path), "utf8"); |
| 16 | } |
| 17 | |
| 18 | function check(path, actualVersion) { |
| 19 | if (actualVersion !== expectedVersion) { |
| 20 | mismatches.push(`${path}: ${actualVersion ?? "missing"} (expected ${expectedVersion})`); |
| 21 | } |
| 22 | } |
| 23 | |
| 24 | function cargoPackageVersion(path) { |
| 25 | return read(path).match(/^\[package\][\s\S]*?^version\s*=\s*"([^"]+)"/m)?.[1]; |
| 26 | } |
| 27 | |
| 28 | for (const directory of ["crates", "sdk/gems"]) { |
| 29 | const directoryPath = resolve(repoRoot, directory); |
| 30 | for (const entry of readdirSync(directoryPath, { withFileTypes: true })) { |
| 31 | if (!entry.isDirectory()) { |
| 32 | continue; |
| 33 | } |
| 34 | |
| 35 | const candidates = [ |
| 36 | `${directory}/${entry.name}/Cargo.toml`, |
| 37 | ...readdirSync(resolve(directoryPath, entry.name), { withFileTypes: true }) |
| 38 | .filter((nestedEntry) => nestedEntry.isDirectory()) |
| 39 | .map((nestedEntry) => `${directory}/${entry.name}/${nestedEntry.name}/Cargo.toml`), |
| 40 | ]; |
| 41 | |
| 42 | for (const candidate of candidates) { |
| 43 | if (existsSync(resolve(repoRoot, candidate))) { |
| 44 | const version = cargoPackageVersion(candidate); |
| 45 | if (version) { |
| 46 | check(candidate, version); |
| 47 | } |
| 48 | } |
| 49 | } |
| 50 | } |
| 51 | } |
| 52 | |
| 53 | for (const match of read("Cargo.toml").matchAll( |
| 54 | /^([\w-]+)\s*=\s*\{\s*version\s*=\s*"([^"]+)"\s*,\s*path\s*=\s*"crates\//gm, |
| 55 | )) { |
| 56 | check(`Cargo.toml workspace dependency ${match[1]}`, match[2]); |
| 57 | } |
| 58 | |
| 59 | for (const path of [ |
| 60 | "sdk/gems/auth/lib/auth/version.rb", |
| 61 | "sdk/gems/email/lib/email/version.rb", |
| 62 | "sdk/gems/model/lib/model/version.rb", |
| 63 | ]) { |
| 64 | check(path, read(path).match(/VERSION\s*=\s*['"]([^'"]+)['"]/)?.[1]); |
| 65 | } |
| 66 | |
| 67 | const npmPackage = JSON.parse(read("npm/smbcloud-cli/package.json")); |
| 68 | check("npm/smbcloud-cli/package.json", npmPackage.version); |
| 69 | |
| 70 | const sdkNpmPackage = JSON.parse(read("sdk/npm/smbcloud-auth/package.json")); |
| 71 | check("sdk/npm/smbcloud-auth/package.json", sdkNpmPackage.version); |
| 72 | |
| 73 | const npmLock = JSON.parse(read("npm/smbcloud-cli/package-lock.json")); |
| 74 | check("npm/smbcloud-cli/package-lock.json", npmLock.version); |
| 75 | check("npm/smbcloud-cli/package-lock.json packages root", npmLock.packages?.[""]?.version); |
| 76 | |
| 77 | const npmXcrsPackage = JSON.parse(read("npm/xcrs/package.json")); |
| 78 | check("npm/xcrs/package.json", npmXcrsPackage.version); |
| 79 | |
| 80 | const npmXcrsLock = JSON.parse(read("npm/xcrs/package-lock.json")); |
| 81 | check("npm/xcrs/package-lock.json", npmXcrsLock.version); |
| 82 | check("npm/xcrs/package-lock.json packages root", npmXcrsLock.packages?.[""]?.version); |
| 83 | |
| 84 | for (const path of ["server.json", "server-xcrs.json"]) { |
| 85 | const server = JSON.parse(read(path)); |
| 86 | check(path, server.version); |
| 87 | for (const [index, packageEntry] of (server.packages ?? []).entries()) { |
| 88 | check(`${path} package ${index + 1}`, packageEntry.version); |
| 89 | } |
| 90 | } |
| 91 | |
| 92 | check( |
| 93 | "nuget/smbcloud-cli/SmbCloud.Cli.csproj", |
| 94 | read("nuget/smbcloud-cli/SmbCloud.Cli.csproj").match(/<PackageVersion>([^<]+)<\/PackageVersion>/)?.[1], |
| 95 | ); |
| 96 | check( |
| 97 | "nuget/xcrs/Xcrs.csproj", |
| 98 | read("nuget/xcrs/Xcrs.csproj").match(/<PackageVersion>([^<]+)<\/PackageVersion>/)?.[1], |
| 99 | ); |
| 100 | check( |
| 101 | "sdk/gems/email/Gemfile.lock", |
| 102 | read("sdk/gems/email/Gemfile.lock").match(/smbcloud-email \(([^)]+)\)/)?.[1], |
| 103 | ); |
| 104 | |
| 105 | if (mismatches.length > 0) { |
| 106 | console.error(`Release version mismatch detected for ${expectedVersion}:`); |
| 107 | for (const mismatch of mismatches) { |
| 108 | console.error(`- ${mismatch}`); |
| 109 | } |
| 110 | process.exit(1); |
| 111 | } |
| 112 | |
| 113 | console.log(`All release artifacts use version ${expectedVersion}.`); |