7.8 KiB
Contributing to LinkBeam
Thank you for your interest in contributing to LinkBeam! This document provides guidelines and instructions for development.
Development Setup
Prerequisites
- Go 1.21 or later
- Make (optional, for using Makefile commands)
- golangci-lint (for code quality checks)
- pre-commit (optional, for automated checks)
Getting Started
- Fork and clone the repository:
git clone https://github.com/5mdt/linkbeam.git
cd linkbeam
- Install dependencies:
go mod download
- Build the project:
make build
# or: go build -o dist/linkbeam cmd/linkbeam/main.go
Pre-commit Hooks
This project uses pre-commit hooks to ensure code quality. Setting them up is highly recommended.
Installation
# Install pre-commit (if not already installed)
pip install pre-commit
# or: brew install pre-commit (on macOS)
# Install golangci-lint (if not already installed)
# See: https://golangci-lint.run/usage/install/
go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
# Install the git hook scripts
pre-commit install
# or: make install-hooks
Running Hooks
# Run against all files
pre-commit run --all-files
# or: make pre-commit
# Hooks will automatically run on git commit
git commit -m "your message"
The pre-commit hooks check:
- Go code formatting (
go fmt) - Import organization (
goimports) - Code quality (
go vet,golangci-lint) - Tests (
go test) - Module tidiness (
go mod tidy) - YAML syntax
- Trailing whitespace
- End of file fixes
- And more
Note: The pre-commit framework will automatically download required Go tools on first run if they're not already installed.
Development Commands
Building
# Build binary (outputs to dist/linkbeam)
make build
# or: go build -o dist/linkbeam cmd/linkbeam/main.go
Running
# Run with example config
make run-example
# or: go run cmd/linkbeam/main.go --config internal/config/testdata/config.yaml
# Run with custom config (long flags)
./linkbeam --config config.yaml --template templates/base.html --output dist/index.html
# Run with custom config (short flags)
./linkbeam -c config.yaml -t templates/base.html -o dist/index.html
Testing
# Run all tests
make test
# or: go test -v ./...
# Run tests for a specific package
go test ./internal/config
go test ./internal/generator
# Run a single test function
go test -v -run TestLoad ./internal/config
# Run tests with coverage
go test -cover ./...
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
Code Quality
# Format code
go fmt ./...
# or: make fmt
# Run go vet
go vet ./...
# Run golangci-lint
golangci-lint run
# or: make vet
# Run all quality checks
make pre-commit
Cleaning
# Clean build artifacts
make clean
Project Structure
linkbeam/
├── cmd/linkbeam/ # Main application entry point
│ ├── main.go
│ └── main_test.go
├── internal/
│ ├── config/ # Configuration loading and validation
│ │ ├── config.go
│ │ ├── config_test.go
│ │ └── testdata/
│ └── generator/ # Site generation and rendering
│ ├── generator.go
│ └── generator_test.go
├── templates/ # HTML templates
│ └── base.html
├── themes/ # CSS theme files
│ ├── light.css
│ └── dark.css
├── dist/ # Build output: binary and generated site (gitignored)
├── .gitea/ # CI/CD workflows
│ └── workflows/
├── Makefile # Build automation
├── go.mod # Go module definition
└── go.sum # Go dependencies
Architecture
Two-Layer Structure
-
Config Layer (
internal/config/):- Loads and validates YAML configuration files
- Defines data structures:
Config,Link,Social - Validates theme (must be "light" or "dark") and required fields
- Config validation happens automatically during
config.Load()
-
Generator Layer (
internal/generator/):- HTML Generation: Orchestrates template rendering using Go's
html/templateGenerateSite(cfg, templatePath, outPath)- Creates HTML from templates
- Asset Management: Copies CSS themes and static files to output directory
CopyAssets(distDir, themeDirs...)- Copies theme files to dist/themes/
- Text Rendering: Plain-text representation for debugging
RenderUserPage(cfg)- Returns text-based preview of the page
- HTML Generation: Orchestrates template rendering using Go's
Testing Strategy
- Tests use table-driven patterns and dependency injection
cmd/linkbeam/main_test.go: Mocks the config loader and captures stdout- Config tests validate YAML parsing and business rules
- Generator tests verify file creation and template execution
- All tests use the testdata in
internal/config/testdata/config.yaml
Making Changes
Adding New Features
- Create a new branch for your feature:
git checkout -b feature/your-feature-name
- Write tests first (TDD approach recommended)
- Implement the feature
- Ensure all tests pass:
go test ./... - Run pre-commit hooks:
pre-commit run --all-files - Commit your changes with a descriptive message
Code Style
- Follow standard Go conventions and idioms
- Use
gofmtfor formatting (handled by pre-commit) - Write clear, descriptive variable and function names
- Add comments for exported functions and types
- Keep functions focused and concise
Testing Guidelines
- Write tests for all new functionality
- Aim for high test coverage
- Use table-driven tests for multiple test cases
- Use testdata files for fixtures
- Test both success and error cases
Commit Messages
- Use clear, descriptive commit messages
- Start with a verb in present tense (e.g., "Add", "Fix", "Update")
- Reference issue numbers when applicable
- Keep the first line under 72 characters
Examples:
Add support for custom CSS themes
Fix avatar path resolution in config loader
Update template to include meta tags
CI/CD Pipeline
The project uses Gitea Actions for continuous integration and deployment.
Workflows
-
CI Pipeline (
.gitea/workflows/ci.yml):- Runs on push to main/develop and pull requests
- Lint: golangci-lint, go fmt, go vet
- Test: Run tests with race detection and coverage
- Build: Multi-platform builds (Linux, Windows, macOS) for multiple architectures
- Docker: Build multi-arch Docker images
-
Docker Publish (
.gitea/workflows/docker-publish.yml):- Triggered on version tags (v*)
- Builds and pushes Docker images to container registry
- Multi-architecture: linux/amd64, linux/arm64, linux/arm/v7
-
Release (
.gitea/workflows/release.yml):- Triggered on semver tags (v*..)
- Creates releases with binaries for all platforms
- Generates SHA256 checksums for verification
Local Testing with Docker
# Test Docker build
docker build -t linkbeam:test .
# Run Docker container
docker run -v $(pwd)/config.yaml:/app/config/config.yaml \
-v $(pwd)/dist:/app/dist \
linkbeam:test
# Test with docker-compose
docker-compose up
Submitting Changes
- Ensure your code passes all tests and checks
- Push your branch to your fork
- Open a pull request with a clear description of your changes
- Wait for CI checks to pass
- Respond to any review feedback
Questions or Issues?
If you have questions or run into issues:
- Check existing issues on the repository
- Open a new issue with a clear description
- Join our community discussions (if available)
License
By contributing to LinkBeam, you agree that your contributions will be licensed under the GNU General Public License v3.0.