mirror of
https://github.com/czhu12/canine.git
synced 2025-12-30 15:49:54 -06:00
events
This commit is contained in:
@@ -2,18 +2,30 @@ class EnvironmentVariables::BulkUpdate
|
||||
extend LightService::Action
|
||||
|
||||
expects :project, :params
|
||||
expects :current_user, default: nil
|
||||
|
||||
executed do |context|
|
||||
project = context.project
|
||||
# Delete all environment variables and create new ones
|
||||
env_variable_data = context.params[:environment_variables]
|
||||
|
||||
project.environment_variables.destroy_all
|
||||
incoming_variable_names = env_variable_data.map { |ev| ev[:name] }
|
||||
current_variable_names = project.environment_variables.pluck(:name)
|
||||
|
||||
(context.params[:environment_variables] || []).each do |environment_variable_params|
|
||||
next if environment_variable_params[:name].blank?
|
||||
name = environment_variable_params[:name].strip.upcase
|
||||
value = environment_variable_params[:value].strip
|
||||
project.environment_variables.create!(name:, value:)
|
||||
new_names = incoming_variable_names - current_variable_names
|
||||
|
||||
if new_names.any?
|
||||
env_variable_data.filter { |ev| new_names.include?(ev[:name]) }.each do |ev|
|
||||
next if ev[:name].blank?
|
||||
project.environment_variables.create!(
|
||||
name: ev[:name].strip.upcase,
|
||||
value: ev[:value].strip,
|
||||
current_user: context.current_user
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
destroy_names = current_variable_names - incoming_variable_names
|
||||
|
||||
project.environment_variables.where(name: destroy_names).destroy_all if destroy_names.any?
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2,18 +2,20 @@ class Projects::DeployLatestCommit
|
||||
extend LightService::Action
|
||||
|
||||
expects :project
|
||||
expects :current_user, default: nil
|
||||
promises :project
|
||||
|
||||
executed do |context|
|
||||
# Fetch the latest commit from the default branch
|
||||
project = context.project
|
||||
current_user = context.current_user || project.account.owner
|
||||
client = Octokit::Client.new(access_token: project.account.github_access_token)
|
||||
commit = client.commits(project.repository_url).first
|
||||
|
||||
build = Build.create!(
|
||||
project: project,
|
||||
build = project.builds.create!(
|
||||
commit_sha: commit.sha,
|
||||
commit_message: commit.commit[:message]
|
||||
commit_message: commit.commit[:message],
|
||||
current_user: current_user
|
||||
)
|
||||
Projects::BuildJob.perform_later(build)
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ module InboundWebhooks
|
||||
record = InboundWebhook.create(body: payload)
|
||||
|
||||
# Queue webhook for processing
|
||||
InboundWebhooks::GithubJob.perform_later(record)
|
||||
InboundWebhooks::GithubJob.perform_later(record, current_user:)
|
||||
|
||||
# Tell service we received the webhook successfully
|
||||
head :ok
|
||||
|
||||
@@ -11,6 +11,7 @@ class Projects::DeploymentsController < Projects::BaseController
|
||||
def redeploy
|
||||
new_build = @build.dup.tap do |build|
|
||||
build.status = :in_progress
|
||||
build.current_user = current_user
|
||||
end
|
||||
if new_build.save
|
||||
Projects::BuildJob.perform_later(new_build)
|
||||
@@ -21,7 +22,7 @@ class Projects::DeploymentsController < Projects::BaseController
|
||||
end
|
||||
|
||||
def deploy
|
||||
result = Projects::DeployLatestCommit.execute(project: @project)
|
||||
result = Projects::DeployLatestCommit.execute(project: @project, current_user:)
|
||||
if result.success?
|
||||
redirect_to @project, notice: "Deploying project..."
|
||||
else
|
||||
|
||||
17
app/helpers/eventable.rb
Normal file
17
app/helpers/eventable.rb
Normal file
@@ -0,0 +1,17 @@
|
||||
module Eventable
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
attr_accessor :current_user
|
||||
has_many :events, as: :eventable, dependent: :destroy
|
||||
after_save :create_event
|
||||
end
|
||||
|
||||
def create_event
|
||||
events.create!(
|
||||
user: current_user,
|
||||
event_action: id_changed? ? :create : :update,
|
||||
project:
|
||||
) if current_user
|
||||
end
|
||||
end
|
||||
@@ -2,14 +2,14 @@ module InboundWebhooks
|
||||
class GithubJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
def perform(inbound_webhook)
|
||||
def perform(inbound_webhook, current_user: nil)
|
||||
inbound_webhook.processing!
|
||||
|
||||
# Process webhook
|
||||
# Determine the project
|
||||
# Trigger a docker build & docker deploy if auto deploy is on for the project
|
||||
body = JSON.parse(inbound_webhook.body)
|
||||
process_webhook(body)
|
||||
process_webhook(body, current_user:)
|
||||
|
||||
inbound_webhook.processed!
|
||||
|
||||
@@ -17,16 +17,16 @@ module InboundWebhooks
|
||||
# inbound_webhook.failed!
|
||||
end
|
||||
|
||||
def process_webhook(body)
|
||||
return if body['pusher'].nil?
|
||||
branch = body['ref'].gsub('refs/heads/', '')
|
||||
projects = Project.where(repository_url: body['repository']['full_name'], branch: branch, autodeploy: true)
|
||||
def process_webhook(body, current_user:)
|
||||
return if body["pusher"].nil?
|
||||
branch = body["ref"].gsub("refs/heads/", "")
|
||||
projects = Project.where(repository_url: body["repository"]["full_name"], branch: branch, autodeploy: true)
|
||||
projects.each do |project|
|
||||
# Trigger a docker build & docker deploy
|
||||
build = Build.create!(
|
||||
project_id: project.id,
|
||||
commit_sha: body['head_commit']['id'],
|
||||
commit_message: body['head_commit']['message']
|
||||
build = project.builds.create!(
|
||||
current_user:,
|
||||
commit_sha: body["head_commit"]["id"],
|
||||
commit_message: body["head_commit"]["message"]
|
||||
)
|
||||
Projects::BuildJob.perform_later(build)
|
||||
end
|
||||
|
||||
@@ -22,8 +22,11 @@
|
||||
#
|
||||
class Build < ApplicationRecord
|
||||
include Loggable
|
||||
include Eventable
|
||||
|
||||
belongs_to :project
|
||||
has_one :deployment, dependent: :destroy
|
||||
|
||||
enum status: {
|
||||
in_progress: 0,
|
||||
completed: 1,
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
# fk_rails_... (project_id => projects.id)
|
||||
#
|
||||
class EnvironmentVariable < ApplicationRecord
|
||||
include Eventable
|
||||
|
||||
belongs_to :project
|
||||
|
||||
validates :name, presence: true, uniqueness: { scope: :project_id }
|
||||
|
||||
28
app/models/event.rb
Normal file
28
app/models/event.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: events
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# event_action :integer not null
|
||||
# eventable_type :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# eventable_id :bigint not null
|
||||
# project_id :bigint not null
|
||||
# user_id :bigint not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_events_on_eventable (eventable_type,eventable_id)
|
||||
# index_events_on_project_id (project_id)
|
||||
# index_events_on_user_id (user_id)
|
||||
#
|
||||
class Event < ApplicationRecord
|
||||
belongs_to :eventable, polymorphic: true
|
||||
belongs_to :user
|
||||
belongs_to :project
|
||||
enum event_action: {
|
||||
create: 0,
|
||||
update: 1
|
||||
}, _prefix: true
|
||||
end
|
||||
@@ -34,9 +34,11 @@ class Project < ApplicationRecord
|
||||
has_many :builds, dependent: :destroy
|
||||
has_many :deployments, through: :builds
|
||||
has_many :domains, through: :services
|
||||
has_many :events
|
||||
validates :name, presence: true,
|
||||
format: { with: /\A[a-z0-9_-]+\z/, message: "must be lowercase, numbers, hyphens, and underscores only" }
|
||||
|
||||
|
||||
validates_uniqueness_of :name, scope: :cluster_id
|
||||
|
||||
enum :status, {
|
||||
|
||||
@@ -28,6 +28,9 @@
|
||||
<th>
|
||||
<span class="text-sm font-medium text-base-content/80">Deployed At</span>
|
||||
</th>
|
||||
<th>
|
||||
<span class="text-sm font-medium text-base-content/80">User</span>
|
||||
</th>
|
||||
<th>
|
||||
<span class="text-sm font-medium text-base-content/80"></span>
|
||||
</th>
|
||||
@@ -65,6 +68,13 @@
|
||||
<div class="text-sm capitalize"><%= distance_of_time_in_words(build.created_at, Time.current) %> ago</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<% if build.events.present? %>
|
||||
<div class="text-sm capitalize truncate w-[100px]">
|
||||
<%= build.events.last.user.email %>
|
||||
</div>
|
||||
<% end %>
|
||||
</td>
|
||||
<td>
|
||||
<div class="text-sm capitalize">
|
||||
<%= button_to redeploy_project_deployment_path(@project, build), method: :post, class: "btn btn-primary btn-sm min-w-max" do %>
|
||||
|
||||
@@ -36,7 +36,7 @@ Rails.application.routes.draw do
|
||||
end
|
||||
resources :metrics, only: [ :index ], module: :projects
|
||||
resources :project_add_ons, only: %i[create destroy], module: :projects
|
||||
resources :environment_variables, only: %i[index create], module: :projects
|
||||
resources :environment_variables, only: %i[index create destroy], module: :projects
|
||||
resources :deployments, only: %i[index show], module: :projects do
|
||||
collection do
|
||||
post :deploy
|
||||
|
||||
11
db/migrate/20241023225911_create_events.rb
Normal file
11
db/migrate/20241023225911_create_events.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
class CreateEvents < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
create_table :events do |t|
|
||||
t.references :user, null: false
|
||||
t.references :project, null: false
|
||||
t.references :eventable, polymorphic: true, null: false
|
||||
t.integer :event_action, null: false
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
||||
15
db/schema.rb
generated
15
db/schema.rb
generated
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.2].define(version: 2024_10_09_172011) do
|
||||
ActiveRecord::Schema[7.2].define(version: 2024_10_23_225911) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
@@ -134,6 +134,19 @@ ActiveRecord::Schema[7.2].define(version: 2024_10_09_172011) do
|
||||
t.index ["project_id"], name: "index_environment_variables_on_project_id"
|
||||
end
|
||||
|
||||
create_table "events", force: :cascade do |t|
|
||||
t.bigint "user_id", null: false
|
||||
t.bigint "project_id", null: false
|
||||
t.string "eventable_type", null: false
|
||||
t.bigint "eventable_id", null: false
|
||||
t.integer "event_action", null: false
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["eventable_type", "eventable_id"], name: "index_events_on_eventable"
|
||||
t.index ["project_id"], name: "index_events_on_project_id"
|
||||
t.index ["user_id"], name: "index_events_on_user_id"
|
||||
end
|
||||
|
||||
create_table "friendly_id_slugs", force: :cascade do |t|
|
||||
t.string "slug", null: false
|
||||
t.integer "sluggable_id", null: false
|
||||
|
||||
28
test/fixtures/account_users.yml
vendored
28
test/fixtures/account_users.yml
vendored
@@ -1,28 +0,0 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: account_users
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :bigint not null
|
||||
# user_id :bigint not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_account_users_on_account_id (account_id)
|
||||
# index_account_users_on_user_id (user_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id)
|
||||
# fk_rails_... (user_id => users.id)
|
||||
#
|
||||
|
||||
one:
|
||||
user: one
|
||||
account: one
|
||||
|
||||
two:
|
||||
user: two
|
||||
account: two
|
||||
24
test/fixtures/accounts.yml
vendored
24
test/fixtures/accounts.yml
vendored
@@ -1,24 +0,0 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: accounts
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# name :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# owner_id :bigint
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_accounts_on_owner_id (owner_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (owner_id => users.id)
|
||||
#
|
||||
|
||||
one:
|
||||
owner_id:
|
||||
|
||||
two:
|
||||
owner_id:
|
||||
@@ -1,25 +0,0 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: accounts
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# name :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# owner_id :bigint
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_accounts_on_owner_id (owner_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (owner_id => users.id)
|
||||
#
|
||||
require "test_helper"
|
||||
|
||||
class AccountTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
||||
@@ -1,27 +0,0 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: account_users
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# account_id :bigint not null
|
||||
# user_id :bigint not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_account_users_on_account_id (account_id)
|
||||
# index_account_users_on_user_id (user_id)
|
||||
#
|
||||
# Foreign Keys
|
||||
#
|
||||
# fk_rails_... (account_id => accounts.id)
|
||||
# fk_rails_... (user_id => users.id)
|
||||
#
|
||||
require "test_helper"
|
||||
|
||||
class AccountUserTest < ActiveSupport::TestCase
|
||||
# test "the truth" do
|
||||
# assert true
|
||||
# end
|
||||
end
|
||||
Reference in New Issue
Block a user