Class: Ligarb::GithubReview
- Inherits:
-
Object
- Object
- Ligarb::GithubReview
- Defined in:
- lib/ligarb/github_review.rb
Overview
Sets up the GitHub-based review scaffolding (.github/ + SETUP.md) in a project — the ‘ligarb setup-github-review` command. This is pure file copying: ligarb never calls Claude or GitHub at runtime. The templates are classified into layers so a future option could split them apart:
- generic layer : works without Claude (Pages deploy, build check, forms)
- claude layer : opt-in Claude integration (issue/PR handlers, SETUP.md)
Re-running OVERWRITES the generated files so a project can follow upstream template changes (e.g. after a ligarb upgrade). The user’s own book.yml is never overwritten. Since projects are git repos, ‘git diff` is the safety net for reviewing/reverting changes after a re-sync.
Defined Under Namespace
Classes: Result
Constant Summary collapse
- TEMPLATE_DIR =
File.("../../templates/github_review", __dir__)
- GENERIC_FILES =
Generic layer: no Claude dependency.
%w[ .github/workflows/deploy-book.yml .github/workflows/build-check.yml .github/ISSUE_TEMPLATE/book-feedback.yml .github/ISSUE_TEMPLATE/config.yml ].freeze
- CLAUDE_FILES =
Claude integration layer: opt-in.
%w[ .github/workflows/claude-feedback.yml .github/workflows/claude-pr-mention.yml SETUP.md SETUP.sh ].freeze
- TEMPLATE_FILES =
(GENERIC_FILES + CLAUDE_FILES).freeze
Class Method Summary collapse
-
.run(directory = nil, owner: nil) ⇒ Object
‘ligarb setup-github-review [DIR]` entry point.
Instance Method Summary collapse
-
#create_readme_if_absent ⇒ Object
Creates a project README.md that links to the published GitHub Pages site, but only when one does not already exist (the reader’s own README is never overwritten).
-
#enable_in_book_yml ⇒ Object
Ensures ‘github_review.enabled: true` is present in book.yml so the reader feedback UI activates (once `repository` is also set).
-
#ensure_repository_in_book_yml ⇒ Object
Seeds a default ‘repository:` in book.yml when it has none, guessing github.com/<owner>/<dir-name>.
-
#ensure_site_url_in_book_yml ⇒ Object
Seeds a default ‘site_url:` in book.yml when it has none, deriving the GitHub Pages URL from `repository`.
-
#generate ⇒ Object
Writes all template files into the project, substituting __OWNER__ / __REPO__ from book.yml’s ‘repository:`.
-
#initialize(target, owner: nil) ⇒ GithubReview
constructor
A new instance of GithubReview.
-
#pages_url(owner, repo) ⇒ Object
GitHub Pages URL for a repo.
- #print_notice(result, repository:, site_url:, enabled:, readme:) ⇒ Object
Constructor Details
#initialize(target, owner: nil) ⇒ GithubReview
Returns a new instance of GithubReview.
66 67 68 69 |
# File 'lib/ligarb/github_review.rb', line 66 def initialize(target, owner: nil) @target = File.(target) @owner = owner end |
Class Method Details
.run(directory = nil, owner: nil) ⇒ Object
‘ligarb setup-github-review [DIR]` entry point. Sets up the scaffolding in an existing ligarb project (book.yml must exist), enables the reader feedback UI in book.yml, and prints the remaining manual-setup steps. Safe to re-run to pull in updated templates (generated files are overwritten; book.yml is not).
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/ligarb/github_review.rb', line 46 def self.run(directory = nil, owner: nil) target = File.(directory || ".") unless File.exist?(File.join(target, "book.yml")) $stderr.puts "Error: book.yml not found in #{target}" $stderr.puts "Run 'ligarb init' or 'ligarb write' first, then set up the GitHub review scaffolding." exit 1 end reviewer = new(target, owner: owner) # book.yml edits must run BEFORE generate so the templates (SETUP.sh, # issue forms, README) are substituted with the resolved repository. repository = reviewer.ensure_repository_in_book_yml site_url = reviewer.ensure_site_url_in_book_yml enabled = reviewer.enable_in_book_yml readme = reviewer.create_readme_if_absent result = reviewer.generate reviewer.print_notice(result, repository: repository, site_url: site_url, enabled: enabled, readme: readme) end |
Instance Method Details
#create_readme_if_absent ⇒ Object
Creates a project README.md that links to the published GitHub Pages site, but only when one does not already exist (the reader’s own README is never overwritten). Returns :created or :present.
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/ligarb/github_review.rb', line 177 def create_readme_if_absent readme = File.join(@target, "README.md") return :present if File.exist?(readme) owner, repo = extract_owner_repo pages = owner && repo ? pages_url(owner, repo) : "https://__OWNER__.github.io/__REPO__/" issues = owner && repo ? "https://github.com/#{owner}/#{repo}/issues/new?template=book-feedback.yml" \ : "https://github.com/__OWNER__/__REPO__/issues/new?template=book-feedback.yml" title = book_title.to_s.empty? ? "Book" : book_title File.write(readme, <<~MD) # #{title} 📖 **公開版(GitHub Pages)**: #{pages} この本は [ligarb](https://github.com/ko1/ligarb) で生成しています。 ## フィードバック 本文の誤り・わかりにくい点・疑問は [Issue](#{issues}) からどうぞ。 公開ページでは本文を選択して「Report as issue」からも送れます。 ## ローカルでビルド ```bash ligarb build # build/index.html を生成 ligarb serve # ローカルプレビュー ``` セットアップ手順は [SETUP.md](SETUP.md) を参照してください。 MD :created end |
#enable_in_book_yml ⇒ Object
Ensures ‘github_review.enabled: true` is present in book.yml so the reader feedback UI activates (once `repository` is also set). Appends the key only when absent, preserving existing formatting/comments. Returns :added, :present, or :unsupported (translations hub / unparsable).
104 105 106 107 108 109 110 111 112 113 |
# File 'lib/ligarb/github_review.rb', line 104 def enable_in_book_yml book_yml = File.join(@target, "book.yml") data = YAML.safe_load_file(book_yml) return :unsupported unless data.is_a?(Hash) return :present if data.key?("github_review") content = File.read(book_yml).rstrip File.write(book_yml, "#{content}\n\ngithub_review:\n enabled: true\n") :added end |
#ensure_repository_in_book_yml ⇒ Object
Seeds a default ‘repository:` in book.yml when it has none, guessing github.com/<owner>/<dir-name>. <owner> is the –owner/–user flag when given, else $USER. This drives __OWNER__/__REPO__ substitution and the GH Pages link; the user edits it if the guess is wrong. Returns :added, :present, or :unsupported. (@default_repository is set to the guessed URL when :added, for the notice.)
Aborts if –owner was given but book.yml already has a ‘repository:`, since we never rewrite an existing repository — the user edits it themselves.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/ligarb/github_review.rb', line 124 def ensure_repository_in_book_yml book_yml = File.join(@target, "book.yml") data = YAML.safe_load_file(book_yml) return :unsupported unless data.is_a?(Hash) if data.key?("repository") if @owner abort "Error: --owner was given but book.yml already has 'repository: #{data["repository"]}'.\n" \ "Edit 'repository:' in book.yml directly to change the owner, then re-run setup-github-review." end return :present end owner = @owner || ENV["USER"] || ENV["USERNAME"] || "your-github-account" @default_repository = "https://github.com/#{owner}/#{File.basename(@target)}" content = File.read(book_yml).rstrip File.write(book_yml, %(#{content}\n\nrepository: "#{@default_repository}"\n)) :added end |
#ensure_site_url_in_book_yml ⇒ Object
Seeds a default ‘site_url:` in book.yml when it has none, deriving the GitHub Pages URL from `repository`. Drives og:url / canonical in the build output; the user edits it for custom domains or other hosting. Returns :added, :present, or :skipped (when no GitHub repository to derive from). (@default_site_url is set to the derived URL when :added, for the notice.)
148 149 150 151 152 153 154 155 156 157 158 159 160 161 |
# File 'lib/ligarb/github_review.rb', line 148 def ensure_site_url_in_book_yml book_yml = File.join(@target, "book.yml") data = YAML.safe_load_file(book_yml) return :skipped unless data.is_a?(Hash) return :present if data.key?("site_url") owner, repo = extract_owner_repo return :skipped unless owner && repo @default_site_url = pages_url(owner, repo) content = File.read(book_yml).rstrip File.write(book_yml, %(#{content}\n\nsite_url: "#{@default_site_url}"\n)) :added end |
#generate ⇒ Object
Writes all template files into the project, substituting __OWNER__ / __REPO__ from book.yml’s ‘repository:`. Existing files are OVERWRITTEN so a project can follow upstream template changes; only files whose content is already identical are left untouched. Returns a Result listing created/updated/unchanged files.
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/ligarb/github_review.rb', line 76 def generate owner, repo = extract_owner_repo created = [] updated = [] unchanged = [] TEMPLATE_FILES.each do |rel| dest = File.join(@target, rel) content = render(rel, File.read(File.join(TEMPLATE_DIR, rel)), owner, repo) if !File.exist?(dest) write_file(dest, content) created << rel elsif File.read(dest) == content unchanged << rel else write_file(dest, content) updated << rel end end Result.new(created: created, updated: updated, unchanged: unchanged) end |
#pages_url(owner, repo) ⇒ Object
GitHub Pages URL for a repo. A repository named “<owner>.github.io” is the owner’s user/org site served at the domain root; everything else is a project site served under /<repo>/.
166 167 168 169 170 171 172 |
# File 'lib/ligarb/github_review.rb', line 166 def pages_url(owner, repo) if repo.downcase == "#{owner.downcase}.github.io" "https://#{owner}.github.io/" else "https://#{owner}.github.io/#{repo}/" end end |
#print_notice(result, repository:, site_url:, enabled:, readme:) ⇒ Object
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/ligarb/github_review.rb', line 211 def print_notice(result, repository:, site_url:, enabled:, readme:) puts "Set up GitHub review scaffolding in #{@target}:" result.created.each { |path| puts " created #{path}" } result.updated.each { |path| puts " updated #{path}" } puts " created README.md (with the GitHub Pages link)" if readme == :created case repository when :added then puts " updated book.yml (repository: #{@default_repository})" end case site_url when :added then puts " updated book.yml (site_url: #{@default_site_url})" end case enabled when :added then puts " updated book.yml (github_review.enabled: true)" when :present then puts " kept book.yml github_review setting" end unless result.unchanged.empty? puts " unchanged #{result.unchanged.size} file(s) already up to date" end if result.updated.any? puts puts "Note: existing scaffolding files were overwritten with the latest" puts "templates. Review with 'git diff' and revert any local edits you" puts "want to keep." end puts puts "Next: edit 'repository:' in book.yml if the guess is wrong, then run" puts "the gh CLI quickstart:" puts " bash SETUP.sh # repo create + secret + Pages + permissions + labels" puts puts "It still needs a token (see SETUP.md): generate one with" puts "'claude setup-token' before running SETUP.sh (it prompts for it)." end |