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

Add deploy on Heroku (via badge) #231

Merged
merged 2 commits into from
Jul 6, 2018
Merged

Conversation

wilzbach
Copy link
Member

@wilzbach wilzbach commented Jul 13, 2017

So I am publicly experimenting with a "Deploy on Heroku badge" to simplify deployment for new mirrors (and do a bit of dog-fooding on the way).
I managed to get the app to start on Heroku, but currently it still fails with:

2017-07-13T12:15:06.389476+00:00 heroku[web.1]: Starting process with command `./dub-registry --port 5199 --mirror=https://code.dlang.org`
2017-07-13T12:15:10.288494+00:00 app[web.1]: Enforcing certificate trust.
2017-07-13T12:15:10.370178+00:00 app[web.1]: MongoDB reply was longer than expected, skipping the rest: 105 vs. 36
2017-07-13T12:15:10.370495+00:00 app[web.1]: object.Exception@../../app/.dub/packages/vibe-d-0.8.0-beta.8/vibe-d/mongodb/vibe/db/mongo/cursor.d(318): Query failed.
2017-07-13T12:15:10.370805+00:00 app[web.1]: ----------------
2017-07-13T12:15:10.370826+00:00 app[web.1]: ??:? [0x6d19ee]
2017-07-13T12:15:10.370851+00:00 app[web.1]: ??:? [0x6d7a52]
2017-07-13T12:15:10.370918+00:00 app[web.1]: ??:? [0x4e144b]
2017-07-13T12:15:10.370931+00:00 app[web.1]: ??:? [0x466f95]
2017-07-13T12:15:10.370933+00:00 app[web.1]: ??:? [0x4700ed]
2017-07-13T12:15:10.370951+00:00 app[web.1]: ??:? [0x46722f]
2017-07-13T12:15:10.370954+00:00 app[web.1]: ??:? [0x466eec]
2017-07-13T12:15:10.370968+00:00 app[web.1]: ??:? [0x46698a]
2017-07-13T12:15:10.370971+00:00 app[web.1]: ??:? [0x421779]
2017-07-13T12:15:10.370985+00:00 app[web.1]: ??:? [0x421433]
2017-07-13T12:15:10.370988+00:00 app[web.1]: ??:? [0x4cb892]
2017-07-13T12:15:10.371003+00:00 app[web.1]: ??:? [0x6ddefe]
2017-07-13T12:15:10.371006+00:00 app[web.1]: ??:? [0x6ddebd]
2017-07-13T12:15:10.371268+00:00 app[web.1]: ??:? __libc_start_main [0x20ff482f]
2017-07-13T12:15:10.371022+00:00 app[web.1]: ??:? [0x6dddb8]
2017-07-13T12:15:10.371286+00:00 app[web.1]: ??:? [0x4074a8]
2017-07-13T12:15:10.477784+00:00 heroku[web.1]: Process exited with status 1
2017-07-13T12:15:10.489833+00:00 heroku[web.1]: State changed from starting to crashed

I will comment on the invidividual fixes needed so far.
This can be reproduced locally, by checking out this branch and then pushing it to Heroku:

heroku create
heroku buildpacks:add http://github.com/MartinNowak/heroku-buildpack-d.git 
git push heroku

(huge thanks to Martin's awesome buildpack)

import std.process : environment;
string mongodbURI = environment.get("MONGODB_URI", "mongodb://127.0.0.1");
parseMongoDBUrl(mongoSettings, mongodbURI);
mongoSettings.authMechanism = MongoAuthMechanism.scramSHA1;
Copy link
Member Author

Choose a reason for hiding this comment

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

Default for Mongo3 (released since two years) - many cloud instances don't support none anymore:

vibe-d/vibe.d#1785

app.json Outdated
"repository": "https://github.com/heroku/node-js-sample",
"logo": "https://dlang.org/images/dlogo_opengraph.png",
"keywords": ["d", "dlang", "dub", "mirror"]
}
Copy link
Member Author

Choose a reason for hiding this comment

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

Setting up a mirror will be only two clicks away - see e.g. https://devcenter.heroku.com/articles/heroku-button

A mongoDB addon is needed though, but there are many free ones (e.g. mLab).

@MartinNowak
Copy link
Member

Think you need to get the github secrets via env to make this work for Heroku.

README.md Outdated
@@ -4,3 +4,5 @@ DUB registry
![vibe.d logo](public/images/logo-small.png) Online registry for [dub](https://github.com/dlang/dub/) packages, see <http://code.dlang.org/>.

[![Build Status](https://travis-ci.org/dlang/dub-registry.svg)](https://travis-ci.org/dlang/dub-registry)

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/dlang/dub-registry)
Copy link
Member

Choose a reason for hiding this comment

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

Should come with a bit more context, e.g. "You can host your own registry instance for private repos.".

@wilzbach
Copy link
Member Author

Think you need to get the github secrets via env to make this work for Heroku.

The mirror-mode doesn't need any credentials and this is only intended for the mirror mode.

@wilzbach
Copy link
Member Author

. "You can host your own registry instance for private repos.".

That's actually a good use case and once we have figured out the Mongo failure, I will definitely make this as an option.

@wilzbach
Copy link
Member Author

Good news 🎉
I finally got this to work, see e.g. https://dub-registry.herokuapp.com

I managed to get the app to start on Heroku, but currently it still fails with:

This was due to "vpmreg" being the default database (and thus getting the segfaults).
FWIW MongoSettings.safe would have shown a nice error message like "not authorized for insert on vpmreg.packages" instead of the rather unspecific Exception from above -> vibe-d/vibe.d#1858

Also for the future it might make sense to show a warning about a non-existent database directly at the handleQuery Exception: vibe-d/vibe.d#1859

. "You can host your own registry instance for private repos.".
That's actually a good use case and once we have figured out the Mongo failure, I will definitely make this as an option.

This could be a follow-up to this PR - this one is big enough already.

Copy link
Member

@MartinNowak MartinNowak left a comment

Choose a reason for hiding this comment

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

Looks OKish

Procfile Outdated
@@ -0,0 +1,3 @@
default_process_types:
web: ./dub-registry --port $PORT --mirror=https://code.dlang.org --hostname=dub-registry.heroku.com --separate-cron --vv --bind 0.0.0.0
cron: ./dub-registry --mirror=https://code.dlang.org --run-cron --vv
Copy link
Member

Choose a reason for hiding this comment

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

Not particularly nice as a cron task in a separate process cannot update in-process caches.
Might be problematic during future development, just support a minor Heroku suspend case.
Any other ideas?

Copy link
Member Author

Choose a reason for hiding this comment

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

Not really. Heroku instances fall asleep very soon, so chances are good that the main dyno gets suspended / terminated a lot anyways.

MongoClientSettings mongoSettings;
string databaseName = "vpmreg";

shared static this()
Copy link
Member

Choose a reason for hiding this comment

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

To avoid another shared static this(), maybe lazily initialize settings or just parse them everytime connectMongoDB is called (once usually).

README.md Outdated
Select the "Scheduler" addon and add the following task:

```
./dub-registry --mirror=https://code.dlang.org --run-cron --vv
Copy link
Member

@MartinNowak MartinNowak Jul 25, 2017

Choose a reason for hiding this comment

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

I'd say the private registry use-case is more interesting than encouraging dozens of mirrors, in particular with the current inefficient mirror protocol.

@dlang-bot
Copy link
Collaborator

Thanks for your pull request, @wilzbach!

@wilzbach
Copy link
Member Author

Not particularly nice as a cron task in a separate process cannot update in-process caches.
Might be problematic during future development, just support a minor Heroku suspend case.
Any other ideas?

Dynos are stopped and restarted on the free version of Heroku quite often anyways and this doesn't affect the default in-process cron job (it's an opt-in CLI flag).

I'd say the private registry use-case is more interesting than encouraging dozens of mirrors, in particular with the current inefficient mirror protocol.

Well, for now, having one free mirror node in a totally different network is quite nice and of course I agree that being able to run a private mirror directly in Heroku would be quite nice, but it's a lot more complicated, e.g.

  • setting GitHub / GitLab authorization credentials
  • Allowing clients to securely & privately access the registry

As a serious company wouldn't host their code with a third-party provider anyways, this is more "fun" use-case, but in any case, this PR should lay the groundworks if this becomes interesting to anyone.

Addressed other comments and rebased.

source/app.d Outdated

readOption("mirror", &s_mirror, "URL of a package registry that this instance should mirror (WARNING: will overwrite local database!)");
readOption("hostname", &hostname, "Domain name of this instance (default: code.dlang.org)");
readOption("separate-cron", &separateCron, "Use a separate cron job to query for packages.");
Copy link
Member Author

Choose a reason for hiding this comment

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

We could also remove this flag as the dyno must likely gets suspended and one or two additional updates won't be problematic.

@MartinNowak
Copy link
Member

The readme still says Deploy your own mirror in a header.
There is no point in having 10 people run a dub-registry mirror on Heroku just because they can.
It will cause unnecessary traffic and load on our main dub-registry instance.
The only interesting use-case is running a separate registry with unofficial/private repos (and optionally mirror-mode fou your Heroku mirror).

@wilzbach
Copy link
Member Author

I just found a new use case for this: setting up automatic deployment to Heroku is really easy, so we could do the following setup:

  • master -> automatic deployment to dub-registry.herokuapp.com
  • testing -> automatic deployment to dub-registry-testing.herokuapp.com

testing could be an unprotected branch to which people can force-push their changes to let everyone preview their PR (like alpha.dub.pm).

So can we move forward with this?

@s-ludwig
Copy link
Member

Mainly Martin's comment about the mirror vs. private registry still stands. I'd agree that we shouldn't unnecessarily advertise the mirror mode at this point, especially because we don't have means to make this a trusted process (e.g. signing the database snapshot), so encouraging the use of code.dlang.org mirrors that are not controlled by trusted people would not be a good idea.

@wilzbach
Copy link
Member Author

Mainly Martin's comment about the mirror vs. private registry still stands. I'd agree that we shouldn't unnecessarily advertise the mirror mode at this point,

OK. Is removing the "Deploy to Heroku" badge from the README enough? I would leave the app.json config for Heroku in as at some point I can/will/might get back to the deploying your private registry use case.

@MartinNowak
Copy link
Member

Yes, a staging preview instance for PRs on Heroku would be nice.

Copy link
Member

@MartinNowak MartinNowak left a comment

Choose a reason for hiding this comment

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

Otherwise LGTM.

source/app.d Outdated
@@ -80,12 +91,20 @@ shared static this()

auto router = new URLRouter;
if (s_mirror.length) router.any("*", (req, res) { req.params["mirror"] = s_mirror; });
router.get("*", (req, res) @trusted { if (!s_checkTask.running) startMonitoring(); });
Copy link
Member

Choose a reason for hiding this comment

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

The check task shouldn't die, so that looks more like a safety guard.

source/app.d Outdated

readOption("mirror", &s_mirror, "URL of a package registry that this instance should mirror (WARNING: will overwrite local database!)");
readOption("hostname", &hostname, "Domain name of this instance (default: code.dlang.org)");
readOption("separate-cron", &separateCron, "Use a separate cron job to query for packages.");
Copy link
Member

Choose a reason for hiding this comment

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

Let's remove the separate cron, it seems superfluous, even on Heroku.

Copy link
Member Author

Choose a reason for hiding this comment

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

Heroku suspends the dynos if they aren't run. How else would we make sure that the DB gets updated at least daily?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok removed.

@wilzbach wilzbach force-pushed the deploy-on-heroku branch 4 times, most recently from 31334fa to afc618b Compare March 30, 2018 03:36
@@ -5,6 +5,7 @@ block title

block body
- import vibe.textfilter.urlencode;
- import std.algorithm.searching : startsWith;
Copy link
Member Author

Choose a reason for hiding this comment

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

if (!branch_or_version.startsWith("~")) (below)

@wilzbach wilzbach force-pushed the deploy-on-heroku branch 6 times, most recently from 2b98f05 to 2e3bf97 Compare June 29, 2018 18:49
@wilzbach
Copy link
Member Author

So I'm gave this another shot as I want to setup Heroku Review Apps. In short. For each PR, a new temporary dyno will be created and be existent for five days (the limit can be customized).
I also removed the controversial bit about deploying a mirror on Heroku and running a separate cron.
However, it now fails with:

2018-06-29T18:03:58.732613+00:00 heroku[web.1]: Starting process with command `./dub-registry --port 43675 --hostname=dub-registry.heroku.com --vv --bind 0.0.0.0`
2018-06-29T18:04:01.339272+00:00 app[web.1]: [main(----) dbg] Initializing OpenSSL...
2018-06-29T18:04:01.339295+00:00 app[web.1]: [main(----) dbg] ... done.
2018-06-29T18:04:01.339296+00:00 app[web.1]: Enforcing certificate trust.
2018-06-29T18:04:01.339298+00:00 app[web.1]: [main(----) dbg] add route GET *
2018-06-29T18:04:01.339303+00:00 app[web.1]: [main(----) dbg] creating new MongoConnection connection, all 0 are in use

I tried disabling the userman part, but without luck so far.
Any ideas?

@wilzbach wilzbach temporarily deployed to dub-registry-staging June 29, 2018 18:57 Inactive
@wilzbach wilzbach changed the title Add deploy on Heroku badge Add deploy on Heroku (via badge) Jul 5, 2018
@wilzbach
Copy link
Member Author

wilzbach commented Jul 5, 2018

Finally figured it out and it's working -> https://dub-registry-staging.herokuapp.com
Travis will fail for now as Vibe.d doesn't work with 2.081 (vibe-d/vibe.d#2181)

@@ -0,0 +1 @@
dmd-2.080.1
Copy link
Member Author

Choose a reason for hiding this comment

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

Required as Vibe.d currently doesn't build with 2.081 (see e.g. vibe-d/vibe.d#2181)

@wilzbach
Copy link
Member Author

wilzbach commented Jul 6, 2018

Going to merge this now as this has been open for more than a year, no one seems to be actively objecting this and I want to get started on the Heroku PR preview.

@wilzbach wilzbach merged commit a76cdec into dlang:master Jul 6, 2018
@wilzbach wilzbach deleted the deploy-on-heroku branch July 6, 2018 17:46
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