Skip to content
Draft
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
100 changes: 100 additions & 0 deletions .github/workflows/test-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
name: Test Build

on:
pull_request:
branches:
- main
- "release/**"

permissions:
contents: read
checks: write
pull-requests: write
packages: write

jobs:
build-and-test:
runs-on: ubuntu-latest
outputs:
pr_number: ${{ github.event.pull_request.number }}
short_sha: ${{ steps.short_sha.outputs.short_sha }}
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Get Short SHA
id: short_sha
run: echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT

- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: "21"
distribution: "corretto"
cache: "maven"

- name: Cache Maven packages
uses: actions/cache@v4
with:
path: |
~/.m2/repository
!~/.m2/repository/org/devgateway/tcdi
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
restore-keys: |
${{ runner.os }}-maven-

- name: Build and Test
run: mvn -B verify -Dcheckstyle.skip=true -Dtest='!**/DatasetClientTest' --file pom.xml

- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
if: always()
with:
files: |
**/target/surefire-reports/*.xml

- name: Upload Build Artifacts
uses: actions/upload-artifact@v4
with:
name: build-artifacts
path: |
**/target/*.jar
retention-days: 7

build-and-push-docker-image:
needs: build-and-test
runs-on: ubuntu-latest
steps:
- name: Checkout Repository
uses: actions/checkout@v4

- name: Set up QEMU
uses: docker/setup-qemu-action@v3
with:
platforms: linux/amd64,linux/arm64

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2

- name: Login to Docker Registry
uses: docker/login-action@v3
with:
registry: ${{ vars.DOCKER_REGISTRY }}
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}

- name: Build and push Docker image
uses: docker/build-push-action@v6
with:
platforms: linux/amd64,linux/arm64
cache-from: type=gha, scope=data-viz-admin
cache-to: type=gha, scope=data-viz-admin
context: .
push: true
build-args: |
VERSION=pr-${{ needs.build-and-test.outputs.pr_number }}
TAG=${{ needs.build-and-test.outputs.short_sha }}
GIT_BRANCH=${{ github.head_ref }}
tags: |
${{ vars.DOCKER_REGISTRY }}/data-viz-admin:pr-${{ needs.build-and-test.outputs.pr_number }}
${{ vars.DOCKER_REGISTRY }}/data-viz-admin:pr-${{ needs.build-and-test.outputs.pr_number }}-${{ needs.build-and-test.outputs.short_sha }}
131 changes: 131 additions & 0 deletions docker-compose-test.README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
# Docker Compose Test Setup

This docker-compose file provides a local testing environment for the TCDI Admin application with all required dependencies.

## Services

| Service | Port | Description |
|---------|------|-------------|
| postgres | 5432 | PostgreSQL database for the admin application |
| postgres-interference | 5433 | PostgreSQL database for the interference service |
| eureka | 8761 | Netflix Eureka service registry |
| mock-interference-service | 8090 | MockServer simulating the interference service API |

## Prerequisites

- Docker and Docker Compose installed
- The admin application built (`mvn install -Dcheckstyle.skip=true -DskipTests`)

## Quick Start

1. **Start the infrastructure:**
```bash
docker-compose -f docker-compose-test.yml up -d
```

2. **Wait for services to be healthy:**
```bash
docker-compose -f docker-compose-test.yml ps
```

3. **Run the admin application:**
```bash
mvn spring-boot:run -pl forms -Dcheckstyle.skip=true \
-Dspring-boot.run.profiles=dev \
-Dspring-boot.run.arguments="--eureka.client.serviceUrl.defaultZone=http://localhost:8761/eureka/"
```

4. **Access the application:**
- Admin UI: http://localhost:8080
- Eureka Dashboard: http://localhost:8761

## Testing CSV Dataset Upload

### Scenario: Test normal upload flow

1. Navigate to the CSV Datasets section in the admin UI
2. Create a new dataset for the "INTERFERENCE" service
3. Upload the test CSV file: `forms/src/test/resources/world_industry_interference_2025.csv`
4. Click "Save and Publish"
5. The mock service will return a successful response

### Scenario: Test stuck publishing detection

1. Create and publish a dataset
2. The job checker runs every minute (`@Scheduled(cron = "0 * * * * *")`)
3. If a job is in PUBLISHING state for longer than `dataset.publishing.timeout.minutes` (default: 30), it will be marked as ERROR_IN_PUBLISHING

### Scenario: Test Cancel Publishing button

1. Create a dataset and start publishing
2. While in PUBLISHING state, a "Cancel Publishing" button should appear
3. Click the button to cancel and mark as ERROR_IN_PUBLISHING
4. This allows retrying the upload after fixing issues

## Configuration

### Publishing Timeout

Configure the timeout for stuck jobs in `application.properties` or via environment variable:

```properties
dataset.publishing.timeout.minutes=30
```

### Mock Service Responses

The mock interference service (MockServer) is configured via `mockserver-init.json`. It simulates:

- `GET /health` - Health check endpoint
- `POST /datasets` - Dataset upload (returns PROCESSING status)
- `GET /jobs/code/tcdi-*` - Job status check (returns COMPLETED)
- `DELETE /datasets/tcdi-*` - Dataset deletion
- `GET /template/download` - CSV template download
- `GET /dimensions` - Get available dimensions
- `GET /measures` - Get available measures

## Cleanup

Stop and remove all containers and volumes:

```bash
docker-compose -f docker-compose-test.yml down -v
```

## Troubleshooting

### Database connection issues

Check if PostgreSQL is healthy:
```bash
docker-compose -f docker-compose-test.yml logs postgres
```

### Eureka connection issues

Ensure Eureka is running and accessible:
```bash
curl http://localhost:8761/actuator/health
```

### Mock service not responding

Check MockServer logs:
```bash
docker-compose -f docker-compose-test.yml logs mock-interference-service
```

## Running Unit Tests

The `DatasetClientServiceTest` class contains unit tests for the new functionality:

```bash
mvn test -pl forms -Dtest=DatasetClientServiceTest -Dcheckstyle.skip=true
```

Tests cover:
- Cancel publishing functionality
- Status transitions (PUBLISHING → PUBLISHED, UNPUBLISHING → DRAFT)
- Error status transitions (PUBLISHING → ERROR_IN_PUBLISHING, UNPUBLISHING → ERROR_IN_UNPUBLISHING)
- Timeout detection for stuck jobs
- Dataset saving based on type (CSV vs Tetsim)
98 changes: 98 additions & 0 deletions docker-compose-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
services:
# PostgreSQL database for the admin application
postgres:
image: postgis/postgis:15-3.3-alpine
restart: unless-stopped
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: admin
POSTGRES_USER: postgres
POSTGRES_DB: tcdi_admin
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d tcdi_admin"]
interval: 10s
timeout: 5s
retries: 5
networks:
- tcdi-network

# PostgreSQL database for the interference service (remote service)
postgres-interference:
image: postgis/postgis:15-3.3-alpine
restart: unless-stopped
ports:
- "5433:5432"
volumes:
- postgres_interference_data:/var/lib/postgresql/data
environment:
POSTGRES_PASSWORD: admin
POSTGRES_USER: postgres
POSTGRES_DB: interference
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d interference"]
interval: 10s
timeout: 5s
retries: 5
networks:
- tcdi-network

# Eureka service registry
eureka:
image: steeltoeoss/eureka-server:latest
restart: unless-stopped
ports:
- "8761:8761"
environment:
EUREKA_SERVER_ENABLE_SELF_PRESERVATION: "false"
healthcheck:
test:
[
"CMD",
"wget",
"-q",
"--spider",
"http://localhost:8761/actuator/health",
]
interval: 10s
timeout: 5s
retries: 10
networks:
- tcdi-network

# Mock interference service for testing CSV uploads
# This is a simple mock that simulates the remote interference service API
mock-interference-service:
image: mockserver/mockserver:5.15.0
restart: unless-stopped
ports:
- "8090:1080"
environment:
MOCKSERVER_INITIALIZATION_JSON_PATH: /config/mockserver-init.json
MOCKSERVER_LOG_LEVEL: INFO
volumes:
- ./mockserver-init.json:/config/mockserver-init.json:ro
healthcheck:
test:
[
"CMD",
"wget",
"-q",
"--spider",
"http://localhost:1080/mockserver/status",
]
interval: 10s
timeout: 5s
retries: 5
networks:
- tcdi-network

networks:
tcdi-network:
driver: bridge

volumes:
postgres_data:
postgres_interference_data:
Loading