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

ci: add heroku deploy button #45

Merged
merged 11 commits into from
Jun 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ GET https://webshot.bots.house/image
| `delay` | `int` | Delay in milliseconds, to wait after the page is loaded | null |
| `full_page` | `bool` | Capture full page screenshot | false |
| `scroll_page` | `bool` | Scroll through the entire page before capturing a screenshot. | false |

## Deploy

### Heroku

[![Deploy](https://www.herokucdn.com/deploy/button.svg)](https://heroku.com/deploy?template=https://github.com/bots-house/webshot/tree/heroku-button)
84 changes: 84 additions & 0 deletions app.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
{
"name": "WebShot",
"description": "Self-hosted web page screenshot service",
"repository": "https://github.com/bots-house/webshot",
"logo": "https://emojipedia-us.s3.dualstack.us-west-1.amazonaws.com/thumbs/240/apple/285/camera-with-flash_1f4f8.png",
"keywords": [
"golang",
"chrome",
"chrome-headless",
"screenshot",
"api"
],
"website": "https://webshot.bots.house",
"success_url": "/",
"buildpacks": [
{
"url": "https://github.com/heroku/heroku-buildpack-google-chrome"
},
{
"url": "https://github.com/heroku/heroku-buildpack-go"
}
],
"env": {
"AUTH_SIGN_KEY": {
"description": "HMAC request signature secret key, provide it if you need auth",
"required": false
},

"BROWSER_ADDR": {
"description": "Remote browser connection string, provide it if you want use remote browser for rendering. Allowed is ws://... or http://",
"required": false
},

"STORAGE_S3_KEY": {
"description": "S3 Access Key, provide it and other STORAGE_S3_* keys if you need caching",
"required": false
},
"STORAGE_S3_SECRET": {
"description": "S3 Secret Key",
"required": false
},
"STORAGE_S3_REGION": {
"description": "S3 Region",
"required": false
},
"STORAGE_S3_BUCKET": {
"description": "S3 Bucket",
"required": false
},
"STORAGE_S3_ENDPOINT": {
"description": "S3 Endpoint",
"required": false
},
"STORAGE_S3_SUBDIR": {
"description": "S3 Subdir e.g. /webshot",
"required": false
},

"LOG_DEBUG": {
"description": "Enable debug logs",
"value": "true",
"required": false
},
"LOG_PRETTY": {
"description": "Enable pretty logs",
"value": "true",
"required": false
},
"SENTRY_DSN": {
"description": "Sentry DSN for errors tracking",
"required": false
},
"SENTRY_ENV": {
"description": "Sentry environment",
"value": "production",
"required": false
},
"SENTRY_TRACES_SAMPLE_RATE": {
"description": "Sentry traces rate, keep it lower on production",
"value": "0.1",
"required": false
}
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// +heroku goVersion go1.16
module github.com/bots-house/webshot

go 1.16
Expand Down
36 changes: 23 additions & 13 deletions internal/renderer/chrome.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import (
)

type Chrome struct {
Debug bool

Debug bool
Args map[string]string
Resolver ChromeResolver
}

Expand All @@ -32,14 +32,20 @@ func (chrome *Chrome) buildContextOptions() []chromedp.ContextOption {
return opts
}

// func (chrome *Chrome) buildAllocator(ctx context.Context) (context.Context, context.CancelFunc) {
// return chromedp.NewExecAllocator(ctx,
// append(
// chromedp.DefaultExecAllocatorOptions[:],
// chromedp.Flag("headless", false),
// )...,
// )
// }
func (chrome *Chrome) newLocalAllocator(ctx context.Context) (context.Context, context.CancelFunc) {
args := make([]chromedp.ExecAllocatorOption, 0, len(chrome.Args))

for k, v := range chrome.Args {
args = append(args, chromedp.Flag(k, v))
}

return chromedp.NewExecAllocator(ctx,
append(
chromedp.DefaultExecAllocatorOptions[:],
args...,
)...,
)
}

func (chrome *Chrome) Render(
ctx context.Context,
Expand Down Expand Up @@ -77,6 +83,8 @@ func (chrome *Chrome) Render(

}(time.Now())

var cancel context.CancelFunc

if chrome.Resolver != nil {
wsurl, err := chrome.Resolver.BrowserWebSocketURL(ctx)
if err != nil {
Expand All @@ -85,15 +93,17 @@ func (chrome *Chrome) Render(

log.Ctx(ctx).Debug().Str("url", wsurl).Msg("use remote browser")

var cancel context.CancelFunc
ctx, cancel = chromedp.NewRemoteAllocator(ctx, wsurl)
defer cancel()
} else {
log.Ctx(ctx).Debug().Msg("use embedded browser")
ctx, cancel = chrome.newLocalAllocator(ctx)
defer cancel()

log.Ctx(ctx).Debug().Interface("args", chrome.Args).Msg("use embedded browser")
}

// create context
ctx, cancel := chromedp.NewContext(
ctx, cancel = chromedp.NewContext(
ctx,
chrome.buildContextOptions()...,
)
Expand Down
17 changes: 13 additions & 4 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ type Config struct {
} `group:"HTTP" namespace:"http" env-namespace:"HTTP"`

Browser struct {
Addr string `long:"addr" description:"remote browser connection string. Allowed is ws://... or http://" env:"ADDR"`
Addr string `long:"addr" description:"remote browser connection string. Allowed is ws://... or http://" env:"ADDR"`
Args map[string]string `long:"args" description:"extra local chrome command line args" env:"ARGS" env-delim:" "`
} `group:"Browser" namespace:"browser" env-namespace:"BROWSER"`

Storage struct {
Expand All @@ -62,6 +63,14 @@ type Config struct {
} `group:"Sentry" namespace:"sentry" env-namespace:"SENTRY"`

Healthcheck bool `long:"healthcheck" description:"do healthcheck and exit if failure"`

Port int `long:"port" description:"port to listen, used by Heroku" env:"PORT" hidden:"true"`
}

func (cfg *Config) compute() {
if cfg.Port != 0 {
cfg.HTTP.Addr = fmt.Sprintf("0.0.0.0:%d", cfg.Port)
}
}

func loadConfig() Config {
Expand All @@ -82,6 +91,8 @@ func loadConfig() Config {
}
}

config.compute()

return config
}

Expand All @@ -97,7 +108,6 @@ const (

func main() {
config := loadConfig()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

Expand Down Expand Up @@ -158,7 +168,6 @@ func runHealthcheck(ctx context.Context, config Config) error {
}

func runServer(ctx context.Context, config Config) error {

storage, err := newStorage(ctx, config)
if err != nil {
return xerrors.Errorf("new storage: %w", err)
Expand Down Expand Up @@ -284,7 +293,7 @@ func newRenderer(ctx context.Context, cfg Config) (renderer.Renderer, error) {
log.Ctx(ctx).Info().Msg("init local chrome renderer")
}

return &renderer.Chrome{Resolver: resolver}, nil
return &renderer.Chrome{Resolver: resolver, Args: cfg.Browser.Args}, nil
}

func newStorage(_ context.Context, cfg Config) (storage.Storage, error) {
Expand Down