Feat: Remove Requirement for Dotfile (#84)

This MR removes the requirement for a dotfile (the dotfile is now optional and will override the configuration provided via environment variables). The requirement for providing a project ID is also eliminated, by parsing the namespace and project name from the SSH or HTTPS remote, and then using that to query Gitlab for a matching project.
This commit is contained in:
Harrison (Harry) Cramer
2023-11-11 23:51:11 -05:00
committed by GitHub
parent 38df51bfbc
commit 80b597e56a
8 changed files with 216 additions and 145 deletions

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"net/http/httputil"
"os"
@@ -18,7 +19,6 @@ type Client struct {
mergeId int
gitlabInstance string
authToken string
logPath string
git *gitlab.Client
}
@@ -27,85 +27,32 @@ type DebugSettings struct {
GoResponse bool `json:"go_response"`
}
var requestLogger retryablehttp.RequestLogHook = func(l retryablehttp.Logger, r *http.Request, i int) {
logPath := os.Args[len(os.Args)-1]
/* This will parse and validate the project settings and then initialize the Gitlab client */
func (c *Client) initGitlabClient() error {
file, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
defer file.Close()
token := r.Header.Get("Private-Token")
r.Header.Set("Private-Token", "REDACTED")
res, err := httputil.DumpRequest(r, true)
if err != nil {
panic(err)
}
r.Header.Set("Private-Token", token)
_, err = file.Write([]byte("\n-- REQUEST --\n")) //nolint:all
_, err = file.Write(res) //nolint:all
_, err = file.Write([]byte("\n")) //nolint:all
}
var responseLogger retryablehttp.ResponseLogHook = func(l retryablehttp.Logger, response *http.Response) {
logPath := os.Args[len(os.Args)-1]
file, err := os.OpenFile(logPath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err)
}
defer file.Close()
res, err := httputil.DumpResponse(response, true)
if err != nil {
panic(err)
if len(os.Args) < 6 {
return errors.New("Must provide gitlab url, port, auth token, debug settings, and log path")
}
_, err = file.Write([]byte("\n-- RESPONSE --\n")) //nolint:all
_, err = file.Write(res) //nolint:all
_, err = file.Write([]byte("\n")) //nolint:all
}
/* This will initialize the client with the token and check for the basic project ID and command arguments */
func (c *Client) init(branchName string) error {
if len(os.Args) < 5 {
return errors.New("Must provide project ID, gitlab instance, port, and auth token!")
gitlabInstance := os.Args[1]
if gitlabInstance == "" {
return errors.New("GitLab instance URL cannot be empty")
}
projectId := os.Args[1]
gitlabInstance := os.Args[2]
authToken := os.Args[4]
debugSettings := os.Args[5]
authToken := os.Args[3]
if authToken == "" {
return errors.New("Auth token cannot be empty")
}
/* Parse debug settings and initialize logger handlers */
debugSettings := os.Args[4]
var debugObject DebugSettings
err := json.Unmarshal([]byte(debugSettings), &debugObject)
if err != nil {
return fmt.Errorf("Could not parse debug settings: %w, %s", err, debugSettings)
}
logPath := os.Args[len(os.Args)-1]
if projectId == "" {
return errors.New("Project ID cannot be empty")
}
if gitlabInstance == "" {
return errors.New("GitLab instance URL cannot be empty")
}
if authToken == "" {
return errors.New("Auth token cannot be empty")
}
c.gitlabInstance = gitlabInstance
c.projectId = projectId
c.authToken = authToken
c.logPath = logPath
var apiCustUrl = fmt.Sprintf(c.gitlabInstance + "/api/v4")
var apiCustUrl = fmt.Sprintf(gitlabInstance + "/api/v4")
gitlabOptions := []gitlab.ClientOptionFunc{
gitlab.WithBaseURL(apiCustUrl),
@@ -125,13 +72,40 @@ func (c *Client) init(branchName string) error {
return fmt.Errorf("Failed to create client: %v", err)
}
c.gitlabInstance = gitlabInstance
c.authToken = authToken
c.git = git
return nil
}
/* This will fetch the project ID and merge request ID using the client */
func (c *Client) initProjectSettings(remoteUrl string, namespace string, projectName string, branchName string) error {
idStr := namespace + "/" + projectName
opt := gitlab.GetProjectOptions{}
project, _, err := c.git.Projects.GetProject(idStr, &opt)
if err != nil {
return fmt.Errorf(fmt.Sprintf("Error getting project at %s", remoteUrl), err)
}
if project == nil {
return fmt.Errorf(fmt.Sprintf("Could not find project at %s", remoteUrl), err)
}
if project == nil {
return fmt.Errorf("No projects you are a member of contained remote URL %s", remoteUrl)
}
c.projectId = fmt.Sprint(project.ID)
options := gitlab.ListProjectMergeRequestsOptions{
Scope: gitlab.String("all"),
State: gitlab.String("opened"),
SourceBranch: &branchName,
}
mergeRequests, _, err := git.MergeRequests.ListProjectMergeRequests(c.projectId, &options)
mergeRequests, _, err := c.git.MergeRequests.ListProjectMergeRequests(c.projectId, &options)
if err != nil {
return fmt.Errorf("Failed to list merge requests: %w", err)
}
@@ -147,7 +121,6 @@ func (c *Client) init(branchName string) error {
}
c.mergeId = mergeIdInt
c.git = git
return nil
}
@@ -165,3 +138,54 @@ func (c *Client) handleError(w http.ResponseWriter, err error, message string, s
c.handleError(w, err, "Could not encode response", http.StatusInternalServerError)
}
}
var requestLogger retryablehttp.RequestLogHook = func(l retryablehttp.Logger, r *http.Request, i int) {
file := openLogFile()
defer file.Close()
token := r.Header.Get("Private-Token")
r.Header.Set("Private-Token", "REDACTED")
res, err := httputil.DumpRequest(r, true)
if err != nil {
log.Fatalf("Error dumping request: %v", err)
os.Exit(1)
}
r.Header.Set("Private-Token", token)
_, err = file.Write([]byte("\n-- REQUEST --\n")) //nolint:all
_, err = file.Write(res) //nolint:all
_, err = file.Write([]byte("\n")) //nolint:all
}
var responseLogger retryablehttp.ResponseLogHook = func(l retryablehttp.Logger, response *http.Response) {
file := openLogFile()
defer file.Close()
res, err := httputil.DumpResponse(response, true)
if err != nil {
log.Fatalf("Error dumping response: %v", err)
os.Exit(1)
}
_, err = file.Write([]byte("\n-- RESPONSE --\n")) //nolint:all
_, err = file.Write(res) //nolint:all
_, err = file.Write([]byte("\n")) //nolint:all
}
func openLogFile() *os.File {
logFile := os.Args[len(os.Args)-1]
file, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
if os.IsNotExist(err) {
log.Printf("Log file %s does not exist", logFile)
} else if os.IsPermission(err) {
log.Printf("Permission denied for log file %s", logFile)
} else {
log.Printf("Error opening log file %s: %v", logFile, err)
}
os.Exit(1)
}
return file
}