From 2f6cc4cdc25cc2cb81bc4db312926a314c6ae838 Mon Sep 17 00:00:00 2001 From: Zsolt Tasnadi Date: Tue, 4 Aug 2026 18:44:32 +0200 Subject: [PATCH] Phase 1: warp_engine gem skeleton (path gem, mounted engine) - libs/ruby/warp_engine: gemspec, WarpEngine::Engine (isolate_namespace with empty table_name_prefix), WarpEngine.configure surface (container paths, update_secret, image_owners), empty engine routes - host Gemfile: path gem; host routes: mount WarpEngine::Engine => "/" as the last entry so host routes always win - docker: api build context moved to repo root so libs/ is visible at bundle-install time; ./libs:/libs runtime mount; root .dockerignore to keep data/ and node_modules out of the build context Co-Authored-By: Claude Fable 5 --- .dockerignore | 7 ++++ apps/api/Dockerfile.development | 7 ++-- apps/api/Gemfile | 4 +++ apps/api/Gemfile.lock | 7 ++++ apps/api/config/routes.rb | 3 ++ docker-compose.yaml | 6 ++-- libs/ruby/warp_engine/README.md | 34 +++++++++++++++++++ libs/ruby/warp_engine/config/routes.rb | 2 ++ libs/ruby/warp_engine/lib/warp_engine.rb | 21 ++++++++++++ .../lib/warp_engine/configuration.rb | 19 +++++++++++ .../warp_engine/lib/warp_engine/engine.rb | 5 +++ .../warp_engine/lib/warp_engine/version.rb | 3 ++ libs/ruby/warp_engine/warp_engine.gemspec | 21 ++++++++++++ 13 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 .dockerignore create mode 100644 libs/ruby/warp_engine/README.md create mode 100644 libs/ruby/warp_engine/config/routes.rb create mode 100644 libs/ruby/warp_engine/lib/warp_engine.rb create mode 100644 libs/ruby/warp_engine/lib/warp_engine/configuration.rb create mode 100644 libs/ruby/warp_engine/lib/warp_engine/engine.rb create mode 100644 libs/ruby/warp_engine/lib/warp_engine/version.rb create mode 100644 libs/ruby/warp_engine/warp_engine.gemspec diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..6b409ba --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +# A repo-gyökér build contextből kihagyandó (az api image-nek csak apps/api + libs kell) +data/ +apps/frontend/node_modules/ +apps/frontend/dist/ +apps/api/tmp/ +apps/api/log/ +.git/ diff --git a/apps/api/Dockerfile.development b/apps/api/Dockerfile.development index f3c2e5e..78e4a40 100644 --- a/apps/api/Dockerfile.development +++ b/apps/api/Dockerfile.development @@ -14,10 +14,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ WORKDIR /app -COPY Gemfile ./ +# A path gemek /libs alá kerülnek, ugyanoda, ahova a compose mountolja őket, +# így a Gemfile "../../libs/..." relatív útvonala build- és futásidőben is stimmel. +COPY libs /libs +COPY apps/api/Gemfile ./ RUN bundle install -COPY . . +COPY apps/api . EXPOSE 3000 diff --git a/apps/api/Gemfile b/apps/api/Gemfile index c692554..64d1649 100644 --- a/apps/api/Gemfile +++ b/apps/api/Gemfile @@ -1,6 +1,10 @@ source "https://rubygems.org" gem "rails", "~> 8.0" + +# Katalógus-engine. A relatív path hoston (apps/api -> repo-gyökér/libs) és a +# konténerben (/app -> /libs mount) is ugyanoda oldódik fel. +gem "warp_engine", path: "../../libs/ruby/warp_engine" gem "mysql2", "~> 0.5" gem "puma", ">= 5.0" gem "rubyzip", "~> 2.3" diff --git a/apps/api/Gemfile.lock b/apps/api/Gemfile.lock index 8fca4dc..345412c 100644 --- a/apps/api/Gemfile.lock +++ b/apps/api/Gemfile.lock @@ -1,3 +1,9 @@ +PATH + remote: ../libs/ruby/warp_engine + specs: + warp_engine (0.1.0) + rails (>= 8.0) + GEM remote: https://rubygems.org/ specs: @@ -380,6 +386,7 @@ DEPENDENCIES sassc-rails shoulda-matchers (~> 6.0) sprockets-rails + warp_engine! BUNDLED WITH 2.5.22 diff --git a/apps/api/config/routes.rb b/apps/api/config/routes.rb index 887ea21..4cf121e 100644 --- a/apps/api/config/routes.rb +++ b/apps/api/config/routes.rb @@ -20,4 +20,7 @@ Rails.application.routes.draw do end get "update", to: "update#update" get "file/*path", to: "files#show", format: false + + # Utolsó sor: a host route-jai nyernek, minden mást az engine kap el. + mount WarpEngine::Engine => "/" end diff --git a/docker-compose.yaml b/docker-compose.yaml index f59e57a..5f076a3 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -144,8 +144,9 @@ services: api: build: - context: ./apps/api - dockerfile: Dockerfile.development + # Repo-gyökér context: a libs/ alatti path gemeknek látszaniuk kell build közben + context: . + dockerfile: apps/api/Dockerfile.development container_name: api environment: - RAILS_ENV=development @@ -168,6 +169,7 @@ services: - ./data/softwares:/softwares - ./data/images:/images - ./apps/api:/app + - ./libs:/libs - api_bundle:/usr/local/bundle labels: - "traefik.enable=true" diff --git a/libs/ruby/warp_engine/README.md b/libs/ruby/warp_engine/README.md new file mode 100644 index 0000000..e8cce07 --- /dev/null +++ b/libs/ruby/warp_engine/README.md @@ -0,0 +1,34 @@ +# WarpEngine + +Mountable Rails engine: retro szoftverkatalógus CI-pipeline-ból hívható release-updaterrel, +publikus read-only JSON API-val és a host adminjába betöltődő ActiveAdmin erőforrásokkal. + +## Használat + +```ruby +# Gemfile +gem "warp_engine", path: "../../libs/ruby/warp_engine" + +# config/routes.rb — utolsó sorként, hogy a host route-jai nyerjenek +mount WarpEngine::Engine => "/" + +# config/initializers/warp_engine.rb +WarpEngine.configure do |c| + c.file_container_path = ENV.fetch("FILE_CONTAINER_PATH", "/softwares") + c.image_container_path = ENV.fetch("IMAGE_CONTAINER_PATH", "/images") + c.update_secret = ENV["UPDATE_SECRET"] + # Ha a host modelljei is használnak katalógus-képeket: + c.image_owners << { + label: "member", + image_ids: -> { Member.where.not(image_id: nil).distinct.pluck(:image_id) }, + usage_label: ->(image) { "member" if Member.where(image_id: image.id).exists? } + } +end +``` + +## Megjegyzések + +- A modellek soft-delete-et használnak (`default_scope { where(deleted_at: nil) }`); + az updater `.unscoped`-dal "feltámasztja" az újra beküldött, korábban törölt rekordokat. +- A táblanevek prefix nélküliek (`softwares`, `releases`, ...). +- Az admin erőforrások a host ActiveAdmin példányába töltődnek be; auth (Devise) a host dolga. diff --git a/libs/ruby/warp_engine/config/routes.rb b/libs/ruby/warp_engine/config/routes.rb new file mode 100644 index 0000000..1935491 --- /dev/null +++ b/libs/ruby/warp_engine/config/routes.rb @@ -0,0 +1,2 @@ +WarpEngine::Engine.routes.draw do +end diff --git a/libs/ruby/warp_engine/lib/warp_engine.rb b/libs/ruby/warp_engine/lib/warp_engine.rb new file mode 100644 index 0000000..a396622 --- /dev/null +++ b/libs/ruby/warp_engine/lib/warp_engine.rb @@ -0,0 +1,21 @@ +require "warp_engine/version" +require "warp_engine/configuration" + +module WarpEngine + # A tábláink prefix nélküliek (softwares, releases, ...) — az isolate_namespace + # által generált "warp_engine_" prefixet üresre cseréljük. Az engine.rb require-je + # előtt kell definiálva lennie. + def self.table_name_prefix + "" + end + + def self.config + @config ||= Configuration.new + end + + def self.configure + yield(config) + end +end + +require "warp_engine/engine" diff --git a/libs/ruby/warp_engine/lib/warp_engine/configuration.rb b/libs/ruby/warp_engine/lib/warp_engine/configuration.rb new file mode 100644 index 0000000..581b322 --- /dev/null +++ b/libs/ruby/warp_engine/lib/warp_engine/configuration.rb @@ -0,0 +1,19 @@ +module WarpEngine + class Configuration + # Owner kontraktus az image_owners elemeire: + # label: String + # image_ids: -> { Array } — az owner által használt image id-k + # usage_label: ->(image) { String vagy nil } — megjelenítendő címke, ha használja + attr_accessor :file_container_path, + :image_container_path, + :update_secret, + :image_owners + + def initialize + @file_container_path = ENV.fetch("FILE_CONTAINER_PATH", "/softwares") + @image_container_path = ENV.fetch("IMAGE_CONTAINER_PATH", "/images") + @update_secret = ENV["UPDATE_SECRET"] + @image_owners = [] + end + end +end diff --git a/libs/ruby/warp_engine/lib/warp_engine/engine.rb b/libs/ruby/warp_engine/lib/warp_engine/engine.rb new file mode 100644 index 0000000..9e473cb --- /dev/null +++ b/libs/ruby/warp_engine/lib/warp_engine/engine.rb @@ -0,0 +1,5 @@ +module WarpEngine + class Engine < ::Rails::Engine + isolate_namespace WarpEngine + end +end diff --git a/libs/ruby/warp_engine/lib/warp_engine/version.rb b/libs/ruby/warp_engine/lib/warp_engine/version.rb new file mode 100644 index 0000000..1ebbfd3 --- /dev/null +++ b/libs/ruby/warp_engine/lib/warp_engine/version.rb @@ -0,0 +1,3 @@ +module WarpEngine + VERSION = "0.1.0" +end diff --git a/libs/ruby/warp_engine/warp_engine.gemspec b/libs/ruby/warp_engine/warp_engine.gemspec new file mode 100644 index 0000000..1a1d5c8 --- /dev/null +++ b/libs/ruby/warp_engine/warp_engine.gemspec @@ -0,0 +1,21 @@ +require_relative "lib/warp_engine/version" + +Gem::Specification.new do |spec| + spec.name = "warp_engine" + spec.version = WarpEngine::VERSION + spec.authors = [ "Teletype Games" ] + spec.summary = "Retro software catalog engine with a CI-callable release updater" + spec.description = "Mountable Rails engine providing a software catalog (softwares, releases, " \ + "release assets, images, platform links), a pipeline-callable update endpoint, " \ + "a public read-only JSON API and ActiveAdmin resources for a host-owned admin." + spec.license = "MIT" + spec.homepage = "https://teletypegames.org" + + spec.required_ruby_version = ">= 3.2" + + spec.metadata["allowed_push_host"] = "https://git.teletypegames.org" + + spec.files = Dir["{app,config,db,lib}/**/*", "README.md"] + + spec.add_dependency "rails", ">= 8.0" +end