package github import ( "context" "net/http" "time" gh "github.com/google/go-github/v53/github" "code.icb4dc0.de/buildr/buildr/modules/state" "github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty/function" ) const DefaultAPITimeout = 30 * time.Second func GetLatestReleaseTag(ctx context.Context, cache state.Cache) function.Function { return function.New(&function.Spec{ Description: "Get tag of latest release of Github project", Params: []function.Parameter{ { Name: "owner", Description: "Owner of the repository", Type: cty.String, }, { Name: "repo", Description: "Name of the repository", Type: cty.String, }, }, VarParam: &function.Parameter{ Name: "token", Description: "GitHub API token", Type: cty.String, }, Type: function.StaticReturnType(cty.String), Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) { owner := args[0].AsString() repo := args[1].AsString() cacheKey := state.KeyOfStrings("latest_github_release", owner, repo) if cache != nil { val, _, err := cache.Get(ctx, cacheKey) if err == nil && len(val) > 0 { return cty.StringVal(string(val)), nil } } var cli *gh.Client if len(args) >= 3 && args[2].AsString() != "" && args[2].AsString() != "" { cli = gh.NewTokenClient(ctx, args[2].AsString()) } else { cli = gh.NewClient(http.DefaultClient) } if cli == nil { return cty.StringVal(""), nil } opCtx, cancel := context.WithTimeout(ctx, DefaultAPITimeout) defer cancel() release, _, err := cli.Repositories.GetLatestRelease(opCtx, owner, repo) if err != nil { return cty.Value{}, err } if cache != nil { _ = cache.Set(opCtx, cacheKey, []byte(release.GetTagName())) } return cty.StringVal(release.GetTagName()), nil }, }) }