Skip to content
Merged
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
fcec602
chore: Add CI and lint workflows, configure golangci-lint, and improv…
eulixir Nov 13, 2025
092b8f6
style: apply lint
eulixir Nov 13, 2025
b7c323e
chore: Remove pull request triggers from CI, lint, and tests workflows
eulixir Nov 13, 2025
6b6b91b
chore: Add pull request triggers to CI workflow and remove lint and t…
eulixir Nov 13, 2025
108f3e5
chore: Remove pull request triggers from CI workflow
eulixir Nov 13, 2025
cab66ce
chore: Remove dependency download step from CI workflow
eulixir Nov 13, 2025
edace5c
chore: Update golangci-lint configuration and CI workflow to include …
eulixir Nov 13, 2025
c0bb275
chore: Remove unused linters from golangci-lint configuration
eulixir Nov 13, 2025
f8fd24b
chore: Update CI workflow to set working directory for all steps
eulixir Nov 13, 2025
7661b72
chore: Update golangci-lint configuration to version 2, enable tests,…
eulixir Nov 13, 2025
a296c40
chore: Refactor CI workflow to streamline golangci-lint step and remo…
eulixir Nov 13, 2025
a461e61
fix: ci file
eulixir Nov 13, 2025
59affbd
chore: Update CI workflow to use environment variable for Go version …
eulixir Nov 13, 2025
cc1f877
chore: Simplify CI workflow by consolidating build and lint steps, up…
eulixir Nov 13, 2025
e450467
chore: Update CI workflow to use '...' syntax for go mod download, en…
eulixir Nov 13, 2025
1c4c9cc
chore: Set default working directory for CI steps to streamline execu…
eulixir Nov 13, 2025
79e1f0e
fix: ci file
eulixir Nov 13, 2025
b433f60
chore: Remove redundant 'go mod download' step from CI workflow to st…
eulixir Nov 13, 2025
2143824
chore: Update golangci-lint configuration to version 2 and enable tes…
eulixir Nov 13, 2025
8951edd
fix: Update cache paths in CI workflow for golangci-lint to ensure co…
eulixir Nov 13, 2025
20e0a34
chore: Add Go module verification step to CI workflow and update gola…
eulixir Nov 13, 2025
8a0f7d3
chore: Refactor CI workflow to rename job, streamline steps, and ensu…
eulixir Nov 13, 2025
02b744d
chore: Initialize Go module and update .gitignore to exclude go.mod a…
eulixir Nov 13, 2025
da1ea39
chore: Simplify golangci-lint output configuration by consolidating f…
eulixir Nov 13, 2025
95b7cd4
chore: Update golangci-lint output configuration to use structured fo…
eulixir Nov 13, 2025
79baca0
chore: Add text format option to golangci-lint output configuration f…
eulixir Nov 14, 2025
dc78e08
chore: Remove test execution option from golangci-lint configuration …
eulixir Nov 14, 2025
90163da
chore: Update golangci-lint installation method in CI workflow to use…
eulixir Nov 14, 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
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
name: CI

on:
push:
branches: [main]
pull_request:

permissions:
contents: read

env:
GO_VERSION: 1.24.10

jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}

- name: Download Go modules
run: go mod tidy && go mod download

- name: Build
run: go build -v ./...

- name: Run tests
run: go test -v ./...

- name: Install golangci-lint
run: |
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v2.0.0

- name: Run golangci-lint
run: golangci-lint run ./...
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ go.work
go.work.sum

# Dependency directories (remove the comment below if you use Go modules)
/go.sum
/go.mod

# IDE/editor specific files
.vscode/
.idea/
Expand Down
80 changes: 80 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
version: 2

output:
formats:
text:
path: stdout
print-linter-name: true
print-issued-lines: true
linters:
default: all
disable:
- depguard
- err113
- exhaustive
- exhaustruct
- godot
- godox
- gomoddirectives
- ireturn
- lll
- musttag
- nlreturn
- nonamedreturns
- revive
- tagalign
- tagliatelle
- varnamelen
- wsl
settings:
gocritic:
enabled-tags:
- diagnostic
- experimental
- opinionated
- performance
- style
govet:
enable-all: true
misspell:
locale: US
staticcheck:
checks:
- all
exclusions:
generated: lax
rules:
- linters:
- errcheck
- gosec
- unparam
path: _test\.go
- linters:
- errcheck
path: _test\.go
text: Error return value of .((t|b|tb|f|g|gb)\.(Fatal|Fatalf|Skip|Skipf)|.*\.Errorf?|.*\.Fail(Now)?). is not checked
- linters:
- all
path: mocks/
- linters:
- all
path: docs/
paths:
- third_party$
- builtin$
- examples$
issues:
max-issues-per-linter: 0
max-same-issues: 0
formatters:
enable:
- gci
- gofmt
- gofumpt
- goimports
exclusions:
generated: lax
paths:
- third_party$
- builtin$
- examples$
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,7 @@ test:
@go test -timeout 30s -run ./...

coverage:
@go test ./... -coverprofile=coverage.out
@go test ./... -coverprofile=coverage.out

lint:
@golangci-lint run ./...
2 changes: 1 addition & 1 deletion domain/entities/helpers/decode_short_url.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ func Base62Decode(shortURL string, salt string) int64 {
if index == -1 {
return 0
}
decoded = decoded*62 + int64(index)
decoded = decoded*base62 + int64(index)
}
return decoded
}
18 changes: 11 additions & 7 deletions domain/entities/helpers/encode_url.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@ import (
"strings"
)

const base62Alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
const (
base62Alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
base62 = 62
minEncodedLen = 4
)

func Base62Encode(id int64, salt string) string {
alphabet := getShuffledAlphabet(salt)
Expand All @@ -16,14 +20,14 @@ func Base62Encode(id int64, salt string) string {
encoded = string(alphabet[0])
} else {
for num > 0 {
encoded = string(alphabet[num%62]) + encoded
num = num / 62
encoded = string(alphabet[num%base62]) + encoded
num /= base62
}
}
if len(encoded) < 4 {
encoded = strings.Repeat(string(alphabet[0]), 4-len(encoded)) + encoded
} else if len(encoded) > 4 {
encoded = encoded[:4]
if len(encoded) < minEncodedLen {
encoded = strings.Repeat(string(alphabet[0]), minEncodedLen-len(encoded)) + encoded
} else if len(encoded) > minEncodedLen {
encoded = encoded[:minEncodedLen]
}
return encoded
}
Expand Down
6 changes: 4 additions & 2 deletions domain/entities/helpers/encode_url_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package helpers
package helpers_test

import (
"testing"

"lnk/domain/entities/helpers"
)

func Test_Helper_Base62Encode(t *testing.T) {
Expand All @@ -24,7 +26,7 @@ func Test_Helper_Base62Encode(t *testing.T) {
}

for _, test := range tests {
got := Base62Encode(test.id, salt)
got := helpers.Base62Encode(test.id, salt)
if got != test.want {
t.Errorf("Base62Encode(%d, %s) = %s, want %s", test.id, salt, got, test.want)
}
Expand Down
9 changes: 5 additions & 4 deletions domain/entities/usecases/create_url.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package usecases

import (
"context"
"fmt"

"lnk/domain/entities"
"lnk/domain/entities/helpers"
)

func (uc *UseCase) CreateShortURL(longURL string) (string, error) {
id, err := uc.redis.Incr(uc.ctx, uc.counterKey)
func (uc *UseCase) CreateShortURL(ctx context.Context, longURL string) (string, error) {
id, err := uc.redis.Incr(ctx, uc.counterKey)
if err != nil {
return "", fmt.Errorf("failed to increment counter: %w", err)
}
Expand All @@ -20,9 +21,9 @@ func (uc *UseCase) CreateShortURL(longURL string) (string, error) {
LongURL: longURL,
}

err = uc.repository.CreateURL(url)
err = uc.repository.CreateURL(ctx, url)
if err != nil {
return "", err
return "", fmt.Errorf("failed to create URL in repository: %w", err)
}

return shortCode, nil
Expand Down
12 changes: 6 additions & 6 deletions domain/entities/usecases/create_url_test.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
package usecases
package usecases_test

import (
"context"

Check failure on line 5 in domain/entities/usecases/create_url_test.go

View workflow job for this annotation

GitHub Actions / build-and-test

File is not properly formatted (gci)
"lnk/domain/entities/usecases"
"lnk/extensions/gocqltesting"
"lnk/extensions/redis/mocks"
"lnk/gateways/gocql/repositories"
Expand All @@ -22,24 +23,23 @@
ctx := context.Background()
logger := zap.NewNop()

repository := repositories.NewRepository(ctx, logger, session)
repository := repositories.NewRepository(logger, session)

mockRedis := mocks.NewMockRedis(t)
mockRedis.On("Incr", mock.Anything, mock.Anything).Return(int64(1), nil)

params := NewUseCaseParams{
Ctx: ctx,
params := usecases.NewUseCaseParams{
Logger: logger,
Repository: repository,
Redis: mockRedis,
Salt: "test",
CounterKey: "test",
}

useCase := NewUseCase(params)
useCase := usecases.NewUseCase(params)

longURL := "https://www.google.com"
shortCode, err := useCase.CreateShortURL(longURL)
shortCode, err := useCase.CreateShortURL(ctx, longURL)
require.NoError(t, err)
require.NotEmpty(t, shortCode)
}
9 changes: 3 additions & 6 deletions domain/entities/usecases/get_long_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import (
"context"
"lnk/domain/entities/usecases"

Check failure on line 5 in domain/entities/usecases/get_long_test.go

View workflow job for this annotation

GitHub Actions / build-and-test

File is not properly formatted (gci)
"lnk/extensions/gocqltesting"
"lnk/extensions/redis/mocks"
"lnk/gateways/gocql/repositories"
Expand All @@ -23,13 +23,12 @@
ctx := context.Background()
logger := zap.NewNop()

repository := repositories.NewRepository(ctx, logger, session)
repository := repositories.NewRepository(logger, session)

mockRedis := mocks.NewMockRedis(t)
mockRedis.On("Incr", mock.Anything, mock.Anything).Return(int64(1), nil)

params := usecases.NewUseCaseParams{
Ctx: ctx,
Logger: logger,
Repository: repository,
Redis: mockRedis,
Expand All @@ -39,7 +38,7 @@

useCase := usecases.NewUseCase(params)

shortCode, err := useCase.CreateShortURL(url)
shortCode, err := useCase.CreateShortURL(ctx, url)
require.NoError(t, err)
require.NotEmpty(t, shortCode)

Expand All @@ -55,13 +54,11 @@
session, err := gocqltesting.NewDB(t, t.Name())
require.NoError(t, err)

ctx := context.Background()
logger := zap.NewNop()

repository := repositories.NewRepository(ctx, logger, session)
repository := repositories.NewRepository(logger, session)

params := usecases.NewUseCaseParams{
Ctx: ctx,
Logger: logger,
Repository: repository,
}
Expand Down
5 changes: 0 additions & 5 deletions domain/entities/usecases/usecase.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,16 @@
package usecases

import (
"context"
"errors"

Check failure on line 4 in domain/entities/usecases/usecase.go

View workflow job for this annotation

GitHub Actions / build-and-test

File is not properly formatted (gci)
"lnk/extensions/redis"
"lnk/gateways/gocql/repositories"

"go.uber.org/zap"
)

// ErrURLNotFound is returned when a URL is not found
var ErrURLNotFound = errors.New("URL not found")

type UseCase struct {
ctx context.Context
logger *zap.Logger
repository *repositories.Repository
redis redis.Redis
Expand All @@ -22,7 +19,6 @@
}

type NewUseCaseParams struct {
Ctx context.Context
Logger *zap.Logger
Repository *repositories.Repository
Redis redis.Redis
Expand All @@ -32,7 +28,6 @@

func NewUseCase(params NewUseCaseParams) *UseCase {
return &UseCase{
ctx: params.Ctx,
logger: params.Logger,
repository: params.Repository,
redis: params.Redis,
Expand Down
14 changes: 8 additions & 6 deletions extensions/config/config.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package config

import (
"lnk/extensions/logger"
"lnk/extensions/redis"
"lnk/gateways/gocql"
"fmt"

"github.com/joho/godotenv"
"github.com/kelseyhightower/envconfig"

Check failure on line 8 in extensions/config/config.go

View workflow job for this annotation

GitHub Actions / build-and-test

File is not properly formatted (gci)
"lnk/extensions/logger"
"lnk/extensions/redis"
"lnk/gateways/gocql"
)

type Config struct {
Expand All @@ -26,14 +28,14 @@
func LoadConfig() (*Config, error) {
err := godotenv.Load()
if err != nil {
return nil, err
return nil, fmt.Errorf("failed to load .env file: %w", err)
}
config := &Config{}
if err := envconfig.Process("", config); err != nil {
return nil, err
return nil, fmt.Errorf("failed to process app config: %w", err)
}
if err := envconfig.Process("", &config.Gocql); err != nil {
return nil, err
return nil, fmt.Errorf("failed to process gocql config: %w", err)
}
return config, nil
}
Loading
Loading