Skip to content
Open
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/reusable-deb-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
dpkg-deb -x "$pkg" "$tmpdir"
./scripts/verify-package-assets.sh "$tmpdir"
./scripts/verify-package-assets.sh "$tmpdir" usr/share/zsh/vendor-completions

- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/reusable-rpm-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ jobs:
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
(cd "$tmpdir" && rpm2cpio "$pkg" | cpio -idm --quiet)
./scripts/verify-package-assets.sh "$tmpdir"
./scripts/verify-package-assets.sh "$tmpdir" usr/share/zsh/site-functions

build-rpm-fedora:
runs-on: ubuntu-24.04
Expand Down Expand Up @@ -92,7 +92,7 @@ jobs:
tmpdir=$(mktemp -d)
trap 'rm -rf "$tmpdir"' EXIT
(cd "$tmpdir" && rpm2cpio "$pkg" | cpio -idm --quiet)
./scripts/verify-package-assets.sh "$tmpdir"
./scripts/verify-package-assets.sh "$tmpdir" usr/share/zsh/site-functions

- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
Expand Down
19 changes: 16 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ LINT_TMP_DIR := ./.tmp
LINT_GO_CACHE := $(LINT_TMP_DIR)/go-build
LINT_GOLANGCI_CACHE := $(LINT_TMP_DIR)/golangci-lint-cache
BASE_REF ?=
# Completion install roots follow the XDG base directory spec, like
# scripts/clean-state.sh, so install and cleanup agree when XDG_DATA_HOME is set.
DATA_HOME ?= $(or $(XDG_DATA_HOME),$(HOME)/.local/share)
ZSH_COMPLETION_DIR := $(DATA_HOME)/zsh/site-functions
BASH_COMPLETION_DIR := $(DATA_HOME)/bash-completion/completions

check-go:
@command -v go >/dev/null 2>&1 || { echo "Go is not installed. Install Go 1.24+ from https://go.dev/dl/"; exit 1; }
Expand All @@ -36,6 +41,7 @@ build: check-go
completions:
mkdir -p $(COMPLETIONS_DIR)
$(BIN_DIR)/$(BINARY) completion bash > $(COMPLETIONS_DIR)/enclave
$(BIN_DIR)/$(BINARY) completion zsh > $(COMPLETIONS_DIR)/_enclave
Comment thread
planger marked this conversation as resolved.

# make install now installs only the self-contained binary. This fixed path is
# used solely for conservative cleanup of assets staged by older source
Expand All @@ -62,8 +68,13 @@ install-binary: clean-legacy-assets
mv -f "$(INSTALL_BIN)/$(BINARY).new" "$(INSTALL_BIN)/$(BINARY)"
ifeq ($(UNAME_S),Linux)
# freedesktop shell completion (Linux only).
mkdir -p "$(HOME)/.local/share/bash-completion/completions"
cp $(COMPLETIONS_DIR)/enclave "$(HOME)/.local/share/bash-completion/completions/enclave"
mkdir -p "$(BASH_COMPLETION_DIR)"
cp $(COMPLETIONS_DIR)/enclave "$(BASH_COMPLETION_DIR)/enclave"
mkdir -p "$(ZSH_COMPLETION_DIR)"
cp $(COMPLETIONS_DIR)/_enclave "$(ZSH_COMPLETION_DIR)/_enclave"
@# zsh has no user-level directory on its default fpath, so a completion
@# installed under the home directory is only found once ~/.zshrc adds it.
@command -v zsh >/dev/null 2>&1 && echo 'zsh completion installed; it is only picked up if ~/.zshrc has "fpath=($(ZSH_COMPLETION_DIR) $$fpath)" before whatever runs compinit' || true
endif
@echo "Installed $(INSTALL_BINARY_LABEL) to $(INSTALL_BIN)/$(BINARY)"

Expand All @@ -73,7 +84,9 @@ clean-legacy-assets:
uninstall:
rm -f "$(INSTALL_BIN)/$(BINARY)"
ifeq ($(UNAME_S),Linux)
rm -f "$(HOME)/.local/share/bash-completion/completions/enclave"
rm -f "$(BASH_COMPLETION_DIR)/enclave"
rm -f "$(ZSH_COMPLETION_DIR)/_enclave"
@command -v zsh >/dev/null 2>&1 && echo 'zsh completion removed; the matching "fpath=($(ZSH_COMPLETION_DIR) ...)" line in ~/.zshrc is now unused' || true
endif
@echo "Uninstalled $(BINARY)"

Expand Down
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,24 @@ is on your `PATH`. On macOS the default is `/usr/local/bin/`; copying there may
need `sudo` or a writable `/usr/local/bin`. Override the destination with
`make install INSTALL_BIN=...`.

On Linux it also installs shell completions: bash into
`~/.local/share/bash-completion/completions/`, which is picked up automatically,
and zsh into `~/.local/share/zsh/site-functions/`, which zsh only searches once
you add it to `fpath` in `~/.zshrc`, before whatever runs `compinit`:

```zsh
fpath=(~/.local/share/zsh/site-functions $fpath)
```

Frameworks such as oh-my-zsh and prezto call `compinit` themselves, so put the
line above their setup and leave the rest to them. On a plain zsh setup that
does not call it anywhere, add `autoload -U compinit && compinit` after the
`fpath` line. Both completion paths honor `XDG_DATA_HOME` if you set it.

The `.deb` and `.rpm` packages install both completions into system directories
that need no such setup. Any shell can also generate its own script on demand
with `enclave completion <bash|zsh|fish>`.

## Quick Start

Run in any project directory:
Expand Down
6 changes: 5 additions & 1 deletion debian/rules
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ override_dh_auto_build:
go build -tags enclave_no_embed -mod=vendor -o bin/enclave ./cmd/enclave
mkdir -p completions
bin/enclave completion bash > completions/enclave
bin/enclave completion zsh > completions/_enclave

override_dh_auto_install:
# Install binary
Expand Down Expand Up @@ -70,9 +71,12 @@ override_dh_auto_install:
cp -r "$$path" "$$dest/"; \
done < $(GATEWAY_PROXY_SOURCE_PATHS_FILE)

# Install bash completions
# Install shell completions. Debian searches zsh/vendor-completions for
# distro-packaged functions; zsh/site-functions under /usr is not on fpath.
install -D -m 0644 completions/enclave \
$(CURDIR)/debian/enclave/usr/share/bash-completion/completions/enclave
install -D -m 0644 completions/_enclave \
$(CURDIR)/debian/enclave/usr/share/zsh/vendor-completions/_enclave

# Install documentation
install -D -m 0644 README.md $(CURDIR)/debian/enclave/usr/share/doc/enclave/README.md
Expand Down
4 changes: 4 additions & 0 deletions packaging/rpm/enclave.spec
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ mkdir -p bin completions
# cgo so RPMs built on Debian or Ubuntu do not acquire host glibc requirements.
CGO_ENABLED=0 go build -tags enclave_no_embed -mod=vendor -o bin/enclave ./cmd/enclave
bin/enclave completion bash > completions/enclave
bin/enclave completion zsh > completions/_enclave

%install
app_root="%{buildroot}%{_datadir}/%{name}"
Expand Down Expand Up @@ -88,6 +89,8 @@ done < internal/gateway/gateway_proxy_build_inputs.txt

install -D -m 0644 completions/enclave \
"%{buildroot}%{_datadir}/bash-completion/completions/enclave"
install -D -m 0644 completions/_enclave \
"%{buildroot}%{_datadir}/zsh/site-functions/_enclave"

install -D -m 0644 README.md "$doc_root/README.md"
install -D -m 0644 docs/ARCHITECTURE.md "$doc_root/ARCHITECTURE.md"
Expand All @@ -107,6 +110,7 @@ rm -rf "%{buildroot}"
%{_bindir}/enclave
%{_datadir}/%{name}
%{_datadir}/bash-completion/completions/enclave
%{_datadir}/zsh/site-functions/_enclave
%dir %{_datadir}/doc/%{name}
%doc %{_datadir}/doc/%{name}/README.md
%doc %{_datadir}/doc/%{name}/ARCHITECTURE.md
Expand Down
2 changes: 1 addition & 1 deletion scripts/check-license-headers.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ is_candidate() {
*.go | *.sh | *.yaml | *.yml | *.js | *.ts | *.css | *.html | *.vue | *.puml | *.toml | *.conf | *.spec)
return 0
;;
go.mod | Makefile | completions/enclave | .dockerignore | */.gitignore | .gitignore | */Dockerfile | Dockerfile | Dockerfile.* | debian/rules | debian/control)
go.mod | Makefile | completions/enclave | completions/_enclave | .dockerignore | */.gitignore | .gitignore | */Dockerfile | Dockerfile | Dockerfile.* | debian/rules | debian/control)
return 0
;;
esac
Expand Down
3 changes: 3 additions & 0 deletions scripts/clean-state.sh
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,9 @@ add_data_install_paths() {
[[ -n "$data_root" ]] || return 0
add_install_path "${data_root}/${APP}"
add_install_path "${data_root}/bash-completion/completions/${APP}"
# Fedora and source installs use site-functions, Debian vendor-completions.
add_install_path "${data_root}/zsh/site-functions/_${APP}"
add_install_path "${data_root}/zsh/vendor-completions/_${APP}"
add_install_path "${data_root}/applications/${APP}.desktop"
for size in "${ICON_SIZES[@]}"; do
add_install_path "${data_root}/icons/hicolor/${size}x${size}/apps/${APP}.png"
Expand Down
14 changes: 12 additions & 2 deletions scripts/verify-package-assets.sh
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,14 @@ set -eu
CDPATH=
export CDPATH

if [ "$#" -ne 1 ]; then
echo "usage: $0 <extracted-package-root>" >&2
if [ "$#" -ne 2 ]; then
echo "usage: $0 <extracted-package-root> <expected-zsh-completion-dir>" >&2
exit 2
fi

repo_root=$(cd -P "$(dirname "$0")/.." && pwd)
package_root=$1
zsh_completion_dir=$2
app_root="$package_root/usr/share/enclave"

[ -f "$app_root/.dockerignore" ]
Expand All @@ -29,6 +30,15 @@ diff -qr "$repo_root/docs" "$app_root/docs"
[ -f "$package_root/usr/share/doc/enclave/LICENSE.md" ]
[ -f "$package_root/usr/share/doc/enclave/NOTICE.md" ]

# Completions are only found if they sit in a directory the shell searches by
# default, and for zsh that directory differs per distro: Debian carries
# zsh/vendor-completions on its default fpath and deliberately omits
# zsh/site-functions, Fedora the other way round. The caller passes the layout
# its packaging is expected to produce so the wrong one fails instead of
# silently shipping a completion no shell ever loads.
[ -f "$package_root/usr/share/bash-completion/completions/enclave" ]
[ -f "$package_root/$zsh_completion_dir/_enclave" ]

# Assets must reach the package byte-for-byte. Packaging toolchains rewrite
# files they mistake for host executables -- Fedora's brp-mangle-shebangs
# rewrites /bin/sh to /usr/bin/sh, which does not exist in the Alpine gateway
Expand Down
Loading