Skip to content

Commit

Permalink
Merge pull request #31 from ancientHacker/stage
Browse files Browse the repository at this point in the history
first pull from stage to production
  • Loading branch information
brotskydotcom committed Dec 27, 2015
2 parents 678a097 + ea03ba2 commit 947aae0
Show file tree
Hide file tree
Showing 31 changed files with 2,206 additions and 1,397 deletions.
34 changes: 24 additions & 10 deletions app.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
{
"name": "susen-dev",
"description": "automatic pull request configuration",
"scripts": {
},
"env": {
},
"addons": [
"papertrail",
"redistogo"
]
"name": "susen-dev",
"description": "automatic pull request configuration",
"scripts": {
},
"env": {
"REDISTOGO_ENV": "dev",
"APPLICATION_ENV": "dev",
"HEROKU_APP_NAME": {
"required": true
},
"HEROKU_RELEASE_VERSION": {
"required": false
},
"HEROKU_SLUG_COMMIT": {
"required": false
},
"HEROKU_DYNO_ID": {
"required": false
}
},
"addons": [
"papertrail",
"redistogo"
]
}
35 changes: 28 additions & 7 deletions client/settings.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package client

import (
"fmt"
"html/template"
"log"
"net/http"
Expand All @@ -15,25 +16,45 @@ Common client settings
*/

const (
applicationName = "Sūsen"
applicationVersion = "0.6"
templatePageSuffix = "Page.tmpl.html"
defaultTemplateDirectoryEnvVar = "TEMPLATE_DIRECTORY"
defaultStaticDirectoryEnvVar = "STATIC_DIRECTORY"
iconPath = "/favicon.ico"
reportBugPath = "/bugreport.html"
templatePageSuffix = "Page.tmpl.html"
applicationNameEnvVar = "HEROKU_APP_NAME"
applicationVersionEnvVar = "HEROKU_RELEASE_VERSION"
applicationBuildEnvVar = "HEROKU_SLUG_COMMIT"
applicationInstanceEnvVar = "HEROKU_DYNO_ID"
applicationEnvEnvVar = "APPLICATION_ENV"
)

var (
defaultTemplateDirectory = filepath.Join("static", "tmpl")
defaultStaticDirectory = filepath.Join("static")
brandName = "Sūsen"
iconPath = "/favicon.ico"
reportBugPath = "/bugreport.html"
defaultStaticDirectory = "static"
defaultTemplateDirectory = filepath.Join(defaultStaticDirectory, "tmpl")
staticResourcePaths = map[string]string{
iconPath: filepath.Join("special", "susen.ico"),
"/robots.txt": filepath.Join("special", "robots.txt"),
reportBugPath: filepath.Join("special", "report_bug.html"),
}
)

// VerifyResources - check that resources can be found, return
// error if not.
func VerifyResources() error {
if fi, err := os.Stat(findStaticDirectory()); err != nil {
return err
} else if !fi.IsDir() {
return fmt.Errorf("Static resource location %q not a directory.", findStaticDirectory())
}
if fi, err := os.Stat(findTemplateDirectory()); err != nil {
return err
} else if !fi.IsDir() {
return fmt.Errorf("Template resource location %q not a directory.", findTemplateDirectory())
}
return nil
}

/*
handle static resources
Expand Down
71 changes: 63 additions & 8 deletions client/settings_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,79 @@ import (

/*
template lookup
resource locations
*/

// testing setup: change default directory since we run from this
// module's directory which is a child of the top. This applies
// to all the tests in this module.
func init() {
defaultStaticDirectory = filepath.Join("..", "static")
defaultTemplateDirectory = filepath.Join("..", "static", "tmpl")
}

func TestVerifyResources(t *testing.T) {
defer func(td, sd string) {
os.Unsetenv(defaultTemplateDirectoryEnvVar)
os.Unsetenv(defaultStaticDirectoryEnvVar)
defaultTemplateDirectory = td
defaultStaticDirectory = sd
}(defaultTemplateDirectory, defaultStaticDirectory)

// should succeed with initalized defaults from above
if err := VerifyResources(); err != nil {
t.Errorf("Couldn't verify resources in %q & %q: %v",
findStaticDirectory(), findTemplateDirectory(), err)
}

// should fail with either or both being a non-existent directory
defaultStaticDirectory = "/no-such-directory"
if err := VerifyResources(); err == nil {
t.Errorf("Incorrectly verified resources in %q & %q",
findStaticDirectory(), findTemplateDirectory())
}
defaultStaticDirectory = defaultTemplateDirectory
defaultTemplateDirectory = "/no-such-directory"
if err := VerifyResources(); err == nil {
t.Errorf("Incorrectly verified resources in %q & %q",
findStaticDirectory(), findTemplateDirectory())
}
defaultStaticDirectory = "/no-such-directory"
defaultTemplateDirectory = "/no-such-directory"
if err := VerifyResources(); err == nil {
t.Errorf("Incorrectly verified resources in %q & %q",
findStaticDirectory(), findTemplateDirectory())
}

// should succeed with overrides
os.Setenv(defaultTemplateDirectoryEnvVar, "testdata")
os.Setenv(defaultStaticDirectoryEnvVar, "testdata")
if err := VerifyResources(); err != nil {
t.Errorf("Couldn't verify resources in %q & %q: %v",
findStaticDirectory(), findTemplateDirectory(), err)
}

// should fail with just one being an existing non-directory
os.Setenv(defaultTemplateDirectoryEnvVar, "settings_test.go")
if err := VerifyResources(); err == nil {
t.Errorf("Incorrectly verified resources in %q & %q",
findStaticDirectory(), findTemplateDirectory())
}
os.Setenv(defaultTemplateDirectoryEnvVar, "testdata")
os.Setenv(defaultStaticDirectoryEnvVar, "settings_test.go")
if err := VerifyResources(); err == nil {
t.Errorf("Incorrectly verified resources in %q & %q",
findStaticDirectory(), findTemplateDirectory())
}
}

/*
template lookup
*/

func TestTemplateLookup(t *testing.T) {
defer func() {
loadedTemplates = make(map[string]*template.Template)
Expand Down Expand Up @@ -80,13 +142,6 @@ static lookup
*/

// testing setup: change default directory since we run from this
// module's directory which is a child of the top. This applies
// to all the tests in this module.
func init() {
defaultStaticDirectory = filepath.Join("..", "static")
}

// helper used in two test functions below
func CoreStaticLookup(t *testing.T, shouldPass bool) {
handlerFunc := func(w http.ResponseWriter, r *http.Request) {
Expand Down
144 changes: 126 additions & 18 deletions client/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"github.com/ancientHacker/susen.go/puzzle"
"html/template"
"os"
"path/filepath"
)

Expand All @@ -19,13 +20,14 @@ solver pages
// findSolverPageTemplate for template location details.
var solverPageTemplate *template.Template

// A templateSolverPage contains the values to file the solver
// A templateSolverPage contains the values to fill the solver
// page template.
type templateSolverPage struct {
SessionID, PuzzleID string
Title, TopHead string
IconFile, CssFile, JsFile string
Puzzle templatePuzzle
ApplicationFooter string
}

// templatePuzzle is the structure expected by the puzzle grid
Expand All @@ -50,29 +52,30 @@ func init() {
// SolverPage executes the solver page template over the passed
// session and puzzle info, and returns the solver page content as a
// string.
func SolverPage(sessionID string, puzzleID string, state puzzle.State) string {
func SolverPage(sessionID string, puzzleID string, state *puzzle.State) string {
var tp templatePuzzle
var err error
if state.Geometry == puzzle.SudokuGeometryCode {
if state.Geometry == puzzle.SudokuGeometryName {
tp, err = sudokuTemplatePuzzle(state.Values)
} else if state.Geometry == puzzle.DudokuGeometryCode {
} else if state.Geometry == puzzle.DudokuGeometryName {
tp, err = dudokuTemplatePuzzle(state.Values)
} else {
err = fmt.Errorf("Can't generate puzzle grid for Geometry Code %v", state.Geometry)
err = fmt.Errorf("Can't generate puzzle grid for geometry %q", state.Geometry)
}
if err != nil {
return errorPage(err)
}

tsp := templateSolverPage{
SessionID: sessionID,
PuzzleID: puzzleID,
Title: fmt.Sprintf("%s: Solver", applicationName),
TopHead: fmt.Sprintf("%s v%s Puzzle Solver", applicationName, applicationVersion),
IconFile: iconPath,
CssFile: "/solver.css",
JsFile: "/solver.js",
Puzzle: tp,
SessionID: sessionID,
PuzzleID: puzzleID,
Title: fmt.Sprintf("%s: Solver", brandName),
TopHead: fmt.Sprintf("Puzzle Solver"),
IconFile: iconPath,
CssFile: "/solver.css",
JsFile: "/solver.js",
Puzzle: tp,
ApplicationFooter: applicationFooter(),
}

tmpl, err := loadPageTemplate("solver")
Expand Down Expand Up @@ -239,16 +242,18 @@ error pages
type templateErrorPage struct {
Title, TopHead, Message string
IconFile, ReportBugPage string
ApplicationFooter string
}

// return error page content
func errorPage(e error) string {
tep := templateErrorPage{
Title: fmt.Sprintf("%s: Error", applicationName),
TopHead: fmt.Sprintf("%s v%s Error Page", applicationName, applicationVersion),
Message: e.Error(),
IconFile: iconPath,
ReportBugPage: reportBugPath,
Title: fmt.Sprintf("%s: Error", brandName),
TopHead: fmt.Sprintf("Error Page"),
Message: e.Error(),
IconFile: iconPath,
ReportBugPage: reportBugPath,
ApplicationFooter: applicationFooter(),
}

tmpl, err := loadPageTemplate("error")
Expand All @@ -263,3 +268,106 @@ func errorPage(e error) string {
}
return buf.String()
}

/*
home page
*/

// The homePageTemplate contains the template for a home
// page. It's initialized when needed; see the definition of
// findHomePageTemplate for template location details.
var homePageTemplate *template.Template

// A templateHomePage contains the values to file the home
// page template.
type templateHomePage struct {
SessionID, PuzzleID string
Title, TopHead string
IconFile, CssFile, JsFile string
PuzzleIDs []string
ApplicationFooter string
}

// add home statics to the static list
func init() {
staticResourcePaths["/home.js"] = filepath.Join("home", "home.js")
staticResourcePaths["/home.css"] = filepath.Join("home", "home.css")
}

// HomePage executes the home page template over the passed
// session and puzzle info, and returns the home page content as
// a string. If there is an error, what's returned is the error
// page content as a string.
func HomePage(sessionID string, puzzleID string, puzzleIDs []string) string {
tsp := templateHomePage{
SessionID: sessionID,
PuzzleID: puzzleID,
Title: fmt.Sprintf("%s: Home", brandName),
TopHead: fmt.Sprintf("%s", brandName),
IconFile: iconPath,
CssFile: "/home.css",
JsFile: "/home.js",
PuzzleIDs: puzzleIDs,
ApplicationFooter: applicationFooter(),
}

tmpl, err := loadPageTemplate("home")
if err != nil {
return errorPage(fmt.Errorf("Couldn't load the %q template: %v", "home", err))
}
buf := new(bytes.Buffer)
err = tmpl.Execute(buf, tsp)
if err != nil {
return errorPage(err)
}
return buf.String()
}

/*
application footer
*/

// applicationFooter - the application footer that shows at the
// bottom of all pages.
func applicationFooter() string {
appName := os.Getenv(applicationNameEnvVar)
appEnv := os.Getenv(applicationEnvEnvVar)
appVersion := os.Getenv(applicationVersionEnvVar)
appInstance := os.Getenv(applicationInstanceEnvVar)
appBuild := os.Getenv(applicationBuildEnvVar)

if appName == "" {
appName = brandName
}

if appEnv == "" {
appEnv = "local"
}

if appVersion != "" {
appVersion = " " + appVersion
}
if len(appBuild) >= 7 {
appBuild = appBuild[:7]
}

if appInstance != "" {
appInstance = " (dyno " + appInstance + ")"
}

switch appEnv {
case "local":
return "[" + appName + " local]"
case "dev":
return "[" + appName + " CI/CD]"
case "stg":
return "[" + appName + appVersion + " <" + appBuild + ">]"
case "prd":
return "[" + appName + appVersion + " <" + appBuild + ">" + appInstance + "]"
}
return "[" + appName + " <??>]"
}
Loading

0 comments on commit 947aae0

Please sign in to comment.