From d4570472d248da0e712caf1031db21ef14ef8002 Mon Sep 17 00:00:00 2001 From: wanlin31 Date: Wed, 10 Sep 2025 17:46:52 +0000 Subject: [PATCH 1/2] Allow automatic checksums.json and version update for Dotnet and python. --- scripts/update-sdk-checksums/main.go | 159 ++++++++++-------- sdks/dotnet/BinaryInstaller.cs | 3 +- sdks/dotnet/TestServerSdk.cs | 3 +- .../python/src/test_server_sdk/checksums.json | 2 +- 4 files changed, 93 insertions(+), 74 deletions(-) diff --git a/scripts/update-sdk-checksums/main.go b/scripts/update-sdk-checksums/main.go index 1aaf35c..9705989 100644 --- a/scripts/update-sdk-checksums/main.go +++ b/scripts/update-sdk-checksums/main.go @@ -27,45 +27,48 @@ import ( "strings" ) +// --- General Project Configuration --- const ( githubOwner = "google" githubRepo = "test-server" projectName = "test-server" - - sdkDir = "sdks/typescript" - postinstallJSFile = "postinstall.js" - checksumsJSONFile = "checksums.json" - testServerVersionVar = "TEST_SERVER_VERSION" -) - -var ( - sdkPostinstallPath string - sdkChecksumsJSONPath string ) -func initPaths() error { - // Determine the project root. This assumes the script might be run - // from the project root or from within its own directory 'scripts/update-sdk-checksums'. - wd, err := os.Getwd() - if err != nil { - return fmt.Errorf("failed to get current working directory: %w", err) - } - - // If current working directory is 'scripts/update-sdk-checksums', go up two levels. - // Otherwise, assume we are already at the project root. - if filepath.Base(wd) == "update-sdk-checksums" && filepath.Base(filepath.Dir(wd)) == "scripts" { - wd = filepath.Dir(filepath.Dir(wd)) - } +// --- SDK Specific Configurations --- - sdkPostinstallPath = filepath.Join(wd, sdkDir, postinstallJSFile) - sdkChecksumsJSONPath = filepath.Join(wd, sdkDir, checksumsJSONFile) +// SDKConfig holds the unique properties for each SDK that needs updating. +type SDKConfig struct { + Name string // e.g., "TypeScript", "Python" + SDKDir string // Relative path to the SDK's directory + InstallScriptFile []string // A list of files to update with the new version + ChecksumsJSONFile string // e.g., "checksums.json" + VersionVarName string // The name of the version constant/variable in the install script +} - // Verify postinstall.js path exists to give early feedback - if _, err := os.Stat(sdkPostinstallPath); os.IsNotExist(err) { - return fmt.Errorf("postinstall.js not found at %s. Ensure you are running the script from the project root, or the script needs path adjustment", sdkPostinstallPath) - } - // checksums.json might not exist initially, which is fine for updateChecksumsJSON. - return nil +// sdksToUpdate is the list of all SDKs this script should manage. +// Add a new entry here to support another SDK. +var sdksToUpdate = []SDKConfig{ + { + Name: "TypeScript", + SDKDir: "sdks/typescript", + InstallScriptFile: []string{"postinstall.js"}, + ChecksumsJSONFile: "checksums.json", + VersionVarName: "TEST_SERVER_VERSION", + }, + { + Name: "Python", + SDKDir: "sdks/python/src/test_server_sdk", + InstallScriptFile: []string{"install.py"}, + ChecksumsJSONFile: "checksums.json", + VersionVarName: "TEST_SERVER_VERSION", + }, + { + Name: "Dotnet", + SDKDir: "sdks/dotnet", + InstallScriptFile: []string{"BinaryInstaller.cs", "TestServerSdk.cs"}, + ChecksumsJSONFile: "checksums.json", + VersionVarName: "TEST_SERVER_VERSION", + }, } func fetchChecksumsTxt(version string) (string, error) { @@ -119,24 +122,23 @@ func parseChecksumsTxt(checksumsText string) (map[string]string, error) { return checksums, nil } -func updateChecksumsJSON(newVersion string, newChecksumsMap map[string]string) error { - allChecksums := make(map[string]map[string]string) +func updateChecksumsJSON(checksumsJSONPath, newVersion string, newChecksumsMap map[string]string) error { + allChecksums := make(map[string]map[string]string) // Reset if unmarshal fails - if _, err := os.Stat(sdkChecksumsJSONPath); err == nil { // Check if file exists - existingJSON, errFileRead := os.ReadFile(sdkChecksumsJSONPath) + if _, err := os.Stat(checksumsJSONPath); err == nil { + existingJSON, errFileRead := os.ReadFile(checksumsJSONPath) if errFileRead != nil { - return fmt.Errorf("failed to read existing %s: %w", sdkChecksumsJSONPath, errFileRead) + return fmt.Errorf("failed to read existing %s: %w", checksumsJSONPath, errFileRead) } - if len(existingJSON) > 0 { // Only unmarshal if not empty + if len(existingJSON) > 0 { if errUnmarshal := json.Unmarshal(existingJSON, &allChecksums); errUnmarshal != nil { - fmt.Printf("Warning: Could not parse existing %s, will overwrite. Error: %v\n", sdkChecksumsJSONPath, errUnmarshal) - allChecksums = make(map[string]map[string]string) // Reset if unmarshal fails + fmt.Printf("Warning: Could not parse existing %s, will overwrite. Error: %v\n", checksumsJSONPath, errUnmarshal) + allChecksums = make(map[string]map[string]string) } } } else if !os.IsNotExist(err) { // If error is not "file does not exist", then it's a problem - return fmt.Errorf("failed to stat %s: %w", sdkChecksumsJSONPath, err) + return fmt.Errorf("failed to stat %s: %w", checksumsJSONPath, err) } - // If file does not exist, allChecksums remains an empty map, which is fine. allChecksums[newVersion] = newChecksumsMap updatedJSON, err := json.MarshalIndent(allChecksums, "", " ") @@ -144,47 +146,43 @@ func updateChecksumsJSON(newVersion string, newChecksumsMap map[string]string) e return fmt.Errorf("failed to marshal updated checksums JSON: %w", err) } - // Append a newline character to match the Node script's output and common file ending. updatedJSON = append(updatedJSON, '\n') - err = os.WriteFile(sdkChecksumsJSONPath, updatedJSON, 0644) + err = os.WriteFile(checksumsJSONPath, updatedJSON, 0644) if err != nil { - return fmt.Errorf("failed to write updated %s: %w", sdkChecksumsJSONPath, err) + return fmt.Errorf("failed to write updated %s: %w", checksumsJSONPath, err) } - fmt.Printf("Updated %s with checksums for version %s.\n", sdkChecksumsJSONPath, newVersion) + fmt.Printf("Updated %s with checksums for version %s.\n", checksumsJSONPath, newVersion) return nil } -func updatePostinstallVersion(newVersion string) error { - content, err := os.ReadFile(sdkPostinstallPath) +func updateVersionInFile(filePath, newVersion, varName string) error { + content, err := os.ReadFile(filePath) if err != nil { - return fmt.Errorf("failed to read %s: %w", sdkPostinstallPath, err) + return fmt.Errorf("failed to read %s: %w", filePath, err) } - re := regexp.MustCompile(`(?m)^\s*const TEST_SERVER_VERSION = .*$`) + re := regexp.MustCompile(fmt.Sprintf(`(?m)(^\s*.*\b%s\b\s*=\s*['"]).*?(['"].*$)`, varName)) if !re.Match(content) { - return fmt.Errorf("could not find '%s' constant in %s. Pattern not matched: %s", testServerVersionVar, sdkPostinstallPath, re.String()) + // If the variable isn't in the file, it's not an error. Just skip it. + fmt.Printf("Note: Did not find '%s' in %s, skipping update for this file.\n", varName, filePath) + return nil } - replacement := fmt.Sprintf("const TEST_SERVER_VERSION = '%s';", newVersion) + replacement := []byte(fmt.Sprintf(`${1}%s${2}`, newVersion)) - updatedContent := re.ReplaceAllString(string(content), replacement) + updatedContent := re.ReplaceAll(content, replacement) - err = os.WriteFile(sdkPostinstallPath, []byte(updatedContent), 0644) + err = os.WriteFile(filePath, updatedContent, 0644) if err != nil { - return fmt.Errorf("failed to write updated %s: %w", sdkPostinstallPath, err) + return fmt.Errorf("failed to write updated %s: %w", filePath, err) } - fmt.Printf("Updated %s in %s to %s.\n", testServerVersionVar, sdkPostinstallPath, newVersion) + fmt.Printf("Updated %s in %s to %s.\n", varName, filePath, newVersion) return nil } func main() { - if err := initPaths(); err != nil { - fmt.Fprintf(os.Stderr, "Error initializing paths: %v\n", err) - os.Exit(1) - } - if len(os.Args) < 2 { fmt.Fprintln(os.Stderr, "Usage: go run scripts/update-sdk-checksums/main.go ") fmt.Fprintln(os.Stderr, "Example: go run scripts/update-sdk-checksums/main.go v0.1.0") @@ -196,8 +194,7 @@ func main() { os.Exit(1) } - fmt.Printf("Updating TypeScript SDK to use test-server version: %s\n", newVersion) - + fmt.Printf("Fetching checksums for test-server version: %s\n", newVersion) checksumsText, err := fetchChecksumsTxt(newVersion) if err != nil { fmt.Fprintf(os.Stderr, "\nError fetching checksums.txt: %v\n", err) @@ -210,19 +207,39 @@ func main() { os.Exit(1) } - if err := updateChecksumsJSON(newVersion, newChecksumsMap); err != nil { - fmt.Fprintf(os.Stderr, "\nError updating %s: %v\n", sdkChecksumsJSONPath, err) - os.Exit(1) + var failedSDKs []string + + for _, sdk := range sdksToUpdate { + fmt.Printf("\n--- Updating %s SDK ---\n", sdk.Name) + + sdkChecksumsJSONPath := filepath.Join(sdk.SDKDir, sdk.ChecksumsJSONFile) + if err := updateChecksumsJSON(sdkChecksumsJSONPath, newVersion, newChecksumsMap); err != nil { + fmt.Fprintf(os.Stderr, "Error updating %s: %v\n", sdkChecksumsJSONPath, err) + failedSDKs = append(failedSDKs, sdk.Name) + continue + } + + var sdkScriptUpdateFailed bool + for _, scriptFile := range sdk.InstallScriptFile { + sdkInstallScriptPath := filepath.Join(sdk.SDKDir, scriptFile) + if err := updateVersionInFile(sdkInstallScriptPath, newVersion, sdk.VersionVarName); err != nil { + fmt.Fprintf(os.Stderr, "Error updating %s: %v\n", sdkInstallScriptPath, err) + sdkScriptUpdateFailed = true + break + } + } + + if sdkScriptUpdateFailed { + failedSDKs = append(failedSDKs, sdk.Name) + continue // Move to the next SDK + } } - if err := updatePostinstallVersion(newVersion); err != nil { - fmt.Fprintf(os.Stderr, "\nError updating %s: %v\n", sdkPostinstallPath, err) + if len(failedSDKs) > 0 { + fmt.Fprintf(os.Stderr, "\nUpdate failed for the following SDKs: %v\n", failedSDKs) os.Exit(1) } - fmt.Println("\nSuccessfully updated SDK checksums and version.") - fmt.Println("Please review the changes in:") - fmt.Printf(" - %s\n", sdkChecksumsJSONPath) - fmt.Printf(" - %s\n", sdkPostinstallPath) + fmt.Println("\nSuccessfully updated all SDK checksums and versions.") fmt.Println("Then commit them to your repository.") } diff --git a/sdks/dotnet/BinaryInstaller.cs b/sdks/dotnet/BinaryInstaller.cs index 097726e..15b760d 100644 --- a/sdks/dotnet/BinaryInstaller.cs +++ b/sdks/dotnet/BinaryInstaller.cs @@ -33,13 +33,14 @@ public static class BinaryInstaller private const string GithubOwner = "google"; private const string GithubRepo = "test-server"; private const string ProjectName = "test-server"; + public const string TEST_SERVER_VERSION = "v0.2.7"; /// /// Ensures the test-server binary for the given version is present in the specified output directory. /// It will download the release asset from GitHub, verify its SHA256 checksum, extract it, and set executable permissions. /// The checksums are read from a 'checksums.json' file expected to be embeded into the TestServerSdk.dll. /// - public static async Task EnsureBinaryAsync(string outDir, string version = "v0.2.7") + public static async Task EnsureBinaryAsync(string outDir, string version = TEST_SERVER_VERSION) { var assembly = Assembly.GetExecutingAssembly(); var resourceName = "TestServerSdk.checksums.json"; diff --git a/sdks/dotnet/TestServerSdk.cs b/sdks/dotnet/TestServerSdk.cs index 4a4fe35..eab3244 100644 --- a/sdks/dotnet/TestServerSdk.cs +++ b/sdks/dotnet/TestServerSdk.cs @@ -45,6 +45,7 @@ public class TestServerProcess private Process? _process; private readonly TestServerOptions _options; private readonly string _binaryPath; + public const string TEST_SERVER_VERSION = "v0.2.7"; public TestServerProcess(TestServerOptions options) { @@ -64,7 +65,7 @@ private string GetBinaryPath() { var targetDir = Path.GetDirectoryName(p) ?? Path.GetFullPath(Directory.GetCurrentDirectory()); Console.WriteLine($"[TestServerSdk] test-server not found at {p}. Installing into {targetDir}..."); - BinaryInstaller.EnsureBinaryAsync(targetDir, "v0.2.7").GetAwaiter().GetResult(); + BinaryInstaller.EnsureBinaryAsync(targetDir, TEST_SERVER_VERSION).GetAwaiter().GetResult(); if (File.Exists(p)) return p; throw new FileNotFoundException($"[TestServerSdk] After installation, test-server binary still not found at: {p}"); } diff --git a/sdks/python/src/test_server_sdk/checksums.json b/sdks/python/src/test_server_sdk/checksums.json index 128062b..4601657 100644 --- a/sdks/python/src/test_server_sdk/checksums.json +++ b/sdks/python/src/test_server_sdk/checksums.json @@ -79,7 +79,7 @@ "test-server_Windows_i386.zip": "6980c83e2118ed739dad53af29dc302b78ec89804f7ff7d7b5e39dcadbab3e83", "test-server_Windows_x86_64.zip": "8a4e36c8fa2d17a256a31956a3cb2851d27a30f423449911caf0b3ec76b9a602" }, - "v0.2.7": { + "v0.2.7": { "test-server_Darwin_arm64.tar.gz": "0fd90238ccf90d74daef781b972c8b864063a40563259f689444d4f0ed41fb14", "test-server_Darwin_x86_64.tar.gz": "8b7853069a9c98585a8075a90db94e73f1a769494fa5ac097c00f5e0c0630f06", "test-server_Linux_arm64.tar.gz": "5dd5ae382db835427a62f4e65d73952b6f6452b5690d6623414f343f04a0b5de", From 76f72eb84e48aae0bcfb077a74515215f0586202 Mon Sep 17 00:00:00 2001 From: wanlin31 Date: Wed, 10 Sep 2025 23:48:53 +0000 Subject: [PATCH 2/2] address comment --- scripts/update-sdk-checksums/main.go | 2 +- sdks/dotnet/tools/installer/Program.cs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/update-sdk-checksums/main.go b/scripts/update-sdk-checksums/main.go index 9705989..0d24f75 100644 --- a/scripts/update-sdk-checksums/main.go +++ b/scripts/update-sdk-checksums/main.go @@ -65,7 +65,7 @@ var sdksToUpdate = []SDKConfig{ { Name: "Dotnet", SDKDir: "sdks/dotnet", - InstallScriptFile: []string{"BinaryInstaller.cs", "TestServerSdk.cs"}, + InstallScriptFile: []string{"BinaryInstaller.cs", "TestServerSdk.cs", "tools/installer/Program.cs"}, ChecksumsJSONFile: "checksums.json", VersionVarName: "TEST_SERVER_VERSION", }, diff --git a/sdks/dotnet/tools/installer/Program.cs b/sdks/dotnet/tools/installer/Program.cs index 12ebfce..a080764 100644 --- a/sdks/dotnet/tools/installer/Program.cs +++ b/sdks/dotnet/tools/installer/Program.cs @@ -17,6 +17,7 @@ using System; using System.Threading.Tasks; using TestServerSdk; +public const string TEST_SERVER_VERSION = "v0.2.7"; // This program is just a thin wrapper around the installer logic in the SDK. if (args.Length == 0) @@ -26,7 +27,7 @@ } string outDir = args[0]; -string version = args.Length > 1 ? args[1] : "v0.2.7"; +string version = args.Length > 1 ? args[1] : TEST_SERVER_VERSION; await BinaryInstaller.EnsureBinaryAsync(outDir, version); return 0;