diff --git a/CHANGELOG.md b/CHANGELOG.md index 54be57b6e..26fefd552 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - endpoint to list builds by branch, by [@bradrydzewski](https://github.com/bradrydzewski). [#1495](https://github.com/drone/drone/issues/1495). - ignore skip comments when cron event, by [@bradrydzewski](https://github.com/bradrydzewski). [#2835](https://github.com/drone/drone/issues/2835). - support for admission extensions, by [@bradrydzewski](https://github.com/bradrydzewski). [#2043](https://github.com/drone/drone/issues/2043). +- endpoint to provide link to git resources, by [@bradrydzewski](https://github.com/bradrydzewski). [#1495](https://github.com/drone/drone/issues/1495). ### Fixed - fixed issue with missing cron job name in user interface, by [@bradrydzewski](https://github.com/bradrydzewski). diff --git a/cmd/drone-server/wire_gen.go b/cmd/drone-server/wire_gen.go index ef1c884a4..cb1c2b0ec 100644 --- a/cmd/drone-server/wire_gen.go +++ b/cmd/drone-server/wire_gen.go @@ -80,7 +80,6 @@ func InitializeApplication(config2 config.Config) (application, error) { runner := provideRunner(buildManager, secretService, registryService, config2) hookService := provideHookService(client, renewer, config2) licenseService := license.NewService(userStore, repositoryStore, buildStore, coreLicense) - coreLinker := linker.New(client) permStore := perm.New(db) repositoryService := provideRepositoryService(client, renewer, config2) session, err := provideSession(userStore, config2) @@ -89,14 +88,15 @@ func InitializeApplication(config2 config.Config) (application, error) { } batcher := batch.New(db) syncer := provideSyncer(repositoryService, repositoryStore, userStore, batcher, config2) - server := api.New(buildStore, commitService, cronStore, corePubsub, globalSecretStore, hookService, logStore, coreLicense, licenseService, coreLinker, permStore, repositoryStore, repositoryService, scheduler, secretStore, stageStore, stepStore, statusService, session, logStream, syncer, system, triggerer, userStore, webhookSender) + server := api.New(buildStore, commitService, cronStore, corePubsub, globalSecretStore, hookService, logStore, coreLicense, licenseService, permStore, repositoryStore, repositoryService, scheduler, secretStore, stageStore, stepStore, statusService, session, logStream, syncer, system, triggerer, userStore, webhookSender) organizationService := orgs.New(client, renewer) userService := user.New(client) admissionService := provideAdmissionPlugin(client, organizationService, userService, config2) hookParser := parser.New(client) + coreLinker := linker.New(client) middleware := provideLogin(config2) options := provideServerOptions(config2) - webServer := web.New(admissionService, buildStore, client, hookParser, coreLicense, licenseService, middleware, repositoryStore, session, syncer, triggerer, userStore, userService, webhookSender, options, system) + webServer := web.New(admissionService, buildStore, client, hookParser, coreLicense, licenseService, coreLinker, middleware, repositoryStore, session, syncer, triggerer, userStore, userService, webhookSender, options, system) mainRpcHandlerV1 := provideRPC(buildManager, config2) mainRpcHandlerV2 := provideRPC2(buildManager, config2) mainHealthzHandler := provideHealthz() diff --git a/core/linker.go b/core/linker.go index b8b19ae84..65bbf5e7a 100644 --- a/core/linker.go +++ b/core/linker.go @@ -19,5 +19,5 @@ import "context" // Linker provides a deep link to to a git resource in the // source control management system for a given build. type Linker interface { - Link(ctx context.Context, repo *Repository, build *Build) (string, error) + Link(ctx context.Context, repo, ref, sha string) (string, error) } diff --git a/go.mod b/go.mod index 05acd8184..89634d17f 100644 --- a/go.mod +++ b/go.mod @@ -24,7 +24,7 @@ require ( github.com/drone/envsubst v1.0.1 github.com/drone/go-license v1.0.2 github.com/drone/go-login v1.0.4-0.20190311170324-2a4df4f242a2 - github.com/drone/go-scm v1.6.1-0.20190920225054-0d1ea63283ad + github.com/drone/go-scm v1.6.1-0.20190921005131-635e46e88c20 github.com/drone/signal v1.0.0 github.com/dustin/go-humanize v1.0.0 github.com/ghodss/yaml v1.0.0 diff --git a/go.sum b/go.sum index 37354c045..9430ab305 100644 --- a/go.sum +++ b/go.sum @@ -151,6 +151,8 @@ github.com/drone/go-scm v1.5.1-0.20190826160521-fda52b1e0829/go.mod h1:YT4FxQ3U/ github.com/drone/go-scm v1.6.0 h1:PZZWLeSHHwdc6zbSQpg9n0CNoRB+8DAINzX9X/wJifY= github.com/drone/go-scm v1.6.1-0.20190920225054-0d1ea63283ad h1:rVQW27ofuahCt6Vur7h8oV+fi7JW8yxCiw6PzQmqEFw= github.com/drone/go-scm v1.6.1-0.20190920225054-0d1ea63283ad/go.mod h1:YT4FxQ3U/ltdCrBJR9B0tRpJ1bYA/PM3NyaLE/rYIvw= +github.com/drone/go-scm v1.6.1-0.20190921005131-635e46e88c20 h1:/Ler+K1NlugcNoBPBLMCcWoN73rnPf+Fscdugb8KWYU= +github.com/drone/go-scm v1.6.1-0.20190921005131-635e46e88c20/go.mod h1:YT4FxQ3U/ltdCrBJR9B0tRpJ1bYA/PM3NyaLE/rYIvw= github.com/drone/signal v1.0.0 h1:NrnM2M/4yAuU/tXs6RP1a1ZfxnaHwYkd0kJurA1p6uI= github.com/drone/signal v1.0.0/go.mod h1:S8t92eFT0g4WUgEc/LxG+LCuiskpMNsG0ajAMGnyZpc= github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= diff --git a/handler/api/api.go b/handler/api/api.go index 67d8b1405..62c7db9ec 100644 --- a/handler/api/api.go +++ b/handler/api/api.go @@ -27,7 +27,6 @@ import ( "github.com/drone/drone/handler/api/queue" "github.com/drone/drone/handler/api/repos" "github.com/drone/drone/handler/api/repos/builds" - "github.com/drone/drone/handler/api/repos/builds/link" "github.com/drone/drone/handler/api/repos/builds/logs" "github.com/drone/drone/handler/api/repos/builds/stages" "github.com/drone/drone/handler/api/repos/collabs" @@ -66,7 +65,6 @@ func New( logs core.LogStore, license *core.License, licenses core.LicenseService, - linker core.Linker, perms core.PermStore, repos core.RepositoryStore, repoz core.RepositoryService, @@ -93,7 +91,6 @@ func New( Logs: logs, License: license, Licenses: licenses, - Linker: linker, Perms: perms, Repos: repos, Repoz: repoz, @@ -123,7 +120,6 @@ type Server struct { Logs core.LogStore License *core.License Licenses core.LicenseService - Linker core.Linker Perms core.PermStore Repos core.RepositoryStore Repoz core.RepositoryService @@ -179,7 +175,6 @@ func (s Server) Handler() http.Handler { r.Get("/latest", builds.HandleLast(s.Repos, s.Builds, s.Stages)) r.Get("/{number}", builds.HandleFind(s.Repos, s.Builds, s.Stages)) - r.Get("/{number}/link", link.HandleLink(s.Repos, s.Builds, s.Linker)) r.Get("/{number}/logs/{stage}/{step}", logs.HandleFind(s.Repos, s.Builds, s.Stages, s.Steps, s.Logs)) r.With( diff --git a/handler/api/repos/builds/link/link.go b/handler/api/repos/builds/link/link.go deleted file mode 100644 index f70f65922..000000000 --- a/handler/api/repos/builds/link/link.go +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright 2019 Drone IO, Inc. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package link - -import ( - "net/http" - "strconv" - - "github.com/drone/drone/core" - "github.com/drone/drone/handler/api/render" - - "github.com/go-chi/chi" -) - -// payload wraps the link and returns to the -// client as a valid json object. -type payload struct { - Link string `json:"link"` -} - -// HandleLink returns an http.HandlerFunc that redirects the -// user to the git resource in the remote source control -// management system. -func HandleLink( - repos core.RepositoryStore, - builds core.BuildStore, - linker core.Linker, -) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - var ( - ctx = r.Context() - namespace = chi.URLParam(r, "owner") - name = chi.URLParam(r, "name") - ) - number, err := strconv.ParseInt(chi.URLParam(r, "number"), 10, 64) - if err != nil { - render.BadRequest(w, err) - return - } - repo, err := repos.FindName(ctx, namespace, name) - if err != nil { - render.NotFound(w, err) - return - } - build, err := builds.FindNumber(ctx, repo.ID, number) - if err != nil { - render.NotFound(w, err) - return - } - to, err := linker.Link(ctx, repo, build) - if err != nil { - render.NotFound(w, err) - return - } - if r.FormValue("redirect") == "true" { - http.Redirect(w, r, to, http.StatusSeeOther) - return - } - v := &payload{to} - render.JSON(w, v, http.StatusOK) - } -} diff --git a/handler/web/link/link.go b/handler/web/link/link.go new file mode 100644 index 000000000..489b6292c --- /dev/null +++ b/handler/web/link/link.go @@ -0,0 +1,68 @@ +// Copyright 2019 Drone IO, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package link + +import ( + "net/http" + + "github.com/drone/drone/core" + "github.com/drone/go-scm/scm" + + "github.com/go-chi/chi" +) + +// HandleCommit returns an http.HandlerFunc that redirects the +// user to the git resource in the remote source control +// management system. +func HandleCommit(linker core.Linker) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var ( + ctx = r.Context() + namespace = chi.URLParam(r, "namespace") + name = chi.URLParam(r, "name") + commit = chi.URLParam(r, "commit") + ref = r.FormValue("ref") + ) + repo := scm.Join(namespace, name) + to, err := linker.Link(ctx, repo, ref, commit) + if err != nil { + http.Error(w, "Not Found", http.StatusNotFound) + return + } + http.Redirect(w, r, to, http.StatusSeeOther) + } +} + +// HandleTree returns an http.HandlerFunc that redirects the +// user to the git resource in the remote source control +// management system. +func HandleTree(linker core.Linker) http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var ( + ctx = r.Context() + namespace = chi.URLParam(r, "namespace") + name = chi.URLParam(r, "name") + ref = chi.URLParam(r, "*") + commit = r.FormValue("sha") + ) + repo := scm.Join(namespace, name) + to, err := linker.Link(ctx, repo, ref, commit) + if err != nil { + http.Error(w, "Not Found", http.StatusNotFound) + return + } + http.Redirect(w, r, to, http.StatusSeeOther) + } +} diff --git a/handler/api/repos/builds/link/link_test.go b/handler/web/link/link_test.go similarity index 100% rename from handler/api/repos/builds/link/link_test.go rename to handler/web/link/link_test.go diff --git a/handler/web/web.go b/handler/web/web.go index f2b7443e6..1f5648e4e 100644 --- a/handler/web/web.go +++ b/handler/web/web.go @@ -20,6 +20,7 @@ import ( "github.com/drone/drone-ui/dist" "github.com/drone/drone/core" "github.com/drone/drone/handler/web/landingpage" + "github.com/drone/drone/handler/web/link" "github.com/drone/drone/logger" "github.com/drone/go-login/login" "github.com/drone/go-scm/scm" @@ -36,6 +37,7 @@ func New( hooks core.HookParser, license *core.License, licenses core.LicenseService, + linker core.Linker, login login.Middleware, repos core.RepositoryStore, session core.Session, @@ -54,6 +56,7 @@ func New( Hooks: hooks, License: license, Licenses: licenses, + Linker: linker, Login: login, Repos: repos, Session: session, @@ -75,6 +78,7 @@ type Server struct { Hooks core.HookParser License *core.License Licenses core.LicenseService + Linker core.Linker Login login.Middleware Repos core.RepositoryStore Session core.Session @@ -101,6 +105,9 @@ func (s Server) Handler() http.Handler { r.Post("/", HandleHook(s.Repos, s.Builds, s.Triggerer, s.Hooks)) }) + r.Get("/link/{namespace}/{name}/tree/*", link.HandleTree(s.Linker)) + r.Get("/link/{namespace}/{name}/src/*", link.HandleTree(s.Linker)) + r.Get("/link/{namespace}/{name}/commit/{commit}", link.HandleCommit(s.Linker)) r.Get("/version", HandleVersion) r.Get("/varz", HandleVarz(s.Client, s.License)) diff --git a/service/linker/linker.go b/service/linker/linker.go index a1513bc50..1adcd7e08 100644 --- a/service/linker/linker.go +++ b/service/linker/linker.go @@ -32,9 +32,9 @@ type service struct { client *scm.Client } -func (s *service) Link(ctx context.Context, repo *core.Repository, build *core.Build) (string, error) { - return s.client.Linker.Resource(ctx, repo.Slug, scm.Reference{ - Path: build.Ref, - Sha: build.After, +func (s *service) Link(ctx context.Context, repo, ref, sha string) (string, error) { + return s.client.Linker.Resource(ctx, repo, scm.Reference{ + Path: ref, + Sha: sha, }) }