Skip to content
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

Added first very basic widget downloader using gist github api #38

Closed

Conversation

JanStevens
Copy link
Contributor

@JanStevens JanStevens commented Nov 25, 2016

Allright, this is a first very basic implementation for downloading a gist and installing it as a widget. Current feature list:

  • Download all the files of the gist using Github Gist API
  • Specify the widget dir name (to prevent overwrites)
  • Asks before overwriting a file (using Mix.Generator.create_file)
  • Elixir files are seen as jobs and placed in the jobs dir

Example usage

 mix kitto.install --widget test_widget --gist JanStevens/0209a4a80cee782e5cdbe11a1e9bc393

Concerns / Ideas

  1. I did not try to update the package.json dependencies, what if multiple widgets specify different versions? I guess the best would be for a widget to have a README with important install instructions.
  2. Lots of assumptions and I'm a beginner elixir programmer so please feel free to add comments and suggestions to clean it up
  3. Comming from rails background: There are external packages (gems) that define hooks so they are included in the main project (assets). It would be easy to reuse mix dependency management so every widget can be a separate mix package? Kitto could then provide a skelleton widget structure.

@coveralls
Copy link

Coverage Status

Coverage decreased (-4.8%) to 75.481% when pulling 85a72d6 on playpasshq:feature/naive-widget-puller into 3f013d8 on kittoframework:master.

@davejlong
Copy link
Member

One of the things we talked about in #18 is to not have a different command for widgets and jobs, instead, if the file is an Elixir file, then treat it as a job (we can update it for hooks later). If it's an HTML or JS file, then make it a widget. This would shorten the command to just mix kitto.install ...

@JanStevens
Copy link
Contributor Author

Right I can easily add it

@zorbash
Copy link
Member

zorbash commented Nov 25, 2016

I think that a command like mix kitto.install should be reserved for a package manager-like thing. An alternative would be to have a different binary for the installer, something in the lines of kittoctl (see: https://github.com/operable/cogctl).

At the moment i feel fetching from gist should be explicit, like mix kitto.install --gist <gist_url> and it should handle both jobs and widgets.

@zorbash zorbash added this to the 0.3.0 milestone Nov 25, 2016
@zorbash
Copy link
Member

zorbash commented Nov 26, 2016

@JanStevens also make sure to run credo (mix credo) and have all checks pass.

@JanStevens
Copy link
Contributor Author

I've update the original MR to reflect recent changes:

  • Job's are now supported (any elixir file is treated as a job)
  • Using Mix.Generator.create_file so we ask before overwriting a file
  • mix credo checks passed
  • the --gist is now required
  • namespaced in install instead of widget

@coveralls
Copy link

Coverage Status

Coverage decreased (-7.0%) to 78.082% when pulling ee0ce5f on playpasshq:feature/naive-widget-puller into 6a9d66e on kittoframework:master.

]
@shortdoc "Install a custom Widget from a Github gist"

@moduledoc """
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you place the moduledoc at the top inside the module?


# Process the install incase we have a gist and widget name
# It will download the gist files and place them in the right location
#
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✂️

For additional information, refer to the documentation for
`Mix.Tasks.Run`.
"""
def run(args) do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a separate @doc for this function.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.2%) to 86.283% when pulling a574bbf on playpasshq:feature/naive-widget-puller into 6a9d66e on kittoframework:master.


# Other files all go into the widget dir
defp determine_file_location(file, widget_name) do
Map.put(file, :path, "./widgets/#{widget_name}/")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use Path.join to create the path.


defp download_gist(url), do: url |> HTTPoison.get! |> process_response

defp build_gist_url(gist_url) when length(gist_url) == 1, do: '#{@github_url}#{hd(gist_url)}'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you use double a quoted string?


## Options

* `--widget` - specifies the widget name that will be used as folder name
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

change folder to directory :neckbeard:

@coveralls
Copy link

Coverage Status

Coverage increased (+1.2%) to 86.283% when pulling b0ff47d on playpasshq:feature/naive-widget-puller into 6a9d66e on kittoframework:master.

def atomify_map(map) do
for {key, value} <- map, into: %{}, do: {String.to_atom(key), value}
end

def assert_file(file) do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All those file assertions and logic deserve their own helper module.

end

test "places all the files in the correct locations" do
in_tmp "installes widgets and jobs", fn ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix typo s/installes/installs


test "fails when `--gist` is not provided" do
Mix.Tasks.Kitto.Install.run(["--widget", "numbers"])
assert_received {:mix_shell, :error, ["Unsupported arguments"]}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please leave a newline above assertions.

test "places all the files in the correct locations" do
in_tmp "installes widgets and jobs", fn ->
with_mock HTTPoison, [get!: mock_gist_with(200, @gist_response)] do
Mix.Tasks.Kitto.Install.run(["--gist", "aaaa", "--widget", "number"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Substitute "aaaaa" with something that could be an actual argument.

end
end

test "fails when the gist has widget but no `--widget` provided" do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most gists will contains widgets, why should the user specify --widget for all those cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Widget is used for the subdirectory under widgets. I added it so people could pull different number widgets by specifying a different directory

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's ok to have that flag, but when i try to fetch a gist containing a JS file with gitlab.js i think that the intuitive thing to do is to create a widgets/gitlab/ dir unless specified otherwise using the flag.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's indeed obvious, can we agree on the following order?

  • Use --widget if provided
  • Use filename from the JS file, note we will have to sanitize it, since it can contain capitalized letters spaces and so on

Will have to think about it a bit since this will require some changes

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Let's also not sanitize the filename, it's up to the gist maintainer to have a "package" which works.

assert File.regular?(file), "Expected #{file} to exist, but does not"
end

def assert_file(file, match) do
Copy link
Member

@zorbash zorbash Nov 26, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we mention that this code segment is taken from: https://github.com/phoenixframework/phoenix/blob/master/installer/test/mix_helper.exs
?
What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes I'll add reference

in_tmp "installes widgets and jobs", fn ->
with_mock HTTPoison, [get!: mock_gist_with(200, @gist_response)] do
Mix.Tasks.Kitto.Install.run(["--gist", "aaaa", "--widget", "number"])
assert_file "widgets/number/number_job.js", fn file ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change file argument to contents makes it explicit that we're performing the assertion on the file contents.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.5%) to 86.58% when pulling 8201c50 on playpasshq:feature/naive-widget-puller into 6a9d66e on kittoframework:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.5%) to 86.58% when pulling e4f5556 on playpasshq:feature/naive-widget-puller into 6a9d66e on kittoframework:master.

Installs community Widget/Job from a Github Gist

mix kitto.install --widget test_widget --gist JanStevens/0209a4a80cee782e5cdbe11a1e9bc393
mix kitto.install --gist 0209a4a80cee782e5cdbe11a1e9bc393
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the second evocation missing the owner of the gist. I expected it to also have JanStevens/0209a4a80cee782e5cdbe11a1e9bc393

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because we only need the last part of the gist url, you could even copy past the full url and it would still work

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know that. I tried it and it works! 🌈

@@ -0,0 +1,100 @@
defmodule Mix.Tasks.Kitto.Install do
use Mix.Task
@shortdoc "Install community Widget/Job from a Github Gist"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add newline above.

end

# Elixir files we place in the jobs dir
defp determine_file_location(%{language: "Elixir"} = file, _) do
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that we can make the assumption that .exs files are for jobs and .ex belong to lib.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oke I'll look into it, do we also want to namespace the ex files in lib?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to namespace them.

@zorbash zorbash closed this in d1eb705 Nov 29, 2016
@zorbash
Copy link
Member

zorbash commented Nov 29, 2016

@JanStevens I rebased and tidied up the branch a bit before merging it. Also changed it to place .exs files under jobs and .ex under lib,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants