Skip to content

Commit 711fd6d

Browse files
committed
fix: add CONTRIBUTING.md and cmd tests (critical issues)
1 parent e2b5492 commit 711fd6d

File tree

2 files changed

+391
-0
lines changed

2 files changed

+391
-0
lines changed

CONTRIBUTING.md

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,269 @@
1+
# Contributing to ASK (Agent Skills Kit)
2+
3+
Thank you for your interest in contributing to ASK! This document provides guidelines and instructions for contributing.
4+
5+
## Table of Contents
6+
7+
- [Code of Conduct](#code-of-conduct)
8+
- [Getting Started](#getting-started)
9+
- [Development Setup](#development-setup)
10+
- [Making Changes](#making-changes)
11+
- [Testing](#testing)
12+
- [Submitting Changes](#submitting-changes)
13+
- [Style Guide](#style-guide)
14+
15+
## Code of Conduct
16+
17+
By participating in this project, you agree to maintain a respectful and inclusive environment for all contributors.
18+
19+
## Getting Started
20+
21+
### Prerequisites
22+
23+
- Go 1.21 or higher
24+
- Git
25+
- A GitHub account
26+
27+
### Development Setup
28+
29+
1. **Fork the repository**
30+
```bash
31+
# Fork on GitHub, then clone your fork
32+
git clone https://github.com/YOUR_USERNAME/ask.git
33+
cd ask
34+
```
35+
36+
2. **Install dependencies**
37+
```bash
38+
go mod download
39+
```
40+
41+
3. **Build the project**
42+
```bash
43+
make build
44+
```
45+
46+
4. **Run tests**
47+
```bash
48+
make test
49+
```
50+
51+
5. **Verify everything works**
52+
```bash
53+
./ask --help
54+
```
55+
56+
## Making Changes
57+
58+
### Branch Naming
59+
60+
Use descriptive branch names:
61+
- `feature/add-xyz` - for new features
62+
- `fix/issue-123` - for bug fixes
63+
- `docs/update-readme` - for documentation
64+
- `refactor/cleanup-xyz` - for refactoring
65+
66+
### Commit Messages
67+
68+
Follow the [Conventional Commits](https://www.conventionalcommits.org/) specification:
69+
70+
```
71+
<type>(<scope>): <description>
72+
73+
[optional body]
74+
75+
[optional footer]
76+
```
77+
78+
**Types:**
79+
- `feat`: New feature
80+
- `fix`: Bug fix
81+
- `docs`: Documentation changes
82+
- `test`: Adding or updating tests
83+
- `refactor`: Code refactoring
84+
- `chore`: Maintenance tasks
85+
- `ci`: CI/CD changes
86+
87+
**Examples:**
88+
```bash
89+
feat(search): add regex support for skill search
90+
fix(install): handle network timeout gracefully
91+
docs: update installation guide for Windows
92+
test: add integration tests for repo commands
93+
```
94+
95+
## Testing
96+
97+
### Running Tests
98+
99+
```bash
100+
# Run all tests
101+
make test
102+
103+
# Run tests with coverage
104+
go test -coverprofile=coverage.out ./...
105+
go tool cover -html=coverage.out
106+
107+
# Run specific package tests
108+
go test ./internal/config -v
109+
110+
# Run individual test
111+
go test ./internal/config -run TestDefaultConfig -v
112+
```
113+
114+
### Writing Tests
115+
116+
- Place test files next to the code they test (`filename_test.go`)
117+
- Use table-driven tests where appropriate
118+
- Aim for at least 60% code coverage
119+
- Test both success and error cases
120+
- Mock external dependencies (git, GitHub API)
121+
122+
**Example:**
123+
```go
124+
func TestSkillInstall(t *testing.T) {
125+
tests := []struct {
126+
name string
127+
skill string
128+
wantErr bool
129+
}{
130+
{"valid skill", "browser-use", false},
131+
{"invalid skill", "", true},
132+
}
133+
134+
for _, tt := range tests {
135+
t.Run(tt.name, func(t *testing.T) {
136+
err := installSkill(tt.skill)
137+
if (err != nil) != tt.wantErr {
138+
t.Errorf("installSkill() error = %v, wantErr %v", err, tt.wantErr)
139+
}
140+
})
141+
}
142+
}
143+
```
144+
145+
### Test Requirements
146+
147+
All PRs must:
148+
- Include tests for new features
149+
- Maintain or improve code coverage
150+
- Pass all existing tests
151+
- Pass `go vet` and `go fmt` checks
152+
153+
## Submitting Changes
154+
155+
### Pull Request Process
156+
157+
1. **Update your fork**
158+
```bash
159+
git checkout main
160+
git pull upstream main
161+
git push origin main
162+
```
163+
164+
2. **Create a feature branch**
165+
```bash
166+
git checkout -b feature/your-feature-name
167+
```
168+
169+
3. **Make your changes**
170+
- Write clean, readable code
171+
- Add tests
172+
- Update documentation
173+
174+
4. **Commit your changes**
175+
```bash
176+
git add .
177+
git commit -m "feat: your feature description"
178+
```
179+
180+
5. **Push to your fork**
181+
```bash
182+
git push origin feature/your-feature-name
183+
```
184+
185+
6. **Create a Pull Request**
186+
- Go to the [ASK repository](https://github.com/yeasy/ask)
187+
- Click "New Pull Request"
188+
- Select your branch
189+
- Fill in the PR template
190+
- Link related issues
191+
192+
### PR Checklist
193+
194+
Before submitting, ensure:
195+
- [ ] Code builds successfully (`make build`)
196+
- [ ] All tests pass (`make test`)
197+
- [ ] Code is formatted (`make fmt`)
198+
- [ ] No linter warnings (`make vet`)
199+
- [ ] Documentation is updated (if needed)
200+
- [ ] CHANGELOG.md is updated (if applicable)
201+
- [ ] Commit messages follow convention
202+
- [ ] Branch is up-to-date with main
203+
204+
## Style Guide
205+
206+
### Go Code Style
207+
208+
Follow the official [Go Code Review Comments](https://go.dev/wiki/CodeReviewComments).
209+
210+
**Key points:**
211+
- Use `gofmt` for formatting
212+
- Use meaningful variable names
213+
- Add comments for exported functions
214+
- Keep functions small and focused
215+
- Handle errors explicitly
216+
- Use early returns to reduce nesting
217+
218+
**Example:**
219+
```go
220+
// SearchSkills searches for skills matching the given keyword across all sources.
221+
// Returns a slice of skills or an error if the search fails.
222+
func SearchSkills(keyword string) ([]Skill, error) {
223+
if keyword == "" {
224+
return nil, fmt.Errorf("keyword cannot be empty")
225+
}
226+
227+
// Search logic here...
228+
229+
return skills, nil
230+
}
231+
```
232+
233+
### File Organization
234+
235+
```
236+
ask/
237+
├── cmd/ # Command implementations
238+
│ ├── root.go # Root command
239+
│ ├── skill.go # Skill subcommand
240+
│ └── *.go # Other commands
241+
├── internal/ # Private packages
242+
│ ├── config/ # Configuration handling
243+
│ ├── git/ # Git operations
244+
│ └── github/ # GitHub API client
245+
├── docs/ # Documentation
246+
└── main.go # Entry point
247+
```
248+
249+
### Documentation
250+
251+
- Update README.md for user-facing changes
252+
- Update docs/ for detailed guides
253+
- Add godoc comments for exported functions
254+
- Include examples in documentation
255+
256+
## Getting Help
257+
258+
- **Questions**: Open a [Discussion](https://github.com/yeasy/ask/discussions)
259+
- **Bugs**: Open an [Issue](https://github.com/yeasy/ask/issues)
260+
- **Security**: See [SECURITY.md](SECURITY.md)
261+
262+
## Recognition
263+
264+
Contributors will be acknowledged in:
265+
- Release notes
266+
- Contributors list
267+
- Special mentions for significant contributions
268+
269+
Thank you for contributing to ASK! 🚀

cmd/cmd_test.go

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
package cmd
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
)
7+
8+
func TestRootCommand(t *testing.T) {
9+
// Reset args before test
10+
rootCmd.SetArgs([]string{"--help"})
11+
12+
var buf bytes.Buffer
13+
rootCmd.SetOut(&buf)
14+
rootCmd.SetErr(&buf)
15+
16+
err := rootCmd.Execute()
17+
if err != nil {
18+
t.Errorf("root command failed: %v", err)
19+
}
20+
21+
output := buf.String()
22+
if output == "" {
23+
t.Error("expected help output, got empty string")
24+
}
25+
26+
// Verify key sections are present in help
27+
expectedSections := []string{
28+
"skill",
29+
"repo",
30+
"init",
31+
}
32+
33+
for _, section := range expectedSections {
34+
if !bytes.Contains([]byte(output), []byte(section)) {
35+
t.Errorf("expected help to contain '%s'", section)
36+
}
37+
}
38+
}
39+
40+
func TestSkillCommandHelp(t *testing.T) {
41+
// Create a new root command for testing to avoid state pollution
42+
cmd := rootCmd
43+
cmd.SetArgs([]string{"skill", "--help"})
44+
45+
var buf bytes.Buffer
46+
cmd.SetOut(&buf)
47+
cmd.SetErr(&buf)
48+
49+
err := cmd.Execute()
50+
if err != nil {
51+
t.Errorf("skill command failed: %v", err)
52+
}
53+
54+
output := buf.String()
55+
if output == "" {
56+
t.Error("expected skill help output, got empty string")
57+
}
58+
59+
// Verify at least some subcommands are listed
60+
// Note: We check for a few key ones rather than all to make test less brittle
61+
expectedCommands := []string{
62+
"search",
63+
"install",
64+
"list",
65+
}
66+
67+
for _, cmd := range expectedCommands {
68+
if !bytes.Contains([]byte(output), []byte(cmd)) {
69+
t.Errorf("expected skill help to contain '%s' command", cmd)
70+
}
71+
}
72+
}
73+
74+
func TestRepoCommandHelp(t *testing.T) {
75+
cmd := rootCmd
76+
cmd.SetArgs([]string{"repo", "--help"})
77+
78+
var buf bytes.Buffer
79+
cmd.SetOut(&buf)
80+
cmd.SetErr(&buf)
81+
82+
err := cmd.Execute()
83+
if err != nil {
84+
t.Errorf("repo command failed: %v", err)
85+
}
86+
87+
output := buf.String()
88+
if output == "" {
89+
t.Error("expected repo help output, got empty string")
90+
}
91+
92+
// Verify subcommands are listed
93+
expectedCommands := []string{
94+
"add",
95+
"list",
96+
}
97+
98+
for _, cmd := range expectedCommands {
99+
if !bytes.Contains([]byte(output), []byte(cmd)) {
100+
t.Errorf("expected repo help to contain '%s' command", cmd)
101+
}
102+
}
103+
}
104+
105+
func TestInitCommandHelp(t *testing.T) {
106+
cmd := rootCmd
107+
cmd.SetArgs([]string{"init", "--help"})
108+
109+
var buf bytes.Buffer
110+
cmd.SetOut(&buf)
111+
cmd.SetErr(&buf)
112+
113+
err := cmd.Execute()
114+
if err != nil {
115+
t.Errorf("init command help failed: %v", err)
116+
}
117+
118+
output := buf.String()
119+
if !bytes.Contains([]byte(output), []byte("Initialize")) {
120+
t.Error("expected init help to contain 'Initialize'")
121+
}
122+
}

0 commit comments

Comments
 (0)