Skip to content

Rakeify rake tasks #43

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

Open
wants to merge 17 commits into
base: master
Choose a base branch
from
Open

Rakeify rake tasks #43

wants to merge 17 commits into from

Conversation

drbrain
Copy link

@drbrain drbrain commented May 10, 2016

This PR makes the rake tasks in mruby-cli use more rake features than they presently do.

Most notable is use of import to load the Rakefile from mruby after the appropriate setup has been finished (same for the package tasks).

Ensuring certain tasks are run inside Docker now uses dependencies instead of rewriting the tasks. (Rewriting the tasks is bad because it converts FileTasks into Tasks and changes their behavior.)

Also, FileUtils references are removed as Rake already included that for us.

The result is as Jim Weirich intended.

drbrain added 11 commits May 10, 2016 10:20
Also, remove () to be consistent across uses of FileUtils methods
This makes it more clear what the commend means
I think that previously the Rakefile would always create mruby_root as
"mruby" regardless of what was in the MRUBY_ROOT environment variable.
Now the correct directory will be created.

A `mruby` task is retained for compatibility.
This moves us a step closer to not having `cd mruby_root` polluting the
package tasks and allows us to make loading mruby use `import` as Jim
Weirich intended.
If we rewrite the task Bad Things happen (like a Rake::FileTask turning
into a Rake::Task).  Instead we can use a dependency because that runs
before anything the task does that would require Docker.

PS: rake-hooks is a pointless library.  Rake already has a way to run
things before a task, a prerequisite.  Rake already has a way to run
things after a task, make the after-task have the before-task a
prerequisite.

With some organization of tasks the before/after isn't an issue, it just
falls out with how you hook up your dependencies.
Rake has the #import method to safely import Rakefiles into the current
rake application.  Using load or require may cause rakefiles to appear
in the wrong place or require cumbersome setup.

In this case the cumbersome setup was the `cd "mruby"` that required
adjustment for the correct path in the release and package tasks.
Otherwise we're making directories when they're not needed.
Missed this one
@drbrain
Copy link
Author

drbrain commented May 10, 2016

I get the same test failure if I build an app with the latest release of mruby-cli and do nothing but run docker-compose run test:

RuntimeError: File TEST SETUP => can't make a socket bi (mrbgems: mruby-io)
Skip: File.expand_path (with ENV)  
RuntimeError: FileTest TEST SETUP => can't make a socket bi (mrbgems: mruby-io)
Fail: FileTest.socket? (mrbgems: mruby-io)
 - Assertion[1] Failed: Expected false to be true
    Expected: true
      Actual: false
RuntimeError: IO TEST SETUP => can't make a socket bi (mrbgems: mruby-io)
MTest 1) Skipped:
test_assert_match(Test4MTest) /home/mruby/code/mruby/build/mrbgems/mruby-mtest/mrblib/mtest_unit.rb:183: assert_match is not defined, because Regexp is not impl. (MTest::Skip)
Total: 687
   OK: 683
   KO: 1
Crash: 3
 Time: 0.13 seconds
rake aborted!

The test task depends upon clearing MRuby's test task but we can't do
that until after MRuby's Rakefile loads.

Moving the test tasks to a separate file we import allows us to clear
MRuby's test actions at the proper time.
@drbrain drbrain force-pushed the drbrain/rakeify branch from bf3329b to 0472ccb Compare May 12, 2016 18:52
@drbrain
Copy link
Author

drbrain commented May 12, 2016

Figured it out, need to clear the test task of MRuby's actions after importing MRuby's Rakefile.

@zzak
Copy link
Contributor

zzak commented May 13, 2016

The patch looks good to me, but we probably need to test this to make sure it doesn't break release or anything (I'm not sure those are thoroughly tested).

@drbrain
Copy link
Author

drbrain commented May 16, 2016

Seems fine:

$ docker-compose run release

Build summary:

================================================
      Config Name: host
 Output Directory: mruby/build/host
         Binaries: mrbc, mrbtest
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
             mruby-compiler - mruby compiler library
             mruby-bin-mrbc - mruby compiler executable
             mruby-test - mruby test
================================================

================================================
      Config Name: x86_64-pc-linux-gnu
 Output Directory: mruby/build/x86_64-pc-linux-gnu
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

================================================
      Config Name: i686-pc-linux-gnu
 Output Directory: mruby/build/i686-pc-linux-gnu
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

================================================
      Config Name: x86_64-apple-darwin14
 Output Directory: mruby/build/x86_64-apple-darwin14
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

================================================
      Config Name: i386-apple-darwin14
 Output Directory: mruby/build/i386-apple-darwin14
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

================================================
      Config Name: x86_64-w64-mingw32
 Output Directory: mruby/build/x86_64-w64-mingw32
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

================================================
      Config Name: i686-w64-mingw32
 Output Directory: mruby/build/i686-w64-mingw32
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

Writing /home/mruby/code/releases/v0.0.4/mruby-cli-0.0.4-x86_64-pc-linux-gnu.tgz
Writing /home/mruby/code/releases/v0.0.4/mruby-cli-0.0.4-i686-pc-linux-gnu.tgz
Writing /home/mruby/code/releases/v0.0.4/mruby-cli-0.0.4-x86_64-apple-darwin14.tgz
Writing /home/mruby/code/releases/v0.0.4/mruby-cli-0.0.4-i386-apple-darwin14.tgz
Writing /home/mruby/code/releases/v0.0.4/mruby-cli-0.0.4-x86_64-w64-mingw32.tgz
Writing /home/mruby/code/releases/v0.0.4/mruby-cli-0.0.4-i686-w64-mingw32.tgz
Writing /home/mruby/code/releases/v0.0.4/mruby-cli-0.0.4.tgz

PS: package seems broken on master:

$ docker-compose run package
[…]
Build summary:

================================================
      Config Name: host
 Output Directory: build/host
         Binaries: mrbc, mrbtest
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
             mruby-compiler - mruby compiler library
             mruby-bin-mrbc - mruby compiler executable
             mruby-test - mruby test
================================================

================================================
      Config Name: x86_64-pc-linux-gnu
 Output Directory: build/x86_64-pc-linux-gnu
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

================================================
      Config Name: i686-pc-linux-gnu
 Output Directory: build/i686-pc-linux-gnu
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

================================================
      Config Name: x86_64-apple-darwin14
 Output Directory: build/x86_64-apple-darwin14
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

================================================
      Config Name: i386-apple-darwin14
 Output Directory: build/i386-apple-darwin14
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

================================================
      Config Name: x86_64-w64-mingw32
 Output Directory: build/x86_64-w64-mingw32
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

================================================
      Config Name: i686-w64-mingw32
 Output Directory: build/i686-w64-mingw32
    Included Gems:
             mruby-io
             mruby-getopts - GNU getopt for mruby
             mruby-dir
             mruby-sprintf - standard Kernel#sprintf method
             mruby-time - standard Time class
             mruby-mtest
             mruby-cli - 0.0.4 - mruby cli utility
               - Binaries: mruby-cli
================================================

Writing releases/v0.0.4/mruby-cli-0.0.4-x86_64-pc-linux-gnu.tgz
Writing releases/v0.0.4/mruby-cli-0.0.4-i686-pc-linux-gnu.tgz
Writing releases/v0.0.4/mruby-cli-0.0.4-x86_64-apple-darwin14.tgz
Writing releases/v0.0.4/mruby-cli-0.0.4-i386-apple-darwin14.tgz
Writing releases/v0.0.4/mruby-cli-0.0.4-x86_64-w64-mingw32.tgz
Writing releases/v0.0.4/mruby-cli-0.0.4-i686-w64-mingw32.tgz
Writing releases/v0.0.4/mruby-cli-0.0.4.tgz
fpm is not installed. Please check your docker install.

@drbrain
Copy link
Author

drbrain commented May 19, 2016

I'm wondering why you want to import the mruby rake tasks atop your own. I find building mruby via subshell is less trouble and easier to use. The same method could be used to run tasks inside docker.

@zzak
Copy link
Contributor

zzak commented May 20, 2016

What is the point of running rake inside of a subshell.. in rake? :woah:

mruby knows how to compile mruby, and when we started building stuff with mruby, we leaned on the existing tasks to do the work for us. What you're doing with mruby-optparse is fine, but I don't think every gem doesn't want to maintain this much configuration.

The Rakefile is a generated file, that users shouldn't have to maintain, it's still there so the smaller the better.

But anyways, when I get a chance to finish mruby-build, hopefully most of this stuff can be upstreamed and we don't have to bikeshed in each project.

Back to this patch, the other thing is mruby-cli was generated.. with mruby-cli. So we have to update the setup.rb stuff so user apps can take advantage of these changes.

The downside to this patch is breaking up the tasks into separate files means having to generate them for the user too (on setup), more files means more things to diff when doing upgrades and such. So we have to consider that as well.

@toch
Copy link
Collaborator

toch commented May 23, 2016

@drbrain Thanks for doing that. It's cleaner 👍.

About package task, it seems that the last docker image is not the good one anymore (even if the Dockerfile in the repo is correct). @hone or @zzak could you give me access to the docker registry of mruby-cli image so I can fix it?

@drbrain as Zak explains, mruby-cli generates different files, including a Rakefile thanks to setup.rb. This is nearly the same than the Rakefile you improved (except a few things such as the package task). Could you also apply your changes to setup.rb? Thanks.

About, multiple files. @zzak I'm wondering if it wouldn't be the path to avoid to have twice the same code. If we can isolate the different task and make them generic, setup.rb can just copy the file, rather than generate it. What do you think?

@drbrain
Copy link
Author

drbrain commented May 24, 2016

I will update setup.rb soon.

@toch I must say I vastly prefer libraries over generated code. It's a ton of work to update generated code, but library code updates are (within compatible versions) labor-free. Unfortunately I'm unsure how a library model can work with mruby-cli as a single binary. (You could do some bizarre stuff with import like I do in this PR, but it would likely quickly devolve into an unmaintainable mess.)

The reason I'm concerned about importing mruby's Rakefile is issues like needing to work around mruby or having to tell users a task must run in docker (which was broken).

There's a few reasons I think separation will be better.

One is that it makes getting started as a rubyist familiar with rake much easier. I can't rake test or rake package, instead I have to docker-compose run test but sometimes that doesn't work so I have to docker-machine start default then eval $(docker-machine) env. I can probably make fully automated docker work with an imported mruby Rakefile, but it's a pain compared to having rake run docker for me. (If you've never used docker mruby-cli has a bucket of mystery to drain before you can see "Hello World" show up on your terminal.)

Another reason I prefer a docker subshell is that I can't easily get tasks to run outside docker to set up state needed for tasks that must run inside docker. For example, I want to generate some .rb files that end up in mrblib/ without having to install a modern ruby inside Docker (thus having to manage my own image). AFAICT this is impossible without running two commands currently because docker-compose run creates a dependency firewall.

With a docker subshell I could use regular rake dependencies to take care of that in a straightforward manner. I could also set up tasks to easily upload my built CLI when docker was finished all from one rake task's dependencies.

For the above reasons I'm likely to switch my current mruby-cli build over to the docker subshell model because I will have less to teach my coworkers who will contribute to my CLI. I can bring the instructions down to "download docker, install docker, run rake" from "download docker, install docker, start docker, load docker env, run docker-compose run test" … "oh, and if you reboot your machine you'll have to remember to start docker again and load the environment" (which they will forget because I forget).

The final one is that it's a separation of concerns. Presently mruby-cli doesn't make any changes to mruby's Rakefile (besides the local:ensure_in_docker with this PR and similar code in existing mruby-cli). This means I don't have any worries about upgrading to a new mruby with my existing mruby-cli. Importing mruby's Rakefile makes it possible to accidentally couple to a given version of mruby meaning I'll have to update to a new mruby-cli to use a new mruby. This would be annoying.

PS: Even rake has a ruby method for running ruby in a subshell.

@drbrain
Copy link
Author

drbrain commented May 24, 2016

Oh, the final thing I should add about importing mruby's Rakefile is that to do it in a rake-like fashion it involves features few people know about, like import and that it will invoke a task that depends on the imported file as this PR does to make sure the download is unpacked.

Also wrapped some lines at 80 columns to improve readability.
@drbrain
Copy link
Author

drbrain commented Jun 17, 2016

setup.rb updated

This check's dependency is :all which runs the compilers so it can never
check what it needs to.

Unfortunately there's no place we can move this compiler check so that
it will work.  Having `task all: :compiler_check` won't work either
because the all task depends on the .o files which run the compiler
check.

I haven't found any tasks in mruby that we can hook into to run such
checks.  I looked extensively to find a place to hook-in for
cross-compiling third party libraries (like libcurl) and such a hook
doesn't exist.

In order to restore this functionality mruby-cli must not import mruby's
Rakefile.  Then we can have tasks that run before mruby is built (like
cross-compiling libraries or checking the cross-compiler environment).
@drbrain
Copy link
Author

drbrain commented Jun 17, 2016

See also @c6adb30 for a reason why mruby-cli should not import mruby's Rakefile.

@toch
Copy link
Collaborator

toch commented Jul 27, 2016

@drbrain first of all, thanks for your patience and your answer.

Let me go through your answers first :).

libraries vs generated code.

I agree with you. I think it would be cleaner to extract that part so we don't have to duplicate it. It's easy to forget to replicate it in the setup.rb and by doing so not providing it to the created mruby-cli app. As we would have the hand on them, there is no really a maintenance of a dependency, it's just a cleaner structure.

So far, my only current concern is as you said it well: "Unfortunately I'm unsure how a library model can work with mruby-cli as a single binary." In our case we need to consider: 1. mruby-cli the framework that allows us to scaffold the CLI app, and 2. the CLI itself. Considering that mruby-cli structure is nearly the same than the one of the CLI app it can scaffold, I don't think it would be a problem to opt for a library model. In a way we're already doing it as both depends on a few dependencies on mruby gems.

refactoring of local:ensure_in_docker

Thanks a lot, it's cleaner and I learned something about Rake :).

rake vs docker-compose

From a user point of view, I really like the idea. It would provide a better UX as we'd provide a very familiar set up, as you said.

a docker subshell

I like what you suggest. In fact, it would allow us to use even more docker as a tool rather than an environment. There are options to do what you suggest from inside, but it's not simple and it would require in a certain case to run it with privileged mode what we don't want.

about separation of concerns

agreed

I'm going to review your changes now.

# since we're in the mruby/
release_dir = "releases/v#{APP_VERSION}"
release_path = Dir.pwd + "/../#{release_dir}"
release_path = File.expand_path "releases/v#{APP_VERSION}"
Copy link
Collaborator

@toch toch Jul 27, 2016

Choose a reason for hiding this comment

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

another good consequence :)
no more headache due to the surprising working directory

@toch
Copy link
Collaborator

toch commented Jul 27, 2016

I've just commented a few lines. Not a lot to say except about the generation of code.

I still need to test the whole, I'll do that after my lunch.

@toch
Copy link
Collaborator

toch commented Jul 27, 2016

There is an issue with the clean task. It seems that the deep_clean task is calling itself in a loop creating a loop bomb that froze my computer and made my X killed eventually.

For the task package, I got the following error:

NameError: undefined local variable or method `package_dir' for main:Object
/home/mruby/code/tasks/package.rake:125:in `block (3 levels) in <top (required)>'
/home/mruby/code/tasks/package.rake:122:in `each'
/home/mruby/code/tasks/package.rake:122:in `block (2 levels) in <top (required)>'

the variable package_dir were previously defined but it is no more in your changes.

The other tasks work as expected. The scaffold works also as expected except for the clean task.

Is it correct that for now, your changes don't implement your idea to run docker from rake?

@drbrain
Copy link
Author

drbrain commented Jul 27, 2016

I'll check the loop and missing package_dir soon.

I don't plan to implement running docker from rake here, it's too much change for one PR.

@toch
Copy link
Collaborator

toch commented Jul 28, 2016

thanks

I don't plan to implement running docker from rake here, it's too much change for one PR.

👍 and I'd happy to help

@tagomoris tagomoris mentioned this pull request Sep 16, 2016
Previously we had a task rewriter that made sure certain tasks were run
in docker that prevented this infinite loop by accident.  After removing
the task rewriter the dependencies were circular (through #sh) and things
could run forever.  (Note that the `clean` task didn't change prior to
this commit.)

Rather than trying to unravel this infinite loop let's run `deep_clean`
directly via docker and let it do all the right things.  The `clean`
task remains for documentation purposes.  MRuby already defines it for
us, but now our users will know to hook into it.
@drbrain
Copy link
Author

drbrain commented Sep 21, 2016

Fixed the infinite loop by removing the looping. Somehow the task rewriter caused this loop because I didn't change the clean task before @b6404e4. See commit message for details.

@drbrain
Copy link
Author

drbrain commented Sep 21, 2016

This should be ready to go now, sorry for the delay.

@toch
Copy link
Collaborator

toch commented Sep 23, 2016

Thanks @drbrain, could you rebase please?

I'm going to try the changes again to be sure.

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.

3 participants