pgbus 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11fc5e1aa1196d1332b426e72aab0364cc548925fe960ff6626a6cd8090b2de5
4
- data.tar.gz: 52fd690b0a3afda834850f5fc0eb3a111fd18062af6b3ca7097fadc085abf1b9
3
+ metadata.gz: 85f2e8748cf70bb74cb736b23e3e0288be5ca0b946b0eb80c08e1d28650e98c0
4
+ data.tar.gz: d1fd675bb9d9a5beb4607f8e0da684c606d096a835948abf60034bd601cdd7f2
5
5
  SHA512:
6
- metadata.gz: f232df26f7a0122db40119b43bf0d03290ea583eaf889ac58c95bb81850c5f745603fa81b848be437f4298ffff5ed65c82c64b890da64bc663ef600a4d05fe0c
7
- data.tar.gz: c2d5f381fa2e4cf4943fe9bd27815459faaf9f92c7bf40d97bb2ea93b5622dcb5a197d8ccdb63249fd2ee681d4c10961070e7016093bacda2ba81010939cd7aa
6
+ metadata.gz: 99b168d4276ef5149effdbf7d18955c542b9f8507a67d022381a61c7c36cacdf58ab414e166e528495e244313ef12d10e054119361bbf77ca2e6cc260f6d1982
7
+ data.tar.gz: 606324c33ddd072b24135c91314258fc2c162e54b6610ec813457cae2b4df3ba5c0391fc5dbd8a1ff6e13f14032968320b41b9a1d9450d0b5fbe2d66686f2c9e
data/Rakefile CHANGED
@@ -50,15 +50,24 @@ task :build do
50
50
  sh("rm -rf /tmp/gem-verify #{gem_file}")
51
51
  end
52
52
 
53
- desc "Release a new version (rake release[1.2.3] or rake release[pre])"
54
- task :release, [:version] do |_t, args|
53
+ desc "Release a new version (rake release[1.2.3] or rake release[pre] or rake release[1.2.3,force])"
54
+ task :release, %i[version force] do |_t, args|
55
55
  require_relative "lib/pgbus/version"
56
56
 
57
+ def info(msg) = puts "\e[34m→\e[0m #{msg}"
58
+ def success(msg) = puts "\e[32m✓\e[0m #{msg}"
59
+ def skip(msg) = puts "\e[33m⊘\e[0m #{msg} \e[33m(skipped)\e[0m"
60
+ def warn(msg) = puts "\e[33m⚠\e[0m #{msg}"
61
+ def error(msg) = puts "\e[31m✗\e[0m #{msg}"
62
+ def header(msg) = puts "\n\e[1;36m#{msg}\e[0m\n#{"─" * msg.length}"
63
+
57
64
  new_version = args[:version]
58
- abort "Usage: rake release[X.Y.Z] or rake release[pre]" unless new_version
65
+ abort "\e[31mUsage: rake release[X.Y.Z] or rake release[X.Y.Z,force]\e[0m" unless new_version
66
+
67
+ force = args[:force]&.to_s&.downcase == "force"
59
68
 
60
69
  dirty = `git status --porcelain`.strip
61
- abort "Aborting: working directory is not clean.\n#{dirty}" unless dirty.empty?
70
+ abort "\e[31mAborting: working directory is not clean.\e[0m\n#{dirty}" unless dirty.empty?
62
71
 
63
72
  current = Pgbus::VERSION
64
73
  prerelease = new_version.match?(/alpha|beta|rc|pre/) || new_version == "pre"
@@ -69,43 +78,97 @@ task :release, [:version] do |_t, args|
69
78
  end
70
79
 
71
80
  tag = "v#{new_version}"
81
+ version_file = "lib/pgbus/version.rb"
72
82
 
73
- puts "Current version: #{current}"
74
- puts "New version: #{new_version}"
75
- puts "Tag: #{tag}"
76
- puts "Pre-release: #{prerelease}"
77
- puts ""
83
+ title = "Release #{tag}"
84
+ title += " (force)" if force
85
+ header title
86
+ info "Current version: #{current}"
87
+ info "New version: #{new_version}"
88
+ info "Pre-release: #{prerelease}"
89
+
90
+ # Step 0: Force cleanup — delete existing release and tag
91
+ if force
92
+ header "Force cleanup"
93
+ if system("gh release view #{tag} >/dev/null 2>&1")
94
+ sh("gh release delete #{tag} --yes --cleanup-tag")
95
+ success "Deleted release and remote tag #{tag}"
96
+ else
97
+ skip "No release #{tag} to delete"
98
+ end
99
+
100
+ if system("git rev-parse #{tag} >/dev/null 2>&1")
101
+ sh("git tag -d #{tag}")
102
+ success "Deleted local tag #{tag}"
103
+ else
104
+ skip "No local tag #{tag} to delete"
105
+ end
106
+ end
78
107
 
79
- # Update version file if needed
80
- version_file = "lib/pgbus/version.rb"
81
- if new_version != current
108
+ # Step 1: Update version file
109
+ header "Version"
110
+ if new_version == current
111
+ skip "Version already #{new_version}"
112
+ else
82
113
  content = File.read(version_file)
83
114
  content.sub!(/VERSION = ".*"/, "VERSION = \"#{new_version}\"")
84
115
  File.write(version_file, content)
85
- puts "Updated #{version_file}"
116
+ success "Updated #{version_file}"
86
117
  end
87
118
 
88
- # Verify gem builds cleanly
119
+ # Step 2: Verify gem builds cleanly
120
+ header "Build verification"
89
121
  sh("gem build pgbus.gemspec --strict")
90
122
  sh("rm -f pgbus-*.gem")
123
+ success "Gem builds cleanly"
91
124
 
92
- # Commit, push, and create release
93
- if new_version != current
125
+ # Step 3: Commit version bump
126
+ header "Git commit"
127
+ version_changed = !`git diff #{version_file}`.strip.empty? || !`git diff --cached #{version_file}`.strip.empty?
128
+ if version_changed
94
129
  sh("git add #{version_file}")
95
130
  sh("git commit -m 'chore: bump version to #{new_version}'")
131
+ success "Committed version bump"
132
+ else
133
+ skip "No version change to commit"
134
+ end
135
+
136
+ # Step 4: Push to origin
137
+ header "Git push"
138
+ local_sha = `git rev-parse HEAD`.strip
139
+ remote_sha = `git rev-parse origin/main 2>/dev/null`.strip
140
+ if local_sha == remote_sha
141
+ skip "origin/main already at #{local_sha[0..6]}"
142
+ else
143
+ sh("git push origin main")
144
+ success "Pushed to origin/main"
96
145
  end
97
- sh("git push origin main")
98
146
 
99
- pre_flag = prerelease ? "--prerelease" : ""
100
- sh("gh release create #{tag} --generate-notes --target main #{pre_flag}".strip)
147
+ # Step 5: Create release
148
+ header "Release"
149
+ tag_exists = system("git rev-parse #{tag} >/dev/null 2>&1")
150
+ release_exists = system("gh release view #{tag} >/dev/null 2>&1")
151
+
152
+ if release_exists
153
+ skip "Release #{tag} already exists (use force to re-create)"
154
+ elsif tag_exists
155
+ info "Tag #{tag} exists, creating release from it"
156
+ pre_flag = prerelease ? "--prerelease" : ""
157
+ sh("gh release create #{tag} --generate-notes #{pre_flag}".strip)
158
+ success "Release #{tag} created from existing tag"
159
+ else
160
+ pre_flag = prerelease ? "--prerelease" : ""
161
+ sh("gh release create #{tag} --generate-notes --target main #{pre_flag}".strip)
162
+ success "Release #{tag} created"
163
+ end
101
164
 
102
165
  puts ""
103
- puts "Release #{tag} created! CI will handle the rest:"
104
- puts " - Run tests"
105
- puts " - Build + verify gem"
106
- puts " - Sign with Sigstore"
107
- puts " - Publish to RubyGems"
108
- puts " - Upload assets to the release"
166
+ success "\e[1mRelease #{tag} complete!\e[0m CI will handle the rest:"
167
+ puts " Run tests"
168
+ puts " Build + verify gem"
169
+ puts " Sign with Sigstore"
170
+ puts " Publish to RubyGems"
171
+ puts " Upload assets to the release"
109
172
  end
110
173
 
111
174
  task default: %i[spec rubocop]
@@ -51,6 +51,7 @@ module Pgbus
51
51
  @available_locales ||= Dir[Pgbus::Engine.root.join("config", "locales", "*.yml")]
52
52
  .map { |f| File.basename(f, ".yml").to_sym }
53
53
  end
54
+ helper_method :available_locales
54
55
 
55
56
  def data_source
56
57
  @data_source ||= Pgbus.configuration.web_data_source || Web::DataSource.new
@@ -67,9 +68,8 @@ module Pgbus
67
68
  def insights_minutes
68
69
  config = Pgbus.configuration
69
70
  default = config.insights_default_minutes.to_i
70
- max = config.stats_retention.to_i / 60
71
71
  value = (params[:minutes] || default).to_i
72
- value.clamp(1, [max, 1].max)
72
+ value.clamp(1, [default, 43_200].max)
73
73
  end
74
74
 
75
75
  def turbo_frame_request?
@@ -4,6 +4,12 @@
4
4
  <meta charset="utf-8">
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1">
6
6
  <title><%= t("pgbus.layout.title") %></title>
7
+ <style>
8
+ /* Prevent white flash during navigation in dark mode.
9
+ Applied before Tailwind CDN loads so the background is correct immediately. */
10
+ html.dark { background-color: #030712; } /* gray-950 */
11
+ html.dark body { background-color: #030712; }
12
+ </style>
7
13
  <script src="https://cdn.tailwindcss.com"></script>
8
14
  <script>
9
15
  tailwind.config = { darkMode: 'class' };
@@ -17,24 +23,17 @@
17
23
  var isDark = document.documentElement.classList.toggle('dark');
18
24
  localStorage.setItem('pgbus-dark', isDark);
19
25
  }
20
- // Locale dropdown toggle
26
+ // Close locale dropdown when clicking outside
21
27
  document.addEventListener('click', function(e) {
22
- var btn = e.target.closest('[data-action="click->dropdown#toggle"]');
23
- var menu = btn && btn.parentElement.querySelector('[data-dropdown-target="menu"]');
24
- // Close all menus first
25
- document.querySelectorAll('[data-dropdown-target="menu"]').forEach(function(m) {
26
- if (m !== menu) m.classList.add('hidden');
27
- });
28
- if (menu) { menu.classList.toggle('hidden'); e.stopPropagation(); }
29
- });
30
- document.addEventListener('click', function() {
31
- document.querySelectorAll('[data-dropdown-target="menu"]').forEach(function(m) {
32
- m.classList.add('hidden');
33
- });
28
+ var switcher = document.getElementById('pgbus-locale-switcher');
29
+ var menu = document.getElementById('pgbus-locale-menu');
30
+ if (menu && switcher && !switcher.contains(e.target)) {
31
+ menu.classList.add('hidden');
32
+ }
34
33
  });
35
34
  </script>
36
35
  <script type="module">
37
- import * as Turbo from "https://cdn.jsdelivr.net/npm/@hotwired/turbo@8/dist/turbo.es2017.esm.js";
36
+ import * as Turbo from "https://esm.sh/@hotwired/turbo@8";
38
37
 
39
38
  <% if Pgbus.configuration.web_live_updates %>
40
39
  const interval = <%= Pgbus.configuration.web_refresh_interval %>;
@@ -43,7 +42,10 @@
43
42
  function refreshFrames() {
44
43
  if (document.hidden) return;
45
44
  document.querySelectorAll("turbo-frame[data-auto-refresh]")
46
- .forEach(frame => frame.reload());
45
+ .forEach(frame => {
46
+ if (!frame.src && frame.dataset.src) frame.src = frame.dataset.src;
47
+ if (frame.src) frame.reload();
48
+ });
47
49
  }
48
50
  function start() { timer = setInterval(refreshFrames, interval); }
49
51
  function stop() { clearInterval(timer); }
@@ -81,19 +83,16 @@
81
83
 
82
84
  <div class="flex items-center space-x-2">
83
85
  <!-- Locale switcher -->
84
- <div class="relative" data-controller="dropdown">
85
- <button type="button" data-action="click->dropdown#toggle" class="rounded-md px-2 py-1.5 text-sm text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500">
86
+ <div class="relative" id="pgbus-locale-switcher">
87
+ <button type="button" onclick="document.getElementById('pgbus-locale-menu').classList.toggle('hidden')" class="rounded-md px-2 py-1 text-sm text-gray-300 hover:text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-indigo-500">
86
88
  <%= pgbus_locale_flag(I18n.locale) %> <%= I18n.locale.to_s.upcase %>
87
89
  </button>
88
- <div data-dropdown-target="menu" class="hidden absolute right-0 z-50 mt-1 w-44 origin-top-right rounded-md bg-white dark:bg-gray-800 shadow-lg ring-1 ring-black/5 dark:ring-white/10">
90
+ <div id="pgbus-locale-menu" class="hidden absolute right-0 z-50 mt-1 w-44 origin-top-right rounded-md bg-white dark:bg-gray-800 shadow-lg ring-1 ring-black/5 dark:ring-white/10">
89
91
  <div class="py-1" role="menu">
90
- <% controller.send(:available_locales).sort.each do |loc| %>
91
- <%= form_tag pgbus.set_locale_path, method: :post, class: "contents" do %>
92
- <%= hidden_field_tag :locale, loc %>
93
- <button type="submit" role="menuitem" class="w-full text-left px-3 py-1.5 text-sm <%= loc == I18n.locale ? 'bg-indigo-50 dark:bg-indigo-900/30 text-indigo-700 dark:text-indigo-300 font-medium' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700' %>">
94
- <%= pgbus_locale_flag(loc) %> <%= pgbus_locale_name(loc) %>
95
- </button>
96
- <% end %>
92
+ <% available_locales.sort.each do |loc| %>
93
+ <a href="<%= pgbus.set_locale_path(locale: loc) %>" role="menuitem" class="block px-3 py-1 text-sm no-underline <%= loc == I18n.locale ? 'bg-indigo-50 dark:bg-indigo-900/30 text-indigo-700 dark:text-indigo-300 font-medium' : 'text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700' %>">
94
+ <%= pgbus_locale_flag(loc) %> <%= pgbus_locale_name(loc) %>
95
+ </a>
97
96
  <% end %>
98
97
  </div>
99
98
  </div>
@@ -1,4 +1,4 @@
1
- <turbo-frame id="dashboard-processes" data-auto-refresh src="<%= pgbus.root_path(frame: 'processes') %>">
1
+ <turbo-frame id="dashboard-processes" data-auto-refresh data-src="<%= pgbus.root_path(frame: 'processes') %>">
2
2
  <div>
3
3
  <h2 class="text-lg font-semibold text-gray-900 dark:text-white mb-3"><%= t("pgbus.dashboard.processes_table.title") %></h2>
4
4
  <div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
@@ -1,4 +1,4 @@
1
- <turbo-frame id="dashboard-queues" data-auto-refresh src="<%= pgbus.root_path(frame: 'queues') %>">
1
+ <turbo-frame id="dashboard-queues" data-auto-refresh data-src="<%= pgbus.root_path(frame: 'queues') %>">
2
2
  <div class="mb-8">
3
3
  <div class="flex items-center justify-between mb-3">
4
4
  <h2 class="text-lg font-semibold text-gray-900 dark:text-white"><%= t("pgbus.dashboard.queues_table.title") %></h2>
@@ -1,4 +1,4 @@
1
- <turbo-frame id="dashboard-failures" data-auto-refresh src="<%= pgbus.root_path(frame: 'failures') %>">
1
+ <turbo-frame id="dashboard-failures" data-auto-refresh data-src="<%= pgbus.root_path(frame: 'failures') %>">
2
2
  <div>
3
3
  <div class="flex items-center justify-between mb-3">
4
4
  <h2 class="text-lg font-semibold text-gray-900 dark:text-white"><%= t("pgbus.dashboard.recent_failures.title") %></h2>
@@ -1,4 +1,4 @@
1
- <turbo-frame id="dashboard-stats" data-auto-refresh src="<%= pgbus.root_path(frame: 'stats') %>">
1
+ <turbo-frame id="dashboard-stats" data-auto-refresh data-src="<%= pgbus.root_path(frame: 'stats') %>">
2
2
  <div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-6 mb-8">
3
3
  <div class="rounded-lg bg-white dark:bg-gray-800 p-5 shadow ring-1 ring-gray-200 dark:ring-gray-700">
4
4
  <p class="text-sm font-medium text-gray-500 dark:text-gray-400"><%= t("pgbus.dashboard.stats_cards.queues") %></p>
@@ -1,4 +1,4 @@
1
- <turbo-frame id="dlq-messages" data-auto-refresh src="<%= pgbus.dead_letter_index_path(frame: 'list') %>">
1
+ <turbo-frame id="dlq-messages" data-auto-refresh data-src="<%= pgbus.dead_letter_index_path(frame: 'list') %>">
2
2
  <div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
3
3
  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
4
4
  <thead class="bg-gray-50 dark:bg-gray-900">
@@ -1,4 +1,4 @@
1
- <turbo-frame id="jobs-enqueued" data-auto-refresh src="<%= pgbus.jobs_path(request.query_parameters.merge(frame: 'enqueued')) %>">
1
+ <turbo-frame id="jobs-enqueued" data-auto-refresh data-src="<%= pgbus.jobs_path(request.query_parameters.merge(frame: 'enqueued')) %>">
2
2
  <div>
3
3
  <h2 class="text-lg font-semibold text-gray-900 dark:text-white mb-3"><%= t("pgbus.jobs.enqueued_table.title") %></h2>
4
4
  <div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
@@ -1,4 +1,4 @@
1
- <turbo-frame id="jobs-failed" data-auto-refresh src="<%= pgbus.jobs_path(frame: 'failed') %>">
1
+ <turbo-frame id="jobs-failed" data-auto-refresh data-src="<%= pgbus.jobs_path(frame: 'failed') %>">
2
2
  <div class="mb-8">
3
3
  <h2 class="text-lg font-semibold text-gray-900 dark:text-white mb-3"><%= t("pgbus.jobs.failed_table.title") %></h2>
4
4
  <div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
@@ -1,4 +1,4 @@
1
- <turbo-frame id="processes-list" data-auto-refresh src="<%= pgbus.processes_path(frame: 'list') %>">
1
+ <turbo-frame id="processes-list" data-auto-refresh data-src="<%= pgbus.processes_path(frame: 'list') %>">
2
2
  <div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
3
3
  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
4
4
  <thead class="bg-gray-50 dark:bg-gray-900">
@@ -1,4 +1,4 @@
1
- <turbo-frame id="queues-list" data-auto-refresh src="<%= pgbus.queues_path(frame: 'list') %>">
1
+ <turbo-frame id="queues-list" data-auto-refresh data-src="<%= pgbus.queues_path(frame: 'list') %>">
2
2
  <div class="overflow-hidden rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
3
3
  <table class="min-w-full divide-y divide-gray-200 dark:divide-gray-700">
4
4
  <thead class="bg-gray-50 dark:bg-gray-900">
@@ -1,4 +1,4 @@
1
- <turbo-frame id="recurring-tasks" data-auto-refresh src="<%= pgbus.recurring_tasks_path(frame: 'recurring_tasks') %>">
1
+ <turbo-frame id="recurring-tasks" data-auto-refresh data-src="<%= pgbus.recurring_tasks_path(frame: 'recurring_tasks') %>">
2
2
  <div class="rounded-lg bg-white dark:bg-gray-800 shadow ring-1 ring-gray-200 dark:ring-gray-700">
3
3
  <% if @recurring_tasks.empty? %>
4
4
  <div class="p-8 text-center text-gray-500">
data/config/routes.rb CHANGED
@@ -52,7 +52,7 @@ Pgbus::Engine.routes.draw do
52
52
  resources :locks, only: [:index]
53
53
  resource :insights, only: [:show], controller: "insights"
54
54
 
55
- post :set_locale, to: "locale#update"
55
+ get :set_locale, to: "locale#update"
56
56
 
57
57
  namespace :api do
58
58
  get :stats, to: "stats#show"
data/lib/pgbus/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pgbus
4
- VERSION = "0.2.2"
4
+ VERSION = "0.2.3"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pgbus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikael Henriksson