checkUpstreamProvenance fetches the skill's SKILL.md via the contents API to check if it contains github-repo metadata pointing to a different repository, indicating the skill was re-published from an upstream source. In interactive mode, the user is asked whether to install from the re-publisher or
(opts *InstallOptions, client *api.Client, hostname string, skill discovery.Skill, commitSHA string)
| 1297 | // installs from the re-publisher. |
| 1298 | // Returns (repo to redirect to, whether upstream was detected, error). |
| 1299 | func checkUpstreamProvenance(opts *InstallOptions, client *api.Client, hostname string, skill discovery.Skill, commitSHA string) (ghrepo.Interface, bool, error) { |
| 1300 | u, err := safeurl.JoinPath("repos", opts.repo.RepoOwner(), opts.repo.RepoName(), "contents", skill.Path+"/SKILL.md") |
| 1301 | if err != nil { |
| 1302 | return nil, false, err |
| 1303 | } |
| 1304 | u.SetQuery("ref", commitSHA) |
| 1305 | var fileResp struct { |
| 1306 | Content string `json:"content"` |
| 1307 | Encoding string `json:"encoding"` |
| 1308 | } |
| 1309 | if err := client.REST(hostname, "GET", u.String(), nil, &fileResp); err != nil { |
| 1310 | return nil, false, nil //nolint:nilerr // best-effort check; failing to fetch is not fatal |
| 1311 | } |
| 1312 | if fileResp.Encoding != "base64" { |
| 1313 | return nil, false, nil |
| 1314 | } |
| 1315 | decoded, decodeErr := io.ReadAll(base64.NewDecoder(base64.StdEncoding, strings.NewReader(fileResp.Content))) |
| 1316 | if decodeErr != nil { |
| 1317 | return nil, false, nil //nolint:nilerr // best-effort; decode failure is not fatal |
| 1318 | } |
| 1319 | content := string(decoded) |
| 1320 | |
| 1321 | result, parseErr := frontmatter.Parse(content) |
| 1322 | if parseErr != nil || result.Metadata.Meta == nil { |
| 1323 | //nolint:nilerr // unparsable frontmatter means no upstream to detect |
| 1324 | return nil, false, nil |
| 1325 | } |
| 1326 | |
| 1327 | existingRepo, _ := result.Metadata.Meta["github-repo"].(string) |
| 1328 | if existingRepo == "" { |
| 1329 | return nil, false, nil |
| 1330 | } |
| 1331 | |
| 1332 | currentRepoURL := source.BuildRepoURL(hostname, opts.repo.RepoOwner(), opts.repo.RepoName()) |
| 1333 | if existingRepo == currentRepoURL { |
| 1334 | return nil, false, nil |
| 1335 | } |
| 1336 | |
| 1337 | upstreamRepo, parseErr := source.ParseRepoURL(existingRepo) |
| 1338 | if parseErr != nil { |
| 1339 | //nolint:nilerr // invalid repo URL means we can't redirect; install normally |
| 1340 | return nil, false, nil |
| 1341 | } |
| 1342 | |
| 1343 | cs := opts.IO.ColorScheme() |
| 1344 | upstreamLabel := ghrepo.FullName(upstreamRepo) |
| 1345 | repoSource := ghrepo.FullName(opts.repo) |
| 1346 | |
| 1347 | fmt.Fprintf(opts.IO.ErrOut, "%s This skill was originally published in %s\n", cs.WarningIcon(), upstreamLabel) |
| 1348 | |
| 1349 | if opts.Upstream { |
| 1350 | fmt.Fprintf(opts.IO.ErrOut, "Redirecting install to %s...\n", upstreamLabel) |
| 1351 | return upstreamRepo, true, nil |
| 1352 | } |
| 1353 | |
| 1354 | if !opts.IO.CanPrompt() { |
| 1355 | fmt.Fprintf(opts.IO.ErrOut, " Installing from %s (use --upstream or interactive mode to choose upstream)\n", repoSource) |
| 1356 | return nil, true, nil |
no test coverage detected