Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c7d68c742d |
+34
-3
@@ -1,10 +1,14 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"log"
|
"log"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"gitea.leeworks.dev/0xwheatyz/gitea-mobile/internal/config"
|
"gitea.leeworks.dev/0xwheatyz/gitea-mobile/internal/config"
|
||||||
giteaclient "gitea.leeworks.dev/0xwheatyz/gitea-mobile/internal/gitea"
|
giteaclient "gitea.leeworks.dev/0xwheatyz/gitea-mobile/internal/gitea"
|
||||||
@@ -36,8 +40,35 @@ func main() {
|
|||||||
handler = middleware.Auth(cfg.SessionSecret, cfg.GiteaToken)(handler)
|
handler = middleware.Auth(cfg.SessionSecret, cfg.GiteaToken)(handler)
|
||||||
handler = middleware.Logging()(handler)
|
handler = middleware.Logging()(handler)
|
||||||
|
|
||||||
slog.Info("server starting", "addr", cfg.ListenAddr, "gitea_url", cfg.GiteaURL)
|
srv := &http.Server{
|
||||||
if err := http.ListenAndServe(cfg.ListenAddr, handler); err != nil {
|
Addr: cfg.ListenAddr,
|
||||||
log.Fatalf("server error: %v", err)
|
Handler: handler,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Channel to receive shutdown signals.
|
||||||
|
quit := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(quit, syscall.SIGTERM, syscall.SIGINT)
|
||||||
|
|
||||||
|
// Start server in a goroutine.
|
||||||
|
go func() {
|
||||||
|
slog.Info("server starting", "addr", cfg.ListenAddr, "gitea_url", cfg.GiteaURL)
|
||||||
|
if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
||||||
|
log.Fatalf("server error: %v", err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Block until a shutdown signal is received.
|
||||||
|
sig := <-quit
|
||||||
|
slog.Info("shutdown signal received, draining in-flight requests", "signal", sig.String())
|
||||||
|
|
||||||
|
// Give in-flight requests up to 15 seconds to complete.
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
if err := srv.Shutdown(ctx); err != nil {
|
||||||
|
slog.Error("server forced to shutdown", "error", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
slog.Info("server stopped gracefully")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -945,40 +945,6 @@ func (c *Client) SetIssueState(ctx context.Context, token, owner, repo string, i
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MergePull merges a pull request using the specified merge style.
|
|
||||||
// Valid styles: "merge", "rebase", "rebase-merge", "squash".
|
|
||||||
// If style is empty, defaults to "merge".
|
|
||||||
func (c *Client) MergePull(ctx context.Context, token, owner, repo string, index int64, style, title, message string) error {
|
|
||||||
if style == "" {
|
|
||||||
style = "merge"
|
|
||||||
}
|
|
||||||
|
|
||||||
payload := map[string]string{
|
|
||||||
"Do": style,
|
|
||||||
}
|
|
||||||
if title != "" {
|
|
||||||
payload["merge_message_field"] = title
|
|
||||||
}
|
|
||||||
if message != "" {
|
|
||||||
payload["merge_message_field"] = message
|
|
||||||
}
|
|
||||||
|
|
||||||
jsonData, err := json.Marshal(payload)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("marshaling merge request: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
path := fmt.Sprintf("/repos/%s/%s/pulls/%d/merge", owner, repo, index)
|
|
||||||
resp, err := c.doRequest(ctx, token, http.MethodPost, path, strings.NewReader(string(jsonData)))
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("merging pull request: %w", err)
|
|
||||||
}
|
|
||||||
resp.Body.Close()
|
|
||||||
|
|
||||||
c.InvalidateAll()
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddComment creates a comment on an issue and returns the created Comment.
|
// AddComment creates a comment on an issue and returns the created Comment.
|
||||||
func (c *Client) AddComment(ctx context.Context, token, owner, repo string, index int64, body string) (*Comment, error) {
|
func (c *Client) AddComment(ctx context.Context, token, owner, repo string, index int64, body string) (*Comment, error) {
|
||||||
return c.PostComment(ctx, token, owner, repo, index, body)
|
return c.PostComment(ctx, token, owner, repo, index, body)
|
||||||
|
|||||||
@@ -1456,81 +1456,3 @@ func TestRetryDelay_ExponentialBackoff(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMergePull(t *testing.T) {
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
if r.Method != http.MethodPost {
|
|
||||||
t.Errorf("expected POST, got %s", r.Method)
|
|
||||||
}
|
|
||||||
if r.URL.Path != "/api/v1/repos/owner1/repo1/pulls/5/merge" {
|
|
||||||
t.Errorf("unexpected path: %s", r.URL.Path)
|
|
||||||
}
|
|
||||||
if r.Header.Get("Authorization") != "token test-token" {
|
|
||||||
t.Error("missing or wrong Authorization header")
|
|
||||||
}
|
|
||||||
|
|
||||||
var body map[string]string
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
|
||||||
t.Fatalf("failed to decode body: %v", err)
|
|
||||||
}
|
|
||||||
if body["Do"] != "squash" {
|
|
||||||
t.Errorf("expected Do=squash, got %q", body["Do"])
|
|
||||||
}
|
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
c := NewClient(server.URL)
|
|
||||||
c.setCache("pulls-org1", "should-be-invalidated")
|
|
||||||
|
|
||||||
err := c.MergePull(context.Background(), "test-token", "owner1", "repo1", 5, "squash", "", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify cache was invalidated.
|
|
||||||
_, ok := c.getFromCache("pulls-org1")
|
|
||||||
if ok {
|
|
||||||
t.Error("expected cache to be invalidated after MergePull")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMergePull_DefaultStyle(t *testing.T) {
|
|
||||||
var receivedStyle string
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
var body map[string]string
|
|
||||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
|
||||||
t.Fatalf("failed to decode body: %v", err)
|
|
||||||
}
|
|
||||||
receivedStyle = body["Do"]
|
|
||||||
w.WriteHeader(http.StatusOK)
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
c := NewClient(server.URL)
|
|
||||||
err := c.MergePull(context.Background(), "test-token", "owner1", "repo1", 5, "", "", "")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unexpected error: %v", err)
|
|
||||||
}
|
|
||||||
if receivedStyle != "merge" {
|
|
||||||
t.Errorf("expected default style 'merge', got %q", receivedStyle)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestMergePull_Error(t *testing.T) {
|
|
||||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
||||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
|
||||||
fmt.Fprintln(w, `{"message":"not mergeable"}`)
|
|
||||||
}))
|
|
||||||
defer server.Close()
|
|
||||||
|
|
||||||
c := NewClient(server.URL)
|
|
||||||
err := c.MergePull(context.Background(), "test-token", "owner1", "repo1", 5, "merge", "", "")
|
|
||||||
if err == nil {
|
|
||||||
t.Fatal("expected error for 405 response, got nil")
|
|
||||||
}
|
|
||||||
if !strings.Contains(err.Error(), "405") {
|
|
||||||
t.Errorf("error should contain status code 405, got: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user