Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 13 additions & 2 deletions .gitlab/ci/release-coordinator.canary.gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
.release-coordinator:canary:stages:
- release-coordinator:canary:notify-start
- release-coordinator:canary:prepare
- release-coordinator:canary:build
- release-coordinator:canary:publish
- release-coordinator:canary:notify-finish
Expand All @@ -11,12 +11,23 @@
release-coordinator:canary:notify-start:
extends:
- .release-coordinator:canary
stage: release-coordinator:canary:notify-start
stage: release-coordinator:canary:prepare
script:
- bin/pyxis internal notify_new_coordinator --coordinator-pipeline-id $CI_PIPELINE_ID
variables:
DRY_RUN: "false"

release-coordinator:canary:check:
extends:
- .release-coordinator:canary
stage: release-coordinator:canary:prepare
needs:
- release-coordinator:canary:notify-start
script:
- bin/pyxis internal check_canary_release --build-id-to-promote $BUILD_ID_TO_PROMOTE
variables:
DRY_RUN: "false"

release-coordinator:canary:tmp-branch:
extends:
- .release-coordinator:canary
Expand Down
8 changes: 7 additions & 1 deletion .rubocop.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
AllCops:
TargetRubyVersion: 3.2.0
TargetRubyVersion: 3.2
NewCops: enable

Metrics:
Enabled: false

Naming/PredicateMethod:
AllowBangMethods: true

Style/Documentation:
Enabled: false

Style/EmptyClassDefinition:
Enabled: false

Style/NumericLiterals:
Enabled: false

Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,5 @@ gem 'semantic_logger', '~> 4.16', require: 'semantic_logger/sync'
gem 'json', '~> 2.12'

gem 'discordrb', '~> 3.7'

gem 'toml-rb', '~> 4.1'
34 changes: 23 additions & 11 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ GEM
public_suffix (>= 2.0.2, < 7.0)
ast (2.4.3)
base64 (0.3.0)
bigdecimal (4.0.1)
citrus (3.0.2)
concurrent-ruby (1.3.5)
discordrb (3.7.2)
base64 (~> 0.2)
Expand All @@ -29,12 +31,17 @@ GEM
http-accept (1.7.0)
http-cookie (1.1.0)
domain_name (~> 0.5)
json (2.12.2)
json (2.18.1)
json-schema (6.1.0)
addressable (~> 2.8)
bigdecimal (>= 3.1, < 5)
jwt (2.10.1)
base64
language_server-protocol (3.17.0.5)
lint_roller (1.1.0)
logger (1.7.0)
mcp (0.8.0)
json-schema (>= 4.1)
mime-types (3.7.0)
logger
mime-types-data (~> 3.2025, >= 3.2025.0507)
Expand All @@ -50,43 +57,47 @@ GEM
opus-ruby (1.0.1)
ffi
parallel (1.27.0)
parser (3.3.8.0)
parser (3.3.10.2)
ast (~> 2.4.1)
racc
prism (1.4.0)
prism (1.9.0)
public_suffix (6.0.2)
racc (1.8.1)
rainbow (3.1.1)
regexp_parser (2.10.0)
regexp_parser (2.11.3)
rest-client (2.1.0)
http-accept (>= 1.7.0, < 2.0)
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
rubocop (1.76.0)
rubocop (1.85.1)
json (~> 2.3)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
mcp (~> 0.6)
parallel (~> 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.45.0, < 2.0)
rubocop-ast (>= 1.49.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.45.0)
rubocop-ast (1.49.0)
parser (>= 3.3.7.2)
prism (~> 1.4)
prism (~> 1.7)
ruby-progressbar (1.13.0)
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
semantic_logger (4.16.1)
concurrent-ruby (~> 1.0)
thor (1.3.2)
unicode-display_width (3.1.4)
unicode-emoji (~> 4.0, >= 4.0.4)
unicode-emoji (4.0.4)
toml-rb (4.1.0)
citrus (~> 3.0, > 3.0)
racc (~> 1.7)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.2.0)
uri (1.0.3)
websocket (1.2.11)
websocket-client-simple (0.9.0)
Expand All @@ -109,6 +120,7 @@ DEPENDENCIES
rubocop (~> 1.76)
semantic_logger (~> 4.16)
thor (~> 1.3)
toml-rb (~> 4.1)
zeitwerk (~> 2.7)

BUNDLED WITH
Expand Down
35 changes: 35 additions & 0 deletions lib/pyxis/checks/aggregated_check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# frozen_string_literal: true

module Pyxis
module Checks
class AggregatedCheck
include Check

attr_reader :check_context, :checks

def initialize(check_context, checks)
@check_context = check_context
@checks = checks
end

def perform_check!
checks.all?(&:pass?)
end

def status_message
message = []
message << if pass?
"#{icon} #{check_context} checks pass"
else
"#{icon} #{check_context} checks fail"
end
checks.each do |check|
message << ''
message << check.status_message
end

message.join("\n")
end
end
end
end
18 changes: 18 additions & 0 deletions lib/pyxis/checks/canary_release.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

module Pyxis
module Checks
class CanaryRelease < AggregatedCheck
def initialize(build_id_to_promote)
info = Pyxis::ManagedVersioning::ComponentInfo.new(build_id: build_id_to_promote)
super(
'Canary release',
[
TucanaVersionMatch.new(info),
OpenIssues.new('release blocking', ['blocks-releases'])
]
)
end
end
end
end
37 changes: 37 additions & 0 deletions lib/pyxis/checks/check.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# frozen_string_literal: true

module Pyxis
module Checks
module Check
def perform_check!
raise NotImplementedError
end

def status_message
raise NotImplementedError
end

def pass?
return @pass if defined?(@pass)

@pass = perform_check!
end

def icon
if pass?
pass_icon
else
fail_icon
end
end

def pass_icon
'✅' # :white_check_mark:
end

def fail_icon
'❌' # :x:
end
end
end
end
40 changes: 40 additions & 0 deletions lib/pyxis/checks/open_issues.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

module Pyxis
module Checks
class OpenIssues
include Check

attr_reader :check_context, :labels

def initialize(check_context, labels)
@check_context = check_context
@labels = labels
end

def perform_check!
issues.empty?
end

def status_message
return "#{icon} No open #{check_context} issues" if pass?

message = []
message << "#{icon} Open #{check_context} issues"
issues.each do |issue|
message << "- [#{issue.title}](#{issue.html_url})"
end

message.join("\n")
end

private

def issues
@issues ||= GithubClient.octokit.search_issues(
"org:#{GithubClient::ORGANIZATION_NAME} is:open is:issue #{labels.map { |l| "label:#{l}" }.join(' ')}"
).items
end
end
end
end
96 changes: 96 additions & 0 deletions lib/pyxis/checks/tucana_version_match.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# frozen_string_literal: true

module Pyxis
module Checks
class TucanaVersionMatch
include Check

attr_reader :component_info

def initialize(component_info)
@component_info = component_info
end

def perform_check!
[sagittarius_version, aquila_version, draco_version, taurus_version].uniq.size == 1
end

def status_message
return "#{icon} Components use the same tucana version" if pass?

message = []
message << "#{icon} Components use different tucana versions"
message << ''
message << "sagittarius: #{sagittarius_version}"
message << "aquila: #{aquila_version}"
message << "draco: #{draco_version}"
message << "taurus: #{taurus_version}"

message.join("\n")
end

private

def sagittarius_version
return @sagittarius_version if defined?(@sagittarius_version)

gemfile_content = Base64.decode64 GithubClient.octokit.contents(
Project::Sagittarius.github_path,
path: 'Gemfile.lock',
ref: executed_component_info[:sagittarius]
).content

@sagittarius_version = Bundler::LockfileParser.new(gemfile_content)
.specs
.find { |spec| spec.name == 'tucana' }
.version
.to_s
end

def aquila_version
@aquila_version ||= from_cargo_lockfile(
Base64.decode64(
GithubClient.octokit.contents(
Project::Aquila.github_path,
path: 'Cargo.lock',
ref: executed_component_info[:aquila]
).content
)
)
end

def draco_version
@draco_version ||= from_cargo_lockfile(
Base64.decode64(
GithubClient.octokit.contents(
Project::Draco.github_path,
path: 'Cargo.lock',
ref: executed_component_info[:draco]
).content
)
)
end

def taurus_version
@taurus_version ||= from_cargo_lockfile(
Base64.decode64(
GithubClient.octokit.contents(
Project::Taurus.github_path,
path: 'Cargo.lock',
ref: executed_component_info[:taurus]
).content
)
)
end

def from_cargo_lockfile(lockfile)
toml = TomlRB.parse(lockfile, symbolize_keys: true)
toml[:package].find { |package| package[:name] == 'tucana' }[:version]
end

def executed_component_info
@executed_component_info ||= component_info.execute
end
end
end
end
Loading