From dbb41df67ea6ae08c007323d4c27449afb911f27 Mon Sep 17 00:00:00 2001 From: Gabriel Jablonski Date: Thu, 28 Aug 2025 10:50:03 -0300 Subject: [PATCH] fix: update GitHub versions link and version fetching (#105) * fix: update GitHub versions link and version fetching * test: specs * chore: use timeout and log error * refactor: redundant helper method --- .../dashboard/components/app/UpdateBanner.vue | 2 +- app/jobs/internal/check_new_versions_job.rb | 17 +++- .../internal/check_new_versions_job_spec.rb | 97 +++++++++++++++++-- 3 files changed, 104 insertions(+), 12 deletions(-) diff --git a/app/javascript/dashboard/components/app/UpdateBanner.vue b/app/javascript/dashboard/components/app/UpdateBanner.vue index fcfcfe11f..d84b14366 100644 --- a/app/javascript/dashboard/components/app/UpdateBanner.vue +++ b/app/javascript/dashboard/components/app/UpdateBanner.vue @@ -73,7 +73,7 @@ export default { v-if="shouldShowBanner" color-scheme="primary" :banner-message="bannerMessage" - href-link="https://github.com/chatwoot/chatwoot/releases" + href-link="https://github.com/fazer-ai/chatwoot/releases" :href-link-text="$t('GENERAL_SETTINGS.LEARN_MORE')" has-close-button @close="dismissUpdateBanner" diff --git a/app/jobs/internal/check_new_versions_job.rb b/app/jobs/internal/check_new_versions_job.rb index a141385d0..23cf39be3 100644 --- a/app/jobs/internal/check_new_versions_job.rb +++ b/app/jobs/internal/check_new_versions_job.rb @@ -4,16 +4,23 @@ class Internal::CheckNewVersionsJob < ApplicationJob def perform return unless Rails.env.production? - @instance_info = ChatwootHub.sync_with_hub - update_version_info + latest_version = fetch_latest_github_release + ::Redis::Alfred.set(::Redis::Alfred::LATEST_CHATWOOT_VERSION, latest_version) if latest_version.present? end private - def update_version_info - return if @instance_info['version'].blank? + def fetch_latest_github_release + response = HTTParty.get('https://api.github.com/repos/fazer-ai/chatwoot/releases/latest', timeout: 5) + unless response.success? + Rails.logger.error "Failed to fetch latest GitHub release: HTTP #{response.code} - #{response.body}" + return nil + end - ::Redis::Alfred.set(::Redis::Alfred::LATEST_CHATWOOT_VERSION, @instance_info['version']) + response['tag_name']&.sub(/^v/, '') + rescue StandardError => e + Rails.logger.error "Failed to fetch latest GitHub release: #{e.message}" + nil end end diff --git a/spec/jobs/internal/check_new_versions_job_spec.rb b/spec/jobs/internal/check_new_versions_job_spec.rb index 82424e202..41aabbbe7 100644 --- a/spec/jobs/internal/check_new_versions_job_spec.rb +++ b/spec/jobs/internal/check_new_versions_job_spec.rb @@ -3,12 +3,97 @@ require 'rails_helper' RSpec.describe Internal::CheckNewVersionsJob do subject(:job) { described_class.perform_now } - it 'updates the latest chatwoot version in redis' do - data = { 'version' => '1.2.3' } + before do allow(Rails.env).to receive(:production?).and_return(true) - allow(ChatwootHub).to receive(:sync_with_hub).and_return(data) - job - expect(ChatwootHub).to have_received(:sync_with_hub) - expect(Redis::Alfred.get(Redis::Alfred::LATEST_CHATWOOT_VERSION)).to eq data['version'] + Redis::Alfred.delete(Redis::Alfred::LATEST_CHATWOOT_VERSION) + end + + describe '#perform' do + context 'when GitHub API returns successful response' do + before do + stub_request(:get, 'https://api.github.com/repos/fazer-ai/chatwoot/releases/latest') + .to_return( + status: 200, + body: { tag_name: 'v1.2.3' }.to_json, + headers: { 'Content-Type' => 'application/json' } + ) + end + + it 'updates the latest chatwoot version in redis with v prefix removed' do + job + expect(Redis::Alfred.get(Redis::Alfred::LATEST_CHATWOOT_VERSION)).to eq '1.2.3' + end + end + + context 'when tag name has no v prefix' do + before do + stub_request(:get, 'https://api.github.com/repos/fazer-ai/chatwoot/releases/latest') + .to_return( + status: 200, + body: { tag_name: '1.2.3' }.to_json, + headers: { 'Content-Type' => 'application/json' } + ) + end + + it 'handles tag names without v prefix' do + job + + expect(Redis::Alfred.get(Redis::Alfred::LATEST_CHATWOOT_VERSION)).to eq '1.2.3' + end + end + + context 'when GitHub API returns failed response' do + before do + stub_request(:get, 'https://api.github.com/repos/fazer-ai/chatwoot/releases/latest') + .to_return(status: 404) + allow(Rails.logger).to receive(:error) + end + + it 'does not update redis when response is not successful' do + expect { job }.not_to change { Redis::Alfred.get(Redis::Alfred::LATEST_CHATWOOT_VERSION) }.from(nil) + expect(Rails.logger).to have_received(:error).with(/Failed to fetch latest GitHub release: HTTP 404 - /) + end + end + + context 'when GitHub API raises an error' do + let(:error_message) { 'Network timeout' } + + before do + stub_request(:get, 'https://api.github.com/repos/fazer-ai/chatwoot/releases/latest') + .to_raise(StandardError.new(error_message)) + allow(Rails.logger).to receive(:error) + end + + it 'logs the error and does not update redis' do + expect { job }.not_to change { Redis::Alfred.get(Redis::Alfred::LATEST_CHATWOOT_VERSION) }.from(nil) + expect(Rails.logger).to have_received(:error).with("Failed to fetch latest GitHub release: #{error_message}") + end + end + + context 'when not in production environment' do + before do + allow(Rails.env).to receive(:production?).and_return(false) + end + + it 'does not make any API calls or update redis' do + expect { job }.not_to change { Redis::Alfred.get(Redis::Alfred::LATEST_CHATWOOT_VERSION) }.from(nil) + expect(a_request(:get, 'https://api.github.com/repos/fazer-ai/chatwoot/releases/latest')).not_to have_been_made + end + end + + context 'when tag_name is nil' do + before do + stub_request(:get, 'https://api.github.com/repos/fazer-ai/chatwoot/releases/latest') + .to_return( + status: 200, + body: { tag_name: nil }.to_json, + headers: { 'Content-Type' => 'application/json' } + ) + end + + it 'does not update redis when tag_name is nil' do + expect { job }.not_to change { Redis::Alfred.get(Redis::Alfred::LATEST_CHATWOOT_VERSION) }.from(nil) + end + end end end