platform files refact
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
2026-08-06 10:00:34 +02:00
parent 565c086a0d
commit 068c4db3f8
45 changed files with 219 additions and 205 deletions
@@ -29,13 +29,13 @@ module WarpEngine
return render json: { error: "Forbidden" }, status: :forbidden
end
input = WarpEngine::UpdateInputDto.new(
input = WarpEngine::PublishInputDto.new(
platform: params[:platform],
name: params[:name],
version: params[:version]
)
WarpEngine::UpdateService.new.update(input)
WarpEngine::PublishService.new.publish(input)
claim_software_ownership(params[:name])
render json: { published: true, name: params[:name], platform: params[:platform], version: params[:version] }
@@ -1,5 +1,5 @@
module WarpEngine
UpdateInputDto = Struct.new(:platform, :name, :version, keyword_init: true) do
PublishInputDto = Struct.new(:platform, :name, :version, keyword_init: true) do
def initialize(platform:, name:, version: nil)
super
end
@@ -2,7 +2,7 @@ require "zip"
require "fileutils"
module WarpEngine
module SoftwareUpdater
module Platforms
module ArchiveExtraction
private
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Builds
module BuildCartridge
extend ActiveSupport::Concern
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Builds
module BuildDocs
extend ActiveSupport::Concern
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Builds
module BuildLinuxX64
extend ActiveSupport::Concern
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Builds
module BuildMacArm64
extend ActiveSupport::Concern
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Builds
module BuildMacUniversal
extend ActiveSupport::Concern
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Builds
module BuildMacX64
extend ActiveSupport::Concern
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Builds
module BuildSource
extend ActiveSupport::Concern
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Builds
module BuildWeb
extend ActiveSupport::Concern
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Builds
module BuildWinX64
extend ActiveSupport::Concern
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Builds
module BuildWinX86
extend ActiveSupport::Concern
@@ -1,7 +1,7 @@
require "json"
module WarpEngine
module SoftwareUpdater
module Platforms
module MetadataParsing
METADATA_KEYS = %i[name title author desc site repo license].freeze
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module SoftwarePersistence
private
@@ -1,5 +1,5 @@
module WarpEngine
module SoftwareUpdater
module Platforms
module Updatable
extend ActiveSupport::Concern
include ArchiveExtraction
@@ -9,7 +9,7 @@ module WarpEngine
class_methods do
def platform(value = nil)
@platform = value if value
@platform ||= name.demodulize.delete_suffix("Service").downcase
@platform ||= name.deconstantize.demodulize.downcase
end
def label(value = nil)
@@ -2,7 +2,7 @@ module WarpEngine
class BuildsService
def index
platforms = WarpEngine::PlatformLink::SUPPORTED_PLATFORMS.each_with_object({}) do |platform, hash|
service_class = "WarpEngine::SoftwareUpdater::#{platform.camelize}Service".constantize
service_class = "WarpEngine::Platforms::#{platform.camelize}::Service".constantize
hash[platform] = {
label: service_class.label,
kinds: service_class.expected_kinds
@@ -16,7 +16,7 @@ module WarpEngine
def show(name)
software = WarpEngine::Software.find_by!(name: name)
service_class = "WarpEngine::SoftwareUpdater::#{software.platform.camelize}Service".constantize
service_class = "WarpEngine::Platforms::#{software.platform.camelize}::Service".constantize
expected = service_class.expected_kinds
releases = software.releases.includes(:release_assets).order(updated_at: :desc)
@@ -2,8 +2,8 @@ require "erb"
module WarpEngine
# Renders the /build/config platform templates: the pipeline logic lives in
# lib/warp_engine/ci_templates/<platform>.yaml.erb, the per-platform builder
# images come from WarpEngine.config.ci_platforms.
# app/services/warp_engine/platforms/<platform>/pipeline.yaml.erb, the
# per-platform builder images come from WarpEngine.config.ci_platforms.
class CiConfigService
PLATFORM_FORMAT = /\A[a-z0-9_-]+\z/
@@ -15,7 +15,7 @@ module WarpEngine
spec = platform_spec(platform)
return nil if spec.nil?
path = templates_dir.join("#{platform}.yaml.erb")
path = templates_dir.join(platform, "pipeline.yaml.erb")
return nil unless path.exist?
ERB.new(path.read, trim_mode: "-").result_with_hash(
@@ -34,7 +34,7 @@ module WarpEngine
end
def templates_dir
WarpEngine::Engine.root.join("lib", "warp_engine", "ci_templates")
WarpEngine::Engine.root.join("app", "services", "warp_engine", "platforms")
end
end
end
@@ -0,0 +1,14 @@
module WarpEngine
module Platforms
module Bevy
class Service
include Updatable
include Builds::BuildWeb
include Builds::BuildWinX64
include Builds::BuildLinuxX64
label "Bevy"
end
end
end
end
@@ -0,0 +1,14 @@
module WarpEngine
module Platforms
module C64
class Service
include Updatable
include Builds::BuildCartridge
label "C64"
def cartridge_ext = ".prg"
end
end
end
end
@@ -0,0 +1,17 @@
module WarpEngine
module Platforms
module Ebitengine
class Service
include Updatable
include Builds::BuildWeb
include Builds::BuildWinX86
include Builds::BuildWinX64
include Builds::BuildLinuxX64
include Builds::BuildMacX64
include Builds::BuildMacArm64
label "Ebitengine"
end
end
end
end
@@ -0,0 +1,16 @@
module WarpEngine
module Platforms
module Godot
class Service
include Updatable
include Builds::BuildWeb
include Builds::BuildWinX86
include Builds::BuildWinX64
include Builds::BuildLinuxX64
include Builds::BuildMacUniversal
label "Godot"
end
end
end
end
@@ -0,0 +1,15 @@
module WarpEngine
module Platforms
module Love
class Service
include Updatable
include Builds::BuildWeb
include Builds::BuildWinX64
include Builds::BuildLinuxX64
include Builds::BuildMacUniversal
label "LÖVE"
end
end
end
end
@@ -0,0 +1,12 @@
module WarpEngine
module Platforms
module Phaser
class Service
include Updatable
include Builds::BuildWeb
label "Phaser"
end
end
end
end
@@ -0,0 +1,40 @@
module WarpEngine
module Platforms
module Tic80
class Service
include Updatable
include Builds::BuildCartridge
include Builds::BuildSource
include Builds::BuildWeb
include Builds::BuildDocs
include Builds::BuildWinX64
include Builds::BuildLinuxX64
include Builds::BuildMacX64
label "TIC-80"
def cartridge_ext = ".tic"
def source_ext = ".lua"
private
def parse_metadata(versioned)
parse_lua_metadata(full_path("#{versioned}.lua"))
end
def parse_lua_metadata(source_path)
metadata = {}
File.foreach(source_path) do |line|
break unless line.start_with?("--")
parts = line[2..].split(":", 2)
next if parts.length != 2
key = parts[0].strip.downcase.to_sym
value = parts[1].strip
metadata[key] = value
end
metadata.slice(*MetadataParsing::METADATA_KEYS)
end
end
end
end
end
@@ -1,11 +1,11 @@
module WarpEngine
class UpdateService
def update(input)
class PublishService
def publish(input)
unless WarpEngine::PlatformLink::SUPPORTED_PLATFORMS.include?(input.platform)
raise ArgumentError, "Unsupported platform: #{input.platform}"
end
"WarpEngine::SoftwareUpdater::#{input.platform.camelize}Service".constantize.new.update(input.name, input.version)
"WarpEngine::Platforms::#{input.platform.camelize}::Service".constantize.new.update(input.name, input.version)
end
end
end
@@ -1,12 +0,0 @@
module WarpEngine
module SoftwareUpdater
class BevyService
include Updatable
include Builds::BuildWeb
include Builds::BuildWinX64
include Builds::BuildLinuxX64
label "Bevy"
end
end
end
@@ -1,12 +0,0 @@
module WarpEngine
module SoftwareUpdater
class C64Service
include Updatable
include Builds::BuildCartridge
label "C64"
def cartridge_ext = ".prg"
end
end
end
@@ -1,15 +0,0 @@
module WarpEngine
module SoftwareUpdater
class EbitengineService
include Updatable
include Builds::BuildWeb
include Builds::BuildWinX86
include Builds::BuildWinX64
include Builds::BuildLinuxX64
include Builds::BuildMacX64
include Builds::BuildMacArm64
label "Ebitengine"
end
end
end
@@ -1,14 +0,0 @@
module WarpEngine
module SoftwareUpdater
class GodotService
include Updatable
include Builds::BuildWeb
include Builds::BuildWinX86
include Builds::BuildWinX64
include Builds::BuildLinuxX64
include Builds::BuildMacUniversal
label "Godot"
end
end
end
@@ -1,13 +0,0 @@
module WarpEngine
module SoftwareUpdater
class LoveService
include Updatable
include Builds::BuildWeb
include Builds::BuildWinX64
include Builds::BuildLinuxX64
include Builds::BuildMacUniversal
label "LÖVE"
end
end
end
@@ -1,10 +0,0 @@
module WarpEngine
module SoftwareUpdater
class PhaserService
include Updatable
include Builds::BuildWeb
label "Phaser"
end
end
end
@@ -1,38 +0,0 @@
module WarpEngine
module SoftwareUpdater
class Tic80Service
include Updatable
include Builds::BuildCartridge
include Builds::BuildSource
include Builds::BuildWeb
include Builds::BuildDocs
include Builds::BuildWinX64
include Builds::BuildLinuxX64
include Builds::BuildMacX64
label "TIC-80"
def cartridge_ext = ".tic"
def source_ext = ".lua"
private
def parse_metadata(versioned)
parse_lua_metadata(full_path("#{versioned}.lua"))
end
def parse_lua_metadata(source_path)
metadata = {}
File.foreach(source_path) do |line|
break unless line.start_with?("--")
parts = line[2..].split(":", 2)
next if parts.length != 2
key = parts[0].strip.downcase.to_sym
value = parts[1].strip
metadata[key] = value
end
metadata.slice(*MetadataParsing::METADATA_KEYS)
end
end
end
end
@@ -184,11 +184,11 @@ RSpec.describe "Build configs endpoint", type: :request do
describe "shipped templates" do
it "renders every template to valid YAML with non-empty steps" do
templates = Dir[WarpEngine::Engine.root.join("lib/warp_engine/ci_templates/*.yaml.erb")]
templates = Dir[WarpEngine::Engine.root.join("app/services/warp_engine/platforms/*/pipeline.yaml.erb")]
expect(templates).not_to be_empty
templates.each do |path|
platform = File.basename(path, ".yaml.erb")
platform = File.basename(File.dirname(path))
allow(WarpEngine.config).to receive(:ci_platforms).and_return(
platform => { builder: "registry.example/builder:1", exporter: "registry.example/exporter:1" }
)
@@ -6,8 +6,8 @@ RSpec.describe "POST /build/publish", type: :request do
end
def stub_updater
updater = instance_double(WarpEngine::SoftwareUpdater::Tic80Service)
allow(WarpEngine::SoftwareUpdater::Tic80Service).to receive(:new).and_return(updater)
updater = instance_double(WarpEngine::Platforms::Tic80::Service)
allow(WarpEngine::Platforms::Tic80::Service).to receive(:new).and_return(updater)
allow(updater).to receive(:update)
updater
end
@@ -1,7 +1,7 @@
require "rails_helper"
require "zip"
RSpec.describe WarpEngine::SoftwareUpdater::Tic80Service do
RSpec.describe WarpEngine::Platforms::Tic80::Service do
let(:tmpdir) { Dir.mktmpdir }
let(:name) { "spectic" }
let(:version) { "9.9" }
@@ -0,0 +1,59 @@
require "rails_helper"
RSpec.describe WarpEngine::PublishService do
describe "#publish" do
it "raises ArgumentError for unsupported platform" do
input = WarpEngine::PublishInputDto.new(platform: "unknown", name: "game", version: "1.0")
expect { described_class.new.publish(input) }.to raise_error(ArgumentError, /Unsupported platform/)
end
it "routes to correct platform service" do
input = WarpEngine::PublishInputDto.new(platform: "tic80", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::Platforms::Tic80::Service)
allow(WarpEngine::Platforms::Tic80::Service).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.publish(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
it "routes godot platform to Godot::Service" do
input = WarpEngine::PublishInputDto.new(platform: "godot", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::Platforms::Godot::Service)
allow(WarpEngine::Platforms::Godot::Service).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.publish(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
it "routes bevy platform to Bevy::Service" do
input = WarpEngine::PublishInputDto.new(platform: "bevy", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::Platforms::Bevy::Service)
allow(WarpEngine::Platforms::Bevy::Service).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.publish(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
it "routes phaser platform to Phaser::Service" do
input = WarpEngine::PublishInputDto.new(platform: "phaser", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::Platforms::Phaser::Service)
allow(WarpEngine::Platforms::Phaser::Service).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.publish(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
end
end
@@ -1,59 +0,0 @@
require "rails_helper"
RSpec.describe WarpEngine::UpdateService do
describe "#update" do
it "raises ArgumentError for unsupported platform" do
input = WarpEngine::UpdateInputDto.new(platform: "unknown", name: "game", version: "1.0")
expect { described_class.new.update(input) }.to raise_error(ArgumentError, /Unsupported platform/)
end
it "routes to correct platform service" do
input = WarpEngine::UpdateInputDto.new(platform: "tic80", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::SoftwareUpdater::Tic80Service)
allow(WarpEngine::SoftwareUpdater::Tic80Service).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.update(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
it "routes godot platform to GodotService" do
input = WarpEngine::UpdateInputDto.new(platform: "godot", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::SoftwareUpdater::GodotService)
allow(WarpEngine::SoftwareUpdater::GodotService).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.update(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
it "routes bevy platform to BevyService" do
input = WarpEngine::UpdateInputDto.new(platform: "bevy", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::SoftwareUpdater::BevyService)
allow(WarpEngine::SoftwareUpdater::BevyService).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.update(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
it "routes phaser platform to PhaserService" do
input = WarpEngine::UpdateInputDto.new(platform: "phaser", name: "game", version: "1.0")
mock_service = instance_double(WarpEngine::SoftwareUpdater::PhaserService)
allow(WarpEngine::SoftwareUpdater::PhaserService).to receive(:new).and_return(mock_service)
allow(mock_service).to receive(:update)
described_class.new.update(input)
expect(mock_service).to have_received(:update).with("game", "1.0")
end
end
end