From da37e39774f511fbc43218e9a85d4b9a34235daa Mon Sep 17 00:00:00 2001 From: Zsolt Tasnadi Date: Mon, 3 Aug 2026 23:46:50 +0200 Subject: [PATCH] Make docs optional in the tic80 updater Older-style tic80 pipelines (bombexpert, mranderson) do not upload a docs zip; the unconditional extraction raised and aborted the whole update, so the new binary assets never got registered. Extract and register docs only when the zip/dir exists. Covered by new Tic80Service specs (optional docs + binary slug pickup). Co-Authored-By: Claude Fable 5 --- .../software_updater/tic80_service.rb | 13 +++- .../software_updater/tic80_service_spec.rb | 73 +++++++++++++++++++ 2 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 apps/api/spec/services/software_updater/tic80_service_spec.rb diff --git a/apps/api/app/services/software_updater/tic80_service.rb b/apps/api/app/services/software_updater/tic80_service.rb index 3af1902..b88ad3e 100644 --- a/apps/api/app/services/software_updater/tic80_service.rb +++ b/apps/api/app/services/software_updater/tic80_service.rb @@ -4,9 +4,12 @@ module SoftwareUpdater private + # a docs opcionális: a régebbi sémájú tic80 pipeline-ok nem töltenek fel + # docs zipet, e nélkül is regisztrálni kell a többi assetet def prepare_files(versioned) extract_zip_to_dir("#{versioned}.html.zip", versioned) - extract_zip_to_dir("#{versioned}-docs.zip", "#{versioned}-docs") + docs_zip = "#{versioned}-docs.zip" + extract_zip_to_dir(docs_zip, "#{versioned}-docs") if File.file?(full_path(docs_zip)) end def parse_metadata(versioned) @@ -14,12 +17,14 @@ module SoftwareUpdater end def asset_paths(versioned) - { + paths = { "cartridge" => full_path("#{versioned}.tic"), "source" => full_path("#{versioned}.lua"), - "html" => full_path(versioned), - "docs" => full_path("#{versioned}-docs") + "html" => full_path(versioned) } + docs_dir = "#{versioned}-docs" + paths["docs"] = full_path(docs_dir) if dir_exists?(docs_dir) + paths end def parse_lua_metadata(source_path) diff --git a/apps/api/spec/services/software_updater/tic80_service_spec.rb b/apps/api/spec/services/software_updater/tic80_service_spec.rb new file mode 100644 index 0000000..55e54c3 --- /dev/null +++ b/apps/api/spec/services/software_updater/tic80_service_spec.rb @@ -0,0 +1,73 @@ +require "rails_helper" +require "zip" + +RSpec.describe SoftwareUpdater::Tic80Service do + let(:tmpdir) { Dir.mktmpdir } + let(:name) { "spectic" } + let(:version) { "9.9" } + let(:versioned) { "#{name}-#{version}" } + + before do + allow(ENV).to receive(:fetch).and_call_original + allow(ENV).to receive(:fetch).with("FILE_CONTAINER_PATH", "/softwares").and_return(tmpdir) + + write_zip("#{versioned}.html.zip", "index.html" => "") + File.write(File.join(tmpdir, "#{versioned}.tic"), "TIC!") + File.write(File.join(tmpdir, "#{versioned}.lua"), <<~LUA) + -- title: Spec TIC + -- name: #{name} + -- author: RSpec + -- desc: spec fixture + -- version: #{version} + function TIC() end + LUA + end + + after do + FileUtils.remove_entry(tmpdir) + Software.unscoped.where(name: name).each do |sw| + Release.unscoped.where(software_id: sw.id).each do |r| + ReleaseAsset.unscoped.where(release_id: r.id).delete_all + r.delete + end + ExternalLink.unscoped.where(software_id: sw.id).delete_all + sw.delete + end + end + + def write_zip(filename, entries) + Zip::File.open(File.join(tmpdir, filename), create: true) do |zip| + entries.each do |entry_name, content| + zip.get_output_stream(entry_name) { |io| io.write(content) } + end + end + end + + def asset_kinds(release) + ReleaseAsset.unscoped.where(release_id: release.id).pluck(:kind) + end + + it "registers the release without a docs zip" do + release = described_class.new.update(name, version) + + expect(asset_kinds(release)).to match_array(%w[cartridge source html]) + end + + it "registers docs when the docs zip is present" do + write_zip("#{versioned}-docs.zip", "index.html" => "docs") + + release = described_class.new.update(name, version) + + expect(asset_kinds(release)).to include("docs") + end + + it "registers binary assets when slug zips are present" do + write_zip("#{versioned}-win-x64.zip", "game.exe" => "MZ") + write_zip("#{versioned}-mac-universal.zip", "game" => "bin") + + release = described_class.new.update(name, version) + + expect(asset_kinds(release)).to include("win_x64", "mac_universal") + expect(asset_kinds(release)).not_to include("linux_x64") + end +end