scripts/download-deps.go (158 lines of code) (raw):

//go:build ignore package main import ( "bufio" "encoding/json" "fmt" "io" "log" "net/http" "os" "path/filepath" "regexp" "strings" ) const buildserver = "https://buildserver.labs.intellij.net" var tcToken string type artifact struct { buildTypeID string pattern string subPath string destPath string } var toolingArtifacts = []artifact{ {"StaticAnalysis_Build_UiAndConverter", "intellij-report-converter.jar", "", "internal/tooling/intellij-report-converter.jar"}, } var clangArtifacts = []artifact{ {"ijplatform_master_CIDR_ExternalTools_VanillaClangTidyAll", `clang-tidy-[^"]*-linux-x64\.tar\.gz`, "", "clang/clang-tidy-linux-amd64.tar.gz"}, {"ijplatform_master_CIDR_ExternalTools_VanillaClangTidyAll", `clang-tidy-[^"]*-linux-aarch64\.tar\.gz`, "", "clang/clang-tidy-linux-arm64.tar.gz"}, {"ijplatform_master_CIDR_ExternalTools_VanillaClangTidyAll", `clang-tidy-[^"]*-mac-x64\.tar\.gz`, "", "clang/clang-tidy-darwin-amd64.tar.gz"}, {"ijplatform_master_CIDR_ExternalTools_VanillaClangTidyAll", `clang-tidy-[^"]*-mac-aarch64\.tar\.gz`, "", "clang/clang-tidy-darwin-arm64.tar.gz"}, {"ijplatform_master_CIDR_ExternalTools_VanillaClangTidyAll", `clang-tidy-[^"]*-win-x64\.zip`, "", "clang/clang-tidy-windows-amd64.zip"}, {"ijplatform_master_CIDR_ExternalTools_VanillaClangTidyAll", `clang-tidy-[^"]*-win-aarch64\.zip`, "", "clang/clang-tidy-windows-arm64.zip"}, } var cdnetArtifacts = []artifact{ {"ijplatform_master_Net_PostCompile_TriggerAllInstallers", `JetBrains\.ReSharper\.GlobalTools\.[^"]*\.nupkg`, "Artifacts.InstallersPortablesZips", "cdnet/clt.zip"}, } func main() { repoRoot := findRepoRoot() loadEnv(filepath.Join(repoRoot, ".env")) tcToken = os.Getenv("TEAMCITY_TOKEN") if tcToken == "" { log.Fatal("TEAMCITY_TOKEN not set (check .env file)") } log.Printf("Downloading dependencies to %s", repoRoot) var all []artifact all = append(all, toolingArtifacts...) all = append(all, clangArtifacts...) all = append(all, cdnetArtifacts...) for _, a := range all { dest := filepath.Join(repoRoot, a.destPath) if err := download(a, dest); err != nil { log.Printf("WARN: %s: %v", a.destPath, err) } } log.Println("Done") } func loadEnv(path string) { f, err := os.Open(path) if err != nil { return } defer f.Close() scanner := bufio.NewScanner(f) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if line == "" || strings.HasPrefix(line, "#") { continue } line = strings.TrimPrefix(line, "export ") if k, v, ok := strings.Cut(line, "="); ok { if os.Getenv(k) == "" { os.Setenv(k, v) } } } } func download(a artifact, dest string) error { artifactName, err := findArtifact(a.buildTypeID, a.subPath, a.pattern) if err != nil { return err } urlPath := artifactName if a.subPath != "" { urlPath = a.subPath + "/" + artifactName } url := fmt.Sprintf("%s/app/rest/builds/buildType:%s,status:SUCCESS,count:1/artifacts/content/%s", buildserver, a.buildTypeID, urlPath) log.Printf("Downloading %s", a.destPath) if err := os.MkdirAll(filepath.Dir(dest), 0755); err != nil { return err } req, _ := http.NewRequest("GET", url, nil) req.Header.Set("Authorization", "Bearer "+tcToken) resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { body, _ := io.ReadAll(resp.Body) return fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body)) } f, err := os.Create(dest) if err != nil { return err } defer f.Close() _, err = io.Copy(f, resp.Body) return err } func findArtifact(buildTypeID, subPath, pattern string) (string, error) { url := fmt.Sprintf("%s/app/rest/builds/buildType:%s,status:SUCCESS,count:1/artifacts", buildserver, buildTypeID) if subPath != "" { url += "/children/" + subPath } req, _ := http.NewRequest("GET", url, nil) req.Header.Set("Accept", "application/json") req.Header.Set("Authorization", "Bearer "+tcToken) resp, err := http.DefaultClient.Do(req) if err != nil { return "", err } defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) if resp.StatusCode != http.StatusOK { return "", fmt.Errorf("HTTP %d: %s", resp.StatusCode, string(body)) } var data struct { File []struct { Name string `json:"name"` } `json:"file"` } if err := json.Unmarshal(body, &data); err != nil { re := regexp.MustCompile(`"` + pattern + `"`) if match := re.FindString(string(body)); match != "" { return strings.Trim(match, `"`), nil } return "", fmt.Errorf("no match for %s", pattern) } re := regexp.MustCompile(pattern) for _, f := range data.File { if re.MatchString(f.Name) { return f.Name, nil } } return "", fmt.Errorf("no match for %s", pattern) } func findRepoRoot() string { dir, _ := os.Getwd() for { if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil { return dir } parent := filepath.Dir(dir) if parent == dir { log.Fatal("Could not find repository root (no go.mod found)") } dir = parent } }