Skip to content

Commit 311ce86

Browse files
committed
Replace chatops with native discord bot
1 parent 509a7bd commit 311ce86

10 files changed

Lines changed: 199 additions & 75 deletions

File tree

.github/workflows/main.yml

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ on:
88
pull_request:
99

1010
jobs:
11-
build:
11+
lint:
1212
runs-on: ubuntu-latest
1313
name: Ruby
1414

@@ -21,3 +21,23 @@ jobs:
2121
bundler-cache: true
2222
- name: Run rubocop
2323
run: bundle exec rubocop
24+
25+
build-docker:
26+
name: Build Image
27+
runs-on: ubuntu-latest
28+
29+
permissions:
30+
packages: write
31+
32+
steps:
33+
- uses: actions/checkout@v6
34+
- run: >-
35+
docker build
36+
-t ghcr.io/code0-tech/pyxis:${{ github.run_number }}
37+
-f Dockerfile
38+
.
39+
- run: echo ${{ secrets.GITHUB_TOKEN }} | docker login -u $ --password-stdin ghcr.io
40+
name: Login to registry
41+
if: ${{ github.event_name == 'push' }}
42+
- run: docker push ghcr.io/code0-tech/pyxis:${{ github.run_number }}
43+
if: ${{ github.event_name == 'push' }}

.gitlab-ci.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,4 @@
1-
include:
2-
- local: .gitlab/ci/chatops.gitlab-ci.yml
3-
41
stages:
5-
- chatops
62
- components
73

84
default:
@@ -24,6 +20,6 @@ components:update:
2420
- taurus
2521
script:
2622
- bundle install
27-
- bin/pyxis components update $COMPONENT
23+
- bin/pyxis components update --component $COMPONENT
2824
rules:
2925
- if: $UPDATE_COMPONENTS == "true"

.gitlab/ci/chatops.gitlab-ci.yml

Lines changed: 0 additions & 14 deletions
This file was deleted.

Dockerfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
FROM ruby:3.2.2
2+
COPY . /pyxis
3+
WORKDIR /pyxis
4+
RUN bundle install

Gemfile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ gem 'openssl', '~> 3.3'
1616
gem 'semantic_logger', '~> 4.16'
1717

1818
gem 'json', '~> 2.12'
19+
20+
gem 'discordrb', '~> 3.7'

Gemfile.lock

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ GEM
66
ast (2.4.3)
77
base64 (0.3.0)
88
concurrent-ruby (1.3.5)
9+
discordrb (3.7.2)
10+
base64 (~> 0.2)
11+
discordrb-webhooks (~> 3.7.2)
12+
ffi (>= 1.9.24)
13+
opus-ruby
14+
rest-client (>= 2.0.0)
15+
websocket-client-simple (>= 0.9.0)
16+
discordrb-webhooks (3.7.2)
17+
rest-client (>= 2.0.0)
18+
domain_name (0.6.20240107)
19+
event_emitter (0.2.6)
920
faraday (2.13.1)
1021
faraday-net_http (>= 2.0, < 3.5)
1122
json
@@ -14,18 +25,30 @@ GEM
1425
net-http (>= 0.5.0)
1526
faraday-retry (2.3.1)
1627
faraday (~> 2.0)
28+
ffi (1.17.3)
29+
http-accept (1.7.0)
30+
http-cookie (1.1.0)
31+
domain_name (~> 0.5)
1732
json (2.12.2)
1833
jwt (2.10.1)
1934
base64
2035
language_server-protocol (3.17.0.5)
2136
lint_roller (1.1.0)
2237
logger (1.7.0)
38+
mime-types (3.7.0)
39+
logger
40+
mime-types-data (~> 3.2025, >= 3.2025.0507)
41+
mime-types-data (3.2026.0113)
42+
mutex_m (0.3.0)
2343
net-http (0.6.0)
2444
uri
45+
netrc (0.11.0)
2546
octokit (10.0.0)
2647
faraday (>= 1, < 3)
2748
sawyer (~> 0.9)
2849
openssl (3.3.0)
50+
opus-ruby (1.0.1)
51+
ffi
2952
parallel (1.27.0)
3053
parser (3.3.8.0)
3154
ast (~> 2.4.1)
@@ -35,6 +58,11 @@ GEM
3558
racc (1.8.1)
3659
rainbow (3.1.1)
3760
regexp_parser (2.10.0)
61+
rest-client (2.1.0)
62+
http-accept (>= 1.7.0, < 2.0)
63+
http-cookie (>= 1.0.2, < 2.0)
64+
mime-types (>= 1.16, < 4.0)
65+
netrc (~> 0.8)
3866
rubocop (1.76.0)
3967
json (~> 2.3)
4068
language_server-protocol (~> 3.17.0.2)
@@ -60,12 +88,19 @@ GEM
6088
unicode-emoji (~> 4.0, >= 4.0.4)
6189
unicode-emoji (4.0.4)
6290
uri (1.0.3)
91+
websocket (1.2.11)
92+
websocket-client-simple (0.9.0)
93+
base64
94+
event_emitter
95+
mutex_m
96+
websocket
6397
zeitwerk (2.7.3)
6498

6599
PLATFORMS
66100
ruby
67101

68102
DEPENDENCIES
103+
discordrb (~> 3.7)
69104
faraday-retry (~> 2.3)
70105
json (~> 2.12)
71106
jwt (~> 2.10)

bin/chatops

Lines changed: 0 additions & 44 deletions
This file was deleted.

bin/discord

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
#!/usr/bin/env ruby
2+
# frozen_string_literal: true
3+
4+
require_relative '../lib/pyxis'
5+
require 'discordrb'
6+
require 'discordrb/webhooks'
7+
8+
token = File.read(ENV.fetch('PYXIS_DC_RELEASE_TOOLS_TOKEN'))
9+
bot = Discordrb::Bot.new(token: token, intents: %i[servers])
10+
11+
def build_command(name, description)
12+
{
13+
name: name,
14+
description: description,
15+
type: 1, # chat_input
16+
contexts: [0], # guild
17+
}
18+
end
19+
20+
OPTION_TYPES = {
21+
string: 3,
22+
boolean: 5,
23+
numeric: 4,
24+
}.freeze
25+
26+
def build_options(thor_options)
27+
options = []
28+
29+
thor_options.each_pair do |name, option|
30+
opt = {
31+
name: name,
32+
description: option.description,
33+
type: OPTION_TYPES[option.type],
34+
required: option.required,
35+
}
36+
37+
options << opt
38+
end
39+
40+
options
41+
end
42+
43+
def build_subcommands(thor_class)
44+
subcommands = []
45+
46+
thor_class.commands.each_pair do |name, command|
47+
cmd = {
48+
type: 1, # sub_command
49+
name: name,
50+
description: command.description,
51+
options: build_options(command.options),
52+
}
53+
54+
subcommands << cmd
55+
end
56+
57+
subcommands
58+
end
59+
60+
def build_from_thor(thor_class)
61+
commands = []
62+
63+
thor_class.commands.each_pair do |name, command|
64+
cmd = build_command(name, command.description)
65+
cmd[:options] =
66+
if thor_class.subcommand_classes.key?(name)
67+
build_subcommands(thor_class.subcommand_classes[name])
68+
else
69+
build_options(command.options)
70+
end
71+
72+
commands << cmd
73+
end
74+
75+
commands
76+
end
77+
78+
commands = build_from_thor(Pyxis::Cli)
79+
80+
Discordrb::API::Application.bulk_overwrite_global_commands(bot.instance_variable_get(:@token), bot.profile.id, commands)
81+
82+
stop_signals = %w[QUIT INT TERM]
83+
84+
stop_signals.each do |signal|
85+
Signal.trap(signal) do
86+
bot.stop
87+
end
88+
end
89+
90+
def build_command_from_event(data)
91+
parts = []
92+
93+
if data['type'] == 1
94+
parts << data['name']
95+
data['options'].each do |option|
96+
parts += build_command_from_event(option)
97+
end
98+
elsif [3, 4, 5].include?(data['type'])
99+
parts << "--#{data['name']}"
100+
parts << data['value'].to_s
101+
end
102+
103+
parts
104+
end
105+
106+
bot.interaction_create do |event|
107+
event.defer(ephemeral: false)
108+
109+
begin
110+
command = build_command_from_event(event.interaction.data)
111+
SemanticLogger['DiscordBot'].info('Executing command', command: command)
112+
result = Pyxis::Cli.start(command, { debug: true })
113+
color = '#4caf50'
114+
rescue Thor::Error, Pyxis::Error => e
115+
result = "#{e.class}\n#{e.message}"
116+
color = '#f44336'
117+
end
118+
119+
event.edit_response(embeds: [Discordrb::Webhooks::Embed.new(description: result, color: color)])
120+
end
121+
122+
bot.run

bin/pyxis

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ require_relative '../lib/pyxis'
66
result = Pyxis::Cli.start(ARGV)
77
SemanticLogger.flush
88

9-
puts result
9+
puts result if result.is_a?(String)

lib/pyxis/commands/components.rb

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@ module Commands
55
class Components < Thor
66
include PermissionHelper
77

8-
desc 'info [BUILD_ID]', 'Get the component versions for a reticulum build'
9-
def info(build_id)
10-
component_versions = ManagedVersioning::ComponentInfo.new(build_id).execute
8+
desc 'info', 'Get the component versions for a reticulum build'
9+
method_option :build, aliases: '-b', desc: 'The build ID', required: true, type: :numeric
10+
def info
11+
component_versions = ManagedVersioning::ComponentInfo.new(options[:build]).execute
1112

1213
result = 'Versions of each component'
1314
component_versions.each do |component, version|
@@ -16,11 +17,12 @@ def info(build_id)
1617
result
1718
end
1819

19-
desc 'update [COMPONENT]', 'Update a component in reticulum'
20-
def update(component)
20+
desc 'update', 'Update a component in reticulum'
21+
method_option :component, aliases: '-c', desc: 'The component to update', required: true, type: :string
22+
def update
2123
assert_executed_by_schedule!
2224

23-
updater(component).execute
25+
updater(options[:component]).execute
2426
end
2527

2628
desc 'list', 'List all available components'
@@ -32,10 +34,11 @@ def list
3234
result
3335
end
3436

35-
desc 'get_version COMPONENT', 'Get the current version of a component in reticulum'
36-
def get_version(component)
37-
current_version = updater(component).find_current_version
38-
puts "Current version of #{component}: #{current_version}"
37+
desc 'get_version', 'Get the current version of a component in reticulum'
38+
method_option :component, aliases: '-c', desc: 'The component to check', required: true, type: :string
39+
def get_version # rubocop:disable Naming/AccessorMethodName
40+
current_version = updater(options[:component]).find_current_version
41+
puts "Current version of #{options[:component]}: #{current_version}"
3942
end
4043

4144
no_commands do

0 commit comments

Comments
 (0)