Using Heroku Scheduler add-on with Golang app - heroku

I can't figure out how to use the Heroku Scheduler add-on with Go.
I would like run a separate Go file periodically, but I can find the command to achieve that.
From Heroku's doc (https://devcenter.heroku.com/articles/scheduler), if the app is not a Rails app, I should use a ruby script. But I don't know how to run a Go file from there.

I ended up forking the same main function used by my web dyno:
func main () {
if len(os.Args) >= 2 && os.Args[1] == "my_job_param" {
// Execute job.
} else {
// Set up my web server with port, router, etc.
}
}
Then, in the Scheduler add-on, I just call: my-app-name "my_job_param". It's pretty hacky, but I wanted to find a solution using the Scheduler add-on.

The typical pattern is to do something like:
.
└── cmd
├── processX
│ └── main.go
└── web
└── main.go
And you set heroku.install to ["./cmd/..."] and Heroku compiles and installs both commands into bin, so you get a bin/web and a bin/processX (processX is just a placeholder, whatever the name of the directory that contains a main package is the name of the resulting executable). In the above case your Procfile would say web: web, the first web being the process type, the second being the name of the executable. And the job you would tell scheduler to run would be processX.
That cleanly separates responsibilities

The Heroku scheduler will run any terminal command basically. So, if you compile your script into an executable called myscript, for example, you could simply put:
myscript
In the scheduler and it will execute that command, thereby running your script =) No ruby is required.

Related

How to reference script files in webpack deploy?

I am using webpack and electron and while I can reference my script files fine locally (app/scripts/scriptname.sh), when it comes to the production deploy, I get an error: Can't open app/components/scripts/scriptname.sh.
It's unclear to me if this is an electron-dependent issue or a webpack-issue.
I am running these using node child_process as:
var ls = spawn('sh', ['app/components/scripts/scriptname.sh']);
I don't necessarily need the scripts to be in their own folder it would just be helpful.
You need to provide the complete absolute path to the script. To do that you can use the app.getAppPath() API of electron
app.getAppPath()
Returns String - The current application directory.
So your code would be something like:
var scriptAbsolutePath = app.getAppPath() + '/app/components/scripts/scriptname.sh';
var ls = spawn('sh', [scriptAbsolutePath]);
You can also have a look at app.getPath(name) API if it satisfies your particular requirement.

Tests not run automatically

I'm trying to setup Guard in my Exercism folder, so that all tests are automatically run (using guard-minitest).
The folder structure looks like this:
.
├── exercism
└── ruby
   ├── bob
   │   ├── bob.rb
   │   ├── bob_test.rb
   ├── etl
   │   ├── etl.rb
   │   ├── etl_test.rb
...
   └── binary_search_tree
      ├── bst.rb
      ├── binary_search_tree.rb
      └── README.md
Due to the unusual folder structure, I made the following configuration in the Guardfile:
# tell Guard to watch all folders under ruby/
all_dirs = Dir.glob('ruby/*')
directories all_dirs
options = {
test_folders: all_dirs,
test_file_patterns: '*_test.rb',
pride: true
}
guard :minitest, options do
watch(%r{^ruby/([^/]+)/([^/]+).rb$})
end
With this setup I expect that all my tests will be run after any edit to a .rb file.
I run guard in debug mode.
All tests run on startup, as expected.
However, when I edit a .rb file the tests are not run again, although Guard outputs this:
20:43:26 - DEBUG - Interactor was stopped or killed
20:43:26 - DEBUG - Hook :run_on_additions_begin executed for Guard::Minitest
20:43:26 - DEBUG - Hook :run_on_additions_end executed for Guard::Minitest
20:43:26 - DEBUG - Start interactor
I tried many variations in the guard configuration, such as:
watch(%r{^ruby/([^/]+)/([^/]+).rb$}) do |m|
Dir.glob("ruby/#{m[1]}/*_test.rb").first
end
(I expect this to only run the test from the folder in which a file was modified.)
Nothing seems to work. I have to go to guard's interactive console and press ENTER to get tests to run.
What am I doing wrong?
EDIT
After reading Cezary's answer below, I tried some more things, including trying this on other environments.
It turns out it wasn't guard's fault, but probably the environment I was using.
I initially ran everything in a Codio box.
I moved the project to other two machines, a Win8 and an Ubuntu 14.04, and it works fine on both using this Guardfile:
all_dirs = Dir.glob('ruby/*')
directories all_dirs
clearing :on
options = {
test_folders: all_dirs,
test_file_patterns: '*_test.rb',
pride: true
}
guard :minitest, options do
watch(%r{^ruby/([^/]+)/([^/]+).rb$}) do |m|
file = Dir.glob("ruby/#{m[1]}/*_test.rb").first
puts " Should test #{file}"
file
end
end
The output of guard -d is as follows:
On the Codio box (where it doesn't work):
<!-- language: lang-none -->
08:55:09 - DEBUG - Interactor was stopped or killed
Should test ruby/anagram/anagram_test.rb
08:55:09 - DEBUG - Hook :run_on_additions_begin executed for Guard::Minitest
08:55:09 - DEBUG - Hook :run_on_additions_end executed for Guard::Minitest
08:55:09 - DEBUG - Start interactor
[1] guard(main)>
On Win/Ubuntu (where it works fine):
<!-- language: lang-none -->
11:02:10 - DEBUG - Interactor was stopped or killed
Should test ruby/anagram/anagram_test.rb
11:02:10 - DEBUG - Hook :run_on_modifications_begin executed for Guard::Minitest
11:02:10 - INFO - Running: ruby/anagram/anagram_test.rb
Run options: --seed 52507
# Running tests:
..........
Finished tests in 0.001249s, 8006.0205 tests/s, 8006.0205 assertions/s.
10 tests, 10 assertions, 0 failures, 0 errors, 0 skips
11:02:10 - DEBUG - Hook :run_on_modifications_end executed for Guard::Minitest
11:02:10 - DEBUG - Start interactor
[1] guard(main)>
I don't know why on Codio I get run_on_additions and on the other two I get run_on_modifications.
Anyway, I guess that's a Codio issue. I tried with and without Manual Save and it's the same.
Hi I'm one of the guys "reponsible" for Guard, and based on this I wrote a walkthrough: https://github.com/guard/guard/wiki/Understanding-Guard
I highly recommend going through it (feedback appreciated).
Here's a list of things to consider:
structure: if you can, put tests in a separate top folder, ideally 'ruby/test' in your example, and the files in 'ruby/lib'. This is closer to the convention and then things like Guard::Minitest would work out of the box. (Some editors - like Vim and Emacs - allow you to switch between "alternative" files and they will automatically know where to look for tests or implementation files).
Guard watches directories recursively (and this can't even be turned off right now). For small projects, you can just watch everything by not specifying a directories option. But, if you have lots of disk activity in your folder and you have large projects, you'll want to select directories. E.g. in your case, it would be: directories ruby. So `Dir.glob('ruby/*') doesn't make much sense here.
Guard::Minitest options - if you use the structure I described, this shouldn't be necessary. If not, I think having test_folder: %w(ruby) should be enough. Also, test_file_patterns shouldn't be necessary, since your files seem to following the defaults/convention (bob_test.rb and etl_test.rb) - unless you have something really strange as having test suites inside the bob.rb and etl.rb files.
Your watch expression has no block, so it returns the files changed. Unfortunately, when you change an implementation file (like bob.rb), that file is passed to Guard::Minitest, which ignore non-test files (probably using the test_file_patterns option, so since bob.rb won't match bob_test.rb, Guard::Minitest will quietly do ... nothing.
Ideally, rename your Guardfile, update your gems (Guard::Minitest basically) and run bundle exec guard init minitest to so what the "current" recommended template is for Guard::Minitest and try to tweak that instead. You'll see that the default has:
watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}test_#{m[2]}.rb" }
which shows how to translate changed implementations files into test files (which are the only files Guard::Minitest cares about).
In your case you may want:
watch(%r{^ruby/(.*/)?([^/]+)\.rb$}) { |m| "ruby/#{m[1]}/#{m[2]}_test.rb" }
I'd say the regexen are horrible - and I'm planning to implement glob pattern support - but this will take a while (lots of critical bug fixes in the pipeline for me).
If this doesn't help - definitely go through the Wiki document above, since there are about 20-50 problems you can have with Guard/Listen - and most are completely outside Guard's/Listen's control. (I wish I could change this to make it simpler, so any suggestions would be helpful).
Since bugs are a priority for me, like most maintainers - we rely on issues reported int GitHub. So we don't usually watch stuff in Stack Overflow (we expect tough issues to be reported in Github).
Ok, I've pointed out so many things wrong, time for stuff you did very, very well:
Running Guard in debug mode - you're AWESOME for doing that
Showing output regarding the changes - you're AWESOME for doing that as well (since this shows the Guard::Minitest is getting the changes, but it's ignoring them - likely since you're passing implementation files and not test files).
Submitting such a detailed issue - that's so helpful. Ideally, you shouldn't have gone through all the trouble (or even had the issue in the first place), but by reporting this you're showing us what is wrong with Guard on so many levels. (Often, as developers/maintainers we "get" the internals, so we "know" what's wrong immediately - even though the docs or messages or debug output says nothing to others - so issues like this help us help others very much).
Thanks again for this - if you ever see other people with issues you can resolve - please do so. If you see obvious bugs or issues in Guard - please open an issue in Guard. If it's in another plugin repository (like Guard::Minitest), just mention me so that important issues aren't ignored (mention me as #e2 on GitHub).
I do hope to make Guard better - currently I'm working hard to make it simpler, more intuitive, more flexible and more reliable. The more I can count on people reporting broken stuff, the faster I can move ahead with cool stuff.
Thanks again and have a great day!
I had a similar issue when wanting to use Guard with any new Ruby Exercism exercise I'd pull down: running the full test suite would work, but tests would not run automatically when files changed. What I did in order to get this working was the following:
Create a common Guardfile and place it at ~/exercism/ruby/Guardfile with the following content:
# frozen_string_literal: true
group :red_green_refactor, halt_on_fail: true do
guard :minitest,
all_on_start: false,
test_folders: ["."] do
# Re-test test files when they're edited.
watch(%r{\A.+_test\.rb\z}) { |m| "./#{m[1]}" }
# Run the test file of the (non-test) file that was edited.
watch(%r{\A(.+)(?<!_test)\.rb\z}) { |m| "./#{m[1]}_test.rb" }
end
guard :rubocop,
all_on_start: false,
cli: ["--display-cop-names"] do
# Only run Rubocop over implementation files only
# as test files are not written by me.
watch(%r{\A(.+)(?<!_test)\.rb\z})
watch(%r{(?:.+/)?\.rubocop\.yml\z}) { |m| File.dirname(m[0]) }
end
end
When running Guard within an exercise folder, always specifically reference this Guardfile ie guard --guardfile ~/exercism/ruby/Guardfile.
Some specific gotchas here about the Guardfile configuration:
The test_folders option, the locations where guard-minitest will go looking for test files, defaults to %w[test spec]. This is fine for any standard Ruby project, but not for Exercism, where the test file and the implementation file are in the same directory. So, it needed to be changed to ["."] to specify that.
In the blocks for the Minitest watch methods, the string returned needs to look like a path, otherwise the tests will just not run when a file is changed (with no error output or indication that something went wrong). For example:
watch(%r{\A.+_test\.rb\z}) { |m| "#{m[1]}" } will not work. It has to be watch(%r{\A.+_test\.rb\z}) { |m| "./#{m[1]}" }.

Martini templates and tests

I'm trying to split my application files from my testing files. It looks something like this:
main.go
views/
layouts/
layout.html
spec/
main_test.go
main.go creates a Martini app and tells Martini.render where to look for the views:
func CreateApplication() {
m := martini.Classic()
m.Use(render.Renderer(render.Options{
Directory: "views",
Layout: "layouts/layout",
Extensions: []string{".html"},
}))
}
That all works really well when I'm using go run from the root folder. However, when I try to use the CreateApplication() function from the spec/main_test.go file, it's now looking for the views in spec/views because that's the run folder.
I went down the route of trying to use runtime.Caller() to get the absolute path, but that totally messes up when compilling the a binary.
I guess my question is how I can make this work? I want that CreateApplication() to work the same no matter where it was called from.
I often run into this problem. What I do in such cases, is to create a symlink from the child directory to the folder in the root directory which holds the templates. Up until now I haven't had any problems using this appraoch, but when an app goes to production I delete those symlinks. I actually have a script that creates the symlinks before I start testing, and then deletes them after I'm done.
In your case, it would look like this (I'm on Ubuntu or Cygwin):
main.go
views/
layouts/
layout.html
spec/
main_test.go
$ cd spec
$ ln -s ../views views
main.go
views/
layouts/
layout.html
spec/
main_test.go
views <- this is the symlink
Now, when running your tests from spec/ the views directoy is found. I hope it helps you, and if my approach is somehow flawed, I'm eager to know!

How do use node-qunit?

The info on this page seems less-than-forth-coming -- https://github.com/kof/node-qunit. I've got a setup where I installed nodejs and installed the node-quit module. I have test runner and executed the command node /path/to/runner.js. Below is an example of my setup. Any ideas or examples on how to do this or maybe I'm using it wrong. I previous ran qunit tests using Rhino and EnvJs without any issues but I figured I try nodejs since I using it for other things and the packaging system can be scripted in my build. Maybe I missing an option to node to include Qunit or some environment variable not set -- that would make sense.
File Structure
node/
public/
js/
main.js
tests/
js/
testrunner.js
tests.js
Installation
cd node
npm install qunit
This will now update the file structure.
node/
node_modules/
qunit/
tests/js/testrunner.js
var runner = require("../../node/node_modules/qunit");
runner.run({
code : "/full/path/to/public/js/main.js",
tests : "/full/path/to/tests/js/tests.js"
});
tests/js/tests.js
test("Hello World", function() {
ok(true);
});
Command
node tests/js/testrunner.js
It appears that you need to use full paths to the main.js and tests.js files and also include a relative path to the qunit module. I updated the code above as an example for others.

Node JS 0.6.1 msi on Windows

How do I use NodeJS on Windows? I've downloaded and installed the 0.6.1 MSI.
I can run node in the command prompt.
What do I do next? I can't seem to find much information such as where to put files etc
It's just for a little experimentation.
Thanks
Ric
Have you followed the basic tutorial exactly as it is posted? If you create a file (let's say, index.js) that looks like this...
var http = require('http');
http.createServer(function(req, res) {
res.writeHead(204, { 'Content-Type':'text/plain'});
res.write('Hello World');
res.end();
}).listen(8080);
...and then launch it via the command line like so (assumes index.js is visible from the current directory)...
node index.js
...you should see Hello World in your browser when you point it to http://localhost:8080.
If you simply run node then you will get an interactive javascript shell, which is not what you want.
Make sure you called listen(port) and also make sure that you called res.end() in order to send the response.
I was being an idiot. I was running node at c: then typing the full path to the file within Node! If any one has the same problem then make sure you change to the folder your js files are in first, then node filename.js

Resources