Skip to content

Commit 43ad0cb

Browse files
authored
Merge pull request #15 from KashifKhn/dev
Dev
2 parents 407cc07 + c15f02b commit 43ad0cb

File tree

14 files changed

+1429
-60
lines changed

14 files changed

+1429
-60
lines changed

.github/workflows/release.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
- name: Setup Go
2020
uses: actions/setup-go@v5
2121
with:
22-
go-version: '1.21'
22+
go-version: '1.25'
2323
cache: true
2424

2525
- name: Run tests
@@ -38,7 +38,7 @@ jobs:
3838
- name: Setup Go
3939
uses: actions/setup-go@v5
4040
with:
41-
go-version: '1.21'
41+
go-version: '1.25'
4242
cache: true
4343

4444
- name: Get version from tag
@@ -47,6 +47,7 @@ jobs:
4747

4848
- name: Build binaries
4949
run: |
50+
mkdir -p dist
5051
VERSION=${{ steps.version.outputs.VERSION }}
5152
LDFLAGS="-s -w -X main.version=${VERSION}"
5253

docs/docs/commands/dev.md

Lines changed: 193 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,51 @@ The `dev` command provides a unified interface for common development tasks. It
2727
| `build` | `b`, `compile` | Build the project |
2828
| `test` | `t` | Run tests |
2929
| `clean` | - | Clean build artifacts |
30+
| `restart` | - | Trigger restart of running dev server |
3031

3132
---
3233

3334
## haft dev serve
3435

35-
Start the Spring Boot application with DevTools for hot-reload.
36+
Start the Spring Boot application in **supervisor mode** with interactive restart support.
37+
38+
### Interactive Mode (Default)
39+
40+
When running in a terminal, `haft dev serve` runs as a supervisor that manages your Spring Boot process. You can use keyboard commands to control the server:
41+
42+
| Key | Action |
43+
|-----|--------|
44+
| `r` | **Restart** - Compiles first, then restarts (keeps old server if compile fails) |
45+
| `q` | **Quit** - Gracefully stops the server and exits |
46+
| `c` | **Clear** - Clears the screen |
47+
| `h` | **Help** - Shows available commands |
48+
| `Ctrl+C` | Same as `q` - Graceful shutdown |
49+
50+
```
51+
╭─────────────────────────────────────────╮
52+
│ Haft Dev Server │
53+
│ Press r to restart, q to quit │
54+
│ Press h for more commands │
55+
╰─────────────────────────────────────────╯
56+
57+
INFO Starting application build-tool=Maven
58+
59+
. ____ _ __ _ _
60+
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
61+
...
62+
```
63+
64+
### Restart Behavior
65+
66+
The restart command (`r`) follows a **compile-first** strategy:
67+
68+
1. Runs compilation (`mvn compile -DskipTests` or `gradle classes -x test`)
69+
2. **If compilation fails**: Shows error, keeps the old server running
70+
3. **If compilation succeeds**:
71+
- Gracefully stops the old server (SIGTERM → 2s wait → SIGKILL)
72+
- Starts a new server instance
73+
74+
This prevents the "dead server" situation where a syntax error leaves you with no running application.
3675

3776
### Usage
3877

@@ -49,11 +88,12 @@ haft dev start [flags] # Alias
4988
| `--profile` | `-p` | Spring profile to activate (e.g., dev, prod) |
5089
| `--debug` | `-d` | Enable remote debugging on port 5005 |
5190
| `--port` | - | Server port (overrides application config) |
91+
| `--no-interactive` | - | Disable interactive mode (for CI/scripts) |
5292

5393
### Examples
5494

5595
```bash
56-
# Start with default settings
96+
# Start with default settings (interactive mode)
5797
haft dev serve
5898

5999
# Start with dev profile
@@ -67,14 +107,157 @@ haft dev serve --port 8081
67107

68108
# Combine options
69109
haft dev serve -p dev -d --port 8081
110+
111+
# Non-interactive mode (for CI/scripts)
112+
haft dev serve --no-interactive
70113
```
71114

72115
### Build Tool Commands
73116

74-
| Build Tool | Executed Command |
75-
|------------|------------------|
76-
| Maven | `mvn spring-boot:run` (or `./mvnw`) |
77-
| Gradle | `./gradlew bootRun` (or `gradle bootRun`) |
117+
| Build Tool | Run Command | Compile Command (for restart) |
118+
|------------|-------------|-------------------------------|
119+
| Maven | `mvn spring-boot:run -DskipTests` | `mvn compile -DskipTests -q` |
120+
| Gradle | `./gradlew bootRun -x test` | `./gradlew classes -x test -q` |
121+
122+
---
123+
124+
## Plugin Integration
125+
126+
External tools (Neovim, VSCode, IntelliJ) can trigger a restart without keyboard interaction.
127+
128+
### Option 1: Using `haft dev restart` Command
129+
130+
The simplest way to trigger a restart from any tool:
131+
132+
```bash
133+
haft dev restart
134+
```
135+
136+
This command creates the trigger file that signals the running dev server to restart.
137+
138+
### Option 2: Creating the Trigger File Directly
139+
140+
When `haft dev serve` is running, it watches for the creation/modification of:
141+
142+
```
143+
.haft/restart
144+
```
145+
146+
To trigger a restart manually:
147+
148+
```bash
149+
touch .haft/restart
150+
```
151+
152+
### Neovim Integration
153+
154+
Add to your `init.lua`:
155+
156+
```lua
157+
-- Auto-restart haft on save (using shell command)
158+
vim.api.nvim_create_autocmd("BufWritePost", {
159+
pattern = { "*.java", "*.kt" },
160+
callback = function()
161+
vim.fn.jobstart("haft dev restart", { detach = true })
162+
end,
163+
})
164+
165+
-- Manual restart keybinding
166+
vim.keymap.set("n", "<leader>hr", function()
167+
vim.fn.jobstart("haft dev restart", { detach = true })
168+
print("Haft restart triggered")
169+
end, { desc = "Trigger Haft restart" })
170+
```
171+
172+
Alternative (direct file creation):
173+
174+
```lua
175+
vim.keymap.set("n", "<leader>hr", function()
176+
local trigger = vim.fn.getcwd() .. "/.haft/restart"
177+
vim.fn.writefile({}, trigger)
178+
print("Haft restart triggered")
179+
end, { desc = "Trigger Haft restart" })
180+
```
181+
182+
### VS Code Integration
183+
184+
Add to `.vscode/tasks.json`:
185+
186+
```json
187+
{
188+
"version": "2.0.0",
189+
"tasks": [
190+
{
191+
"label": "Haft Restart",
192+
"type": "shell",
193+
"command": "haft dev restart",
194+
"problemMatcher": [],
195+
"presentation": {
196+
"reveal": "silent"
197+
}
198+
}
199+
]
200+
}
201+
```
202+
203+
Add keybinding in `keybindings.json`:
204+
205+
```json
206+
{
207+
"key": "ctrl+shift+r",
208+
"command": "workbench.action.tasks.runTask",
209+
"args": "Haft Restart"
210+
}
211+
```
212+
213+
### IntelliJ IDEA Integration
214+
215+
1. Go to **Settings → Tools → External Tools**
216+
2. Add new tool:
217+
- **Name**: Haft Restart
218+
- **Program**: `haft`
219+
- **Arguments**: `dev restart`
220+
- **Working directory**: `$ProjectFileDir$`
221+
3. Assign a keyboard shortcut in **Settings → Keymap**
222+
223+
---
224+
225+
## haft dev restart
226+
227+
Trigger a restart of the running dev server from the command line.
228+
229+
### Usage
230+
231+
```bash
232+
haft dev restart
233+
```
234+
235+
### Description
236+
237+
This command creates a trigger file that signals the running dev server (`haft dev serve`) to restart. It's useful for:
238+
239+
- Shell scripts that need to trigger restarts
240+
- Editor plugins that prefer calling CLI commands
241+
- CI/CD pipelines for hot-reload testing
242+
- Any tool that can execute shell commands
243+
244+
### Examples
245+
246+
```bash
247+
# Trigger restart of running dev server
248+
haft dev restart
249+
250+
# Use in a shell script
251+
#!/bin/bash
252+
# Edit some files...
253+
haft dev restart
254+
255+
# Use with file watchers
256+
fswatch -o src/ | xargs -n1 -I{} haft dev restart
257+
258+
# Use with entr (run on file changes)
259+
find src -name "*.java" | entr haft dev restart
260+
```
78261

79262
---
80263

@@ -224,9 +407,12 @@ This ensures consistent builds across different environments.
224407
## Typical Workflow
225408

226409
```bash
227-
# Start development server
410+
# Start development server (interactive mode)
228411
haft dev serve -p dev
229412

413+
# Press 'r' to restart after making changes
414+
# Or trigger restart from your editor
415+
230416
# In another terminal, run tests
231417
haft dev test
232418

go.mod

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ require (
4747
golang.org/x/crypto v0.43.0 // indirect
4848
golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect
4949
golang.org/x/sync v0.17.0 // indirect
50-
golang.org/x/sys v0.37.0 // indirect
50+
golang.org/x/sys v0.39.0 // indirect
51+
golang.org/x/term v0.38.0 // indirect
5152
gopkg.in/yaml.v2 v2.4.0 // indirect
5253
)

go.sum

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,10 @@ golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBc
9393
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
9494
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ=
9595
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
96+
golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
97+
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
98+
golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
99+
golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
96100
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k=
97101
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM=
98102
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

internal/cli/dev/dev.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,17 @@ execute the appropriate underlying commands.`,
2323
haft dev test
2424
2525
# Clean build artifacts
26-
haft dev clean`,
26+
haft dev clean
27+
28+
# Trigger restart (for use with haft dev serve)
29+
haft dev restart`,
2730
}
2831

2932
cmd.AddCommand(newServeCommand())
3033
cmd.AddCommand(newBuildCommand())
3134
cmd.AddCommand(newTestCommand())
3235
cmd.AddCommand(newCleanCommand())
36+
cmd.AddCommand(newRestartCommand())
3337

3438
return cmd
3539
}

0 commit comments

Comments
 (0)