Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
ae8afb2
test: set up test infrastructure for API query
arcangelo7 Mar 3, 2026
05da9af
build: drop Python 3.9, add 3.12 and 3.13 support
arcangelo7 Mar 3, 2026
27c2ef9
ci: deploy coverage report to GitHub Pages
arcangelo7 Mar 3, 2026
bc13639
ci: upload coverage artifact on all branches
arcangelo7 Mar 3, 2026
803a3a0
refactor(meta): remove dead code and deduplicate tests
arcangelo7 Mar 3, 2026
9a95624
Update coverage badge
actions-user Mar 3, 2026
de28603
test(index): add index API tests with real citation data
arcangelo7 Mar 4, 2026
f84f1b3
Update coverage badge
actions-user Mar 4, 2026
8333166
test(index): add DOI, PMID, and ISSN query tests
arcangelo7 Mar 4, 2026
b8201bd
Update coverage badge
actions-user Mar 4, 2026
ab7f405
fix(index): split UNION in venue OPTIONAL to fix Virtuoso SPARQL eval…
arcangelo7 Mar 4, 2026
a0188a2
refactor(index): remove dead code and replace dateutil.parser with st…
arcangelo7 Mar 4, 2026
5382434
Update coverage badge
actions-user Mar 4, 2026
8694d13
fix(index): align v1 SPARQL queries with v2 and add v1 tests
arcangelo7 Mar 4, 2026
40fefa0
Update coverage badge
actions-user Mar 4, 2026
90c4b01
refactor(index): extract shared logic into indexapi_common and remove…
arcangelo7 Mar 4, 2026
ececb5b
Update coverage badge
actions-user Mar 4, 2026
9bcacff
refactor(index)!: remove v1 metadata endpoint and associated dead code
arcangelo7 Mar 8, 2026
4828e64
Update coverage badge
actions-user Mar 8, 2026
b9a47c6
refactor(index): inline __get_omid_of into id2omids and drop dead bra…
arcangelo7 Mar 8, 2026
5578d43
Update coverage badge
actions-user Mar 8, 2026
22de01e
refactor: remove dead WebLogger module and fix lint warnings
arcangelo7 Mar 8, 2026
a08e1f0
Update coverage badge
actions-user Mar 8, 2026
51b87e6
merge: sync with main
arcangelo7 Apr 3, 2026
8fa1a85
Update coverage badge
actions-user Apr 3, 2026
edffb86
perf(index): consolidate shared logic
arcangelo7 Apr 3, 2026
859ca68
Update coverage badge
actions-user Apr 3, 2026
95b2be6
ci: drop python 3.13 support due to web-py incompatibility
arcangelo7 Apr 3, 2026
e34ad43
fix(deps): regenerate lockfile after dropping python 3.13
arcangelo7 Apr 3, 2026
92a433a
refactor(deps): replace vendored ramose with package dependency
arcangelo7 Apr 3, 2026
bd76ee7
Update coverage badge
actions-user Apr 3, 2026
2a9d328
fix(ci): surface pytest failures and upgrade six for python 3.12
arcangelo7 Apr 3, 2026
536cec1
fix(test): track pre-built indexes and surface pytest failures in CI
arcangelo7 Apr 3, 2026
6f69774
chore(test): remove obsolete db setup scripts
arcangelo7 Apr 3, 2026
b076b89
chore: bump version to 2.3.0
arcangelo7 Apr 3, 2026
a70a7c6
chore: bump version to 2.3.0
arcangelo7 Apr 3, 2026
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
38 changes: 19 additions & 19 deletions .github/workflows/docker-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ env:
jobs:
docker-build-push:
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Read version from pyproject.toml
id: get_version
run: |
Expand All @@ -32,76 +32,76 @@ jobs:
fi
echo "VERSION=$VERSION" >> $GITHUB_OUTPUT
echo "Found version: $VERSION"

- name: Check if image exists on DockerHub
id: check_image
env:
VERSION: ${{ steps.get_version.outputs.VERSION }}
run: |
echo "Checking if image exists: ${{ env.DOCKER_REGISTRY }}/${{ env.SERVIZIO_OC }}:${VERSION}"

# Query DockerHub API to check if tag exists
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
"https://hub.docker.com/v2/repositories/${{ env.DOCKER_REGISTRY }}/${{ env.SERVIZIO_OC }}/tags/${VERSION}/")

if [ "$HTTP_CODE" == "200" ]; then
echo "Image already exists on DockerHub"
echo "IMAGE_EXISTS=true" >> $GITHUB_OUTPUT
else
echo "Image not found on DockerHub, will build new one"
echo "IMAGE_EXISTS=false" >> $GITHUB_OUTPUT
fi

- name: Set up Docker Buildx
if: steps.check_image.outputs.IMAGE_EXISTS == 'false'
uses: docker/setup-buildx-action@v3
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0

- name: Login to DockerHub
if: steps.check_image.outputs.IMAGE_EXISTS == 'false'
uses: docker/login-action@v3
uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build and push Docker image
if: steps.check_image.outputs.IMAGE_EXISTS == 'false'
env:
VERSION: ${{ steps.get_version.outputs.VERSION }}
run: |
echo "Building image: ${{ env.DOCKER_REGISTRY }}/${{ env.SERVIZIO_OC }}:${VERSION}"

# Build image with no cache
docker build --no-cache -t ${{ env.DOCKER_REGISTRY }}/${{ env.SERVIZIO_OC }}:${VERSION} .
sleep 1

# Tag image
docker tag ${{ env.DOCKER_REGISTRY }}/${{ env.SERVIZIO_OC }}:${VERSION} ${{ env.DOCKER_REGISTRY }}/${{ env.SERVIZIO_OC }}:${VERSION}
sleep 1

# Push to registry
echo "Pushing image to DockerHub..."
docker push ${{ env.DOCKER_REGISTRY }}/${{ env.SERVIZIO_OC }}:${VERSION}
sleep 1

# Check result
if [ $? == 0 ]; then
echo "ALL DONE !"
else
echo "NO NO NOOOOOOO !"
exit 1
fi

- name: Build summary
run: |
VERSION="${{ steps.get_version.outputs.VERSION }}"
IMAGE_EXISTS="${{ steps.check_image.outputs.IMAGE_EXISTS }}"

echo "Build Summary:"
echo "Version: ${VERSION}"
echo "Image: ${{ env.DOCKER_REGISTRY }}/${{ env.SERVIZIO_OC }}:${VERSION}"

if [ "$IMAGE_EXISTS" == "true" ]; then
echo "Status: Image already exists, skipped build"
else
echo "Status: New image built and pushed successfully"
fi
fi
72 changes: 47 additions & 25 deletions .github/workflows/run_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,45 +21,38 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.9", "3.10", "3.11"]
python-version: ["3.10", "3.11", "3.12"]

steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Install uv
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
with:
enable-cache: true
python-version: ${{ matrix.python-version }}

- name: Install uv
uses: astral-sh/setup-uv@v6

- name: Install dependencies
run: uv sync --dev

- name: Start test database
run: ./test/start_test_db.sh
- name: Install dependencies
run: uv sync --dev --locked

- name: Run tests with coverage
run: |
echo "COVERAGE=$(uv run pytest --cov=src --cov-report=term-missing --cov-report=html | tee /dev/stderr | grep TOTAL | awk '{print $4}')" >> $GITHUB_ENV

- name: Stop test database
if: always()
run: ./test/stop_test_db.sh
set -o pipefail
uv run pytest | tee pytest-output.txt
echo "COVERAGE=$(grep TOTAL pytest-output.txt | awk '{print $4}')" >> $GITHUB_ENV

- name: Upload coverage artifact
if: matrix.python-version == '3.10'
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
with:
name: coverage-report
path: ${{ env.COVERAGE_REPORT_PATH }}

- name: Generate coverage badge
if: matrix.python-version == '3.10'
run: |
COVERAGE_NUM=$(echo ${{ env.COVERAGE }} | sed 's/%//')

if (( $(echo "$COVERAGE_NUM >= 90" | bc -l) )); then
COLOR="green"
elif (( $(echo "$COVERAGE_NUM >= 75" | bc -l) )); then
Expand All @@ -69,9 +62,9 @@ jobs:
else
COLOR="red"
fi

echo "BADGE_COLOR=$COLOR" >> $GITHUB_ENV

- name: Create coverage badge
if: matrix.python-version == '3.10'
uses: emibcn/badge-action@v2.0.3
Expand All @@ -80,12 +73,41 @@ jobs:
status: '${{ env.COVERAGE }}'
color: '${{ env.BADGE_COLOR }}'
path: 'test/coverage-badge.svg'

- name: Commit coverage badge
if: matrix.python-version == '3.10' && github.event_name == 'push'
run: |
git config --local user.email "action@github.com"
git config --local user.name "GitHub Action"
git add test/coverage-badge.svg
git diff --staged --quiet || git commit -m "Update coverage badge"
git push
git push

deploy-coverage:
needs: CheckCoverage
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Download coverage artifact
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
name: coverage-report
path: site/coverage

- name: Setup Pages
uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0

- name: Upload Pages artifact
uses: actions/upload-pages-artifact@7b1f4a764d45c48632c6b24a0339c27f5614fb0b # v4.0.0
with:
path: site

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0
14 changes: 6 additions & 8 deletions .github/workflows/smoketest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,16 @@ jobs:

steps:
- name: Checkout code
uses: actions/checkout@v4
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Set up Python 3.11
uses: actions/setup-python@v5
- name: Install uv
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57 # v8.0.0
with:
enable-cache: true
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@v6

- name: Install dependencies
run: uv sync --frozen --no-dev
run: uv sync --locked --no-dev

- name: Start Gunicorn
run: |
Expand Down Expand Up @@ -133,4 +131,4 @@ jobs:
- name: Stop Gunicorn
if: always()
run: |
pkill -f gunicorn || true
pkill -f gunicorn || true
7 changes: 5 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,12 @@ var/

# Tests
test/virtuoso-test-data/
test/virtuoso-meta-data/database/virtuoso.lck
test/virtuoso-meta-data/database/virtuoso.log
test/virtuoso-meta-data/index_entities.txt
test/qlever-index-data/oc-index-test.server-log.txt
.coverage


# uv
.venv/
.python-version
.python-version
33 changes: 5 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

[<img src="https://img.shields.io/badge/powered%20by-OpenCitations-%239931FC?labelColor=2D22DE" />](http://opencitations.net)
[![Run tests](https://github.com/opencitations/oc_api/actions/workflows/run_tests.yml/badge.svg?branch=main)](https://github.com/opencitations/oc_api/actions/workflows/run_tests.yml)
![Coverage](test/coverage-badge.svg)
[![Coverage](test/coverage-badge.svg)](https://opencitations.github.io/oc_api/coverage/)

This repository contains the API service for OpenCitations, allowing users to interact with the OpenCitations datasets through RESTful endpoints.

Expand Down Expand Up @@ -140,37 +140,14 @@ You can customize the Gunicorn server configuration by modifying the `gunicorn.c

### Running Tests Locally

To run the API tests locally, you'll need to have the test environment set up properly. The tests require a Virtuoso database to be running.
The tests require Docker. Pytest fixtures in `test/conftest.py` automatically start and stop the QLever and Virtuoso containers.

#### Prerequisites

1. Install dependencies using uv:
```bash
uv sync --dev
```

2. Start the test database:
1. Install dependencies:
```bash
./test/start_test_db.sh
uv sync --dev
```

#### Running the Tests

Once the test database is running, you can execute the tests with coverage:
2. Run the tests:
```bash
# Run tests with coverage report
uv run pytest --cov=src --cov-report=term-missing --cov-report=html

# Run only specific test files
uv run pytest test/test_metaapi.py

# Run tests with verbose output
uv run pytest -v
```

#### Stopping the Test Database

After running the tests, stop the test database:
```bash
./test/stop_test_db.sh
```
Loading
Loading