Skip to content

Implement Repository Services #17

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 28 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
3834565
create contribution fetching for all users in the system from bigquer…
VishakhaSainani Jun 5, 2025
1c7b715
Merge branch 'feat/db_migrations' into feat/contribution-service
VishakhaSainani Jun 5, 2025
284fdaf
Merge branch 'fix/login-timestamp-type' into feat/contribution-service
VishakhaSainani Jun 9, 2025
d3d91a4
use userid while adding contribution
VishakhaSainani Jun 9, 2025
1c1135f
get id and score from contribution_score
VishakhaSainani Jun 9, 2025
f94000e
fix date format
VishakhaSainani Jun 9, 2025
a17215c
refactor processfetchedcontribution function and update http client h…
VishakhaSainani Jun 16, 2025
de13e7a
implement users five recent contributions
VishakhaSainani Jun 17, 2025
f7e8fa9
fetch all contributions for the user
VishakhaSainani Jun 17, 2025
887faa4
remove unnecessary lines
VishakhaSainani Jun 17, 2025
f59627d
implement fetch all contributed repositories of user (my contribution…
VishakhaSainani Jun 18, 2025
8e88ba1
Merge branch 'feat/contribution-service' into feat/repository-service
VishakhaSainani Jun 18, 2025
82afbdd
send all details for the repository
VishakhaSainani Jun 18, 2025
c8da5f1
fetch particular repository details
VishakhaSainani Jun 18, 2025
121d59c
implement fetch particular repo contributors
VishakhaSainani Jun 18, 2025
465fcd4
implement fetch contributions of user in a particular repository
VishakhaSainani Jun 18, 2025
f85a010
fetch particular repository language percentage
VishakhaSainani Jun 19, 2025
bb68dfa
pass http client in service struct
VishakhaSainani Jun 19, 2025
e5a4d0b
add contributors_url in repository table
VishakhaSainani Jun 19, 2025
a8e5768
Merge branch 'db/migration/add-contributors-url' into feat/contributi…
VishakhaSainani Jun 19, 2025
5773245
fetch and contributors url for repository
VishakhaSainani Jun 20, 2025
f365171
remove fetch five recent contributions for the user- this could be ha…
VishakhaSainani Jun 20, 2025
89961fd
Merge branch 'feat/contribution-service' into feat/repository-service
VishakhaSainani Jun 20, 2025
966d2a2
Fix: Restore correct merge changes for internal/app/repository/domain.go
VishakhaSainani Jun 20, 2025
671c8ac
add contributors url when fetching users contributes repositories
VishakhaSainani Jun 20, 2025
67ab318
seperate logic for fetching repo by github id and repository table id
VishakhaSainani Jun 20, 2025
778c359
use repo id for fetching contributions of a particular repo of a user
VishakhaSainani Jun 23, 2025
f5af0ac
log error in slog
VishakhaSainani Jun 23, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
local.yaml
local.yaml

*.ps1
15 changes: 11 additions & 4 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"log/slog"
"net/http"
"os"

"os/signal"
"syscall"
"time"
Expand All @@ -18,21 +18,28 @@ import (
func main() {
ctx := context.Background()

cfg,err := config.LoadAppConfig()
cfg, err := config.LoadAppConfig()
if err != nil {
slog.Error("error loading app config", "error", err)
return
}


db, err := config.InitDataStore(cfg)
if err != nil {
slog.Error("error initializing database", "error", err)
return
}
defer db.Close()

dependencies := app.InitDependencies(db,cfg)
bigqueryInstance, err := config.BigqueryInit(ctx, cfg)
if err != nil {
slog.Error("error initializing bigquery", "error", err)
return
}

httpClient := &http.Client{}

dependencies := app.InitDependencies(db, cfg, bigqueryInstance, httpClient)

router := app.NewRouter(dependencies)

Expand Down
47 changes: 43 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,62 @@ module github.com/joshsoftware/code-curiosity-2025
go 1.23.4

require (
cloud.google.com/go/bigquery v1.68.0
github.com/golang-jwt/jwt/v4 v4.5.2
github.com/golang-migrate/migrate/v4 v4.18.3
github.com/ilyakaznacheev/cleanenv v1.5.0
github.com/jmoiron/sqlx v1.4.0
github.com/lib/pq v1.10.9
golang.org/x/oauth2 v0.29.0
google.golang.org/api v0.231.0
)

require (
cloud.google.com/go v0.121.0 // indirect
cloud.google.com/go/auth v0.16.1 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/iam v1.5.2 // indirect
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/golang-migrate/migrate/v4 v4.18.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/apache/arrow/go/v15 v15.0.2 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/google/flatbuffers v23.5.26+incompatible // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/joho/godotenv v1.5.1 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
github.com/pierrec/lz4/v4 v4.1.18 // indirect
github.com/zeebo/xxh3 v1.0.2 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/metric v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect
go.uber.org/atomic v1.11.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
golang.org/x/crypto v0.37.0 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/mod v0.23.0 // indirect
golang.org/x/net v0.39.0 // indirect
golang.org/x/sync v0.14.0 // indirect
golang.org/x/sys v0.32.0 // indirect
golang.org/x/text v0.24.0 // indirect
golang.org/x/time v0.11.0 // indirect
golang.org/x/tools v0.30.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250428153025-10db94c68c34 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250428153025-10db94c68c34 // indirect
google.golang.org/grpc v1.72.0 // indirect
google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 // indirect
)
179 changes: 169 additions & 10 deletions go.sum

Large diffs are not rendered by default.

15 changes: 15 additions & 0 deletions internal/app/bigquery/domain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package bigquery

import "time"

type ContributionResponse struct {
ID string `bigquery:"id"`
Type string `bigquery:"type"`
ActorID int `bigquery:"actor_id"`
ActorLogin string `bigquery:"actor_login"`
RepoID int `bigquery:"repo_id"`
RepoName string `bigquery:"repo_name"`
RepoUrl string `bigquery:"repo_url"`
Payload string `bigquery:"payload"`
CreatedAt time.Time `bigquery:"created_at"`
}
87 changes: 87 additions & 0 deletions internal/app/bigquery/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package bigquery

import (
"context"
"fmt"
"log/slog"
"strings"
"time"

bq "cloud.google.com/go/bigquery"
"github.com/joshsoftware/code-curiosity-2025/internal/config"
"github.com/joshsoftware/code-curiosity-2025/internal/pkg/apperrors"
"github.com/joshsoftware/code-curiosity-2025/internal/repository"
)

type service struct {
bigqueryInstance config.Bigquery
userRepository repository.UserRepository
}

type Service interface {
FetchDailyContributions(ctx context.Context) (*bq.RowIterator, error)
}

func NewService(bigqueryInstance config.Bigquery, userRepository repository.UserRepository) Service {
return &service{
bigqueryInstance: bigqueryInstance,
userRepository: userRepository,
}
}

func (s *service) FetchDailyContributions(ctx context.Context) (*bq.RowIterator, error) {
YesterdayDate := time.Now().AddDate(0, 0, -1)
YesterdayYearMonthDay := YesterdayDate.Format("20060102")

usersNamesList, err := s.userRepository.GetAllUsersGithubUsernames(ctx, nil)
if err != nil {
slog.Error("error fetching users github usernames")
return nil, apperrors.ErrInternalServer
}

var quotedUsernamesList []string
for _, username := range usersNamesList {
quotedUsernamesList = append(quotedUsernamesList, fmt.Sprintf("'%s'", username))
}

githubUsernames := strings.Join(quotedUsernamesList, ",")
fetchDailyContributionsQuery := fmt.Sprintf(`
SELECT
id,
type,
public,
actor.id AS actor_id,
actor.login AS actor_login,
actor.gravatar_id AS actor_gravatar_id,
actor.url AS actor_url,
actor.avatar_url AS actor_avatar_url,
repo.id AS repo_id,
repo.name AS repo_name,
repo.url AS repo_url,
payload,
created_at,
other
FROM
githubarchive.day.%s
WHERE
type IN (
'IssuesEvent',
'PullRequestEvent',
'PullRequestReviewEvent',
'IssueCommentEvent',
'PullRequestReviewCommentEvent'
)
AND (
actor.login IN (%s)
)
`, YesterdayYearMonthDay, githubUsernames)

bigqueryQuery := s.bigqueryInstance.Client.Query(fetchDailyContributionsQuery)
contributionRows, err := bigqueryQuery.Read(ctx)
if err != nil {
slog.Error("error fetching contributions", "error", err)
return nil, err
}

return contributionRows, err
}
50 changes: 50 additions & 0 deletions internal/app/contribution/domain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package contribution

import "time"

type ContributionResponse struct {
ID string `bigquery:"id"`
Type string `bigquery:"type"`
ActorID int `bigquery:"actor_id"`
ActorLogin string `bigquery:"actor_login"`
RepoID int `bigquery:"repo_id"`
RepoName string `bigquery:"repo_name"`
RepoUrl string `bigquery:"repo_url"`
Payload string `bigquery:"payload"`
CreatedAt time.Time `bigquery:"created_at"`
}

type Repository struct {
Id int
GithubRepoId int
RepoName string
Description string
LanguagesUrl string
RepoUrl string
OwnerName string
UpdateDate time.Time
ContributorsUrl string
CreatedAt time.Time
UpdatedAt time.Time
}

type Contribution struct {
Id int
UserId int
RepositoryId int
ContributionScoreId int
ContributionType string
BalanceChange int
ContributedAt time.Time
CreatedAt time.Time
UpdatedAt time.Time
}

type ContributionScore struct {
Id int
AdminId int
ContributionType string
Score int
CreatedAt time.Time
UpdatedAt time.Time
}
52 changes: 52 additions & 0 deletions internal/app/contribution/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package contribution

import (
"log/slog"
"net/http"

"github.com/joshsoftware/code-curiosity-2025/internal/pkg/apperrors"
"github.com/joshsoftware/code-curiosity-2025/internal/pkg/response"
)

type handler struct {
contributionService Service
}

type Handler interface {
FetchUserLatestContributions(w http.ResponseWriter, r *http.Request)
FetchUsersAllContributions(w http.ResponseWriter, r *http.Request)
}

func NewHandler(contributionService Service) Handler {
return &handler{
contributionService: contributionService,
}
}

func (h *handler) FetchUserLatestContributions(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

err := h.contributionService.ProcessFetchedContributions(ctx)
if err != nil {
slog.Error("error fetching latest contributions", "error", err)
status, errorMessage := apperrors.MapError(err)
response.WriteJson(w, status, errorMessage, nil)
return
}

response.WriteJson(w, http.StatusOK, "contribution fetched successfully", nil)
}

func (h *handler) FetchUsersAllContributions(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()

usersAllContributions, err := h.contributionService.FetchUsersAllContributions(ctx)
if err != nil {
slog.Error("error fetching all contributions for user", "error", err)
status, errorMessage := apperrors.MapError(err)
response.WriteJson(w, status, errorMessage, nil)
return
}

response.WriteJson(w, http.StatusOK, "all contributions for user fetched successfully", usersAllContributions)
}
Loading