Configurability, to permit running a development instance that doesn't touch prod.
This commit is contained in:
parent
0df0c2d06b
commit
b36882fa63
65
README.md
65
README.md
|
@ -6,6 +6,53 @@ You will need to install the following Racket packages:
|
||||||
|
|
||||||
raco pkg install reloadable
|
raco pkg install reloadable
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
See the directory `configs/` for example configuration files. To
|
||||||
|
select a configuration file, set the environment variable `CONFIG` to
|
||||||
|
its base filename. For example, to select `configs/live.rkt`, set
|
||||||
|
`CONFIG` to `live`. A good place to do this is in the `run-prelude`
|
||||||
|
file; see the description of `run-prelude` below.
|
||||||
|
|
||||||
|
If `CONFIG` is not set, it defaults to the short hostname of the
|
||||||
|
machine (`hostname -s`).
|
||||||
|
|
||||||
|
Within a configuration file, configuration details are to be given as
|
||||||
|
a hashtable to `main`.
|
||||||
|
|
||||||
|
Keys useful for deployment:
|
||||||
|
|
||||||
|
- *port*: number; default the value of the `SITE_PORT` environment
|
||||||
|
variable, if defined; otherwise, 8443.
|
||||||
|
- *ssl?*: boolean; default `#t`.
|
||||||
|
- *reloadable?*: boolean; `#t` if the `SITE_RELOADABLE` environment
|
||||||
|
variable is defined; otherwise, `#f`.
|
||||||
|
- *recent-seconds*: number, in seconds; default 172800. Packages
|
||||||
|
modified fewer than this many seconds ago are considered "recent",
|
||||||
|
and displayed as such in the UI.
|
||||||
|
|
||||||
|
Keys useful for development:
|
||||||
|
|
||||||
|
- *package-index-url*: string; default
|
||||||
|
`http://pkgs.racket-lang.org/pkgs-all.json.gz`.
|
||||||
|
- *package-fetch-interval*; number, in seconds; default 300.
|
||||||
|
- *session-lifetime*: number, in seconds; default 604800.
|
||||||
|
- *static-cached-directory*: string; names a directory relative to
|
||||||
|
`src/` within which generated static HTML files are to be placed.
|
||||||
|
Must be writable by the user running the server.
|
||||||
|
- *static-cached-urlprefix*: string; absolute or relative URL,
|
||||||
|
prepended to relative URLs referring to generated static HTML files
|
||||||
|
placed in `static-cached-directory`.
|
||||||
|
- *disable-cache?*: boolean; default `#f`.
|
||||||
|
- *backend-baseurl*: string; default `https://pkgd.racket-lang.org`.
|
||||||
|
Must point to the backend package server API root, such that (for
|
||||||
|
example) `/jsonp/authenticate`, when appended to it, resolves to
|
||||||
|
the authentication call.
|
||||||
|
- *pkg-build-baseurl*: string; default
|
||||||
|
`http://pkg-build.racket-lang.org/`. Used to build URLs relative to
|
||||||
|
the package build host, for such as documentation links and build
|
||||||
|
reports.
|
||||||
|
|
||||||
## Local testing
|
## Local testing
|
||||||
|
|
||||||
You will need some dummy SSL keys. Run `make keys` to produce some.
|
You will need some dummy SSL keys. Run `make keys` to produce some.
|
||||||
|
@ -19,8 +66,8 @@ compiles the code and starts the server.
|
||||||
### Automatic code reloading
|
### Automatic code reloading
|
||||||
|
|
||||||
If you would like to enable the automatic code-reloading feature, set
|
If you would like to enable the automatic code-reloading feature, set
|
||||||
the environment variable `SITE_RELOADABLE` to a non-empty string. (A
|
the environment variable `SITE_RELOADABLE` to a non-empty string or
|
||||||
good place to do that is in a `run-prelude` script; see below.)
|
set the `reloadable?` configuration variable to `#t`.
|
||||||
|
|
||||||
You must also delete any compiled code `.zo` files. Otherwise, the
|
You must also delete any compiled code `.zo` files. Otherwise, the
|
||||||
system will not be able to correctly replace modules while running.
|
system will not be able to correctly replace modules while running.
|
||||||
|
@ -44,7 +91,8 @@ logging of stdout/stderr.
|
||||||
If the file `run-prelude` exists in the same directory as `run`, it
|
If the file `run-prelude` exists in the same directory as `run`, it
|
||||||
will be dotted in before racket is invoked. I use this to update my
|
will be dotted in before racket is invoked. I use this to update my
|
||||||
`PATH` to include my locally-built racket `bin` directory, necessary
|
`PATH` to include my locally-built racket `bin` directory, necessary
|
||||||
because I don't have a system-wide racket.
|
because I don't have a system-wide racket, and to select an
|
||||||
|
appropriate `CONFIG` setting.
|
||||||
|
|
||||||
On Debian, daemontools can be installed with `apt-get install
|
On Debian, daemontools can be installed with `apt-get install
|
||||||
daemontools daemontools-run`, and the services directory is
|
daemontools daemontools-run`, and the services directory is
|
||||||
|
@ -61,6 +109,17 @@ You can send signals to the running service by creating files in
|
||||||
- creating `.restart-required` causes it to exit, to be restarted by
|
- creating `.restart-required` causes it to exit, to be restarted by
|
||||||
daemontools.
|
daemontools.
|
||||||
|
|
||||||
|
- creating `.reload` causes an explicit code reload. Useful when
|
||||||
|
automatic code reloading is disabled.
|
||||||
|
|
||||||
|
- creating `.fetchindex` causes an immediate refetch of the package
|
||||||
|
index from the backend server.
|
||||||
|
|
||||||
|
- creating `.rerender` causes an immediate rerendering of all
|
||||||
|
generated static HTML files.
|
||||||
|
|
||||||
|
See `src/signals.rkt` for details of the available signals.
|
||||||
|
|
||||||
So long as `sudo chmod 0777 /etc/service/webservice/signals`, these
|
So long as `sudo chmod 0777 /etc/service/webservice/signals`, these
|
||||||
are useful for non-root administrators to control the running service.
|
are useful for non-root administrators to control the running service.
|
||||||
|
|
||||||
|
|
4
configs/live.rkt
Normal file
4
configs/live.rkt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#lang racket/base
|
||||||
|
;; Default configuration; should be suitable for live deployment.
|
||||||
|
(require "../src/main.rkt")
|
||||||
|
(main)
|
6
configs/tonyg.rkt
Normal file
6
configs/tonyg.rkt
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#lang racket/base
|
||||||
|
;; Configuration for tonyg's development setup.
|
||||||
|
(require "../src/main.rkt")
|
||||||
|
(main (hash 'port 8444
|
||||||
|
'reloadable? #t
|
||||||
|
))
|
16
run
16
run
|
@ -1,7 +1,19 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
if [ -f ./run-prelude ]; then . ./run-prelude; fi
|
if [ -f ./run-prelude ]; then . ./run-prelude; fi
|
||||||
cd src
|
|
||||||
|
if [ -z "$CONFIG" ]; then
|
||||||
|
CONFIG=$(hostname -s)
|
||||||
|
echo 'Environment variable CONFIG not defined; defaulting to "'"${CONFIG}"'"'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f configs/${CONFIG}.rkt ]; then
|
||||||
|
echo "Config ${CONFIG} not found: config/${CONFIG}.rkt not readable"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
PLTSTDERR=info
|
PLTSTDERR=info
|
||||||
export PLTSTDERR
|
export PLTSTDERR
|
||||||
echo '============================================='
|
echo '============================================='
|
||||||
exec racket main.rkt 2>&1
|
cd src
|
||||||
|
exec racket ../configs/${CONFIG}.rkt 2>&1
|
||||||
|
|
9
src/config.rkt
Normal file
9
src/config.rkt
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#lang racket/base
|
||||||
|
|
||||||
|
(provide config)
|
||||||
|
|
||||||
|
(require reloadable)
|
||||||
|
|
||||||
|
(define *config* (make-persistent-state '*config* (lambda () config)))
|
||||||
|
|
||||||
|
(define (config) (*config*))
|
17
src/main.rkt
17
src/main.rkt
|
@ -1,11 +1,18 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
|
|
||||||
(module+ main
|
(provide main)
|
||||||
(require "entrypoint.rkt")
|
|
||||||
|
(require reloadable)
|
||||||
|
(require "entrypoint.rkt")
|
||||||
|
|
||||||
|
(define (main [config (hash)])
|
||||||
|
(make-persistent-state '*config* (lambda () config))
|
||||||
(void (make-reloadable-entry-point 'refresh-packages! "packages.rkt"))
|
(void (make-reloadable-entry-point 'refresh-packages! "packages.rkt"))
|
||||||
(void (make-reloadable-entry-point 'rerender-all! "site.rkt"))
|
(void (make-reloadable-entry-point 'rerender-all! "site.rkt"))
|
||||||
(start-service #:reloadable? (getenv "SITE_RELOADABLE")
|
(start-service #:port (hash-ref config 'port (lambda ()
|
||||||
#:port (let ((port-str (getenv "SITE_PORT")))
|
(let ((port-str (getenv "SITE_PORT")))
|
||||||
(if port-str (string->number port-str) 8443))
|
(if port-str (string->number port-str) 8443))))
|
||||||
|
#:ssl? (hash-ref config 'ssl? (lambda () #t))
|
||||||
|
#:reloadable? (hash-ref config 'reloadable? (lambda () (getenv "SITE_RELOADABLE")))
|
||||||
(make-reloadable-entry-point 'request-handler "site.rkt")
|
(make-reloadable-entry-point 'request-handler "site.rkt")
|
||||||
(make-reloadable-entry-point 'on-continuation-expiry "site.rkt")))
|
(make-reloadable-entry-point 'on-continuation-expiry "site.rkt")))
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
(require web-server/private/gzip)
|
(require web-server/private/gzip)
|
||||||
(require net/url)
|
(require net/url)
|
||||||
(require reloadable)
|
(require reloadable)
|
||||||
|
(require "config.rkt")
|
||||||
(require "daemon.rkt")
|
(require "daemon.rkt")
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -41,8 +42,15 @@
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
||||||
(define package-index-url "http://pkgs.racket-lang.org/pkgs-all.json.gz")
|
(define package-index-url
|
||||||
(define package-fetch-interval (* 300 1000)) ;; 300 seconds = 300,000 milliseconds = 5 minutes
|
(or (@ (config) package-index-url)
|
||||||
|
"http://pkgs.racket-lang.org/pkgs-all.json.gz"))
|
||||||
|
|
||||||
|
(define package-fetch-interval
|
||||||
|
(* (or (@ (config) package-fetch-interval)
|
||||||
|
300) ;; 300 seconds = 5 minutes
|
||||||
|
1000)) ;; convert to milliseconds
|
||||||
|
|
||||||
(define base-bogus-timeout (* 5 1000)) ;; 5 seconds
|
(define base-bogus-timeout (* 5 1000)) ;; 5 seconds
|
||||||
|
|
||||||
(struct package-manager-state (local-packages
|
(struct package-manager-state (local-packages
|
||||||
|
|
|
@ -10,10 +10,14 @@
|
||||||
lookup-session)
|
lookup-session)
|
||||||
|
|
||||||
(require "randomness.rkt")
|
(require "randomness.rkt")
|
||||||
|
(require "config.rkt")
|
||||||
(require reloadable)
|
(require reloadable)
|
||||||
|
|
||||||
(define current-session (make-parameter #f))
|
(define current-session (make-parameter #f))
|
||||||
(define session-lifetime (make-parameter (* 7 24 60 60 1000))) ;; one week in milliseconds
|
(define session-lifetime
|
||||||
|
(* (or (hash-ref (config) 'session-lifetime-seconds #f)
|
||||||
|
(* 7 24 60 60)) ;; one week in seconds
|
||||||
|
1000)) ;; convert to milliseconds
|
||||||
|
|
||||||
(struct session (key expiry email password) #:prefab)
|
(struct session (key expiry email password) #:prefab)
|
||||||
|
|
||||||
|
|
29
src/site.rkt
29
src/site.rkt
|
@ -22,11 +22,19 @@
|
||||||
(require "jsonp-client.rkt")
|
(require "jsonp-client.rkt")
|
||||||
(require reloadable)
|
(require reloadable)
|
||||||
(require "daemon.rkt")
|
(require "daemon.rkt")
|
||||||
|
(require "config.rkt")
|
||||||
|
|
||||||
(define static-cached-directory "../static/cached")
|
(define static-cached-directory
|
||||||
(define static-cached-urlprefix "/cached")
|
(or (@ (config) static-cached-directory)
|
||||||
|
"../static/cached"))
|
||||||
|
|
||||||
(define disable-cache? #f)
|
(define static-cached-urlprefix
|
||||||
|
(or (@ (config) static-cached-urlprefix)
|
||||||
|
"/cached"))
|
||||||
|
|
||||||
|
(define disable-cache?
|
||||||
|
(or (@ (config) disable-cache?)
|
||||||
|
#f))
|
||||||
|
|
||||||
(define nav-index "Package Index")
|
(define nav-index "Package Index")
|
||||||
(define nav-search "Search")
|
(define nav-search "Search")
|
||||||
|
@ -44,11 +52,20 @@
|
||||||
;; "http://download.racket-lang.org/")
|
;; "http://download.racket-lang.org/")
|
||||||
))
|
))
|
||||||
|
|
||||||
(define backend-baseurl "https://pkgd.racket-lang.org")
|
(define backend-baseurl
|
||||||
|
(or (@ (config) backend-baseurl)
|
||||||
|
"https://pkgd.racket-lang.org"))
|
||||||
|
|
||||||
(define default-empty-source-url "git://github.com//")
|
(define default-empty-source-url "git://github.com//")
|
||||||
(define COOKIE "pltsession")
|
(define COOKIE "pltsession")
|
||||||
(define recent-seconds (* 2 24 60 60)) ;; two days
|
|
||||||
|
(define recent-seconds
|
||||||
|
(or (@ (config) recent-seconds)
|
||||||
|
(* 2 24 60 60))) ;; two days
|
||||||
|
|
||||||
|
(define pkg-build-baseurl
|
||||||
|
(or (@ (config) pkg-build-baseurl)
|
||||||
|
"http://pkg-build.racket-lang.org/"))
|
||||||
|
|
||||||
(struct draft-package (old-name name description authors tags versions) #:prefab)
|
(struct draft-package (old-name name description authors tags versions) #:prefab)
|
||||||
|
|
||||||
|
@ -435,7 +452,7 @@
|
||||||
|
|
||||||
(define (buildhost-link #:attributes [attributes '()] url-suffix label)
|
(define (buildhost-link #:attributes [attributes '()] url-suffix label)
|
||||||
`(a (,@attributes
|
`(a (,@attributes
|
||||||
(href ,(format "http://pkg-build.racket-lang.org/~a" url-suffix))) ,label))
|
(href ,(format "~a~a" pkg-build-baseurl url-suffix))) ,label))
|
||||||
|
|
||||||
(define (authors-list authors #:gravatars? [gravatars? #f])
|
(define (authors-list authors #:gravatars? [gravatars? #f])
|
||||||
`(ul ((class "authors")) ,@(for/list ((author authors))
|
`(ul ((class "authors")) ,@(for/list ((author authors))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user