/ scripts / syncLiteLLMVersion.js
syncLiteLLMVersion.js
  1  #!/usr/bin/env node
  2  const fs = require("fs")
  3  const path = require("path")
  4  
  5  const repoRoot = path.resolve(__dirname, "..")
  6  const versionConfigPath = path.join(repoRoot, "hosting", "litellm-version.json")
  7  
  8  function readJson(filePath) {
  9    return JSON.parse(fs.readFileSync(filePath, "utf8"))
 10  }
 11  
 12  function updateFile(filePath, updater) {
 13    const original = fs.readFileSync(filePath, "utf8")
 14    const updated = updater(original)
 15  
 16    return {
 17      changed: original !== updated,
 18      updated,
 19    }
 20  }
 21  
 22  function required(value, label) {
 23    if (!value || typeof value !== "string") {
 24      throw new Error(`Invalid ${label}`)
 25    }
 26    return value
 27  }
 28  
 29  function replaceRequired(content, pattern, replacement, filePath) {
 30    if (!pattern.test(content)) {
 31      throw new Error(`Could not find target pattern in ${filePath}`)
 32    }
 33    return content.replace(pattern, replacement)
 34  }
 35  
 36  function main() {
 37    const checkOnly = process.argv.includes("--check")
 38    const versionConfig = readJson(versionConfigPath)
 39    const version = required(versionConfig.version, "version")
 40    const channel = required(versionConfig.channel, "channel")
 41  
 42    const imageTag = `main-v${version}-${channel}`
 43  
 44    const updates = [
 45      {
 46        path: path.join(repoRoot, "hosting", "single", "Dockerfile"),
 47        update: content =>
 48          replaceRequired(
 49            content,
 50            /ARG LITELLM_PYPI_VERSION=.*/,
 51            `ARG LITELLM_PYPI_VERSION=${version}`,
 52            "hosting/single/Dockerfile"
 53          ),
 54      },
 55      {
 56        path: path.join(repoRoot, "hosting", "docker-compose.yaml"),
 57        update: content =>
 58          replaceRequired(
 59            content,
 60            /image:\s*(?:docker\.litellm\.ai|ghcr\.io)\/berriai\/litellm:[^\s\n]+/,
 61            `image: ghcr.io/berriai/litellm:${imageTag}`,
 62            "hosting/docker-compose.yaml"
 63          ),
 64      },
 65      {
 66        path: path.join(repoRoot, "hosting", "docker-compose.build.yaml"),
 67        update: content =>
 68          replaceRequired(
 69            content,
 70            /image:\s*(?:docker\.litellm\.ai|ghcr\.io)\/berriai\/litellm:[^\s\n]+/,
 71            `image: ghcr.io/berriai/litellm:${imageTag}`,
 72            "hosting/docker-compose.build.yaml"
 73          ),
 74      },
 75      {
 76        path: path.join(repoRoot, "hosting", "docker-compose.dev.yaml"),
 77        update: content =>
 78          replaceRequired(
 79            content,
 80            /image:\s*(?:docker\.litellm\.ai|ghcr\.io)\/berriai\/litellm:[^\s\n]+/,
 81            `image: ghcr.io/berriai/litellm:${imageTag}`,
 82            "hosting/docker-compose.dev.yaml"
 83          ),
 84      },
 85      {
 86        path: path.join(repoRoot, "charts", "budibase", "values.yaml"),
 87        update: content =>
 88          replaceRequired(
 89            content,
 90            /image:\s*ghcr\.io\/berriai\/litellm:[^\s\n]+/,
 91            `image: ghcr.io/berriai/litellm:${imageTag}`,
 92            "charts/budibase/values.yaml"
 93          ),
 94      },
 95    ]
 96  
 97    const changed = []
 98    for (const item of updates) {
 99      const result = updateFile(item.path, item.update)
100      if (result.changed) {
101        if (!checkOnly) {
102          fs.writeFileSync(item.path, result.updated)
103        }
104        changed.push(path.relative(repoRoot, item.path))
105      }
106    }
107  
108    console.log(
109      `LiteLLM version ${
110        checkOnly ? "check" : "sync"
111      }: version=${version}, channel=${channel}`
112    )
113    if (changed.length > 0) {
114      const header = checkOnly ? "Out-of-sync files" : "Updated files"
115      console.log(`${header}:\n${changed.join("\n")}`)
116      if (checkOnly) {
117        process.exit(1)
118      }
119    } else {
120      console.log(checkOnly ? "All files are in sync" : "No files changed")
121    }
122  }
123  
124  main()