Skip to content

Contributing Guide

Marc Sanchis edited this page Jun 5, 2025 · 1 revision

Contributing Guide

Welcome to the Hyperloop UPV Control Station project! This guide will help you contribute effectively to our mission-critical software.

🎯 Overview

We welcome contributions from team members, collaborators, and the broader hyperloop community. This guide outlines our development process, standards, and best practices.

Project Goals

  • Safety First: All code must prioritize system safety and reliability
  • Real-Time Performance: Maintain sub-millisecond response times for critical operations
  • Cross-Platform Support: Ensure compatibility across Windows, macOS, and Linux
  • Modular Design: Keep components loosely coupled and highly cohesive

πŸš€ Getting Started

1. Development Environment Setup

Before contributing, ensure you have a properly configured development environment:

# Clone the repository
git clone https://github.com/HyperloopUPV-H8/software.git
cd software

# Follow the setup guide
# See: Development-Environment-Setup.md

2. Understanding the Codebase

Review these essential documents:

3. Setting Up Your Development Workflow

# Create a feature branch
git checkout -b feature/your-feature-name

# Set up pre-commit hooks (recommended)
npm install -g pre-commit
pre-commit install

πŸ”„ Development Workflow

Branch Strategy

We use a simplified Git flow:

main (production-ready)
β”œβ”€β”€ develop (integration branch)
β”‚   β”œβ”€β”€ feature/new-sensor-integration
β”‚   β”œβ”€β”€ feature/ui-improvements
β”‚   └── bugfix/blcu-communication-fix
└── hotfix/critical-security-patch

Branch Naming Convention

  • Features: feature/description-of-feature
  • Bug fixes: bugfix/description-of-fix
  • Hotfixes: hotfix/critical-issue-description
  • Documentation: docs/documentation-update

Development Process

  1. Create Issue: Start by creating a GitHub issue describing your planned work
  2. Create Branch: Create a feature branch from develop
  3. Develop: Implement your changes following our coding standards
  4. Test: Ensure all tests pass and add new tests for your code
  5. Document: Update documentation as needed
  6. Submit PR: Create a pull request for review

πŸ“ Coding Standards

Go Backend Standards

Code Style

// Use gofmt and golint
go fmt ./...
golint ./...

// Package naming: lowercase, single word
package vehicle

// Function naming: PascalCase for exported, camelCase for internal
func ProcessSensorData() error { /* exported */ }
func parsePacket() error { /* internal */ }

// Constants: PascalCase with descriptive names
const (
    DefaultTimeout = 30 * time.Second
    MaxRetries     = 3
)

Error Handling

// Always handle errors explicitly
data, err := readSensorData()
if err != nil {
    return fmt.Errorf("failed to read sensor data: %w", err)
}

// Use structured logging
log.WithFields(log.Fields{
    "sensor_id": sensorID,
    "error":     err,
}).Error("Sensor read failed")

Concurrency Best Practices

// Use contexts for cancellation
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

// Protect shared state with mutexes
type SafeCounter struct {
    mu    sync.RWMutex
    value int
}

func (c *SafeCounter) Inc() {
    c.mu.Lock()
    defer c.mu.Unlock()
    c.value++
}

TypeScript Frontend Standards

Code Style

// Use Prettier and ESLint
npm run format
npm run lint

// Interface naming: PascalCase with 'I' prefix for complex types
interface ISensorData {
  id: number;
  value: number;
  timestamp: Date;
}

// Component naming: PascalCase
const SensorDisplay: React.FC<ISensorDisplayProps> = ({ data }) => {
  // Component implementation
};

// Hook naming: camelCase starting with 'use'
const useSensorData = (sensorId: string) => {
  // Hook implementation
};

State Management

// Use Redux Toolkit for global state
const sensorsSlice = createSlice({
  name: 'sensors',
  initialState,
  reducers: {
    updateSensorData: (state, action) => {
      state.sensors[action.payload.id] = action.payload.data;
    },
  },
});

// Use Zustand for local component state
const useLocalState = create<LocalState>((set) => ({
  isLoading: false,
  setLoading: (loading) => set({ isLoading: loading }),
}));

Performance Considerations

// Use React.memo for expensive components
const ExpensiveComponent = React.memo(({ data }) => {
  // Component implementation
});

// Use useMemo for expensive calculations
const processedData = useMemo(() => {
  return expensiveCalculation(rawData);
}, [rawData]);

// Use useCallback for event handlers
const handleClick = useCallback((id: string) => {
  onSensorClick(id);
}, [onSensorClick]);

πŸ§ͺ Testing Guidelines

Backend Testing

Unit Tests

// Test file naming: *_test.go
func TestProcessSensorData(t *testing.T) {
    // Arrange
    input := &SensorData{ID: 1, Value: 42.0}
    
    // Act
    result, err := ProcessSensorData(input)
    
    // Assert
    assert.NoError(t, err)
    assert.Equal(t, expected, result)
}

// Use table-driven tests for multiple scenarios
func TestValidateInput(t *testing.T) {
    tests := []struct {
        name    string
        input   string
        wantErr bool
    }{
        {"valid input", "valid", false},
        {"invalid input", "", true},
    }
    
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            err := ValidateInput(tt.input)
            if (err != nil) != tt.wantErr {
                t.Errorf("ValidateInput() error = %v, wantErr %v", err, tt.wantErr)
            }
        })
    }
}

Integration Tests

func TestSensorIntegration(t *testing.T) {
    // Setup test environment
    server := startTestServer()
    defer server.Close()
    
    // Test real scenarios
    client := NewClient(server.URL)
    response, err := client.GetSensorData("sensor1")
    
    assert.NoError(t, err)
    assert.NotNil(t, response)
}

Frontend Testing

Component Tests

// Use React Testing Library
import { render, screen, fireEvent } from '@testing-library/react';
import { SensorDisplay } from './SensorDisplay';

describe('SensorDisplay', () => {
  it('displays sensor data correctly', () => {
    const mockData = { id: 1, value: 42, timestamp: new Date() };
    
    render(<SensorDisplay data={mockData} />);
    
    expect(screen.getByText('42')).toBeInTheDocument();
  });
  
  it('handles click events', () => {
    const handleClick = jest.fn();
    render(<SensorDisplay data={mockData} onClick={handleClick} />);
    
    fireEvent.click(screen.getByRole('button'));
    
    expect(handleClick).toHaveBeenCalledWith(mockData.id);
  });
});

Hook Tests

import { renderHook, act } from '@testing-library/react';
import { useSensorData } from './useSensorData';

describe('useSensorData', () => {
  it('fetches sensor data', async () => {
    const { result } = renderHook(() => useSensorData('sensor1'));
    
    await act(async () => {
      // Wait for async operations
    });
    
    expect(result.current.data).toBeDefined();
    expect(result.current.isLoading).toBe(false);
  });
});

Test Coverage Requirements

  • Backend: Minimum 80% coverage for critical paths
  • Frontend: Minimum 70% coverage for components and hooks
  • Integration: Cover all API endpoints and user workflows
# Check backend coverage
cd backend
go test -cover ./...

# Check frontend coverage
cd control-station
npm run test:coverage

πŸ“š Documentation Standards

Code Documentation

Go Documentation

// Package comment describes the package purpose
// Package vehicle manages pod vehicle state and board communication.
package vehicle

// Function comments explain purpose, parameters, and return values
// ProcessSensorData validates and processes incoming sensor measurements.
// It returns the processed data or an error if validation fails.
//
// Parameters:
//   - data: Raw sensor data from the vehicle
//
// Returns:
//   - *ProcessedData: Validated and normalized sensor data
//   - error: Validation or processing error
func ProcessSensorData(data *SensorData) (*ProcessedData, error) {
    // Implementation
}

TypeScript Documentation

/**
 * Hook for managing sensor data state and real-time updates
 * 
 * @param sensorId - Unique identifier for the sensor
 * @param options - Configuration options for data fetching
 * @returns Object containing sensor data, loading state, and error state
 * 
 * @example
 * ```typescript
 * const { data, isLoading, error } = useSensorData('VCU_SPEED', {
 *   refreshInterval: 1000
 * });
 * ```
 */
export const useSensorData = (
  sensorId: string,
  options?: SensorDataOptions
): SensorDataHook => {
  // Implementation
};

Documentation Files

README Updates

When adding new features, update relevant README files:

  • Root README.md: High-level project overview
  • Package READMEs: Component-specific documentation
  • Wiki Pages: Detailed guides and tutorials

Change Documentation

Document significant changes in:

  • CHANGELOG.md: User-facing changes
  • Migration guides: Breaking changes
  • Wiki updates: New features and procedures

πŸ” Code Review Process

Pull Request Guidelines

PR Title Format

<type>(<scope>): <description>

Examples:
feat(backend): add BLCU firmware upload support
fix(frontend): resolve WebSocket reconnection issues
docs(wiki): update installation guide for Windows

PR Description Template

## Summary
Brief description of changes and motivation.

## Changes Made
- List of specific changes
- New features or fixes implemented
- Files modified

## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests pass
- [ ] Manual testing completed
- [ ] Cross-platform testing (if applicable)

## Documentation
- [ ] Code comments updated
- [ ] README updated (if needed)
- [ ] Wiki documentation updated (if needed)

## Breaking Changes
List any breaking changes and migration steps.

## Related Issues
Closes #123
Relates to #456

Review Checklist

For Reviewers

  • Code Quality: Follows coding standards
  • Security: No security vulnerabilities introduced
  • Performance: No performance regressions
  • Tests: Adequate test coverage
  • Documentation: Changes are documented
  • Backwards Compatibility: No unexpected breaking changes

For Authors

  • Self-Review: Code reviewed by author first
  • Tests Pass: All automated tests pass
  • Linting: Code passes all linting checks
  • Manual Testing: Functionality tested manually
  • Documentation: All changes documented

πŸš€ Release Process

Version Management

We follow Semantic Versioning:

  • MAJOR: Breaking changes
  • MINOR: New features (backwards compatible)
  • PATCH: Bug fixes (backwards compatible)

Release Checklist

  1. Pre-Release

    • All tests pass
    • Documentation updated
    • CHANGELOG.md updated
    • Version numbers incremented
  2. Release

    • Create release branch
    • Build and test release artifacts
    • Create GitHub release
    • Deploy to production (if applicable)
  3. Post-Release

    • Monitor for issues
    • Update documentation
    • Communicate changes to team

πŸ›‘οΈ Security Guidelines

Security Best Practices

Code Security

  • Input Validation: Validate all external inputs
  • Error Handling: Don't leak sensitive information in errors
  • Authentication: Secure all API endpoints appropriately
  • Encryption: Use TLS for all network communications

Dependency Management

# Regularly audit dependencies
npm audit
go list -m -u all

# Update dependencies carefully
npm update
go get -u ./...

Secrets Management

  • Never commit secrets to version control
  • Use environment variables for configuration
  • Rotate credentials regularly
  • Use secure storage for sensitive data

Reporting Security Issues

For security issues:

  1. Do NOT create public GitHub issues
  2. Contact the security team directly
  3. Provide detailed information about the vulnerability
  4. Allow time for fix before public disclosure

🀝 Community Guidelines

Code of Conduct

We are committed to providing a welcoming environment for all contributors:

  • Be Respectful: Treat everyone with respect and courtesy
  • Be Inclusive: Welcome people of all backgrounds and experience levels
  • Be Collaborative: Work together towards common goals
  • Be Professional: Maintain professional communication

Communication Channels

  • GitHub Issues: Bug reports and feature requests
  • Pull Requests: Code review and discussion
  • Wiki Discussions: Documentation and process discussions
  • Team Chat: Internal team communications

Recognition

We value all contributions:

  • Contributors: Listed in README and release notes
  • Major Contributors: Special recognition for significant contributions
  • Maintainers: Core team members with commit access

πŸ“ˆ Performance Considerations

Backend Performance

  • Profile regularly: Use Go's built-in profiler
  • Optimize hot paths: Focus on frequently called functions
  • Memory management: Avoid memory leaks and excessive allocations
  • Concurrency: Use goroutines efficiently

Frontend Performance

  • Bundle size: Keep bundle sizes reasonable
  • Rendering: Optimize React component rendering
  • Network: Minimize API calls and payload sizes
  • Caching: Implement appropriate caching strategies

πŸ”— Related Resources

Development Tools

Project Documentation


πŸŽ‰ Thank you for contributing to Hyperloop UPV!

Your contributions help advance the future of transportation. Together, we're building systems that will safely transport passengers at incredible speeds.

Clone this wiki locally