Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.sh text eol=lf
56 changes: 0 additions & 56 deletions .github/workflows/build_and_test.yml

This file was deleted.

41 changes: 41 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Deploy code

on:
push:
branches:
- develop
- master

jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Generate Semantic Version
id: version
uses: PaulHatch/semantic-version@v4
with:
tag_prefix: "v"
major_pattern: "feat!"
minor_pattern: "feat"
format: "${major}.${minor}.${patch}"

- name: Log version
run: echo "Version is ${{ steps.version.outputs.version }}"

- name: Set VERSION environment variable
run: echo "VERSION=${{ steps.version.outputs.version }}" >> $GITHUB_ENV

- name: Log in to DockerHub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build Docker image
run: docker compose build

- name: Push Docker image
run: docker compose push
90 changes: 90 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: Test on develop

on:
pull_request:
branches:
- develop

paths:
- 'src/**'
- 'compose.yml'
- '*.sh'

jobs:
unit-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24

- name: Cache Go modules
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-

- name: Write private key from secret
run: printf "%s" "${{ secrets.PRIVATE_KEY }}" > keys/private_key.key

- name: Write public key from secret
run: printf "%s" "${{ secrets.PUBLIC_KEY }}" > keys/public_key.pem

- name: Set key permissions
run: chmod 400 keys/private_key.key

- name: Run test script
run: |
chmod +x ./run-tests.sh
./run-tests.sh

- name: Upload test results as artifacts
uses: actions/upload-artifact@v4
with:
name: unit-test-results
path: |
src/test-out/

integration-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.24

- name: Cache Go modules
uses: actions/cache@v4
with:
path: |
~/go/pkg/mod
~/.cache/go-build
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-

- name: Write private key from secret
run: printf "%s" "${{ secrets.PRIVATE_KEY }}" > keys/private_key.key

- name: Write public key from secret
run: printf "%s" "${{ secrets.PUBLIC_KEY }}" > keys/public_key.pem

- name: Set key permissions
run: chmod 400 keys/private_key.key

- name: Run tests
run: docker compose -f compose.integration.yml up --build --abort-on-container-exit --exit-code-from test-runner

- name: Cleanup
run: docker compose -f compose.integration.yml down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
test-out/

# If you prefer the allow list template instead of the deny list, see community template:
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
#
Expand Down
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ Run tests locally:
./run-tests.sh
```

Run integration tests:

```
docker compose -f compose.integration.yml up --build --abort-on-container-exit --exit-code-from test-runner
docker compose -f compose.integration.yml down
```


# Contributing guidelines

1) Follow [Feature Branch Workflow](https://www.atlassian.com/git/tutorials/comparing-workflows/feature-branch-workflow)
Expand Down
60 changes: 60 additions & 0 deletions compose.integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
services:
test-runner:
build:
context: ./src
dockerfile: test.Dockerfile
depends_on:
db:
condition: service_healthy
user-service:
condition: service_healthy
volumes:
- go-mod-cache:/go/pkg/mod

user-service:
build:
context: ./src
dockerfile: Dockerfile
image: user-service-test
ports:
- "0:8080"
environment:
DB_HOST: db
DB_PORT: 5432
DB_NAME: bookem_userdb_test
DB_USER: bookem_userdb_user
DB_PASSWORD: testpass
JWT_PRIVATE_KEY_PATH: /app/keys/private_key.key
JWT_PUBLIC_KEY_PATH: /app/keys/public_key.pem
ENABLE_TEST_MODE: "true"
depends_on:
db:
condition: service_healthy
volumes:
- ./keys/private_key.key:/app/keys/private_key.key:ro
- ./keys/public_key.pem:/app/keys/public_key.pem:ro
healthcheck:
test: ["CMD-SHELL", "wget --spider --tries=1 --no-verbose http://user-service:8080/healthz || exit 1"]
interval: 10s
timeout: 5s
retries: 5

db:
image: postgres:15-alpine
environment:
POSTGRES_DB: bookem_userdb_test
POSTGRES_USER: bookem_userdb_user
POSTGRES_PASSWORD: testpass
ports:
- "0:5432"
volumes:
- type: tmpfs
target: /var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 10s
timeout: 5s
retries: 5

volumes:
go-mod-cache:
18 changes: 13 additions & 5 deletions compose.yml
Comment thread
Vasilijez marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
services:
user-service:
container_name: bookem-user-service
image: magley/bookem-user-service
image: magley/bookem-user-service:${VERSION:-localDevDefault}
restart: always
build: ./src
ports:
Expand All @@ -15,15 +14,20 @@ services:
JWT_PRIVATE_KEY_PATH: /app/keys/private_key.key
JWT_PUBLIC_KEY_PATH: /app/keys/public_key.pem
depends_on:
- db
db:
condition: service_healthy
volumes:
- ./keys/private_key.key:/app/keys/private_key.key:ro
- ./keys/public_key.pem:/app/keys/public_key.pem:ro
healthcheck:
test: ["CMD-SHELL", "wget --spider --tries=1 --no-verbose http://user-service:8080/healthz || exit 1"]
interval: 10s
timeout: 5s
retries: 5

db:
image: postgres:alpine
restart: always
container_name: bookem-user-service-db
environment:
POSTGRES_DB: bookem_userdb_db
POSTGRES_USER: bookem_userdb_user
Expand All @@ -34,11 +38,15 @@ services:
target: /var/lib/postgresql/data
ports:
- "8501:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s
timeout: 3s
retries: 5

adminer:
image: adminer:4.8.0-standalone
restart: always
container_name: bookem-user-service-adminer
ports:
- "8502:8080"

Expand Down
18 changes: 11 additions & 7 deletions run-tests.sh
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
#!/bin/bash

cd src
mkdir test-out

set -euo pipefail

echo "Running tests..."
echo "Running unit tests..."

cd src
go test -coverprofile=coverage.out -coverpkg=./... ./...
go tool cover -func=coverage.out
go test -v -coverprofile=./test-out/coverage-unit.out -coverpkg=./... ./test/unit/...

echo "Linting..."
echo "Building coverage report..."

go tool cover -func=./test-out/coverage-unit.out
go tool cover -html=./test-out/coverage-unit.out -o ./test-out/coverage-unit.html

go vet ./...
echo "Linting..."

echo "All checks passed!"
go vet ./...
2 changes: 1 addition & 1 deletion src/api/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,5 @@ func (h *Handler) login(ctx *gin.Context) {
return
}

ctx.JSON(http.StatusOK, gin.H{"jwt": jwt})
ctx.JSON(http.StatusOK, domain.JWTDTO{Jwt: jwt})
}
2 changes: 2 additions & 0 deletions src/api/middleware/error_middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ func mapErrorToStatus(err error) int {
return http.StatusBadRequest
case errors.Is(err, domain.ErrUsernameExists), errors.Is(err, domain.ErrEmailExists):
return http.StatusConflict
case errors.Is(err, domain.ErrLoginFailed):
return http.StatusBadRequest
default:
return http.StatusInternalServerError
}
Expand Down
4 changes: 4 additions & 0 deletions src/domain/dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,7 @@ type LoginDTO struct {
UsernameOrEmail string `json:"usernameOrEmail" binding:"required"`
Password string `json:"password" binding:"required"`
}

type JWTDTO struct {
Jwt string `json:"jwt"`
}
Loading
Loading