docs: add GitHub Copilot instructions
This commit is contained in:
125
.github/copilot-instructions.md
vendored
Normal file
125
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
# GitHub Copilot Instructions
|
||||||
|
|
||||||
|
This is an electronic component inventory management system built with Phoenix LiveView. Follow these project-specific patterns for effective contributions.
|
||||||
|
|
||||||
|
## Project Architecture
|
||||||
|
|
||||||
|
**Core Structure**: Phoenix 1.8 with LiveView-first architecture for real-time inventory management
|
||||||
|
- `lib/components_elixir/` - Business logic contexts (Inventory, AprilTag, Auth)
|
||||||
|
- `lib/components_elixir_web/live/` - LiveView modules for real-time UI
|
||||||
|
- Key contexts: `Inventory` (components/categories/locations), `DatasheetDownloader`, `AprilTag`
|
||||||
|
|
||||||
|
**Hierarchical Data Pattern**: Both categories and storage locations use unlimited nesting
|
||||||
|
```elixir
|
||||||
|
# Use Hierarchical module for tree operations
|
||||||
|
alias ComponentsElixir.Inventory.Hierarchical
|
||||||
|
Hierarchical.build_tree(categories) # Converts flat list to nested structure
|
||||||
|
```
|
||||||
|
|
||||||
|
**Authentication**: Simple session-based auth using `ComponentsElixir.Auth`
|
||||||
|
- All LiveViews must check `Auth.authenticated?(session)` in mount/3
|
||||||
|
- Default password: "changeme" (configurable via `AUTH_PASSWORD` env var)
|
||||||
|
|
||||||
|
## Key Development Workflows
|
||||||
|
|
||||||
|
**Development Setup**:
|
||||||
|
```bash
|
||||||
|
mix deps.get
|
||||||
|
mix ecto.setup # Creates DB, runs migrations, seeds data
|
||||||
|
mix phx.server # Starts dev server with hot reload
|
||||||
|
```
|
||||||
|
|
||||||
|
**Code Quality (Critical)**: Always run before committing
|
||||||
|
```bash
|
||||||
|
mix precommit # Compiles with warnings-as-errors, formats, runs tests
|
||||||
|
```
|
||||||
|
|
||||||
|
**Database Operations**:
|
||||||
|
```bash
|
||||||
|
mix ecto.reset # Drop/recreate/migrate/seed database
|
||||||
|
mix ecto.gen.migration # Generate new migration
|
||||||
|
```
|
||||||
|
|
||||||
|
## LiveView Patterns
|
||||||
|
|
||||||
|
**Stream-Based Components**: Use LiveView streams for component lists to prevent memory issues:
|
||||||
|
```elixir
|
||||||
|
# In LiveView
|
||||||
|
stream(socket, :components, components)
|
||||||
|
|
||||||
|
# In template
|
||||||
|
<div id="components" phx-update="stream">
|
||||||
|
<div :for={{id, component} <- @streams.components} id={id}>
|
||||||
|
<!-- component content -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
**File Upload Handling**: Uses Phoenix.LiveView.Upload with custom validators
|
||||||
|
- Datasheets: PDF only, 10MB max, stored in `uploads/datasheets/`
|
||||||
|
- Images: JPEG/PNG only, 5MB max, stored in `uploads/images/`
|
||||||
|
|
||||||
|
## Database Conventions
|
||||||
|
|
||||||
|
**Hierarchical Relationships**: Self-referential `parent_id` foreign keys
|
||||||
|
```elixir
|
||||||
|
# Schema pattern for categories/locations
|
||||||
|
field :parent_id, :id
|
||||||
|
belongs_to :parent, __MODULE__
|
||||||
|
has_many :children, __MODULE__, foreign_key: :parent_id
|
||||||
|
```
|
||||||
|
|
||||||
|
**Component Search**: Full-text search across name, description, keywords
|
||||||
|
```elixir
|
||||||
|
# Use ilike for case-insensitive search
|
||||||
|
from c in Component, where: ilike(c.name, ^"%#{search}%")
|
||||||
|
```
|
||||||
|
|
||||||
|
## Asset Management
|
||||||
|
|
||||||
|
**DaisyUI Components**: Prefer DaisyUI classes for consistent styling:
|
||||||
|
- `btn btn-primary` for buttons
|
||||||
|
- `card card-compact` for component cards
|
||||||
|
- `badge` for category/location tags
|
||||||
|
|
||||||
|
## External Dependencies
|
||||||
|
|
||||||
|
**AprilTag Generation**: SVG-based tags for physical location labeling
|
||||||
|
```elixir
|
||||||
|
ComponentsElixir.AprilTag.generate_svg(tag_id) # Returns SVG string
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Guidelines
|
||||||
|
|
||||||
|
**Factory Pattern**: Use explicit test data setup, not factories
|
||||||
|
- Seed realistic test data in `test/support/` modules
|
||||||
|
- Test both hierarchical and flat data structures
|
||||||
|
|
||||||
|
## Production Deployment
|
||||||
|
|
||||||
|
**Docker-First**: Primary deployment method via `docker-compose.yml`
|
||||||
|
- Environment: `SECRET_KEY_BASE`, `AUTH_PASSWORD`, `PHX_HOST`
|
||||||
|
- File uploads mounted as volumes: `./uploads:/app/uploads`
|
||||||
|
|
||||||
|
**Release Commands**: Database migrations via release tasks
|
||||||
|
```bash
|
||||||
|
# In production container
|
||||||
|
./bin/components_elixir eval "ComponentsElixir.Release.migrate"
|
||||||
|
```
|
||||||
|
|
||||||
|
## CI/CD with Gitea Actions
|
||||||
|
|
||||||
|
**Gitea Actions Limitations** (important differences from GitHub Actions):
|
||||||
|
- No `concurrency`, `run-name`, `permissions`, `timeout-minutes`, `continue-on-error` support
|
||||||
|
- Limited expression support (only `always()` function)
|
||||||
|
- No package repository authorization - use Personal Access Token for OCI publishing
|
||||||
|
- Problem matchers and error annotations are ignored
|
||||||
|
- Simple `runs-on` syntax only (`runs-on: ubuntu-latest`, not complex selectors)
|
||||||
|
|
||||||
|
**CI Pipeline Will Include**:
|
||||||
|
- Code quality checks (`mix precommit`)
|
||||||
|
- Test execution across Elixir/OTP versions
|
||||||
|
- Docker image building and publishing (requires PAT for package registry)
|
||||||
|
- Database migration testing
|
||||||
|
|
||||||
|
Ensure all code passes `mix precommit` before pushing, as this will be enforced in CI.
|
||||||
Reference in New Issue
Block a user