GoFish, the Package Manager 🐠

GoFish is a cross-platform systems package manager, bringing the ease of use of Homebrew to Linux and Windows.

$ gofish install go
==> Installing go...
🐠  go 1.10.1: installed in 2.307602197s

About

GoFish works across all three major operating systems (Windows, MacOS, and Linux). It installs packages into its own directory and symlinks their files into /usr/local (or C:\ProgramData for Windows). You can think of it as the cross-platform Homebrew.

$ cd /usr/local/Fish
$ find Barrel
Barrel
Barrel/helm
Barrel/helm/2.8.2
Barrel/helm/2.8.2/darwin-amd64
Barrel/helm/2.8.2/darwin-amd64/LICENSE
Barrel/helm/2.8.2/darwin-amd64/README.md
Barrel/helm/2.8.2/darwin-amd64/helm
$ ls -l /usr/local/bin | grep helm
helm -> ../Fish/Barrel/helm/2.8.2/darwin-amd64/helm

GoFish takes the ideas of Homebrew Formulas to the next level by installing pre-packaged tools. GoFish’s fish food are simple Lua scripts:

local name = "helm"
local version = "2.8.2"

food = {
    name = name,
    description = "The Kubernetes Package Manager",
    homepage = "https://github.com/kubernetes/helm",
    version = version,
    packages = {
        {
            os = "darwin",
            arch = "amd64",
            url = "https://storage.googleapis.com/kubernetes-helm/helm-v" .. version .. "-darwin-amd64.tar.gz",
            sha256 = "a0a8cf462080b2bc391f38b7cf617618b189cdef9f071c06fa0068c2418cc413",
            resources = {
                {
                    path = "darwin-amd64/" .. name,
                    installpath = "bin/" .. name,
                    executable = true
                }
            }
        },
        {
            os = "linux",
            arch = "amd64",
            url = "https://storage.googleapis.com/kubernetes-helm/helm-v" .. version .. "-linux-amd64.tar.gz",
            sha256 = "614b5ac79de4336b37c9b26d528c6f2b94ee6ccacb94b0f4b8d9583a8dd122d3",
            resources = {
                {
                    path = "linux-amd64/" .. name,
                    installpath = "bin/" .. name,
                    executable = true
                }
            }
        },
        {
            os = "windows",
            arch = "amd64",
            url = "https://storage.googleapis.com/kubernetes-helm/helm-v" .. version .. "-windows-amd64.tar.gz",
            sha256 = "cb6ea5d60f202c752f1f0777e4bebd98c619a2c18e52468df7a302e783216f23",
            resources = {
                {
                    path = "windows-amd64\\" .. name .. ".exe",
                    installpath = "bin\\" .. name .. ".exe"
                }
            }
        }
    }
}

Install

MacOS/Linux:

curl -fsSL https://raw.githubusercontent.com/fishworks/gofish/master/scripts/install.sh | bash

Windows (Powershell, as Administrator):

Set-ExecutionPolicy Bypass -Scope Process -Force
iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/fishworks/gofish/master/scripts/install.ps1'))

After running one of the install scripts:

gofish init

Once you have GoFish up and running, you can upgrade at any time using

gofish install gofish

Then:

gofish upgrade gofish

Please inspect the install scripts prior to running them to ensure your OS’s safety. I trust my own code, but you should verify the security and contents of any script from the internet you are not familiar with.

FAQ

How do I get started?

After running one of the install scripts:

gofish init

How do I update my local packages?

First update the rigs:

gofish update

You can now find out what is outdated with:

gofish rotten

Upgrade everything with:

gofish upgrade

Or upgrade a particular fish food with:

gofish upgrade <food>

For example, to upgrade GoFish:

gofish upgrade gofish

How do I uninstall old versions of a fish food?

By default, GoFish does not uninstall old versions of fish food, so over time you will accumulate old versions. To remove them, simply use:

gofish cleanup <food>

or clean up everything at once:

gofish cleanup

or to see what would be cleaned up:

gofish cleanup -n

Where does stuff get downloaded?

GoFish stores downloaded files to either ~/Library/Caches/Fish for macOS, ~/.fish for Linux, and %APPDATA%/Local/Fish for Windows. See gofish tank to know more about GoFish’s environment.

Why can’t you support Homebrew formulas?

GoFish aims to work across all three major operating systems. Most Homebrew formulas in core work based on compiling a package from source and symlinking the result in other parts of /usr/local. Because compiling from source differs vastly between all three operating systems, it didn’t feel right to provide such a system for the initial release.

However, certain formulae provide pre-compiled versions known as bottles, which are available at https://bintray.com/homebrew/bottles. GoFish can use these pre-compiled bottles to get some compatibility with Homebrew.

I have packages I installed with Homebrew, however I want to use GoFish instead. How?

brew unlink foo
gofish install foo

How can I add something to the FAQ?

Something missing? Feel like making a contribution?

Troubleshooting

If you feel something’s missing from the troubleshooting guide, it’s a great opportunity to make a contribution!

Nothing has been added to the troubleshooting guide yet. Feel like making a contribution?

Fish Food Cookbook

Fish food is a package definition written in Lua. It can be created with gofish create <food>. Fish food use the Lua runtime to provide simple scripting capabilities that other markdown languages cannot provide on their own.

GoFish terminology

Term Description Example
Food The package definition /usr/local/Fish/Rigs/github.com/fishworks/fish-food
Rig A git repository containing fish food /usr/local/Fish/Rigs/github.com/fishworks/fish-food
Barrel All fish food are installed here /usr/local/Fish/Barrel

An introduction

GoFish uses git for contributing to the project.

GoFish installs to the Barrel and then symlinks some of the installation into /usr/local so that other programs can see what’s going on. We suggest you use find on a few of the food in your Barrel to see how it is all arranged.

Packages are installed according to their fish food, which are written in Lua and live in /usr/local/Fish/Rigs/github.com/fishworks/fish-food.

Basic instructions

Make sure you run gofish update before you start. This prepares your Rigs by bumping them to the latest revision.

Before submitting a new food, make sure your package:

  • isn’t already in fish-food
  • isn’t already waiting to be merged (check the pull request queue)
  • is still supported by upstream
  • has a stable, tagged version (i.e. not just a work-in-progress with no versions)

Before submitting a new food, make sure you read over our contribution guidelines.

Create the fish food

gofish update # make sure we've got a fresh checkout of master
vim $(gofish create foo)

Test the fish food

…By installing it!

gofish install --log-level 9001 foo

Manuals

GoFish expects to find manual pages in /usr/local/share/man/, not in /usr/local/man/.

A quick word on naming

Name the food like the project markets the product. For example, use pkg-config over pkgconfig, and sdl_mixer over sdl-mixer or sdlmixer.

Commit

Everything is built on git, so contribution is easy:

eval $(gofish tank)
cd $GOFISH_DEFAULT_RIG
# Create a new git branch for your food so your pull request is easy to
# modify if any changes come up during review.
git checkout -b <some-descriptive-name>
git add Food/foo.lua
git commit

Fork

Now you just need to push your commit to GitHub.

If you haven’t forked GoFish yet, go to the fish-food repository and hit the Fork button.

If you have already forked GoFish on GitHub, then you can manually push (just make sure you have been pulling from the fishworks/fish-food master):

git push https://github.com/myname/fish-food/

Now, open a pull request for your changes.

  • One formula per commit; one commit per formula
  • Keep merge commits out of the pull request

Hacking up GoFish 🍣

This guide is for developers who want to improve Fish. These instructions will help you set up a development environment for working on the GoFish source code.

Prerequisites

To compile and test GoFish, you will need:

In most cases, install each prerequisite according to its instructions.

Fork the Repository

Begin at Github by forking GoFish, then clone your fork locally. Since GoFish is a Go package, it should be located at $GOPATH/src/github.com/fishworks/gofish.

$ mkdir -p $GOPATH/src/github.com/fishworks
$ cd $GOPATH/src/github.com/fishworks
$ git clone [email protected]:<username>/gofish.git
$ cd gofish

Add the conventional upstream git remote in order to fetch changes from GoFish’s main master branch and to create pull requests:

$ git remote add upstream https://github.com/fishworks/gofish.git

Make your Changes

With the prerequisites installed and your fork of GoFish cloned, you can make changes to local GoFish source code.

Run make to build GoFish:

$ make bootstrap
$ make

Test your Changes

GoFish includes a suite of tests:

  • make test-lint: runs linter/style checks
  • make test-unit: runs basic unit tests
  • make test: runs all of the above

Contributing to GoFish

GoFish accepts contributions via GitHub pull requests. This document outlines the process to help get your contribution accepted.

Reporting a Security Issue

Most of the time, when you find a bug in GoFish, it should be reported using GitHub issues. However, if you are reporting a security vulnerability, please email a report to Matt Fisher directly. This will give myself a chance to try to fix the issue before it is exploited in the wild.

Support Channels

Whether you are a user or contributor, official support channels include:

  • GitHub issues
  • IRC - tbd at a later date

Before opening a new issue or submitting a new pull request, it’s helpful to search the project - it’s likely that another user has already reported the issue you’re facing, or it’s a known issue that we’re already aware of.

Milestones

We use milestones to track progress of releases. A milestone (and hence release) is considered done when all outstanding issues/PRs have been closed or moved to another milestone.

Semver

GoFish maintains a strong commitment to backward compatibility. All of our changes to protocols and formats are backward compatible from GoFish 1.0 until GoFish 2.0. No features, flags, or commands are removed or substantially modified (other than bug fixes).

We also try very hard to not change publicly accessible Go library definitions inside of the pkg/ directory of our source code, but it is not guaranteed to be backwards compatible as we move the project forward.

If there’s some package you rely on inside of GoFish that would be useful to split out and maintain separately, open an issue to discuss it!

For a quick summary of our backward compatibility guidelines for releases between 1.0 and 2.0:

  • Command line commands, flags, and arguments MUST be backward compatible
  • Directory formats within /usr/local/Fish MUST be backward compatible
  • Any fish food that worked on a previous version of GoFish MUST work on a new version of GoFish, barring the cases where
    • it is out of our control, e.g. the Operating System itself changed, and
    • the fish food worked because it exploited a bug

Issues

Issues are used as the primary method for tracking anything to do with the GoFish project.

Issue Types

There are 4 types of issues (each with their own corresponding label):

Question/Support

These are support or functionality inquiries that we want to have a record of for future reference. Depending on the discussion, it may require further information from the user before these can turn into Feature or Bug issues.

Proposal

Used for items that propose a new ideas or functionality that require a larger community discussion. This allows for feedback from others in the community before a feature is actually developed. This is not needed for small additions. Final word on whether or not a featureneeds a proposal is up to the core maintainers. All issues that are proposals should both have a label and an issue title of “Proposal: [the rest of the title].” A proposal can become a Feature and does not require a milestone.

Feature

These track specific feature requests and ideas until they are complete. They can evolve from a Proposal or can be submitted individually depending on the size.

Bug

These track bugs with the code or problems with the documentation (i.e. missing or incomplete)

Issue Lifecycle

The issue lifecycle is mainly driven by the core maintainers, but is good information for those contributing to GoFish. All issue types follow the same general lifecycle. Differences are noted below.

  1. Issue creation
  2. Triage
    • The maintainer in charge of triaging will apply the proper labels for the issue. This includes labels for priority, type, and metadata (such as “starter”). The only issue priority we will be tracking is whether or not the issue is “critical.” If additional levels are needed in the future, we will add them.
    • (If needed) Clean up the title to succinctly and clearly state the issue. Also ensure that proposals are prefaced with “Proposal”.
    • Add the issue to the correct milestone. If any questions come up, don’t worry about adding the issue to a milestone until the questions are answered.
    • We attempt to do this process at least once per work day.
  3. Discussion
    • “Feature” and “Bug” issues should be connected to the PR that resolves it.
    • Whoever is working on a “Feature” or “Bug” issue (whether a maintainer or someone from the community), should either assign the issue to them self or make a comment in the issue saying that they are taking it.
    • “Proposal” and “Question” issues should stay open until resolved or if they have not been active for more than 30 days. This will help keep the issue queue to a manageable size and reduce noise. Should the issue need to stay open, the keep open label can be added.
  4. Issue closure

How to Contribute a Patch

  1. Fork the desired repo, develop and test your code changes.
  2. Submit a pull request.

The next section contains more information on the workflow followed for PRs

Pull Requests

Like any good open source project, we use Pull Requests to track code changes.

PR Lifecycle

  1. PR creation
    • We more than welcome PRs that are currently in progress. They are a great way to keep track of important work that is in-flight, but useful for others to see. If a PR is a work in progress, it must be prefaced with “WIP: [title]“. Once the PR is ready for review, remove “WIP” from the title.
    • It is preferred, but not required, to have a PR tied to a specific issue.
  2. Triage
    • The maintainer in charge of triaging will apply the proper labels for the issue. This should include at least a size label, bug or feature, and awaiting review once all labels are applied. See the Labels section for full details on the definitions of labels
    • Add the PR to the correct milestone. This should be the same as the issue the PR closes.
  3. Assigning reviews
    • Once a review has the awaiting review label, maintainers will review them as schedule permits. The maintainer who takes the issue should self-request a review.
    • Reviews from others in the community, especially those who have encountered a bug or have requested a feature, are highly encouraged, but not required. Maintainer reviews are required before any merge
    • Any PR with the size/large label requires 2 review approvals from maintainers before it can be merged. Those with size/medium are per the judgement of the maintainers
  4. Reviewing/Discussion
    • All reviews will be completed using Github review tool.
    • A “Comment” review should be used when there are questions about the code that should be answered, but that don’t involve code changes. This type of review does not count as approval.
    • A “Changes Requested” review indicates that changes to the code need to be made before they will be merged.
  5. Address comments by answering questions or changing code
  6. Merge or close
    • PRs should stay open until merged or if they have not been active for more than 30 days. This will help keep the PR queue to a manageable size and reduce noise. Should the PR need to stay open (like in the case of a WIP), the keep open label can be added.
    • If the owner of the PR is listed in OWNERS, that user must merge their own PRs or explicitly request another OWNER do that for them.
    • If the owner of a PR is not listed in OWNERS, any core committer may merge the PR once it is approved.

A note about Documentation PRs

Documentation PRs will follow the same lifecycle as other PRs. They will also be labeled with the docs label. For documentation, special attention will be paid to spelling, grammar, and clarity (whereas those things don’t matter as much for comments in code).

Labels

The following tables define all label types used for GoFish. It is split up by category.

Common

Label Description
bug Marks an issue as a bug or a PR as a bugfix
critical Marks an issue or PR as critical. This means that addressing the PR or issue is top priority and will be handled first by maintainers
docs Indicates the issue or PR is a documentation change
duplicate Indicates that the issue or PR is a duplicate of another
feature Marks the issue as a feature request or a PR as a feature implementation
keep open Denotes that the issue or PR should be kept open past 30 days of inactivity
refactor Indicates that the issue is a code refactor and is not fixing a bug or adding additional functionality

Issue Specific

Label Description
help wanted This issue is one the core maintainers would appreciate help with
proposal This issue is a proposal
question/support This issue is a support request or question
good first issue This issue is a good for someone new to contributing to GoFish
wontfix The issue has been discussed and will not be accepted

Release Specific

Label Description
needs pick Indicates that the PR needs to be picked into a feature branch (generally bugfix branches). Once it has been, the picked label should be applied and this one removed
picked This PR has been picked into a feature branch

Code of Conduct

In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.

Our Standards

Examples of behavior that contributes to creating a positive environment include:

  • Using welcoming and inclusive language
  • Being respectful of differing viewpoints and experiences
  • Gracefully accepting constructive criticism
  • Focusing on what is best for the community
  • Showing empathy towards other community members

Examples of unacceptable behavior by participants include:

  • The use of sexualized language or imagery and unwelcome sexual attention or advances
  • Trolling, insulting/derogatory comments, and personal or political attacks
  • Public or private harassment
  • Publishing others’ private information, such as a physical or electronic address, without explicit permission
  • Other conduct which could reasonably be considered inappropriate in a professional setting

Our Responsibilities

Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.

Scope

This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.

Enforcement

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team. All complaints will be reviewed and investigated and will result in a response that is deemed necessary and appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.

Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project’s leadership.

Attribution

This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html