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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/beam_up.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ module BeamUp
"aws_s3" => Providers::AwsS3,
"bunny" => Providers::Bunny,
"digital_ocean_spaces" => Providers::DigitalOceanSpaces,
"github_pages" => Providers::GitHubPages,
"hetzner" => Providers::Hetzner,
"neocities" => Providers::Neocities,
"netlify" => Providers::Netlify,
Expand Down
1 change: 1 addition & 0 deletions lib/beam_up/providers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require "beam_up/providers/aws_s3"
require "beam_up/providers/bunny"
require "beam_up/providers/digital_ocean_spaces"
require "beam_up/providers/github_pages"
require "beam_up/providers/hetzner"
require "beam_up/providers/neocities"
require "beam_up/providers/netlify"
Expand Down
117 changes: 117 additions & 0 deletions lib/beam_up/providers/github_pages.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
# frozen_string_literal: true

require "tmpdir"

module BeamUp
module Providers
class GitHubPages < Base
class Config
def self.config_keys = %w[token branch]

attr_accessor :token, :branch

def initialize
@branch = "gh-pages"
end

def with(options)
self.token = options[:token]
self.branch = options[:branch] || "gh-pages"
self
end

def validate! = nil
end

def deploy!(path)
@path = path

verify_git_installed
owner, repo = parse_remote_url(current_remote_url)

Dir.mktmpdir do |directory|
copy_files_to(directory)
run_git(directory, "init")
add_origin_remote(directory, owner, repo)
git_commit(directory)
git_push(directory)
end

Result.new(
provider: "GitHub Pages",
deploy_id: Time.now.to_i.to_s,
url: pages_url(owner, repo)
)
rescue => error
Result.new(provider: "GitHub Pages", error: error.message)
end

private

def verify_git_installed
raise ConfigurationError, "Git must be installed to deploy to GitHub Pages" unless system("git", "--version", out: File::NULL, err: File::NULL)
end

def current_remote_url
output = `git remote get-url origin 2>/dev/null`.strip
raise ConfigurationError, "Could not detect GitHub remote. Ensure you are in a git repository with an origin remote." if output.empty?

output
end

def parse_remote_url(url)
if url.start_with?("https://")
parts = url.delete_prefix("https://").delete_prefix("github.com/").split("/")
owner = parts[0]
repo = parts[1].to_s.delete_suffix(".git").delete_suffix("/")
elsif url.start_with?("git@github.com:")
parts = url.delete_prefix("git@github.com:").split("/")
owner = parts[0]
repo = parts[1].to_s.delete_suffix(".git").delete_suffix("/")
else
raise ConfigurationError, "Unsupported remote URL format: #{url}"
end

[owner, repo]
end

def copy_files_to(directory)
files_to_deploy.each do |file|
relative_path = file.sub("#{@path}/", "")
target_path = File.join(directory, relative_path)

FileUtils.mkdir_p(File.dirname(target_path))
FileUtils.cp(file, target_path)
end
end

def add_origin_remote(directory, owner, repo)
remote_url = if @configuration.token
"https://#{@configuration.token}@github.com/#{owner}/#{repo}.git"
else
"https://github.com/#{owner}/#{repo}.git"
end

run_git(directory, "remote", "add", "origin", remote_url)
end

def git_commit(directory)
run_git(directory, "add", ".")
run_git(directory, "commit", "-m", "Deploy #{Time.now}")
end

def git_push(directory)
run_git(directory, "push", "--force", "origin", "HEAD:#{@configuration.branch}")
end

def run_git(dir, *args)
command = ["git", "-C", dir, *args]
result = system(*command)

raise DeploymentError, "Git command failed: #{command.join(" ")}" unless result
end

def pages_url(owner, repo) = "https://#{owner}.github.io/#{repo}/"
end
end
end
57 changes: 57 additions & 0 deletions test/beam_up/providers/github_pages_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

require "test_helper"

module BeamUp
module Providers
class GitHubPagesTest < Minitest::Test
def test_config_defaults
config = GitHubPages::Config.new

assert_equal "gh-pages", config.branch
assert_nil config.token
end

def test_config_accepts_custom_branch_and_token
config = GitHubPages::Config.new
config.with(token: "ghp_secret", branch: "docs")

assert_equal "ghp_secret", config.token
assert_equal "docs", config.branch
end

def test_parse_https_remote_url
provider = GitHubPages.new(GitHubPages::Config.new)

owner, repo = provider.send(:parse_remote_url, "https://github.com/railsdesigner/beam_up.git")

assert_equal "railsdesigner", owner
assert_equal "beam_up", repo
end

def test_parse_https_remote_url_with_trailing_slash
provider = GitHubPages.new(GitHubPages::Config.new)

owner, repo = provider.send(:parse_remote_url, "https://github.com/railsdesigner/beam_up/")

assert_equal "railsdesigner", owner
assert_equal "beam_up", repo
end

def test_parse_ssh_remote_url
provider = GitHubPages.new(GitHubPages::Config.new)

owner, repo = provider.send(:parse_remote_url, "git@github.com:railsdesigner/beam_up.git")

assert_equal "railsdesigner", owner
assert_equal "beam_up", repo
end

def test_pages_url
provider = GitHubPages.new(GitHubPages::Config.new)

assert_equal "https://railsdesigner.github.io/beam_up/", provider.send(:pages_url, "railsdesigner", "beam_up")
end
end
end
end