kcppayments_rails 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +49 -0
  4. data/Rakefile +4 -0
  5. data/lib/generators/kcppayments_rails/install/install_generator.rb +21 -0
  6. data/lib/generators/kcppayments_rails/install/templates/kcp_controller.js +54 -0
  7. data/lib/generators/kcppayments_rails/install/templates/kcppayments_rails.rb +14 -0
  8. data/lib/kcppayments_rails/client.rb +49 -0
  9. data/lib/kcppayments_rails/configuration.rb +24 -0
  10. data/lib/kcppayments_rails/engine.rb +21 -0
  11. data/lib/kcppayments_rails/helpers/kcp_helper.rb +33 -0
  12. data/lib/kcppayments_rails/version.rb +5 -0
  13. data/lib/kcppayments_rails.rb +26 -0
  14. data/sig/kcppayments_rails.rbs +4 -0
  15. data/test_app/.dockerignore +51 -0
  16. data/test_app/.github/dependabot.yml +12 -0
  17. data/test_app/.github/workflows/ci.yml +55 -0
  18. data/test_app/.gitignore +87 -0
  19. data/test_app/.kamal/hooks/docker-setup.sample +3 -0
  20. data/test_app/.kamal/hooks/post-app-boot.sample +3 -0
  21. data/test_app/.kamal/hooks/post-deploy.sample +14 -0
  22. data/test_app/.kamal/hooks/post-proxy-reboot.sample +3 -0
  23. data/test_app/.kamal/hooks/pre-app-boot.sample +3 -0
  24. data/test_app/.kamal/hooks/pre-build.sample +51 -0
  25. data/test_app/.kamal/hooks/pre-connect.sample +47 -0
  26. data/test_app/.kamal/hooks/pre-deploy.sample +122 -0
  27. data/test_app/.kamal/hooks/pre-proxy-reboot.sample +3 -0
  28. data/test_app/.kamal/secrets +17 -0
  29. data/test_app/.rubocop.yml +8 -0
  30. data/test_app/.ruby-version +1 -0
  31. data/test_app/Dockerfile +72 -0
  32. data/test_app/Gemfile +60 -0
  33. data/test_app/Gemfile.lock +370 -0
  34. data/test_app/README.md +181 -0
  35. data/test_app/Rakefile +6 -0
  36. data/test_app/app/assets/images/.keep +0 -0
  37. data/test_app/app/assets/stylesheets/application.css +10 -0
  38. data/test_app/app/controllers/application_controller.rb +4 -0
  39. data/test_app/app/controllers/concerns/.keep +0 -0
  40. data/test_app/app/controllers/orders_controller.rb +31 -0
  41. data/test_app/app/controllers/payments_controller.rb +120 -0
  42. data/test_app/app/helpers/application_helper.rb +2 -0
  43. data/test_app/app/helpers/orders_helper.rb +2 -0
  44. data/test_app/app/helpers/payments_helper.rb +2 -0
  45. data/test_app/app/javascript/application.js +3 -0
  46. data/test_app/app/javascript/controllers/application.js +9 -0
  47. data/test_app/app/javascript/controllers/hello_controller.js +7 -0
  48. data/test_app/app/javascript/controllers/index.js +4 -0
  49. data/test_app/app/javascript/controllers/kcp_controller.js +310 -0
  50. data/test_app/app/jobs/application_job.rb +7 -0
  51. data/test_app/app/mailers/application_mailer.rb +4 -0
  52. data/test_app/app/models/application_record.rb +3 -0
  53. data/test_app/app/models/concerns/.keep +0 -0
  54. data/test_app/app/models/order.rb +67 -0
  55. data/test_app/app/views/layouts/application.html.erb +28 -0
  56. data/test_app/app/views/layouts/mailer.html.erb +13 -0
  57. data/test_app/app/views/layouts/mailer.text.erb +1 -0
  58. data/test_app/app/views/orders/create.html.erb +2 -0
  59. data/test_app/app/views/orders/index.html.erb +41 -0
  60. data/test_app/app/views/orders/new.html.erb +44 -0
  61. data/test_app/app/views/orders/show.html.erb +36 -0
  62. data/test_app/app/views/payments/_receipt_links.html.erb +31 -0
  63. data/test_app/app/views/payments/callback.html.erb +2 -0
  64. data/test_app/app/views/payments/create.html.erb +2 -0
  65. data/test_app/app/views/payments/failure.html.erb +20 -0
  66. data/test_app/app/views/payments/new.html.erb +145 -0
  67. data/test_app/app/views/payments/receipt.html.erb +156 -0
  68. data/test_app/app/views/payments/success.html.erb +34 -0
  69. data/test_app/app/views/pwa/manifest.json.erb +22 -0
  70. data/test_app/app/views/pwa/service-worker.js +26 -0
  71. data/test_app/bin/brakeman +7 -0
  72. data/test_app/bin/dev +2 -0
  73. data/test_app/bin/docker-entrypoint +14 -0
  74. data/test_app/bin/importmap +4 -0
  75. data/test_app/bin/jobs +6 -0
  76. data/test_app/bin/kamal +16 -0
  77. data/test_app/bin/rails +4 -0
  78. data/test_app/bin/rake +4 -0
  79. data/test_app/bin/rubocop +8 -0
  80. data/test_app/bin/setup +65 -0
  81. data/test_app/bin/thrust +5 -0
  82. data/test_app/config/application.rb +42 -0
  83. data/test_app/config/boot.rb +4 -0
  84. data/test_app/config/cable.yml +17 -0
  85. data/test_app/config/cache.yml +16 -0
  86. data/test_app/config/credentials.yml.enc +1 -0
  87. data/test_app/config/database.yml +41 -0
  88. data/test_app/config/deploy.yml +116 -0
  89. data/test_app/config/environment.rb +5 -0
  90. data/test_app/config/environments/development.rb +74 -0
  91. data/test_app/config/environments/production.rb +90 -0
  92. data/test_app/config/environments/test.rb +53 -0
  93. data/test_app/config/importmap.rb +7 -0
  94. data/test_app/config/initializers/assets.rb +7 -0
  95. data/test_app/config/initializers/content_security_policy.rb +25 -0
  96. data/test_app/config/initializers/filter_parameter_logging.rb +8 -0
  97. data/test_app/config/initializers/inflections.rb +16 -0
  98. data/test_app/config/initializers/kcppayments_rails.rb +29 -0
  99. data/test_app/config/locales/en.yml +31 -0
  100. data/test_app/config/master.key +1 -0
  101. data/test_app/config/puma.rb +41 -0
  102. data/test_app/config/queue.yml +18 -0
  103. data/test_app/config/recurring.yml +15 -0
  104. data/test_app/config/routes.rb +29 -0
  105. data/test_app/config/storage.yml +34 -0
  106. data/test_app/config.ru +6 -0
  107. data/test_app/db/cable_schema.rb +11 -0
  108. data/test_app/db/cache_schema.rb +14 -0
  109. data/test_app/db/migrate/20250827075913_create_orders.rb +16 -0
  110. data/test_app/db/migrate/20250827121258_add_kcp_fields_to_orders.rb +6 -0
  111. data/test_app/db/queue_schema.rb +129 -0
  112. data/test_app/db/schema.rb +28 -0
  113. data/test_app/db/seeds.rb +80 -0
  114. data/test_app/lib/tasks/.keep +0 -0
  115. data/test_app/log/.keep +0 -0
  116. data/test_app/public/.well-known/appspecific/com.chrome.devtools.json +1 -0
  117. data/test_app/public/400.html +114 -0
  118. data/test_app/public/404.html +114 -0
  119. data/test_app/public/406-unsupported-browser.html +114 -0
  120. data/test_app/public/422.html +114 -0
  121. data/test_app/public/500.html +114 -0
  122. data/test_app/public/icon.png +0 -0
  123. data/test_app/public/icon.svg +3 -0
  124. data/test_app/public/robots.txt +1 -0
  125. data/test_app/script/.keep +0 -0
  126. data/test_app/tmp/.keep +0 -0
  127. data/test_app/tmp/restart.txt +0 -0
  128. data/test_app/vendor/.keep +0 -0
  129. data/test_app/vendor/javascript/.keep +0 -0
  130. metadata +184 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7026a79427dd30b522920128a591957439895f19d06776aab7e96766ee05d596
4
+ data.tar.gz: b9d7886e466d486c3921c29dac75abebd0922ef9391712d49e5ad52abfc5c2cc
5
+ SHA512:
6
+ metadata.gz: 426bb8883a6ea59ba25631ee2afe05dd5d3464ceb617086fef2e1c1d48576dd441ccb533db677b715eaf89426f0e43e54410670abc68288026d7eb82df2ca46c
7
+ data.tar.gz: 50098b2c35b0d1cf665a37bd7ed1314a54f2b21435a53d720906f8cf2163caf6cbf40172eaba17a0a2fd1020bc186a89abfa00ec8ce7a64f006aa45b01eaac0f
data/CHANGELOG.md ADDED
@@ -0,0 +1,5 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.1.0] - 2025-08-24
4
+
5
+ - Initial release
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ # KCP Payments Rails
2
+
3
+ Rails 7/8에서 KCP 표준결제 연동을 간편하게 도와주는 Rails Engine + Stimulus 래퍼 젬입니다.
4
+
5
+ ## 설치
6
+
7
+ ```ruby
8
+ gem "kcppayments_rails", github: "luciuschoi/kcppayments_rails"
9
+ ```
10
+
11
+ ```bash
12
+ bundle install
13
+ bin/rails g kcppayments_rails:install
14
+ ```
15
+
16
+ ## 초기화 설정
17
+
18
+ `config/initializers/kcppayments_rails.rb` 파일을 열어 KCP 상점 정보를 설정하세요.
19
+
20
+ ## 뷰 사용 예시 (ERB)
21
+
22
+ ```erb
23
+ <%= kcp_script_tag %>
24
+
25
+ <%= form_with url: checkout_payments_path, method: :post, **kcp_form_attrs(
26
+ order_id: @order.number,
27
+ amount: @order.total_price,
28
+ buyer_name: current_user.name,
29
+ buyer_email: current_user.email,
30
+ product_name: @order.summary,
31
+ return_url: payment_complete_url
32
+ ) do |f| %>
33
+ <button data-controller="kcp" data-action="click->kcp#requestPayment">결제하기</button>
34
+ <% end %>
35
+ ```
36
+
37
+ ## 서버 처리
38
+
39
+ 승인/취소 등의 서버-서버 통신은 `KcppaymentsRails::Client`를 사용하세요.
40
+
41
+ ```ruby
42
+ client = KcppaymentsRails::Client.new
43
+ result = client.approve({ # KCP 요구 파라미터 })
44
+ ```
45
+
46
+ ## 주의사항
47
+
48
+ - KCP 표준결제는 레거시 스크립트를 로드합니다. `kcp_script_tag`를 `<head>` 혹은 `<body>` 상단에서 불러오세요.
49
+ - 상점코드(`site_cd`)와 키(`site_key`)는 환경변수 또는 이니셜라이저에서 설정하세요.
data/Rakefile ADDED
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ task default: %i[]
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+
5
+ module KcppaymentsRails
6
+ module Generators
7
+ class InstallGenerator < Rails::Generators::Base
8
+ source_root File.expand_path("templates", __dir__)
9
+
10
+ def copy_stimulus_controller
11
+ template "kcp_controller.js", "app/javascript/controllers/kcp_controller.js"
12
+ end
13
+
14
+ def create_initializer
15
+ template "kcppayments_rails.rb", "config/initializers/kcppayments_rails.rb"
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+
@@ -0,0 +1,54 @@
1
+ import { Controller } from "@hotwired/stimulus";
2
+
3
+ // data-controller="kcp"
4
+ // Values:
5
+ // data-kcp-order-id-value
6
+ // data-kcp-amount-value
7
+ // data-kcp-buyer-name-value
8
+ // data-kcp-buyer-email-value
9
+ // data-kcp-product-name-value
10
+ // data-kcp-return-url-value
11
+ // data-kcp-escrow-value
12
+ // data-kcp-tax-free-amount-value
13
+
14
+ export default class extends Controller {
15
+ static values = {
16
+ orderId: String,
17
+ amount: Number,
18
+ buyerName: String,
19
+ buyerEmail: String,
20
+ productName: String,
21
+ returnUrl: String,
22
+ escrow: Boolean,
23
+ taxFreeAmount: Number,
24
+ };
25
+
26
+ connect() {
27
+ // KCP 스크립트는 서버에서 include되어야 함 (kcp_script_tag)
28
+ }
29
+
30
+ requestPayment(event) {
31
+ event?.preventDefault();
32
+
33
+ if (typeof window.KCP_Pay_Execute !== "function") {
34
+ console.error(
35
+ "KCP_Pay_Execute is not loaded. Make sure kcp_script_tag is included."
36
+ );
37
+ return;
38
+ }
39
+
40
+ // 결제 실행 (KCP 페이지의 form name/id 관례를 따를 수 있음)
41
+ const form = this.element.closest("form");
42
+ if (!form) {
43
+ console.error("No form element found for KCP payment.");
44
+ return;
45
+ }
46
+
47
+ // KCP_Pay_Execute(form) 같은 레거시 호출을 래핑
48
+ try {
49
+ window.KCP_Pay_Execute(form);
50
+ } catch (e) {
51
+ console.error("KCP_Pay_Execute failed:", e);
52
+ }
53
+ }
54
+ }
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # KcpPaymentsRails 초기화 설정
4
+ KcppaymentsRails.configure do |config|
5
+ # 테스트/운영 계정에 맞게 설정하세요
6
+ # config.site_cd = ENV["KCP_SITE_CD"]
7
+ # config.site_key = ENV["KCP_SITE_KEY"]
8
+ # config.gateway_url = "https://testpaygw.kcp.co.kr"
9
+ # config.js_url = "https://testpay.kcp.co.kr/plugin/payplus_web.jsp"
10
+ # config.escrow = false
11
+ # config.tax_free_amount_field = :tax_free_amount
12
+ end
13
+
14
+
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "uri"
5
+ require "json"
6
+
7
+ module KcppaymentsRails
8
+ class Client
9
+ # 서버-서버 통신용 기본 클라이언트 (승인/취소 등)
10
+ def initialize(site_cd: KcppaymentsRails.configuration.site_cd, site_key: KcppaymentsRails.configuration.site_key, gateway_url: KcppaymentsRails.configuration.gateway_url)
11
+ @site_cd = site_cd
12
+ @site_key = site_key
13
+ @gateway_url = gateway_url
14
+ end
15
+
16
+ def approve(params)
17
+ post("/center/pp_ax_hub.jsp", params)
18
+ end
19
+
20
+ def cancel(params)
21
+ post("/center/pp_ax_hub.jsp", params.merge(type: "cancel"))
22
+ end
23
+
24
+ private
25
+
26
+ def post(path, params)
27
+ uri = URI.join(@gateway_url, path)
28
+ req = Net::HTTP::Post.new(uri)
29
+ req.set_form_data(params.merge(site_cd: @site_cd, site_key: @site_key))
30
+
31
+ http = Net::HTTP.new(uri.host, uri.port)
32
+ http.use_ssl = uri.scheme == "https"
33
+ res = http.request(req)
34
+ parse_response(res)
35
+ end
36
+
37
+ def parse_response(res)
38
+ content_type = res["Content-Type"]
39
+ if content_type&.include?("json")
40
+ JSON.parse(res.body)
41
+ else
42
+ # KCP는 key=value\n 형태도 반환함
43
+ res.body.to_s.split(/\r?\n/).map { |l| l.split("=", 2) }.to_h
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KcppaymentsRails
4
+ class Configuration
5
+ # KCP 표준결제 기본 설정 값들
6
+ attr_accessor :site_cd, :site_key, :gateway_url, :js_url, :escrow, :tax_free_amount_field
7
+
8
+ def initialize
9
+ @site_cd = ENV["KCP_SITE_CD"]
10
+ @site_key = ENV["KCP_SITE_KEY"]
11
+ @gateway_url = ENV["KCP_GATEWAY_URL"] || "https://testpaygw.kcp.co.kr"
12
+ @js_url = ENV["KCP_JS_URL"] || "https://testpay.kcp.co.kr/plugin/payplus_web.jsp"
13
+ # @target_url = if Rails.env.production? # 운영서버
14
+ # "https://spl.kcp.co.kr"
15
+ # else # Rails.env.development? || Rails.env.staging? # 개발서버 또는 스테이징서버
16
+ # "https://stg-spl.kcp.co.kr"
17
+ # end
18
+ @escrow = false
19
+ @tax_free_amount_field = :tax_free_amount
20
+ end
21
+ end
22
+ end
23
+
24
+
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/engine"
4
+
5
+ module KcppaymentsRails
6
+ class Engine < ::Rails::Engine
7
+ isolate_namespace KcppaymentsRails
8
+
9
+ initializer "kcppayments_rails.view_helpers" do
10
+ ActiveSupport.on_load(:action_view) do
11
+ include KcppaymentsRails::KcpHelper
12
+ end
13
+
14
+ ActiveSupport.on_load(:action_controller) do
15
+ helper KcppaymentsRails::KcpHelper
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KcppaymentsRails
4
+ module KcpHelper
5
+ # KCP 표준결제 스크립트 로더
6
+ def kcp_script_tag
7
+ src = KcppaymentsRails.configuration.js_url
8
+ # KCP는 전통적으로 jsp 경로를 로드합니다 (ex: payplus_web.jsp)
9
+ # 레거시 리소스이므로 async/defer 없이 삽입하는 것을 권장합니다.
10
+ javascript_include_tag(src)
11
+ end
12
+
13
+ # 결제 폼에 필요한 hidden 필드 및 data-controller 속성을 부여
14
+ # form_with 등의 블록 내부에서 사용
15
+ def kcp_form_attrs(order_id:, amount:, buyer_name:, buyer_email:, product_name:, return_url: nil, escrow: nil, tax_free_amount: nil)
16
+ {
17
+ data: {
18
+ controller: "kcp",
19
+ kcp_order_id_value: order_id,
20
+ kcp_amount_value: amount,
21
+ kcp_buyer_name_value: buyer_name,
22
+ kcp_buyer_email_value: buyer_email,
23
+ kcp_product_name_value: product_name,
24
+ kcp_return_url_value: return_url,
25
+ kcp_escrow_value: (escrow.nil? ? KcppaymentsRails.configuration.escrow : escrow),
26
+ kcp_tax_free_amount_value: tax_free_amount
27
+ }
28
+ }
29
+ end
30
+ end
31
+ end
32
+
33
+
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module KcppaymentsRails
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "kcppayments_rails/version"
4
+ require_relative "kcppayments_rails/configuration"
5
+ require_relative "kcppayments_rails/client"
6
+ require_relative "kcppayments_rails/helpers/kcp_helper"
7
+
8
+ begin
9
+ require_relative "kcppayments_rails/engine"
10
+ rescue LoadError
11
+ # Rails가 아닌 환경에서는 엔진을 로드하지 않습니다.
12
+ end
13
+
14
+ module KcppaymentsRails
15
+ class Error < StandardError; end
16
+
17
+ class << self
18
+ def configuration
19
+ @configuration ||= Configuration.new
20
+ end
21
+
22
+ def configure
23
+ yield(configuration)
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,4 @@
1
+ module KcppaymentsRails
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end
@@ -0,0 +1,51 @@
1
+ # See https://docs.docker.com/engine/reference/builder/#dockerignore-file for more about ignoring files.
2
+
3
+ # Ignore git directory.
4
+ /.git/
5
+ /.gitignore
6
+
7
+ # Ignore bundler config.
8
+ /.bundle
9
+
10
+ # Ignore all environment files.
11
+ /.env*
12
+
13
+ # Ignore all default key files.
14
+ /config/master.key
15
+ /config/credentials/*.key
16
+
17
+ # Ignore all logfiles and tempfiles.
18
+ /log/*
19
+ /tmp/*
20
+ !/log/.keep
21
+ !/tmp/.keep
22
+
23
+ # Ignore pidfiles, but keep the directory.
24
+ /tmp/pids/*
25
+ !/tmp/pids/.keep
26
+
27
+ # Ignore storage (uploaded files in development and any SQLite databases).
28
+ /storage/*
29
+ !/storage/.keep
30
+ /tmp/storage/*
31
+ !/tmp/storage/.keep
32
+
33
+ # Ignore assets.
34
+ /node_modules/
35
+ /app/assets/builds/*
36
+ !/app/assets/builds/.keep
37
+ /public/assets
38
+
39
+ # Ignore CI service files.
40
+ /.github
41
+
42
+ # Ignore Kamal files.
43
+ /config/deploy*.yml
44
+ /.kamal
45
+
46
+ # Ignore development files
47
+ /.devcontainer
48
+
49
+ # Ignore Docker-related files
50
+ /.dockerignore
51
+ /Dockerfile*
@@ -0,0 +1,12 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: bundler
4
+ directory: "/"
5
+ schedule:
6
+ interval: daily
7
+ open-pull-requests-limit: 10
8
+ - package-ecosystem: github-actions
9
+ directory: "/"
10
+ schedule:
11
+ interval: daily
12
+ open-pull-requests-limit: 10
@@ -0,0 +1,55 @@
1
+ name: CI
2
+
3
+ on:
4
+ pull_request:
5
+ push:
6
+ branches: [ main ]
7
+
8
+ jobs:
9
+ scan_ruby:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: .ruby-version
20
+ bundler-cache: true
21
+
22
+ - name: Scan for common Rails security vulnerabilities using static analysis
23
+ run: bin/brakeman --no-pager
24
+
25
+ scan_js:
26
+ runs-on: ubuntu-latest
27
+
28
+ steps:
29
+ - name: Checkout code
30
+ uses: actions/checkout@v4
31
+
32
+ - name: Set up Ruby
33
+ uses: ruby/setup-ruby@v1
34
+ with:
35
+ ruby-version: .ruby-version
36
+ bundler-cache: true
37
+
38
+ - name: Scan for security vulnerabilities in JavaScript dependencies
39
+ run: bin/importmap audit
40
+
41
+ lint:
42
+ runs-on: ubuntu-latest
43
+ steps:
44
+ - name: Checkout code
45
+ uses: actions/checkout@v4
46
+
47
+ - name: Set up Ruby
48
+ uses: ruby/setup-ruby@v1
49
+ with:
50
+ ruby-version: .ruby-version
51
+ bundler-cache: true
52
+
53
+ - name: Lint code for consistent style
54
+ run: bin/rubocop -f github
55
+
@@ -0,0 +1,87 @@
1
+ # See https://help.github.com/articles/ignoring-files for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile '~/.gitignore_global'
6
+
7
+ # Ignore bundler config.
8
+ /.bundle
9
+
10
+ # Ignore all environment files (dotenv).
11
+ /.env*
12
+ !/.env*.enc
13
+
14
+ # Ignore all logfiles and tempfiles.
15
+ /log/*
16
+ /tmp/*
17
+ !/log/.keep
18
+ !/tmp/.keep
19
+
20
+ # Ignore pidfiles, but keep the directory.
21
+ /tmp/pids/*
22
+ !/tmp/pids/
23
+ !/tmp/pids/.keep
24
+
25
+ /tmp/cache/*
26
+ !/tmp/cache/
27
+ !/tmp/cache/.keep
28
+
29
+ # Ignore storage (uploaded files in development and any SQLite databases).
30
+ /storage/*
31
+ !/storage/.keep
32
+ /tmp/storage/*
33
+ !/tmp/storage/
34
+ !/tmp/storage/.keep
35
+
36
+ /public/assets
37
+
38
+ # Ignore master key for decrypting credentials and more.
39
+ /config/master.key
40
+
41
+ # Ignore database files
42
+ /db/*.sqlite3
43
+ /db/*.sqlite3-*
44
+
45
+ # Ignore test files
46
+ /coverage/
47
+
48
+ # Ignore node_modules
49
+ /node_modules
50
+
51
+ # Ignore yarn files
52
+ /yarn-error.log
53
+ yarn-debug.log*
54
+ .yarn-integrity
55
+
56
+ # Ignore editor and system files
57
+ .DS_Store
58
+ *~
59
+ .*.sw?
60
+ .#*
61
+ \#*#
62
+ /.emacs.desktop
63
+ /.emacs.desktop.lock
64
+ *.elc
65
+ auto-save-list
66
+ tramp
67
+ .\#*
68
+
69
+ # Ignore RubyMine files
70
+ /.idea
71
+
72
+ # Ignore Sublime Text files
73
+ /*.sublime*
74
+
75
+ # Ignore VS Code files
76
+ .vscode/
77
+
78
+ # Ignore vim swap files
79
+ *.swp
80
+ *.swo
81
+
82
+ # Ignore generated files
83
+ /public/packs
84
+ /public/packs-test
85
+ /public/vite*
86
+ /app/assets/builds/*
87
+ !/app/assets/builds/.keep
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ echo "Docker set up on $KAMAL_HOSTS..."
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ echo "Booted app version $KAMAL_VERSION on $KAMAL_HOSTS..."
@@ -0,0 +1,14 @@
1
+ #!/bin/sh
2
+
3
+ # A sample post-deploy hook
4
+ #
5
+ # These environment variables are available:
6
+ # KAMAL_RECORDED_AT
7
+ # KAMAL_PERFORMER
8
+ # KAMAL_VERSION
9
+ # KAMAL_HOSTS
10
+ # KAMAL_ROLES (if set)
11
+ # KAMAL_DESTINATION (if set)
12
+ # KAMAL_RUNTIME
13
+
14
+ echo "$KAMAL_PERFORMER deployed $KAMAL_VERSION to $KAMAL_DESTINATION in $KAMAL_RUNTIME seconds"
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ echo "Rebooted kamal-proxy on $KAMAL_HOSTS"
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ echo "Booting app version $KAMAL_VERSION on $KAMAL_HOSTS..."
@@ -0,0 +1,51 @@
1
+ #!/bin/sh
2
+
3
+ # A sample pre-build hook
4
+ #
5
+ # Checks:
6
+ # 1. We have a clean checkout
7
+ # 2. A remote is configured
8
+ # 3. The branch has been pushed to the remote
9
+ # 4. The version we are deploying matches the remote
10
+ #
11
+ # These environment variables are available:
12
+ # KAMAL_RECORDED_AT
13
+ # KAMAL_PERFORMER
14
+ # KAMAL_VERSION
15
+ # KAMAL_HOSTS
16
+ # KAMAL_ROLES (if set)
17
+ # KAMAL_DESTINATION (if set)
18
+
19
+ if [ -n "$(git status --porcelain)" ]; then
20
+ echo "Git checkout is not clean, aborting..." >&2
21
+ git status --porcelain >&2
22
+ exit 1
23
+ fi
24
+
25
+ first_remote=$(git remote)
26
+
27
+ if [ -z "$first_remote" ]; then
28
+ echo "No git remote set, aborting..." >&2
29
+ exit 1
30
+ fi
31
+
32
+ current_branch=$(git branch --show-current)
33
+
34
+ if [ -z "$current_branch" ]; then
35
+ echo "Not on a git branch, aborting..." >&2
36
+ exit 1
37
+ fi
38
+
39
+ remote_head=$(git ls-remote $first_remote --tags $current_branch | cut -f1)
40
+
41
+ if [ -z "$remote_head" ]; then
42
+ echo "Branch not pushed to remote, aborting..." >&2
43
+ exit 1
44
+ fi
45
+
46
+ if [ "$KAMAL_VERSION" != "$remote_head" ]; then
47
+ echo "Version ($KAMAL_VERSION) does not match remote HEAD ($remote_head), aborting..." >&2
48
+ exit 1
49
+ fi
50
+
51
+ exit 0
@@ -0,0 +1,47 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # A sample pre-connect check
4
+ #
5
+ # Warms DNS before connecting to hosts in parallel
6
+ #
7
+ # These environment variables are available:
8
+ # KAMAL_RECORDED_AT
9
+ # KAMAL_PERFORMER
10
+ # KAMAL_VERSION
11
+ # KAMAL_HOSTS
12
+ # KAMAL_ROLES (if set)
13
+ # KAMAL_DESTINATION (if set)
14
+ # KAMAL_RUNTIME
15
+
16
+ hosts = ENV["KAMAL_HOSTS"].split(",")
17
+ results = nil
18
+ max = 3
19
+
20
+ elapsed = Benchmark.realtime do
21
+ results = hosts.map do |host|
22
+ Thread.new do
23
+ tries = 1
24
+
25
+ begin
26
+ Socket.getaddrinfo(host, 0, Socket::AF_UNSPEC, Socket::SOCK_STREAM, nil, Socket::AI_CANONNAME)
27
+ rescue SocketError
28
+ if tries < max
29
+ puts "Retrying DNS warmup: #{host}"
30
+ tries += 1
31
+ sleep rand
32
+ retry
33
+ else
34
+ puts "DNS warmup failed: #{host}"
35
+ host
36
+ end
37
+ end
38
+
39
+ tries
40
+ end
41
+ end.map(&:value)
42
+ end
43
+
44
+ retries = results.sum - hosts.size
45
+ nopes = results.count { |r| r == max }
46
+
47
+ puts "Prewarmed %d DNS lookups in %.2f sec: %d retries, %d failures" % [ hosts.size, elapsed, retries, nopes ]