Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

153-End to End build test. #266

Merged
merged 30 commits into from
Nov 26, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
aeb978e
Updated functions in cli.py to use argv[Optional[Sequence[str]] inste…
charles-turner-1 Nov 18, 2024
9e785f4
Skeleton of e2e test
charles-turner-1 Nov 18, 2024
6206a7e
Peelin apart argparse for e2e test
charles-turner-1 Nov 18, 2024
a4aab12
Pass build in using argparse
charles-turner-1 Nov 18, 2024
c7efe95
End to end build test working - now to add queries
charles-turner-1 Nov 18, 2024
1f4feea
Pre-commit
charles-turner-1 Nov 18, 2024
02fdd23
Updated workflow to only run tests in 'tests' dir
charles-turner-1 Nov 18, 2024
e194ead
Lots of tests working - mostly just the content tests to finish
charles-turner-1 Nov 20, 2024
be30446
Pre-commit
charles-turner-1 Nov 20, 2024
37d3a68
End to end test done & working. Now just needs a workflow trigger
charles-turner-1 Nov 20, 2024
436676a
formatting
charles-turner-1 Nov 20, 2024
9be91f3
Merge branch 'main' into 153-e2e
charles-turner-1 Nov 20, 2024
1d69c30
Removed unused build_subset.sh file
charles-turner-1 Nov 20, 2024
5071f0b
Merge branch '153-e2e' of https://github.com/ACCESS-NRI/access-nri-in…
charles-turner-1 Nov 20, 2024
6511acc
Removed some redundant stuff (Marc's comments)
charles-turner-1 Nov 24, 2024
ab511ab
Moved end to end test into tests dir (yet to see if we can get it all…
charles-turner-1 Nov 24, 2024
efd3fcd
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 24, 2024
7a56289
Added workflow & shell script to submit it to Gadi
charles-turner-1 Nov 24, 2024
b91d1df
Clean up test file (remove unused string, etc etc)
charles-turner-1 Nov 24, 2024
823613b
Clean up test file (remove unused string, scope=session => module)
charles-turner-1 Nov 24, 2024
d7715be
Merge branch '153-e2e' of https://github.com/ACCESS-NRI/access-nri-in…
charles-turner-1 Nov 24, 2024
04d14c4
Merge branch 'main' into 153-e2e
charles-turner-1 Nov 24, 2024
40918c0
Added reference to e2e tests in docs
charles-turner-1 Nov 25, 2024
96b88a6
Merge branch '153-e2e' of https://github.com/ACCESS-NRI/access-nri-in…
charles-turner-1 Nov 25, 2024
dd8c090
Cleaned up fixture, removed redundant second conftest.py, fixed confi…
charles-turner-1 Nov 25, 2024
268c98f
Cleaning up a few tests where mocks no longer necessary
charles-turner-1 Nov 25, 2024
a63bdab
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Nov 25, 2024
4629f27
Merge remote-tracking branch 'origin/main' into 153-e2e
marc-white Nov 26, 2024
54abc39
Fixed workflow trigger & type hint that disappeared
charles-turner-1 Nov 26, 2024
6d543fd
Pre-commit
charles-turner-1 Nov 26, 2024
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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ jobs:

- name: Run tests
shell: bash -l {0}
run: coverage run -m --source=access_nri_intake pytest
run: coverage run -m --source=access_nri_intake pytest tests

- name: Generate coverage report
shell: bash -l {0}
Expand Down
36 changes: 36 additions & 0 deletions .github/workflows/e2e.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
name: Run end-to-end tests on Gadi
on:
workflow_dispatch:
inputs:
release_version:
description: 'Release version'
required: true

jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
### Latest at time of writing
uses: actions/checkout@v4.2.2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would just assume we have a copy on Gadi for now. You can delete the checkout and the rsync.

- name: Sync repository to Gadi
### Latest at time of writing
uses: up9cloud/action-rsync@v1.4
env:
HOST: gadi.nci.org.au
TARGET: ${{secrets.GADI_REPO_PATH}}
KEY: ${{secrets.DEPLOY_KEY}}
USER: ${{secrets.GADI_USER}}
PRE_SCRIPT: |
export PROJECT=xp65_w
- name: Run end-to-end tests
uses: appleboy/ssh-action@v1.1.0
with:
host: gadi.nci.org.au
username: ${{secrets.GADI_USER}}
key: ${{secrets.DEPLOY_KEY}}
script: |
cd ${{secrets.GADI_REPO_PATH}}
qsub bin/build_all.sh
charles-turner-1 marked this conversation as resolved.
Show resolved Hide resolved


27 changes: 27 additions & 0 deletions bin/test_end_to_end.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/bash -l

#PBS -P iq82
#PBS -l storage=gdata/xp65+gdata/ik11+gdata/cj50+gdata/hh5+gdata/p73+gdata/dk92+gdata/al33+gdata/rr3+gdata/fs38+gdata/oi10
#PBS -q normal
#PBS -W block=true
#PBS -l walltime=00:30:00
#PBS -l mem=32gb
#PBS -l ncpus=12
#PBS -l wd
#PBS -j oe

###########################################################################################
# Copyright 2022 ACCESS-NRI and contributors. See the top-level COPYRIGHT file for details.
# SPDX-License-Identifier: Apache-2.0

# Description:
# Generate access-nri intake metacatalog from config files

###########################################################################################

set -e

module use /g/data/xp65/public/modules
module load conda/access-med-0.6

pytest -s --e2e tests
5 changes: 5 additions & 0 deletions docs/contributing/code.rst
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,10 @@ contributions and submitting a pull request.

pytest .

This project has both unit tests and integration tests. Integration tests are disabled by default due to computational
expense, and can only be run on Gadi. To run the full test suite, including integration tests, run::

pytest --e2e .

#. Once you are happy with your contribution, go `here <https://github.com/ACCESS-NRI/access-nri-intake-catalog/pulls>`_
and open a new pull request to merge your branch of your fork with the main branch of the base.
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ test = [
"pytest",
"tox",
]
e2e = [
"pytest",
"pytest-ordering",
]

[project.scripts]
catalog-build = "access_nri_intake.cli:build"
Expand Down
34 changes: 20 additions & 14 deletions src/access_nri_intake/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import logging
import os
import re
from collections.abc import Sequence
from pathlib import Path

import jsonschema
Expand All @@ -27,7 +28,9 @@ class MetadataCheckError(Exception):
pass


def _parse_build_inputs(config_yamls, build_path, data_base_path):
def _parse_build_inputs(
config_yamls: list[str], build_path, data_base_path: str
) -> list[tuple[str, dict]]:
"""
Parse build inputs into a list of tuples of CatalogManager methods and args to
pass to the methods
Expand Down Expand Up @@ -78,9 +81,12 @@ def _parse_build_inputs(config_yamls, build_path, data_base_path):
return args


def _check_build_args(args_list):
def _check_build_args(args_list: list[dict]) -> None:
"""
Run some checks on the parsed build argmuents to be passed to the CatalogManager

Raises:
MetadataCheckError: If there are experiments with the same name or experiment_uuid
"""

names = []
Expand All @@ -91,18 +97,18 @@ def _check_build_args(args_list):

if len(names) != len(set(names)):
seen = set()
dupes = [name for name in names if name in seen or seen.add(name)]
dupes = [name for name in names if name in seen or seen.add(name)] # type: ignore
raise MetadataCheckError(f"There are experiments with the same name: {dupes}")
if len(uuids) != len(set(uuids)):
seen = set()
dupes = [uuid for uuid in uuids if uuid in seen or seen.add(uuid)]
dupes = [uuid for uuid in uuids if uuid in seen or seen.add(uuid)] # type: ignore
dupes = [name for name, uuid in zip(names, uuids) if uuid in dupes]
raise MetadataCheckError(
f"There are experiments with the same experiment_uuid: {dupes}"
)


def build():
def build(argv: Sequence[str] | None = None):
"""
Build an intake-dataframe-catalog from YAML configuration file(s).
"""
Expand Down Expand Up @@ -180,7 +186,7 @@ def build():
),
)

args = parser.parse_args()
args = parser.parse_args(argv)
config_yamls = args.config_yaml
build_base_path = args.build_base_path
catalog_base_path = args.catalog_base_path
Expand Down Expand Up @@ -212,21 +218,21 @@ def _get_project(path):
return match.groups()[0] if match else None

project = set()
for method, args in parsed_sources:
for method, src_args in parsed_sources:
if method == "load":
# This is a hack but I don't know how else to get the storage from pre-built datastores
esm_ds = open_esm_datastore(args["path"][0])
esm_ds = open_esm_datastore(src_args["path"][0])
project |= set(esm_ds.df["path"].map(_get_project))

project |= {_get_project(path) for path in args["path"]}
project |= {_get_project(path) for path in src_args["path"]}
project |= {_get_project(build_base_path)}
storage_flags = "+".join(sorted([f"gdata/{proj}" for proj in project]))

# Build the catalog
cm = CatalogManager(path=metacatalog_path)
for method, args in parsed_sources:
logger.info(f"Adding '{args['name']}' to metacatalog '{metacatalog_path}'")
getattr(cm, method)(**args)
for method, src_args in parsed_sources:
logger.info(f"Adding '{src_args['name']}' to metacatalog '{metacatalog_path}'")
getattr(cm, method)(**src_args)

# Write catalog yaml file
cat = cm.dfcat
Expand Down Expand Up @@ -367,7 +373,7 @@ def _combine_storage_flags(a: str, b: str) -> str:
return "+".join(sorted(list(set(aflags + bflags))))


def metadata_validate():
def metadata_validate(argv: Sequence[str] | None = None):
"""
Check provided metadata.yaml file(s) against the experiment schema
"""
Expand All @@ -379,7 +385,7 @@ def metadata_validate():
help="The path to the metadata.yaml file. Multiple file paths can be passed.",
)

args = parser.parse_args()
args = parser.parse_args(argv)
files = args.file

for f in files:
Expand Down
38 changes: 32 additions & 6 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,42 @@

import os
import warnings
from datetime import datetime
from pathlib import Path

from pytest import fixture

here = os.path.abspath(os.path.dirname(__file__))
here = Path(__file__).parent


@fixture(scope="session")
def test_data():
return Path(here / "data")


@fixture(scope="session")
def config_dir():
return Path(here / "e2e/configs")


@fixture(scope="session")
def BASE_DIR(tmp_path_factory):
yield tmp_path_factory.mktemp("catalog-dir")


@fixture(scope="session")
def v_num():
return datetime.now().strftime("v%Y-%m-%d")


def pytest_addoption(parser):
parser.addoption(
"--e2e",
action="store_true",
default=False,
help="Run end-to-end tests",
dest="e2e",
)


def _get_xfail():
Expand All @@ -34,11 +65,6 @@ def _get_xfail():
_add_xfail = _get_xfail()


@fixture(scope="session")
def test_data():
return Path(os.path.join(here, "data"))


def pytest_collection_modifyitems(config, items):
"""
This function is called by pytest to modify the items collected during test
Expand Down
Empty file added tests/e2e/__init__.py
Empty file.
9 changes: 9 additions & 0 deletions tests/e2e/configs/access-om2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
builder: AccessOm2Builder

translator: DefaultTranslator

sources:

- metadata_yaml: /g/data/ik11/outputs/access-om2/1deg_jra55_ryf9091_gadi/metadata.yaml
path:
- /g/data/ik11/outputs/access-om2/1deg_jra55_ryf9091_gadi
9 changes: 9 additions & 0 deletions tests/e2e/configs/cmip5.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
builder: null

translator: Cmip5Translator

sources:

- metadata_yaml: /g/data/xp65/admin/access-nri-intake-catalog/config/metadata_sources/cmip5-al33/metadata.yaml
path:
- /g/data/al33/catalog/v2/esm/catalog.json
Loading
Loading