get_gitlab_repo_procfile.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. package project_integration
  2. import (
  3. "errors"
  4. "fmt"
  5. "net/http"
  6. "net/url"
  7. "regexp"
  8. "strings"
  9. "github.com/porter-dev/porter/api/server/handlers"
  10. "github.com/porter-dev/porter/api/server/shared"
  11. "github.com/porter-dev/porter/api/server/shared/apierrors"
  12. "github.com/porter-dev/porter/api/server/shared/config"
  13. "github.com/porter-dev/porter/api/types"
  14. "github.com/porter-dev/porter/internal/models"
  15. ints "github.com/porter-dev/porter/internal/models/integrations"
  16. "github.com/xanzy/go-gitlab"
  17. )
  18. var procfileRegex = regexp.MustCompile("^([A-Za-z0-9_]+):\\s*(.+)$")
  19. type GetGitlabRepoProcfileHandler struct {
  20. handlers.PorterHandlerReadWriter
  21. }
  22. func NewGetGitlabRepoProcfileHandler(
  23. config *config.Config,
  24. decoderValidator shared.RequestDecoderValidator,
  25. writer shared.ResultWriter,
  26. ) *GetGitlabRepoProcfileHandler {
  27. return &GetGitlabRepoProcfileHandler{
  28. PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
  29. }
  30. }
  31. func (p *GetGitlabRepoProcfileHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  32. project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
  33. user, _ := r.Context().Value(types.UserScope).(*models.User)
  34. gi, _ := r.Context().Value(types.GitlabIntegrationScope).(*ints.GitlabIntegration)
  35. request := &types.GetGitlabProcfileRequest{}
  36. ok := p.DecodeAndValidate(w, r, request)
  37. if !ok {
  38. return
  39. }
  40. path, err := url.QueryUnescape(request.Path)
  41. if err != nil {
  42. p.HandleAPIError(w, r, apierrors.NewErrForbidden(fmt.Errorf("malformed query param path")))
  43. return
  44. }
  45. client, err := getGitlabClient(p.Repo(), user.ID, project.ID, gi, p.Config())
  46. if err != nil {
  47. if errors.Is(err, errUnauthorizedGitlabUser) {
  48. p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(errUnauthorizedGitlabUser, http.StatusUnauthorized))
  49. }
  50. p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  51. return
  52. }
  53. file, resp, err := client.RepositoryFiles.GetRawFile(request.RepoPath,
  54. strings.TrimPrefix(path, "./"), &gitlab.GetRawFileOptions{
  55. Ref: gitlab.String(request.Branch),
  56. },
  57. )
  58. if resp.StatusCode == http.StatusUnauthorized {
  59. p.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(fmt.Errorf("unauthorized gitlab user"), http.StatusUnauthorized))
  60. return
  61. } else if resp.StatusCode == http.StatusNotFound {
  62. w.WriteHeader(http.StatusNotFound)
  63. p.HandleAPIError(w, r, apierrors.NewErrInternal(fmt.Errorf("no such procfile exists")))
  64. return
  65. }
  66. if err != nil {
  67. p.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  68. return
  69. }
  70. parsedContents := make(types.GetProcfileResponse)
  71. // parse the procfile information
  72. for _, line := range strings.Split(string(file), "\n") {
  73. if matches := procfileRegex.FindStringSubmatch(line); matches != nil {
  74. parsedContents[matches[1]] = matches[2]
  75. }
  76. }
  77. p.WriteResult(w, r, parsedContents)
  78. }