Skip to content

Commit f8e1ecb

Browse files
committed
Add GitHub Actions for CI & Releases
1 parent 38b52ee commit f8e1ecb

File tree

4 files changed

+173
-2
lines changed

4 files changed

+173
-2
lines changed

cmd/common.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ func getSSHKeys() string {
5858
if err != nil {
5959
log.Fatalf("Error fetching SSH keys: %v", err)
6060
}
61-
return strings.TrimSpace(strings.ReplaceAll(output, "\n", ","))
61+
// Trim trailing comma
62+
return strings.TrimRight(strings.TrimSpace(strings.ReplaceAll(output, "\n", ",")), ",")
6263
}
6364

6465
// fzfSelect presents a list of options using fzf and returns the selected line

cmd/common_test.go

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package cmd
2+
3+
import (
4+
"os/exec"
5+
"strings"
6+
"testing"
7+
)
8+
9+
// Test validateAndGetRepoURL function
10+
func TestValidateAndGetRepoURL(t *testing.T) {
11+
tests := []struct {
12+
input string
13+
expected string
14+
}{
15+
{"https://github.com/wilmoore/pro.git", "https://github.com/wilmoore/pro.git"},
16+
{"wilmoore/pro", "https://github.com/wilmoore/pro.git"},
17+
}
18+
19+
for _, test := range tests {
20+
result := validateAndGetRepoURL(test.input)
21+
if result != test.expected {
22+
t.Errorf("validateAndGetRepoURL(%q) = %q; want %q", test.input, result, test.expected)
23+
}
24+
}
25+
}
26+
27+
// Test processTags function
28+
func TestProcessTags(t *testing.T) {
29+
tests := []struct {
30+
providerTag string
31+
cliTags string
32+
expected string
33+
}{
34+
{"digitalocean", "web,db", "pro,digitalocean,web,db"},
35+
{"aws", "", "pro,aws"},
36+
{"gcp", "backend,api", "pro,gcp,backend,api"},
37+
}
38+
39+
for _, test := range tests {
40+
result := processTags(test.providerTag, test.cliTags)
41+
if result != test.expected {
42+
t.Errorf("processTags(%q, %q) = %q; want %q", test.providerTag, test.cliTags, result, test.expected)
43+
}
44+
}
45+
}
46+
47+
// Test generateCloudInit function
48+
func TestGenerateCloudInit(t *testing.T) {
49+
repoURL := "https://github.com/wilmoore/pro.git"
50+
branch := "main"
51+
playbookPath := "src/pro"
52+
53+
result := generateCloudInit(repoURL, branch, playbookPath)
54+
55+
expectedParts := []string{
56+
"git clone -b main https://github.com/wilmoore/pro.git /opt/ansible",
57+
"cd /opt/ansible/src/pro",
58+
"ansible-playbook -i \"localhost,\" -c local playbook.yml",
59+
}
60+
61+
for _, part := range expectedParts {
62+
if !strings.Contains(result, part) {
63+
t.Errorf("generateCloudInit() missing expected content: %q", part)
64+
}
65+
}
66+
}
67+
68+
// Test getSSHKeys function
69+
func TestGetSSHKeys(t *testing.T) {
70+
// Mock doctl response
71+
mockOutput := "123456\n789012\n"
72+
cmd := exec.Command("bash", "-c", "echo -n '"+mockOutput+"'") // Simulate doctl output
73+
74+
output, err := cmd.Output()
75+
if err != nil {
76+
t.Fatalf("Error executing mock command: %v", err)
77+
}
78+
79+
expected := "123456,789012"
80+
result := strings.TrimRight(strings.TrimSpace(strings.ReplaceAll(string(output), "\n", ",")), ",")
81+
if result != expected {
82+
t.Errorf("getSSHKeys() = %q; want %q", result, expected)
83+
}
84+
}
85+
86+
// Test runCommand function
87+
func TestRunCommand(t *testing.T) {
88+
output, err := runCommand("echo", "hello")
89+
if err != nil {
90+
t.Fatalf("runCommand() failed: %v", err)
91+
}
92+
expected := "hello\n"
93+
if output != expected {
94+
t.Errorf("runCommand() = %q; want %q", output, expected)
95+
}
96+
}
97+
98+
// Test fzfSelect function (mocked)
99+
func TestFzfSelect(t *testing.T) {
100+
mockOptions := []string{"Option 1", "Option 2", "Option 3"}
101+
102+
// Mock fzf by using `echo` to select the first option
103+
cmd := exec.Command("bash", "-c", "echo 'Option 1'")
104+
cmd.Stdin = strings.NewReader(strings.Join(mockOptions, "\n"))
105+
106+
output, err := cmd.Output()
107+
if err != nil {
108+
t.Fatalf("fzfSelect() mock failed: %v", err)
109+
}
110+
111+
expected := "Option 1"
112+
result := strings.TrimSpace(string(output))
113+
if result != expected {
114+
t.Errorf("fzfSelect() = %q; want %q", result, expected)
115+
}
116+
}

cmd/root.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Supports multiple cloud providers including DigitalOcean, AWS, Azure, GCP, and O
1616

1717
// Custom help function to separate commands
1818
func customHelpFunc(cmd *cobra.Command, args []string) {
19-
fmt.Println("\n🚀 PRO CLI: Cloud Server Provisioning\n")
19+
fmt.Println("🚀 PRO CLI: Cloud Server Provisioning")
2020
fmt.Println("Usage:")
2121
fmt.Printf(" %s [command]\n\n", cmd.Name())
2222

makefile

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Project Variables
2+
PROJECT_NAME = pro
3+
VERSION = v1.0.0
4+
BUILD_DIR = dist
5+
6+
# List of supported OS and architectures
7+
OS_LIST = linux darwin windows
8+
ARCH_LIST = amd64 arm64
9+
10+
# Default target (runs tests)
11+
.PHONY: all
12+
all: test build
13+
14+
# 🛠 Build binary for the current system
15+
.PHONY: build
16+
build:
17+
@echo "🔨 Building $(PROJECT_NAME)..."
18+
@go build -o $(BUILD_DIR)/$(PROJECT_NAME) main.go
19+
20+
# 🛠 Build binaries for all platforms
21+
.PHONY: build-all
22+
build-all:
23+
@echo "🚀 Building $(PROJECT_NAME) for all platforms..."
24+
@mkdir -p $(BUILD_DIR)
25+
@for OS in $(OS_LIST); do \
26+
for ARCH in $(ARCH_LIST); do \
27+
echo "🔨 Building for $$OS/$$ARCH..."; \
28+
GOOS=$$OS GOARCH=$$ARCH go build -o $(BUILD_DIR)/$(PROJECT_NAME)-$$OS-$$ARCH main.go; \
29+
done; \
30+
done
31+
32+
# ✅ Run tests
33+
.PHONY: test
34+
test:
35+
@echo "✅ Running tests..."
36+
@go test ./cmd -v
37+
38+
# 🏗️ Clean build artifacts
39+
.PHONY: clean
40+
clean:
41+
@echo "🗑️ Cleaning up..."
42+
@rm -rf $(BUILD_DIR)
43+
44+
# 📦 Create a GitHub release
45+
.PHONY: release
46+
release: build-all
47+
@echo "🚀 Releasing $(VERSION)..."
48+
@git tag $(VERSION)
49+
@git push origin $(VERSION)
50+
@gh release create $(VERSION) $(BUILD_DIR)/* --title "$(PROJECT_NAME) $(VERSION)" --notes "Release $(VERSION)"
51+
52+
# 🏗 Run all steps before a release
53+
.PHONY: prepare-release
54+
prepare-release: clean test build-all

0 commit comments

Comments
 (0)