added build packs creation
@@ -9,9 +9,7 @@ module Projects
|
||||
:repository_url,
|
||||
:branch,
|
||||
:cluster_id,
|
||||
:docker_build_context_directory,
|
||||
:docker_command,
|
||||
:dockerfile_path,
|
||||
:container_registry_url,
|
||||
:predeploy_command,
|
||||
:project_fork_status,
|
||||
@@ -58,7 +56,10 @@ module Projects
|
||||
{
|
||||
provider: project.project_credential_provider.provider,
|
||||
driver: BuildConfiguration::DEFAULT_BUILDER,
|
||||
image_repository: project.repository_url
|
||||
build_type: :dockerfile,
|
||||
image_repository: project.repository_url,
|
||||
context_directory: ".",
|
||||
dockerfile_path: "./Dockerfile"
|
||||
}
|
||||
end
|
||||
|
||||
@@ -69,6 +70,7 @@ module Projects
|
||||
end
|
||||
|
||||
steps << Projects::ValidateNamespaceAvailability
|
||||
steps << Projects::InitializeBuildPacks
|
||||
steps << Projects::Save
|
||||
|
||||
# Only register webhook in cloud mode
|
||||
|
||||
34
app/actions/projects/initialize_build_packs.rb
Normal file
@@ -0,0 +1,34 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module Projects
|
||||
class InitializeBuildPacks
|
||||
extend LightService::Action
|
||||
|
||||
expects :build_configuration, :params
|
||||
promises :build_packs
|
||||
|
||||
def self.fetch_buildpack_details!(build_pack)
|
||||
result = Buildpacks::Details.execute(
|
||||
namespace: build_pack.namespace,
|
||||
name: build_pack.name
|
||||
)
|
||||
build_pack.details = result.result.to_h
|
||||
build_pack
|
||||
end
|
||||
|
||||
executed do |context|
|
||||
build_configuration = context.build_configuration
|
||||
next context unless build_configuration&.buildpacks?
|
||||
|
||||
build_packs_params = context.params.dig(:project, :build_configuration, :build_packs_attributes)
|
||||
next context unless build_packs_params
|
||||
|
||||
context.build_packs = build_packs_params.map.with_index do |pack_params, build_order|
|
||||
build_pack = build_configuration.build_packs.build(
|
||||
pack_params.permit(:namespace, :name, :version, :reference_type).merge(build_order:)
|
||||
)
|
||||
fetch_buildpack_details!(build_pack)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -12,7 +12,8 @@ module Projects
|
||||
build_configuration:,
|
||||
params:
|
||||
).reduce(
|
||||
Projects::UpdateSave
|
||||
Projects::UpdateSave,
|
||||
Projects::UpdateBuildPacks
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
55
app/actions/projects/update_build_packs.rb
Normal file
@@ -0,0 +1,55 @@
|
||||
class Projects::UpdateBuildPacks
|
||||
extend LightService::Action
|
||||
|
||||
expects :build_configuration, :params
|
||||
|
||||
executed do |context|
|
||||
build_configuration = context.build_configuration
|
||||
next context unless build_configuration&.buildpacks?
|
||||
|
||||
build_packs_params = context.params
|
||||
.dig(:project, :build_configuration, :build_packs_attributes) || []
|
||||
|
||||
# Create a hash of existing build packs keyed by build_pack.key
|
||||
existing_packs = {}
|
||||
build_configuration.build_packs.each do |pack|
|
||||
existing_packs[pack.key] = pack
|
||||
end
|
||||
|
||||
# Track which build packs are in the params and their order
|
||||
incoming_keys = []
|
||||
|
||||
ActiveRecord::Base.transaction do
|
||||
# Process each incoming build pack
|
||||
build_packs_params.each_with_index do |pack_params, build_order|
|
||||
permitted = pack_params.permit(:namespace, :name, :version, :reference_type)
|
||||
namespace = permitted[:namespace]
|
||||
name = permitted[:name]
|
||||
|
||||
key = "#{namespace}/#{name}"
|
||||
next if namespace.blank? || name.blank?
|
||||
|
||||
incoming_keys << key unless incoming_keys.include?(key)
|
||||
|
||||
if existing_packs[key]
|
||||
# Build pack already exists, update its order
|
||||
build_pack = existing_packs[key]
|
||||
build_pack.build_order = build_order
|
||||
else
|
||||
# Build pack doesn't exist, create it and fetch details
|
||||
build_pack = build_configuration.build_packs.build(permitted.merge(build_order:))
|
||||
Projects::InitializeBuildPacks.fetch_buildpack_details!(build_pack)
|
||||
end
|
||||
build_pack.save!
|
||||
end
|
||||
|
||||
# Delete build packs that are not in the incoming params (only persisted ones)
|
||||
packs_to_delete = build_configuration.build_packs.reject do |pack|
|
||||
incoming_keys.include?(pack.key)
|
||||
end
|
||||
packs_to_delete.each(&:destroy!)
|
||||
end
|
||||
|
||||
context
|
||||
end
|
||||
end
|
||||
@@ -4,7 +4,7 @@ class Avo::Resources::BuildPack < Avo::BaseResource
|
||||
# self.search = {
|
||||
# query: -> { query.ransack(id_eq: q, m: "or").result(distinct: false) }
|
||||
# }
|
||||
|
||||
|
||||
def fields
|
||||
field :id, as: :id
|
||||
field :build_configuration, as: :belongs_to
|
||||
|
||||
256
app/javascript/controllers/buildpack_fields_controller.js
Normal file
@@ -0,0 +1,256 @@
|
||||
import { Controller } from "@hotwired/stimulus"
|
||||
import Sortable from "sortablejs"
|
||||
|
||||
export default class extends Controller {
|
||||
static targets = ["list", "template", "modal", "baseBuilder", "availableBuildpacks", "selectedBuildpacks"]
|
||||
static values = {
|
||||
packs: Object
|
||||
}
|
||||
|
||||
connect() {
|
||||
this.selectedPacks = []
|
||||
this.initializeSortable()
|
||||
|
||||
// Listen for buildpack selection from search
|
||||
this.element.addEventListener("buildpack-search:buildpack-selected", this.handleSearchSelection.bind(this))
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.element.removeEventListener("buildpack-search:buildpack-selected", this.handleSearchSelection.bind(this))
|
||||
}
|
||||
|
||||
handleSearchSelection(event) {
|
||||
const { namespace, name, version, description } = event.detail
|
||||
|
||||
// Create a pack object with buildpack.webp as the default image
|
||||
const pack = {
|
||||
key: `${namespace}/${name}`,
|
||||
namespace: namespace,
|
||||
name: name,
|
||||
version: version || '',
|
||||
image: '/images/languages/buildpack.webp',
|
||||
description: description || ''
|
||||
}
|
||||
|
||||
// Check if already selected
|
||||
if (!this.selectedPacks.some(p => p.key === pack.key)) {
|
||||
this.selectedPacks.push(pack)
|
||||
this.displayAvailableBuildpacks()
|
||||
this.renderSelectedBuildpacks()
|
||||
}
|
||||
}
|
||||
|
||||
initializeSortable() {
|
||||
if (this.hasListTarget) {
|
||||
this.sortable = Sortable.create(this.listTarget, {
|
||||
animation: 150,
|
||||
handle: ".drag-handle",
|
||||
ghostClass: "opacity-50"
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
initializeModalSortable() {
|
||||
if (this.hasSelectedBuildpacksTarget && !this.modalSortable) {
|
||||
this.modalSortable = Sortable.create(this.selectedBuildpacksTarget, {
|
||||
animation: 150,
|
||||
ghostClass: "opacity-50",
|
||||
onEnd: () => {
|
||||
this.updateSelectedPacksOrder()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
updateSelectedPacksOrder() {
|
||||
// Get the current DOM order and update selectedPacks array
|
||||
const elements = this.selectedBuildpacksTarget.querySelectorAll('[data-key]')
|
||||
this.selectedPacks = Array.from(elements).map(el => {
|
||||
const key = el.dataset.key
|
||||
return { key, ...this.packsValue[key] }
|
||||
})
|
||||
}
|
||||
|
||||
openModal() {
|
||||
// Repopulate selectedPacks from existing buildpacks in the form
|
||||
this.selectedPacks = this.getExistingBuildpacks()
|
||||
this.displayAvailableBuildpacks()
|
||||
this.renderSelectedBuildpacks()
|
||||
this.modalTarget.showModal()
|
||||
// Initialize sortable after modal is shown
|
||||
setTimeout(() => this.initializeModalSortable(), 100)
|
||||
}
|
||||
|
||||
closeModal() {
|
||||
this.modalTarget.close()
|
||||
}
|
||||
|
||||
getExistingBuildpacks() {
|
||||
const existingPacks = []
|
||||
const cards = this.listTarget.querySelectorAll('.card')
|
||||
|
||||
cards.forEach(card => {
|
||||
const namespaceInput = card.querySelector('input[name*="[namespace]"]')
|
||||
const nameInput = card.querySelector('input[name*="[name]"]')
|
||||
|
||||
if (namespaceInput && nameInput) {
|
||||
const key = `${namespaceInput.value}/${nameInput.value}`
|
||||
const pack = this.packsValue[key]
|
||||
if (pack) {
|
||||
existingPacks.push({ key, ...pack })
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return existingPacks
|
||||
}
|
||||
|
||||
displayAvailableBuildpacks() {
|
||||
const builder = this.baseBuilderTarget.value
|
||||
const namespace = this.detectNamespace(builder)
|
||||
|
||||
if (!namespace) {
|
||||
this.availableBuildpacksTarget.innerHTML = '<div class="text-sm text-gray-500 p-4 text-center">Please select a base builder first</div>'
|
||||
return
|
||||
}
|
||||
|
||||
const availablePacks = Object.entries(this.packsValue)
|
||||
.filter(([key, pack]) => pack.namespace === namespace)
|
||||
.map(([key, pack]) => ({ key, ...pack }))
|
||||
|
||||
if (availablePacks.length === 0) {
|
||||
this.availableBuildpacksTarget.innerHTML = '<div class="text-sm text-gray-500 p-4 text-center">No buildpacks available for this builder</div>'
|
||||
return
|
||||
}
|
||||
|
||||
this.renderAvailableBuildpacks(availablePacks)
|
||||
}
|
||||
|
||||
renderAvailableBuildpacks(packs) {
|
||||
const filteredPacks = packs.filter(pack =>
|
||||
!this.selectedPacks.some(selected => selected.key === pack.key)
|
||||
)
|
||||
|
||||
if (filteredPacks.length === 0) {
|
||||
this.availableBuildpacksTarget.innerHTML = '<div class="text-sm text-gray-500 p-4 text-center">All buildpacks selected</div>'
|
||||
return
|
||||
}
|
||||
|
||||
const html = filteredPacks.map(pack => `
|
||||
<div class="p-3 hover:bg-base-200 cursor-pointer border-b border-base-300 flex items-center gap-3"
|
||||
data-action="click->buildpack-fields#selectBuildpack"
|
||||
data-key="${pack.key}">
|
||||
<img src="${pack.image}" alt="${pack.key}" class="w-10 h-10 object-contain" />
|
||||
<div class="flex-1">
|
||||
<div class="font-medium">${pack.namespace}/${pack.name}</div>
|
||||
<div class="text-sm text-gray-600">${pack.description}</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('')
|
||||
|
||||
this.availableBuildpacksTarget.innerHTML = html
|
||||
}
|
||||
|
||||
renderSelectedBuildpacks() {
|
||||
if (this.selectedPacks.length === 0) {
|
||||
this.selectedBuildpacksTarget.innerHTML = '<div class="text-sm text-gray-500 p-4 text-center">No buildpacks selected</div>'
|
||||
if (this.modalSortable) {
|
||||
this.modalSortable.destroy()
|
||||
this.modalSortable = null
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
const html = this.selectedPacks.map((pack, index) => `
|
||||
<div class="p-3 hover:bg-base-200 cursor-move border-b border-base-300 flex items-center gap-3"
|
||||
data-key="${pack.key}"
|
||||
data-index="${index}">
|
||||
<img src="${pack.image}" alt="${pack.key}" class="w-10 h-10 object-contain" />
|
||||
<div class="flex-1">
|
||||
<div class="font-medium">${pack.namespace}/${pack.name}</div>
|
||||
<div class="text-sm text-gray-600">${pack.description}</div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-xs btn-circle btn-ghost" data-action="click->buildpack-fields#deselectBuildpack" data-index="${index}">
|
||||
<iconify-icon icon="mdi:close" width="16" height="16"></iconify-icon>
|
||||
</button>
|
||||
</div>
|
||||
`).join('')
|
||||
|
||||
this.selectedBuildpacksTarget.innerHTML = html
|
||||
|
||||
// Reinitialize sortable after rendering
|
||||
if (this.modalSortable) {
|
||||
this.modalSortable.destroy()
|
||||
this.modalSortable = null
|
||||
}
|
||||
this.initializeModalSortable()
|
||||
}
|
||||
|
||||
detectNamespace(builder) {
|
||||
if (!builder) return null
|
||||
|
||||
if (builder.includes("paketo")) {
|
||||
return "paketo-buildpacks"
|
||||
} else if (builder.includes("heroku")) {
|
||||
return "heroku"
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
selectBuildpack(event) {
|
||||
const key = event.currentTarget.dataset.key
|
||||
const pack = { key, ...this.packsValue[key] }
|
||||
|
||||
this.selectedPacks.push(pack)
|
||||
this.displayAvailableBuildpacks()
|
||||
this.renderSelectedBuildpacks()
|
||||
}
|
||||
|
||||
deselectBuildpack(event) {
|
||||
event.stopPropagation()
|
||||
const index = parseInt(event.currentTarget.dataset.index)
|
||||
this.selectedPacks.splice(index, 1)
|
||||
this.displayAvailableBuildpacks()
|
||||
this.renderSelectedBuildpacks()
|
||||
}
|
||||
|
||||
addSelectedBuildpacks() {
|
||||
// Clear existing buildpacks from the list
|
||||
this.listTarget.innerHTML = ''
|
||||
|
||||
this.selectedPacks.forEach((pack, index) => {
|
||||
const template = this.templateTarget.content || this.templateTarget
|
||||
const clone = template.cloneNode(true)
|
||||
|
||||
const img = clone.querySelector('[data-template-image]')
|
||||
img.src = pack.image
|
||||
img.alt = pack.key
|
||||
|
||||
const title = clone.querySelector('[data-template-title]')
|
||||
title.textContent = `${pack.namespace}/${pack.name}`
|
||||
|
||||
const description = clone.querySelector('[data-template-description]')
|
||||
description.textContent = pack.description
|
||||
|
||||
const namespaceInput = clone.querySelector('[data-template-namespace]')
|
||||
namespaceInput.value = pack.namespace
|
||||
|
||||
const nameInput = clone.querySelector('[data-template-name]')
|
||||
nameInput.value = pack.name
|
||||
|
||||
const referenceTypeInput = clone.querySelector('[data-template-reference-type]')
|
||||
referenceTypeInput.value = pack.reference_type
|
||||
|
||||
const container = document.createElement('div')
|
||||
container.appendChild(clone)
|
||||
|
||||
this.listTarget.insertAdjacentHTML("beforeend", container.innerHTML)
|
||||
})
|
||||
|
||||
this.closeModal()
|
||||
}
|
||||
|
||||
remove(event) {
|
||||
event.target.closest(".card").remove()
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,14 @@ export default class extends AsyncSearchDropdownController {
|
||||
}
|
||||
|
||||
onItemSelect(buildpack, itemElement) {
|
||||
console.log('Selected buildpack:', buildpack)
|
||||
const latest = buildpack.latest
|
||||
this.dispatch("buildpack-selected", {
|
||||
detail: {
|
||||
namespace: latest.namespace,
|
||||
name: latest.name,
|
||||
version: latest.version,
|
||||
description: latest.description
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,9 +109,16 @@ export default class extends Controller {
|
||||
|
||||
selectItem(item, itemElement) {
|
||||
this.onItemSelect(item, itemElement)
|
||||
this.clearInput()
|
||||
this.hideDropdown()
|
||||
}
|
||||
|
||||
clearInput() {
|
||||
if (this.input) {
|
||||
this.input.value = ''
|
||||
}
|
||||
}
|
||||
|
||||
showDropdown() {
|
||||
this.dropdown.classList.remove('hidden')
|
||||
}
|
||||
@@ -123,9 +130,9 @@ export default class extends Controller {
|
||||
|
||||
showLoading() {
|
||||
this.dropdown.innerHTML = `
|
||||
<li class="p-4 text-center">
|
||||
<li class="p-4 text-center flex items-center justify-center gap-2">
|
||||
<span class="loading loading-spinner loading-sm"></span>
|
||||
<span class="ml-2">Searching...</span>
|
||||
<span>Searching...</span>
|
||||
</li>
|
||||
`
|
||||
this.showDropdown()
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
#
|
||||
# Table name: build_configurations
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# build_type :integer default(0), not null
|
||||
# driver :integer not null
|
||||
# image_repository :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# build_cloud_id :bigint
|
||||
# project_id :bigint not null
|
||||
# provider_id :bigint not null
|
||||
# id :bigint not null, primary key
|
||||
# build_type :integer default("dockerfile"), not null
|
||||
# buildpack_base_builder :string
|
||||
# context_directory :string default("."), not null
|
||||
# dockerfile_path :string default("./Dockerfile"), not null
|
||||
# driver :integer not null
|
||||
# image_repository :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# build_cloud_id :bigint
|
||||
# project_id :bigint not null
|
||||
# provider_id :bigint not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
@@ -36,7 +39,7 @@ class BuildConfiguration < ApplicationRecord
|
||||
belongs_to :project
|
||||
belongs_to :build_cloud, optional: true
|
||||
belongs_to :provider
|
||||
has_many :build_packs, dependent: :destroy
|
||||
has_many :build_packs, -> { order(:build_order) }, dependent: :destroy
|
||||
|
||||
validates_presence_of :project, :provider, :driver
|
||||
validates_presence_of :image_repository
|
||||
@@ -46,9 +49,19 @@ class BuildConfiguration < ApplicationRecord
|
||||
}
|
||||
|
||||
def self.permit_params(params)
|
||||
params.permit(:image_repository, :driver, :build_cloud_id, :provider_id)
|
||||
params.permit(:image_repository, :driver, :build_cloud_id, :provider_id, :context_directory, :dockerfile_path, :build_type, :buildpack_base_builder)
|
||||
end
|
||||
|
||||
def self.available_buildpacks
|
||||
packs_file = Rails.root.join("resources", "build_packs", "packs.yaml")
|
||||
YAML.load_file(packs_file)
|
||||
end
|
||||
|
||||
enum :build_type, {
|
||||
dockerfile: 0,
|
||||
buildpacks: 1
|
||||
}
|
||||
|
||||
enum :driver, {
|
||||
cloud: 0,
|
||||
docker: 1,
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
# Table name: build_packs
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# build_order :integer not null
|
||||
# details :jsonb
|
||||
# name :string
|
||||
# namespace :string
|
||||
# reference_type :string not null
|
||||
# reference_type :integer not null
|
||||
# uri :text
|
||||
# version :string
|
||||
# created_at :datetime not null
|
||||
@@ -27,11 +28,12 @@ class BuildPack < ApplicationRecord
|
||||
VERIFIED_NAMESPACES = %w[io.buildpacks paketo-buildpacks heroku tanzu-buildpacks].freeze
|
||||
|
||||
belongs_to :build_configuration
|
||||
validates_presence_of :build_order
|
||||
|
||||
enum :reference_type, {
|
||||
registry: 0,
|
||||
git: 1,
|
||||
url: 2,
|
||||
url: 2
|
||||
}
|
||||
|
||||
validates :reference_type, presence: true
|
||||
@@ -69,4 +71,12 @@ class BuildPack < ApplicationRecord
|
||||
uri
|
||||
end
|
||||
end
|
||||
|
||||
def key
|
||||
"#{namespace}/#{name}"
|
||||
end
|
||||
|
||||
def static_info
|
||||
BuildConfiguration.available_buildpacks[key] || {}
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,7 +42,7 @@ module Builders
|
||||
command += [ "--push" ] # Push directly to registry
|
||||
command += [ "--progress", "plain" ]
|
||||
command += [ "-t", project.container_image_reference ]
|
||||
command += [ "-f", File.join(repository_path, project.dockerfile_path) ]
|
||||
command += [ "-f", File.join(repository_path, project.build_configuration.dockerfile_path) ]
|
||||
|
||||
# Add build arguments
|
||||
project.environment_variables.each do |envar|
|
||||
@@ -56,7 +56,7 @@ module Builders
|
||||
command += [ "--push" ]
|
||||
|
||||
# Add build context
|
||||
command << File.join(repository_path, project.docker_build_context_directory)
|
||||
command << File.join(repository_path, project.build_configuration.context_directory)
|
||||
|
||||
command
|
||||
end
|
||||
|
||||
@@ -32,7 +32,7 @@ module Builders
|
||||
"--progress=plain",
|
||||
"--platform", "linux/amd64",
|
||||
"-t", project.container_image_reference,
|
||||
"-f", File.join(repository_path, project.dockerfile_path)
|
||||
"-f", File.join(repository_path, project.build_configuration.dockerfile_path)
|
||||
]
|
||||
|
||||
# Add environment variables to the build command
|
||||
@@ -43,7 +43,7 @@ module Builders
|
||||
docker_build_command.push("--push")
|
||||
|
||||
# Add the build context directory at the end
|
||||
docker_build_command.push(File.join(repository_path, project.docker_build_context_directory))
|
||||
docker_build_command.push(File.join(repository_path, project.build_configuration.context_directory))
|
||||
Rails.logger.info("Docker build command: `#{docker_build_command.join(" ")}`")
|
||||
docker_build_command
|
||||
end
|
||||
|
||||
@@ -1,19 +1,7 @@
|
||||
<div class="form-control">
|
||||
<label class="label">
|
||||
<span class="label-text">Search Buildpacks</span>
|
||||
</label>
|
||||
<div class="relative" data-controller="buildpack-search">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search for buildpacks (e.g., ruby, node, python)..."
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
</div>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">Search Cloud Native Buildpacks to add to your project</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div id="selected-buildpacks" class="mt-4 space-y-2">
|
||||
<!-- Selected buildpacks will appear here -->
|
||||
<div class="relative" data-controller="buildpack-search">
|
||||
<input
|
||||
type="text"
|
||||
placeholder="Search for buildpacks (e.g., ruby, node, python)..."
|
||||
class="input input-bordered w-full"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
<div data-controller="buildpack-fields" data-buildpack-fields-packs-value="<%= BuildConfiguration.available_buildpacks.to_json %>">
|
||||
<div class="form-control mt-1 mb-2 w-full max-w-sm">
|
||||
<label class="label">
|
||||
<span class="label-text">Base Builder</span>
|
||||
</label>
|
||||
<%= bc_form.select(
|
||||
:buildpack_base_builder,
|
||||
options_for_select(
|
||||
[
|
||||
["heroku/builder-classic:22", "heroku/builder-classic:22"],
|
||||
["heroku/builder:22", "heroku/builder:22"],
|
||||
["heroku/builder:24", "heroku/builder:24"],
|
||||
["heroku/buildpacks:18", "heroku/buildpacks:18"],
|
||||
["heroku/buildpacks:20", "heroku/buildpacks:20"],
|
||||
["paketobuildpacks/builder-jammy-full:latest", "paketobuildpacks/builder-jammy-full:latest"],
|
||||
["paketobuildpacks/builder:full", "paketobuildpacks/builder:full"]
|
||||
],
|
||||
selected: build_configuration.buildpack_base_builder || "heroku/buildpacks:20"
|
||||
),
|
||||
{ include_blank: "Select a base builder..." },
|
||||
{ class: "select select-bordered w-full", data: { buildpack_fields_target: "baseBuilder" } }
|
||||
) %>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">Select the base builder image for Cloud Native Buildpacks</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mt-1 mb-2 w-full max-w-sm">
|
||||
<label class="label">
|
||||
<span class="label-text">Buildpacks</span>
|
||||
</label>
|
||||
<div data-buildpack-fields-target="list" class="space-y-2">
|
||||
<% build_configuration.build_packs.each do |build_pack| %>
|
||||
<%= render "projects/build_configurations/buildpack_item", build_pack: build_pack %>
|
||||
<% end %>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline btn-primary mt-2" data-action="click->buildpack-fields#openModal">
|
||||
<iconify-icon icon="mdi:plus" width="20" height="20"></iconify-icon>
|
||||
Add Buildpack
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<template data-buildpack-fields-target="template">
|
||||
<%= render "projects/build_configurations/buildpack_item" %>
|
||||
</template>
|
||||
|
||||
<dialog data-buildpack-fields-target="modal" class="modal">
|
||||
<div class="modal-box w-11/12 max-w-5xl">
|
||||
<h3 class="font-bold text-lg">Add Buildpacks</h3>
|
||||
<p class="py-2 text-sm text-gray-600">Select buildpacks to add to your build configuration.</p>
|
||||
|
||||
<div class="space-y-4 mt-4">
|
||||
<div>
|
||||
<h4 class="font-semibold mb-2">Selected Buildpacks</h4>
|
||||
<div data-buildpack-fields-target="selectedBuildpacks" class="border border-base-300 rounded-lg max-h-48 overflow-y-auto">
|
||||
<div class="text-sm text-gray-500 p-4 text-center">No buildpacks selected</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 class="font-semibold mb-2">Official Buildpacks</h4>
|
||||
<div data-buildpack-fields-target="availableBuildpacks" class="border border-base-300 rounded-lg max-h-64 overflow-y-auto">
|
||||
<!-- Official buildpacks will be rendered here -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h4 class="font-semibold mb-2">Search Registry</h4>
|
||||
<%= render "build_packs/search" %>
|
||||
<div data-buildpack-fields-target="searchResults" class="border border-base-300 rounded-lg max-h-64 overflow-y-auto mt-2">
|
||||
<!-- Search results will be rendered here -->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-action">
|
||||
<button type="button" class="btn btn-ghost" data-action="click->buildpack-fields#closeModal">Cancel</button>
|
||||
<button type="button" class="btn btn-primary" data-action="click->buildpack-fields#addSelectedBuildpacks">Add Selected</button>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
</div>
|
||||
@@ -0,0 +1,19 @@
|
||||
<% build_pack = local_assigns[:build_pack] || BuildPack.new %>
|
||||
<div class="card bg-base-200 p-4">
|
||||
<div class="flex gap-3 items-center">
|
||||
<div class="drag-handle cursor-move flex items-center">
|
||||
<iconify-icon icon="mdi:drag-vertical" width="20" height="20" class="text-gray-500"></iconify-icon>
|
||||
</div>
|
||||
<img data-template-image class="w-10 h-10 object-contain" src="<%= build_pack.static_info['image'] || '/images/languages/buildpack.webp' %>" />
|
||||
<div class="flex-1">
|
||||
<div class="font-medium" data-template-title><%= "#{build_pack.namespace}/#{build_pack.name}" %></div>
|
||||
<div class="text-sm text-gray-600" data-template-description><%= build_pack.details.dig('latest', 'description') %></div>
|
||||
</div>
|
||||
<button type="button" class="btn btn-sm btn-ghost" data-action="click->buildpack-fields#remove">
|
||||
<iconify-icon icon="mdi:close" width="20" height="20"></iconify-icon>
|
||||
</button>
|
||||
</div>
|
||||
<input type="hidden" data-template-namespace name="project[build_configuration][build_packs_attributes][][namespace]" value="<%= build_pack.namespace %>" />
|
||||
<input type="hidden" data-template-name name="project[build_configuration][build_packs_attributes][][name]" value="<%= build_pack.name %>" />
|
||||
<input type="hidden" data-template-reference-type name="project[build_configuration][build_packs_attributes][][reference_type]" value="<%= build_pack.reference_type %>" />
|
||||
</div>
|
||||
@@ -0,0 +1,25 @@
|
||||
<div>
|
||||
<div class="form-control mt-1 mb-2 w-full max-w-sm">
|
||||
<label class="label">
|
||||
<span class="label-text">Dockerfile path</span>
|
||||
</label>
|
||||
<%= bc_form.text_field(
|
||||
:dockerfile_path,
|
||||
class: "input input-bordered w-full focus:outline-offset-0",
|
||||
value: build_configuration.dockerfile_path
|
||||
) %>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">* Required</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-control mt-1 mb-2 w-full max-w-sm">
|
||||
<label class="label">
|
||||
<span class="label-text">Build context directory</span>
|
||||
</label>
|
||||
<%= bc_form.text_field(
|
||||
:context_directory,
|
||||
class: "input input-bordered w-full focus:outline-offset-0",
|
||||
value: build_configuration.context_directory
|
||||
) %>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,6 +1,6 @@
|
||||
<div>
|
||||
<div>
|
||||
<% build_configuration = project.build_configuration || BuildConfiguration.new(driver: 'docker') %>
|
||||
<% build_configuration = project.build_configuration || BuildConfiguration.new %>
|
||||
<%= form.fields_for :build_configuration, build_configuration do |bc_form| %>
|
||||
<div class="form-control mt-4">
|
||||
<%= render "shared/partials/radio_selector", selected: build_configuration.driver, options: [
|
||||
@@ -64,6 +64,31 @@
|
||||
pattern: "[a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]/[a-zA-Z0-9._-]+",
|
||||
title: "Must be in the format 'namespace/repo'"
|
||||
) %>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">If this is left blank, a container registry will be automatically created for you.</span>
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-control mt-4">
|
||||
<%= render "shared/partials/radio_selector", selected: build_configuration.build_type || "dockerfile", options: [
|
||||
{
|
||||
icon: "skill-icons:docker",
|
||||
name: "project[build_configuration][build_type]",
|
||||
label: "Dockerfile",
|
||||
value: "dockerfile",
|
||||
description: "Build images using a Dockerfile. Traditional Docker build approach with full control over the build process.",
|
||||
partial: "projects/build_configurations/dockerfile_fields",
|
||||
locals: { bc_form:, build_configuration: }
|
||||
},
|
||||
{
|
||||
icon: "devicon:heroku",
|
||||
name: "project[build_configuration][build_type]",
|
||||
label: "Buildpacks",
|
||||
value: "buildpacks",
|
||||
description: "Use Cloud Native Buildpacks to automatically detect and build your application. No Dockerfile needed.",
|
||||
partial: "projects/build_configurations/buildpack_fields",
|
||||
locals: { bc_form:, build_configuration: }
|
||||
}
|
||||
] %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
@@ -80,16 +80,6 @@
|
||||
<span class="label-text-alt">* Required</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-control mt-1 mb-2 w-full max-w-sm">
|
||||
<label class="label">
|
||||
<span class="label-text">Container registry URL</span>
|
||||
</label>
|
||||
<%= form.text_field :container_registry_url, class: "input input-bordered w-full focus:outline-offset-0", value: "" %>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">If this is left blank, <span data-new-project-target="gitProviderLabel">Github</span> Container Registry will be used</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
@@ -100,23 +90,6 @@
|
||||
<%= form.check_box :autodeploy, class: "checkbox" %>
|
||||
<% end %>
|
||||
|
||||
<%= render(FormFieldComponent.new(
|
||||
label: "Dockerfile path",
|
||||
description: "The path to the Dockerfile in your repository."
|
||||
)) do %>
|
||||
<%= form.text_field :dockerfile_path, class: "input input-bordered w-full focus:outline-offset-0" %>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">* Required</span>
|
||||
</label>
|
||||
<% end %>
|
||||
|
||||
<%= render(FormFieldComponent.new(
|
||||
label: "Docker build context directory",
|
||||
description: "The directory to use as the build context for the Docker build."
|
||||
)) do %>
|
||||
<%= form.text_field :docker_build_context_directory, class: "input input-bordered w-full focus:outline-offset-0" %>
|
||||
<% end %>
|
||||
|
||||
<%= render(FormFieldComponent.new(
|
||||
label: "Docker command",
|
||||
description: "The command to run to start the container."
|
||||
|
||||
@@ -23,17 +23,6 @@
|
||||
<%= form.check_box :autodeploy, class: "checkbox" %>
|
||||
<% end %>
|
||||
|
||||
<%= render(FormFieldComponent.new(label: "Dockerfile path")) do %>
|
||||
<%= form.text_field :dockerfile_path, class: "input input-bordered w-full focus:outline-offset-0" %>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">* Required</span>
|
||||
</label>
|
||||
<% end %>
|
||||
|
||||
<%= render(FormFieldComponent.new(label: "Docker build context directory")) do %>
|
||||
<%= form.text_field :docker_build_context_directory, class: "input input-bordered w-full focus:outline-offset-0" %>
|
||||
<% end %>
|
||||
|
||||
<%= render(FormFieldComponent.new(label: "Docker command")) do %>
|
||||
<%= form.text_field :docker_command, class: "input input-bordered w-full focus:outline-offset-0" %>
|
||||
<label class="label">
|
||||
@@ -45,17 +34,6 @@
|
||||
<%= form.text_field :predeploy_command, class: "input input-bordered w-full focus:outline-offset-0" %>
|
||||
<% end %>
|
||||
|
||||
<%= render(FormFieldComponent.new(label: "Container registry URL")) do %>
|
||||
<%= form.text_field(
|
||||
:container_registry_url,
|
||||
class: "input input-bordered w-full focus:outline-offset-0",
|
||||
value: form.object.attributes["container_registry_url"],
|
||||
) %>
|
||||
<label class="label">
|
||||
<span class="label-text-alt">If this is left blank, <%= project.github? ? "Github" : "Gitlab" %> Container Registry will be used</span>
|
||||
</label>
|
||||
<% end %>
|
||||
|
||||
<% if Flipper.enabled?(:build_configuration, current_account) %>
|
||||
<%= render(FormFieldComponent.new(label: "Build configuration")) do %>
|
||||
<%= render "projects/build_configurations/form", form: form, project: project %>
|
||||
|
||||
@@ -2,10 +2,11 @@ class CreateBuildPacks < ActiveRecord::Migration[7.2]
|
||||
def change
|
||||
create_table :build_packs do |t|
|
||||
t.references :build_configuration, null: false, foreign_key: true
|
||||
t.string :reference_type, null: false # registry, docker, git, url, path
|
||||
t.integer :reference_type, null: false # registry, docker, git, url, path
|
||||
t.string :namespace # for registry buildpacks
|
||||
t.string :name # for registry buildpacks
|
||||
t.string :version
|
||||
t.integer :build_order, null: false
|
||||
t.text :uri # for git, url, path, or docker references
|
||||
t.jsonb :details, default: {}
|
||||
|
||||
@@ -14,5 +15,6 @@ class CreateBuildPacks < ActiveRecord::Migration[7.2]
|
||||
|
||||
add_index :build_packs, [ :build_configuration_id, :reference_type, :namespace, :name ], name: 'index_build_packs_on_config_type_namespace_name'
|
||||
add_index :build_packs, [ :build_configuration_id, :uri ], name: 'index_build_packs_on_config_uri'
|
||||
add_column :build_configurations, :buildpack_base_builder, :string
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
class MoveDockerFieldsFromProjectToBuildConfiguration < ActiveRecord::Migration[7.2]
|
||||
def up
|
||||
# Add build fields to build_configurations (excluding docker_command which is used at runtime)
|
||||
add_column :build_configurations, :context_directory, :string, default: ".", null: false
|
||||
add_column :build_configurations, :dockerfile_path, :string, default: "./Dockerfile", null: false
|
||||
|
||||
# Backfill data from projects to build_configurations
|
||||
reversible do |dir|
|
||||
dir.up do
|
||||
Project.reset_column_information
|
||||
BuildConfiguration.reset_column_information
|
||||
|
||||
Project.find_each do |project|
|
||||
# Create build_configuration if it doesn't exist
|
||||
if project.build_configuration.nil?
|
||||
# Skip projects that don't have the required associations
|
||||
next unless project.project_credential_provider.present?
|
||||
|
||||
BuildConfiguration.create!(
|
||||
project: project,
|
||||
provider: project.project_credential_provider.provider,
|
||||
driver: BuildConfiguration::DEFAULT_BUILDER,
|
||||
image_repository: project.repository_url,
|
||||
context_directory: project.docker_build_context_directory,
|
||||
dockerfile_path: project.dockerfile_path
|
||||
)
|
||||
else
|
||||
# Update existing build_configuration
|
||||
project.build_configuration.update!(
|
||||
context_directory: project.docker_build_context_directory,
|
||||
dockerfile_path: project.dockerfile_path
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# Remove build fields from build_configurations
|
||||
remove_column :build_configurations, :context_directory
|
||||
remove_column :build_configurations, :dockerfile_path
|
||||
end
|
||||
end
|
||||
22
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: 2025_10_27_014101) do
|
||||
ActiveRecord::Schema[7.2].define(version: 2025_11_03_000229) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "plpgsql"
|
||||
|
||||
@@ -112,11 +112,30 @@ ActiveRecord::Schema[7.2].define(version: 2025_10_27_014101) do
|
||||
t.bigint "provider_id", null: false
|
||||
t.integer "build_type", default: 0, null: false
|
||||
t.string "image_repository", null: false
|
||||
t.string "buildpack_base_builder"
|
||||
t.string "context_directory", default: ".", null: false
|
||||
t.string "dockerfile_path", default: "./Dockerfile", null: false
|
||||
t.index ["build_cloud_id"], name: "index_build_configurations_on_build_cloud_id"
|
||||
t.index ["project_id"], name: "index_build_configurations_on_project_id"
|
||||
t.index ["provider_id"], name: "index_build_configurations_on_provider_id"
|
||||
end
|
||||
|
||||
create_table "build_packs", force: :cascade do |t|
|
||||
t.bigint "build_configuration_id", null: false
|
||||
t.integer "reference_type", null: false
|
||||
t.string "namespace"
|
||||
t.string "name"
|
||||
t.string "version"
|
||||
t.integer "build_order", null: false
|
||||
t.text "uri"
|
||||
t.jsonb "details", default: {}
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["build_configuration_id", "reference_type", "namespace", "name"], name: "index_build_packs_on_config_type_namespace_name"
|
||||
t.index ["build_configuration_id", "uri"], name: "index_build_packs_on_config_uri"
|
||||
t.index ["build_configuration_id"], name: "index_build_packs_on_build_configuration_id"
|
||||
end
|
||||
|
||||
create_table "builds", force: :cascade do |t|
|
||||
t.bigint "project_id", null: false
|
||||
t.string "repository_url"
|
||||
@@ -508,6 +527,7 @@ ActiveRecord::Schema[7.2].define(version: 2025_10_27_014101) do
|
||||
add_foreign_key "build_configurations", "build_clouds"
|
||||
add_foreign_key "build_configurations", "projects"
|
||||
add_foreign_key "build_configurations", "providers"
|
||||
add_foreign_key "build_packs", "build_configurations"
|
||||
add_foreign_key "builds", "projects"
|
||||
add_foreign_key "clusters", "accounts"
|
||||
add_foreign_key "cron_schedules", "services"
|
||||
|
||||
@@ -15,13 +15,14 @@
|
||||
"@codemirror/view": "^6.38.1",
|
||||
"@gorails/ninja-keys": "^1.2.1",
|
||||
"@hotwired/stimulus": "^3.2.2",
|
||||
"@hotwired/turbo-rails": "^8.0.10",
|
||||
"@hotwired/turbo-rails": "^8.0.20",
|
||||
"@iconify/tailwind": "^1.1.3",
|
||||
"@popperjs/core": "^2.11.8",
|
||||
"@rails/actioncable": "^7.1.0",
|
||||
"@rails/activestorage": "^7.2.100",
|
||||
"@rails/request.js": "^0.0.11",
|
||||
"@rails/request.js": "^0.0.12",
|
||||
"@rails/ujs": "^7.1.3-4",
|
||||
"@stimulus-components/sortable": "^5.0.3",
|
||||
"@tailwindcss/aspect-ratio": "^0.4.0",
|
||||
"@tailwindcss/forms": "^0.5.0",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
@@ -44,6 +45,7 @@
|
||||
"prettier": "^3.3.3",
|
||||
"prettier-plugin-tailwindcss": "^0.6.8",
|
||||
"sass": "^1.79.3",
|
||||
"sortablejs": "^1.15.6",
|
||||
"stimulus-flatpickr": "^3.0.0-0",
|
||||
"stimulus-textarea-autogrow": "^4.1.0",
|
||||
"tailwindcss": "^3.4.1",
|
||||
|
||||
BIN
public/images/languages/buildpack.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
public/images/languages/buildpack.webp
Normal file
|
After Width: | Height: | Size: 4.7 KiB |
BIN
public/images/languages/golang.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/images/languages/golang.webp
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
public/images/languages/java.png
Normal file
|
After Width: | Height: | Size: 16 KiB |
BIN
public/images/languages/java.webp
Normal file
|
After Width: | Height: | Size: 7.8 KiB |
BIN
public/images/languages/javascript.png
Normal file
|
After Width: | Height: | Size: 65 KiB |
BIN
public/images/languages/javascript.webp
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
public/images/languages/php.png
Normal file
|
After Width: | Height: | Size: 31 KiB |
BIN
public/images/languages/php.webp
Normal file
|
After Width: | Height: | Size: 4.6 KiB |
BIN
public/images/languages/python.png
Normal file
|
After Width: | Height: | Size: 5.9 KiB |
BIN
public/images/languages/python.webp
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
public/images/languages/ruby.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
public/images/languages/ruby.webp
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
public/images/languages/rust.png
Normal file
|
After Width: | Height: | Size: 27 KiB |
BIN
public/images/languages/rust.webp
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
public/images/languages/scala.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
public/images/languages/scala.webp
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
101
resources/build_packs/packs.yaml
Normal file
@@ -0,0 +1,101 @@
|
||||
---
|
||||
# Flat list of available buildpacks
|
||||
# Key format: namespace/name
|
||||
|
||||
paketo-buildpacks/ruby:
|
||||
namespace: paketo-buildpacks
|
||||
name: ruby
|
||||
image: /images/languages/ruby.webp
|
||||
description: "Paketo Ruby Buildpack - A language family buildpack for building Ruby apps"
|
||||
reference_type: registry
|
||||
|
||||
heroku/ruby:
|
||||
namespace: heroku
|
||||
name: ruby
|
||||
image: /images/languages/ruby.webp
|
||||
description: "Heroku's buildpack for Ruby applications"
|
||||
reference_type: registry
|
||||
|
||||
paketo-buildpacks/python:
|
||||
namespace: paketo-buildpacks
|
||||
name: python
|
||||
image: /images/languages/python.webp
|
||||
description: "Paketo Python Buildpack - A language family buildpack for building Python apps"
|
||||
reference_type: registry
|
||||
|
||||
heroku/python:
|
||||
namespace: heroku
|
||||
name: python
|
||||
image: /images/languages/python.webp
|
||||
description: "Heroku's buildpack for Python applications"
|
||||
reference_type: registry
|
||||
|
||||
paketo-buildpacks/go:
|
||||
namespace: paketo-buildpacks
|
||||
name: go
|
||||
image: /images/languages/golang.webp
|
||||
description: "Paketo Go Buildpack - A language family buildpack for building Go apps"
|
||||
reference_type: registry
|
||||
|
||||
heroku/go:
|
||||
namespace: heroku
|
||||
name: go
|
||||
image: /images/languages/golang.webp
|
||||
description: "Heroku's buildpack for Go applications"
|
||||
reference_type: registry
|
||||
|
||||
paketo-buildpacks/java:
|
||||
namespace: paketo-buildpacks
|
||||
name: java
|
||||
image: /images/languages/java.webp
|
||||
description: "Paketo Java Buildpack - A language family buildpack for building Java apps"
|
||||
reference_type: registry
|
||||
|
||||
heroku/java:
|
||||
namespace: heroku
|
||||
name: java
|
||||
image: /images/languages/java.webp
|
||||
description: "Heroku's buildpack for Java applications"
|
||||
reference_type: registry
|
||||
|
||||
paketo-buildpacks/nodejs:
|
||||
namespace: paketo-buildpacks
|
||||
name: nodejs
|
||||
image: /images/languages/javascript.webp
|
||||
description: "Paketo Node.js Buildpack - A language family buildpack for building Node.js apps"
|
||||
reference_type: registry
|
||||
|
||||
heroku/nodejs:
|
||||
namespace: heroku
|
||||
name: nodejs
|
||||
image: /images/languages/javascript.webp
|
||||
description: "Heroku's buildpack for Node.js applications"
|
||||
reference_type: registry
|
||||
|
||||
paketo-buildpacks/php:
|
||||
namespace: paketo-buildpacks
|
||||
name: php
|
||||
image: /images/languages/php.webp
|
||||
description: "Paketo PHP Buildpack - A language family buildpack for building PHP apps"
|
||||
reference_type: registry
|
||||
|
||||
heroku/php:
|
||||
namespace: heroku
|
||||
name: php
|
||||
image: /images/languages/php.webp
|
||||
description: "Heroku's buildpack for PHP applications"
|
||||
reference_type: registry
|
||||
|
||||
paketo-buildpacks/sbt:
|
||||
namespace: paketo-buildpacks
|
||||
name: sbt
|
||||
image: /images/languages/scala.webp
|
||||
description: "Paketo SBT Buildpack - A buildpack for building Scala apps with SBT"
|
||||
reference_type: registry
|
||||
|
||||
heroku/scala:
|
||||
namespace: heroku
|
||||
name: scala
|
||||
image: /images/languages/scala.webp
|
||||
description: "Heroku's buildpack for Scala applications"
|
||||
reference_type: registry
|
||||
@@ -74,6 +74,67 @@ RSpec.describe Projects::Create do
|
||||
expect(subject.project.build_configuration.provider_id).to eq(provider.id)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with buildpacks' do
|
||||
let(:params) do
|
||||
ActionController::Parameters.new({
|
||||
project: {
|
||||
name: 'example-repo',
|
||||
branch: 'main',
|
||||
cluster_id: cluster.id,
|
||||
repository_url: 'example/repo',
|
||||
docker_command: 'rails s',
|
||||
container_registry_url: '',
|
||||
project_credential_provider: {
|
||||
provider_id: provider.id
|
||||
},
|
||||
build_configuration: {
|
||||
driver: 'docker',
|
||||
image_repository: 'example/repo',
|
||||
provider_id: provider.id,
|
||||
build_type: 'buildpacks',
|
||||
buildpack_base_builder: 'paketobuildpacks/builder:full',
|
||||
build_packs_attributes: {
|
||||
'0' => {
|
||||
namespace: 'paketo-buildpacks',
|
||||
name: 'ruby',
|
||||
version: '',
|
||||
reference_type: 'registry'
|
||||
},
|
||||
'1' => {
|
||||
namespace: 'paketo-buildpacks',
|
||||
name: 'nodejs',
|
||||
version: '1.2.3',
|
||||
reference_type: 'registry'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
it 'creates build packs associated with build configuration' do
|
||||
expect(subject).to be_success
|
||||
expect(subject.project.build_configuration).to be_persisted
|
||||
expect(subject.project.build_configuration.build_type).to eq('buildpacks')
|
||||
expect(subject.project.build_configuration.buildpack_base_builder).to eq('paketobuildpacks/builder:full')
|
||||
|
||||
build_packs = subject.project.build_configuration.build_packs
|
||||
expect(build_packs.count).to eq(2)
|
||||
|
||||
first_pack = build_packs.first
|
||||
expect(first_pack.namespace).to eq('paketo-buildpacks')
|
||||
expect(first_pack.name).to eq('ruby')
|
||||
expect(first_pack.version).to eq('')
|
||||
expect(first_pack.reference_type).to eq('registry')
|
||||
|
||||
second_pack = build_packs.second
|
||||
expect(second_pack.namespace).to eq('paketo-buildpacks')
|
||||
expect(second_pack.name).to eq('nodejs')
|
||||
expect(second_pack.version).to eq('1.2.3')
|
||||
expect(second_pack.reference_type).to eq('registry')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for docker hub' do
|
||||
@@ -97,6 +158,7 @@ RSpec.describe Projects::Create do
|
||||
expect(subject).to eq([
|
||||
Projects::ValidateGitRepository,
|
||||
Projects::ValidateNamespaceAvailability,
|
||||
Projects::InitializeBuildPacks,
|
||||
Projects::Save,
|
||||
Projects::RegisterGitWebhook
|
||||
])
|
||||
@@ -112,6 +174,7 @@ RSpec.describe Projects::Create do
|
||||
expect(subject).to eq([
|
||||
Projects::ValidateGitRepository,
|
||||
Projects::ValidateNamespaceAvailability,
|
||||
Projects::InitializeBuildPacks,
|
||||
Projects::Save
|
||||
])
|
||||
end
|
||||
|
||||
63
spec/actions/projects/initialize_build_packs_spec.rb
Normal file
@@ -0,0 +1,63 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Projects::InitializeBuildPacks do
|
||||
let(:provider) { create(:provider, :github) }
|
||||
let(:project) { create(:project) }
|
||||
let(:build_configuration) do
|
||||
create(:build_configuration,
|
||||
project: project,
|
||||
provider: provider,
|
||||
build_type: :buildpacks,
|
||||
buildpack_base_builder: 'paketobuildpacks/builder:full')
|
||||
end
|
||||
|
||||
let(:params) do
|
||||
ActionController::Parameters.new({
|
||||
project: {
|
||||
build_configuration: {
|
||||
build_packs_attributes: {
|
||||
'0' => {
|
||||
namespace: 'paketo-buildpacks',
|
||||
name: 'ruby',
|
||||
version: '0.47.7',
|
||||
reference_type: 'registry'
|
||||
},
|
||||
'1' => {
|
||||
namespace: 'paketo-buildpacks',
|
||||
name: 'nodejs',
|
||||
version: '',
|
||||
reference_type: 'registry'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
let(:context) do
|
||||
{
|
||||
build_configuration: build_configuration,
|
||||
params: params
|
||||
}
|
||||
end
|
||||
|
||||
subject { described_class.execute(context) }
|
||||
|
||||
it 'builds build packs from attributes' do
|
||||
expect { subject }.to change { build_configuration.build_packs.size }.from(0).to(2)
|
||||
|
||||
first_pack = build_configuration.build_packs[0]
|
||||
expect(first_pack.namespace).to eq('paketo-buildpacks')
|
||||
expect(first_pack.name).to eq('ruby')
|
||||
expect(first_pack.version).to eq('0.47.7')
|
||||
expect(first_pack.reference_type).to eq('registry')
|
||||
|
||||
second_pack = build_configuration.build_packs[1]
|
||||
expect(second_pack.namespace).to eq('paketo-buildpacks')
|
||||
expect(second_pack.name).to eq('nodejs')
|
||||
expect(second_pack.version).to eq('')
|
||||
expect(second_pack.reference_type).to eq('registry')
|
||||
end
|
||||
end
|
||||
93
spec/actions/projects/update_build_packs_spec.rb
Normal file
@@ -0,0 +1,93 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Projects::UpdateBuildPacks do
|
||||
let(:provider) { create(:provider, :github) }
|
||||
let(:project) { create(:project) }
|
||||
let(:build_configuration) do
|
||||
create(:build_configuration,
|
||||
project: project,
|
||||
provider: provider,
|
||||
build_type: :buildpacks,
|
||||
buildpack_base_builder: 'paketobuildpacks/builder:full')
|
||||
end
|
||||
|
||||
let!(:existing_ruby) do
|
||||
create(
|
||||
:build_pack,
|
||||
build_configuration: build_configuration,
|
||||
namespace: 'paketo-buildpacks',
|
||||
name: 'ruby',
|
||||
reference_type: 'registry',
|
||||
build_order: 0,
|
||||
)
|
||||
end
|
||||
|
||||
let!(:existing_nodejs) do
|
||||
create(
|
||||
:build_pack,
|
||||
build_configuration: build_configuration,
|
||||
namespace: 'paketo-buildpacks',
|
||||
name: 'nodejs',
|
||||
reference_type: 'registry',
|
||||
build_order: 1,
|
||||
)
|
||||
end
|
||||
|
||||
let(:params) do
|
||||
ActionController::Parameters.new({
|
||||
project: {
|
||||
build_configuration: {
|
||||
build_packs_attributes: [
|
||||
{
|
||||
namespace: 'paketo-buildpacks',
|
||||
name: 'go',
|
||||
version: '',
|
||||
reference_type: 'registry'
|
||||
},
|
||||
{
|
||||
namespace: 'paketo-buildpacks',
|
||||
name: 'ruby',
|
||||
version: '',
|
||||
reference_type: 'registry'
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
|
||||
let(:context) do
|
||||
{
|
||||
build_configuration: build_configuration,
|
||||
params: params
|
||||
}
|
||||
end
|
||||
|
||||
let(:buildpack_details_result) do
|
||||
double(
|
||||
result: Buildpacks::Details::BuildpackDetailsResult.new(
|
||||
latest: {
|
||||
version: '0.47.7',
|
||||
namespace: 'paketo-buildpacks',
|
||||
name: 'go',
|
||||
description: 'Go buildpack'
|
||||
},
|
||||
versions: []
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
allow(Buildpacks::Details).to receive(:execute).and_return(buildpack_details_result)
|
||||
end
|
||||
|
||||
it 'keeps existing build packs, creates new ones, and deletes missing ones' do
|
||||
expect(build_configuration.build_packs.map(&:key)).to eq(['paketo-buildpacks/ruby', 'paketo-buildpacks/nodejs'])
|
||||
described_class.execute(context)
|
||||
build_configuration.build_packs.reload
|
||||
expect(build_configuration.build_packs.map(&:key)).to eq(['paketo-buildpacks/go', 'paketo-buildpacks/ruby'])
|
||||
end
|
||||
end
|
||||
|
||||
@@ -9,10 +9,8 @@ RSpec.describe Projects::Update do
|
||||
name: 'original-name',
|
||||
branch: 'main',
|
||||
cluster: cluster,
|
||||
docker_build_context_directory: '.',
|
||||
repository_url: 'original/repo',
|
||||
docker_command: 'rails s',
|
||||
dockerfile_path: 'Dockerfile',
|
||||
)
|
||||
end
|
||||
|
||||
@@ -24,10 +22,12 @@ RSpec.describe Projects::Update do
|
||||
name: 'updated-name',
|
||||
branch: 'develop',
|
||||
cluster_id: cluster.id,
|
||||
docker_build_context_directory: './app',
|
||||
repository_url: 'updated/repo',
|
||||
docker_command: 'bundle exec rails s',
|
||||
dockerfile_path: 'docker/Dockerfile'
|
||||
build_configuration: {
|
||||
context_directory: './app',
|
||||
dockerfile_path: 'docker/Dockerfile'
|
||||
}
|
||||
}
|
||||
})
|
||||
end
|
||||
@@ -39,10 +39,10 @@ RSpec.describe Projects::Update do
|
||||
expect(result).to be_success
|
||||
expect(result.project.name).to eq('updated-name')
|
||||
expect(result.project.branch).to eq('develop')
|
||||
expect(result.project.docker_build_context_directory).to eq('./app')
|
||||
expect(result.project.build_configuration.context_directory).to eq('./app')
|
||||
expect(result.project.repository_url).to eq('updated/repo')
|
||||
expect(result.project.docker_command).to eq('bundle exec rails s')
|
||||
expect(result.project.dockerfile_path).to eq('docker/Dockerfile')
|
||||
expect(result.project.build_configuration.dockerfile_path).to eq('docker/Dockerfile')
|
||||
end
|
||||
|
||||
it 'strips and downcases repository_url' do
|
||||
@@ -64,7 +64,9 @@ RSpec.describe Projects::Update do
|
||||
driver: 'k8s',
|
||||
build_cloud_id: build_cloud.id,
|
||||
provider_id: build_provider.id,
|
||||
image_repository: 'updated/repo'
|
||||
image_repository: 'updated/repo',
|
||||
context_directory: './app',
|
||||
dockerfile_path: 'docker/Dockerfile'
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
#
|
||||
# Table name: build_configurations
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# build_type :integer default(0), not null
|
||||
# driver :integer not null
|
||||
# image_repository :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# build_cloud_id :bigint
|
||||
# project_id :bigint not null
|
||||
# provider_id :bigint not null
|
||||
# id :bigint not null, primary key
|
||||
# build_type :integer default("dockerfile"), not null
|
||||
# buildpack_base_builder :string
|
||||
# context_directory :string default("."), not null
|
||||
# dockerfile_path :string default("./Dockerfile"), not null
|
||||
# driver :integer not null
|
||||
# image_repository :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# build_cloud_id :bigint
|
||||
# project_id :bigint not null
|
||||
# provider_id :bigint not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
@@ -29,6 +32,9 @@ FactoryBot.define do
|
||||
provider
|
||||
project
|
||||
driver { :docker }
|
||||
build_type { :dockerfile }
|
||||
image_repository { "CanineHQ/canine" }
|
||||
context_directory { "." }
|
||||
dockerfile_path { "./Dockerfile" }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
# Table name: build_packs
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# build_order :integer not null
|
||||
# details :jsonb
|
||||
# name :string
|
||||
# namespace :string
|
||||
# reference_type :string not null
|
||||
# reference_type :integer not null
|
||||
# uri :text
|
||||
# version :string
|
||||
# created_at :datetime not null
|
||||
@@ -26,7 +27,7 @@
|
||||
FactoryBot.define do
|
||||
factory :build_pack do
|
||||
build_configuration
|
||||
reference_type { :registry }
|
||||
reference_type { "registry" }
|
||||
namespace { "paketo-buildpacks" }
|
||||
name { "ruby" }
|
||||
version { "0.47.7" }
|
||||
@@ -40,25 +41,19 @@ FactoryBot.define do
|
||||
end
|
||||
|
||||
trait :git do
|
||||
reference_type { :git }
|
||||
reference_type { "git" }
|
||||
namespace { nil }
|
||||
name { nil }
|
||||
version { nil }
|
||||
uri { "https://github.com/DataDog/heroku-buildpack-datadog.git" }
|
||||
details { {} }
|
||||
end
|
||||
|
||||
trait :docker do
|
||||
reference_type { :docker }
|
||||
namespace { nil }
|
||||
name { nil }
|
||||
uri { "docker://paketobuildpacks/ruby:0.47.7" }
|
||||
details { {} }
|
||||
end
|
||||
|
||||
trait :url do
|
||||
reference_type { :url }
|
||||
reference_type { "url" }
|
||||
namespace { nil }
|
||||
name { nil }
|
||||
version { nil }
|
||||
uri { "https://github.com/heroku/buildpacks-ruby/releases/download/v0.1.0/buildpack.tgz" }
|
||||
details { {} }
|
||||
end
|
||||
|
||||
@@ -2,15 +2,18 @@
|
||||
#
|
||||
# Table name: build_configurations
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# build_type :integer default(0), not null
|
||||
# driver :integer not null
|
||||
# image_repository :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# build_cloud_id :bigint
|
||||
# project_id :bigint not null
|
||||
# provider_id :bigint not null
|
||||
# id :bigint not null, primary key
|
||||
# build_type :integer default("dockerfile"), not null
|
||||
# buildpack_base_builder :string
|
||||
# context_directory :string default("."), not null
|
||||
# dockerfile_path :string default("./Dockerfile"), not null
|
||||
# driver :integer not null
|
||||
# image_repository :string not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# build_cloud_id :bigint
|
||||
# project_id :bigint not null
|
||||
# provider_id :bigint not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
||||
@@ -3,10 +3,11 @@
|
||||
# Table name: build_packs
|
||||
#
|
||||
# id :bigint not null, primary key
|
||||
# build_order :integer not null
|
||||
# details :jsonb
|
||||
# name :string
|
||||
# namespace :string
|
||||
# reference_type :string not null
|
||||
# reference_type :integer not null
|
||||
# uri :text
|
||||
# version :string
|
||||
# created_at :datetime not null
|
||||
@@ -28,7 +29,7 @@ require 'rails_helper'
|
||||
RSpec.describe BuildPack, type: :model do
|
||||
describe '#reference' do
|
||||
context 'registry buildpack' do
|
||||
let(:build_pack) { create(:build_pack, namespace: 'paketo-buildpacks', name: 'ruby') }
|
||||
let(:build_pack) { create(:build_pack) }
|
||||
|
||||
context 'when version is present' do
|
||||
before { build_pack.update(version: '0.47.7') }
|
||||
@@ -55,14 +56,6 @@ RSpec.describe BuildPack, type: :model do
|
||||
end
|
||||
end
|
||||
|
||||
context 'docker buildpack' do
|
||||
let(:build_pack) { create(:build_pack, :docker) }
|
||||
|
||||
it 'returns the docker URI' do
|
||||
expect(build_pack.reference).to eq('docker://paketobuildpacks/ruby:0.47.7')
|
||||
end
|
||||
end
|
||||
|
||||
context 'url buildpack' do
|
||||
let(:build_pack) { create(:build_pack, :url) }
|
||||
|
||||
@@ -91,7 +84,7 @@ RSpec.describe BuildPack, type: :model do
|
||||
|
||||
describe '#display_name' do
|
||||
it 'returns namespace/name for registry buildpacks' do
|
||||
build_pack = create(:build_pack, namespace: 'paketo-buildpacks', name: 'ruby')
|
||||
build_pack = create(:build_pack)
|
||||
expect(build_pack.display_name).to eq('paketo-buildpacks/ruby')
|
||||
end
|
||||
|
||||
|
||||
252
yarn.lock
@@ -97,11 +97,126 @@
|
||||
style-mod "^4.1.0"
|
||||
w3c-keyname "^2.2.4"
|
||||
|
||||
"@esbuild/aix-ppc64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz#b57697945b50e99007b4c2521507dc613d4a648c"
|
||||
integrity sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw==
|
||||
|
||||
"@esbuild/android-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz#1add7e0af67acefd556e407f8497e81fddad79c0"
|
||||
integrity sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w==
|
||||
|
||||
"@esbuild/android-arm@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.0.tgz#ab7263045fa8e090833a8e3c393b60d59a789810"
|
||||
integrity sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew==
|
||||
|
||||
"@esbuild/android-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.0.tgz#e8f8b196cfdfdd5aeaebbdb0110983460440e705"
|
||||
integrity sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ==
|
||||
|
||||
"@esbuild/darwin-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz"
|
||||
integrity sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw==
|
||||
|
||||
"@esbuild/darwin-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz#33087aab31a1eb64c89daf3d2cf8ce1775656107"
|
||||
integrity sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA==
|
||||
|
||||
"@esbuild/freebsd-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz#bb76e5ea9e97fa3c753472f19421075d3a33e8a7"
|
||||
integrity sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA==
|
||||
|
||||
"@esbuild/freebsd-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz#e0e2ce9249fdf6ee29e5dc3d420c7007fa579b93"
|
||||
integrity sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ==
|
||||
|
||||
"@esbuild/linux-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz#d1b2aa58085f73ecf45533c07c82d81235388e75"
|
||||
integrity sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g==
|
||||
|
||||
"@esbuild/linux-arm@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz#8e4915df8ea3e12b690a057e77a47b1d5935ef6d"
|
||||
integrity sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw==
|
||||
|
||||
"@esbuild/linux-ia32@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz#8200b1110666c39ab316572324b7af63d82013fb"
|
||||
integrity sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA==
|
||||
|
||||
"@esbuild/linux-loong64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz#6ff0c99cf647504df321d0640f0d32e557da745c"
|
||||
integrity sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g==
|
||||
|
||||
"@esbuild/linux-mips64el@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz#3f720ccd4d59bfeb4c2ce276a46b77ad380fa1f3"
|
||||
integrity sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA==
|
||||
|
||||
"@esbuild/linux-ppc64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz#9d6b188b15c25afd2e213474bf5f31e42e3aa09e"
|
||||
integrity sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ==
|
||||
|
||||
"@esbuild/linux-riscv64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz#f989fdc9752dfda286c9cd87c46248e4dfecbc25"
|
||||
integrity sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw==
|
||||
|
||||
"@esbuild/linux-s390x@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz#29ebf87e4132ea659c1489fce63cd8509d1c7319"
|
||||
integrity sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g==
|
||||
|
||||
"@esbuild/linux-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz#4af48c5c0479569b1f359ffbce22d15f261c0cef"
|
||||
integrity sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA==
|
||||
|
||||
"@esbuild/netbsd-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz#1ae73d23cc044a0ebd4f198334416fb26c31366c"
|
||||
integrity sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg==
|
||||
|
||||
"@esbuild/openbsd-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz#5d904a4f5158c89859fd902c427f96d6a9e632e2"
|
||||
integrity sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg==
|
||||
|
||||
"@esbuild/openbsd-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz#4c8aa88c49187c601bae2971e71c6dc5e0ad1cdf"
|
||||
integrity sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q==
|
||||
|
||||
"@esbuild/sunos-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz#8ddc35a0ea38575fa44eda30a5ee01ae2fa54dd4"
|
||||
integrity sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA==
|
||||
|
||||
"@esbuild/win32-arm64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz#6e79c8543f282c4539db684a207ae0e174a9007b"
|
||||
integrity sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA==
|
||||
|
||||
"@esbuild/win32-ia32@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz#057af345da256b7192d18b676a02e95d0fa39103"
|
||||
integrity sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw==
|
||||
|
||||
"@esbuild/win32-x64@0.24.0":
|
||||
version "0.24.0"
|
||||
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz#168ab1c7e1c318b922637fad8f339d48b01e1244"
|
||||
integrity sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA==
|
||||
|
||||
"@gorails/ninja-keys@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/@gorails/ninja-keys/-/ninja-keys-1.2.1.tgz"
|
||||
@@ -111,23 +226,23 @@
|
||||
hotkeys-js "3.8.9"
|
||||
lit "2.2.2"
|
||||
|
||||
"@hotwired/stimulus@^3.0.0", "@hotwired/stimulus@^3.2.1", "@hotwired/stimulus@^3.2.2", "@hotwired/stimulus@>= 3.0.0":
|
||||
"@hotwired/stimulus@^3.0.0", "@hotwired/stimulus@^3.2.2":
|
||||
version "3.2.2"
|
||||
resolved "https://registry.npmjs.org/@hotwired/stimulus/-/stimulus-3.2.2.tgz"
|
||||
integrity sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A==
|
||||
|
||||
"@hotwired/turbo-rails@^8.0.10":
|
||||
version "8.0.10"
|
||||
resolved "https://registry.npmjs.org/@hotwired/turbo-rails/-/turbo-rails-8.0.10.tgz"
|
||||
integrity sha512-BkERfjTbNwMb9/YQi0RL9+f9zkD+dZH2klEONtGwXrIE3O9BE1937Nn9++koZpDryD4XN3zE5U5ibyWoYJAWBg==
|
||||
"@hotwired/turbo-rails@^8.0.20":
|
||||
version "8.0.20"
|
||||
resolved "https://registry.yarnpkg.com/@hotwired/turbo-rails/-/turbo-rails-8.0.20.tgz#a6f6f78591e9868ca1e5e67f4c7d453dbd49a475"
|
||||
integrity sha512-4aYkYF9XMKL7ZZPfgElq15+60osZOwMwhztE4myKQYEzCPvaPUxwZH301tOrBNtWUwOD+TNOm1Hrpeaq22RX9A==
|
||||
dependencies:
|
||||
"@hotwired/turbo" "^8.0.6"
|
||||
"@rails/actioncable" "^7.0"
|
||||
"@hotwired/turbo" "^8.0.20"
|
||||
"@rails/actioncable" ">=7.0"
|
||||
|
||||
"@hotwired/turbo@^8.0.6":
|
||||
version "8.0.10"
|
||||
resolved "https://registry.npmjs.org/@hotwired/turbo/-/turbo-8.0.10.tgz"
|
||||
integrity sha512-xen1YhNQirAHlA8vr/444XsTNITC1Il2l/Vx4w8hAWPpI5nQO78mVHNsmFuayETodzPwh25ob2TgfCEV/Loiog==
|
||||
"@hotwired/turbo@^8.0.20":
|
||||
version "8.0.20"
|
||||
resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-8.0.20.tgz#068ede648c4db09fed4cf0ac0266788056673f2f"
|
||||
integrity sha512-IilkH/+h92BRLeY/rMMR3MUh1gshIfdra/qZzp/Bl5FmiALD/6sQZK/ecxSbumeyOYiWr/JRI+Au1YQmkJGnoA==
|
||||
|
||||
"@iconify/tailwind@^1.1.3":
|
||||
version "1.1.3"
|
||||
@@ -251,7 +366,7 @@
|
||||
"@nodelib/fs.stat" "2.0.5"
|
||||
run-parallel "^1.1.9"
|
||||
|
||||
"@nodelib/fs.stat@^2.0.2", "@nodelib/fs.stat@2.0.5":
|
||||
"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2":
|
||||
version "2.0.5"
|
||||
resolved "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz"
|
||||
integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==
|
||||
@@ -286,7 +401,12 @@
|
||||
resolved "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz"
|
||||
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
|
||||
|
||||
"@rails/actioncable@^7.0", "@rails/actioncable@^7.1.0":
|
||||
"@rails/actioncable@>=7.0":
|
||||
version "8.1.100"
|
||||
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-8.1.100.tgz#b1f85f3482425fb91e5eba1deb55152ee0bb2f85"
|
||||
integrity sha512-j4vJQqz51CDVYv2UafKRu4jiZi5/gTnm7NkyL+VMIgEw3s8jtVtmzu9uItUaZccUg9NJ6o05yVyBAHxNfTuCRA==
|
||||
|
||||
"@rails/actioncable@^7.1.0":
|
||||
version "7.2.100"
|
||||
resolved "https://registry.npmjs.org/@rails/actioncable/-/actioncable-7.2.100.tgz"
|
||||
integrity sha512-7xtIENf0Yw59AFDM3+xqxPCZxev3QVAqjPmUzmgsB9eL8S/zTpB0IU9srNc7XknzJI4e09XKNnCaJRx3gfYzXA==
|
||||
@@ -298,10 +418,10 @@
|
||||
dependencies:
|
||||
spark-md5 "^3.0.1"
|
||||
|
||||
"@rails/request.js@^0.0.11":
|
||||
version "0.0.11"
|
||||
resolved "https://registry.npmjs.org/@rails/request.js/-/request.js-0.0.11.tgz"
|
||||
integrity sha512-2U3uYS0kbljt+pAstN+LIlZOl7xmOKig5N6FrvtUWO1wq0zR1Hf90fHfD2SYiyV8yH1nyKpoTmbLqWT0xe1zDg==
|
||||
"@rails/request.js@^0.0.12":
|
||||
version "0.0.12"
|
||||
resolved "https://registry.yarnpkg.com/@rails/request.js/-/request.js-0.0.12.tgz#3d1f73e7585141d9c4c2149a34476d128eb900bc"
|
||||
integrity sha512-g3//JBja1s04Zflj7IoMLQuXza9i4ZvtLmm0r0dMwh1QQUs6rL2iKUOGGyERfLsd81SnXC5ucfVV//rtsDlEEA==
|
||||
|
||||
"@rails/ujs@^7.1.3-4":
|
||||
version "7.1.3-4"
|
||||
@@ -313,6 +433,11 @@
|
||||
resolved "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-2.3.0.tgz"
|
||||
integrity sha512-LtoMMhxAlorcGhmFYI+LhPgbPZCkgP6ra1YL604EeF6U98pLlQ3iWIGMdWSC+vWmPBWBNgmDBAhnAobLROJmwg==
|
||||
|
||||
"@stimulus-components/sortable@^5.0.3":
|
||||
version "5.0.3"
|
||||
resolved "https://registry.yarnpkg.com/@stimulus-components/sortable/-/sortable-5.0.3.tgz#b8b64f954a05497fa6ca00f21557d466a2ebe47b"
|
||||
integrity sha512-GSiu4CX2irR3gIuo3nsSNXlJsEvXVurC2caNTNshlGbsP0sHb70bLn7iiVib7iGSmLJdXdU6wCpD3AEnMKCt2Q==
|
||||
|
||||
"@tailwindcss/aspect-ratio@^0.4.0":
|
||||
version "0.4.2"
|
||||
resolved "https://registry.npmjs.org/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz"
|
||||
@@ -447,7 +572,7 @@ braces@^3.0.3, braces@~3.0.2:
|
||||
dependencies:
|
||||
fill-range "^7.1.1"
|
||||
|
||||
browserslist@^4.23.3, "browserslist@>= 4.21.0":
|
||||
browserslist@^4.23.3:
|
||||
version "4.24.0"
|
||||
resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz"
|
||||
integrity sha512-Rmb62sR1Zpjql25eSanFGEhAxcFwfA1K0GuQcLoaJBAcENegrQut3hYdhXFF1obQfiDyqIW/cLM5HSJ/9k884A==
|
||||
@@ -467,7 +592,7 @@ caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001663:
|
||||
resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001663.tgz"
|
||||
integrity sha512-o9C3X27GLKbLeTYZ6HBOLU1tsAcBZsLis28wrVzddShCS16RujjHp9GDHKZqrB3meE0YjhawvMFsGb/igqiPzA==
|
||||
|
||||
chart.js@^4.4.6, chart.js@>=2.8.0, chart.js@4:
|
||||
chart.js@4, chart.js@^4.4.6:
|
||||
version "4.4.6"
|
||||
resolved "https://registry.npmjs.org/chart.js/-/chart.js-4.4.6.tgz"
|
||||
integrity sha512-8Y406zevUPbbIBA/HRk33khEmQPk5+cxeflWE/2rx1NJsjVWMPw/9mSP9rxHP5eqi6LNoPBVMfZHxbwLSgldYA==
|
||||
@@ -488,37 +613,7 @@ chartkick@^5.0.1:
|
||||
chartjs-adapter-date-fns ">=3"
|
||||
date-fns ">=2"
|
||||
|
||||
chokidar@^3.3.0:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz"
|
||||
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
|
||||
dependencies:
|
||||
anymatch "~3.1.2"
|
||||
braces "~3.0.2"
|
||||
glob-parent "~5.1.2"
|
||||
is-binary-path "~2.1.0"
|
||||
is-glob "~4.0.1"
|
||||
normalize-path "~3.0.0"
|
||||
readdirp "~3.6.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
chokidar@^3.5.2:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz"
|
||||
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
|
||||
dependencies:
|
||||
anymatch "~3.1.2"
|
||||
braces "~3.0.2"
|
||||
glob-parent "~5.1.2"
|
||||
is-binary-path "~2.1.0"
|
||||
is-glob "~4.0.1"
|
||||
normalize-path "~3.0.0"
|
||||
readdirp "~3.6.0"
|
||||
optionalDependencies:
|
||||
fsevents "~2.3.2"
|
||||
|
||||
chokidar@^3.5.3:
|
||||
chokidar@^3.3.0, chokidar@^3.5.2, chokidar@^3.5.3:
|
||||
version "3.6.0"
|
||||
resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz"
|
||||
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
|
||||
@@ -635,7 +730,7 @@ daisyui@^4.12.10:
|
||||
picocolors "^1"
|
||||
postcss-js "^4"
|
||||
|
||||
date-fns@>=2, date-fns@>=2.0.0:
|
||||
date-fns@>=2:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz"
|
||||
integrity sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==
|
||||
@@ -699,7 +794,7 @@ esbuild-rails@^1.0.7:
|
||||
dependencies:
|
||||
fast-glob "^3.2.12"
|
||||
|
||||
esbuild@*, esbuild@^0.24.0:
|
||||
esbuild@^0.24.0:
|
||||
version "0.24.0"
|
||||
resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.24.0.tgz"
|
||||
integrity sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ==
|
||||
@@ -764,7 +859,7 @@ fill-range@^7.1.1:
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
flatpickr@^4.6.10, flatpickr@>=4.6.2:
|
||||
flatpickr@^4.6.10:
|
||||
version "4.6.13"
|
||||
resolved "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz"
|
||||
integrity sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw==
|
||||
@@ -943,7 +1038,7 @@ jackspeak@^3.1.2:
|
||||
optionalDependencies:
|
||||
"@pkgjs/parseargs" "^0.11.0"
|
||||
|
||||
jiti@^1.21.0, jiti@>=1.21.0:
|
||||
jiti@^1.21.0:
|
||||
version "1.21.6"
|
||||
resolved "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz"
|
||||
integrity sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==
|
||||
@@ -1000,15 +1095,6 @@ lit-html@^2.2.0, lit-html@^2.8.0:
|
||||
dependencies:
|
||||
"@types/trusted-types" "^2.0.2"
|
||||
|
||||
lit@^2.0.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz"
|
||||
integrity sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==
|
||||
dependencies:
|
||||
"@lit/reactive-element" "^1.6.0"
|
||||
lit-element "^3.3.0"
|
||||
lit-html "^2.8.0"
|
||||
|
||||
lit@2.2.2:
|
||||
version "2.2.2"
|
||||
resolved "https://registry.npmjs.org/lit/-/lit-2.2.2.tgz"
|
||||
@@ -1018,6 +1104,15 @@ lit@2.2.2:
|
||||
lit-element "^3.2.0"
|
||||
lit-html "^2.2.0"
|
||||
|
||||
lit@^2.0.0:
|
||||
version "2.8.0"
|
||||
resolved "https://registry.npmjs.org/lit/-/lit-2.8.0.tgz"
|
||||
integrity sha512-4Sc3OFX9QHOJaHbmTMk28SYgVxLN3ePDjg7hofEft2zWlehFL3LiAuapWc4U/kYwMYJSh2hTCPZ6/LIC7ii0MA==
|
||||
dependencies:
|
||||
"@lit/reactive-element" "^1.6.0"
|
||||
lit-element "^3.3.0"
|
||||
lit-html "^2.8.0"
|
||||
|
||||
local-time@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.npmjs.org/local-time/-/local-time-3.0.2.tgz"
|
||||
@@ -1270,14 +1365,6 @@ postcss-reporter@^7.0.0:
|
||||
picocolors "^1.0.0"
|
||||
thenby "^1.3.4"
|
||||
|
||||
postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.1.1:
|
||||
version "6.1.2"
|
||||
resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz"
|
||||
integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
postcss-selector-parser@6.0.10:
|
||||
version "6.0.10"
|
||||
resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz"
|
||||
@@ -1286,12 +1373,20 @@ postcss-selector-parser@6.0.10:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
postcss-selector-parser@^6.0.11, postcss-selector-parser@^6.1.1:
|
||||
version "6.1.2"
|
||||
resolved "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz"
|
||||
integrity sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==
|
||||
dependencies:
|
||||
cssesc "^3.0.0"
|
||||
util-deprecate "^1.0.2"
|
||||
|
||||
postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
|
||||
version "4.2.0"
|
||||
resolved "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz"
|
||||
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
|
||||
|
||||
postcss@^8.0.0, postcss@^8.1.0, postcss@^8.2.14, postcss@^8.4.21, postcss@^8.4.23, postcss@^8.4.47, postcss@>=8.0.9:
|
||||
postcss@^8.4.23, postcss@^8.4.47:
|
||||
version "8.4.47"
|
||||
resolved "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz"
|
||||
integrity sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==
|
||||
@@ -1305,7 +1400,7 @@ prettier-plugin-tailwindcss@^0.6.8:
|
||||
resolved "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.6.8.tgz"
|
||||
integrity sha512-dGu3kdm7SXPkiW4nzeWKCl3uoImdd5CTZEJGxyypEPL37Wj0HT2pLqjrvSei1nTeuQfO4PUfjeW5cTUNRLZ4sA==
|
||||
|
||||
prettier@^3.0, prettier@^3.3.3:
|
||||
prettier@^3.3.3:
|
||||
version "3.3.3"
|
||||
resolved "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz"
|
||||
integrity sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==
|
||||
@@ -1423,7 +1518,12 @@ slash@^5.0.0, slash@^5.1.0:
|
||||
resolved "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz"
|
||||
integrity sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==
|
||||
|
||||
source-map-js@^1.2.1, "source-map-js@>=0.6.2 <2.0.0":
|
||||
sortablejs@^1.15.6:
|
||||
version "1.15.6"
|
||||
resolved "https://registry.yarnpkg.com/sortablejs/-/sortablejs-1.15.6.tgz#ff93699493f5b8ab8d828f933227b4988df1d393"
|
||||
integrity sha512-aNfiuwMEpfBM/CN6LY0ibyhxPfPbyFeBTYJKCvzkJ2GkUpazIt3H+QIPAMHwqQ7tMKaHz1Qj+rJJCqljnf4p3A==
|
||||
|
||||
"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.2.1:
|
||||
version "1.2.1"
|
||||
resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz"
|
||||
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
|
||||
@@ -1544,7 +1644,7 @@ svg.filter.js@^2.0.2:
|
||||
dependencies:
|
||||
svg.js "^2.2.5"
|
||||
|
||||
svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5, svg.js@>=2.3.x:
|
||||
svg.js@>=2.3.x, svg.js@^2.0.1, svg.js@^2.2.5, svg.js@^2.4.0, svg.js@^2.6.5:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.npmjs.org/svg.js/-/svg.js-2.7.1.tgz"
|
||||
integrity sha512-ycbxpizEQktk3FYvn/8BH+6/EuWXg7ZpQREJvgacqn46gIddG24tNNe4Son6omdXCnSOaApnpZw6MPCBA1dODA==
|
||||
@@ -1583,7 +1683,7 @@ tailwindcss-stimulus-components@^5.1.0:
|
||||
resolved "https://registry.npmjs.org/tailwindcss-stimulus-components/-/tailwindcss-stimulus-components-5.1.1.tgz"
|
||||
integrity sha512-9e3H9WLZoGzWQBVOdYvxqM42MsJ4dfkfdrs3NGV+HYvHbIcF9tukl2MPKVZpBv/pP+puZbJv0lFgdn79IGVApA==
|
||||
|
||||
tailwindcss@^3.4.1, "tailwindcss@>=2.0.0 || >=3.0.0 || >=3.0.0-alpha.1", "tailwindcss@>=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20", "tailwindcss@>=3.0.0 || insiders || >=4.0.0-alpha.20":
|
||||
tailwindcss@^3.4.1:
|
||||
version "3.4.13"
|
||||
resolved "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.13.tgz"
|
||||
integrity sha512-KqjHOJKogOUt5Bs752ykCeiwvi0fKVkr5oqsFNt/8px/tA8scFPIlkygsf6jXrfCqGHz7VflA6+yytWuM+XhFw==
|
||||
|
||||