lein new duct

This commit is contained in:
Marcin Kulik 2017-01-07 16:45:14 +01:00
parent 75143edddf
commit af35483f2d
17 changed files with 467 additions and 94 deletions

16
.gitignore vendored
View File

@ -23,10 +23,16 @@ public/uploads/*
.rbx
.env
/.dir-locals.el
/.lein-env
/.lein-repl-history
/target
/classes
/checkouts
pom.xml
pom.xml.asc
*.jar
*.class
/.lein-*
/.nrepl-port
/dev/
/.dir-locals.el
/profiles.clj
/target/
/dev/resources/local.edn
/dev/src/local.clj

202
README.md
View File

@ -1,116 +1,140 @@
# asciinema.org
# asciinema
[![Build Status](https://travis-ci.org/asciinema/asciinema.org.svg?branch=master)](https://travis-ci.org/asciinema/asciinema.org)
[![Code Climate](https://codeclimate.com/github/asciinema/asciinema.org/badges/gpa.svg)](https://codeclimate.com/github/asciinema/asciinema.org)
[![Coverage Status](https://coveralls.io/repos/asciinema/asciinema.org/badge.svg)](https://coveralls.io/r/asciinema/asciinema.org)
FIXME: description
Record and share your terminal sessions, the right way.
## Developing
asciinema is a free and open source solution for recording terminal sessions
and sharing them on the web.
### Setup
This is the source code of asciinema.org website. You can find asciinema's
terminal recorder at
[asciinema/asciinema](https://github.com/asciinema/asciinema) and asciinema
player at
[asciinema/asciinema-player](https://github.com/asciinema/asciinema-player).
## Setup instructions
Below you'll find setup instructions in case you want to contribute, play with
it on your local machine, or setup your own instance for private use or for
your organization.
### Quickstart Using Docker Compose
Required:
- [Docker](https://docs.docker.com/engine/getstarted/step_one/#step-1-get-docker)
- [docker-compose 1.5+](https://docs.docker.com/compose/install/)
```bash
$ wget https://raw.githubusercontent.com/asciinema/asciinema.org/master/docker-compose.yml
$ docker-compose up -d asciinema
$ docker-compose run --rm db_init
When you first clone this repository, run:
```sh
lein setup
```
You can override the address/port that is sent in email with login token by passing HOST="host:port" environment variable when starting the web server.
This will create files for local configuration, and prep your system
for the project.
Assuming you are running Docker Toolbox and VirtualBox: go to http://192.168.99.100:3000/ and enjoy.
### Environment
### Manual setup
To begin developing, start with a REPL.
#### 1. Install dependencies
asciinema.org site is a Ruby on Rails application. You need to have following
dependencies installed:
* Ruby 2.0+ (Ruby 2.1 is recommended)
* bundler gem
`gem install bundler`
* PostgreSQL 8+ with libpq development headers
`sudo apt-get install postgresql libpq-dev` on Debian/Ubuntu
* asciinema's libtsm fork (`asciinema` branch)
See [here](https://github.com/asciinema/libtsm/blob/asciinema/README) for installation instructions.
If you don't install it now the setup script (point 4 below) will try to
install it for you anyway.
* phantomjs 2.0+
`sudo add-apt-repository ppa:tanguy-patte/phantomjs && sudo apt-get update && sudo apt-get install phantomjs`
#### 2. Get the source code
Clone git repository:
```bash
$ git clone git://github.com/asciinema/asciinema.org.git
$ cd asciinema.org
```sh
lein repl
```
#### 3. Prepare database config file
Then load the development environment.
Copy *config/database.yml.example* to *config/database.yml*. Then set
database/user/password to whatever you prefer.
If database specified in database.yml doesn't exist then the following setup
task will create it (make sure database user is allowed to create new
databases).
#### 4. Setup the app
Following script will install gem dependencies and setup database:
```bash
$ ./script/setup
```clojure
user=> (dev)
:loaded
```
#### 5. Run Rails server
Run `go` to initiate and start the system.
```bash
$ bundle exec rails server
```clojure
dev=> (go)
:started
```
#### 6. Run the background job processor
By default this creates a web server at <http://localhost:3000>.
The background job processor is needed for asciicast pre-processing and
thumbnail generation.
When you make changes to your source files, use `reset` to reload any
modified files and reset the server.
```bash
$ bundle exec sidekiq
```clojure
dev=> (reset)
:reloading (...)
:resumed
```
## Contributing
### Testing
If you want to contribute to this project check out
[Contributing](http://asciinema.org/contributing) page.
Testing is fastest through the REPL, as you avoid environment startup
time.
## Authors
```clojure
dev=> (test)
...
```
Developed with passion by [Marcin Kulik](http://ku1ik.com) and great open
source [contributors](https://github.com/asciinema/asciinema.org/contributors)
But you can also run tests through Leiningen.
## Copyright
```sh
lein test
```
Copyright &copy; 2011-2016 Marcin Kulik. See LICENSE.txt for details.
### Migrations
Migrations are handled by [ragtime][]. Migration files are stored in
the `resources/migrations` directory, and are applied in alphanumeric
order.
To update the database to the latest migration, open the REPL and run:
```clojure
dev=> (migrate)
Applying 20150815144312-create-users
Applying 20150815145033-create-posts
```
To rollback the last migration, run:
```clojure
dev=> (rollback)
Rolling back 20150815145033-create-posts
```
Note that the system needs to be setup with `(init)` or `(go)` before
migrations can be applied.
[ragtime]: https://github.com/weavejester/ragtime
### Generators
This project has several generator functions to help you create files.
To create a new endpoint:
```clojure
dev=> (gen/endpoint "bar")
Creating file src/foo/endpoint/bar.clj
Creating file test/foo/endpoint/bar_test.clj
Creating directory resources/foo/endpoint/bar
nil
```
To create a new component:
```clojure
dev=> (gen/component "baz")
Creating file src/foo/component/baz.clj
Creating file test/foo/component/baz_test.clj
nil
```
To create a new boundary:
```clojure
dev=> (gen/boundary "quz" foo.component.baz.Baz)
Creating file src/foo/boundary/quz.clj
Creating file test/foo/boundary/quz_test.clj
nil
```
To create a new SQL migration:
```clojure
dev=> (gen/sql-migration "create-users")
Creating file resources/foo/migrations/20160519143643-create-users.up.sql
Creating file resources/foo/migrations/20160519143643-create-users.down.sql
nil
```
## Deploying
FIXME: steps to deploy
## Legal
Copyright © 2017 FIXME

9
dev/resources/dev.edn Normal file
View File

@ -0,0 +1,9 @@
{:config
{:app
{:middleware
{:functions {:stacktrace #var ring.middleware.stacktrace/wrap-stacktrace}
:applied ^:replace [:not-found :webjars :ring-defaults :route-aliases :stacktrace]}}
:http
{:port 4000}
:db
{:uri "jdbc:postgresql://localhost/postgres"}}}

21
dev/src/dev.clj Normal file
View File

@ -0,0 +1,21 @@
(ns dev
(:refer-clojure :exclude [test])
(:require [clojure.repl :refer :all]
[clojure.pprint :refer [pprint]]
[clojure.tools.namespace.repl :refer [refresh]]
[clojure.java.io :as io]
[com.stuartsierra.component :as component]
[duct.generate :as gen]
[duct.util.repl :refer [setup test cljs-repl migrate rollback]]
[duct.util.system :refer [load-system]]
[reloaded.repl :refer [system init start stop go reset]]))
(defn new-system []
(load-system (keep io/resource ["asciinema/system.edn" "dev.edn" "local.edn"])))
(when (io/resource "local.clj")
(load "local"))
(gen/set-ns-prefix 'asciinema)
(reloaded.repl/set-init! new-system)

8
dev/src/user.clj Normal file
View File

@ -0,0 +1,8 @@
(ns user)
(defn dev
"Load and switch to the 'dev' namespace."
[]
(require 'dev)
(in-ns 'dev)
:loaded)

40
project.clj Normal file
View File

@ -0,0 +1,40 @@
(defproject asciinema "0.1.0-SNAPSHOT"
:description "FIXME: write description"
:url "http://example.com/FIXME"
:min-lein-version "2.0.0"
:dependencies [[org.clojure/clojure "1.8.0"]
[com.stuartsierra/component "0.3.1"]
[compojure "1.5.1"]
[duct "0.8.2"]
[environ "1.1.0"]
[ring "1.5.0"]
[ring/ring-defaults "0.2.1"]
[ring-jetty-component "0.3.1"]
[ring-webjars "0.1.1"]
[org.slf4j/slf4j-nop "1.7.21"]
[org.webjars/normalize.css "3.0.2"]
[duct/hikaricp-component "0.1.0"]
[org.postgresql/postgresql "9.4.1211"]
[duct/ragtime-component "0.1.4"]]
:plugins [[lein-environ "1.0.3"]]
:main ^:skip-aot asciinema.main
:target-path "target/%s/"
:aliases {"setup" ["run" "-m" "duct.util.repl/setup"]}
:profiles
{:dev [:project/dev :profiles/dev]
:test [:project/test :profiles/test]
:uberjar {:aot :all}
:profiles/dev {}
:profiles/test {}
:project/dev {:dependencies [[duct/generate "0.8.2"]
[reloaded.repl "0.2.3"]
[org.clojure/tools.namespace "0.2.11"]
[org.clojure/tools.nrepl "0.2.12"]
[eftest "0.1.1"]
[com.gearswithingears/shrubbery "0.4.1"]
[kerodon "0.8.0"]]
:source-paths ["dev/src"]
:resource-paths ["dev/resources"]
:repl-options {:init-ns user}
:env {:port "3000"}}
:project/test {}})

View File

@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en" class="example">
<head>
<title>Example Endpoint</title>
<link rel="stylesheet" href="/assets/normalize.css/normalize.css">
<link rel="stylesheet" href="/css/site.css">
</head>
<body>
<h1>This is an example endpoint</h1>
</body>
</html>

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en" class="error-page">
<head>
<title>Server Error</title>
<link rel="stylesheet" href="/assets/normalize.css/normalize.css">
<link rel="stylesheet" href="/css/site.css">
</head>
<body>
<h1>Resource Not Found</h1>
<h2>The requested page does not exist.</h2>
</body>
</html>

View File

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html lang="en" class="error-page">
<head>
<title>Server Error</title>
<link rel="stylesheet" href="/assets/normalize.css/normalize.css">
<link rel="stylesheet" href="/css/site.css">
</head>
<body>
<h1>Internal Server Error</h1>
<h2>Sorry, something went wrong.</h2>
</body>
</html>

View File

@ -0,0 +1,103 @@
.error-page body {
background: #eee;
}
.error-page h1 {
margin: 15% 0 0 0;
text-align: center;
font-size: 42px;
color: #900;
}
.error-page h2 {
text-align: center;
font-size: 32px;
font-weight: normal;
color: #333;
}
.welcome body {
background: #eee;
color: #333;
font-family: Helvetica, Arial, sans-serif;
max-width: 700px;
padding: 15px;
margin: auto;
}
.welcome p {
line-height: 1.4em;
}
.welcome code {
font-family: Menlo, DejaVu Sans Mono, Lucida Console, monospace;
font-size: 12px;
background: #ddd;
color: #111;
}
.welcome h1 {
text-align: center;
font-size: 36px;
font-weight: lighter;
margin: 40px 0 30px 0;
}
.welcome h1 .outer {
border: solid 4px #555;
padding: 3px;
display: inline-block;
}
.welcome h1 .inner {
border: solid 2px #555;
padding: 0 3px;
display: inline-block;
font-weight: normal;
color: #444;
}
.welcome .project-name {
font-weight: bold;
}
.welcome .profiles {
margin-top: 30px;
}
.welcome .profiles code {
font-size: 11px;
}
.welcome .profiles h2 {
font-weight: normal;
font-size: 23px;
margin-bottom: 0;
color: #333;
}
.welcome .profiles dl {
margin: 0 10px;
}
.welcome .profiles dt {
font-weight: normal;
font-size: 19px;
margin: 18px 0 5px 0;
}
.welcome .profiles dd {
font-size: 14px;
margin: 8px 0 8px 0;
}
.example body {
background: #eee;
}
.example h1 {
margin: 15% 0 0 0;
text-align: center;
font-size: 36px;
font-weight: normal;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en" class="welcome">
<head>
<title>Welcome to Duct</title>
<link rel="stylesheet" href="/assets/normalize.css/normalize.css">
<link rel="stylesheet" href="/css/site.css">
</head>
<body>
<h1>Welcome to <span class="outer"><span class="inner">Duct</span></span></h1>
<div class="intro">
<p>Congratulations! Your project <span class="project-name">asciinema</span> is
ready and running.</p>
<p>This is a static welcome page located at <code>resources/asciinema/public/index.html</code>
in the project directory. Remove or replace it when you start developing.
If you remove the index page entirely, be sure to change the
<code>:route-aliases</code> map in <code>resources/asciinema/system.edn</code>.
</div>
<div class="profiles">
<h2>Template profiles used:</h2>
<dl>
<dt>+example</dt>
<dd>Adds an example endpoint at <a href="/example">/example</a>.</dd>
<dt>+postgres</dt>
<dd>Adds a PostgreSQL dependency and database component. The database used for
development defaults to <code>postgres</code> on <code>localhost</code>.</dd>
<dt>+ragtime</dt>
<dd>Adds Ragtime migrations. Use <code>(migrate)</code> and <code>(rollback)</code>
in the REPL. Migrations are stored in <code>resources/asciinema/migrations</code>.
</dd>
<dt>+site</dt>
<dd>Adds middleware and configuration suited for a user-facing website.</dd>
</dl>
</div>
</body>
</html>

View File

@ -0,0 +1,2 @@
User-agent: *
Disallow:

View File

@ -0,0 +1,50 @@
{:components
{:app #var duct.component.handler/handler-component
:http #var ring.component.jetty/jetty-server
:db #var duct.component.hikaricp/hikaricp
:ragtime #var duct.component.ragtime/ragtime}
:endpoints
{:example #var asciinema.endpoint.example/example-endpoint}
:dependencies
{:http [:app]
:app [:example]
:ragtime [:db]
:example [:db]}
:config
{:app
{:middleware
{:functions
{:hide-errors #var duct.middleware.errors/wrap-hide-errors
:not-found #var duct.middleware.not-found/wrap-not-found
:ring-defaults #var ring.middleware.defaults/wrap-defaults
:route-aliases #var duct.middleware.route-aliases/wrap-route-aliases
:webjars #var ring.middleware.webjars/wrap-webjars}
:applied
[:not-found :webjars :ring-defaults :route-aliases :hide-errors]
:arguments
{:not-found #resource "asciinema/errors/404.html"
:hide-errors #resource "asciinema/errors/500.html"
:route-aliases {"/" "/index.html"}
:ring-defaults
{:params {:urlencoded true
:keywordize true
:multipart true
:nested true}
:cookies true
:session {:flash true
:cookie-attrs {:http-only true}}
:security {:anti-forgery true
:xss-protection {:enable? true, :mode :block}
:frame-options :sameorigin
:content-type-options :nosniff}
:static {:resources "asciinema/public"}
:responses {:not-modified-responses true
:absolute-redirects true
:content-types true
:default-charset "utf-8"}}}}}
:http
{:port http-port}
:db
{:uri db-uri}
:ragtime
{:resource-path "asciinema/migrations"}}}

View File

@ -0,0 +1,8 @@
(ns asciinema.endpoint.example
(:require [compojure.core :refer :all]
[clojure.java.io :as io]))
(defn example-endpoint [{{db :spec} :db}]
(context "/example" []
(GET "/" []
(io/resource "asciinema/endpoint/example/example.html"))))

15
src/asciinema/main.clj Normal file
View File

@ -0,0 +1,15 @@
(ns asciinema.main
(:gen-class)
(:require [com.stuartsierra.component :as component]
[duct.util.runtime :refer [add-shutdown-hook]]
[duct.util.system :refer [load-system]]
[environ.core :refer [env]]
[clojure.java.io :as io]))
(defn -main [& args]
(let [bindings {'http-port (Integer/parseInt (:port env "3000"))
'db-uri (:database-url env)}
system (->> (load-system [(io/resource "asciinema/system.edn")] bindings)
(component/start))]
(add-shutdown-hook ::stop-system #(component/stop system))
(println "Started HTTP server on port" (-> system :http :port))))

View File

@ -0,0 +1,16 @@
(ns asciinema.endpoint.example-test
(:require [com.stuartsierra.component :as component]
[clojure.test :refer :all]
[kerodon.core :refer :all]
[kerodon.test :refer :all]
[shrubbery.core :as shrub]
[asciinema.endpoint.example :as example]))
(def handler
(example/example-endpoint {}))
(deftest smoke-test
(testing "example page exists"
(-> (session handler)
(visit "/example")
(has (status? 200) "page exists"))))