Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ jobs:

- name: "GoReleaser"
id: go
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
uses: goreleaser/goreleaser-action@ec59f474b9834571250b370d4735c50f8e2d1e29 # v7.0.0
env:
#GITHUB_TOKEN: ${{ steps.app.outputs.token }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Expand Down
35 changes: 25 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[![GitHub Release Version](https://img.shields.io/github/v/release/smashedr/install-release?logo=github)](https://github.com/smashedr/install-release/releases)
[![GitHub Downloads](https://img.shields.io/github/downloads/smashedr/install-release/total?logo=rolldown&logoColor=white)](https://github.com/smashedr/install-release/releases/latest)
[![Asset Size](https://badges.cssnr.com/gh/release/smashedr/install-release/latest/asset/ir_Windows_x86_64.zip/size?label=asset&lucide=file-archive)](https://github.com/smashedr/install-release/releases/latest)
[![Image Size](https://badges.cssnr.com/ghcr/size/smashedr/install-release?label=docker)](https://github.com/smashedr/install-release/pkgs/container/install-release)
[![Asset Size](https://badges.cssnr.com/gh/release/smashedr/install-release/latest/asset/ir_Windows_x86_64.zip/size?label=asset&lucide=file-archive&color=darkgreen)](https://github.com/smashedr/install-release/releases/latest)
[![Image Size](https://badges.cssnr.com/ghcr/size/smashedr/install-release?label=docker&color=darkgreen)](https://github.com/smashedr/install-release/pkgs/container/install-release)
[![Go Version](https://img.shields.io/github/go-mod/go-version/smashedr/install-release?logo=go&logoColor=white&label=go)](https://github.com/smashedr/install-release/blob/master/go.mod)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=smashedr_install-release&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=smashedr_install-release)
[![Deployment Docs](https://img.shields.io/github/deployments/smashedr/install-release/docs?logo=materialformkdocs&logoColor=white&label=docs)](https://github.com/smashedr/install-release/deployments/docs)
Expand Down Expand Up @@ -125,18 +125,33 @@ Install a specific version/tag.
ir owner/repo v1.0.0
```

Install using many formats:
Specify repo in any format:

```shell
ir owner repo
ir owner/repo
ir owner repo tag
ir owner/repo tag
ir owner/repo/tag
ir owner/repo:tag
ir owner/repo@tag
ir owner[/ ]repo
ir owner[/ ]repo[@:/ ]tag
ir github.com/owner[/ ]repo[@:/ ]tag
ir https://github.com/owner[/ ]repo[@:/ ]tag
```

<details><summary>View Examples</summary>

```shell
ir smashedr bup
ir smashedr/bup
ir smashedr bup latest
ir smashedr/bup latest
ir smashedr/bup/latest
ir smashedr/bup:latest
ir smashedr/bup@latest
ir github.com/smashedr/bup
ir github.com/smashedr/bup/latest
ir https://github.com/smashedr/bup
ir https://github.com/smashedr/bup@latest
```

</details>

Skip the asset and name prompts.

```shell
Expand Down
4 changes: 4 additions & 0 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ tasks:
- go get -u
- task: tidy

actions:
desc: Actions Up
cmd: actions-up --exclude "cssnr/.*,actions/.*,docker/.*" --yes

lint:
desc: Lint
cmds:
Expand Down
6 changes: 3 additions & 3 deletions cmd/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ var infoCmd = &cobra.Command{
log.Debug("infoCmd", "args", args, "binPath", binPath, "preRelease", preRelease)

if len(args) >= 1 && strings.Contains(args[0], "/") {
owner, repo, tag, err := parseRepository(args)
repo, err := parseRepository(args)
if err != nil {
_ = cmd.Help()
log.Fatal(err)
}
log.Info("Repository", "owner", owner, "repo", repo, "tag", tag)
log.Info("Repository", "repo", repo)
client := getClient()
release, err := getRelease(client, owner, repo, tag, preRelease, true)
release, err := getRelease(client, repo, preRelease, true)
if err != nil {
log.Fatalf("Error getting release: %v", err)
}
Expand Down
128 changes: 84 additions & 44 deletions cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"io"
"io/fs"
"net/http"
"net/url"
"os"
"path/filepath"
"runtime"
Expand All @@ -30,6 +31,12 @@ var archAliases = map[string][]string{
"arm64": {"arm64", "aarch64"},
}

type Repository struct {
Owner string
Name string
Tag string
}

func runInstall(cmd *cobra.Command, args []string) error { // NOSONAR
cmd.SilenceUsage = true // set here so subcommands do not silence usage
binPath := viper.GetString("bin")
Expand All @@ -45,28 +52,29 @@ func runInstall(cmd *cobra.Command, args []string) error { // NOSONAR
return fmt.Errorf("repository must be in format: owner/repo")
}

owner, repo, tag, err := parseRepository(args)
repo, err := parseRepository(args)
if err != nil {
log.Debugf("parseRepository err: %v", err)
_ = cmd.Help()
return err
}
log.Info("Repository", "owner", owner, "repo", repo, "tag", tag)
log.Info("Repository", "repo", repo)

log.Info("runtime", "GOOS", runtime.GOOS, "GOARCH", runtime.GOARCH)

tagDisplay := tag
if tag == "" {
tagDisplay := repo.Tag
if repo.Tag == "" {
if preRelease {
tagDisplay = "pre-release"
} else {
tagDisplay = "latest"
}
}
styles.PrintKV("Repository", fmt.Sprintf("%s/%s:%s", owner, repo, tagDisplay))
styles.PrintKV("Repository", fmt.Sprintf("%s/%s:%s", repo.Owner, repo.Name, tagDisplay))

client := getClient()

release, err := getRelease(client, owner, repo, tag, preRelease, skipPrompts)
release, err := getRelease(client, repo, preRelease, skipPrompts)
if err != nil {
return fmt.Errorf("get release error: %w", err)
}
Expand Down Expand Up @@ -120,7 +128,7 @@ func runInstall(cmd *cobra.Command, args []string) error { // NOSONAR
styles.PrintKV("Asset Name", asset.GetName())

rc, _, err := client.Repositories.DownloadReleaseAsset(
context.Background(), owner, repo, asset.GetID(), http.DefaultClient,
context.Background(), repo.Owner, repo.Name, asset.GetID(), http.DefaultClient,
)
if err != nil {
return err
Expand Down Expand Up @@ -395,31 +403,31 @@ func getClient() *github.Client {
return github.NewClient(httpClient)
}

func getRelease(client *github.Client, owner, repo, tag string, pre, skip bool) (*github.RepositoryRelease, error) {
func getRelease(client *github.Client, repo Repository, pre, skip bool) (*github.RepositoryRelease, error) {
ctx := context.Background()
var release *github.RepositoryRelease
var err error
if tag != "" {
log.Debugf("client.Repositories.GetReleaseByTag: %v", tag)
release, _, err = client.Repositories.GetReleaseByTag(ctx, owner, repo, tag)
if repo.Tag != "" {
log.Debugf("client.Repositories.GetReleaseByTag: %v", repo.Tag)
release, _, err = client.Repositories.GetReleaseByTag(ctx, repo.Owner, repo.Name, repo.Tag)
} else if pre {
log.Debugf("GetLatestRelease")
release, err = getLatestRelease(client, owner, repo)
release, err = getLatestRelease(client, repo)
} else if skip {
log.Debugf("client.Repositories.GetLatestRelease")
release, _, err = client.Repositories.GetLatestRelease(ctx, owner, repo)
release, _, err = client.Repositories.GetLatestRelease(ctx, repo.Owner, repo.Name)
} else {
log.Debugf("chooseRelease")
release, err = chooseRelease(client, owner, repo, 30)
release, err = chooseRelease(client, repo, 30)
}
if err != nil {
return nil, fmt.Errorf("get release error: %w", err)
}
return release, nil
}

func getLatestRelease(client *github.Client, owner, repo string) (*github.RepositoryRelease, error) {
releases, err := getReleases(client, owner, repo, 1)
func getLatestRelease(client *github.Client, repo Repository) (*github.RepositoryRelease, error) {
releases, err := getReleases(client, repo, 1)
if err != nil {
return nil, err
}
Expand All @@ -429,17 +437,17 @@ func getLatestRelease(client *github.Client, owner, repo string) (*github.Reposi
return releases[0], nil
}

func getReleases(client *github.Client, owner, repo string, number int) ([]*github.RepositoryRelease, error) {
func getReleases(client *github.Client, repo Repository, number int) ([]*github.RepositoryRelease, error) {
ctx := context.Background()
releases, _, err := client.Repositories.ListReleases(ctx, owner, repo, &github.ListOptions{PerPage: number})
releases, _, err := client.Repositories.ListReleases(ctx, repo.Owner, repo.Name, &github.ListOptions{PerPage: number})
if err != nil {
return nil, err
}
return releases, nil
}

func chooseRelease(client *github.Client, owner, repo string, number int) (*github.RepositoryRelease, error) {
releases, err := getReleases(client, owner, repo, number)
func chooseRelease(client *github.Client, repo Repository, number int) (*github.RepositoryRelease, error) {
releases, err := getReleases(client, repo, number)
if err != nil {
return nil, fmt.Errorf("error getting releases: %w", err)
}
Expand Down Expand Up @@ -477,52 +485,84 @@ func ensureWinExt(destName string) string {
return destName
}

func parseRepository(args []string) (owner, repo, tag string, err error) {
func parseRepository(args []string) (repo Repository, err error) {
helpErr := errors.New("repository format: owner/repo[:tag]")
log.Debugf("parseRepository %v: %v", len(args), args)

switch len(args) {
case 0:
return "", "", "", helpErr
return repo, helpErr
case 1:
repository := args[0]
// Parse URL
parsed := parseURL(args[0])
log.Debug("URL", "args[0]", args[0], "parsed", parsed)
fullName := parsed
// Check for :tag @tag /tag
if idx := strings.IndexAny(args[0], ":@"); idx != -1 {
if idx := strings.IndexAny(parsed, ":@"); idx != -1 {
log.Debugf("idx: %v", idx)
repository = args[0][:idx]
tag = args[0][idx+1:]
} else if strings.Count(args[0], "/") == 2 {
split := strings.Split(args[0], "/")
fullName = parsed[:idx]
repo.Tag = parsed[idx+1:]
} else if strings.Count(parsed, "/") == 2 {
split := strings.Split(parsed, "/")
if split[2] != "" {
repository = split[0] + "/" + split[1]
tag = split[2]
fullName = split[0] + "/" + split[1]
repo.Tag = split[2]
}
}
// Set owner/repo
split := strings.Split(repository, "/")
split := strings.Split(fullName, "/")
if len(split) != 2 {
return "", "", "", helpErr
return repo, helpErr
}
owner = split[0]
repo = split[1]
repo.Owner = split[0]
repo.Name = split[1]
case 2:
if strings.Contains(args[0], "/") {
split := strings.Split(args[0], "/")
owner = split[0]
repo = split[1]
tag = args[1]
repo.Owner = split[0]
repo.Name = split[1]
repo.Tag = args[1]
} else {
owner = args[0]
repo = args[1]
repo.Owner = args[0]
repo.Name = args[1]
}
default:
owner = args[0]
repo = args[1]
tag = args[2]
repo.Owner = args[0]
repo.Name = args[1]
repo.Tag = args[2]
}

if owner == "" || repo == "" {
if repo.Owner == "" || repo.Name == "" {
log.Infof("owner/repo are blank")
return "", "", "", helpErr
return repo, helpErr
}
return
}

func parseURL(original string) string {
log.Debugf("parseURL: %v", original)
u, err := url.Parse(original)
if err != nil {
log.Debug(err)
return original
}
u.Path = strings.TrimLeft(u.Path, "/")
log.Debug("Original", "Host", u.Host, "Path", u.Path)

if u.Host == "" && strings.HasPrefix(strings.ToLower(u.Path), "github.com/") {
u.Scheme = "https"
u.Host = "github.com"
u.Path = u.Path[11:]
}

log.Debug("Updated", "Host", u.Host, "Path", u.Path)

split := strings.Split(strings.TrimRight(u.Path, "/"), "/")
log.Debugf("split: %v", split)
count := len(split)
log.Debugf("count: %v", count)
if count < 2 {
return original
}
return u.Path
}
39 changes: 27 additions & 12 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ icon: lucide/rocket

[![GitHub Release Version](https://img.shields.io/github/v/release/smashedr/install-release?logo=github)](https://github.com/smashedr/install-release/releases)
[![GitHub Downloads](https://img.shields.io/github/downloads/smashedr/install-release/total?logo=rolldown&logoColor=white)](https://github.com/smashedr/install-release/releases/latest)
[![APK Size](https://badges.cssnr.com/gh/release/smashedr/install-release/latest/asset/ir_Windows_x86_64.zip/size?label=asset&lucide=file-archive)](https://github.com/smashedr/install-release/releases/latest)
[![Image Size](https://badges.cssnr.com/ghcr/size/smashedr/install-release?label=docker)](https://github.com/smashedr/install-release/pkgs/container/install-release)
[![Asset Size](https://badges.cssnr.com/gh/release/smashedr/install-release/latest/asset/ir_Windows_x86_64.zip/size?label=asset&lucide=file-archive&color=darkgreen)](https://github.com/smashedr/install-release/releases/latest)
[![Image Size](https://badges.cssnr.com/ghcr/size/smashedr/install-release?label=docker&color=darkgreen)](https://github.com/smashedr/install-release/pkgs/container/install-release)
[![Go Version](https://img.shields.io/github/go-mod/go-version/smashedr/install-release?logo=go&logoColor=white&label=go)](https://github.com/smashedr/install-release/blob/master/go.mod)
[![GitHub Last Commit](https://img.shields.io/github/last-commit/smashedr/install-release?logo=listenhub&label=updated)](https://github.com/smashedr/install-release/pulse)
[![GitHub Repo Size](https://img.shields.io/github/repo-size/smashedr/install-release?logo=googlecloudstorage&logoColor=white&label=repo%20size)](https://github.com/smashedr/install-release?tab=readme-ov-file#readme)
Expand Down Expand Up @@ -56,8 +56,8 @@ If you run into any issues or have any questions, [support](support.md) is avail

--8<-- "docs/snippets/install.md"

[![Latest Release](https://img.shields.io/github/v/release/smashedr/install-release?style=for-the-badge&logo=github&label=latest%20version)](https://github.com/smashedr/install-release/releases/latest)
[![Latest Pre-Release](https://img.shields.io/github/v/release/smashedr/install-release?style=for-the-badge&logo=github&include_prereleases&label=pre-release)](https://github.com/smashedr/install-release/releases)
[![Latest Release](https://img.shields.io/github/v/release/smashedr/install-release?style=for-the-badge&logo=github&label=latest%20version&color=blue)](https://github.com/smashedr/install-release/releases/latest)
[![Latest Pre-Release](https://img.shields.io/github/v/release/smashedr/install-release?style=for-the-badge&logo=github&include_prereleases&label=pre-release&color=orange)](https://github.com/smashedr/install-release/releases)

## :lucide-terminal-square: Usage

Expand All @@ -79,18 +79,33 @@ Install a specific version/tag.
ir owner/repo v1.0.0
```

Install using many formats:
Specify repo in any format:

```shell
ir owner repo
ir owner/repo
ir owner repo tag
ir owner/repo tag
ir owner/repo/tag
ir owner/repo:tag
ir owner/repo@tag
ir owner[/ ]repo
ir owner[/ ]repo[@:/ ]tag
ir github.com/owner[/ ]repo[@:/ ]tag
ir https://github.com/owner[/ ]repo[@:/ ]tag
```

<details><summary>View Examples</summary>

```shell
ir smashedr bup
ir smashedr/bup
ir smashedr bup latest
ir smashedr/bup latest
ir smashedr/bup/latest
ir smashedr/bup:latest
ir smashedr/bup@latest
ir github.com/smashedr/bup
ir github.com/smashedr/bup/latest
ir https://github.com/smashedr/bup
ir https://github.com/smashedr/bup@latest
```

</details>

Skip the asset and name prompts.

```shell
Expand Down
Loading
Loading