Skip to content

Commit

Permalink
Merge pull request #69 from ekristen/beta-docs
Browse files Browse the repository at this point in the history
docs: improving docs
  • Loading branch information
ekristen authored Nov 11, 2024
2 parents 4301b7d + 006d86c commit 2c1b96e
Show file tree
Hide file tree
Showing 9 changed files with 205 additions and 14 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
10 changes: 10 additions & 0 deletions docs/config.md
Original file line number Diff line number Diff line change
@@ -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.

170 changes: 164 additions & 6 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -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\<username>\.distillery\bin;" + $env:Path
```

#### For Current User

```powershell
[Environment]::SetEnvironmentVariable("Path", "C:\Users\<username>\.distillery\bin;" + $env:Path, [EnvironmentVariableTarget]::User)
```

### For System

```powershell
[Environment]::SetEnvironmentVariable("Path", "C:\Users\<username>\.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/[email protected]
```

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/<binaries>`
- 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.
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,4 @@ markdown_extensions:
# Page tree
nav:
- Home: index.md
- Config: config.md
13 changes: 12 additions & 1 deletion pkg/commands/info/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package info

import (
"fmt"
"os"
"runtime"
"strings"

"github.com/apex/log"
"github.com/urfave/cli/v2"
Expand All @@ -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)
Expand All @@ -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
}

Expand Down
6 changes: 3 additions & 3 deletions pkg/commands/install/source.go
Original file line number Diff line number Diff line change
Expand Up @@ -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],
Expand All @@ -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},
Expand All @@ -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],
Expand Down
6 changes: 3 additions & 3 deletions pkg/config/alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 7 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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()}

Expand Down
4 changes: 3 additions & 1 deletion pkg/source/gitlab.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import (
"github.com/ekristen/distillery/pkg/provider"
)

const GitLabSource = "gitlab"

type GitLab struct {
provider.Provider

Expand All @@ -27,7 +29,7 @@ type GitLab struct {
}

func (s *GitLab) GetSource() string {
return "gitlab"
return GitLabSource
}
func (s *GitLab) GetOwner() string {
return s.Owner
Expand Down

0 comments on commit 2c1b96e

Please sign in to comment.