Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
09b409d
Add Facility API, demo data, stricter query validation and /api/v1 di…
juztas Jan 12, 2026
3e8b0b2
Make NamedObject reusable
juztas Jan 15, 2026
cf79917
Include operation_id for facility (similar to pull request #21)
juztas Jan 15, 2026
0d68a1c
simplified facility endpoint proposal
gabor-lbl Jan 15, 2026
ed6befa
Add Facility API, demo data, stricter query validation and /api/v1 di…
juztas Jan 12, 2026
28e5ba7
Remove /api/v1
juztas Jan 15, 2026
e8d256b
Refactor shared validators & models to fix import loading issues
juztas Jan 20, 2026
58b9ef8
Github Action to validate api
juztas Jan 20, 2026
bc55843
Add custom get extra function
juztas Jan 20, 2026
75a5cb6
Implement opentelemetry. Use UTC in demo adapter
juztas Jan 20, 2026
be30570
Rename dependencies to common
juztas Jan 20, 2026
6b85fbf
Do not swallow exceptions
juztas Jan 21, 2026
952aea0
Ensure that computed fields are included in output
juztas Jan 22, 2026
a1c4e53
Code base compliant with the official Spec
juztas Jan 23, 2026
6fb8e8b
Fully compliant with official spec
juztas Jan 23, 2026
53bc4c3
Enforce Py 3.14 as used release for everything
juztas Jan 23, 2026
846c1f8
Enable deepsource scanning
juztas Jan 23, 2026
2374d34
Enforce consistent package versions (pin major/minor version)
juztas Jan 25, 2026
2040b48
Update Facility endpoint (based on new Format discussed during the me…
juztas Feb 5, 2026
e85c266
Fix operation id: getJob, getJobs
juztas Feb 5, 2026
431da63
Remove resource_uri and event_uris
juztas Feb 5, 2026
8892724
Remove resource_uri and event_uris
juztas Feb 5, 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
9 changes: 9 additions & 0 deletions .deepsource.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
version = 1

[[analyzers]]
name = "python"
enabled = true

[analyzers.meta]
runtime_version = "3.x.x"
max_line_length = 200
132 changes: 132 additions & 0 deletions .github/workflows/api-validation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
name: API Validation with Schemathesis

on:
pull_request:
push:
branches: [ main ]

jobs:
schemathesis:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}

- name: Checkout schema validator repository
uses: actions/checkout@v4
with:
repository: doe-iri/iri-facility-api-docs
ref: main
path: schema-validator
token: ${{ secrets.GITHUB_TOKEN }}

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: "3.14"

- name: Install uv
run: pip install uv

- name: Build an image
run: docker build --platform=linux/amd64 -t iri-facility-api-base .

- name: Run Facility API container
run: |
docker run -d \
-p 8000:8000 \
--platform=linux/amd64 \
--name iri-facility-api-base \
-e IRI_API_ADAPTER_facility=app.demo_adapter.DemoAdapter \
-e IRI_API_ADAPTER_status=app.demo_adapter.DemoAdapter \
-e IRI_API_ADAPTER_account=app.demo_adapter.DemoAdapter \
-e IRI_API_ADAPTER_compute=app.demo_adapter.DemoAdapter \
-e IRI_API_ADAPTER_filesystem=app.demo_adapter.DemoAdapter \
-e IRI_API_ADAPTER_task=app.demo_adapter.DemoAdapter \
-e API_URL_ROOT=http://127.0.0.1:8000 \
-e IRI_API_TOKEN=12345 \
iri-facility-api-base

- name: Wait for API to be ready
run: |
for i in {1..60}; do
if curl -fs http://127.0.0.1:8000/openapi.json; then
echo "API ready"
exit 0
fi
sleep 2
done
echo "API did not start"
exit 1

- name: Create venv & install validator dependencies
run: |
uv venv
source .venv/bin/activate
uv pip install -r schema-validator/verification/requirements.txt

- name: Run Schemathesis validation (local spec)
id: schemathesis_local
env:
IRI_API_TOKEN: "12345" # This is dummy token for testing (mock adapter)
run: |
set +e
source .venv/bin/activate
python schema-validator/verification/api-validator.py \
--baseurl http://127.0.0.1:8000 \
--report-name schemathesis-local
echo "exitcode=$?" >> $GITHUB_OUTPUT

- name: Run Schemathesis validation (official spec)
id: schemathesis_official
env:
IRI_API_TOKEN: "12345"
run: |
set +e
source .venv/bin/activate
python schema-validator/verification/api-validator.py \
--baseurl http://localhost:8000 \
--schema-url https://raw.githubusercontent.com/doe-iri/iri-facility-api-docs/refs/heads/main/specification/openapi/openapi_iri_facility_api_v1.json \
--report-name schemathesis-official
echo "exitcode=$?" >> $GITHUB_OUTPUT

- name: Fail if any Schemathesis run failed
if: always()
run: |
if [ "${{ steps.schemathesis_local.outputs.exitcode }}" != "0" ] || \
[ "${{ steps.schemathesis_official.outputs.exitcode }}" != "0" ]; then
echo "One or more Schemathesis validations failed"
exit 1
else
echo "Both Schemathesis validations passed"
fi

- name: Upload Schemathesis report # This only works on git actions
if: always() && env.ACT != 'true'
uses: actions/upload-artifact@v4
with:
if-no-files-found: warn
name: schemathesis-report
path: |
schemathesis-local.html
schemathesis-local.xml
schemathesis-official.html
schemathesis-official.xml

- name: Save Schemathesis reports locally # This only works if run locally with act
if: always() && env.ACT == 'true'
run: |
mkdir -p artifacts
cp schemathesis-local.html schemathesis-local.xml artifacts/ || true
cp schemathesis-official.html schemathesis-official.xml artifacts/ || true

- name: Dump API logs
if: always()
run: docker logs iri-facility-api-base || true

- name: Stop container
if: always()
run: docker stop iri-facility-api-base || true
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM python:3
FROM python:3.14

RUN mkdir /app
COPY . /app
Expand Down
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
dev : .venv
@source ./.venv/bin/activate && \
IRI_API_ADAPTER_facility=app.demo_adapter.DemoAdapter \
IRI_API_ADAPTER_status=app.demo_adapter.DemoAdapter \
IRI_API_ADAPTER_account=app.demo_adapter.DemoAdapter \
IRI_API_ADAPTER_compute=app.demo_adapter.DemoAdapter \
IRI_API_ADAPTER_filesystem=app.demo_adapter.DemoAdapter \
IRI_API_ADAPTER_task=app.demo_adapter.DemoAdapter \
OPENTELEMETRY_ENABLED=true \
API_URL_ROOT='http://127.0.0.1:8000' fastapi dev


Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ If using docker (see next section), your dockerfile could extend this reference
- `API_URL_ROOT`: the base url when constructing links returned by the api (eg.: https://iri.myfacility.com)
- `API_PREFIX`: the path prefix where the api is hosted. Defaults to `/`. (eg.: `/api`)
- `API_URL`: the path to the api itself. Defaults to `api/v1`.
- `OPENTELEMETRY_ENABLED`: Enables OpenTelemetry. If enabled, the application will use OpenTelemetry SDKs and emit traces, metrics, and logs. Default to false
- `OTLP_ENDPOINT`: OpenTelemetry Protocol collector endpoint to export telemetry data. If empty or not set, telemetry data is logged locally to log file. Default: ""

Links to data, created by this api, will concatenate these values producing links, eg: `https://iri.myfacility.com/my_api_prefix/my_api_url/projects/123`

Expand Down
23 changes: 23 additions & 0 deletions VALIDATION.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# API Validation with Schemathesis

On every pull request or push to `main` branch, Github Actions run the following steps below that validates an IRI Facility API implementation against OpenAPI spec using Schemathesis.

1. Builds the Facility API Docker image from Dockerfile.
2. Runs the API container with demo adapter.
3. Waits for `/openapi.json` to become available on localhost:8000.
4. Runs Schemathesis validation twice:
- Against Facilities API’s OpenAPI spec. (http://localhost:8000/openapi.json)
- Against the official IRI Facility API OpenAPI spec. (https://github.com/doe-iri/iri-facility-api-docs/blob/main/specification/openapi/openapi_iri_facility_api_v1.json)
5. Fails the workflow if either validation fails.
6. Saves Schemathesis HTML/XML reports as artifacts (or saves it locally when run with `act`).
7. Dumps API container logs and do clean up to stop container.

## Running locally

```bash
act -W .github/workflows/api-validator.yml -s GITHUB_TOKEN=<GITHUB_TOKEN>
```

## Known issues

Python implementation not fully aligns with the official Specification. Running against Official Spec will continue to fail, until Spec or Py implementation is fixed.
5 changes: 5 additions & 0 deletions app/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,8 @@
API_URL_ROOT = os.environ.get("API_URL_ROOT", "https://api.iri.nersc.gov")
API_PREFIX = os.environ.get("API_PREFIX", "/")
API_URL = os.environ.get("API_URL", "api/v1")

OPENTELEMETRY_ENABLED = os.environ.get("OPENTELEMETRY_ENABLED", "false").lower() == "true"
OPENTELEMETRY_DEBUG = os.environ.get("OPENTELEMETRY_DEBUG", "false").lower() == "true"
OTLP_ENDPOINT = os.environ.get("OTLP_ENDPOINT", "")
OTEL_SAMPLE_RATE = float(os.environ.get("OTEL_SAMPLE_RATE", "0.2"))
Loading
Loading