mirror of
https://github.com/btouchard/ackify.git
synced 2026-01-05 20:39:39 -06:00
514 lines
9.0 KiB
Markdown
514 lines
9.0 KiB
Markdown
# Development
|
|
|
|
Guide for contributing and developing on Ackify.
|
|
|
|
## Development Setup
|
|
|
|
### Prerequisites
|
|
|
|
- **Go 1.24.5+**
|
|
- **Node.js 22+** and npm
|
|
- **PostgreSQL 16+**
|
|
- **Docker & Docker Compose**
|
|
- Git
|
|
|
|
### Clone & Setup
|
|
|
|
```bash
|
|
# Clone
|
|
git clone https://github.com/btouchard/ackify-ce.git
|
|
cd ackify-ce
|
|
|
|
# Copy .env
|
|
cp .env.example .env
|
|
|
|
# Edit .env with your OAuth2 credentials
|
|
nano .env
|
|
```
|
|
|
|
## Backend Development
|
|
|
|
### Build
|
|
|
|
```bash
|
|
cd backend
|
|
go mod download
|
|
go build ./cmd/community
|
|
```
|
|
|
|
### Run
|
|
|
|
```bash
|
|
# Start PostgreSQL with Docker
|
|
docker compose up -d ackify-db
|
|
|
|
# Apply migrations
|
|
go run ./cmd/migrate up
|
|
|
|
# Launch app
|
|
./community
|
|
```
|
|
|
|
API accessible at `http://localhost:8080`.
|
|
|
|
### Tests
|
|
|
|
```bash
|
|
# Unit tests
|
|
go test -v -short ./...
|
|
|
|
# Tests with coverage
|
|
go test -coverprofile=coverage.out ./internal/... ./pkg/...
|
|
|
|
# View coverage
|
|
go tool cover -html=coverage.out
|
|
|
|
# Integration tests (PostgreSQL required)
|
|
docker compose -f ../compose.test.yml up -d
|
|
INTEGRATION_TESTS=1 go test -tags=integration -v ./internal/infrastructure/database/
|
|
docker compose -f ../compose.test.yml down
|
|
```
|
|
|
|
### Linting
|
|
|
|
```bash
|
|
# Format
|
|
go fmt ./...
|
|
|
|
# Vet
|
|
go vet ./...
|
|
|
|
# Staticcheck (optional)
|
|
go install honnef.co/go/tools/cmd/staticcheck@latest
|
|
staticcheck ./...
|
|
```
|
|
|
|
## Frontend Development
|
|
|
|
### Setup
|
|
|
|
```bash
|
|
cd webapp
|
|
npm install
|
|
```
|
|
|
|
### Dev Server
|
|
|
|
```bash
|
|
npm run dev
|
|
```
|
|
|
|
Frontend accessible at `http://localhost:5173` with Hot Module Replacement.
|
|
|
|
### Production Build
|
|
|
|
```bash
|
|
npm run build
|
|
# Output: webapp/dist/
|
|
```
|
|
|
|
### Type Checking
|
|
|
|
```bash
|
|
npm run type-check
|
|
```
|
|
|
|
### i18n Validation
|
|
|
|
```bash
|
|
npm run lint:i18n
|
|
```
|
|
|
|
Verifies all translations are complete.
|
|
|
|
## Docker Development
|
|
|
|
### Local Build
|
|
|
|
```bash
|
|
# Build complete image (frontend + backend)
|
|
docker compose -f compose.local.yml up -d --build
|
|
|
|
# Logs
|
|
docker compose -f compose.local.yml logs -f ackify-ce
|
|
|
|
# Rebuild after changes
|
|
docker compose -f compose.local.yml up -d --force-recreate ackify-ce --build
|
|
```
|
|
|
|
### Debug
|
|
|
|
```bash
|
|
# Shell in container
|
|
docker compose exec ackify-ce sh
|
|
|
|
# PostgreSQL shell
|
|
docker compose exec ackify-db psql -U ackifyr -d ackify
|
|
```
|
|
|
|
## Code Structure
|
|
|
|
### Backend
|
|
|
|
```
|
|
backend/
|
|
├── cmd/
|
|
│ ├── community/ # main.go + dependency injection
|
|
│ └── migrate/ # Migration tool
|
|
├── internal/
|
|
│ ├── domain/models/ # Entities (User, Signature, Document)
|
|
│ ├── application/services/ # Business logic
|
|
│ ├── infrastructure/
|
|
│ │ ├── auth/ # OAuth2
|
|
│ │ ├── database/ # Repositories
|
|
│ │ ├── email/ # SMTP
|
|
│ │ └── config/ # Config
|
|
│ └── presentation/api/ # HTTP handlers
|
|
└── pkg/ # Utilities
|
|
```
|
|
|
|
### Frontend
|
|
|
|
```
|
|
webapp/src/
|
|
├── components/ # Vue components
|
|
├── pages/ # Pages (router)
|
|
├── services/ # API client
|
|
├── stores/ # Pinia stores
|
|
├── router/ # Vue Router
|
|
└── locales/ # Translations
|
|
```
|
|
|
|
## Code Conventions
|
|
|
|
### Go
|
|
|
|
**Naming**:
|
|
- Packages: lowercase, singular (`user`, `signature`)
|
|
- Interfaces: suffix `er` or descriptive (`SignatureRepository`, `EmailSender`)
|
|
- Constructors: `New...()` or `...From...()`
|
|
|
|
**Example**:
|
|
```go
|
|
// Service
|
|
type SignatureService struct {
|
|
repo SignatureRepository
|
|
crypto CryptoService
|
|
}
|
|
|
|
func NewSignatureService(repo SignatureRepository, crypto CryptoService) *SignatureService {
|
|
return &SignatureService{repo: repo, crypto: crypto}
|
|
}
|
|
|
|
// Method
|
|
func (s *SignatureService) CreateSignature(ctx context.Context, docID, userSub string) (*models.Signature, error) {
|
|
// ...
|
|
}
|
|
```
|
|
|
|
**Errors**:
|
|
```go
|
|
// Wrapping
|
|
return nil, fmt.Errorf("failed to create signature: %w", err)
|
|
|
|
// Custom errors
|
|
var ErrAlreadySigned = errors.New("user has already signed this document")
|
|
```
|
|
|
|
### TypeScript
|
|
|
|
**Naming**:
|
|
- Components: PascalCase (`DocumentCard.vue`)
|
|
- Composables: camelCase with `use` prefix (`useAuth.ts`)
|
|
- Stores: camelCase with `Store` suffix (`userStore.ts`)
|
|
|
|
**Example**:
|
|
```typescript
|
|
// Composable
|
|
export function useAuth() {
|
|
const user = ref<User | null>(null)
|
|
|
|
async function login() {
|
|
// ...
|
|
}
|
|
|
|
return { user, login }
|
|
}
|
|
|
|
// Store
|
|
export const useUserStore = defineStore('user', () => {
|
|
const currentUser = ref<User | null>(null)
|
|
|
|
async function fetchMe() {
|
|
const { data } = await api.get('/users/me')
|
|
currentUser.value = data
|
|
}
|
|
|
|
return { currentUser, fetchMe }
|
|
})
|
|
```
|
|
|
|
## Adding a Feature
|
|
|
|
### 1. Planning
|
|
|
|
- Define required API endpoints
|
|
- SQL schema if needed
|
|
- User interface
|
|
|
|
### 2. Backend
|
|
|
|
```bash
|
|
# 1. Create migration if needed
|
|
touch backend/migrations/XXXX_my_feature.up.sql
|
|
touch backend/migrations/XXXX_my_feature.down.sql
|
|
|
|
# 2. Create model
|
|
# backend/internal/domain/models/my_model.go
|
|
|
|
# 3. Create repository interface
|
|
# backend/internal/application/services/my_service.go
|
|
|
|
# 4. Implement repository
|
|
# backend/internal/infrastructure/database/my_repository.go
|
|
|
|
# 5. Create API handler
|
|
# backend/internal/presentation/api/myfeature/handler.go
|
|
|
|
# 6. Register routes
|
|
# backend/internal/presentation/api/router.go
|
|
```
|
|
|
|
### 3. Frontend
|
|
|
|
```bash
|
|
# 1. Create API service
|
|
# webapp/src/services/myFeatureService.ts
|
|
|
|
# 2. Create Pinia store
|
|
# webapp/src/stores/myFeatureStore.ts
|
|
|
|
# 3. Create components
|
|
# webapp/src/components/MyFeature.vue
|
|
|
|
# 4. Add translations
|
|
# webapp/src/locales/{fr,en,es,de,it}.json
|
|
|
|
# 5. Add routes if needed
|
|
# webapp/src/router/index.ts
|
|
```
|
|
|
|
### 4. Tests
|
|
|
|
```bash
|
|
# Backend
|
|
# backend/internal/presentation/api/myfeature/handler_test.go
|
|
|
|
# Test
|
|
go test -v ./internal/presentation/api/myfeature/
|
|
```
|
|
|
|
### 5. Documentation
|
|
|
|
Update:
|
|
- `/api/openapi.yaml` - OpenAPI specification
|
|
- `/docs/api.md` - API documentation
|
|
- `/docs/features/my-feature.md` - User guide
|
|
|
|
## Debugging
|
|
|
|
### Backend
|
|
|
|
```go
|
|
// Structured logs
|
|
logger.Info("signature created",
|
|
"doc_id", docID,
|
|
"user_sub", userSub,
|
|
"signature_id", sig.ID,
|
|
)
|
|
|
|
// Debug via Delve (optional)
|
|
dlv debug ./cmd/community
|
|
```
|
|
|
|
### Frontend
|
|
|
|
```typescript
|
|
// Vue DevTools (Chrome/Firefox extension)
|
|
// Inspect: Components, Pinia stores, Router
|
|
|
|
// Console debug
|
|
console.log('[DEBUG] User:', user.value)
|
|
|
|
// Breakpoints via browser
|
|
debugger
|
|
```
|
|
|
|
## SQL Migrations
|
|
|
|
### Create Migration
|
|
|
|
```sql
|
|
-- XXXX_add_field.up.sql
|
|
ALTER TABLE signatures ADD COLUMN new_field TEXT;
|
|
|
|
-- XXXX_add_field.down.sql
|
|
ALTER TABLE signatures DROP COLUMN new_field;
|
|
```
|
|
|
|
### Apply
|
|
|
|
```bash
|
|
go run ./cmd/migrate up
|
|
```
|
|
|
|
### Rollback
|
|
|
|
```bash
|
|
go run ./cmd/migrate down
|
|
```
|
|
|
|
## Integration Tests
|
|
|
|
### Setup PostgreSQL Test
|
|
|
|
```bash
|
|
docker compose -f compose.test.yml up -d
|
|
```
|
|
|
|
### Run Tests
|
|
|
|
```bash
|
|
INTEGRATION_TESTS=1 go test -tags=integration -v ./internal/infrastructure/database/
|
|
```
|
|
|
|
### Cleanup
|
|
|
|
```bash
|
|
docker compose -f compose.test.yml down -v
|
|
```
|
|
|
|
## CI/CD
|
|
|
|
### GitHub Actions
|
|
|
|
Project uses `.github/workflows/ci.yml`:
|
|
|
|
**Jobs**:
|
|
1. **Lint** - go fmt, go vet, eslint
|
|
2. **Test Backend** - Unit + integration tests
|
|
3. **Test Frontend** - Type checking + i18n validation
|
|
4. **Coverage** - Upload to Codecov
|
|
5. **Build** - Verify Docker image builds
|
|
|
|
### Pre-commit Hooks (optional)
|
|
|
|
```bash
|
|
# Install pre-commit
|
|
pip install pre-commit
|
|
|
|
# Setup hooks
|
|
pre-commit install
|
|
|
|
# Run manually
|
|
pre-commit run --all-files
|
|
```
|
|
|
|
## Contribution
|
|
|
|
### Git Workflow
|
|
|
|
```bash
|
|
# 1. Create branch
|
|
git checkout -b feature/my-feature
|
|
|
|
# 2. Develop + commit
|
|
git add .
|
|
git commit -m "feat: add my feature"
|
|
|
|
# 3. Push
|
|
git push origin feature/my-feature
|
|
|
|
# 4. Create Pull Request on GitHub
|
|
```
|
|
|
|
### Commit Messages
|
|
|
|
Format: `type: description`
|
|
|
|
**Types**:
|
|
- `feat` - New feature
|
|
- `fix` - Bug fix
|
|
- `docs` - Documentation
|
|
- `refactor` - Refactoring
|
|
- `test` - Tests
|
|
- `chore` - Maintenance
|
|
|
|
**Examples**:
|
|
```
|
|
feat: add checksum verification feature
|
|
fix: resolve OAuth callback redirect loop
|
|
docs: update API documentation for signatures
|
|
refactor: simplify signature service logic
|
|
test: add integration tests for expected signers
|
|
```
|
|
|
|
### Code Review
|
|
|
|
**Checklist**:
|
|
- ✅ Tests pass (CI green)
|
|
- ✅ Code formatted (`go fmt`, `eslint`)
|
|
- ✅ No committed secrets
|
|
- ✅ Documentation updated
|
|
- ✅ Complete translations (i18n)
|
|
|
|
## Troubleshooting
|
|
|
|
### Backend won't start
|
|
|
|
```bash
|
|
# Check PostgreSQL
|
|
docker compose ps ackify-db
|
|
docker compose logs ackify-db
|
|
|
|
# Check environment variables
|
|
cat .env
|
|
|
|
# Detailed logs
|
|
ACKIFY_LOG_LEVEL=debug ./community
|
|
```
|
|
|
|
### Frontend build fails
|
|
|
|
```bash
|
|
# Clean and reinstall
|
|
rm -rf node_modules package-lock.json
|
|
npm install
|
|
|
|
# Check Node version
|
|
node --version # Should be 22+
|
|
```
|
|
|
|
### Tests fail
|
|
|
|
```bash
|
|
# Backend - check PostgreSQL test
|
|
docker compose -f compose.test.yml ps
|
|
|
|
# Frontend - check types
|
|
npm run type-check
|
|
```
|
|
|
|
## Resources
|
|
|
|
- [Go Documentation](https://go.dev/doc/)
|
|
- [Vue 3 Guide](https://vuejs.org/guide/)
|
|
- [PostgreSQL Docs](https://www.postgresql.org/docs/)
|
|
- [Chi Router](https://github.com/go-chi/chi)
|
|
- [Pinia](https://pinia.vuejs.org/)
|
|
|
|
## Support
|
|
|
|
- [GitHub Issues](https://github.com/btouchard/ackify-ce/issues)
|
|
- [GitHub Discussions](https://github.com/btouchard/ackify-ce/discussions)
|