diff --git a/README.md b/README.md index 122b6ea..0a91ddd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # RetroGit -Service that shows you your GitHub commits from a year ago. Includes a mail digest to that you can see each day what you were up to in the past. +Service that shows you your GitHub commits from previous years. Includes a mail digest to that you can see each day what you were up to in the past. It's currently running at [https://www.retrogit.com/](https://www.retrogit.com/). @@ -21,5 +21,5 @@ The server can the be accessed at [http://localhost:8080/](http://localhost:8080 ## Deploying to App Engine ``` -gcloud app deploy --project retrogit app/app.yaml +./deploy.sh ``` diff --git a/app/account.go b/app/account.go index 57d99a3..df0e77e 100644 --- a/app/account.go +++ b/app/account.go @@ -1,13 +1,13 @@ -package retrogit +package main import ( "bytes" + "context" "encoding/gob" "errors" "time" - "appengine" - "appengine/datastore" + "google.golang.org/appengine/datastore" "code.google.com/p/goauth2/oauth" "github.com/google/go-github/github" @@ -28,7 +28,7 @@ type Account struct { WeeklyDay time.Weekday } -func getAccount(c appengine.Context, githubUserId int) (*Account, error) { +func getAccount(c context.Context, githubUserId int) (*Account, error) { key := datastore.NewKey(c, "Account", "", int64(githubUserId), nil) account := new(Account) err := datastore.Get(c, key, account) @@ -63,7 +63,7 @@ func initAccount(account *Account) error { return nil } -func getAllAccounts(c appengine.Context) ([]Account, error) { +func getAllAccounts(c context.Context) ([]Account, error) { q := datastore.NewQuery("Account") var accounts []Account _, err := q.GetAll(c, &accounts) @@ -88,7 +88,7 @@ func (account *Account) IsRepoIdExcluded(repoId int) bool { return false } -func (account *Account) Put(c appengine.Context) error { +func (account *Account) Put(c context.Context) error { w := new(bytes.Buffer) err := gob.NewEncoder(w).Encode(&account.OAuthToken) if err != nil { @@ -100,7 +100,7 @@ func (account *Account) Put(c appengine.Context) error { return err } -func (account *Account) Delete(c appengine.Context) error { +func (account *Account) Delete(c context.Context) error { key := datastore.NewKey(c, "Account", "", int64(account.GitHubUserId), nil) err := datastore.Delete(c, key) return err diff --git a/app/admin.go b/app/admin.go index 2fca4c4..9c13f99 100644 --- a/app/admin.go +++ b/app/admin.go @@ -1,11 +1,11 @@ -package retrogit +package main import ( "net/http" "sort" "strconv" - "appengine" + "google.golang.org/appengine" "github.com/google/go-github/github" ) diff --git a/app/app.go b/app/app.go index c429ddf..1d2ed61 100644 --- a/app/app.go +++ b/app/app.go @@ -1,4 +1,4 @@ -package retrogit +package main import ( "encoding/json" @@ -6,13 +6,14 @@ import ( "fmt" "html/template" "io/ioutil" - "log" + log_ "log" "net/http" "path/filepath" "strings" - "appengine" - "appengine/mail" + "google.golang.org/appengine" + "google.golang.org/appengine/log" + "google.golang.org/appengine/mail" "github.com/google/go-github/github" "github.com/gorilla/sessions" @@ -208,14 +209,14 @@ func handleAppError(e *AppError, w http.ResponseWriter, r *http.Request) { return } } else { - c.Errorf("GitHub fetch error was not of type github.ErrorResponse") + log.Errorf(c, "GitHub fetch error was not of type github.ErrorResponse") } } else if e.Type == AppErrorTypeRedirect { http.Redirect(w, r, e.Message, e.Code) return } if e.Type != AppErrorTypeBadInput { - c.Errorf("%v", e.Error) + log.Errorf(c, "%v", e.Error) if !appengine.IsDevAppServer() { sendAppErrorMail(e, r) } @@ -226,11 +227,11 @@ func handleAppError(e *AppError, w http.ResponseWriter, r *http.Request) { w.WriteHeader(e.Code) templateError := templates["internal-error"].Render(w, data) if templateError != nil { - c.Errorf("Error %s rendering error template.", templateError.Error.Error()) + log.Errorf(c, "Error %s rendering error template.", templateError.Error.Error()) } return } else { - c.Infof("%v", e.Error) + log.Infof(c, "%v", e.Error) } http.Error(w, e.Message, e.Code) } @@ -260,7 +261,7 @@ Error: %s`, c := appengine.NewContext(r) err := mail.Send(c, errorMessage) if err != nil { - c.Errorf("Error %s sending error email.", err.Error()) + log.Errorf(c, "Error %s sending error email.", err.Error()) } } @@ -323,11 +324,11 @@ func loadTemplates() (templates map[string]*Template) { } sharedFileNames, err := filepath.Glob("templates/shared/*.html") if err != nil { - log.Panicf("Could not read shared template file names %s", err.Error()) + log_.Panicf("Could not read shared template file names %s", err.Error()) } templateFileNames, err := filepath.Glob("templates/*.html") if err != nil { - log.Panicf("Could not read template file names %s", err.Error()) + log_.Panicf("Could not read template file names %s", err.Error()) } templates = make(map[string]*Template) for _, templateFileName := range templateFileNames { @@ -344,7 +345,7 @@ func loadTemplates() (templates map[string]*Template) { _, templateFileName = filepath.Split(fileNames[0]) parsedTemplate, err := template.New(templateFileName).Funcs(funcMap).ParseFiles(fileNames...) if err != nil { - log.Printf("Could not parse template files for %s: %s", templateFileName, err.Error()) + log_.Printf("Could not parse template files for %s: %s", templateFileName, err.Error()) } templates[templateName] = &Template{parsedTemplate} } @@ -354,13 +355,13 @@ func loadTemplates() (templates map[string]*Template) { func loadStyles() (result map[string]template.CSS) { stylesBytes, err := ioutil.ReadFile("config/styles.json") if err != nil { - log.Panicf("Could not read styles JSON: %s", err.Error()) + log_.Panicf("Could not read styles JSON: %s", err.Error()) } var stylesJson interface{} err = json.Unmarshal(stylesBytes, &stylesJson) result = make(map[string]template.CSS) if err != nil { - log.Printf("Could not parse styles JSON %s: %s", stylesBytes, err.Error()) + log_.Printf("Could not parse styles JSON %s: %s", stylesBytes, err.Error()) return } var parse func(string, map[string]interface{}, *string) @@ -377,7 +378,7 @@ func loadStyles() (result map[string]template.CSS) { parse(path+k, v.(map[string]interface{}), &nestedStyle) result[path+k] = template.CSS(nestedStyle) default: - log.Printf("Unexpected type for %s in styles JSON, ignoring", k) + log_.Printf("Unexpected type for %s in styles JSON, ignoring", k) } } } diff --git a/app/app.yaml b/app/app.yaml index 17bc42e..9e30b5d 100644 --- a/app/app.yaml +++ b/app/app.yaml @@ -1,5 +1,4 @@ -runtime: go -api_version: go1 +runtime: go111 handlers: - url: /static @@ -11,11 +10,11 @@ handlers: static_files: static/robots.txt upload: static/robots.txt - url: /digest/cron - script: _go_app + script: auto login: admin - url: /admin/.* - script: _go_app + script: auto login: admin - url: /.* - script: _go_app + script: auto secure: always diff --git a/app/caching_transport.go b/app/caching_transport.go index c528a0d..e08cd3f 100644 --- a/app/caching_transport.go +++ b/app/caching_transport.go @@ -1,8 +1,9 @@ -package retrogit +package main import ( "bufio" "bytes" + "context" "crypto/md5" "fmt" "io" @@ -11,8 +12,8 @@ import ( "strings" "time" - "appengine" - "appengine/memcache" + "google.golang.org/appengine/log" + "google.golang.org/appengine/memcache" ) // Simple http.RoundTripper implementation which wraps an existing transport and @@ -20,7 +21,7 @@ import ( // iteration cycle during development. type CachingTransport struct { Transport http.RoundTripper - Context appengine.Context + Context context.Context } func (t *CachingTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) { @@ -50,7 +51,7 @@ func (t *CachingTransport) RoundTrip(req *http.Request) (resp *http.Response, er cachedRespItem, err := memcache.Get(t.Context, cacheKey) if err != nil && err != memcache.ErrCacheMiss { - t.Context.Errorf("Error getting cached response: %v", err) + log.Errorf(t.Context, "Error getting cached response: %v", err) return t.Transport.RoundTrip(req) } if err == nil { @@ -59,17 +60,17 @@ func (t *CachingTransport) RoundTrip(req *http.Request) (resp *http.Response, er if err == nil { return resp, nil } else { - t.Context.Errorf("Error readings bytes for cached response: %v", err) + log.Errorf(t.Context, "Error readings bytes for cached response: %v", err) } } - t.Context.Infof("Fetching %s", req.URL) + log.Infof(t.Context, "Fetching %s", req.URL) resp, err = t.Transport.RoundTrip(req) if err != nil || resp.StatusCode != 200 { return } respBytes, err := httputil.DumpResponse(resp, true) if err != nil { - t.Context.Errorf("Error dumping bytes for cached response: %v", err) + log.Errorf(t.Context, "Error dumping bytes for cached response: %v", err) return resp, nil } var expiration time.Duration = time.Hour @@ -86,7 +87,7 @@ func (t *CachingTransport) RoundTrip(req *http.Request) (resp *http.Response, er Expiration: expiration, }) if err != nil { - t.Context.Errorf("Error setting cached response for %s (cache key %s, %d bytes to cache): %v", + log.Errorf(t.Context, "Error setting cached response for %s (cache key %s, %d bytes to cache): %v", req.URL, cacheKey, len(respBytes), err) } return resp, nil diff --git a/app/digest.go b/app/digest.go index 90783ad..dc377c6 100644 --- a/app/digest.go +++ b/app/digest.go @@ -1,13 +1,14 @@ -package retrogit +package main import ( "bytes" + "context" "fmt" "sort" "strings" "time" - "appengine" + "google.golang.org/appengine/log" "github.com/google/go-github/github" ) @@ -171,7 +172,7 @@ type Digest struct { RepoErrors map[string]error } -func newDigest(c appengine.Context, githubClient *github.Client, account *Account) (*Digest, error) { +func newDigest(c context.Context, githubClient *github.Client, account *Account) (*Digest, error) { user, _, err := githubClient.Users.Get("") if err != nil { return nil, err @@ -225,7 +226,7 @@ func newDigest(c appengine.Context, githubClient *github.Client, account *Accoun digest.fetch(githubClient) for repoFullName, err := range digest.RepoErrors { - c.Errorf("Error fetching %s: %s", repoFullName, err.Error()) + log.Errorf(c, "Error fetching %s: %s", repoFullName, err.Error()) } return digest, nil } diff --git a/app/index.yaml b/app/index.yaml new file mode 100644 index 0000000..6536212 --- /dev/null +++ b/app/index.yaml @@ -0,0 +1,2 @@ +indexes: +# AUTOGENERATED diff --git a/app/recovery.go b/app/recovery.go index af9fedc..3db691d 100644 --- a/app/recovery.go +++ b/app/recovery.go @@ -1,4 +1,4 @@ -package retrogit +package main // From Martini's recovery package: // https://github.com/go-martini/martini/blob/master/recovery.go diff --git a/app/repos.go b/app/repos.go index 50813d1..7e0cfa1 100644 --- a/app/repos.go +++ b/app/repos.go @@ -1,13 +1,15 @@ -package retrogit +package main import ( + "context" "fmt" "time" - "appengine" - "appengine/datastore" - "appengine/delay" - "appengine/taskqueue" + "google.golang.org/appengine" + "google.golang.org/appengine/datastore" + "google.golang.org/appengine/delay" + "google.golang.org/appengine/log" + "google.golang.org/appengine/taskqueue" "github.com/google/go-github/github" ) @@ -23,16 +25,16 @@ type RepoVintage struct { Vintage time.Time `datastore:",noindex"` } -func getVintageKey(c appengine.Context, userId int, repoId int) *datastore.Key { +func getVintageKey(c context.Context, userId int, repoId int) *datastore.Key { return datastore.NewKey(c, "RepoVintage", fmt.Sprintf("%d-%d", userId, repoId), 0, nil) } var computeVintageFunc *delay.Function -func computeVintage(c appengine.Context, userId int, userLogin string, repoId int, repoOwnerLogin string, repoName string) error { +func computeVintage(c context.Context, userId int, userLogin string, repoId int, repoOwnerLogin string, repoName string) error { account, err := getAccount(c, userId) if err != nil { - c.Errorf("Could not load account %d: %s. Presumed deleted, aborting computing vintage for %s/%s", userId, err.Error(), repoOwnerLogin, repoName) + log.Errorf(c, "Could not load account %d: %s. Presumed deleted, aborting computing vintage for %s/%s", userId, err.Error(), repoOwnerLogin, repoName) return nil } @@ -42,7 +44,7 @@ func computeVintage(c appengine.Context, userId int, userLogin string, repoId in repo, response, err := githubClient.Repositories.Get(repoOwnerLogin, repoName) if response.StatusCode == 403 || response.StatusCode == 404 { - c.Warningf("Got a %d when trying to look up %s/%s (%d)", response.StatusCode, repoOwnerLogin, repoName, repoId) + log.Warningf(c, "Got a %d when trying to look up %s/%s (%d)", response.StatusCode, repoOwnerLogin, repoName, repoId) _, err = datastore.Put(c, getVintageKey(c, userId, repoId), &RepoVintage{ UserId: userId, RepoId: repoId, @@ -50,7 +52,7 @@ func computeVintage(c appengine.Context, userId int, userLogin string, repoId in }) return err } else if err != nil { - c.Errorf("Could not load repo %s/%s (%d): %s", repoOwnerLogin, repoName, repoId, err.Error()) + log.Errorf(c, "Could not load repo %s/%s (%d): %s", repoOwnerLogin, repoName, repoId, err.Error()) return err } @@ -69,7 +71,7 @@ func computeVintage(c appengine.Context, userId int, userLogin string, repoId in // GitHub returns with a 409 when a repository is empty. commits = make([]github.RepositoryCommit, 0) } else if err != nil { - c.Errorf("Could not load commits for repo %s (%d): %s", *repo.FullName, repoId, err.Error()) + log.Errorf(c, "Could not load commits for repo %s (%d): %s", *repo.FullName, repoId, err.Error()) return err } @@ -78,10 +80,10 @@ func computeVintage(c appengine.Context, userId int, userLogin string, repoId in if len(commits) > 0 { stats, response, err := githubClient.Repositories.ListContributorsStats(repoOwnerLogin, repoName) if response.StatusCode == 202 { - c.Infof("Stats were not available for %s, will try again later", *repo.FullName) + log.Infof(c, "Stats were not available for %s, will try again later", *repo.FullName) task, err := computeVintageFunc.Task(userId, userLogin, repoId, repoOwnerLogin, repoName) if err != nil { - c.Errorf("Could create delayed task for %s: %s", *repo.FullName, err.Error()) + log.Errorf(c, "Could create delayed task for %s: %s", *repo.FullName, err.Error()) return err } task.Delay = time.Second * 10 @@ -89,7 +91,7 @@ func computeVintage(c appengine.Context, userId int, userLogin string, repoId in return nil } if err != nil { - c.Errorf("Could not load stats for repo %s: %s", *repo.FullName, err.Error()) + log.Errorf(c, "Could not load stats for repo %s: %s", *repo.FullName, err.Error()) return err } for _, stat := range stats { @@ -111,7 +113,7 @@ func computeVintage(c appengine.Context, userId int, userLogin string, repoId in Vintage: vintage, }) if err != nil { - c.Errorf("Could save vintage for repo %s: %s", *repo.FullName, err.Error()) + log.Errorf(c, "Could save vintage for repo %s: %s", *repo.FullName, err.Error()) return err } @@ -122,7 +124,7 @@ func init() { computeVintageFunc = delay.Func("computeVintage", computeVintage) } -func fillVintages(c appengine.Context, user *github.User, repos []*Repo) error { +func fillVintages(c context.Context, user *github.User, repos []*Repo) error { if len(repos) > VintageChunkSize { for chunkStart := 0; chunkStart < len(repos); chunkStart += VintageChunkSize { chunkEnd := chunkStart + VintageChunkSize @@ -151,7 +153,7 @@ func fillVintages(c appengine.Context, user *github.User, repos []*Repo) error { if err == datastore.ErrNoSuchEntity { vintages[i] = nil } else if err != nil { - c.Errorf("%d/%s vintage fetch error: %s", i, *repos[i].FullName, err.Error()) + log.Errorf(c, "%d/%s vintage fetch error: %s", i, *repos[i].FullName, err.Error()) return err } } @@ -238,7 +240,7 @@ type UserRepos struct { Repos []*Repo } -func getRepos(c appengine.Context, githubClient *github.Client, account *Account, user *github.User) (*Repos, error) { +func getRepos(c context.Context, githubClient *github.Client, account *Account, user *github.User) (*Repos, error) { clientUserRepos := make([]github.Repository, 0) page := 1 for { diff --git a/app/retrogit.go b/app/retrogit.go index 1965ea5..813f9ce 100644 --- a/app/retrogit.go +++ b/app/retrogit.go @@ -1,11 +1,12 @@ -package retrogit +package main import ( "bytes" + "context" "encoding/json" "fmt" "io/ioutil" - "log" + log_ "log" "net/http" "net/url" "strconv" @@ -13,11 +14,12 @@ import ( "sync" "time" - "appengine" - "appengine/datastore" - "appengine/delay" - "appengine/mail" - "appengine/urlfetch" + "google.golang.org/appengine" + "google.golang.org/appengine/datastore" + "google.golang.org/appengine/delay" + "google.golang.org/appengine/log" + "google.golang.org/appengine/mail" + "google.golang.org/appengine/urlfetch" "code.google.com/p/goauth2/oauth" "github.com/google/go-github/github" @@ -33,7 +35,7 @@ var sessionStore *sessions.CookieStore var sessionConfig SessionConfig var templates map[string]*Template -func init() { +func main() { templates = loadTemplates() timezones = initTimezones() sessionStore, sessionConfig = initSession() @@ -62,6 +64,8 @@ func init() { router.Handle("/admin/repos", AppHandler(reposAdminHandler)).Name("repos-admin") router.Handle("/admin/delete-account", AppHandler(deleteAccountAdminHandler)).Name("delete-account-admin") http.Handle("/", router) + + appengine.Main() } func initGithubOAuthConfig(includePrivateRepos bool) (config oauth.Config) { @@ -72,11 +76,11 @@ func initGithubOAuthConfig(includePrivateRepos bool) (config oauth.Config) { path += ".json" configBytes, err := ioutil.ReadFile(path) if err != nil { - log.Panicf("Could not read GitHub OAuth config from %s: %s", path, err.Error()) + log_.Panicf("Could not read GitHub OAuth config from %s: %s", path, err.Error()) } err = json.Unmarshal(configBytes, &config) if err != nil { - log.Panicf("Could not parse GitHub OAuth config %s: %s", configBytes, err.Error()) + log_.Panicf("Could not parse GitHub OAuth config %s: %s", configBytes, err.Error()) } repoScopeModifier := "" if !includePrivateRepos { @@ -232,12 +236,12 @@ func digestCronHandler(w http.ResponseWriter, r *http.Request) *AppError { if account.Frequency == "weekly" { now := time.Now().In(account.TimezoneLocation) if now.Weekday() != account.WeeklyDay { - c.Infof("Skipping %d, since it wants weekly digests on %ss and today is a %s.", + log.Infof(c, "Skipping %d, since it wants weekly digests on %ss and today is a %s.", account.GitHubUserId, account.WeeklyDay, now.Weekday()) continue } } - c.Infof("Enqueing task for %d...", account.GitHubUserId) + log.Infof(c, "Enqueing task for %d...", account.GitHubUserId) sendDigestForAccountFunc.Call(c, account.GitHubUserId) } fmt.Fprint(w, "Done") @@ -246,31 +250,31 @@ func digestCronHandler(w http.ResponseWriter, r *http.Request) *AppError { var sendDigestForAccountFunc = delay.Func( "sendDigestForAccount", - func(c appengine.Context, githubUserId int) error { - c.Infof("Sending digest for %d...", githubUserId) + func(c context.Context, githubUserId int) error { + log.Infof(c, "Sending digest for %d...", githubUserId) account, err := getAccount(c, githubUserId) if err != nil { - c.Errorf(" Error looking up account: %s", err.Error()) + log.Errorf(c, " Error looking up account: %s", err.Error()) return err } sent, err := sendDigestForAccount(account, c) if err != nil { - c.Errorf(" Error: %s", err.Error()) + log.Errorf(c, " Error: %s", err.Error()) if !appengine.IsDevAppServer() { sendDigestErrorMail(err, c, githubUserId) } } else if sent { - c.Infof(" Sent!") + log.Infof(c, " Sent!") } else { - c.Infof(" Not sent, digest was empty") + log.Infof(c, " Not sent, digest was empty") } return err }) -func sendDigestErrorMail(e error, c appengine.Context, gitHubUserId int) { +func sendDigestErrorMail(e error, c context.Context, gitHubUserId int) { if strings.Contains(e.Error(), ": 502") { // Ignore 502s from GitHub, there's nothing we do about them. - return; + return } errorMessage := &mail.Message{ Sender: "RetroGit Admin ", @@ -280,11 +284,11 @@ func sendDigestErrorMail(e error, c appengine.Context, gitHubUserId int) { } err := mail.Send(c, errorMessage) if err != nil { - c.Errorf("Error %s sending error email.", err.Error()) + log.Errorf(c, "Error %s sending error email.", err.Error()) } } -func sendDigestForAccount(account *Account, c appengine.Context) (bool, error) { +func sendDigestForAccount(account *Account, c context.Context) (bool, error) { oauthTransport := githubOAuthTransport(c) oauthTransport.Token = &account.OAuthToken githubClient := github.NewClient(oauthTransport.Client()) @@ -295,7 +299,7 @@ func sendDigestForAccount(account *Account, c appengine.Context) (bool, error) { gitHubStatus := gitHubError.Response.StatusCode if gitHubStatus == http.StatusUnauthorized || gitHubStatus == http.StatusForbidden { - c.Errorf(" GitHub auth error while getting email adddress, skipping: %s", err.Error()) + log.Errorf(c, " GitHub auth error while getting email adddress, skipping: %s", err.Error()) return false, nil } } @@ -312,7 +316,7 @@ func sendDigestForAccount(account *Account, c appengine.Context) (bool, error) { gitHubStatus := gitHubError.Response.StatusCode if gitHubStatus == http.StatusUnauthorized || gitHubStatus == http.StatusForbidden { - c.Errorf(" GitHub auth error while getting digest, sending error email: %s", err.Error()) + log.Errorf(c, " GitHub auth error while getting digest, sending error email: %s", err.Error()) var authErrorHtml bytes.Buffer if err := templates["github-auth-error-email"].Execute(&authErrorHtml, nil); err != nil { return false, err @@ -516,11 +520,11 @@ func setInitialTimezoneHandler(w http.ResponseWriter, r *http.Request, state *Ap var cacheDigestForAccountFunc = delay.Func( "cacheDigestForAccount", - func(c appengine.Context, githubUserId int) error { - c.Infof("Caching digest for %d...", githubUserId) + func(c context.Context, githubUserId int) error { + log.Infof(c, "Caching digest for %d...", githubUserId) account, err := getAccount(c, githubUserId) if err != nil { - c.Errorf(" Error looking up account: %s", err.Error()) + log.Errorf(c, " Error looking up account: %s", err.Error()) // Not returning error since we don't want these tasks to be // retried. return nil @@ -531,9 +535,9 @@ var cacheDigestForAccountFunc = delay.Func( githubClient := github.NewClient(oauthTransport.Client()) _, err = newDigest(c, githubClient, account) if err != nil { - c.Errorf(" Error computing digest: %s", err.Error()) + log.Errorf(c, " Error computing digest: %s", err.Error()) } - c.Infof(" Done!") + log.Infof(c, " Done!") return nil }) @@ -544,12 +548,12 @@ func deleteAccountHandler(w http.ResponseWriter, r *http.Request, state *AppSign return RedirectToRoute("index") } -func githubOAuthTransport(c appengine.Context) *oauth.Transport { - appengineTransport := &urlfetch.Transport{Context: c} - appengineTransport.Deadline = time.Second * 60 +func githubOAuthTransport(c context.Context) *oauth.Transport { + ctx_with_timeout, _ := context.WithTimeout(c, time.Second*60) + appengineTransport := &urlfetch.Transport{Context: ctx_with_timeout} cachingTransport := &CachingTransport{ Transport: appengineTransport, - Context: c, + Context: ctx_with_timeout, } return &oauth.Transport{ Config: &githubOauthConfig, diff --git a/app/session.go b/app/session.go index 75baba5..caf0376 100644 --- a/app/session.go +++ b/app/session.go @@ -1,4 +1,4 @@ -package retrogit +package main import ( "encoding/base64" @@ -6,7 +6,7 @@ import ( "io/ioutil" "log" - "appengine" + "google.golang.org/appengine" "github.com/gorilla/sessions" ) diff --git a/app/timezones.go b/app/timezones.go index cbeb627..a7e5ab7 100644 --- a/app/timezones.go +++ b/app/timezones.go @@ -1,4 +1,4 @@ -package retrogit +package main import ( "encoding/json" diff --git a/deploy.sh b/deploy.sh new file mode 100755 index 0000000..4fb6a1e --- /dev/null +++ b/deploy.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +# With the Go 1.11 runtime, if we're not using modules, all source (including +# the app itself) must live under GOPATH. Copy it there before deploying. +DEST="$GOPATH/src/retrogit" +rm -rf $DEST +cp -r app $DEST +cd $DEST +gcloud app deploy --project retro-git app.yaml