From 58c165749d34dc247925f89830642cad1b69a985 Mon Sep 17 00:00:00 2001 From: DaX Date: Mon, 16 Feb 2026 00:35:08 +0100 Subject: [PATCH] Migrate from GitHub to Gitea with CI/CD - Add Gitea Actions workflow for automated frontend and API deployment - Update all raw download URLs from GitHub to Gitea - Remove deprecated Amplify config and GitHub-specific Terraform variables - Clean up commented-out Amplify resources from Terraform - Update documentation to reflect new repository and CI/CD setup --- .gitea/workflows/deploy.yml | 117 +++++++++++++++++++++++++++++ CLAUDE.md | 63 ++++++++++------ README.md | 55 ++++++-------- scripts/deploy-api-update.sh | 6 +- scripts/update-api-server.sh | 2 +- terraform/main.tf | 97 +----------------------- terraform/terraform.tfvars.example | 6 +- terraform/variables.tf | 11 --- 8 files changed, 190 insertions(+), 167 deletions(-) create mode 100644 .gitea/workflows/deploy.yml diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml new file mode 100644 index 0000000..3c467d9 --- /dev/null +++ b/.gitea/workflows/deploy.yml @@ -0,0 +1,117 @@ +name: Deploy + +on: + push: + branches: [main] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 2 + + - name: Detect changes + id: changes + run: | + FRONTEND_CHANGED=false + API_CHANGED=false + + if git diff --name-only HEAD~1 HEAD | grep -qvE '^api/'; then + FRONTEND_CHANGED=true + fi + + if git diff --name-only HEAD~1 HEAD | grep -qE '^api/'; then + API_CHANGED=true + fi + + echo "frontend=$FRONTEND_CHANGED" >> $GITHUB_OUTPUT + echo "api=$API_CHANGED" >> $GITHUB_OUTPUT + echo "Frontend changed: $FRONTEND_CHANGED" + echo "API changed: $API_CHANGED" + + # ── Frontend Deploy ────────────────────────────────────────────── + - name: Setup Node.js + if: steps.changes.outputs.frontend == 'true' + uses: actions/setup-node@v4 + with: + node-version: 18 + cache: npm + + - name: Install dependencies + if: steps.changes.outputs.frontend == 'true' + run: npm ci + + - name: Security check + if: steps.changes.outputs.frontend == 'true' + run: npm run security:check + + - name: Run tests + if: steps.changes.outputs.frontend == 'true' + run: npm test -- --passWithNoTests + + - name: Build Next.js + if: steps.changes.outputs.frontend == 'true' + run: npm run build + env: + NEXT_PUBLIC_API_URL: ${{ vars.NEXT_PUBLIC_API_URL }} + NEXT_PUBLIC_MATOMO_URL: ${{ vars.NEXT_PUBLIC_MATOMO_URL }} + NEXT_PUBLIC_MATOMO_SITE_ID: ${{ vars.NEXT_PUBLIC_MATOMO_SITE_ID }} + + - name: Configure AWS credentials + if: steps.changes.outputs.frontend == 'true' || steps.changes.outputs.api == 'true' + uses: aws-actions/configure-aws-credentials@v4 + with: + aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} + aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + aws-region: ${{ vars.AWS_REGION }} + + - name: Deploy to S3 + if: steps.changes.outputs.frontend == 'true' + run: | + S3_BUCKET="${{ vars.S3_BUCKET }}" + + # Upload HTML files with no-cache + aws s3 sync out/ s3://$S3_BUCKET/ \ + --delete \ + --exclude "*" \ + --include "*.html" \ + --cache-control "public, max-age=0, must-revalidate" \ + --content-type "text/html" + + # Upload _next static assets with immutable 1-year cache + aws s3 sync out/_next/ s3://$S3_BUCKET/_next/ \ + --cache-control "public, max-age=31536000, immutable" + + # Upload other assets with 1-day cache + aws s3 sync out/ s3://$S3_BUCKET/ \ + --exclude "*.html" \ + --exclude "_next/*" \ + --cache-control "public, max-age=86400" + + - name: Invalidate CloudFront + if: steps.changes.outputs.frontend == 'true' + run: | + aws cloudfront create-invalidation \ + --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \ + --paths "/*" + + # ── API Deploy ─────────────────────────────────────────────────── + - name: Deploy API via SSM + if: steps.changes.outputs.api == 'true' + run: | + aws ssm send-command \ + --region ${{ vars.AWS_REGION }} \ + --instance-ids "${{ vars.INSTANCE_ID }}" \ + --document-name "AWS-RunShellScript" \ + --parameters 'commands=[ + "cd /home/ubuntu/filamenteka-api", + "cp server.js server.js.backup", + "curl -o server.js https://git.demirix.dev/dax/Filamenteka/raw/branch/main/api/server.js", + "sudo systemctl restart node-api", + "sudo systemctl status node-api" + ]' \ + --output json + echo "API deploy command sent via SSM" diff --git a/CLAUDE.md b/CLAUDE.md index eba40d1..8fb5ad1 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -7,7 +7,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co Filamenteka is a 3D printing filament inventory management system for tracking Bambu Lab filaments. It consists of: - **Frontend**: Next.js app with React, TypeScript, and Tailwind CSS (static export) - **Backend**: Node.js API server with PostgreSQL database -- **Infrastructure**: AWS (Amplify for frontend, EC2 for API, RDS for database) +- **Infrastructure**: AWS (CloudFront + S3 for frontend, EC2 for API, RDS for database) ## Critical Rules @@ -20,13 +20,17 @@ Filamenteka is a 3D printing filament inventory management system for tracking B ## Common Commands ```bash -# Development +# Frontend Development npm run dev # Start Next.js development server (port 3000) npm run build # Build static export to /out directory npm run lint # Run ESLint +npm run typecheck # Run TypeScript type checking npm test # Run Jest tests npm run test:watch # Run Jest in watch mode +# API Development (in /api directory) +cd api && npm run dev # Start API server with nodemon (port 4000) + # Security & Quality npm run security:check # Check for credential leaks (scripts/security/security-check.js) npm run test:build # Test if build succeeds without creating files @@ -67,10 +71,15 @@ scripts/deploy-frontend.sh # Manual frontend deployment helper ### Key Components - `FilamentTableV2` - Main inventory display with sorting/filtering - `SaleManager` - Bulk sale management interface +- `BulkFilamentPriceEditor` - Bulk price modification interface - `ColorCell` - Smart color rendering with gradient support - `EnhancedFilters` - Advanced filtering system - `ColorRequestForm` - Customer color request form - `ColorRequestModal` - Modal for color requests +- `SaleCountdown` - Sale timer display +- `MatomoAnalytics` - Analytics tracking +- `BackToTop` - Scroll-to-top button +- `MaterialBadge`, `ColorSwatch`, `InventoryBadge` - Display components ### Data Models @@ -117,11 +126,15 @@ color_requests: { ## Deployment -### Frontend (AWS Amplify) -- Automatic deployment on push to main branch -- Build output: Static files in `/out` directory -- Config: `amplify.yml`, `next.config.js` (output: 'export') -- Security check runs during build (amplify.yml preBuild phase) +### Frontend (AWS CloudFront + S3) +- **Primary Method**: CloudFront distribution with S3 origin +- S3 bucket: `filamenteka-frontend` +- CloudFront Function: `index-rewrite` for directory-to-index.html routing +- Build output: Static files in `/out` directory (Next.js static export) +- Config: `next.config.js` (output: 'export'), `terraform/cloudfront-frontend.tf` +- Cache: 24h TTL for static assets, GET/HEAD methods cached +- OAC (Origin Access Control): S3 public access blocked, CloudFront-only access +- **CI/CD**: Gitea Actions workflow (`.gitea/workflows/deploy.yml`) auto-deploys on push to main ### API Server (EC2) - Deployment via `scripts/deploy-api-update.sh` (uses AWS SSM to push updates) @@ -129,7 +142,7 @@ color_requests: { - Server IP: `3.71.161.51` - Domain: `api.filamenteka.rs` - Service: `node-api` (systemd) -- Deploy script pulls from GitHub main branch and restarts service +- Deploy script pulls from Gitea main branch and restarts service - IMPORTANT: When deploying API, remember to build for AMD64 Linux (not ARM macOS) ### Database (RDS PostgreSQL) @@ -170,7 +183,14 @@ color_requests: { - Config: `jest.config.js`, `jest.setup.js` - Coverage goal: >80% - Run with `npm test` or `npm run test:watch` -- Tests include: component tests, API integration tests, data consistency checks +- Test files include: + - `ui-features.test.ts` - UI functionality + - `api-integration.test.ts` - API interactions + - `no-mock-data.test.ts` - Real data validation (ensures no fake/mock data) + - `color-management.test.ts` - Color CRUD operations + - `data-consistency.test.ts` - Data validation + - `components/*.test.tsx` - Component unit tests + - `data/*.test.ts` - Data structure validation ## Environment Variables @@ -225,18 +245,16 @@ Important database constraints: - `filaments.kolicina` has check constraint: `kolicina = refill + spulna` - Always update `colors` table first before adding filaments with new colors -### API Deployment Workflow -1. Make changes to `/api/server.js` -2. Commit and push to main branch -3. Run `./scripts/deploy-api-update.sh` (uses AWS SSM to pull from GitHub and restart) -4. Verify deployment: `curl https://api.filamenteka.rs/` should return `{"status":"ok"}` +### Deployment Workflow (Gitea Actions CI/CD) +Pushing to `main` triggers `.gitea/workflows/deploy.yml` which auto-detects what changed: +- **Frontend changes**: Runs security check, tests, builds Next.js, deploys to S3 with cache headers, invalidates CloudFront +- **API changes**: Sends SSM command to EC2 to download `server.js` from Gitea and restart the service +- **Both**: If a push touches frontend and API files, both deploy steps run -### Frontend Deployment Workflow -1. Make changes to app/components/pages -2. Test locally: `npm run dev` -3. Run pre-commit checks: `./scripts/pre-commit.sh` -4. Commit and push to main branch -5. AWS Amplify automatically builds and deploys (monitors main branch) +Manual deployment is still available: +1. Frontend: `./scripts/deploy-frontend.sh` +2. API: `./scripts/deploy-api-update.sh` +3. Verify API: `curl https://api.filamenteka.rs/` should return `{"status":"ok"}` ## Infrastructure @@ -256,4 +274,7 @@ Infrastructure as Code in `/terraform/`: - **API**: EC2 instance running Node.js/Express with systemd service - **Database**: AWS RDS PostgreSQL (eu-central-1) - **DNS**: Cloudflare for api.filamenteka.rs -- **Deployment**: AWS Amplify for frontend, SSM for API updates \ No newline at end of file +- **CI/CD**: Gitea Actions (`.gitea/workflows/deploy.yml`) +- **Deployment**: CloudFront + S3 for frontend, SSM for API updates +- **Repository**: `git.demirix.dev/dax/Filamenteka` +- **CDN**: CloudFront PriceClass_100 (US, Canada, Europe) \ No newline at end of file diff --git a/README.md b/README.md index 34447d8..e02f59e 100644 --- a/README.md +++ b/README.md @@ -4,21 +4,22 @@ A web application for tracking Bambu Lab filament inventory with automatic color ## Features -- 🎨 **Automatic Color Coding** - Table rows are automatically colored based on filament colors -- 🔍 **Search & Filter** - Quick search across all filament properties -- 📊 **Sortable Columns** - Click headers to sort by any column -- 🌈 **Gradient Support** - Special handling for gradient filaments like Cotton Candy Cloud -- 📱 **Responsive Design** - Works on desktop and mobile devices -- 💰 **Sale Management** - Bulk sale pricing with countdown timers -- 🔐 **Admin Panel** - Protected dashboard for inventory management -- 📦 **Spool Types** - Support for both regular and refill spools +- Automatic Color Coding - Table rows are automatically colored based on filament colors +- Search & Filter - Quick search across all filament properties +- Sortable Columns - Click headers to sort by any column +- Gradient Support - Special handling for gradient filaments like Cotton Candy Cloud +- Responsive Design - Works on desktop and mobile devices +- Sale Management - Bulk sale pricing with countdown timers +- Admin Panel - Protected dashboard for inventory management +- Spool Types - Support for both regular and refill spools ## Technology Stack - **Frontend**: Next.js + React + TypeScript + Tailwind CSS - **Backend**: Node.js API server (Express) - **Database**: PostgreSQL (AWS RDS) -- **Infrastructure**: AWS Amplify (Frontend), EC2 (API), RDS (Database) +- **Infrastructure**: AWS CloudFront + S3 (Frontend), EC2 (API), RDS (Database) +- **CI/CD**: Gitea Actions - **IaC**: Terraform ## Prerequisites @@ -27,15 +28,14 @@ A web application for tracking Bambu Lab filament inventory with automatic color - PostgreSQL (for local development) - AWS Account (for deployment) - Terraform 1.0+ (for infrastructure) -- GitHub account ## Setup Instructions ### 1. Clone the Repository ```bash -git clone https://github.com/yourusername/filamenteka.git -cd filamenteka +git clone https://git.demirix.dev/DaX/Filamenteka.git +cd Filamenteka ``` ### 2. Install Dependencies @@ -90,7 +90,7 @@ The filament table displays these columns: - **Boja** - Color name (e.g., Mistletoe Green, Hot Pink) - **Refill** - Number of refill spools - **Spulna** - Number of regular spools -- **Količina** - Total quantity (refill + spulna) +- **Kolicina** - Total quantity (refill + spulna) - **Cena** - Price per unit - **Sale** - Active sale percentage and end date @@ -106,15 +106,19 @@ Unknown colors default to light gray. ## Deployment -Push to the main branch to trigger automatic deployment: +Pushing to `main` triggers automatic deployment via Gitea Actions: +- Frontend changes are built, tested, and deployed to S3/CloudFront +- API changes are deployed to EC2 via AWS SSM + +Manual deployment is also available: ```bash -git add . -git commit -m "Update filament colors" -git push origin main -``` +# Frontend +./scripts/deploy-frontend.sh -Amplify will automatically build and deploy your changes. +# API +./scripts/deploy-api-update.sh +``` ## Admin Panel @@ -155,9 +159,7 @@ Deploy API server updates: ```bash # Use the deployment script -./scripts/deploy-api.sh - -# Or deploy manually to EC2 instance +./scripts/deploy-api-update.sh ``` ## Troubleshooting @@ -181,12 +183,3 @@ Deploy API server updates: ## License MIT - -## Contributing - -1. Fork the repository -2. Create a feature branch -3. Commit your changes -4. Push to the branch -5. Create a Pull Request - diff --git a/scripts/deploy-api-update.sh b/scripts/deploy-api-update.sh index acf711d..246aafb 100755 --- a/scripts/deploy-api-update.sh +++ b/scripts/deploy-api-update.sh @@ -13,8 +13,8 @@ cd /home/ubuntu/filamenteka-api # Backup current server.js cp server.js server.js.backup -# Download the updated server.js from GitHub -curl -o server.js https://raw.githubusercontent.com/daxdax89/Filamenteka/sale/api/server.js +# Download the updated server.js from Gitea +curl -o server.js https://git.demirix.dev/dax/Filamenteka/raw/branch/main/api/server.js # Restart the service sudo systemctl restart node-api @@ -30,7 +30,7 @@ aws ssm send-command \ --parameters "commands=[ 'cd /home/ubuntu/filamenteka-api', 'cp server.js server.js.backup', - 'curl -o server.js https://raw.githubusercontent.com/daxdax89/Filamenteka/sale/api/server.js', + 'curl -o server.js https://git.demirix.dev/dax/Filamenteka/raw/branch/main/api/server.js', 'sudo systemctl restart node-api', 'sudo systemctl status node-api' ]" \ diff --git a/scripts/update-api-server.sh b/scripts/update-api-server.sh index b0532d9..7a3178a 100644 --- a/scripts/update-api-server.sh +++ b/scripts/update-api-server.sh @@ -1,6 +1,6 @@ #!/bin/bash -# Script to update API server via GitHub +# Script to update API server via Gitea # Since we can't SSH directly, we'll use the API server to pull latest code echo "🚀 Updating API server with latest code..." diff --git a/terraform/main.tf b/terraform/main.tf index 38f4eca..480a65c 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -20,98 +20,5 @@ provider "cloudflare" { api_token = var.cloudflare_api_token != "" ? var.cloudflare_api_token : "dummy" # Dummy token if not provided } -# ===== DEPRECATED: Amplify Hosting (Migrated to CloudFront + S3) ===== -# Amplify app was deleted due to broken GitHub integration -# Frontend now hosted on CloudFront + S3 (see cloudfront-frontend.tf) -# Kept here for reference only -# -# resource "aws_amplify_app" "filamenteka" { -# name = "filamenteka" -# repository = var.github_repository -# platform = "WEB" -# -# build_spec = <<-EOT -# version: 1 -# frontend: -# phases: -# preBuild: -# commands: -# - npm ci -# - npm run security:check -# build: -# commands: -# - npm run build -# - npm run test -# artifacts: -# baseDirectory: .next -# files: -# - '**/*' -# cache: -# paths: -# - node_modules/**/* -# - .next/cache/**/* -# EOT -# -# environment_variables = { -# NEXT_PUBLIC_API_URL = "https://api.filamenteka.rs/api" -# } -# -# custom_rule { -# source = "/<*>" -# status = "404" -# target = "/index.html" -# } -# -# enable_branch_auto_build = true -# -# tags = { -# Name = "Filamenteka" -# Environment = var.environment -# "amplify:github_app_migration" = "opted_out" -# } -# } -# -# resource "aws_amplify_branch" "main" { -# app_id = aws_amplify_app.filamenteka.id -# branch_name = "main" -# enable_auto_build = true -# environment_variables = {} -# stage = "PRODUCTION" -# tags = { -# Name = "Filamenteka-main" -# Environment = var.environment -# } -# } -# -# resource "aws_amplify_branch" "dev" { -# app_id = aws_amplify_app.filamenteka.id -# branch_name = "dev" -# enable_auto_build = true -# stage = "DEVELOPMENT" -# tags = { -# Name = "Filamenteka-dev" -# Environment = "development" -# } -# } -# -# resource "aws_amplify_domain_association" "filamenteka" { -# count = var.domain_name != "" ? 1 : 0 -# app_id = aws_amplify_app.filamenteka.id -# domain_name = var.domain_name -# wait_for_verification = false -# -# sub_domain { -# branch_name = aws_amplify_branch.main.branch_name -# prefix = "" -# } -# -# sub_domain { -# branch_name = aws_amplify_branch.main.branch_name -# prefix = "www" -# } -# -# sub_domain { -# branch_name = aws_amplify_branch.dev.branch_name -# prefix = "dev" -# } -# } \ No newline at end of file +# Frontend hosted on CloudFront + S3 (see cloudfront-frontend.tf) +# CI/CD handled by Gitea Actions (see .gitea/workflows/deploy.yml) \ No newline at end of file diff --git a/terraform/terraform.tfvars.example b/terraform/terraform.tfvars.example index cc90ef8..4134979 100644 --- a/terraform/terraform.tfvars.example +++ b/terraform/terraform.tfvars.example @@ -1,11 +1,7 @@ # Copy this file to terraform.tfvars and fill in your values -# GitHub repository for Amplify -github_repository = "https://github.com/yourusername/filamenteka" -github_token = "ghp_your_github_token_here" - # Domain configuration domain_name = "filamenteka.yourdomain.com" # Cloudflare configuration (optional) -cloudflare_api_token = "your-cloudflare-api-token" \ No newline at end of file +cloudflare_api_token = "your-cloudflare-api-token" diff --git a/terraform/variables.tf b/terraform/variables.tf index 8598d3e..9806942 100644 --- a/terraform/variables.tf +++ b/terraform/variables.tf @@ -1,14 +1,3 @@ -variable "github_repository" { - description = "GitHub repository URL" - type = string -} - -variable "github_token" { - description = "GitHub personal access token for Amplify" - type = string - sensitive = true -} - variable "domain_name" { description = "Custom domain name (optional)" type = string