Fly CLI: buildGoPackage with bash completions

I’m writing a derivation for the fly CLI (for use with Concourse CI).

I wanted to include bash completions along with the fly executable. Because buildGoPackage produces a multiple-output package, I ended up using symlinkJoin to wrap things up in a single derivation.

I’m not familiar with golang, and it was a bit of a journey figuring out how to package the bash completions alongside the binary. I’d like to post what I ended up with in case anyone has suggestions about possible improvements.

At the moment, I’m accessing the derivation through an overlay:

self: super: {
  fly = super.callPackage pkgs/fly { };

The pkgs/fly/default.nix:

{ pkgs ? import ./nixpkgs.nix { } }:

  pinned = builtins.fromJSON (builtins.readFile ./pinned.json);

  fly = with pkgs; buildGoPackage rec {
    name = "fly-${version}";
    version =;
    src = fetchFromGitHub;

    goPackagePath = "";
    goDeps = ./deps.nix;

    buildFlagsArray = ''
        -X ${goPackagePath}/version.Version=${version}

    postInstall = ''
      install -D -m 444 ${
        pkgs.writeText "fly.bash" (builtins.readFile ./fly.bash)
      } $out/share/bash-completion/completions/fly

in pkgs.symlinkJoin {
  name = "fly";

  paths = [

The pkgs/fly/fly.bash script:

#!/usr/bin/env bash

_fly() {
    # All arguments except the first one

    # Only split on newlines
    local IFS=$'\n'

    # Call completion (note that the first element of COMP_WORDS is
    # the executable itself)
    COMPREPLY=($(GO_FLAGS_COMPLETION=1 ${COMP_WORDS[0]} "${args[@]}"))
    return 0

complete -F _fly fly

The pkgs/fly/deps.nix was generated using go2nix as follows:

git clone --jobs=8 --recursive --branch=v4.2.3
cd concourse
nix-shell -p go go2nix
export GOPATH=$PWD
cd src/
go build -ldflags "-X"
go2nix save

As a side-note, I’m using buildGoPackage rather than buildGoModule because the version of fly I need doesn’t use go modules. I’d like to eventually submit a derivation to nixpkgs, though I’ll probably try to package a more recent version of fly for that, and would put something more idiomatic together (e.g. without pinned.json, etc.).

@ivanbrennan I was also looking for a solution to this and stumbled on the Helm package on nixpkgs:

Not sure if this accomplishes precisely what you’re trying to do but perhaps worth checking out.

Yeah, that’s the approach now being used in the fly derivation. I don’t remember if I packaged it before fly added the completion generator or I just wasn’t aware that it was an option at the time, but it was eventually updated to use the provided generator.

Good call out though :+1:

1 Like