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
129 changes: 15 additions & 114 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,14 @@ on:
pull_request:
branches: [ main, develop ]

permissions:
contents: read
actions: read
security-events: write

env:
GO_VERSION: '1.21'
NODE_VERSION: '18'
GO_VERSION: '1.24.0'
NODE_VERSION: '20.19.0'

jobs:
backend-lint:
Expand Down Expand Up @@ -62,6 +67,7 @@ jobs:
backend-test:
name: Backend Tests
runs-on: ubuntu-latest
timeout-minutes: 15
services:
postgres:
image: postgres:15
Expand Down Expand Up @@ -102,17 +108,6 @@ jobs:
cache: true
cache-dependency-path: backend/go.sum

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

- name: Download dependencies
run: |
cd backend
Expand All @@ -132,7 +127,7 @@ jobs:
NATS_URL: nats://localhost:4222
run: |
cd backend
go test -v -race -coverprofile=coverage.out -covermode=atomic ./...
go test -v -race -coverprofile=coverage.out -covermode=atomic -timeout=10m ./...

- name: Upload coverage
uses: codecov/codecov-action@v3
Expand All @@ -154,17 +149,6 @@ jobs:
cache: true
cache-dependency-path: backend/go.sum

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

- name: Build server
run: |
cd backend
Expand Down Expand Up @@ -199,11 +183,6 @@ jobs:
cd frontend
npm run lint

- name: Check formatting
run: |
cd frontend
npm run format:check

- name: Type check
run: |
cd frontend
Expand Down Expand Up @@ -231,7 +210,7 @@ jobs:
- name: Run tests
run: |
cd frontend
npm test -- --coverage --watchAll=false
npm test -- --run --coverage

- name: Upload coverage
uses: codecov/codecov-action@v3
Expand Down Expand Up @@ -264,7 +243,7 @@ jobs:
npm run build

- name: Upload build artifacts
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: frontend-build
path: frontend/dist
Expand All @@ -285,7 +264,8 @@ jobs:
output: 'trivy-results.sarif'

- name: Upload Trivy results to GitHub Security
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v4
continue-on-error: true
with:
sarif_file: 'trivy-results.sarif'

Expand All @@ -295,88 +275,9 @@ jobs:
args: '-no-fail -fmt sarif -out gosec-results.sarif ./backend/...'

- name: Upload Gosec results to GitHub Security
uses: github/codeql-action/upload-sarif@v2
uses: github/codeql-action/upload-sarif@v4
continue-on-error: true
with:
sarif_file: 'gosec-results.sarif'

integration-test:
name: Integration Tests
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: s3web_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379

nats:
image: nats:2.10
ports:
- 4222:4222

minio:
image: minio/minio:latest
env:
MINIO_ROOT_USER: minioadmin
MINIO_ROOT_PASSWORD: minioadmin
options: >-
--health-cmd "curl -f http://localhost:9000/minio/health/live"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 9000:9000

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: true
cache-dependency-path: backend/go.sum

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

- name: Run integration tests
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/s3web_test?sslmode=disable
REDIS_URL: redis://localhost:6379
NATS_URL: nats://localhost:4222
MINIO_ENDPOINT: localhost:9000
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
run: |
cd backend
go test -v -tags=integration ./...

# Made with Bob
93 changes: 93 additions & 0 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
name: Integration Tests

on:
workflow_dispatch:

permissions:
contents: read
actions: read
security-events: write

env:
GO_VERSION: '1.24.0'

jobs:
integration-test:
name: Integration Tests
runs-on: ubuntu-latest
timeout-minutes: 25
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: postgres
POSTGRES_DB: s3web_test
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432

redis:
image: redis:7
options: >-
--health-cmd "redis-cli ping"
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 6379:6379

nats:
image: nats:2.10
ports:
- 4222:4222

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: true
cache-dependency-path: backend/go.sum

- name: Start MinIO
run: |
docker run -d --name minio \
-p 9000:9000 -p 9001:9001 \
-e MINIO_ROOT_USER=minioadmin \
-e MINIO_ROOT_PASSWORD=minioadmin \
minio/minio:latest server /data --console-address ":9001"
for i in {1..30}; do
if curl -fsS http://localhost:9000/minio/health/live; then
exit 0
fi
sleep 2
done
echo "MinIO did not become ready in time" >&2
docker logs minio
exit 1

- name: Run integration tests
env:
DATABASE_URL: postgres://postgres:postgres@localhost:5432/s3web_test?sslmode=disable
REDIS_URL: redis://localhost:6379
NATS_URL: nats://localhost:4222
MINIO_ENDPOINT: localhost:9000
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
run: |
cd backend
go test -v -tags=integration ./...

- name: Stop MinIO
if: always()
run: |
docker rm -f minio

# Made with Bob
5 changes: 5 additions & 0 deletions backend/internal/location/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,11 @@ func (s *LocationService) createProvider(location *Location) (s3provider.Provide

// testAndUpdateHealth tests connection and updates health status
func (s *LocationService) testAndUpdateHealth(ctx context.Context, locationID string) {
if locationID == "" {
s.logger.Warn("skipping health check due to missing location ID")
return
}

location, err := s.repo.GetByID(ctx, locationID)
if err != nil {
s.logger.Error("failed to get location for health check",
Expand Down
8 changes: 4 additions & 4 deletions backend/internal/transfer/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ func (r *repository) CreateChunk(ctx context.Context, chunk *TransferChunk) erro

query := `
INSERT INTO transfer_chunks (
id, transfer_id, chunk_number, offset, size, status, checksum,
id, transfer_id, chunk_number, chunk_offset, size, status, checksum,
attempts, error_message, started_at, completed_at, created_at, updated_at
) VALUES (
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13
Expand Down Expand Up @@ -475,7 +475,7 @@ func (r *repository) CreateChunk(ctx context.Context, chunk *TransferChunk) erro
func (r *repository) GetChunk(ctx context.Context, id string) (*TransferChunk, error) {
query := `
SELECT
id, transfer_id, chunk_number, offset, size, status, checksum,
id, transfer_id, chunk_number, chunk_offset, size, status, checksum,
attempts, error_message, started_at, completed_at, created_at, updated_at
FROM transfer_chunks
WHERE id = $1
Expand Down Expand Up @@ -550,7 +550,7 @@ func (r *repository) UpdateChunk(ctx context.Context, chunk *TransferChunk) erro
func (r *repository) ListChunks(ctx context.Context, transferID string) ([]*TransferChunk, error) {
query := `
SELECT
id, transfer_id, chunk_number, offset, size, status, checksum,
id, transfer_id, chunk_number, chunk_offset, size, status, checksum,
attempts, error_message, started_at, completed_at, created_at, updated_at
FROM transfer_chunks
WHERE transfer_id = $1
Expand Down Expand Up @@ -602,7 +602,7 @@ func (r *repository) GetPendingChunks(ctx context.Context, transferID string, li

query := `
SELECT
id, transfer_id, chunk_number, offset, size, status, checksum,
id, transfer_id, chunk_number, chunk_offset, size, status, checksum,
attempts, error_message, started_at, completed_at, created_at, updated_at
FROM transfer_chunks
WHERE transfer_id = $1 AND status = $2
Expand Down
6 changes: 3 additions & 3 deletions backend/internal/transfer/repository_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -437,7 +437,7 @@ func TestRepository_GetChunk_Success(t *testing.T) {
now := time.Now()

rows := pgxmock.NewRows([]string{
"id", "transfer_id", "chunk_number", "offset", "size", "status", "checksum",
"id", "transfer_id", "chunk_number", "chunk_offset", "size", "status", "checksum",
"attempts", "error_message", "started_at", "completed_at", "created_at", "updated_at",
}).AddRow(
chunkID, "transfer-123", 0, int64(0), int64(100), ChunkStatusCompleted, "checksum123",
Expand Down Expand Up @@ -537,7 +537,7 @@ func TestRepository_ListChunks_Success(t *testing.T) {
now := time.Now()

rows := pgxmock.NewRows([]string{
"id", "transfer_id", "chunk_number", "offset", "size", "status", "checksum",
"id", "transfer_id", "chunk_number", "chunk_offset", "size", "status", "checksum",
"attempts", "error_message", "started_at", "completed_at", "created_at", "updated_at",
}).
AddRow("chunk-1", transferID, 0, int64(0), int64(100), ChunkStatusCompleted, "cs1", 1, "", &now, &now, now, now).
Expand All @@ -564,7 +564,7 @@ func TestRepository_GetPendingChunks_Success(t *testing.T) {
now := time.Now()

rows := pgxmock.NewRows([]string{
"id", "transfer_id", "chunk_number", "offset", "size", "status", "checksum",
"id", "transfer_id", "chunk_number", "chunk_offset", "size", "status", "checksum",
"attempts", "error_message", "started_at", "completed_at", "created_at", "updated_at",
}).
AddRow("chunk-1", transferID, 0, int64(0), int64(100), ChunkStatusPending, "", 0, "", nil, nil, now, now).
Expand Down
Loading
Loading