From 710f5327c746de104a5aa7592040a160b83a390e Mon Sep 17 00:00:00 2001 From: Erik Kristensen Date: Mon, 11 Nov 2024 16:37:30 -0700 Subject: [PATCH 1/2] docs: improving docs --- README.md | 2 + docs/config.md | 10 +++ docs/index.md | 170 +++++++++++++++++++++++++++++++++++++++++++++++-- mkdocs.yml | 1 + 4 files changed, 177 insertions(+), 6 deletions(-) create mode 100644 docs/config.md diff --git a/README.md b/README.md index cba8d94..9830b53 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,8 @@ you can set aliases in your `.envrc` file for specific versions. ## Directory Structure +This is the default directory structure that distillery uses. Some of this can be overridden via the configuration. + - Binaries - Symlinks `$HOME/.distillery/bin` (this should be in your `$PATH` variable) - Binaries `$HOME/.distillery/opt` (this is where the raw binaries are stored and symlinked to) diff --git a/docs/config.md b/docs/config.md new file mode 100644 index 0000000..a2e36ac --- /dev/null +++ b/docs/config.md @@ -0,0 +1,10 @@ +# Configuration + +The default location for the configuration file is operating system dependent. YAML and TOML are supported. + +- On macOS, it is located at `~/.config/distillery.yaml` +- On Linux, it is located at `~/.config/distillery.yaml`. +- On Windows, it is located at `%APPDATA%\distillery.yaml` + +The configuration file is optional. If it is not found, the default configuration is used. + diff --git a/docs/index.md b/docs/index.md index acdf9c8..72e8f9d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,11 +1,169 @@ # Distillery +![Static Badge](https://img.shields.io/badge/Status%20-%20Beta%20-%20orange) +![GitHub Release](https://img.shields.io/github/v/release/ekristen/distillery?include_prereleases) +![GitHub Downloads (all assets, all releases)](https://img.shields.io/github/downloads/ekristen/distillery/total) +![GitHub License](https://img.shields.io/github/license/ekristen/distillery) + +[![Known Vulnerabilities](https://snyk.io/test/github/ekristen/distillery/badge.svg)](https://snyk.io/test/github/ekristen/distillery) +[![Go Report Card](https://goreportcard.com/badge/github.com/ekristen/distillery)](https://goreportcard.com/report/github.com/ekristen/distillery) + +Most things are working, this project follows semantic commits and semantic releases, any breaking +changes will result in new major versions. + ## Overview -Without a doubt, [homebrew](https://brew.sh) has had a major impact on the macOS ecosystem. It has made it easy to -install software and keep it up to date. However, it is not without its flaws. It has been around for 15 years and -while it has evolved over time, its core technology hasn't changed, and 15 year is an eternity in the tech world. +Without a doubt, [homebrew](https://brew.sh) has had a major impact on the macOS and even the linux ecosystem. It has made it easy +to install software and keep it up to date. However, it has been around for 15+ years and while it has evolved over time, +its core technology really hasn't changed, and 15+ years is an eternity in the tech world. Languages like [Go](https://golang.org) +and [Rust](https://www.rust-lang.org) have made it easy to compile binaries and distribute them without complicated +installers or dependencies. **I love homebrew**, but I think there's room for another tool. + +**dist**illery is a tool that is designed to make it easy to install binaries on your system from multiple different +sources. It is designed to be simple and easy to use. It is **NOT** designed to be a package manager or handle complex +dependencies, that's where homebrew shines. + +The goal of this project is to install binaries by leverage the collective power of all the developers out there that +are using tools like [goreleaser](https://goreleaser.com/) and [cargo-dist](https://github.com/axodotdev/cargo-dist) +and many others to pre-compile their software and put their binaries up on GitHub or GitLab. + +## Features + +- Simple to install binaries on your system from multiple sources +- No reliance on a centralized repository of metadata like package managers +- Support multiple platforms and architectures +- Support private repositories (this was a feature removed from homebrew) +- Support checksum verifications (if they exist) +- Support signatures verifications (if they exist) (**not implemented yet**) + +## Install + +## MacOS/Linux + +1. Set your path `export PATH=$HOME/.distillery/bin:$PATH` +2. Download the latest release from the [releases page](https://github.com/ekristen/distillery/releases) +3. Extract and Run `./dist install ekristen/distillery` +4. Delete `./dist` and the .tar.gz, now use `dist` normally +5. Run `dist install owner/repo` to install a binary from GitHub Repository + +## Windows + +1. [Set Your Path](#set-your-path) +2. Download the latest release from the [releases page](https://github.com/ekristen/distillery/releases) +3. Extract and Run `.\dist.exe install ekristen/distillery` +4. Delete `.\dist.exe` and the .zip, now use `dist` normally +5. Run `dist install owner/repo` to install a binary from GitHub Repository + +### Set Your Path + +#### For Current Session + +```powershell +$env:Path = "C:\Users\\.distillery\bin;" + $env:Path +``` + +#### For Current User + +```powershell +[Environment]::SetEnvironmentVariable("Path", "C:\Users\\.distillery\bin;" + $env:Path, [EnvironmentVariableTarget]::User) +``` + +### For System + +```powershell +[Environment]::SetEnvironmentVariable("Path", "C:\Users\\.distillery\bin;" + $env:Path, [EnvironmentVariableTarget]::Machine) +``` + +### Uninstall + +1. Run `dist info` +2. Remove the directories listed under the cleanup section + +### Examples + +Install a specific version of a tool using `@version` syntax. `github` is the default scope, this implies +`github/ekristen/aws-nuke` + +```console +dist install ekristen/aws-nuke@3.16.0 +``` + +Install a tool from a specific owner and repository, in this case hashicorp. This will install the latest version. +However, because hashicorp hosts their binaries on their own domain, distillery has special handling for obtaining +the latest version from releases.hashicorp.com instead of GitHub. + +```console +dist install hashicorp/terraform +``` + +Install a binary from GitLab. +```console +dist install gitlab/gitlab-org/gitlab-runner +``` + +Often times installing from GitHub or GitLab is sufficient, but if you are on a MacOS system and Homebrew +has the binary you want, you can install it using the `homebrew` scope. I would generally still recommend just +installing from GitHub or GitLab directly. + +```console +dist install homebrew/opentofu +``` + +## Supported Platforms + +- GitHub +- GitLab +- Homebrew (binaries only, if anything has a dependency, it will not work at this time) +- Hashicorp (special handling for their releases, pointing to github repos will automatically pass through) + +### Authentication + +Distillery supports authentication for GitHub and GitLab. There are CLI options to pass in a token, but the preferred +method is to set the `DISTILLERY_GITHUB_TOKEN` or `DISTILLERY_GITLAB_TOKEN` environment variables using a tool like +[direnv](https://direnv.net/). + +## Behaviors + +- Allow for multiple versions of a binary using `tool@version` syntax +- Running installation for any version will automatically update the default symlink to that version (i.e. switching versions) +- Caching of HTTP calls where possible (GitHub primarily) +- Caching of downloads + +### Running install always updates default symlink + +**Note:** this might change before exiting beta. + +Whenever you run install the default symlink will always be updated to whatever version you specify. This is to make +it easy to switch versions. + +### Multiple Versions + +Every time you run install it will by default seek out the latest version, it will not remove any other versions. All +versions are symlinked with the suffix `@version` this means you can have multiple versions installed at the same time. + +It also means you can call any version any time using the `@version` syntax or if you are using something like [direnv](https://direnv.net/) +you can set aliases in your `.envrc` file for specific versions. + +## Directory Structure + +- Binaries + - Symlinks `$HOME/.distillery/bin` (this should be in your `$PATH` variable) + - Binaries `$HOME/.distillery/opt` (this is where the raw binaries are stored and symlinked to) + - `source/owner/repo/version/` + - example: `github/ekristen/aws-nuke/v2.15.0/aws-nuke` + - example: `hashicorp/terraform/v0.14.7/terraform` +- Cache directory (downloads, http caching) + - MacOS `$HOME/Library/Caches/distillery` + - Linux `$HOME/.cache/distillery` + - Windows `$HOME/AppData/Local/distillery` + +### Caching + +At the moment there are two discrete caches. One for HTTP requests and one for downloads. The HTTP cache is used to +store the ETag and Last-Modified headers from the server to determine if the file has changed. The download cache is +used to store the downloaded file. The download cache is not used to determine if the file has changed, that is done +by the HTTP cache. + +If you need to delete your cache simply run `dist info` identify the cache directory and remove it. -The goal of this project is to leverage the collective power of all the developers out there that are using tools like -[goreleaser](https://goreleaser.com/) and [cargo-dist](https://github.com/axodotdev/cargo-dist) and many others to -pre-compile their software and put their binaries up on GitHub or GitLab and install the binaries. +**Note:** I may add a cache clear command in the future. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index b85cb68..b58ecb6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -66,3 +66,4 @@ markdown_extensions: # Page tree nav: - Home: index.md + - Config: config.md From 006d86ce227865649b50720294f1088f26a11b32 Mon Sep 17 00:00:00 2001 From: Erik Kristensen Date: Mon, 11 Nov 2024 16:39:35 -0700 Subject: [PATCH 2/2] docs: improving docs --- pkg/commands/info/info.go | 13 ++++++++++++- pkg/commands/install/source.go | 6 +++--- pkg/config/alias.go | 6 +++--- pkg/config/config.go | 7 +++++++ pkg/source/gitlab.go | 4 +++- 5 files changed, 28 insertions(+), 8 deletions(-) diff --git a/pkg/commands/info/info.go b/pkg/commands/info/info.go index 91d0e18..b4eace7 100644 --- a/pkg/commands/info/info.go +++ b/pkg/commands/info/info.go @@ -2,7 +2,9 @@ package info import ( "fmt" + "os" "runtime" + "strings" "github.com/apex/log" "github.com/urfave/cli/v2" @@ -17,7 +19,8 @@ func Execute(c *cli.Context) error { return err } - log.Infof("distillery/%s", common.AppVersion.Summary) + log.Info("version information") + log.Infof(" distillery/%s", common.AppVersion.Summary) fmt.Println("") log.Infof("system information") log.Infof(" os: %s", runtime.GOOS) @@ -34,6 +37,14 @@ func Execute(c *cli.Context) error { log.Warnf(" - %s", cfg.BinPath) log.Warnf(" - %s", cfg.GetOptPath()) + path := os.Getenv("PATH") + if !strings.Contains(path, cfg.BinPath) { + fmt.Println("") + log.Warnf("Problem: distillery will not work correctly") + log.Warnf(" - %s is not in your PATH", cfg.BinPath) + fmt.Println("") + } + return nil } diff --git a/pkg/commands/install/source.go b/pkg/commands/install/source.go index 29e1e56..5cd8365 100644 --- a/pkg/commands/install/source.go +++ b/pkg/commands/install/source.go @@ -86,7 +86,7 @@ func NewSource(src string, opts *provider.Options) (provider.ISource, error) { / Repo: parts[1], Version: version, }, nil - case "gitlab": + case source.GitLabSource: return &source.GitLab{ Provider: provider.Provider{Options: opts, OSConfig: detectedOS}, Owner: parts[0], @@ -97,7 +97,7 @@ func NewSource(src string, opts *provider.Options) (provider.ISource, error) { / return nil, fmt.Errorf("invalid install source, expect alias or format of owner/repo or owner/repo@version") } else if len(parts) >= 3 { - if strings.HasPrefix(parts[0], "github") { + if strings.HasPrefix(parts[0], source.GitHubSource) { if parts[1] == source.HashicorpSource { return &source.Hashicorp{ Provider: provider.Provider{Options: opts, OSConfig: detectedOS}, @@ -123,7 +123,7 @@ func NewSource(src string, opts *provider.Options) (provider.ISource, error) { / Repo: parts[2], Version: version, }, nil - } else if strings.HasPrefix(parts[0], "gitlab") { + } else if strings.HasPrefix(parts[0], source.GitLabSource) { return &source.GitLab{ Provider: provider.Provider{Options: opts, OSConfig: detectedOS}, Owner: parts[1], diff --git a/pkg/config/alias.go b/pkg/config/alias.go index 1b10ecc..17f742e 100644 --- a/pkg/config/alias.go +++ b/pkg/config/alias.go @@ -9,9 +9,9 @@ import ( type Aliases map[string]*Alias type Alias struct { - Name string `yaml:"name" toml:"name"` - Version string `yaml:"version" toml:"version"` - Bin string `yaml:"bin" toml:"bin"` + Name string `yaml:"name" toml:"name"` + Version string `yaml:"version" toml:"version"` + Flags map[string]bool `yaml:"flags" toml:"flags"` } func (a *Alias) UnmarshalYAML(unmarshal func(interface{}) error) error { diff --git a/pkg/config/config.go b/pkg/config/config.go index 00d33a7..a8d22fa 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -13,6 +13,7 @@ import ( "github.com/ekristen/distillery/pkg/common" ) +// Config - the configuration for distillery type Config struct { // Path - path to store the configuration files, this path is set by default based on the operating system type // and your user's home directory. Typically, this is set to $HOME/.distillery @@ -40,22 +41,27 @@ type Config struct { Language string `yaml:"language" toml:"language"` } +// GetCachePath - get the cache path func (c *Config) GetCachePath() string { return filepath.Join(c.CachePath, common.NAME) } +// GetMetadataPath - get the metadata path func (c *Config) GetMetadataPath() string { return filepath.Join(c.CachePath, common.NAME, "metadata") } +// GetDownloadsPath - get the downloads path func (c *Config) GetDownloadsPath() string { return filepath.Join(c.CachePath, common.NAME, "downloads") } +// GetOptPath - get the opt path func (c *Config) GetOptPath() string { return filepath.Join(c.Path, "opt") } +// GetAlias - get an alias by name func (c *Config) GetAlias(name string) *Alias { if c.Aliases == nil { return nil @@ -70,6 +76,7 @@ func (c *Config) GetAlias(name string) *Alias { return nil } +// MkdirAll - create all the directories func (c *Config) MkdirAll() error { paths := []string{c.BinPath, c.GetOptPath(), c.CachePath, c.GetMetadataPath(), c.GetDownloadsPath()} diff --git a/pkg/source/gitlab.go b/pkg/source/gitlab.go index f863de2..bcd87e4 100644 --- a/pkg/source/gitlab.go +++ b/pkg/source/gitlab.go @@ -14,6 +14,8 @@ import ( "github.com/ekristen/distillery/pkg/provider" ) +const GitLabSource = "gitlab" + type GitLab struct { provider.Provider @@ -27,7 +29,7 @@ type GitLab struct { } func (s *GitLab) GetSource() string { - return "gitlab" + return GitLabSource } func (s *GitLab) GetOwner() string { return s.Owner