Deploy pure Elixir app on Heroku or other hosting services - heroku

I've just made a pure elixir app which generates a random image based on the text user inputs. I do not have any front-end for this and fully rely on terminal to input a text to the app.
I know how to make a Phoenix app using Elixir and deploy it on Heroku or other hosting services. But I wonder if it's possible to deploy a pure Elixir app (not relying on any framework like Phoenix).
Please correct me if I'm wrong for asking this question.

For a CLI application, you can package it as an escript: Mix.Tasks.Escript.Build
This gives you an application with a main/1 entry point.
mix.exs:
defmodule MyApp.Mixfile do
use Mix.Project
def project do
[
app: :my_app,
version: "0.0.1",
escript: escript()
]
end
def escript do
[main_module: MyApp.CLI]
end
end
lib/my_app/cli.ex:
defmodule MyApp.CLI do
def main(_args) do
IO.puts("Hello from MyApp!")
end
end

Related

How to programatically create Hobby of type `Dyno` from Heroku API (Preferrably with Ruby)?

The following method returns a 422 HTTP status code when I attempt to create a Dyno with the heroku app api:
client = PlatformAPI.connect_oauth(API_KEY)
dyno_interface = PlatformAPI::Dyno.new(client)
begin
dyno_interface.create('my-cool-app', {"command" => " bin/rails server -p
$PORT -e $RAILS_ENV", "size" => "hobby", "type"=> "run"})
rescue => e
resp = e.response
end
It fails with the message: Requested type Hobby is not available. Please use Free.
If it matters, I've tried on different versions of the Ruby client, (version 2.0.0). Also, my app does not currently have a Procfile but I was unsure if this would matter.
TLDR: How can I automatically create Dynos of type Hobby via the Heroku API (preferably in Ruby).
Never did figure out how to change the dyno type from Ruby so instead we ended up calling bash/Heroku CLI from ruby.
Still interested if anyone knows how to do this from Ruby.

Missing GDAL on Heroku

A Django application running has GeoJSON data stored in one of the models via django-geojson. In the admin interface, this field is editable via django-leaflet. When I run the application locally with ./manage.py runserver, the interface works just fine, the page looks like this.
However, when I deploy to Heroku, which builds just fine, and open the same Location instance in the admin interface, the blue marker isn't anywhere on the map, the map loads normally, and I get this error delivered to me:
Error creating geometry from value '{
"coordinates":[
"-105.2449000",
"40.0474000"
],
"type":"Point"
}' (Initializing geometry from JSON input requires GDAL.)
I'm just recording simple Point data in my models.py
from djgeojson.fields import PointField
from django.db import models
class Location(models.Model):
"""
A model subclass for recording geographic data.
"""
service_id = models.CharField(max_length=255, blank=True, null=True)
name = models.CharField(max_length=255, blank=True, null=True)
geom = PointField() # GeoJSON (remember, coordinates: [long, lat])
def __str__(self):
return self.name
This is my first time using geoJson, Leaflet, and Heroku. Am I missing some dependency, is there's some Heroku configuration I'm neglecting? Here's my requirements.txt.
dj-database-url==0.4.1
Django==1.10
django-filter==0.13.0
django-geojson==2.9.0
django-leaflet==0.18.1
gunicorn==19.6.0
httplib2==0.9.2
jsonfield==1.0.3
oauth2==1.9.0.post1
oauthlib==1.1.2
psycopg2==2.6.2
PyJWT==1.4.1
python-openid==2.2.5
requests==2.10.0
requests-oauthlib==0.6.2
six==1.10.0
wheel==0.24.0
whitenoise==3.2
Heroku is currently running the heroku-18 stack and for python projects the default build pack has the geospatial libraries https://github.com/heroku/heroku-buildpack-python
To use them run heroku config:set BUILD_WITH_GEO_LIBRARIES=1 and add
GDAL_LIBRARY_PATH = os.environ.get('GDAL_LIBRARY_PATH')
GEOS_LIBRARY_PATH = os.environ.get('GEOS_LIBRARY_PATH')
to settings.py.
See also https://github.com/heroku/heroku-buildpack-python/issues/752
Looks like Heroku have dropped support for BUILD_WITH_GEO_LIBRARIES. You now need to add a buildpack to enable support:
# Add the buildpack
heroku buildpacks:add --index 1 https://github.com/heroku/heroku-geo-buildpack.git
# Remove the environment variable
heroku config:unset BUILD_WITH_GEO_LIBRARIES
See Heroku help post
GDAL is not a Python dependency, it is a separate framework that must be installed in your production environment (Heroku).
One way to do this is using a separate buildpack like heroku-geo-buildpack. Heroku has instructions on how to add multiple buildpacks - i.e. here Python and GDAL.
Once installed, the heroku-geo-buildpack suggests the following method for testing GDAL is installed in a Django app. From your Heroku Python console do:
>>> from django.contrib.gis import gdal
>>> gdal.HAS_GDAL
True
You should then be good to go.

is there a pure command-line oauth flow for installed apps?

I'm trying to get a pure command line oauth flow for an installed app and it's not easy to piece this together... Docs are sorely lacking... I started with the drive example (https://github.com/google/google-api-ruby-client-samples/tree/master/drive) but when it gets to client.authorization = flow.authorize(file_storage) it tries to start webrick to put up a web page. I need something that works similarly to the CLI tools provided by google: it needs to print out the URL I need to visit and then read in the response that I can copy&paste. Is this possible with the google ruby client?
Looks like the following monkey-patch works:
module Google
class APIClient
class InstalledAppFlow
def authorize_cli(storage)
puts "Please visit: #{#authorization.authorization_uri.to_s}"
printf "Enter the code: code="
code = gets
#authorization.code = code
#authorization.fetch_access_token!
if #authorization.access_token
if storage.respond_to?(:write_credentials)
storage.write_credentials(#authorization)
end
#authorization
else
nil
end
end
end
end
end

Using sessions in Espresso Framework

good progress so far.
got all controllers and actions up and running in matter of minutes.
However not sure how make sessions work.
trying:
class Cart
session :memory
# my actions
end
but it fails with an error that say to use sessions at app level.
how that? where is that app level?
I guess you are starting the app like this:
Cart.run
it is a good one unless you need to add some setup to your app.
creating app is as easy as:
app = EApp.new :automount
app.run
and if you have some setup for the app, use a block at initialization:
app = EApp.new :automount do
session :memory
end
app.run
Please note the first argument - :automount - it instructs the app to search for controllers and mount them automatically.
If you want to mount your controllers manually, omit first argument:
app = EApp.new do
session :memory
end
app.mount Cart
app.run

How to mount other rack apps, such as Grape API's to Padrino application?

I am looking around on how to mount other rack apps such as a grape API to my padrino application. I tried searching around but couldn't possibly find an answer.
I tried with the following way:
Padrino.mount("API", :app_file => "path_to_api_rb", :app_class => "MyApp::API").to("/")
But Padrino didn't start with this setting. It seems that facility is only for Padrino-sub apps. Has anyone tried this before?
here's a project showing how to use Grape as a subapp:
PadrinoEatsGrape
(Other Rack apps could work, i guess)
u can use the Rack::Cascade: to mix the grape, rails and pandrino apps:
rails_app = Rack::Builder.new do
use Rails::Rack::LogTailer #Optional
use rails::Rack::Static #Optional
run ActionController::Dispatcher.new
end
run Rack::Cascade.new([
MyApp::API,
rails_app,
Padrino.application
])

Resources