New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Spike out jekyll-remote-theme #1
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks really good!! Nice work 🎉
lib/jekyll-remote-theme/cloner.rb
Outdated
return false | ||
end | ||
|
||
Jekyll.logger.info "Remote theme: ", "Cloning into #{git_url}" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cloning into path, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ooph. Verified locally and this is currently the opposite of how Git is implemented (and users would expect). Will update.
lib/jekyll-remote-theme/cloner.rb
Outdated
|
||
private | ||
|
||
def clone_command |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In safe mode, we'll want to disable any credentials access and restrict to the https protocol only.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's restricted to HTTPS because the use can only pass the name + owner + ref. We lock it to https://github.com/*
Some additional context... Current implementationAfter several iterations and discussions with @parkr the process is as follows:
Other considerationsThe first implementations stored the site in a Since we don't need the history, and don't want the checkout to live where it can be committed, we opted for |
This is awesome! 😮:+1: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very, very nice! Download, extract, wire up. Cleanly done. Just a few notes for some nits (including some suggestions for a later iteration around optimizing for bad shelling-out environments) but no blockers near as I can tell.
One thing I might recommend is a simple smoke test. You have excellent unit tests. It'd be great to have a simple script and a fixture jekyll site that just runs jekyll build -s fixture_site -d output
and checks that the theme is properly loaded etc. The actual Jekyll integration isn't well-tested unless my 10PM head cold/flu brain is making my memory fuzzy.
Anyway, excellent work. ✨
jekyll-remote-theme.gemspec
Outdated
s.summary = "Jekyll plugin for building Jekyll sites with any GitHub-hosted theme" | ||
|
||
s.files = `git ls-files app lib`.split("\n") | ||
s.platform = Gem::Platform::RUBY |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is platform
required here? This might limit things...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/shrug
. Was part of the boilerplate. Removed via fa461f2.
@@ -0,0 +1,27 @@ | |||
require "jekyll" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you add the magic # frozen_string_literal: true
comment to the top of all your Ruby files? I'm surprised Jekyll 3.6's rubocop.yml file didn't include that...
Once that's done, you can get rid of the .freeze
calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Believe jekyll/jekyll#6444 was the reason it wasn't added. Added via 8cc5936.
lib/jekyll-remote-theme.rb
Outdated
autoload :VERSION, "jekyll-remote-theme/version" | ||
|
||
CONFIG_KEY = "remote_theme".freeze | ||
LOG_KEY = "Remmote Theme:".freeze |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remmote
class Downloader | ||
include RemoteTheme::Executor | ||
|
||
HOST = "https://codeload.github.com".freeze |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be useful to allow us to override these with environment variables? Maybe a later version.
return | ||
end | ||
|
||
download |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this fails, how will a user be told?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, if Executor gets a non-zero exit code, it raises a DownloadError and dumps stdout.
end | ||
|
||
it "extracts the theme" do | ||
expect("#{theme.root}/_layouts/default.html").to be_an_existing_file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
|
||
context "without a theme" do | ||
before { site.config["theme"] = nil } | ||
before { subject.munge! } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can these be part of the same before
block instead of having 2?
end | ||
|
||
context "without a theme" do | ||
before { site.config["theme"] = nil } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe this could be done via a let(:config)
?
RSpec.describe Jekyll::RemoteTheme::Theme do | ||
let(:owner) { "foo" } | ||
let(:name) { "bar" } | ||
let(:nwo) { "foo/bar" } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let(:nwo) { "#{owner}/#{name}" }
?
let(:nwo) { " FoO/bAr " } | ||
|
||
it "normalizes the nwo" do | ||
expect(subject.instance_variable_get("@raw_theme")).to eql("foo/bar") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we know for sure that codeload will respect these kinds of capitalization differences? E.g. my theme is BenBalter/foOOOO
but we request benbalter/fooooo
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. I tested and it's case insensitive.
This is so cool. Users gonna love this. Well done @benbalter One question though, how are theme dependencies handled? 📦📦📦📦 The typical use case I imagine for this (correct me if I'm wrong), is that one might want to try a few different themes without having to fork a repo or install anything. You just change the value for the One of the dependencies isn't met so here is what I got: Remmote Theme: Using theme benbalter/retlab
Liquid Exception: Liquid syntax error (/private/var/folders/4s/1tjg18y173934vzsz9lg3mf80000gn/T/jekyll-remote-theme-20171020-80204-1l6htmc/retlab-master/_includes/improve.html line 7): Unknown tag 'github_edit_link' included in /_layouts/page.html
jekyll 3.6.0 | Error: Liquid syntax error (/private/var/folders/4s/1tjg18y173934vzsz9lg3mf80000gn/T/jekyll-remote-theme-20171020-80204-1l6htmc/retlab-master/_includes/improve.html line 7): Unknown tag 'github_edit_link' included Hence my question: if Maybe this does not qualify for a For Jekyll users that don't host their site on GitHub Pages, should If you ask me, an optimal experience would be: Using remote theme: benbalter/retlab
Installing theme dependencies… |
@DirtyF great question. Right now, they're not. Since we're allowing any user-supplied theme, we have to treat the theme as untrusted, arbitrary user input. In order to determine dependencies, we'd have to parse/eval the Gemspec, which could lead to arbitrary code execution. In a subsequent version, we could theoretically use e.g., regex to determine dependencies, and auto require any whitelisted dependency. We likely won't be able to support arbitrary plugins given our current setup. Edit: For now, you'll have to add the dependencies to the config file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
*timeout_command, "curl", "--url", zip_url, "--output", zip_file.path, | ||
"--user-agent", USER_AGENT, "--fail", "--silent", "--show-error", | ||
] | ||
run_command(*cmd) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe for a later iteration, but retries here might be nice. A network blip could cause downloads to fail so giving this a rescue ExecutionError
with some recursion might be helpful to prevent these kinds of blips.
def download(tries: 3)
run_command(*cmd)
rescue ExecutionError => e
raise e if tries <= 0
download(tries: tries - 1)
end
❓
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a first pass at arbitrary/remote theme support for Jekyll (and hopefully eventually GitHub Pages).
Usage
in
_config.yml
addremote_theme: foo/bar
or
remote_theme: foo/bar@git_ref
What it does
ClonesDownloads and unzips the remote theme toa temporary directory and sets it as_theme
site.theme
Gotchas
theme
key, but the way the Site object is created, it'd raise a "dependency not found error". We could theoretically monkey patch, but I thoughtremote_theme
was a cleaner solution.(some of the test are still intended to go the other way)2. After the initial clone,_theme
exists in the source dir. This is fine, until that_theme
dir is committed and pushed, or the theme is update (meaning the two are out of sync. Potential workarounds: (1) warn if_theme
isn't in.gitignore
, (2) Do a fresh clone on each build (3) clone to a random temp dir outside of source./cc @parkr