-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmagefile.go
More file actions
308 lines (246 loc) Β· 7.87 KB
/
Copy pathmagefile.go
File metadata and controls
308 lines (246 loc) Β· 7.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
//go:build mage
package main
import (
"fmt"
"os"
"path/filepath"
"runtime"
"github.com/magefile/mage/mg"
"github.com/magefile/mage/sh"
)
const (
binaryName = "devrewoh-portfolio"
dockerTag = "devrewoh-portfolio"
)
var Default = Build
// Core Development Tasks
// Generate generates templ templates
func Generate() error {
fmt.Println("π Generating templates...")
return sh.RunV("templ", "generate")
}
// Build builds the application binary
func Build() error {
mg.Deps(Generate)
fmt.Println("π¨ Building application...")
return sh.RunV("go", "build", "-o", filepath.Join("bin", binaryName), ".")
}
// Run builds and runs the application locally
func Run() error {
mg.Deps(Build)
fmt.Println("π Running application...")
return sh.RunV(filepath.Join("bin", binaryName))
}
// Dev runs development server with hot reload
func Dev() error {
fmt.Println("π Starting development server...")
// Check if air is available (use -v flag, not --version)
if err := sh.Run("air", "-v"); err != nil {
fmt.Println("β Air not found, install with: go install github.com/air-verse/air@latest")
fmt.Println("π Or run 'mage install' to install all tools")
fmt.Println("π Falling back to regular run...")
return Run()
}
// Kill any existing processes on port 8080
fmt.Println("π§Ή Cleaning up any existing processes...")
if err := sh.Run("pkill", "-f", binaryName); err != nil {
// Don't return error if no process found - that's expected
fmt.Println("π No existing processes found (this is normal)")
}
// Kill anything specifically on port 8080
if err := sh.Run("lsof", "-ti:8080"); err == nil {
fmt.Println("π Killing process on port 8080...")
sh.Run("sh", "-c", "lsof -ti:8080 | xargs kill -9")
}
// Ensure tmp directory exists for air
if err := os.MkdirAll("tmp", 0755); err != nil {
fmt.Printf("β οΈ Warning: couldn't create tmp directory: %v\n", err)
}
// Small delay to ensure ports are released
fmt.Println("β³ Waiting for port cleanup...")
sh.Run("sleep", "1")
// Run air with the config file
fmt.Println("πͺοΈ Starting Air for hot reloading...")
return sh.RunV("air", "-c", ".air.toml")
}
// DevDebug runs development server with hot reload in debug mode
func DevDebug() error {
fmt.Println("π Starting development server in debug mode...")
// Check if air is available
if err := sh.Run("air", "-v"); err != nil {
fmt.Println("β Air not found, install with: go install github.com/air-verse/air@latest")
return Run()
}
// Kill any existing processes
fmt.Println("π§Ή Cleaning up any existing processes...")
sh.Run("pkill", "-f", binaryName)
sh.Run("sh", "-c", "lsof -ti:8080 | xargs kill -9")
// Ensure tmp directory exists
if err := os.MkdirAll("tmp", 0755); err != nil {
fmt.Printf("β οΈ Warning: couldn't create tmp directory: %v\n", err)
}
// Small delay to ensure ports are released
fmt.Println("β³ Waiting for port cleanup...")
sh.Run("sleep", "1")
// Run air with debug mode
fmt.Println("π Starting Air with debug output...")
return sh.RunV("air", "-c", ".air.toml", "-d")
}
// Watch runs templ in watch mode alongside air (alternative dev mode)
func Watch() error {
fmt.Println("π Starting watch mode with templ and air...")
// Check if air is available
if err := sh.Run("air", "-v"); err != nil {
fmt.Println("β Air not found, install with: go install github.com/air-verse/air@latest")
return Run()
}
// Kill any existing processes
fmt.Println("π§Ή Cleaning up any existing processes...")
sh.Run("pkill", "-f", binaryName)
sh.Run("sh", "-c", "lsof -ti:8080 | xargs kill -9")
// Ensure tmp directory exists
if err := os.MkdirAll("tmp", 0755); err != nil {
fmt.Printf("β οΈ Warning: couldn't create tmp directory: %v\n", err)
}
// Small delay to ensure ports are released
sh.Run("sleep", "1")
// This is an alternative approach - you might prefer this
return sh.RunV("air")
}
// Quality Assurance
// Format formats Go code and templates
func Format() error {
fmt.Println("π¨ Formatting code...")
if err := sh.RunV("go", "fmt", "./..."); err != nil {
return err
}
return sh.RunV("templ", "fmt", ".")
}
// Test runs tests
func Test() error {
fmt.Println("π§ͺ Running tests...")
return sh.RunV("go", "test", "-v", "./...")
}
// TestCoverage runs tests with coverage
func TestCoverage() error {
fmt.Println("π§ͺ Running tests with coverage...")
if err := sh.RunV("go", "test", "-v", "-coverprofile=coverage.out", "./..."); err != nil {
return err
}
return sh.RunV("go", "tool", "cover", "-html=coverage.out", "-o", "coverage.html")
}
// Production Deployment
// BuildProd builds for production deployment
func BuildProd() error {
mg.Deps(Generate)
fmt.Println("π Building for production...")
env := map[string]string{
"CGO_ENABLED": "0",
"GOOS": "linux",
"GOARCH": "amd64",
}
return sh.RunWithV(env, "go", "build",
"-ldflags", "-s -w",
"-o", filepath.Join("bin", binaryName),
".")
}
// Docker Operations
// DockerBuild builds the Docker image
func DockerBuild() error {
fmt.Printf("π³ Building Docker image: %s\n", dockerTag)
return sh.RunV("docker", "build", "-t", dockerTag, ".")
}
// DockerRun runs the Docker container locally
func DockerRun() error {
mg.Deps(DockerBuild)
fmt.Printf("π³ Running Docker container: %s\n", dockerTag)
return sh.RunV("docker", "run", "-p", "8080:8080", dockerTag)
}
// Rebuild cleans and rebuilds everything
func Rebuild() error {
fmt.Println("π Rebuilding from scratch...")
mg.Deps(Clean, Build)
fmt.Println("β
Rebuild completed!")
return nil
}
// Utility Tasks
// Clean removes build artifacts
func Clean() error {
fmt.Println("π§Ή Cleaning...")
// Remove directories and files
paths := []string{
"bin/",
"tmp/",
"coverage.out",
"coverage.html",
}
for _, path := range paths {
if err := sh.Rm(path); err != nil {
fmt.Printf("β οΈ Warning: couldn't remove %s: %v\n", path, err)
}
}
// Remove generated template files
if err := sh.Run("find", ".", "-name", "*_templ.go", "-delete"); err != nil {
fmt.Printf("β οΈ Warning: couldn't remove template files: %v\n", err)
}
fmt.Println("β
Cleanup completed!")
return nil
}
// Install installs required tools
func Install() error {
fmt.Println("π¦ Installing tools...")
tools := []string{
"github.com/a-h/templ/cmd/templ@latest",
"github.com/air-verse/air@latest",
}
for _, tool := range tools {
fmt.Printf("π¦ Installing %s...\n", tool)
if err := sh.RunV("go", "install", tool); err != nil {
fmt.Printf("β οΈ Failed to install %s: %v\n", tool, err)
return err
}
fmt.Printf("β
Successfully installed %s\n", tool)
}
fmt.Println("β
All tools installed successfully!")
return nil
}
// Setup initializes the project
func Setup() error {
fmt.Println("ποΈ Setting up project...")
// Create necessary directories
dirs := []string{"bin", "tmp", "static/css", "static/images"}
for _, dir := range dirs {
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("failed to create directory %s: %w", dir, err)
}
fmt.Printf("π Created directory: %s\n", dir)
}
mg.Deps(Install, Generate)
fmt.Println("β
Setup complete! Run 'mage dev' to start development")
return nil
}
// Info shows project information
func Info() error {
fmt.Println("π Project Info:")
fmt.Printf("Binary: %s\n", binaryName)
fmt.Printf("Go: %s\n", runtime.Version())
fmt.Printf("OS/Arch: %s/%s\n", runtime.GOOS, runtime.GOARCH)
if wd, err := os.Getwd(); err == nil {
fmt.Printf("Directory: %s\n", wd)
}
// Check if tools are installed
fmt.Println("\nπ§ Tool Status:")
// Check templ
if err := sh.Run("templ", "version"); err != nil {
fmt.Printf("β templ: not installed\n")
} else {
fmt.Printf("β
templ: installed\n")
}
// Check air (air uses -v not --version)
if err := sh.Run("air", "-v"); err != nil {
fmt.Printf("β air: not installed\n")
} else {
fmt.Printf("β
air: installed\n")
}
return nil
}