Skip to content

Commit

Permalink
Merge pull request #51
Browse files Browse the repository at this point in the history
Create build only if the config file exists in repo
  • Loading branch information
bartekpacia authored Oct 27, 2024
2 parents eaff4b8 + fd3ad40 commit ba63877
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 21 deletions.
5 changes: 0 additions & 5 deletions backend/cmd/gh-updater/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,6 @@ func main() {
slog.Error("error decoding GitHub App private key from base64", slog.Any("error", err))
os.Exit(1)
}

// FIXME: remove this!!!
slog.Debug("DEBUG: ", slog.Int64("GITHUB_APP_ID", githubAppID))
slog.Debug("DEBUG: ", slog.String("GITHUB_APP_PRIVATE_KEY_BASE64", privateKeyBase64))

rsaPrivateKey, err := jwt.ParseRSAPrivateKeyFromPEM(privateKey)
if err != nil {
slog.Error("error parsing GitHub App RSA private key from PEM", slog.Any("error", err))
Expand Down
57 changes: 53 additions & 4 deletions backend/cmd/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@ package main

import (
"context"
"crypto/tls"
"encoding/base64"
"fmt"
"github.com/bee-ci/bee-ci-system/internal/common/ghservice"
"github.com/golang-jwt/jwt/v5"
"github.com/redis/go-redis/v9"
"log/slog"
"net/http"
"os"
"os/signal"
"strconv"
"time"

influxdb2 "github.com/influxdata/influxdb-client-go/v2"
Expand All @@ -24,16 +30,25 @@ var jwtSecret = []byte("your-very-secret-key")

func main() {
ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)

slog.SetDefault(setUpLogging())
slog.Debug("server is starting...")

serverURL := mustGetenv("SERVER_URL")
port := mustGetenv("PORT")

mainDomain := os.Getenv("MAIN_DOMAIN")
frontendURL := mustGetenv("FRONTEND_URL")

slog.Debug("server is starting...")
githubAppID := mustGetenvInt64("GITHUB_APP_ID")
privateKeyBase64 := mustGetenv("GITHUB_APP_PRIVATE_KEY_BASE64")
privateKey, err := base64.StdEncoding.DecodeString(privateKeyBase64)
if err != nil {
slog.Error("error decoding GitHub App private key from base64", slog.Any("error", err))
os.Exit(1)
}
rsaPrivateKey, err := jwt.ParseRSAPrivateKeyFromPEM(privateKey)
if err != nil {
slog.Error("error parsing GitHub App RSA private key from PEM", slog.Any("error", err))
}

githubAppClientID := mustGetenv("GITHUB_APP_CLIENT_ID")
githubAppWebhookSecret := mustGetenv("GITHUB_APP_WEBHOOK_SECRET")
Expand All @@ -53,6 +68,28 @@ func main() {
}
slog.Info("connected to Postgres database", "host", dbHost, "port", dbPort, "user", dbUser, "name", dbName, "options", dbOpts)

redisAddr := mustGetenv("REDIS_ADDRESS")
redisPassword := mustGetenv("REDIS_PASSWORD")

var tlsConfig *tls.Config
if mustGetenv("REDIS_USE_TLS") == "true" {
tlsConfig = &tls.Config{}
}

redisDB := redis.NewClient(&redis.Options{
Addr: redisAddr,
Password: redisPassword,
TLSConfig: tlsConfig,
DB: 0, // use default DB
})

err = redisDB.Ping(ctx).Err()
if err != nil {
slog.Error("error connecting to Redis database", slog.Any("error", err))
os.Exit(1)
}
slog.Info("connected to Redis database", "address", redisAddr)

influxURL := mustGetenv("INFLUXDB_URL")
influxToken := mustGetenv("INFLUXDB_TOKEN")
influxBucket := mustGetenv("INFLUXDB_BUCKET")
Expand All @@ -72,7 +109,9 @@ func main() {
repoRepo := data.NewPostgresRepoRepo(db)
logsRepo := data.NewInfluxLogsRepo(influxClient, influxOrg, influxBucket)

webhooks, err := webhook.NewHandler(userRepo, repoRepo, buildRepo, mainDomain, frontendURL, githubAppClientID, githubAppClientSecret, githubAppWebhookSecret, jwtSecret)
githubService := ghservice.NewGithubService(githubAppID, rsaPrivateKey, redisDB)

webhooks, err := webhook.NewHandler(userRepo, repoRepo, buildRepo, githubService, mainDomain, frontendURL, githubAppClientID, githubAppClientSecret, githubAppWebhookSecret, jwtSecret)
if err != nil {
slog.Error("error creating webhook handler", slog.Any("error", err))
os.Exit(1)
Expand Down Expand Up @@ -151,3 +190,13 @@ func mustGetenv(varname string) string {
}
return value
}

func mustGetenvInt64(varname string) int64 {
value := mustGetenv(varname)
i, err := strconv.ParseInt(value, 10, 64)
if err != nil {
slog.Error(varname+" env var is not a valid int64", slog.Any("error", err))
os.Exit(1)
}
return i
}
3 changes: 0 additions & 3 deletions backend/internal/common/ghservice/ghservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,6 @@ func (g GithubService) getInstallationAccessToken(ctx context.Context, installat
return "", fmt.Errorf("generate signed jwt: %w", err)
}

// FIXME(bartekpacia): Remove this print!!!
g.logger.Debug("DEBUG: generated a signed JWT string", slog.String("jwt", jwtString))

appClient := http.Client{Transport: &bearerTransport{Token: jwtString}}
gh := github.NewClient(&appClient)
res, _, err := gh.Apps.CreateInstallationToken(ctx, installationID, nil)
Expand Down
50 changes: 41 additions & 9 deletions backend/internal/server/webhook/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import (
"embed"
"encoding/json"
"fmt"
"github.com/bee-ci/bee-ci-system/internal/common/ghservice"
"html/template"
"io"
"log"
"log/slog"
"net/http"
"net/url"
"slices"
"strconv"
"time"

Expand All @@ -28,14 +30,13 @@ import (
var redirectHTMLPage embed.FS

type Handler struct {
httpClient *http.Client
userRepo data.UserRepo
repoRepo data.RepoRepo
buildRepo data.BuildRepo

// The domain where the auth cookie will be placed. For example:
// - .pacia.tech
// - .karolak.cc
httpClient *http.Client
userRepo data.UserRepo
repoRepo data.RepoRepo
buildRepo data.BuildRepo
githubService *ghservice.GithubService

// The domain where the auth cookie will be placed, for example ".pacia.tech" or .karolak.cc".
//
// Must be empty for localhost.
mainDomain string
Expand All @@ -57,6 +58,7 @@ func NewHandler(
userRepo data.UserRepo,
repoRepo data.RepoRepo,
buildRepo data.BuildRepo,
githubService *ghservice.GithubService,
mainDomain string,
frontendURL string,
githubAppClientID string,
Expand All @@ -74,6 +76,7 @@ func NewHandler(
userRepo: userRepo,
repoRepo: repoRepo,
buildRepo: buildRepo,
githubService: githubService,
mainDomain: mainDomain,
redirectURL: redirectURL,
githubAppClientID: githubAppClientID,
Expand Down Expand Up @@ -367,7 +370,36 @@ func (h Handler) handleWebhook(w http.ResponseWriter, r *http.Request) {
slog.Int64("sender.id", userID),
)

// Create build
repoOwner := *event.Repo.Owner.Login
repoName := *event.Repo.Name

// Check if the config file exists. If it does, parse it.
ghClient, err := h.githubService.GetClientForInstallation(r.Context(), *installation.ID)
if err != nil {
logger.Error("error getting github client", slog.Any("error", err))
http.Error(w, "error getting github client", http.StatusInternalServerError)
return
}

// Validate that the config file exists
_, files, _, err := ghClient.Repositories.GetContents(r.Context(), repoOwner, repoName, "/", nil)
if err != nil {
logger.Error("error getting repo's root directory content", slog.Any("error", err))
http.Error(w, "error getting repo's directory content", http.StatusInternalServerError)
return
}
hasConfigFile := slices.ContainsFunc(files, func(file *github.RepositoryContent) bool {
return *file.Name == ".bee-ci.json"
})

if !hasConfigFile {
logger.Debug(".bee-ci.json config file does not exist, skipping execution")
return
}

logger.Debug(".bee-ci.json config file exists, proceeding with execution...")

// Create a new build
if *event.Action == "requested" || *event.Action == "rerequested" {
headSHA := *event.CheckSuite.HeadSHA
message := *event.CheckSuite.HeadCommit.Message
Expand Down
3 changes: 3 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ services:
INFLUXDB_TOKEN: ${INFLUXDB_TOKEN}
INFLUXDB_ORG: ${INFLUXDB_ORG}
INFLUXDB_BUCKET: ${INFLUXDB_BUCKET}
REDIS_ADDRESS: ${REDIS_ADDRESS}
REDIS_PASSWORD: ${REDIS_PASSWORD}
REDIS_USE_TLS: false

gh-updater:
build:
Expand Down

0 comments on commit ba63877

Please sign in to comment.