Files
component-system/.github/copilot-instructions.md
2025-09-20 12:08:50 +02:00

4.2 KiB

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

# 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:

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

mix precommit  # Compiles with warnings-as-errors, formats, runs tests

Database Operations:

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:

# 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

# 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

# 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

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

# 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.