Skip to content

Commit f868860

Browse files
authored
(feature): New interface and features (#5)
* upgrade dependencies * better ui * update ci and grouping * fix ci yaml * fix ci golanglint-ci * fix table headers * general fix and improvements * group by default * adding dockerfile * feat tab key navigation * fixed container status * fix page header * fix lint issues * fix unit tests * table width * fix table header width * upgrate to charm stack v2 * add quick menu * standard navigation
1 parent 465bd91 commit f868860

46 files changed

Lines changed: 5343 additions & 987 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ jobs:
1212
runs-on: ubuntu-latest
1313
strategy:
1414
matrix:
15-
go-version: [ '1.24', 'stable' ]
15+
go-version: [ '1.26', 'stable' ]
1616

1717
steps:
1818
- uses: actions/checkout@v4
@@ -24,10 +24,12 @@ jobs:
2424
check-latest: true
2525

2626
- name: Generate mocks
27-
run: make generate-mocks
27+
run: |
28+
go install github.com/vektra/mockery/v3@latest
29+
mockery --config .mockery.yaml
2830
2931
- name: Run golangci-lint (latest)
30-
uses: golangci/golangci-lint-action@v6
32+
uses: golangci/golangci-lint-action@v9
3133
with:
3234
version: latest
3335
args: --timeout=5m
@@ -37,7 +39,7 @@ jobs:
3739
runs-on: ubuntu-latest
3840
strategy:
3941
matrix:
40-
go-version: [ '1.24', 'stable' ]
42+
go-version: [ '1.26', 'stable' ]
4143

4244
steps:
4345
- uses: actions/checkout@v4
@@ -50,13 +52,20 @@ jobs:
5052
cache: true
5153

5254
- name: Generate mocks
53-
run: make generate-mocks
55+
run: |
56+
go install github.com/vektra/mockery/v3@latest
57+
mockery --config .mockery.yaml
5458
5559
- name: Verify dependencies
5660
run: go mod tidy && git diff --exit-code go.mod go.sum
5761

5862
- name: Build
59-
run: make build
63+
run: go build -o berth ./cmd/berth
6064

6165
- name: Test
62-
run: make test
66+
run: go test ./... -coverprofile=coverage.txt
67+
68+
- name: Upload coverage reports to Codecov
69+
uses: codecov/codecov-action@v5
70+
with:
71+
token: ${{ secrets.CODECOV_TOKEN }}

.github/workflows/release.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,10 @@ jobs:
1515
steps:
1616
- uses: actions/checkout@v4
1717

18-
- name: Setup Go 1.24 (or higher)
18+
- name: Setup Go 1.26
1919
uses: actions/setup-go@v5
2020
with:
21-
go-version: '1.24'
21+
go-version: '1.26'
2222
check-latest: true
2323

2424
# - name: Run tests

Dockerfile.dev

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM docker.io/golangci/golangci-lint:v2.12.1 AS golangci-lint
2+
3+
FROM golang:1.26-alpine
4+
5+
RUN apk add --no-cache git curl
6+
7+
# golangci-lint for local Podman lint runs.
8+
COPY --from=golangci-lint /usr/bin/golangci-lint /usr/local/bin/golangci-lint
9+
10+
# mockery (matches CI: go install github.com/vektra/mockery/v3@latest)
11+
RUN go install github.com/vektra/mockery/v3@latest
12+
13+
# pre-cache module deps — layer cache survives image rebuilds when go.mod unchanged
14+
WORKDIR /app
15+
COPY go.mod go.sum ./
16+
RUN go mod download
17+
18+
WORKDIR /app

Makefile

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
GO := go
2-
APP_NAME := berth
3-
APP_PATH := ./cmd/berth
1+
GO := go
2+
APP_NAME := berth
3+
APP_PATH := ./cmd/berth
4+
PODMAN_IMAGE := berth-dev
5+
PODMAN_RUN := podman run --rm -v $(shell pwd):/app:Z -w /app $(PODMAN_IMAGE)
46

5-
.PHONY: all build run clean test lint help
7+
.PHONY: all build run clean test lint help podman-image podman-build podman-test podman-lint docker-image docker-build docker-test docker-lint
68

79
all: build
810

@@ -36,13 +38,38 @@ lint:
3638
# go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
3739
golangci-lint run ./...
3840

41+
podman-image:
42+
@echo "Building Podman dev image (Go 1.26)..."
43+
podman build -t $(PODMAN_IMAGE) -f Dockerfile.dev .
44+
45+
podman-build: podman-image
46+
@echo "Building $(APP_NAME) in Podman..."
47+
$(PODMAN_RUN) go build -o $(APP_NAME) $(APP_PATH)
48+
49+
podman-test: podman-image
50+
@echo "Running tests in Podman..."
51+
$(PODMAN_RUN) sh -c "mockery --config .mockery.yaml && go test ./..."
52+
53+
podman-lint: podman-image
54+
@echo "Running lint in Podman..."
55+
$(PODMAN_RUN) sh -c "mockery --config .mockery.yaml && golangci-lint run --timeout=5m ./..."
56+
57+
docker-image: podman-image
58+
docker-build: podman-build
59+
docker-test: podman-test
60+
docker-lint: podman-lint
61+
3962
help:
4063
@echo "Usage: make <command>"
4164
@echo "\nCommands:"
42-
@echo " all : Builds the application (default)"
43-
@echo " build : Compiles the application binary"
44-
@echo " run : Runs the application"
45-
@echo " clean : Removes build artifacts and the application binary"
46-
@echo " test : Runs all tests"
47-
@echo " lint : Runs go fmt and go vet"
48-
@echo " help : Displays this help message"
65+
@echo " all : Builds the application (default)"
66+
@echo " build : Compiles the application binary"
67+
@echo " run : Runs the application"
68+
@echo " clean : Removes build artifacts and the application binary"
69+
@echo " test : Runs all tests"
70+
@echo " lint : Runs golangci-lint"
71+
@echo " podman-image : Builds Podman dev image (Go 1.26)"
72+
@echo " podman-build : Builds the binary inside Podman"
73+
@echo " podman-test : Runs tests inside Podman"
74+
@echo " podman-lint : Runs lint inside Podman"
75+
@echo " help : Displays this help message"

README.md

Lines changed: 75 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
<div align="center">
1+
<p align="center">
2+
<img src="docs/assets/berth-logo.png" alt="canery logo" height="240">
3+
</p>
24

3-
# 🚢 Berth – Terminal UI for Containers
5+
<div align="center">
46

5-
[![Go Version](https://img.shields.io/badge/go-1.24-blue?logo=go)](https://golang.org)
7+
[![CI](https://github.com/rluders/berth/actions/workflows/ci.yml/badge.svg)](https://github.com/rluders/berth/actions/workflows/ci.yml)
8+
![Go](https://img.shields.io/badge/go-1.26+-00ADD8?logo=go&logoColor=white)
9+
[![Go Report Card](https://goreportcard.com/badge/github.com/rluders/berth)](https://goreportcard.com/report/github.com/rluders/berth)
10+
[![GitHub release](https://img.shields.io/github/v/release/rluders/berth?sort=semver)](https://github.com/rluders/berth/releases)
11+
[![codecov](https://codecov.io/gh/rluders/berth/graph/badge.svg)](https://codecov.io/gh/rluders/berth)
612
[![License](https://img.shields.io/github/license/rluders/berth)](LICENSE)
7-
[![Build](https://img.shields.io/badge/build-passing-brightgreen)]()
8-
[![Status](https://img.shields.io/badge/status-alpha-orange)]()
913
[![Made with Bubbletea](https://img.shields.io/badge/made%20with-bubbletea-ff69b4?logo=github)](https://github.com/charmbracelet/bubbletea)
1014

11-
> **Berth** is a terminal-based UI to manage your containers, images, volumes, networks, and system usage — with support for **Docker** and **Podman**.
12-
> 🧠 Name origin: In maritime terms, a **berth** is a designated place where a ship is docked — just like containers in your stack. Clean, organized, and under control.
15+
**Berth** is a terminal-based UI to manage your containers, images, volumes, networks, and system usage — with support for **Docker** and **Podman**. Name origin: In maritime terms, a **berth** is a designated place where a ship is docked — just like containers in your stack. Clean, organized, and under control.
1316

1417
</div>
1518

@@ -31,7 +34,7 @@ Berth is a comprehensive terminal user interface (TUI) application built in Go,
3134

3235
### Prerequisites
3336

34-
- [Go](https://golang.org/doc/install) (version 1.24 or higher recommended)
37+
- [Go](https://golang.org/doc/install) (version 1.26 or higher recommended)
3538
- [Docker](https://docs.docker.com/get-docker/) or [Podman](https://podman.io/docs/installation) installed and running
3639

3740
### Steps
@@ -54,39 +57,72 @@ make run
5457

5558
Berth provides an intuitive keyboard-driven interface.
5659

57-
### 🎹 Navigation
60+
### 🎹 Global Keys
5861

59-
* `1` — Containers View
60-
* `2` — Images View
61-
* `3` — Volumes View
62-
* `4` — Networks View
63-
* `5` — System View
62+
| Key | Action |
63+
| --------- | ------------------- |
64+
| `1` | Containers view |
65+
| `2` | Images view |
66+
| `3` | Volumes view |
67+
| `4` | Networks view |
68+
| `5` | System view |
69+
| `?` | Toggle help overlay |
70+
| `q` / `esc` | Back / quit |
71+
| `ctrl+c` | Quit |
6472

6573
### 🛠️ Container Actions
6674

67-
| Key | Action |
68-
| --- | ------------------------ |
69-
| `s` | Start selected container |
70-
| `x` | Stop selected container |
71-
| `d` | Remove container |
72-
| `l` | View logs |
73-
| `i` | Inspect container |
74-
75-
### 📦 Image & Volume Actions
76-
77-
* `d` — Remove selected image or volume
75+
| Key | Action |
76+
| ------- | ------------------------- |
77+
| `enter` | Container details |
78+
| `s` | Start container |
79+
| `x` | Stop container |
80+
| `r` | Restart container |
81+
| `d` | Remove container |
82+
| `l` | View logs |
83+
| `i` | Inspect container |
84+
| `e` | Exec shell |
85+
| `/` | Filter containers |
86+
| `g` | Toggle group by compose |
87+
| `` | Expand compose group |
88+
| `` | Collapse compose group |
89+
90+
### 📦 Image Actions
91+
92+
| Key | Action |
93+
| --- | -------------------- |
94+
| `d` | Remove image |
95+
| `P` | Prune dangling images |
96+
| `/` | Filter images |
97+
98+
### 💾 Volume Actions
99+
100+
| Key | Action |
101+
| --- | ------------- |
102+
| `d` | Remove volume |
103+
| `/` | Filter volumes |
104+
105+
### 🌐 Network Actions
106+
107+
| Key | Action |
108+
| --- | --------------- |
109+
| `i` | Inspect network |
78110

79111
### 🧼 System Cleanup
80112

81-
| Key | Action |
82-
| --- | ---------------- |
83-
| `b` | Basic Cleanup |
84-
| `a` | Advanced Cleanup |
85-
| `t` | Total Cleanup |
113+
| Key | Action |
114+
| --- | --------------------------------------------------- |
115+
| `b` | Basic cleanup — stopped containers, unused networks, dangling images |
116+
| `a` | Advanced cleanup — basic + unused volumes |
117+
| `t` | Total cleanup — all unused resources |
86118

87-
### 🔙 Back / Exit
119+
### 📋 Logs View
88120

89-
* `q` or `esc` — Return to the previous view or quit the application from the main views.
121+
| Key | Action |
122+
| --- | ------------------- |
123+
| `p` | Pause log stream |
124+
| `f` | Follow (tail) logs |
125+
| `n` | Toggle line numbers |
90126

91127
## 🛠️ Technology Stack
92128

@@ -99,14 +135,14 @@ Berth provides an intuitive keyboard-driven interface.
99135

100136
```
101137
.
102-
├── cmd/ # CLI entry point (e.g., main.go)
138+
├── cmd/ # CLI entry point
103139
├── internal/
104-
│ ├── tui/ # All Bubbletea models/views/components
105-
│ ├── engine/ # Docker/Podman abstraction layer
106-
│ ├── controller/ # Logic for container/image/volume actions
107-
│ ├── state/ # Global state models
108-
│ └── utils/ # Helpers: formatting, exec wrappers, etc.
109-
├── assets/ # Logo, themes, maybe future plugins
140+
│ ├── tui/ # Bubble Tea models, views, and components
141+
│ ├── engine/ # Docker/Podman client abstraction
142+
│ ├── service/ # Service layer (container, image, volume, network, system)
143+
│ ├── controller/ # Action handlers (start, stop, remove, inspect, …)
144+
│ └── utils/ # Formatting helpers and exec wrappers
145+
├── docs/ # Assets (logo, screenshots)
110146
├── go.mod
111147
└── README.md
112148
```

cmd/berth/main.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
"log/slog"
77
"os"
88

9-
tea "github.com/charmbracelet/bubbletea"
9+
tea "charm.land/bubbletea/v2"
1010
"github.com/rluders/berth/internal/tui"
1111
)
1212

@@ -18,7 +18,11 @@ func main() {
1818
fmt.Printf("Error opening log file: %v\n", err)
1919
os.Exit(1)
2020
}
21-
defer logFile.Close()
21+
defer func() {
22+
if err := logFile.Close(); err != nil {
23+
fmt.Fprintf(os.Stderr, "Error closing log file: %v\n", err)
24+
}
25+
}()
2226

2327
handler := slog.NewTextHandler(logFile, &slog.HandlerOptions{Level: slog.LevelDebug})
2428
slog.SetDefault(slog.New(handler))
@@ -42,7 +46,7 @@ func main() {
4246
}
4347
}()
4448
slog.Debug("Initializing Bubble Tea program...")
45-
program = tea.NewProgram(tui.InitialModel(), tea.WithAltScreen())
49+
program = tea.NewProgram(tui.InitialModel())
4650
}()
4751

4852
slog.Debug("Running Bubble Tea program...")

docs/assets/berth-logo.png

942 KB
Loading

0 commit comments

Comments
 (0)