Skip to content

Commit

Permalink
feat: Add gitHubLatestRelease template function
Browse files Browse the repository at this point in the history
fix: lint failure
  • Loading branch information
MuXiu1997 authored and twpayne committed Nov 20, 2021
1 parent 240f7ec commit 8e1d647
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 2 deletions.
23 changes: 22 additions & 1 deletion docs/REFERENCE.md
Expand Up @@ -106,6 +106,7 @@ Manage your dotfiles across multiple machines, securely.
* [`decrypt` *ciphertext*](#decrypt-ciphertext)
* [`encrypt` *plaintext*](#encrypt-plaintext)
* [`gitHubKeys` *user*](#githubkeys-user)
* [`gitHubLatestRelease` *user-repo*](#githubkeys-user-repo)
* [`gopass` *gopass-name*](#gopass-gopass-name)
* [`gopassRaw` *gopass-name*](#gopassraw-gopass-name)
* [`include` *filename*](#include-filename)
Expand Down Expand Up @@ -2044,7 +2045,7 @@ environment variables `$CHEZMOI_GITHUB_ACCESS_TOKEN`, `$GITHUB_ACCESS_TOKEN`, or
the GitHub API request, with a higher rate limit (currently 5,000 requests per
hour per user).

In practice, GitHub API rate limits are high enough that you should never need
In practice, GitHub API rate limits are high enough that you should rarely need
to set a token, unless you are sharing a source IP address with many other
GitHub users. If needed, the GitHub documentation describes how to [create a
personal access
Expand All @@ -2060,6 +2061,26 @@ token](https://docs.github.com/en/github/authenticating-to-github/creating-a-per

---

### `gitHubLatestRelease` *user-repo*

`gitHubLatestRelease` calls the GitHub API to retrieve the latest release about the given
*user-repo*, returning structured data as defined by the [GitHub Go API
bindings](https://pkg.go.dev/github.com/google/go-github/v40/github#RepositoryRelease).

Calls to `gitHubLatestRelease` are cached so calling `gitHubLatestRelease` with the same
*user-repo* will only result in one call to the GitHub API.


`gitHubLatestRelease` uses the same API request mechanism as `gitHubKeys`.

#### `gitHubLatestRelease` examples

```
{{ (gitHubLatestRelease "docker/compose").TagName }}
```

---

### `gopass` *gopass-name*

`gopass` returns passwords stored in [gopass](https://www.gopass.pw/) using the
Expand Down
1 change: 1 addition & 0 deletions internal/cmd/config.go
Expand Up @@ -404,6 +404,7 @@ func newConfig(options ...configOption) (*Config, error) {
"decrypt": c.decryptTemplateFunc,
"encrypt": c.encryptTemplateFunc,
"gitHubKeys": c.gitHubKeysTemplateFunc,
"gitHubLatestRelease": c.gitHubLatestReleaseTemplateFunc,
"gopass": c.gopassTemplateFunc,
"gopassRaw": c.gopassRawTemplateFunc,
"include": c.includeTemplateFunc,
Expand Down
44 changes: 43 additions & 1 deletion internal/cmd/githubtemplatefuncs.go
Expand Up @@ -2,12 +2,15 @@ package cmd

import (
"context"
"fmt"
"strings"

"github.com/google/go-github/v40/github"
)

type gitHubData struct {
keysCache map[string][]*github.Key
keysCache map[string][]*github.Key
latestReleaseCache map[string]map[string]*github.RepositoryRelease
}

func (c *Config) gitHubKeysTemplateFunc(user string) []*github.Key {
Expand Down Expand Up @@ -43,3 +46,42 @@ func (c *Config) gitHubKeysTemplateFunc(user string) []*github.Key {
c.gitHub.keysCache[user] = allKeys
return allKeys
}

func (c *Config) gitHubLatestReleaseTemplateFunc(userRepo string) *github.RepositoryRelease {
user, repo := parseGitHubUserRepo(userRepo)

if release := c.gitHub.latestReleaseCache[user][repo]; release != nil {
return release
}

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

gitHubClient := newGitHubClient(ctx)

release, _, err := gitHubClient.Repositories.GetLatestRelease(ctx, user, repo)
if err != nil {
returnTemplateError(err)
return nil
}

if c.gitHub.latestReleaseCache == nil {
c.gitHub.latestReleaseCache = make(map[string]map[string]*github.RepositoryRelease)
}
if c.gitHub.latestReleaseCache[user] == nil {
c.gitHub.latestReleaseCache[user] = make(map[string]*github.RepositoryRelease)
}
c.gitHub.latestReleaseCache[user][repo] = release

return release
}

func parseGitHubUserRepo(userRepo string) (string, string) {
fields := strings.SplitN(userRepo, "/", 2)
if len(fields) != 2 || fields[0] == "" || fields[1] == "" {
returnTemplateError(fmt.Errorf("%s: not a user/repo", userRepo))
return "", ""
}
user, repo := fields[0], fields[1]
return user, repo
}

0 comments on commit 8e1d647

Please sign in to comment.