ferryboat 0.1.1 → 0.1.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: aa70498d8da44c4794ae00a29448c7d601ff41e81da201c782708145ae00accb
4
- data.tar.gz: d5c44d72d8a1e96b07e1b6c29414c3575aaa4bbbd87d6c0ede793f5a38b12507
3
+ metadata.gz: fdc6d5593bb5c8e80755aa06380ddd8f3096d1569d7a7fc5561f9c943e9c9fc3
4
+ data.tar.gz: cdbb2b13faabcd143ba1c38b2a0571c6bb384a7b582cc7f7a72239b74b0c69ce
5
5
  SHA512:
6
- metadata.gz: ac33e17fb7b363c51e728cec591618c42145acbac25122685a3d3ddb02a8cc8f564c8d213eaa79a365002658c70577749734120dbeb70b114f931c15bfefc69b
7
- data.tar.gz: d9cc8fc64f0d03a93a920d99f29eb6682d34f472edef567e7c19640c6833a47963f0a0377252e29588075c8f8aa97fa68b6da17ac57c77ceb3ac87a4ec98a078
6
+ metadata.gz: 349532f647384780b9c39d9753589139aeec49067399b507b0d20b72574afdca1e2a46a8bd878d676027bb87f0ce7f7b8e4fed8c883882bd4cc86384d75636ee
7
+ data.tar.gz: 705168fb7067e2cb0a6cb942fe8d558aa8026459f48c2f4c2f66e47d46d40da94418aa41802e08f25ca09da4ce2950734450ae8351ec124f8766ac54fceac635
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Ferryboat ⚓️
2
2
 
3
- **Ferryboat** is a lightweight deployment tool built by **21tycoons** for teams who want **zero-downtime deployments** without the complexity of Kubernetes or heavyweight DevOps stacks.
3
+ **Ferryboat** is a lightweight deployment tool built by **21tycoons** for teams who want **zero-downtime deployments** for marketing/static sites without the complexity of Kubernetes or heavyweight DevOps stacks.
4
4
 
5
5
  It’s designed for marketing sites, micro-apps, and fast-moving projects that need **confidence in production** while staying **simple, portable, and developer-friendly**.
6
6
 
@@ -12,7 +12,7 @@ It’s designed for marketing sites, micro-apps, and fast-moving projects that n
12
12
  - **Staging environments baked in**
13
13
  - **Lightweight backups** of container volumes
14
14
  - **GitHub integration** for pulling and building images
15
- - **Simple CLI** powered by Thor
15
+ - **Simple CLI**
16
16
  - **Config-driven** via `ferryboat.yml`
17
17
 
18
18
  ---
data/bin/console ADDED
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "bundler/setup"
5
+ require "ferryboat"
6
+
7
+ # You can add fixtures and/or initialization code here to make experimenting
8
+ # with your gem easier. You can also use a different console, if you like.
9
+
10
+ require "irb"
11
+ IRB.start(__FILE__)
data/bin/ferryboat ADDED
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $stdout.sync = true
5
+
6
+ # Quiet thread exceptions
7
+ Thread.report_on_exception = false
8
+
9
+ # Be nice on Ctrl-C and TERM
10
+ Signal.trap("INT") { exit 0 }
11
+ Signal.trap("TERM") { exit 0 }
12
+ Signal.trap("PIPE") { exit 0 } rescue nil
13
+
14
+ begin
15
+ require "ferryboat"
16
+ require "ferryboat/cli" # explicit for reliability
17
+ rescue LoadError => e
18
+ warn "ferryboat: failed to load library: #{e.message}"
19
+ warn e.backtrace.join("\n") if ENV["FERRY_DEBUG"] == "1"
20
+ exit 1
21
+ end
22
+
23
+ begin
24
+ Ferryboat::Cli.start(ARGV)
25
+ rescue SystemExit => e
26
+ # Respect Thor's exit codes
27
+ exit e.status
28
+ rescue => e
29
+ warn "ferryboat: #{e.message}"
30
+ warn e.backtrace.join("\n") if ENV["FERRY_DEBUG"] == "1"
31
+ exit 1
32
+ end
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
File without changes
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "yaml"
4
+
5
+ module Ferryboat
6
+ class Config
7
+ attr_reader :env, :service, :image_repo, :domain, :host,
8
+ :provider, :git_url, :git_branch,
9
+ :health_path, :health_timeout, :detect_timeout,
10
+ :auto_backup
11
+
12
+ REQUIRED_KEYS = %i[service image_repo domain].freeze
13
+
14
+ def self.from_env(env: ENV.fetch("FERRY_ENV", "production"))
15
+ new(
16
+ env: env,
17
+ service: ENV.fetch("FERRY_SERVICE", nil),
18
+ image_repo: ENV.fetch("FERRY_IMAGE", nil),
19
+ domain: ENV.fetch("FERRY_DOMAIN", nil),
20
+ host: ENV.fetch("FERRY_HOST", "localhost"),
21
+ provider: ENV.fetch("FERRY_PROVIDER", "docker"), # docker|kamal
22
+ git_url: ENV["GIT_URL"],
23
+ git_branch: ENV.fetch("GIT_BRANCH", "main"),
24
+ health_path: ENV.fetch("FERRY_HEALTH_PATH", "/up"),
25
+ health_timeout: Integer(ENV.fetch("FERRY_HEALTH_TIMEOUT", "120")),
26
+ detect_timeout: Integer(ENV.fetch("FERRY_TRAEFIK_DETECT_TIMEOUT", "60")),
27
+ auto_backup: ENV["FERRY_AUTO_BACKUP"] == "true"
28
+ )
29
+ end
30
+
31
+ # Optional YAML loader (keeps env override semantics)
32
+ def self.from_file(path, env: "production")
33
+ data = YAML.load_file(path)
34
+ cfg = (data[env] || {})
35
+ new(
36
+ env: env,
37
+ service: ENV["FERRY_SERVICE"] || cfg["service"],
38
+ image_repo: ENV["FERRY_IMAGE"] || cfg["image_repo"] || cfg["docker_registry"],
39
+ domain: ENV["FERRY_DOMAIN"] || cfg["domain"],
40
+ host: ENV["FERRY_HOST"] || cfg["host"] || "localhost",
41
+ provider: ENV["FERRY_PROVIDER"] || cfg["provider"] || "docker",
42
+ git_url: ENV["GIT_URL"] || cfg["git_url"],
43
+ git_branch: ENV["GIT_BRANCH"] || cfg["git_branch"] || "main",
44
+ health_path: ENV["FERRY_HEALTH_PATH"] || cfg["health_path"] || "/up",
45
+ health_timeout: Integer(ENV["FERRY_HEALTH_TIMEOUT"] || cfg["health_timeout"] || 120),
46
+ detect_timeout: Integer(ENV["FERRY_TRAEFIK_DETECT_TIMEOUT"] || cfg["detect_timeout"] || 60),
47
+ auto_backup: (ENV["FERRY_AUTO_BACKUP"] || cfg["auto_backup"]).to_s == "true"
48
+ )
49
+ end
50
+
51
+ def initialize(env:, service:, image_repo:, domain:, host:, provider:, git_url:, git_branch:, health_path:, health_timeout:, detect_timeout:, auto_backup:)
52
+ @env, @service, @image_repo, @domain = env, service, image_repo, domain
53
+ @host, @provider = host, provider
54
+ @git_url, @git_branch = git_url, git_branch
55
+ @health_path, @health_timeout, @detect_timeout = health_path, health_timeout, detect_timeout
56
+ @auto_backup = auto_backup
57
+ validate!
58
+ end
59
+
60
+ def validate!
61
+ missing = []
62
+ missing << :service if blank?(service)
63
+ missing << :image_repo if blank?(image_repo)
64
+ missing << :domain if blank?(domain)
65
+ return true if missing.empty?
66
+ raise ArgumentError, "Missing required config: #{missing.join(', ')}"
67
+ end
68
+
69
+ def provider_runner
70
+ case provider
71
+ when "kamal" then Ferryboat::Deployer::KamalRunner.new
72
+ when "docker" then Ferryboat::Deployer::DockerRunner.new
73
+ else raise ArgumentError, "Unknown provider: #{provider.inspect}"
74
+ end
75
+ end
76
+
77
+ def to_h
78
+ {
79
+ env: env, service: service, image_repo: image_repo, domain: domain,
80
+ host: host, provider: provider, git_url: git_url, git_branch: git_branch,
81
+ health_path: health_path, health_timeout: health_timeout,
82
+ detect_timeout: detect_timeout, auto_backup: auto_backup
83
+ }
84
+ end
85
+
86
+ private
87
+
88
+ def blank?(s) = s.nil? || s.to_s.strip.empty?
89
+ end
90
+ end
File without changes
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Ferryboat
4
+ # Wraps Kamal CLI commands for remote execution
5
+ class Kamal
6
+ def initialize(app: nil, reuse: true)
7
+ @app = app || ENV.fetch("FERRY_SERVICE")
8
+ @reuse = reuse
9
+ end
10
+
11
+ # run a raw kamal command
12
+ def run(*args)
13
+ cmd = ["kamal"]
14
+ cmd << "app" << "exec"
15
+ cmd << "--reuse" if @reuse
16
+ cmd << "--app" << @app if @app
17
+ cmd << "--" << "/bin/sh" << "-lc" << %("#{args.join(' ')}")
18
+ sh cmd.join(" ")
19
+ end
20
+
21
+ # convenience: docker subcommand
22
+ def docker(*args)
23
+ run("docker", *args)
24
+ end
25
+
26
+ private
27
+
28
+ def sh(cmd)
29
+ puts "→ #{cmd}"
30
+ system(cmd)
31
+ end
32
+ end
33
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ferryboat
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.3"
5
5
  end
data/lib/ferryboat.rb CHANGED
@@ -3,6 +3,4 @@
3
3
  require_relative "ferryboat/version"
4
4
 
5
5
  module Ferryboat
6
- class Error < StandardError; end
7
- # Your code goes here...
8
6
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ferryboat
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - 21tycoons
8
- bindir: exe
8
+ bindir: bin
9
9
  cert_chain: []
10
- date: 2025-08-17 00:00:00.000000000 Z
10
+ date: 2025-08-20 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: thor
@@ -38,18 +38,26 @@ dependencies:
38
38
  - !ruby/object:Gem::Version
39
39
  version: '1.0'
40
40
  description: |
41
- Ferryboat is a deployment solution focused on simplicity and reliability.
41
+ Ferryboat is a deployment solution for marketing/static sites focused on simplicity and reliability.
42
42
  It supports zero-downtime rollouts, staging environments, and basic volume
43
43
  backups. Designed to work with Docker and SSH, it helps teams deliver code
44
44
  safely to production without unnecessary complexity.
45
45
  email:
46
46
  - liroy@tycooncrm.com
47
- executables: []
47
+ executables:
48
+ - ferryboat
48
49
  extensions: []
49
50
  extra_rdoc_files: []
50
51
  files:
51
52
  - README.md
53
+ - bin/console
54
+ - bin/ferryboat
55
+ - bin/setup
52
56
  - lib/ferryboat.rb
57
+ - lib/ferryboat/cli.rb
58
+ - lib/ferryboat/config.rb
59
+ - lib/ferryboat/deployer.rb
60
+ - lib/ferryboat/kamal.rb
53
61
  - lib/ferryboat/version.rb
54
62
  homepage: https://github.com/21tycoons/ferryboat
55
63
  licenses:
@@ -71,5 +79,5 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
79
  requirements: []
72
80
  rubygems_version: 3.6.5
73
81
  specification_version: 4
74
- summary: Lightweight zero-downtime deployment tool.
82
+ summary: Lightweight zero-downtime deployment tool for marketing/static sites.
75
83
  test_files: []