diff --git a/.github/workflows/schema-ci.yml b/.github/workflows/schema-ci.yml index ffefc14..5604996 100644 --- a/.github/workflows/schema-ci.yml +++ b/.github/workflows/schema-ci.yml @@ -8,8 +8,13 @@ on: workflow_dispatch: env: - SCHEMA_DIR: au.org.access-nri/model/output/file-metadata/2-0-0 - TEST_DIR: tests/2-0-0 + SCHEMA_DIRS: | + au.org.access-nri/model/output/file-metadata/2-0-0 + au.org.access-nri/model/output/file-metadata/2-1-0 + # TEST_DIRS need to have matching SCHEMA_DIRS in the same order + TEST_DIRS: | + tests/2-0-0 + tests/2-1-0 jobs: schema-tests: @@ -18,16 +23,31 @@ jobs: - uses: actions/checkout@v4 - name: Install the Sourcemeta JSON Schema CLI - uses: sourcemeta/jsonschema@v11.8.3 + uses: sourcemeta/jsonschema@f0b6672d82955e58a73efd320068284a4e7a4483 #v14.14.2 - name: Check schemas against their metaschemas - run: jsonschema metaschema --verbose $SCHEMA_DIR + run: jsonschema metaschema --verbose $SCHEMA_DIRS - name: Check schemas are formatted - run: jsonschema fmt --check --verbose $SCHEMA_DIR + run: jsonschema fmt --check --verbose $SCHEMA_DIRS - name: Lint schemas - run: jsonschema lint --verbose --exclude enum_with_type $SCHEMA_DIR + run: | + jsonschema lint --verbose \ + --exclude enum_with_type \ + --exclude description_trailing_period \ + --exclude top_level_examples \ + $SCHEMA_DIRS - name: Run test suite - run: jsonschema test --verbose $TEST_DIR --resolve $SCHEMA_DIR + run: | + # Need to iterate through each pair of DIRS since there will be name + # collisions with different versions of the same schema + # Turn the strings into arrays of strings first + test_arr=($TEST_DIRS) + schema_arr=($SCHEMA_DIRS) + for i in "${!test_arr[@]}"; do + test_dir=${test_arr[i]} + schema_dir=${schema_arr[i]} + jsonschema test --verbose $test_dir --resolve $schema_dir + done diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global.json index 83eeda5..b9d3ca0 100644 --- a/au.org.access-nri/model/output/file-metadata/2-1-0/global.json +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global.json @@ -13,6 +13,10 @@ "experiment_repo", "experiment_uuid", "frequency", + "geospatial_lat_max", + "geospatial_lat_min", + "geospatial_lon_max", + "geospatial_lon_min", "license", "model_version", "model", @@ -54,6 +58,24 @@ "frequency": { "$ref": "global/frequency.json" }, + "geospatial_lat_max": { + "$ref": "global/geospatial_lat_max.json" + }, + "geospatial_lat_min": { + "$ref": "global/geospatial_lat_min.json" + }, + "geospatial_lat_units": { + "$ref": "global/geospatial_lat_units.json" + }, + "geospatial_lon_max": { + "$ref": "global/geospatial_lon_max.json" + }, + "geospatial_lon_min": { + "$ref": "global/geospatial_lon_min.json" + }, + "geospatial_lon_units": { + "$ref": "global/geospatial_lon_units.json" + }, "grid": { "$ref": "global/grid.json" }, diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_max.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_max.json new file mode 100644 index 0000000..d9cce1a --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_max.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lat_max.json", + "title": "geospatial_lat_max", + "description": "Specifies the northernmost latitude covered by the dataset. Units should be \"degrees North\".", + "examples": [ 90, 12.98 ], + "type": "number" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_min.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_min.json new file mode 100644 index 0000000..a950d73 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_min.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lat_min.json", + "title": "geospatial_lat_min", + "description": "Specifies the southernmost latitude covered by the dataset. Units should be \"degrees North\".", + "examples": [ -90, -57.97 ], + "type": "number" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_units.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_units.json new file mode 100644 index 0000000..5a9b18a --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_units.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lat_units.json", + "title": "geospatial_lat_units", + "description": "Units for the latitude axis described in \"geospatial_lat_min\" and \"geospatial_lat_max\" attributes. These should be \"degrees_north\".", + "const": "degrees_north" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_max.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_max.json new file mode 100644 index 0000000..58b69e9 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_max.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lon_max.json", + "title": "geospatial_lon_max", + "description": "Specifies the easternmost longitude covered by the dataset. Units should be \"degrees East\". Cases where geospatial_lon_min is greater than geospatial_lon_max indicate the bounding box extends from geospatial_lon_max, through the longitude range discontinuity meridian (e.g. the antimeridian for -180:180 values ranges) to geospatial_lon_min; for example, geospatial_lon_min=170 and geospatial_lon_max=-175 incorporates 15 degrees of longitude (ranges 170 to 180 and -180 to -175).", + "examples": [ 180, -152.61 ], + "type": "number" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_min.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_min.json new file mode 100644 index 0000000..e028416 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_min.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lon_min.json", + "title": "geospatial_lon_min", + "description": "Specifies the westernmost latitude covered by the dataset. Units should be \"degrees East\". See also geospatial_lon_max.", + "examples": [ -180, 88.48 ], + "type": "number" +} diff --git a/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_units.json b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_units.json new file mode 100644 index 0000000..85cce73 --- /dev/null +++ b/au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_units.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "global/geospatial_lon_units.json", + "title": "geospatial_lon_units", + "description": "Units for the longitude axis described in \"geospatial_lon_min\" and \"geospatial_lon_max\" attributes. These should be \"degrees_east\".", + "const": "degrees_east" +} diff --git a/tests/2-1-0/global/test_geospatial_lat_max.json b/tests/2-1-0/global/test_geospatial_lat_max.json new file mode 100644 index 0000000..7cc5aeb --- /dev/null +++ b/tests/2-1-0/global/test_geospatial_lat_max.json @@ -0,0 +1,25 @@ +{ + "target": "../../../au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_max.json", + "tests": [ + { + "description": "Valid lat_max - -90", + "valid": true, + "data": -90 + }, + { + "description": "Valid lat_max - 90", + "valid": true, + "data": 90 + }, + { + "description": "Valid lat_max - explicit float", + "valid": true, + "data": 12.3456 + }, + { + "description": "Invalid lat_max - string", + "valid": false, + "data": "-90" + } + ] +} diff --git a/tests/2-1-0/global/test_geospatial_lat_min.json b/tests/2-1-0/global/test_geospatial_lat_min.json new file mode 100644 index 0000000..b2417d4 --- /dev/null +++ b/tests/2-1-0/global/test_geospatial_lat_min.json @@ -0,0 +1,25 @@ +{ + "target": "../../../au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lat_min.json", + "tests": [ + { + "description": "Valid lat_min - -90", + "valid": true, + "data": -90 + }, + { + "description": "Valid lat_min - 90", + "valid": true, + "data": 90 + }, + { + "description": "Valid lat_min - explicit float", + "valid": true, + "data": 12.3456 + }, + { + "description": "Invalid lat_min - string", + "valid": false, + "data": "-90" + } + ] +} diff --git a/tests/2-1-0/global/test_geospatial_lon_max.json b/tests/2-1-0/global/test_geospatial_lon_max.json new file mode 100644 index 0000000..746a956 --- /dev/null +++ b/tests/2-1-0/global/test_geospatial_lon_max.json @@ -0,0 +1,25 @@ +{ + "target": "../../../au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_max.json", + "tests": [ + { + "description": "Valid lon_max - -180", + "valid": true, + "data": -180 + }, + { + "description": "Valid lon_max - 180", + "valid": true, + "data": 180 + }, + { + "description": "Valid lon_max - explicit float", + "valid": true, + "data": 12.3456 + }, + { + "description": "Invalid lon_max - string", + "valid": false, + "data": "-90" + } + ] +} diff --git a/tests/2-1-0/global/test_geospatial_lon_min.json b/tests/2-1-0/global/test_geospatial_lon_min.json new file mode 100644 index 0000000..2956ee3 --- /dev/null +++ b/tests/2-1-0/global/test_geospatial_lon_min.json @@ -0,0 +1,25 @@ +{ + "target": "../../../au.org.access-nri/model/output/file-metadata/2-1-0/global/geospatial_lon_min.json", + "tests": [ + { + "description": "Valid lon_min - -180", + "valid": true, + "data": -180 + }, + { + "description": "Valid lon_min - 180", + "valid": true, + "data": 180 + }, + { + "description": "Valid lon_min - explicit float", + "valid": true, + "data": 12.3456 + }, + { + "description": "Invalid lon_min - string", + "valid": false, + "data": "-90" + } + ] +} diff --git a/tests/2-1-0/test.json b/tests/2-1-0/test.json index 7191d75..4a50e56 100644 --- a/tests/2-1-0/test.json +++ b/tests/2-1-0/test.json @@ -16,6 +16,12 @@ "id": "F6B536FA-766D-4609-B767-754C9424440A", "frequency": "1hr", "grid": "grid goes here", + "geospatial_lat_min": -90, + "geospatial_lat_max": 90, + "geospatial_lat_units": "degrees_north", + "geospatial_lon_min": -180, + "geospatial_lon_max": 180, + "geospatial_lon_units": "degrees_east", "license": "CC-BY-4.0", "model_version": "2025.06.001", "model": "ACCESS-ESM1.6", diff --git a/tests/2-1-0/test_global.json b/tests/2-1-0/test_global.json new file mode 100644 index 0000000..d57314d --- /dev/null +++ b/tests/2-1-0/test_global.json @@ -0,0 +1,64 @@ +{ + "target": "../../au.org.access-nri/model/output/file-metadata/2-1-0/global.json", + "tests": [ + { + "description": "Valid global attrs", + "valid": true, + "data": { + "base_configuration": "release-preindustrial+concentrations-2.0", + "contact": "data.access.nri@anu.edu.au", + "Conventions": "CF-1.11", + "date_created": "2025-12-03T11:22:00Z", + "data_specification": "ACCESS Output Data Specification v0.1 XX.XXXX/zenodo.XXXXX", + "experiment_repo": "x", + "experiment_uuid": "F6B536FA-766D-4609-B767-754C9424440A", + "id": "F6B536FA-766D-4609-B767-754C9424440A", + "frequency": "1hr", + "grid": "grid goes here", + "geospatial_lat_min": -90, + "geospatial_lat_max": 90, + "geospatial_lat_units": "degrees_north", + "geospatial_lon_min": -180, + "geospatial_lon_max": 180, + "geospatial_lon_units": "degrees_east", + "license": "CC-BY-4.0", + "model_version": "2025.06.001", + "model": "ACCESS-ESM1.6", + "naming_authority": "au.org.access-nri", + "realm": "atmos", + "run_id": "00b0e8d102733a0e36093a96b273ed2853ac2006", + "title": "this is a title", + "variable_id": "tas" + } + }, + { + "description": "Invalid global - missing required 'frequency'", + "valid": false, + "data": { + "base_configuration": "release-preindustrial+concentrations-2.0", + "contact": "data.access.nri@anu.edu.au", + "Conventions": "CF-1.11", + "date_created": "2025-12-03T11:22:00Z", + "data_specification": "ACCESS Output Data Specification v0.1 XX.XXXX/zenodo.XXXXX", + "experiment_repo": "x", + "experiment_uuid": "F6B536FA-766D-4609-B767-754C9424440A", + "id": "F6B536FA-766D-4609-B767-754C9424440A", + "grid": "grid goes here", + "geospatial_lat_min": -90, + "geospatial_lat_max": 90, + "geospatial_lat_units": "degrees_north", + "geospatial_lon_min": -180, + "geospatial_lon_max": 180, + "geospatial_lon_units": "degrees_east", + "license": "CC-BY-4.0", + "model_version": "2025.06.001", + "model": "ACCESS-ESM1.6", + "naming_authority": "au.org.access-nri", + "realm": "atmos", + "run_id": "00b0e8d102733a0e36093a96b273ed2853ac2006", + "title": "this is a title", + "variable_id": "tas" + } + } + ] +}